pari-2.7.5/0000755000175000017500000000000012613365633011116 5ustar billbillpari-2.7.5/README0000644000175000017500000000656412463145062012004 0ustar billbillThis is PARI/GP, version 2.7.x (*). PARI/GP Number Theory-oriented Computer Algebra System Copyright (C) 2000-2015 The PARI Group, Bordeaux. ========================================================================== To get started, run tex doc/INSTALL.tex and have a look at the file doc/INSTALL.dvi, extracted verbatim from Appendix A of the User Manual. If you are in a hurry, look at INSTALL (ascii file). But a lot of information is missing there. Once 'Configure' has been run, 'make doc' typesets separate user's manual for GP and libpari, a tutorial and reference card in directory doc. See the files NEW and COMPAT for new features and incompatible changes respectively between 2.7 and older versions. See CHANGES-* for a terse description of subsequent patches. For the adventurous: to check out bleeding-edge development versions of PARI/GP, see the file README-git. Afterwards, you're on your own. ========================================================================== There are three mailing lists devoted to the PARI/GP package, and most feedback should be directed to those. They are: * pari-announce: to announce major version changes. You can't write to this one, but you should probably subscribe. * pari-dev: for everything related to the development of PARI, including suggestions, technical questions, bug reports or patch submissions. * pari-users: for everything else. To subscribe, send empty messages respectively to pari-announce-request@pari.math.u-bordeaux.fr pari-users-request@pari.math.u-bordeaux.fr pari-dev-request@pari.math.u-bordeaux.fr with a Subject: containing the word "subscribe". If you are not a member of any of those lists and do not want to become one, you can write to us at pari@math.u-bordeaux.fr We may forward your mail to the lists above and will definitely try to correct faulty behaviour, if necessary. But we cannot promise that you will get an individual answer. Last but not least, PARI home page can be found at http://pari.math.u-bordeaux.fr/ Thanks for your support, and have fun ! ======================================================================== 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; either version 2 of the License, or (at your option) any later version. 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. (*) Version numbers have the shape: MAJOR.MINOR.patchlevel.status. The status increases through {alpha, beta, release}. New features are introduced during the `alpha' phase, tested during `beta', and declared stable when `release' is reached. The MAJOR version number will not change for a while. The MINOR version number increases by 2 when a new status cycle starts (as soon as a 'release' version is out): odd numbers are reserved for 'released' versions, even ones for alpha/beta phase. The patchlevel goes up each time we feel an upgrade is necessary (improvement or bugfix). 'Release' versions may be updated with further patchlevels if important bugs need to be fixed before the next cycle reaches completion. pari-2.7.5/Configure0000755000175000017500000001432412533333715012766 0ustar billbill#! /bin/sh # # 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. # Configuration file for GP/PARI. Run Configure --help for Usage. # # Perl's Configure and GNU autoconfig were of much help in writing these files. # $Id$ TOP=`pwd` MAKE=${MAKE:-make} config_dir=config data_dir=data doc_dir=doc examples_dir=examples misc_dir=misc src_dir=src desc_dir=src/desc case "x$RUNTEST" in x);; x/*);; *) RUNTEST="$TOP/$RUNTEST";; esac cd $config_dir # Process options, initialize . ./get_head # do we need head -n # or head -# ? . ./version echo "Configuring pari-$pari_release_verbose $patchlevel_verbose" . ./get_config_options ####################### CONFIGURE - SHELL ################################### . ./get_nl # how to get echo without \n ? (for config questions) . ./get_PATH # We might need the following : echo Looking for some tools first ... _tools_list='gzip cc gcc ld perl zcat' pathspace=`echo $PATH | sed -e "s/$dir_sep/ /g" | sed -e 's,\\\\,/,g'` for file in $_tools_list; do x=`./locate $file '' $pathspace` eval $file=$x case $x in # support also DOS filesystems (hard drive prepended) ?:/*|/*) echo ..."$file is $x";; *) echo ..."I could not find $file." >&2;; esac done if test -z "$zcat" -a -n "$gzip"; then zcat="$gzip -dc"; fi ####################### CONFIGURE - ARCHITECTURE ############################ . ./get_archos # arch, osname config_log="$TOP/config-$arch-$osname$$.log" cat > $config_log<< EOT This file contains messages produced while configuring pari-$pari_release $patchlevel_verbose to aid debugging if Configure makes a mistake. Command line was > $0 $@ EOT exec 5>> $config_log ####################### CONFIGURE - COMPILATION ############################# # $_cc_list (includes 'optimization'), extraflag . ./get_cc # . ./get_mt # doubleformat, sizeof_long . ./get_double_format # asmarch, pretty . ./get_kernel # _dl_list, DLCFLAGS, update CFLAGS . ./get_dlcflags # $_ld_list . ./get_ld # $_dlld_list . ./get_dlld # $_perl_list . ./get_perl ####################### CONFIGURE - LIBC #################################### . ./get_libc # $_has_list, RT_LIBS, DL_LIBS ####################### CONFIGURE - LIBRARIES ############################### # Looking for libraries: gmp, X11, fltk, Qt, readline echo Checking for optional libraries and headers... . ./get_include_path . ./get_libpth # $_gmp_list if test "$kernlvl1" = "gmp"; then . ./get_gmp fi # $_graphic_list . ./get_graphic_lib # $_readline_list (includes 'readline') case "$without_readline" in yes);; *) . ./get_readline esac ############################################################################# case $kernlvl1 in gmp) libpari_base=pari-gmp;; none) libpari_base=pari;; esac case $enable_tls in yes) libpari_base="${libpari_base}-tls" esac if test `expr $VersionMinor % 2` = 0; then libpari_base=$libpari_base-$version fi ####################### CONFIGURE - MAKE #################################### . ./get_install # $_install_list . ./get_objdir # objdir, cdobjdir . ./get_static # static # For dynamic linking, before and after installing runpath=\"$libdir\" LDDYN="-lpari" # get_modld needs $includedir from get_install, static, and LDDYN . ./get_modld # $_modld_list # Which copy, SHELL ? case "$osname" in os2) ln_s=cp; make_sh=sh;; *) ln_s="ln -s"; make_sh="/bin/sh";; esac ####################### CONFIGURE - CLEANUP ################################# rm -f gmon.out # created by Configure -pg rm -f *.gcno *.gcda # created by Configure -gcov ####################### CONFIGURE - SPIT #################################### . ./get_tests #_test_list # Now spit out the results cat << EOT ========================================================================== EOT cd "$TOP" if test ! -d $objdir; then mkdir -p $objdir; fi rm -f $objdir/config.log; mv $config_log $objdir/config.log dflt_conf_file=$objdir/$dflt_conf_file cat > $dflt_conf_file << EOT # Config file for Pari $release -- $pretty EOT case "$osname" in os2|mingw) shell_q='"'; echo "shell_q='\"'" >> $dflt_conf_file;; *) shell_q="'"; echo "shell_q=\"'\"" >> $dflt_conf_file;; esac for variable in\ pari_release pari_release_verbose version libpari_base static TOP objdir\ arch asmarch osname pretty\ kernlvl0 kernlvl1 RT_LIBS DL_LIBS MT_LIBS LIBS\ dir_sep runpath runpathprefix LDDYN RUNTEST\ ln_s make_sh\ sizeof_long doubleformat\ thread_engine enable_tls\ $_tools_list\ $_test_list\ $_install_list\ $_perl_list\ $_cc_list\ $_ld_list\ $_dl_list\ $_dlld_list\ $_graphic_list\ $_modld_list\ $_readline_list\ $_gmp_list\ $_has_list; do eval "echo $variable=\'"'$'"$variable\'" \>\> $dflt_conf_file done . $config_dir/extract_files if test "$osname" = mingw && test "$sizeof_long" = 8; then echo $n "Patching PARI source for LLP64 mode... $c" ./config/convertllp64 > /dev/null echo done fi # Building... cat << EOT ========================================================================== EOT 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) else echo $n "Shall we try to build pari $version.$patch ($status) now (y/n)? $c" dflt=n; rep='y n'; . $config_dir/myread fi mkobjdir=`$config_dir/objdir` cdobjdir= if test "$objdir" != "$mkobjdir"; then cdobjdir="cd $objdir; " fi case $ans in y) if (cd $objdir; $MAKE gp); then echo $n "Shall we install the files where they belong (y/n)? $c" dflt=n; rep='y n'; . $config_dir/myread case $ans in y) $MAKE install;; n) echo "Ok. Type \"${cdobjdir}make install\" when you are ready";; esac fi;; n) echo "Ok. Type \"${cdobjdir}make install\" when you are ready";; esac echo 'Bye !' pari-2.7.5/doc/0000755000175000017500000000000012613365633011663 5ustar billbillpari-2.7.5/doc/tutorial.tex0000644000175000017500000047345012413013142014244 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/\kbd{gp} documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % This should be compiled with plain TeX \def\TITLE{A Tutorial for Pari/GP} \input parimacro.tex \chapno=0 \begintitle \vskip2.5truecm \centerline{\mine A Tutorial} \vskip1.truecm \centerline{\mine for} \vskip1.truecm \centerline{\mine PARI / GP} \vskip1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip1.truecm \authors \endtitle \copyrightpage \tableofcontents \noindent This booklet is a guided tour and a tutorial to the \kbd{gp} calculator. Many examples will be given, but each time a new function is used, the reader should look at the appropriate section in the \emph{User's Manual to PARI/GP} for detailed explanations. This chapter can be read independently, for example to get acquainted with the possibilities of \kbd{gp} without having to read the whole manual. At this point. \section{Greetings!} So you are sitting in front of your workstation (or terminal, or PC\dots), and you type \kbd{gp} to get the program started (or click on the relevant icon, or select some menu item). It says hello in its particular manner, and then waits for you after its \kbd{prompt}, initially \kbd{?} (or something like {\bf gp}~\kbd{>}). Type \bprog 2 + 2 @eprog\noindent What happens? Maybe not what you expect. First of all, of course, you should tell \kbd{gp} that your input is finished, and this is done by hitting the \kbd{Return} (or \kbd{Newline}, or \kbd{Enter}) key. If you do exactly this, you will get the expected answer. However some of you may be used to other systems like Gap, Macsyma, Magma or Maple. In this case, you will have subconsciously ended the line with a semicolon ``\kbd{;}'' before hitting \kbd{Return}, since this is how it is done on those systems. In that case, you will simply see \kbd{gp} answering you with a smug expression, i.e.~a new prompt and no answer! This is because a semicolon at the end of a line tells \kbd{gp} not to print the result (it is still stored in the result history). You will certainly want to use this feature if the output is several pages long. Try \bprog 27 * 37 @eprog\noindent Wow! even multiplication works. Actually, maybe those spaces are not necessary after all. Let's try \kbd{27*37}. Seems to be ok. We will still insert them in this document since it makes things easier to read, but as \kbd{gp} does not care about them, you don't have to type them all. Now this session is getting lengthy, so the second thing one needs to learn is to quit. Each system has its quit signal. In \kbd{gp}, you can use \kbd{quit} or \b{q} (backslash q), the \kbd{q} being of course for quit. Try it. Now you've done it! You're out of \kbd{gp}, so how do you want to continue studying this tutorial? Get back in please. Let's get to more serious stuff. I seem to remember that the decimal expansion of $1/7$ has some interesting properties. Let's see what \kbd{gp} has to say about this. Type \bprog 1 / 7 @eprog\noindent What? This computer is making fun of me, it just spits back to me my own input, that's not what I want! Now stop complaining, and think a little. Mathematically, $1/7$ is an element of the field $\Q$ of rational numbers, so how else but $1/7$ can the computer give the answer to you? Well maybe $2/14$ or $7^{-1}$, but why complicate matters? Seriously, the basic point here is that PARI, hence \kbd{gp}, will almost always try to give you a result which is as precise as possible (we will see why ``almost'' later). Hence since here the result can be represented exactly, that's what it gives you. But I still want the decimal expansion of $1/7$. No problem. Type one of the following: \bprog 1./ 7 1 / 7. 1./ 7. 1 / 7 + 0. @eprog\noindent Immediately a number of decimals of this fraction appear, 38 on most systems, 28 on the others, and the repeating pattern is $142857$. The reason is that you have included in the operations numbers like \kbd{0.}, \kbd{1.} or \kbd{7.} which are \emph{imprecise} real numbers, hence \kbd{gp} cannot give you an exact result. Why 28 / 38 decimals by the way? Well, it is the default initial precision. This has been chosen so that the computations are very fast, and gives already 12 decimals more accuracy than conventional double precision floating point operations. The precise value depends on a technical reason: if your machine supports 64-bit integers (the standard C library can handle integers up to $2^{64}$), the default precision is 38 decimals, and 28 otherwise. For definiteness, we will assume the former henceforth. Of course, you can extend the precision (almost) as much as you like as we will see in a moment. I'm getting bored, why don't we get on with some more exciting stuff? Well, try \kbd{exp(1)}. Presto, comes out the value of $e$ to 38 digits. Try \kbd{log(exp(1))}. Well, we get a floating point number and not an exact $1$, but pretty close! That's what you lose by working numerically. What could we try now? Hum, \kbd{pi}? The answer is not that enlightening. \kbd{Pi}? Ah. This works better. But let's remember that \kbd{gp} distinguishes between uppercase and lowercase letters. \kbd{pi} was as meaningless to it as \kbd{stupid garbage} would have been: in both cases \kbd{gp} will just create a variable with that funny unknown name you just used. Try it! Note that it is actually equivalent to type \kbd{stupidgarbage}: all spaces are suppressed from the input. In the \kbd{27~*~37} example it was not so conspicuous as we had an operator to separate the two operands. This has important consequences for the writing of \kbd{gp} scripts. More about this later. By the way, you can ask \kbd{gp} about any identifier you think it might know about: just type it, prepending a question mark ``\kbd{?}''. Try \kbd{?Pi} and \kbd{?pi} for instance. On most systems, an extended online help should be available: try doubling the question mark to check whether it's the case on yours: \kbd{??Pi}. In fact the \kbd{gp} header already gave you that information if it was the case, just before the copyright message. As well, if it says something like ``\kbd{readline enabled}'' then you should have a look at the \kbd{readline} introduction in the User's Manual before you go on: it will be much easier to type in examples and correct typos after you've done that. Now try \kbd{exp(Pi * sqrt(163))}. Hmmm, we suspect that the last digit may be wrong, can this really be an integer? This is the time to change precision. Type \kbd{\b{p} 50}, then try \kbd{exp(Pi * sqrt(163))} again. We were right to suspect that the last decimal was incorrect, since we get quite a few nines in its place, but it is now convincingly clear that this is not an integer. Maybe it's a bug in PARI, and the result is really an integer? Type \bprog (log(%) / Pi)^2 @eprog\noindent immediately after the preceding computation; \kbd{\%} means the result of the last computed expression. More generally, the results are numbered \kbd{\%1, \%2, \dots} \emph{including} the results that you do not want to see printed by putting a semicolon at the end of the line, and you can evidently use all these quantities in any further computations. The result seems to be indistinguishable from $163$, hence it does not seem to be a bug. In fact, it is known that $\exp(\pi*\sqrt{n})$ not only is not an integer or a rational number, but is even a transcendental number when $n$ is a non-zero rational number. So \kbd{gp} is just a fancy calculator, able to give me more decimals than I will ever need? Not so, \kbd{gp} is incredibly more powerful than an ordinary calculator, independently of its arbitrary precision possibilities. \misctitle{Additional comments} (you are supposed to skip this at first, 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})}. 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 unique exception: when you multiply an imprecise number by the exact number 0, you will get the exact 0. Compare \kbd{0 * 1.4} and \kbd{0.~*~1.4}. \smallskip % 3) Not only can the number of decimal places of real numbers be large, but the number of digits of integers also. Try \kbd{1000!}. It is never necessary to tell \kbd{gp} in advance the size of the integers that it will encounter. The same is true for real numbers, although most computations with floating point assume a default precision and truncate their results to this accuracy; initially 38 decimal digits, but we may change that with \b{p} of course. \smallskip % 4) Come back to 38 digits of precision (\kbd{\b{p} 38}), and type \kbd{exp(100)}. As you can see the result is printed in exponential format. This is because \kbd{gp} never wants you to believe that a result is correct when it is not. We are working with 38 digits of precision, but the integer part of $\exp(100)$ has 44 decimal digits. Hence if \kbd{gp} had dutifully printed out 44 digits, the last few digits would have been wrong. Hence \kbd{gp} wants to print only 38 significant digits, but to do so it has to print in exponential format. \smallskip % 5) There are two ways to avoid this. One is of course to increase the precision. Let's try it. To give it a wide margin, we set the precision to 50 decimals. Then we recall our last result (\kbd{\%} or \kbd{\%n} where \kbd{n} is the number of the result). What? We still have an exponential format! Do you understand why? Again let's try to see what's happening. The number you recalled had been computed only to 38 decimals, and even if you set the precision to 1000 decimals, \kbd{gp} knows that your number has only 38 digits of accuracy but an integral part with 44 digits. So you haven't improved things by increasing the precision. Or have you? What if we retype \kbd{exp(100)} now that we have 50 digits? Try it. Now we no longer have an exponential format. \medskip % 6) What if I forget what the current precision is and I don't feel like counting all the decimals? Well, you can type \b{p} by itself. You may also learn about \kbd{gp} internal variables (and change them!) using \kbd{default}. Type \kbd{default(realprecision)}, then \kbd{default(realprecision, 38)}. Huh? In fact this last command is strictly equivalent to \kbd{\b{p} 38}! (Admittedly more cumbersome to type.) There are more ``defaults'' than just \kbd{format} and \kbd{realprecision}: type \kbd{default} by itself now, they are all there. \smallskip % 7) Note that the \kbd{default} command reacts differently according to the number of input arguments. This is not an uncommon behavior for \kbd{gp} functions. You can see this from the online help, or the complete description in Chapter~3: any argument surrounded by braces \kbd{\obr\cbr} in the function prototype is optional, which really means that a \emph{default} argument will be supplied by \kbd{gp}. You can then check out from the text what effect a given value will have, and in particular the default one. \smallskip % 8) Try the following: starting in precision 38, type first \kbd{default(format, "e0.100")}, then \kbd{exp(1)}. Where are my 100 significant digits? Well, \kbd{default(format,)} only changes the output format, but \emph{not} the default precision. On the other hand, the \b{p} command changes both the precision and the output format. \section{Warming up} Another thing you better get used to pretty fast is error messages. Try typing \kbd{1/0}. Could not be clearer. But why has the prompt become funny, turning from \kbd{?} to \kbd{break>} ? When an error occurs, we enter a so-called \emph{break loop}, where you get a chance, e.g to inspect (and save!) values of variables before the prompt returns and all computations so far are lost. In fact you can run an arbitrary command at this point, and this mechanism is a tremendous help in debugging. To get out of the break loop, type \kbd{break}, as instructed in the error message last line. \misctitle{Comment} You can enter the break loop at any time using \kbd{Control-C}: this freezes the current computation and gets you a new prompt so that you may e.g., increase debugging level, inspect or modify variables (again, run arbitrary commands), before letting the program go on. \medskip Now, back to our favorite example, in precision 38, type \bprog floor(exp(100)) @eprog\noindent \kbd{floor} is the mathematician's integer part, not to be confused with \kbd{truncate}, which is the computer scientist's: \kbd{floor(-3.4)} is equal to $-4$ whereas \kbd{truncate(-3.4)} is equal to $-3$. You get a more cryptic error message, which you would immediately understand if you had read the additional comments of the preceding section. Since you were told not to read them, here's the explanation: \kbd{gp} is unable to compute the integer part of \kbd{exp(100)} given only 38 decimals of accuracy, since it has 44 digits. Some error messages are more cryptic and sometimes not so easy to understand. For instance, try \kbd{log(x)}. It simply tells you that \kbd{gp} does not understand what \kbd{log(x)} is, although it does know the \kbd{log} function, as \kbd{?log} will readily tell us. Now let's try \kbd{sqrt(-1)} to see what error message we get now. Haha! \kbd{gp} even knows about complex numbers, so impossible to trick it that way. Similarly, try typing \kbd{log(-2)}, \kbd{exp(I*Pi)}, \kbd{I\pow I}\dots\ So we have a lot of real and complex analysis at our disposal. There always is a specific branch of multivalued complex transcendental functions which is taken, specified in the manual. Again, beware that \kbd{I} and \kbd{i} are not the same thing. Compare \kbd{I\pow2} with \kbd{i\pow2} for instance. Just for fun, let's try \kbd{6*zeta(2) / Pi\pow2}. Pretty close, no? \medskip Now \kbd{gp} didn't seem to know what \kbd{log(x)} was, although it did know how to compute numerical values of \kbd{log}. This is annoying. Maybe it knows the exponential function? Let's give it a try. Type \kbd{exp(x)}. What's this? If you had any experience with other computer algebra systems, the answer should have simply been \kbd{exp(x)} again. But here the answer is the Taylor expansion of the function around $\kbd{x}=0$, to 16 terms. 16 is the default \kbd{seriesprecision}, which can be changed by typing \kbd{\b{ps} $n$} or \kbd{default(seriesprecision, $n$)} where $n$ is the number of terms that you want in your power series. Note the \kbd{O(x\pow16)} which ends the series, and which is trademark of this type of object in \kbd{gp}. It is the familiar ``big--oh'' notation of analysis. You thus automatically get the Taylor expansion of any function that can be expanded around $0$, and incidentally this explains why we weren't able to do anything with \kbd{log(x)} which is not defined at $0$. (In fact \kbd{gp} knows about Laurent series, but \kbd{log(x)} is not meromorphic either at $0$.) If we try \kbd{log(1+x)}, then it works. But what if we wanted the expansion around a point different from 0? Well, you're able to change $x$ into $x-a$, aren't you? So for instance you can type \kbd{log(x+2)} to have the expansion of \kbd{log} around $\kbd{x}=2$. As exercises you can try \bprog cos(x) cos(x)^2 + sin(x)^2 exp(cos(x)) gamma(1 + x) exp(exp(x) - 1) 1 / tan(x) @eprog\noindent for different values of \kbd{serieslength} (change it using \b{ps} \var{newvalue}). Let's try something else: type \kbd{(1 + x)\pow 3}. No \kbd{O(x)} here, since the result is a polynomial. Haha, but I have learnt that if you do not take exponents which are integers greater or equal to 0, you obtain a power series with an infinite number of non-zero terms. Let's try. Type \kbd{(1 + x)\pow (-3)} (the parentheses around \kbd{-3} are not necessary but make things easier to read). Surprise! Contrary to what we expected, we don't get a power series but a rational function. Again this is for the same reason that \kbd{1 / 7} just gave you $1/7$: the result being exact, PARI doesn't see any reason to make it non-exact. But I still want that power series. To obtain it, you can do as in the $1/7$ example and type \bprog (1 + x)^(-3) + O(x^16) (1 + x)^(-3) * (1 + O(x^16)) (1 + x + O(x^16))^(-3) @eprog\noindent (Not on this example, but there is a difference between the first $2$ methods. Do you spot it?) Better yet, use the series constructor which transforms any object into a power series, using the current \kbd{seriesprecision}, and simply type \bprog Ser( (1 + x)^(-3) ) @eprog Now try \kbd{(1 + x)\pow (1/2)}: we obtain a power series, since the result is an object which PARI does not know how to represent exactly. (We could teach PARI about algebraic functions, but then take \kbd{(1 + x)\pow Pi} as another example.) This gives us still another solution to our preceding exercise: we can type \kbd{(1 + x)\pow (-3.)}. Since \kbd{-3.} is not an exact quantity, PARI has no means to know that we are dealing with a rational function, and will instead give you the power series, this time with real instead of integer coefficients. \smallskip To summarize, in this section we have seen that in addition to integers, real numbers and rational numbers, PARI can handle complex numbers, polynomials, rational functions and power series. A large number of functions exist which handle these types, but in this tutorial we will only look at a few. \misctitle{Additional comments} (as before, you are supposed to skip this at first reading) 1) In almost all cases, there is no loss of information in PARI output: what you see is all that PARI knows about the object, and you can happily copy-paste it into another session. There are exceptions, though. Type \kbd{n = 3 + 0*x}, then \kbd{n} is not the integer 3 but a constant polynomial equal to $3 x^0$. Check it with \kbd{type(n)}. However, it \emph{looks} like an integer without being one, and this may cause some confusion in programs which actually expect integers. Hence if you try to \kbd{factor(n)}, you obtain an empty factorization ! (Because, once considered as a polynomial, \kbd{n} is a unit in $\Q[x]$.) If you try to apply more general arithmetic functions, say the Euler totient function (known as \kbd{eulerphi} to \kbd{gp}), you get an error message worrying about integer arguments. You would have guessed yourself, but the message is difficult to understand since 3 looks like a genuine integer! Please make sure you understand the above, it is a common source of incomprehension. 2) If you want the final expression to be in the simplest form possible (for example before applying an arithmetic function, or simply because things will go faster afterwards), apply the function \kbd{simplify} to the result. This is done automatically at the end of a \kbd{gp} command, but \emph{not} in intermediate expressions. Hence \kbd{n} above is not an integer, but the final result stored in the output history is! So if you type \kbd{type(\%)} instead of \kbd{type(n)} the answer is \typ{INT}, adding to the confusion. 3) As already stated, power series expansions are always implicitly around $\kbd{x} = 0$. When we wanted them around $\kbd{x} = \kbd{a}$, we replaced \kbd{x} by \kbd{z + a} in the function we wanted to expand. For complicated functions, it may be simpler to use the substitution function \kbd{subst}. For example, if \kbd{p~= 1 / (x\pow 4 + 3*x\pow 3 + 5*x\pow 2 - 6*x + 7)}, you may not want to retype this, replacing \kbd{x} by \kbd{z~+ a}, so you can write \kbd{subst(p, x, z+a)} (look up the exact description of the \kbd{subst} function). Now type \kbd{subst(1 + O(x), x, z+1)}. Do you understand the error message? 4) The valuation at $\kbd{x} = 0$ for a power series \kbd{p} is obtained as \kbd{valuation(p, x)}. \section{The Remaining PARI Types} Let's talk some more about the basic PARI types. Type \kbd{p = x * exp(-x)}. As expected, you get the power series expansion to 16 terms (if you have not changed the default). Now type \kbd{pr = serreverse(p)}. You are asking here for the \emph{reversion} of the power series \kbd{p}, in other words the inverse function. This is possible only for power series whose first non-zero coefficient is that of $x^1$. To check the correctness of the result, you can type \kbd{subst(p, x, pr)} or \kbd{ subst(pr, x, p)} and you should get back \kbd{x + O(x\pow 17)}. Now the coefficients of \kbd{pr} obey a very simple formula. First, we would like to multiply the coefficient of \kbd{x\pow n} by \kbd{n!} (in the case of the exponential function, this would simplify things considerably!). The PARI function \kbd{serlaplace} does just that. So type \kbd{ps = serlaplace(pr)}. The coefficients now become integers, which can be immediately recognized by inspection. The coefficient of $x^n$ is now equal to $n^{n-1}$. In other words, we have % $$\kbd{pr} = \sum_{n\ge1}\dfrac{n^{n-1}}{n!} X^{n}.$$ % Do you know how to prove this? (The proof is difficult.) \smallskip % Of course PARI knows about vectors (rows and columns are distinguished, even though mathematically there is no difference) and matrices. Type for example \kbd{[1,2,3,4]}. This gives the row vector whose coordinates are 1, 2, 3 and 4. If you want a column vector, type \kbd{[1,2,3,4]\til}, the tilde meaning 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(v)} is also available, for instance \kbd{v[\#v]} is the last element of \kbd{v}. Type \kbd{m = [a,b,c; d,e,f]}. You have just entered a matrix with 2 rows and 3 columns. Note that the matrix is entered by \emph{rows} and the rows are separated by semicolons ``\kbd{;}''. The matrix is printed naturally in a rectangle shape. If you want it printed horizontally just as you typed it, type \b{a}, or if you want this type of printing to be the permanent default type \kbd{default(output, 0)}. Type \kbd{default(output, 1)} if you want to come back to the original output mode. Now type \kbd{m[1,2]}, \kbd{m[1,]}, \kbd{m[,2]}. Are explanations necessary? (In an expression such as \kbd{m[j,k]}, the \kbd{j} always refers to the row number, and the \kbd{k} to the column number, and the first index is always 1, never 0. This default cannot be changed.) Even better, type \kbd{m[1,2] = 5; m}. The semicolon also allows us to put several instructions on the same line; the final result is the output of the last statement on the line. Now type \kbd{m[1,] = [15,-17,8]}. No problem. Finally type \kbd{m[,2] = [j,k]}. You have an error message since you have typed a row vector, while \kbd{m[,2]} is a column vector. If you type instead \kbd{m[,2] = [j,k]\til} it works. \smallskip % \label{se:types} Type now \kbd{h = mathilbert(20)}. You get the so-called ``Hilbert matrix'' whose coefficient of row $i$ and column $j$ is equal to $(i+j-1)^{-1}$. Incidentally, the matrix \kbd{h} takes too much room. If you don't want to see it, simply type a semi-colon ``\kbd{;}'' at the end of the line (\kbd{h = mathilbert(20);}). This is an example of a ``precomputed'' matrix, built into PARI. We will see a more general construction later. What is interesting about Hilbert matrices is that first their inverses and determinants can be computed explicitly (and the inverse has integer coefficients), and second they are numerically very unstable, which make them a severe test for linear algebra packages in numerical analysis. Of course with PARI, no such problem can occur: since the coefficients are given as rational numbers, the computation will be done exactly, so there cannot be any numerical error. Try it. Type \kbd{d~=~matdet(h)}. The result is a rational number (of course) of numerator equal to 1 and denominator having 226 digits. How do I know, by the way? Well, type \kbd{sizedigit(1/d)}. Or \kbd{\#Str(1/d)}. (The length of the character string representing the result.) Now type \kbd{hr = 1.* h;} (do not forget the semicolon, we don't want to see the result!), then \kbd{dr = matdet(hr)}. You notice two things. First the computation, is much faster than in the rational case. (If your computer is too fast for you to notice, try again with \kbd{h = mathilbert(40)}, or even some larger value.) The reason for this is that PARI is handling real numbers with 38 digits of accuracy, while in the rational case it is handling integers having up to 226 decimal digits. The second, more important, fact is that the result is terribly wrong. If you compare with \kbd{1.$*$d} computed earlier, which is the correct answer, you will see that few decimals agree! (None agree if you replaced 20 by 40 as suggested above.) This catastrophic instability is as already mentioned one of the characteristics of Hilbert matrices. In fact, the situation is worse than that. Type \kbd{norml2(1/h - 1/hr)} (the function \kbd{norml2} gives the square of the $L^2$ norm, i.e.~the sum of the squares of the coefficients). The result is larger than $10^{32}$, showing that some coefficients of \kbd{1/hr} are wrong by as much as $10^{16}$. To obtain the correct result after rounding for the inverse, we have to use a default precision of 57 digits (try it). Although vectors and matrices can be entered manually, by typing explicitly their elements, very often the elements satisfy a simple law and one uses a different syntax. For example, assume that you want a vector whose $i$-th coordinate is equal to $i^2$. No problem, type for example \kbd{vector(10,i, i\pow 2)} if you want a vector of length 10. Similarly, if you type \bprog matrix(5,5, i,j, 1 / (i+j-1)) @eprog\noindent you will get the Hilbert matrix of order 5, hence the \kbd{mathilbert} function is in fact redundant. The \kbd{i} and \kbd{j} represent dummy variables which are used to number the rows and columns respectively (in the case of a vector only one is present of course). You must not forget, in addition to the dimensions of the vector or matrix, to indicate explicitly the names of these variables. You may omit the variables and the final expression to get zero entries, as in \kbd{matrix(10,20)}. \misctitle{Warning} The letter \kbd{I} is reserved for the complex number 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}. 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 value, which is of course equal to the evaluated part of the \kbd{if}. So for example you can type \bprog matrix(8,8, i,j, if ((i-j)%2, 1, 0)) @eprog\noindent to get a checkerboard matrix of \kbd{1} and \kbd{0}. Note however that a vector or matrix must be \emph{created} first before being used. For example, it is possible to write \bprog v = vector(5); for (i = 1, 5, v[i] = 1/i) @eprog\noindent but this would fail if the vector \kbd{v} had not been created beforehand. Of course, the above example is better written as \bprog v = vector(5, i, 1/i); @eprog Another useful way to create vectors and matrices is to extract them from larger ones. For instance, if \kbd{h} is the $20\times 20$ Hilbert matrix as above, \bprog h = mathilbert(20); h[11..20, 11..20] @eprog\noindent is its lower right quadrant. \medskip The last PARI types which we have not yet played with are closely linked to number theory. People not interested in number theory can skip ahead. The first is the type ``integer--modulo''. Let us see an example. Type \bprog n = 10^15 + 3 @eprog We want to know whether this number is prime or not. Of course we could make use of the built-in facilities of PARI, but let us do otherwise. We first trial divide by the built-in table of primes. We slightly cheat here and use a variant of the function \kbd{factor} which does exactly this. So type \kbd{factor(n, 200000)}. The last argument tells \kbd{factor} to trial divide up to the given bound and stop at this point. Set it to 0 to trial divide by the full set of built-in primes, which goes up to $500000$ by default. As for all factoring functions, the result is a 2 column matrix: the first column gives the primes and the second their exponents. Here we get a single row, telling us that if primes stopped at $200000$ as we made \kbd{factor} believe, \kbd{n} would be prime. (Or is that a contradiction?) More seriously, \kbd{n} is not divisible by any prime up to $200000$. We could now trial divide further, or cheat and call the PARI function \kbd{factor} without the optional second argument, but before we do this let us see how to get an answer ourselves. By Fermat's little theorem, if $n$ is prime we must have $a^{n-1}\equiv 1 \pmod{n}$ for all $a$ not divisible by $n$. Hence we could try this with $a=2$ for example. But $2^{n-1}$ is a number with approximately $3\cdot10^{14}$ digits, hence impossible to write down, let alone to compute. But instead type \kbd{a = Mod(2,n)}. This creates the number $2$ considered now as an element of the ring $R = \Z/\kbd{n}\Z$. The elements of $R$, called intmods, can always be represented by numbers smaller than \kbd{n}, hence small. Fermat's theorem can be rewritten % $\kbd{a}^{n-1} = \kbd{Mod(1,n)}$ % in the ring $R$, and this can be computed very efficiently. Elements of $R$ may be lifted back to $\Z$ with either \kbd{lift} or \kbd{centerlift}. Type \kbd{a\pow (n-1)}. The result is definitely \emph{not} equal to \kbd{Mod(1,n)}, thus \emph{proving} that \kbd{n} is not a prime. If we had obtained \kbd{Mod(1,n)} on the other hand, it would have given us a hint that \kbd{n} is maybe prime, but not a proof. To find the factors is another story. In this case, the integer $n$ is small enough to let trial division run to completion. Type \kbd{\#} to turn on the \kbd{gp} timer, then \bprog for (i = 2, ceil(sqrt(n)), if (n%i==0, print(i); break)) @eprog\noindent This should take less than 5 seconds. In general, one must use less naive techniques than trial division, or be very patient. Type \kbd{fa = factor(n)} to let the factoring engine find all prime factors. You may stop the timer by typing \kbd{\#} again. Note that, as is the case with most ``prime''-producing functions, the ``prime'' factors given by \kbd{factor} are only strong pseudoprimes, and not \emph{proven} primes. Use \kbd{isprime( fa[,1] )} to rigorously prove primality of the factors. The latter command applies \kbd{isprime} to all entries in the first column of \kbd{fa}, i.e to all pseudoprimes, and returns the column vector of results: all equal to 1, so our pseudoprimes were true primes. All arithmetic functions can be applied in this way to the entries of a vector or matrix. In fact, it has been checked that the strong pseudoprimes output by \kbd{factor} (Baillie-Pomerance-Selfridge-Wagstaff pseudoprimes, without small divisors) are true primes at least up to $2^{64}$, and no explicit counter-example is known.\smallskip The second specifically number-theoretic type is the $p$-adic numbers. I have no room for definitions, so please skip ahead if you have no use for such beasts. A $p$-adic number is entered as a rational or integer valued expression to which is added \kbd{O(p\pow n)}, or simply \kbd{O(p)} if $\kbd{n}=1$, where \kbd{p} is the prime and \kbd{n} the $p$-adic precision. Note that you have to explicitly type in \kbd{3\pow 2} for instance, \kbd{9} will not do. Unless you want to cheat \kbd{gp} into believing that \kbd{9} is prime, but you had better know what you are doing in this case: most computations will yield a wrong result. Apart from the usual arithmetic operations, you can apply a number of transcendental functions. For example, type \kbd{n = 569 + O(7\pow 8)}, then \kbd{s~=~sqrt(n)}, you obtain one of the square roots of \kbd{n}; to check this, type \kbd{s\pow 2 - n}). Type now \kbd{s = log(n)}, then \kbd{e = exp(s)}. If you know about $p$-adic logarithms, you will not be surprised that \kbd{e} is not equal to \kbd{n}. Type \kbd{(n/e)\pow 6}: \kbd{e} is in fact equal to \kbd{n} times the $(p-1)$-st root of unity \kbd{teichmuller(n)}. Incidentally, if you want to get back the integer 569 from the $p$-adic number \kbd{n}, type \kbd{lift(n)} or \kbd{truncate(n)}. \smallskip The third number-theoretic type is the type ``quadratic number''. This type is specially tailored so that we can easily work in a quadratic extension of a base field, usually $\Q$. It is a generalization of the type ``complex''. To start, we must specify which quadratic field we want to work in. For this, we use the function \kbd{quadgen} applied to the \emph{discriminant} \kbd{d} (as opposed to the radicand) of the quadratic field. This returns a number (always printed as \kbd{w}) equal to $(\kbd{d}+a) / 2$ where $a$ is equal to 0 or 1 according to whether \kbd{d} is even or odd. The behavior of \kbd{quadgen} is a little special: although its result is always printed as \kbd{w}, the variable \kbd{w} itself is not set to that value. Hence it is necessary to write systematically \kbd{w = quadgen(d)} using the variable name \kbd{w} (or \kbd{w1} etc. if you have several quadratic fields), otherwise things will get confusing. So type \kbd{w = quadgen(-163)}, then \kbd{charpoly(w)} which asks for the characteristic polynomial of \kbd{w}. The result shows what \kbd{w} will represent. You may ask for \kbd{1.*w} to see which root of the quadratic has been taken, but this is rarely necessary. We can now play in the field $\Q(\sqrt{-163})$. Type for example \kbd{w\pow 10}, \kbd{norm(3 + 4*w)}, \kbd{1 / (4+w)}. More interesting, type \kbd{a = Mod(1,23) * w} then \kbd{b = a\pow 264}. This is a generalization of Fermat's theorem to quadratic fields. If you do not want to see the modulus 23 all the time, type \kbd{lift(b)}. Another example: type \kbd{p = x\pow 2 + w*x + 5*w + 7}, then \kbd{norm(p)}. We thus obtain the quartic equation over $\Q$ corresponding to the relative quadratic extension over $\Q(\kbd{w})$ defined by \kbd{p}. On the other hand, if you type \kbd{wr = sqrt(w\pow 2)}, do not expect to get back \kbd{w}. Instead, you get the numerical value, the function \kbd{sqrt} being considered as a ``transcendental'' function, even though it is algebraic. Type \kbd{algdep(wr,2)}: this looks for algebraic relations involving the powers of \kbd{w} up to degree 2. This is one way to get \kbd{w} back. Similarly, type \kbd{algdep(sqrt(3*w + 5), 4)}. See the user's manual for the function \kbd{algdep}.\smallskip The fourth number-theoretic type is the type ``polynomial--modulo'', i.e. polynomial modulo another polynomial. This type is used to work in general algebraic extensions, for example elements of number fields (if the base field is $\Q$), or elements of finite fields (if the base field is $\Z/p\Z$ for a prime $p$). In a sense it is a generalization of the type quadratic number. The syntax used is the same as for intmods. For example, instead of typing \kbd{w = quadgen(-163)}, you can type \bprog w = Mod(x, quadpoly(-163)) @eprog\noindent Then, exactly as in the quadratic case, you can type \kbd{w\pow 10}, \kbd{norm(3 + 4*w)}, \kbd{1 / (4+w)}, \kbd{a = Mod(1,23)*w}, \kbd{b = a\pow 264}, obtaining of course the same results. (Type \kbd{lift(\dots)} if you don't want to see the polynomial \kbd{x\pow 2 - x + 41} repeated all the time.) Of course, you can work in any degree, not only quadratic. For the latter, the corresponding elementary operations will be slower than with quadratic numbers. Start the timer, then compare \bprog w = quadgen(-163); W = Mod(x, quadpoly(-163)); a = 2 + w; A = 2 + W; b = 3 + w; B = 3 + W; for (i=1,10^5, a+b) for (i=1,10^5, A+B) for (i=1,10^5, a*b) for (i=1,10^5, A*B) for (i=1,10^5, a/b) for (i=1,10^5, A/B) @eprog\noindent Don't retype everything, use the arrow keys! There is however a slight difference in behavior. Keeping our polmod \kbd{w}, type \kbd{1.*w}. As you can see, the result is not the same. Type \kbd{sqrt(w)}. Here, we obtain a vector with 2 components, the two components being the principal branch of the square root of all the possible embeddings of \kbd{w} in $\C$. More generally, if \kbd{w} was of degree $n$, we would get an $n$-component vector, and similarly for all transcendental functions. We have at our disposal the usual arithmetic functions, plus a few others. Type \kbd{a = Mod(x, x\pow 3 - x - 1)} defining a cubic extension. We can for example ask for \kbd{b = a\pow 5}. Now assume we want to express \kbd{a} as a polynomial in \kbd{b}. This is possible since \kbd{b} is also a generator of the same field. No problem, type \kbd{modreverse(b)}. This gives a new defining polynomial for the same field, i.e.~the characteristic polynomial of \kbd{b}, and expresses \kbd{a} in terms of this new polmod, i.e.~in terms of \kbd{a}. We will see this in more detail in the number field section. An important special case of the above construction allows to work in finite fields, by choosing an irreductible polynomial $T$ of degree $f$ over $\F_p$ and considering $\F_p[t]/(T)$. As in \bprog T = ffinit(5, 6, 't); \\ @com degree 6, irreducible over $\F_5$ g = Mod(t, T) @eprog\noindent Try a few elementary operations involving $g$, such as $g^{100}$. This special case of \typ{POLMOD}s is in fact so important that we now introduce a final dedicated number theoretical type \typ{FFELT}, for ``finite field element'', to simplify work with finite fields: \kbd{g = ffgen(5\pow6, 't)} computes a suitable polynomial $T$ as above and returns the generator $t \mod T(t)$. This has major advantages over the generic \typ{POLMOD} solution: elements are printed in a simplified way (in lifted form), and functions can assume that $T$ is indeed irreducible. A few dedicated functions \kbd{ffprimroot} (analog of \kbd{znprimroot}), \kbd{fforder} (analog of \kbd{znorder}), \kbd{fflog} (analog of \kbd{znlog}) are available. Rational expressions in the variable $t$ can be mapped to such a finite field by substituting $t$ by $g$, for instance \bprog ? g = ffgen(5^6, 't); ? g.mod \\ @com irreducible over $\F_5$, defines $\F_{5^6}$ %2 = t^6 + t^5 + t^4 + t^3 + t^2 + t + 1 ? Q = x^2 + t*x + 1 ? factor(subst(Q,t,g)) %3 = [ x + (t^5 + 3*t^4 + t^3 + 4*t + 1) 1] [x + (4*t^5 + 2*t^4 + 4*t^3 + 2*t + 4) 1] @eprog\noindent factors the polynomial $Q \in \F_{5^6}[x]$, where $\F_{5^6} = \F_5[t]/(\kbd{g.mod})$. \section{Elementary Arithmetic Functions} Since PARI is aimed at number theorists, it is not surprising that there exists a large number of arithmetic functions; see the list by typing \kbd{?4}. We have already seen several, such as \kbd{factor}. Note that \kbd{factor} handles not only integers, but also univariate polynomials. Type for example \kbd{factor(x\pow 200 - 1)}. You can also ask to factor a polynomial modulo a prime $p$ (\kbd{factormod}) and even in a finite field which is not a prime field (\kbd{factorff}). Evidently, you have functions for computing GCD's (\kbd{gcd}), extended GCD's (\kbd{bezout}), solving the Chinese remainder theorem (\kbd{chinese}) and so on. In addition to the factoring facilities, you have a few functions related to primality testing such as \kbd{isprime}, \kbd{ispseudoprime}, \kbd{precprime}, and \kbd{nextprime}. As previously mentioned, only strong pseudoprimes are produced by the latter two (they pass the \kbd{ispseudoprime} test); the more sophisticated primality tests in \kbd{isprime}, being so much slower, are not applied by default. We also have the usual multiplicative arithmetic functions: the M\"obius $\mu$ function (\kbd{moebius}), the Euler $\phi$ function (\kbd{eulerphi}), the $\omega$ and $\Omega$ functions (\kbd{omega} and \kbd{bigomega}), the $\sigma_k$ functions (\kbd{sigma}), which compute sums of $k$-th powers of the positive divisors of a given integer, etc\dots You can compute continued fractions. For example, type \kbd{\b{p} 1000}, then \kbd{contfrac(exp(1))}: you obtain the continued fraction of the base of natural logarithms, which as you can see obeys a very simple pattern. Can you prove it? In many cases, one wants to perform some task only when an arithmetic condition is satisfied. \kbd{gp} gives you the following functions: \kbd{isprime} as mentioned above, \kbd{issquare}, \kbd{isfundamental} to test whether an integer is a fundamental discriminant (i.e.~$1$ or the discriminant of a quadratic field), and the \kbd{forprime}, \kbd{fordiv} and \kbd{sumdiv} loops. Assume for example that we want to compute the product of all the divisors of a positive integer \kbd{n}. The easiest way is to write \bprog p = 1; fordiv(n,d, p *= d); p @eprog\noindent (There is a simple formula for this product in terms of $n$ and the number of its divisors: find and prove it!) The notation \kbd{p *= d} is just a shorthand for \kbd{p = p * d}. If we want to know the list of primes $p$ less than 1000 such that 2 is a primitive root modulo $p$, one way would be to write: \bprog forprime(p=3,1000, if (znprimroot(p) == 2, print(p))) @eprog\noindent % Note that this assumes that \kbd{znprimroot} returns the smallest primitive root, and this is indeed the case. Had we not known about this, we could have written \bprog forprime(p=3,1000, if (znorder(Mod(2,p)) == p-1, print(p))) @eprog\noindent % (which is actually faster since we only compute the order of $2$ in $\Z/p\Z$, instead of looking for a generator by trying successive elements whose orders have to be computed as well.) Once we know a primitive root $g$, we can write any non-zero element of $\Z/p\Z$ as $g^x$ for some unique $x$ in $\Z/(p-1)\Z$. Computing such a discrete logarithm is a hard problem in general, performed by the function \kbd{znlog}. Arithmetic functions related to quadratic fields, binary quadratic forms and general number fields will be seen in the next sections. \section{Performing Linear Algebra} The standard linear algebra routines are available: \kbd{matdet}, \kbd{mateigen} (eigenvectors), \kbd{matker}, \kbd{matimage}, \kbd{matrank}, \kbd{matsolve} (to solve a linear system), \kbd{charpoly} (characteristic polynomial), to name a few. Bilinear algebra over $\R$ is also there: \kbd{qfgaussred} (Gauss reduction), \kbd{qfsign} (signature). You may also type \kbd{?8}. Can you guess what each of these do? Let us see how this works. First, a vector space (or module) is given by a generating set of vectors (often a basis) which are represented as \emph{column} vectors. This set of vectors is in turn represented by the columns of a matrix. Quadratic forms are represented by their Gram matrix. The base field (or ring) can be any ring type PARI supports. However, certain operations are specifically written for a real or complex base field, while others are written for $\Z$ as the base ring. We had some fun with Hilbert matrices and numerical instability a while back, but most of the linear algebra routines are generic. If as before \kbd{h = mathilbert(20)}, we may compute \bprog matdet(h * Mod(1,101)) matdet(h * (1 + O(101^100))) @eprog\noindent in $\Z/101\Z$ and the $p$-adic ring $\Z_{101}$ (to $100$ words of accuracy) respectively. Let \kbd{H = 1/h} the inverse of \kbd{h}: \bprog H = 1/h; \\ @com integral L = primes([10^5, 10^5 + 1000]); \\ @com pick a few primes v = vector(#L, i, matdet(H * Mod(1,L[i]))); centerlift( chinese(v) ) @eprog\noindent returns the determinant of \kbd{H}. (Assuming it is an integer less than half the product of elements of \kbd{L} in absolute value, which it is.) In fact, we computed an homomorphic image of the determinant in a few small finite fields, which admits a single integer representative given the size constraints. We could also have made a single determinant computation modulo a big prime (or pseudoprime) number, e.g \kbd{nextprime(2 * B)} if we know that the determinant is less than \kbd{B} in absolute value. (Why is that $2$ necessary?) By the way, this is how you insert comments in a script: everything following a double backslash, up to the first newline character, is ignored. If you want comments which span many lines, you can brace them between \kbd{/* ... */} pairs. Everything in between will be ignored as well. For instance as a header for the script above you could insert the following: \bprog /* Homomorphic imaging scheme to compute the determinant of a classical * integral matrix. * TODO: Look up the explicit formula */ @eprog\noindent (I hope you did not waste your time copying this nonsense, did you?) \medskip In addition, linear algebra over $\Z$, i.e.~work on lattices, can also be performed. Let us now consider the lattice $\Lambda$ generated by the columns of \kbd{H} in $\Z^{20}\subset\R^{20}$. Since the determinant is non-zero, we have in fact a basis. What is the structure of the finite abelian group $\Z^{20}/\Lambda$? Type \kbd{matsnf(H)}. Wow, 20 cyclic factors. There is a triangular basis for $\Lambda$ (triangular when expressed in the canonical basis), perhaps it looks better than our initial one? Type \kbd{mathnf(H)}. Hum, what if I also want the unimodular transformation matrix? Simple : \kbd{z = mathnf(H, 1);} \kbd{z[1]} is the triangular HNF basis, and \kbd{z[2]} is the base change matrix from the canonical basis to the new one, with determinant $\pm 1$. Try \kbd{matdet(z[2])}, then \kbd{H * z[2] == z[1]}. Fine, it works. And \kbd{z[1]} indeed looks better than \kbd{H}. Can we do better? Perhaps, but then we'd better drop the requirement that the basis be triangular, since the latter is essentially canonical. Type \bprog M = H * qflll(H) @eprog Its columns give an LLL-reduced basis for $\Lambda$ (\kbd{qflll(H)} itself gives the base change matrix). The LLL algorithm outputs a nice basis for a lattice given by an arbitrary basis, where nice means the basis vectors are almost orthogonal and short, with precise guarantees on their relations to the shortest vectors. Not really spectacular on this example, though. Let us try something else, there should be an integer relation between $\log 3$, $\log 5$ and $\log 15$. How to detect it? \bprog u = [log(15), log(5), log(3)]; m = matid(3); m[3,] = round(u * 10^25); v = qflll(m)[,1] \\@com first vector of the LLL-reduced basis u * v @eprog\noindent Pretty close. In fact, \kbd{lindep} automates this kind of search for integer relations; try \kbd{lindep(u)}. Let us come back to $\Lambda$ above, and our LLL basis in \kbd{M}. Type \bprog G = M~*M \\@com Gram matrix m = qfminim(G, norml2(M[,1]), 100, 2); @eprog\noindent This enumerates the vectors in $\Lambda$ which are shorter than the first LLL basis vector, at most 100 of them. The final argument $2$ instructs the function to use a safe (slower) algorithm, since the matrix entries are rather large; trying to remove it should produce an error, in this case. There are $\kbd{m[1]} = 6$ such vectors, and \kbd{m[3]} gives half of them (\kbd{-m[3]} would complete the lot): they are the first 3 basis vectors! So these are optimally short, at least with respect to the Euclidean length. Let us try \bprog m = qfminim(G, norml2(M[,4]), 100, 2); @eprog\noindent (The flag $2$ instructs \kbd{qfminim} to use a different enumeration strategy, which is much faster when we expect more short vectors than we want to store. Without the flag, this example requires several hours. This is an exponential time algorithm, after all!) This time, we find a slew of short vectors; \kbd{matrank(m[3])} says the 100 we have are all included in a 2-dimensional space. Let us try \bprog m = qfminim(G, norml2(M[,4]) - 1, 100000, 2); @eprog\noindent This time we find 50886 vectors of the requested length, spanning a $4$-dimensional space, which is actually generated by \kbd{M[,1]}, \kbd{M[,2]} \kbd{M[,3]} and \kbd{M[,5]}. \section{Using Transcendental Functions} All the elementary transcendental functions and several higher transcendental functions are provided: $\Gamma$ function, incomplete $\Gamma$ function, error function, exponential integral, Bessel functions ($H^1$, $H^2$, $I$, $J$, $K$, $N$), confluent hypergeometric functions, Riemann $\zeta$ function, polylogarithms, Weber functions, theta functions. More will be written if the need arises. In this type of functions, the default precision plays an essential role. In almost all cases transcendental functions work in the following way. If the argument is exact, the result is computed using the current default precision. If the argument is not exact, the precision of the argument is used for the computation. A note of warning however: even in this case the \emph{printed} value is the current real format, usually the same as the default precision. In the present chapter we assume that your machine works with 64-bit long integers. If it is not the case, we leave it to you as a good exercise to make the necessary modifications. Let's assume that we have 38 decimals of default precision (this is what we get automatically at the start of a \kbd{gp} session on 64-bit machines). Type \kbd{e = exp(1)}. We get the number $e=2.718\dots$ to 38 decimals. Let us check how many correct decimals we really have. Change the precision to a substantially higher value, for example by typing \kbd{\b{p} 100}. Then type \kbd{e}, then \kbd{exp(1)} once again. This last value is the correct value of the mathematical constant $e$ to 100 decimals, while the variable \kbd{e} shows the value that was computed to 38 decimals. Clearly they coincide to exactly 29 significant digits. So 38 digits are printed, but how many significant digits are actually contained in the variable \kbd{e}? Type \kbd{\#e} which indicates we have exactly $2$ mantissa words. Since $2\ln(2^{64}) / \ln(10)\approx38.5$ we see that we have 38 or 39 significant digits (on 64-bit machines). \smallskip Come back to 38 decimals (\kbd{\b{p} 38}). If we type \kbd{exp(1.)} you can check that we also obtain 38 decimals. However, type \kbd{f = exp(1 + 1E-40)}. Although the default precision is still 38, you can check using the method above that we have in fact 96 significant digits! The reason is that \kbd{1 + 1E-40} is computed according to the PARI philosophy, i.e.~to the best possible precision. Since \kbd{1E-40} has 39 significant digits and 1 has ``infinite'' precision, the number \kbd{1 + 1E-30} will have $79=39+40$ significant digits, hence \kbd{f} also. Now type \kbd{cos(1E-19)}. The result is printed as $1.0000\dots$, but is of course not exactly equal to 1. Using \kbd{\#\%}, we see that the result has 4 mantissa words, giving us the possibility of having 77 correct significant digits. PARI gives you as much as it can, and since 3 mantissa words would have given you only 57 digits, it uses 4. But why does it give so precise a result? Well, it is the same reason as before. When $x$ is close to 1, $\cos(x)$ is close to $1-x^2/2$, hence the precision is going to be approximately the same as when computing this quantity, here $1-0.5*10^{-38}$ where $0.5*10^{-38}$ is considered with 38 significant digit accuracy. Hence the result will have approximately $38+38=76$ significant digits. This philosophy cannot go too far. For example, when you type \kbd{cos(0)}, \kbd{gp} should give you exactly 1. Since it is reasonable for a program to assume that a transcendental function never gives you an exact result, \kbd{gp} gives you $1.000\dots$ with as many mantissa word as the current precision. \medskip Let's see some more transcendental functions at work. Type \kbd{gamma(10)}. No problem (type \kbd{9!} to check). Type \kbd{gamma(100)}. The number is now written in exponential format because the default accuracy is too small to give the correct result. To get all digits, the most natural solution is to increase the precision; since \kbd{gamma(100)} has 156 decimal digits, type \kbd{\b{p} 170} to be on the safe side, then \kbd{gamma(100)} once again. Another one is to compute \kbd{99!} directly. Try \kbd{gamma(1/2 + 10*I)}. No problem, we have the complex $\Gamma$ function. Now type \bprog t = 1000; z = gamma(1 + I*t) * t^(-1/2) * exp(Pi/2*t) / sqrt(2*Pi) norm(z) @eprog\noindent The latter is very close to 1, in accordance with the complex Stirling formula. \smallskip Let's play now with the Riemann zeta function. First turn on the timer (type \kbd{\#}). Type \kbd{zeta(2)}, then \kbd{Pi\pow 2/6}. This seems correct. Type \kbd{zeta(3)}. All this takes essentially no time at all. However, type \kbd{zeta(3.1)}. You will notice that the time is substantially larger; if your machine is too fast to see the difference, increase the precision to \kbd{\b{p}1000}. This is because PARI uses special formulas to compute \kbd{zeta(n)} when \kbd{n} is an integer. Type \kbd{zeta(1 + I)}. This also works. Now for fun, let us compute in a naive way the first complex zero of \kbd{zeta}. We know that it is of the form $1/2 + i*t$ with $t$ between 14 and 15. Thus, we can use the following series of instructions. But instead of typing them directly, write them into a file, say \kbd{zeta.gp}, then type \kbd{\b{r} zeta.gp} under \kbd{gp} to read it in: \bprog { t1 = 1/2 + 14*I; t2 = 1/2 + 15*I; eps = 1E-50; z1 = zeta(t1); until (norm(z2) < eps, z2 = zeta(t2); if (norm(z2) < norm(z1), t3 = t1; t1 = t2; t2 = t3; z1 = z2 ); t2 = (t1+t2) / 2.; print(t1 ": " z1) ) } @eprog\noindent Don't forget the braces: they tell \kbd{gp} that a sequence of instructions is going to span many lines. We thus obtain the first zero to 25 significant digits. By the way, you don't need to type in the suffix~\kbd{.gp} in the \b{r} command: it is supplied by \kbd{gp} if you forget it. The suffix is not mandatory either, but it is convenient to have all GP scripts labeled in the same distinctive way. Also, some text editors, e.g. Emacs or Vim, will recognize GP scripts as such by their suffix and load special colourful modes. \medskip % As mentioned at the beginning of this tutorial, some transcendental functions can also be applied to $p$-adic numbers. This is as good a time as any to familiarize yourself with them. Type \bprog a = exp(7 + O(7^10)) log(a) @eprog\noindent All seems in order. \bprog b = log(5 + O(7^10)) exp(b) @eprog\noindent Is something wrong? We don't recover the number we started with? This is normal: type \bprog exp(b) * teichmuller(5 + O(7^10)) @eprog\noindent and we indeed recover our initial number. The Teichm\"uller character \kbd{teichmuller(x)} on $\Z_p^*$ is the unique \hbox{$(p-1)$-st} root of unity which is congruent to \kbd{x} modulo $p$, assuming that \kbd{x} is a $p$-adic unit.\smallskip % Let us come back to real numbers for the moment. Type \kbd{agm(1,sqrt(2))}. This gives the arithmetic-geometric mean of 1 and $\sqrt2$, and is the basic method for computing complete elliptic integrals. In fact, type \kbd{Pi/2 / intnum(t=0,Pi/2, 1 / sqrt(1 + sin(t)\pow 2))}, \noindent and the result is the same. The elementary transformation \kbd{x = sin(t)} gives the mathematical equality $$\int_0^1 \dfrac{dx}{\sqrt{1-x^4}} = \dfrac{\pi}{2\text{AGM}(1,\sqrt2)} \enspace,$$ which was one of Gauss's remarkable discoveries in his youth. Now type \kbd{2 * agm(1,I) / (1+I)}. As you see, the complex AGM also works, although one must be careful with its definition. The result found is almost identical to the previous one. Do you see why? Finally, type \kbd{agm(1, 1 + 7 + O(7\pow 10))}. So we also have $p$-adic AGM. Note however that since the square root of a $p$-adic number is not in general an element of the same $p$-adic field, only certain $p$-adic AGMs can be computed. In addition, when $p=2$, the congruence restriction is that \kbd{agm(a,b)} can be computed only when \kbd{a/b} is congruent to 1 modulo $16$, and not 8 as could be expected.\smallskip % Now type \kbd{?3}. This gives you the list of all transcendental functions. Instead of continuing with more examples, we suggest that you experiment yourself with this list. Try integer, real, complex and $p$-adic arguments. You will notice that some have not been implemented (or do not have a reasonable definition). \section{Using Numerical Tools} Although not written to be a numerical analysis package, PARI can nonetheless perform some numerical computations. Since linear algebra and polynomial computations are treated somewhere else, this section focuses on solving equations and various methods of summation. You of course know the formula $\pi = 4(1-\dfrac13+\dfrac15-\dfrac17+\cdots)$ which is deduced from the power series expansion of \kbd{atan(x)}. You also know that $\pi$ cannot be computed from this formula, since the convergence is so slow. Right? Wrong! Type \bprog \p 100 4 * sumalt(k=0, (-1)^k/(2*k + 1)) @eprog\noindent In a split second, we get $\pi$ to 100 significant digits (type \kbd{Pi} to check). Similarly, try \bprog sumpos(k=1, k^-2) @eprog\noindent Although once again the convergence is slow, the summation is rather fast; compare with the exact result \kbd{Pi\pow 2/6}. This is less impressive because a bit slower than for alternating sums, but still useful. Even better, \kbd{sumalt} can be used to sum divergent series! Type \bprog zet(s) = sumalt(k=1, (-1)^(k-1) / k^s) / (1 - 2^(1-s)) @eprog\noindent Then for positive values of \kbd{s} different from 1, \kbd{zet(s)} is equal to \kbd{zeta(s)} and the series converges, albeit slowly; \kbd{sumalt} doesn't care however. For negative \kbd{s}, the series diverges, but \kbd{zet(s)} still gives the correct result! (Namely, the value of a suitable analytic continuation.) Try \kbd{zet(-1)}, \kbd{zet(-2)}, \kbd{zet(-1.5)}, and compare with the corresponding values of \kbd{zeta}. You should not push the game too far: \kbd{zet(-100)}, for example, gives a completely wrong answer. Try \kbd{zet(I)}, and compare with \kbd{zeta(I)}. Even (some) complex values work, although the sum is not alternating any more! Similarly, try \bprog sumalt(n=1, (-1)^n / (n+I)) @eprog \medskip More traditional functions are the numerical integration functions. Try \kbd{intnum(t=1,2, 1/t)} and presto! you get 100 decimals of $\log(2)$. Look at Chapter 3 to see the available integration functions. With PARI, however, you can go further since complex types are allowed. For example, assume that we want to know the location of the zeros of the function $h(z)=e^z-z$. We use Cauchy's theorem, which tells us that the number of zeros in a disk of radius $r$ centered around the origin is equal to $$\dfrac{1}{2i\pi}\int_{C_r}\dfrac{h'(z)}{h(z)}\,dz\enspace,$$ where $C_r$ is the circle of radius $r$ centered at the origin. The function we want to integrate is \bprog fun(z) = my(u = exp(z)); (u-1) / (u-z) @eprog\noindent (Here \kbd{u} is a local variable to the function \kbd{f}: whenever a function is called, \kbd{gp} fills its argument list with the actual arguments given, and initializes the other declared parameters and local variables to 0. It will then restore their former values upon exit. If we had not declared \kbd{u} in the function prototype, it would be considered as a global variable, whose value would be permanently changed. It is not mandatory to declare in this way all parameters, but beware of side effects!) Type now: \bprog zero(r) = r/(2*Pi) * intnum(t=0, 2*Pi, real( fun(r*exp(I*t)) * exp(I*t) )) @eprog The function \kbd{zero(r)} will count the number of zeros of \kbd{fun} whose modulus is less than \kbd{r}: we simply made the change of variable $z = r*\exp(i*t)$, and took the real part to avoid integrating the imaginary part. Actually, there is a built-in function \kbd{intcirc} to integrate over a circle, yielding the much simpler: \bprog zero2(r) = intcirc(z=0, r, fun(z)) @eprog (This is a little faster than the previous implementation, and no less accurate.) We may type \kbd{\b{p} 9} since we know that the result is a small integer (but the computations should be instantaneous even at \b{p} 100 or so), then \kbd{zero(1)}, \kbd{zero(1.5)}. The result tells us that there are no zeros inside the unit disk, but that there are two (necessarily complex conjugate) in the annulus $1<|z|<1.5$. For the sake of completeness, let us compute them. Let $z = x+iy$ be such a zero, with $x$ and $y$ real. Then the equation $e^z-z=0$ implies, after elementary transformations, that $e^{2x}=x^2+y^2$ and that $e^x\cos(y)=x$. Hence $y=\pm\sqrt{e^{2x}-x^2}$ and hence $e^x\cos(\sqrt{e^{2x}-x^2})=x$. Therefore, type \bprog fun(x) = my(u = exp(x)); u * cos(sqrt(u^2 - x^2)) - x @eprog\noindent Then \kbd{fun(0)} is positive while \kbd{fun(1)} is negative. Come back to precision 38 and type \bprog x0 = solve(x=0,1, fun(x)) z = x0 + I*sqrt(exp(2*x0) - x0^2) @eprog\noindent which is the required zero. As a check, type \kbd{exp(z) - z}. Of course you can integrate over contours which are more complicated than circles, but you must perform yourself the variable changes, as we have done above to reduce the integral to a number of integrals on line segments. \smallskip % The example above also shows the use of the \kbd{solve} function. To use \kbd{solve} on functions of a complex variable, it is necessary to reduce the problem to a real one. For example, to find the first complex zero of the Riemann zeta function as above, we could try typing \kbd{solve(t=14,15, real( zeta(1/2 + I*t) ))}, \noindent but this does not work because the real part is positive for $\kbd{t}=14$ and $15$. As it happens, the imaginary part works. Type \kbd{solve(t=14,15, imag( zeta(1/2 + I*t) ))}, \noindent and this now works. We could also narrow the search interval and type for instance \kbd{solve(t=14,14.2, real( zeta(1/2 + I*t) ))} \noindent which would also work. \section{Polynomials} First a word of warning: it is essential to understand the difference between exact and inexact objects. Try \bprog gcd(x - Pi, x^2 - 6*zeta(2)) @eprog\noindent We return a trivial GCD because the notion of GCD for non-exact polynomials doesn't make much sense. A better quantitative approach is to use \bprog polresultant(x - Pi, x^2 - 6*zeta(2)) @eprog\noindent A result close to zero shows that the GCD is non-trivial for small deformations of the inputs. Without telling us what it is, of course. This being said, we will mostly use polynomials (and power series) with exact coefficients in our examples.\smallskip The simplest way to input a polynomial, is to simply write it down, or use an explicit formula for the coefficients and the function \kbd{sum}: \bprog T = 1 + x^2 + 27*x^10; T = sum(i = 1, 100, (i+1) * x^i); @eprog\noindent but it is in much more efficient to create a vector of coefficients then convert it to a polynomial using \kbd{Pol} or \kbd{Polrev} (\kbd{Pol([1,2])} is $x+2$, \kbd{Polrev([1,2]) is $2x + 1$}) : \bprog T = Polrev( vector(100, i, i) ); for (i=1, 10^4, Polrev( vector(100, i, i) ) ) \\@com time: 60ms for (i=1, 10^4, sum(i = 1, 100, (i+1) * x^i) ) \\@com time: 1,74ms @eprog\noindent The reason for the discrepancy is that the explicit summation (of densely encoded polynomials) is quadratic in the degree, whereas creating a vector of coefficients then converting it to a polynomial type is linear. We also have a few built-in classical polynomial families. Consider the $15$-th cyclotomic polynomial, \bprog pol = polcyclo(15) @eprog\noindent which is of degree $\varphi(15)=8$. Now, type \bprog r = polroots(pol) @eprog\noindent We obtain the 8 complex roots of \kbd{pol}, given to 38 significant digits. To see them better, type \b{b}: they are given as pairs of complex conjugate roots, in a random order. The only ordering done by the function \kbd{polroots} concerns the real roots, which are given first, and in increasing order. The roots of \kbd{pol} are by definition the primitive $15$-th roots of unity. To check this, simply type \kbd{rc = r\pow 15}. Why, we get an error message! Fair enough, vectors cannot be multiplied, even less raised to a power. However, type \bprog rc = r^15. @eprog\noindent without forgetting the `\kbd{.}' at the end. Now it works, because powering to a non-integer exponent is a transcendental function and hence is applied termwise. Note that the fact that $15.$ is a real number which is representable exactly as an integer has nothing to do with the problem. We see that the components of the result are very close to 1. It is however tedious to look at all these real and imaginary parts. It would be impossible if we had many more. Let's do it automatically. Type \bprog rr = round(rc) sqrt( norml2(rc - rr) ) @eprog\noindent We see that \kbd{rr} is indeed all 1's, and that the $L^2$-norm of \kbd{rc - rr} is around $2.10^{-37}$, reasonable enough when we work with 38 significant digits! Note that the function \kbd{norml2}, contrary to what its name implies, does not give the $L^2$ norm but its square, hence we must take the square root. Well, this is not absolutely necessary in the present case! In fact, \kbd{round} itself already provides a built-in rough approximation of the error: \bprog rr = round(rc, &e) @eprog\noindent Now \kbd{e} contains the number of error bits when rounding \kbd{rc} to \kbd{rr}; in other words the sup norm of $\kbd{rc} - \kbd{rr}$ is bounded by $2^{-\kbd{e}}$. % \smallskip Now type \bprog pol = x^5 + x^4 + 2*x^3 - 2*x^2 - 4*x - 3 factor(pol) factor( poldisc(pol) ) fun(p) = factorpadic(pol,p,10); @eprog\noindent The polynomial \kbd{pol} factors over $\Q$ (or $\Z$) as a product of two factors, and the primes dividing its discriminant are $11$, $23$ and $37$. We also created a function \kbd{fun(p)} which factors \kbd{pol} over $\Q_p$ to $p$-adic precision 10. Type \bprog fun(5) fun(11) fun(23) fun(37) @eprog\noindent to see different splittings. Similarly, type \bprog lf(p) = lift( factormod(pol,p) ); lf(2) lf(11) lf(23) lf(37) @eprog\noindent which show the different factorizations, this time over $\F_p$. In fact, even better: type successively \bprog t = 't; \\@com we want \kbd{t} to be a free variable T = ffinit(3,3, t) pol2 = subst(T, t, x) fq = factorff(pol2, 3, T) centerlift( lift(fq) ) @eprog\noindent \kbd{T}, which is actually \kbd{t\pow 3 + t\pow 2 + t + 2} (with intmod coefficients), is defined above to be an irreducible polynomial of degree $3$ over $\F_3$. This code snippet factors the polynomial \kbd{pol2} over the finite field $\F_3[t]/(T)$. This is of course a form of the field $\F_{27}$. We know that Gal$(\F_{27}/\F_3)$ is cyclic of order 3 generated by the Frobenius homomorphism $u\mapsto u^3$, and the roots that we have found give the action of the powers of the Frobenius on \kbd{t}. (If you do not know what I am talking about, please try some examples, it's not so hard to figure out.) We took pain above to factor a polynomial in the variable $x$ over a finite field defined by a polynomial in $t$, even though they were apparently one and the same. There is a crucial rule in all routines involving relative extensions: the variable associated to the base field is required to have lower priority than the variables of polynomials whose coefficients are taken in that base field. Have a look at the section on \emph{Variable priorities} in the user's manual (see ``The GP programming language''). A simpler way to accomplish the above, using \typ{FFELT}s is \bprog g = ffgen(3^3, 't); T = subst(g.mod, t, x); factor(T * g^0) @eprog\noindent Multiplying by $g^0 = 1$ seems to do ``nothing'', but it has the interesting effect of mapping all coefficients of $T$ to $\F_{27}$. The generic function \kbd{factor} then does the right thing. (Typing \kbd{factor(T)} directly would factor it over $\Q$, not what we wanted.) Similarly, type \bprog pol3 = x^4 - 4*x^2 + 16 fn = lift( factornf(pol3, t^2 + 1) ) @eprog\noindent and we get the factorization of the polynomial \kbd{pol3} over the number field defined by $t^2+1$, i.e.~over $\Q(i)$. Without the \kbd{lift}, the result would involve number field elements as \typ{POLMOD}s of the form \kbd{Mod(1+t, t\pow2+1)}, which are more explicit but much less readable. \smallskip To summarize, in addition to being able to factor integers, you can factor polynomials over $\C$ and $\R$ using \kbd{polroots}, over $\F_p$ using \kbd{factormod}, over $\F_{p^k}$ using \kbd{factorff}, over $\Q_p$ using \kbd{factorpadic}, over $\Q$ using \kbd{factor}, and over number fields using \kbd{factornf} or \kbd{nffactor}. Note however that \kbd{factor} itself will try to guess intelligently over which ring you want to factor: try \bprog pol = x^2 + 1; factor(pol) factor(pol *1.) factor(pol * (1 + 0*I)) factor(pol * (1 + 0.*I)) factor(pol * Mod(1,2)) factor(pol * Mod(1, Mod(1,3)*(t^2+1))) @eprog In the present version \vers{}, it is not possible to factor over other rings than the ones mentioned above. For example \kbd{gp} cannot directly factor multivariate polynomials, although it is not too hard to write a simple-minded Kronecker's substitution to reduce to the univariate case. (Exercise!) Other functions related to factoring are \kbd{padicappr}, \kbd{polrootsmod}, \kbd{polrootspadic}, \kbd{polsturm}. Play with them a little. Finally, type \bprog polsym(pol3, 20) @eprog\noindent where \kbd{pol3} was defined above. This gives the sum of the $k$-th powers of the roots of \kbd{pol3} up to $k=20$, of course computed using Newton's formula and not using \kbd{polroots}. You notice that every odd sum is zero (expected, since the polynomial is even), but also that the signs follow a regular pattern and that the (non-zero) absolute values are powers of 2. This is true: prove it, and more precisely find an explicit formula for the $k$-th symmetric power not involving (non-rational) algebraic numbers. \section{Power series} Now let's play with power series as we have done at the beginning. Type \bprog N = 39; 8*x + prod(n=1,N, if(n%4, 1 - x^n, 1), 1 + O(x^(N+1)))^8 @eprog\noindent Apparently, only even powers of \kbd{x} appear. This is surprising, but can be proved using the theory of modular forms. Note that we initialize the product to \kbd{1 + O(x\pow (N+1))}, otherwise the whole computation would be done with polynomials; this would first have been slightly slower and also totally useless since the coefficients of \kbd{x\pow (N+1)} and above are irrelevant anyhow if we stop the product at $\kbd{n} = \kbd{N}$. While we are on the subject of modular forms (which, together with Taylor series expansions are another great source of power series), type \bprog \ps 122 \\@com shortcut for \kbd{default(seriesprecision, 122)} d = x * eta(x)^24 @eprog\noindent This gives the first 122 terms of the Fourier series expansion of the modular discriminant function $\Delta$ of Ramanujan. Its coefficients give by definition the Ramanujan $\tau$ function, which has a number of marvelous properties (look at any book on modular forms for explanations). We would like to see its properties modulo 2. Type \kbd{d\%2}. Hmm, apparently PARI doesn't like to reduce coefficients of power series, or polynomials for that matter, directly. Can we do it without writing a little program? No problem. Type instead \bprog lift(Mod(1,2) * d) centerlift(Mod(1,3) * d) @eprog\noindent and now this works like a charm. The pattern in the first result is clear; the pattern is less clear in the second result, but nonetheless there is one. Of course, it now remains to prove it (see Antwerp III or your resident modular forms guru). \section{Working with Elliptic Curves} Now we are getting to more complicated objects. Just as with number fields which we will meet later on, the first thing to do is to initialize them. That's because a lot of data will be needed repeatedly, and it's much more convenient to have it ready once and for all. Here, this is done with the function \kbd{ellinit}. So type \bprog e0 = ellinit([6,-3,9,-16,-14]) @eprog This computes a number of things about the elliptic curve defined by the affine equation % $$ y^2+6xy+9y = x^3-3x^2-16x-14\enspace. $$ % It is not that clear what all these funny numbers mean, except that we recognize the first few of them as the coefficients we just input. To retrieve meaningful information from such complicated objects (and number fields will be much worse), one uses so-called \emph{member functions}. Type \kbd{?.} to get a complete list. Whenever \kbd{ell} appears in the right hand side, we can apply the corresponding function to an object output by \kbd{ellinit}. (I'm sure you know how the other \kbd{init} functions will be called now, don't you? Oh, by the way, neither \kbd{clgpinit} nor \kbd{pridinit} exist.) Let's try it. The discriminant \kbd{e0.disc} is equal to 37, hence the conductor of the curve is 37. Of course in general it is not so trivial. In fact, although the equation of the curve is clearly minimal (since the discriminant is $12$th-power-free), it is not in standard reduced form, so type \bprog e = ellminimalmodel(e0) @eprog\noindent which gives the \kbd{ell} structure associated with the standard model, exactly as if we had used \kbd{ellinit} on a reduced equation. For some related data, type \bprog gr = ellglobalred(e0) @eprog\noindent The first component \kbd{gr[1]} tells us that the conductor is 37 as we already knew. The second component is a 4-component vector which allows us to get the minimal equation: in fact \kbd{e} is \kbd{ellchangecurve(e0, gr[2])}. You can for the moment ignore the third component \kbd{gr[3]}. (For the impatient reader, this is the product of the local Tamagawa numbers, $c_p$.) Type \bprog q0 = [-2,2] ellisoncurve(e0, q0) q = ellchangepoint(q0,gr[2]) ellisoncurve(e, q) @eprog\noindent The point \kbd{q0} is on the curve, as checked by \kbd{ellisoncurve}, and we transferred it onto the minimal model \kbd{e}, using \kbd{ellchangepoint} and the change of variable computed above. Note that \kbd{ellchangepoint()} is unusual among the elliptic curve functions in that it does not take an \kbd{ell} structure as its first argument: in \kbd{gp}, points do not ``know'' which curve they are on, but to move a point from one model to another we only need to know the coordinates of the point and the transformation data here stored in \kbd{gr[2]}. Also, the point at infinity is represented as \kbd{[0]} on all elliptic curves; this is the identity for the group law. Here, \kbd{q=[0,0]} obviously lies on \kbd{e}, which has equation $y^2+y = x^3-x$. Let us now play a little with points on \kbd{e}. The group law on an elliptic curve is implemented with the functions \kbd{elladd} for addition, \kbd{ellsub} for subtraction and \kbd{ellmul} for multiplication by an integer. For example, the negative of \kbd{q} is \kbd{ellsub(e,[0],q)}, and the double is obtained either as \kbd{ellmul(e,q,2)} or as \kbd{elladd(e,q,q)}. Now \kbd{q} may be a torsion point. Type \kbd{ellheight(e, q)}, which computes the canonical Neron-Tate height of \kbd{q}. Note that \kbd{ellheight} assumes that \kbd{e} is \emph{minimal}! (Which it is.) This is non-zero, hence \kbd{q} is not torsion. To see this even better, type \bprog for(k = 1, 20, print(ellmul(e, q, k))) @eprog\noindent and we see the characteristic parabolic explosion of the size of the points. (And another proof that \kbd{q} is not torsion, assuming Mazur's bound on the size of the rational torsion.) We could can also type \kbd{ellorder(e, q)} which returns 0, telling us yet again that \kbd{q} is non-torsion. As a consistency check, type \bprog ellheight(e, ellmul(e, q,20)) / ellheight(e, q) @eprog\noindent We indeed find $400=20^2$ as it should be. Notice how (almost) all those \kbd{ell}--prefixed functions take our elliptic curve as a first argument? This will be true with number fields as well: whatever object was initialized by an $ob$--\kbd{init} function will have to be used as a first argument of all the $ob$--prefixed functions. Conversely, you won't be able to use any such high-level function before you correctly initialize the relevant object. \smallskip Ok, let's try another curve. Type \bprog E = ellinit([0,-1,1,0,0]) q = [0,0]; ellheight(E, q) @eprog\noindent This corresponds to the equation $y^2+y = x^3-x^2$ and an obvious rational point on it. Again from the discriminant we see that the conductor is equal to 11, and if you type \kbd{ellminimalmodel(E)} you will see that the equation for \kbd{E} is minimal. This time the height is very close to zero, hence \kbd{q} must be a torsion point. Indeed, typing \bprog for(k=1, 5, print(ellmul(E, q,k))) ellorder(E, q) \\@com simpler @eprog\noindent we see in two different ways that \kbd{q} is a point of order 5. Moreover, typing \bprog elltors(E) @eprog\noindent shows that \kbd{q} generates all the torsion of \kbd{E}, which is cyclic of order~$5$. \smallskip Let's try still another curve, $y^2+y = x^3-7x+6$: \bprog e = ellinit([0,0,1,-7,6]) ellglobalred(e) @eprog\noindent As before, this is a minimal equation; now the conductor is 5077. There are some trivial integral points on this curve, but let's try to be more systematic. Typing \bprog elltors(e) @eprog\noindent shows that the torsion subgroup is trivial, so we don't have to worry about torsion points. Next, the member \kbd{e.roots} gives us the 3 roots of the minimal equation over $\C$, i.e.~$Y^2=X^3-7X+25/4$ (set $(X,Y)=(x,y+1/2)$) so if $(x,y)$ is a real point on the curve, $x$ must be at least equal to the smallest root, i.e.~$x\ge-3$. Finally, if $(x,y)$ is on the curve, its opposite is clearly $(x,-y-1)$. Type \bprog { v = List(); for (x = -3, 1000, s = ellordinate(e,x); if (#s, listput(v, [x,s[1]])) \\@com or \kbd{if (\#s != 0,} ); v } @eprog\noindent (If cardinality of \kbd{s} is non-zero, insert the first point with given \kbd{x}.) We thus get a large number (18) of integral points. Together with their opposites and the point at infinity, this makes a total of 37 integral points, which is large for a curve having such a small conductor. So we suspect (if we do not know already, since this curve is quite famous!) that the rank of this curve must be large. Let's try and put some order into this. Note that we work only with the integral points, but in general rational points should also be considered. Type \bprog v = Vec(v); \\@com convert to a vector hv = ellheight(e, v) @eprog\noindent (We convert the list to a vector because \typ{LIST}s are not accepted as input by most mathematical functions. They must be converted to a standard vector type first.) This gives the vector of canonical heights. Let us order the points according to their height. For this, type \bprog perm = vecsort(vector(#v,i,i), (a,b) -> hv[a]>hv[b]); v = vecextract(v, perm) @eprog\noindent Note how we input a non-obvious comparison function to \kbd{vecsort}, using an inline anonymous function: we sort the integers between $1$ and the number of points we have declaring that $a > b$ if and only if the height of the $a$-th point is larger than the height of the $b$-th. The result is a permutation which we apply to \kbd{v} using \kbd{vecextract}. It seems reasonable to take the numbers with smallest height as possible generators of the Mordell-Weil group. Let's try the first four: type \bprog m = ellheightmatrix(e, v[1..4]); matdet(m) @eprog\noindent Since the curve has no torsion, the determinant being close to zero implies that the first four points are dependent. To find the dependency, it is enough to find the kernel of the matrix \kbd{m}. So type \kbd{matker(m)}: we indeed get a non-trivial kernel, and the coefficients are close to integers. Typing \kbd{elladd(e, v[1],v[3])} does indeed show that it is equal to \kbd{v[4]}. Taking any other four points, we would in fact always find a dependency. Let's find all dependencies. Type \bprog vp = [v[1],v[2],v[3]]~; m = ellheightmatrix(e,vp); matdet(m) @eprog\noindent This is now clearly non-zero so the first 3 points are linearly independent, showing that the rank of the curve is at least equal to 3. (It is in fact equal to 3, and \kbd{e} is the curve of smallest conductor having rank 3.) We would like to see whether the other points are dependent. For this, we use the function \kbd{ellbil}. Indeed, if \kbd{Q} is some point which is dependent on \kbd{v[1],v[2]} and \kbd{v[3]}, then \kbd{matsolve(m, ellbil(e, vp,Q))} will by definition give the coefficients of the dependence relation. If these coefficients are close to integers, then there is a dependency, otherwise not. This is much safer than using the \kbd{matker} function. Thus, type \bprog w = vector(#v, k, matsolve(m, ellbil(e, vp,v[k]))) wr = round(w, &err) @eprog\noindent We ``see'' that the coefficients are all very close to integers, and we quantified it with the last instruction: \kbd{wr} is the vector expressing all the components of \kbd{v} on its first 3, and \kbd{err} gives an upper bound on the maximum distance to an integer. We are thus led to strongly believe that the curve has rank exactly 3, with generators \kbd{v[1]}, \kbd{v[2]} and \kbd{v[3]}, and this can be proved to be the case. Two remarks: (1) Using the height pairing to find dependence relations as we have done only in fact finds relations modulo torsion; but in this example, the curve has trivial torsion, as we checked earlier. (2) In the above calculation we were lucky that all the \kbd{v[j]} were $\Z$-linear combinations of \kbd{v[1]}, \kbd{v[2]} and \kbd{v[3]} and not just $\Q$-linear combinations; in general the result of \kbd{matsolve(m, ellbil(e, vp,Q))} might have given a vector of rationals: if $k\ge2$ is minimal such that $kQ$ is in the subgroup generated by \kbd{v[1]}, \kbd{v[2]} and \kbd{v[3]}, then the entries of \kbd{matsolve(m, ellbil(e, vp,Q))} will be rationals with common denominator~$k$. \smallskip Let us explore a few more elliptic curve related functions. Keep our curve \kbd{e} of rank 3, and type \bprog v1 = [1,0]; z1 = ellpointtoz(e, v1) v2 = [2,0]; z2 = ellpointtoz(e, v2) @eprog\noindent We thus get the complex parametrization of the curve. To add the points \kbd{v1} and \kbd{v2}, we should of course type \kbd{elladd(e, v1,v2)}, but we can also type \kbd{ellztopoint(e, z1 + z2)} which has the disadvantage of giving complex numbers, but illustrates how the group law on \kbd{e} is obtained from the addition law on $\C$. Type \bprog f = x * Ser(ellan(e, 30)) @eprog\noindent This gives a power series which is the Fourier expansion of a modular form of weight 2 for $\Gamma_0(5077)$. (This has been proved directly, before Wiles's general result.) In fact, to find the modular parametrization of the curve, type \bprog modul = elltaniyama(e) u = modul[1]; v = modul[2]; @eprog\noindent We can check in various ways that this indeed parametrizes the curve: \bprog (v^2 + v) - (u^3 - 7*u + 6) @eprog\noindent is close to $0$ for instance, or simply that \kbd{ellisoncurve(e,modul)} returns~$1$. Now type \bprog x * u' / (2*v + 1) @eprog\noindent and we see that this is equal to the modular form \kbd{f} found above; the quote \kbd{'} tells \kbd{gp} to take the derivative of the expression with respect to its main variable. The functions \kbd{u} and \kbd{v}, considered on the upper half plane with $x=e^{2i\pi\tau}$, are in fact modular \emph{functions} for $\Gamma_0(5077)$. \smallskip The function \kbd{ellan(e, 30)} gives the first~$30$ coefficients $a_n$ of the $L$-series of \kbd{e}. One can also ask for a single coefficient: the millionth is \kbd{ellak(e, 10\pow 6)}. Note however that calling \kbd{ellan(e,100000)} is much faster than the equivalent \kbd{vector(100000,k,ellak(e,k))}. For a prime~\kbd{p}, \kbd{ellap(e,p)} is equivalent to \kbd{ellak(e,p)}; this is the integer $a_p$ such that the number of points on \kbd{e} over $\F_p$ is $1+p-a_p$. (With the standard PARI distribution, \kbd{ellap} is the only way to obtain the order of an elliptic curve over $\F_p$ in \kbd{gp}. The external package \kbd{ellsea} provides much more efficient routines.) Finally, let us come back to the curve \kbd{E} defined above by \kbd{E = ellinit([0,-1,1,0,0])}, which had an obvious rational $5$-torsion point. The sign of the functional equation, given by \kbd{ellrootno(E)}, is $+1$. Assuming the rank parity conjecture, it follows that the Mordell-Weil group of $E$ has even rank. The value of the L-function of \kbd{E} at 1 \bprog ls = elllseries(E, 1) @eprog\noindent is definitely non-zero, so \kbd{E} has rank $0$. According to the Birch and Swinnerton-Dyer conjecture, which is proved for this curve, \kbd{ls} is given by the following formula (in this case): % \def\sha{\hbox{III}} $$L(E,1)=\dfrac{\Omega\cdot c\cdot|\sha|}{|E_{\text{tors}}|^2}\enspace,$$ % where $\Omega$ is the real period of $E$, $c$ is the global Tamagawa number, product of the local $c_p$ for primes $p$ dividing the conductor, $|\sha|$ is the order of the Tate-Shafarevich group, and $E_{\text{tors}}$ is the torsion group of $E$. Now we know many of these quantities: $\Omega$ is equal to \kbd{E.omega[1]} (if there had been 3 real roots instead of 1 in \kbd{E.roots}, $\Omega$ would be equal to \kbd{2 * E.omega[1]}). The Tamagawa number $c$ is given as the last component of \kbd{ellglobalred(E)}, and here is equal to 1. We already know that the torsion subgroup of $E$ contains a point of order 5, and typing \kbd{elltors(E)} shows that it is of order exactly 5. So type \bprog ls * 25/E.omega[1] @eprog\noindent This shows that $\sha$ must be the trivial group. For more detailed information on the local reduction of an elliptic curve at a specific prime~\kbd{p}, use the function \kbd{elllocalred(E,p)}; the second component gives the Kodaira symbol in an encoded form. See the manual or online help for details. \section{Working in Quadratic Number Fields} The simplest of all number fields outside $\Q$ are quadratic fields and are the subject of the present section. We shall deal in the next one with general number fields (including $\Q$ and quadratic fields!), and one should be aware that all we will see now has a more powerful, in general easier to use, equivalent in the general context. But possibly much slower. Such fields are characterized by their discriminant. Even better, any non-square integer $D$ congruent to 0 or 1 modulo 4 is the discriminant of a specific order in a quadratic field. We can check whether this order is maximal with \kbd{isfundamental(D)}. Elements of a quadratic field are of the form $a+b\omega$, where $\omega$ is chosen as $\sqrt{D}/2$ if $D$ is even and $(1+\sqrt{D})/2$ if $D$ is odd, and are represented in PARI by quadratic numbers. To initialize working in a quadratic order, one starts by the command \kbd{w = quadgen($D$)}. This sets \kbd{w} equal to $\omega$ as above, and is printed \kbd{w}. Note however that if several different quadratic orders are used, a printed \kbd{w} may have several different meanings. For example if you type \bprog w1 = quadgen(-23) w2 = quadgen(-15) @eprog\noindent both will be printed as \kbd{w}, but of course they are not equal. Hence beware when dealing with several quadratic orders at once. \smallskip % In addition to elements of a quadratic order, we also want to be able to handle ideals of such orders. In the quadratic case, it is equivalent to handling binary quadratic forms. For negative discriminants, quadratic forms are triples $(a,b,c)$ representing the form $ax^2+bxy+cy^2$. Such a form will be printed as, and can be created by, \kbd{Qfb($a$,$b$,$c$)}. Such forms can be multiplied, divided, powered as many PARI objects using the usual operations, and they can also be reduced using the function \kbd{qfbred} (it is not the purpose of this tutorial to explain what all these things mean). In addition, Shanks's NUCOMP algorithm has been implemented (functions \kbd{qfbnucomp} and \kbd{qfbnupow}), and this is usually a little faster. Finally, you have at your disposal the functions \kbd{qfbclassno} which (\emph{usually}) gives the class number, the function \kbd{qfbhclassno} which gives the Hurwitz class number, and the much more sophisticated \kbd{quadclassunit} function which gives the class number and class group structure. Let us see examples of all this at work. Type \kbd{qfbclassno(-10007)}. \kbd{gp} tells us that the result is 77. However, you may have noticed in the explanation above that the result is only \emph{usually} correct. This is because the implementers of the algorithm have been lazy and have not put the complete Shanks algorithm into PARI, causing it to fail in certain very rare cases. In practice, it is almost always correct, and the much more powerful \kbd{quadclassunit} program, which \emph{is} complete (at least for fundamental discriminants) can give confirmation; but now, under the Generalized Riemann Hypothesis! So we may be a little suspicious of this class number. Let us check it. First, we need to find a quadratic form of discriminant $-10007$. Since this discriminant is congruent to 1 modulo 8, we know that there is an ideal of norm equal to 2, i.e.~a binary quadratic form $(a,b,c)$ with $a=2$. To compute it we type \kbd{f = qfbprimeform(-10007, 2)}. OK, now we have a form. If the class number is correct, the very least is that this form raised to the power 77 should equal the identity. Type \kbd{f\pow 77}. We get a form starting with 1, i.e.~the identity. Raising \kbd{f} to the powers 11 and 7 does not give the identity, thus we now know that the order of \kbd{f} is exactly 77, hence the class number is a multiple of 77. But how can we be sure that it is exactly 77 and not a proper multiple? Well, type \bprog sqrt(10007)/Pi * prodeuler(p=2,500, 1./(1 - kronecker(-10007,p)/p)) @eprog\noindent This is nothing else than an approximation to the Dirichlet class number formula. The function \kbd{kronecker} is the Kronecker symbol, in this case simply the Legendre symbol. Note also that we have written \kbd{1./(1 - \dots)} with a dot after the first 1. Otherwise, PARI may want to compute the whole thing as a rational number, which would be terribly long and useless. In fact PARI does no such thing in this particular case (\kbd{prodeuler} is always computed as a real number), but you never know. Better safe than sorry! We find 77.77, pretty close to 77, so things seem in order. Explicit bounds on the prime limit to be used in the Euler product can be given which make the above reasoning rigorous. Let us try the same thing with $D=-3299$. \kbd{qfbclassno} and the Euler product convince us that the class number must be 27. However, we get stuck when we try to prove this in the simple-minded way above. Indeed, we type \kbd{f = qfbprimeform(-3299, 3)} (2 is not the norm of a prime ideal but 3 is), and we see that \kbd{f} raised to the power 9 is equal to the identity. This is the case for any other quadratic form we choose. So we suspect that the class group is not cyclic. Indeed, if we list all 9 distinct powers of \kbd{f}, we see that \kbd{qfbprimeform(-3299, 5)} is not on the list, although its cube is as it must. This implies that the class group is probably equal to a product of a cyclic group of order 9 by a cyclic group of order 3. The Euler product plus explicit bounds prove this. Another way to check it is to use the \kbd{quadclassunit} function by typing for example \bprog quadclassunit(-3299) @eprog\noindent Note that this function cheats a little and could still give a wrong answer, even assuming GRH: the forms given could generate a strict subgroup of the class group. If we want to use proven bounds under GRH, we have to type \bprog quadclassunit(-3299,,[1,6]) @eprog\noindent The double comma \kbd{,,} is not a typo, it means we omit an optional second argument. As we want to use the optional \emph{third} argument, we have to indicate to \kbd{gp} we skipped this one. Now, if we believe in GRH, the class group is as we thought (see Chapter 3 for a complete description of this function). Note that using the even more general function \kbd{bnfinit} (which handles general number fields and gives more complicated results), we could \emph{certify} this result, i.e~remove the GRH assumption. Let's do it, type \bprog bnf = bnfinit(x^2 + 3299); bnfcertify(bnf) @eprog A non-zero result (here 1) means that everything is ok. Good, but what did we certify after all? Let's have a look at this \kbd{bnf} (just type it!). Enlightening, isn't it? Recall that the \kbd{init} functions (we've already seen \kbd{ellinit}) store all kind of technical information which you certainly don't care about, but which will be put to good use by higher level functions. That's why \kbd{bnfcertify} could not be used on the output of \kbd{quadclassunit}: it needs much more data. To extract sensible information from such complicated objects, you must use one of the many \emph{member functions} (remember: \kbd{?.} to get a complete list). In this case \kbd{bnf.clgp} which extracts the class group structure. This is much better. Type \kbd{\%.no} to check that this leading 27 is indeed what we think it is and not some stupid technical parameter. Note that \kbd{bnf.clgp.no} would work just as well, or even \kbd{bnf.no}! As a last check, we can request a relative equation for the Hilbert class field of $\Q(\sqrt{-3299})$: type \kbd{quadhilbert(-3299)}. It is indeed of degree 27 so everything fits together. \medskip % Working in real quadratic fields instead of complex ones, i.e.~with $D>0$, is not very different. The same \kbd{quadgen} function is used to create elements. Ideals are again represented by binary quadratic forms $(a,b,c)$, this time indefinite. However, the Archimedean valuations of the number field start to come into play, hence in fact quadratic forms with positive discriminant will be represented as a quadruplet $(a,b,c,d)$ where the quadratic form itself is $ax^2+bxy+cy^2$ with $a$, $b$ and $c$ integral, and $d\in \R$ is a ``distance'' component, as defined by Shanks and Lenstra. To create such forms, one uses the same function as for definite ones, but you can add a fourth (optional) argument to initialize the distance: \kbd{q = Qfb($a$, $b$, $c$, $d$)}. If the discriminant of \kbd{poldisc(q)} is negative, $d$ is silently discarded. If you omit it, this component is set to \kbd{0.} (i.e.~a real zero to the current precision). Again these forms can be multiplied, divided, powered, and they can be reduced using \kbd{qfbred}. This function is in fact a succession of elementary reduction steps corresponding essentially to a continued fraction expansion, and a single one of these steps can be achieved by adding an (optional) flag to the arguments of \kbd{qfbred}. Since handling the fourth component $d$ usually involves computing expensive logarithms, the same flag may be used to ignore the fourth component. Finally, it is sometimes useful to operate on forms of positive discriminant without performing any reduction (this is useless in the negative case), the functions \kbd{qfbcompraw} and \kbd{qfbpowraw} do exactly that. Again, the function \kbd{qfbprimeform} gives a prime form, but the form which is given corresponds to an ideal of prime norm which is usually not reduced. If desired, it can be reduced using \kbd{qfbred}. Finally, you still have at your disposal the function \kbd{qfbclassno} which gives the class number (this time \emph{guaranteed} correct), \kbd{quadregulator} which gives the regulator, and the much more sophisticated \kbd{quadclassunit} giving the class group's structure and its generators, as well as the regulator. The \kbd{qfbclassno} and \kbd{quadregulator} functions use an algorithm which is $O(\sqrt D)$, hence become very slow for discriminants of more than 10 digits. \kbd{quadclassunit} can be used on a much larger range. Let us see examples of all this at work and learn some little known number theory at the same time. First of all, type \bprog d = 3 * 3299; qfbclassno(d) @eprog\noindent We see that the class number is 3. (We know in advance that it must be divisible by 3 from the \kbd{d = -3299} case above and Scholz's mirror theorem.) Let us create a form by typing \bprog f = qfbred(qfbprimeform(d,2), 2) @eprog\noindent (the last 2 tells \kbd{qfbred} to ignore the Archimedean component). This gives us a prime ideal of norm equal to 2. Is this ideal principal? Well, one way to check this, which is not the most efficient but will suffice for now, is to look at the complete cycle of reduced forms equivalent to \kbd{f}. Type \bprog g = f; for(i=1,20, g = qfbred(g, 3); print(g)) @eprog\noindent (this time the 3 means to do a single reduction step, still not using Shanks's distance). We see that we come back to the form \kbd{f} without having the principal form (starting with $\pm1$) in the cycle, so the ideal corresponding to \kbd{f} is not principal. Since the class number is equal to 3, we know however that \kbd{f\pow 3} will be a principal ideal $\alpha\Z_K$. How do we find $\alpha$? For this, type \bprog f3 = qfbpowraw(f, 3) @eprog This computes the cube of \kbd{f}, without reducing it. Hence it corresponds to an ideal of norm equal to $8=2^3$, so we already know that the norm of $\alpha$ is equal to $\pm8$. We need more information, and this will be given by the fourth component of the form. Reduce your form until you reach the unit form (you will have to type \kbd{qfbred(\%,~1)} exactly 6 times), then extract the Archimedean component, say $c$. By definition of this distance, we know that $${\alpha\over{\sigma(\alpha)}}=\pm e^{2c},$$ where $\sigma$ denotes real conjugation in our quadratic field. This can be automated: \bprog q = f3; while(abs(component(q,1)) != 1, print(q); q = qfbred(q, 1)) c = component(q,4); @eprog\noindent Thus, if we type \bprog a = sqrt(8 * exp(2*c)) sa = 8 / a @eprog\noindent we know that up to sign, \kbd{a} and \kbd{sa} are numerical approximations of $\alpha$ and $\sigma(\alpha)$. Of course, $\alpha$ can always be chosen to be positive, and a quick numerical check shows that the difference of \kbd{a} and \kbd{sa} is close to an integer, and not the sum, so that in fact the norm of $\alpha$ is equal to $-8$ and the numerical approximation to $\sigma(\alpha)$ is \kbd{$-$sa}. Thus we type \bprog p = x^2 - round(a-sa)*x - 8 @eprog\noindent and this is the characteristic polynomial of $\alpha$. We can check that the discriminant of this polynomial is a square multiple of \kbd{d}, so $\alpha$ is indeed in our field. More precisely, solving for $\alpha$ and using the numerical approximation that we have to resolve the sign ambiguity in the square root, we get explicitly $\alpha=(15221+153\sqrt d)/2$. Note that this can also be done automatically using the functions \kbd{polred} and \kbd{modreverse}, as we will see later in the general number field case, or by solving a system of 2 linear equations in 2 variables. (Exercise: now that we have $\alpha$, check that it is indeed a generator of the ideal corresponding to the form \kbd{f3}.) \medskip Let us now play a little with cycles. Type \bprog D = 10^7 + 1 quadclassunit(D) @eprog\noindent We get as a result a 5-component vector, which tells us that (under GRH) the class number is equal to 1, and the regulator is approximately equal to $2641.5$. You may certify this with \bprog bnf = bnfinit(x^2 - D, 1); \\ @com insist on finding fundamental unit bnfcertify(bnf); @eprog\noindent although it's a little inefficient. Indeed \kbd{bnfcertify} needs the fundamental unit which is so large that \kbd{bnfinit} will have a hard time computing it: it needs about $R/\log(10)\approx 1147$ digits of precision! (So that it would have given up had we not inserted the flag $1$.) See \kbd{bnf.fu}. On the other hand, you can try \kbd{quadunit(D)}. Impressive, isn't it? (You can check that its logarithm is indeed equal to the regulator.) Now just as an example, let's assume that we want the regulator to 500 decimals, say. (Without cheating and computing the fundamental unit exactly first!) I claim that simply from the crude approximation above, this can be computed with no effort. This time, we want to start with the unit form. Type: \bprog u = qfbred(qfbprimeform(D, 1), 2) @eprog\noindent We use the function \kbd{qfbred} with no distance since we want the initial distance to be equal to~0. Now type \kbd{f = qfbred(u, 1)}. This is the first form encountered along the principal cycle. For the moment, keep the precision low, for example the initial default precision. The distance from the identity of \kbd{f} is around 4.253. Very crudely, since we want a distance of $2641.5$, this should be encountered approximately at $2641.5/4.253=621$ times the distance of \kbd{f}. Hence, as a first try, we type \kbd{f\pow 621}. Oops, we overshot, since the distance is now $3173.02$. Now we can refine our initial estimate and believe that we should be close to the correct distance if we raise \kbd{f} to the power $621*2641.5/3173$ which is close to $517$. Now if we compute \kbd{f\pow 517} we hit the principal form right on the dot. Note that this is not a lucky accident: we will always land extremely close to the correct target using this method, and usually at most one reduction correction step is necessary. Of course, only the distance component can tell us where we are along the cycle. Up to now, we have only worked to low precision. The goal was to obtain this unknown integer $517$. Note that this number has absolutely no mathematical significance: indeed the notion of reduction of a form with positive discriminant is not well defined since there are usually many reduced forms equivalent to a given form. However, when PARI makes its computations, the specific order and reductions that it performs are dictated entirely by the coefficients of the quadratic form itself, and not by the distance component, hence the precision used has no effect. Hence we now start again by setting the precision to (for example) 500, we retype the definition of \kbd{u} (why is this necessary?), and then \kbd{qfbred(u, 1)\pow 517}. Of course we know in advance that we land on the unit form, and the fourth component gives us the regulator to 500 decimal places with no effort at all. In a similar way, we could obtain the so-called \emph{compact representation} of the fundamental unit itself, or $p$-adic regulators. I leave this as exercises for the interested reader. You can try the \kbd{quadhilbert} function on that field but, since the class number is $1$, the result won't be that exciting. If you try it on our preceding example ($3*3299$) it should take about 2 seconds. \medskip Time for a coffee break? \section{Working in General Number Fields} \subsec{Elements} The situation here is of course more difficult. First of all, remembering what we did with elliptic curves, we need to initialize data linked to our base number field, with something more serious than \kbd{quadgen}. For example assume that we want to work in the number field $K$ defined by one of the roots of the equation $x^4+24x^2+585x+1791=0$. This is done by typing \bprog T = x^4 + 24*x^2 + 585*x + 1791 nf = nfinit(T) @eprog\noindent We get an \kbd{nf} structure but, thanks to member functions, we do not need to know anything about it. If you type \kbd{nf.pol}, you will get the polynomial \kbd{T} which you just input. \kbd{nf.sign} yields the signature $(r_1,r_2)$ of the field, \kbd{nf.disc} the field discriminant, \kbd{nf.zk} an integral basis, etc\dots. The integral basis is expressed in terms of a generic root \kbd{x} of \kbd{T} and we notice it's very far from being a power integral basis, which is a little strange for such a small field. Hum, let's check that: \kbd{poldisc(T)}? Ooops, small wonder we had such denominators, the index of the power order $\Z[x]/(T)$ in the maximal order $\Z_K$ is, well, \kbd{nf.index}. Note that this is also given by \bprog sqrtint(poldisc(nf.pol) / nf.disc) @eprog\noindent Anyway, that's $3087$, we don't want to work with such a badly skewed polynomial! So, we type \bprog P = polred(T) @eprog\noindent We see from the third component that the polynomial $x^4-x^3-21x^2+17x+133$ defines the same field with much smaller coefficients, so type \bprog A = P[3] @eprog\noindent The \kbd{polred} function usually gives a simpler polynomial, and also sometimes some information on the existence of subfields. For example in this case, the second component of \kbd{polred} tells us that the field defined by $x^2-x+1=0$, i.e.~the field generated by the cube roots of unity, is a subfield of~$K$. Note this is incidental information and that the list of subfields found in this way is usually far from complete. To get the complete list, one uses \kbd{nfsubfields} (we shall do that later on). Type \kbd{poldisc(A)}, this is much better, but maybe not optimal yet (the index is still $7$). Type \kbd{polredabs(A)} (the \kbd{abs} stands for absolute). Since it seems that we won't get anything better, we'll stick with \kbd{A} (note however that \kbd{polredabs} finds a smallest generating polynomial with respect to a bizarre norm which ensures that the index will be small, but not necessarily minimal). In fact, had you typed \kbd{nfinit(T, 3)}, \kbd{nfinit} would first have tried to find a good polynomial defining the same field (i.e.~one with small index) before proceeding. It's not too late, let's redefine our number field: \bprog NF = nfinit(nf, 3) @eprog\noindent The output is a two-component vector. The first component is the new \kbd{nf}: type \bprog nf = NF[1]; @eprog\noindent If you type \kbd{nf.pol}, you notice that \kbd{gp} indeed replaced your bad polynomial \kbd{T} by a much better one, which happens to be \kbd{A}. (Small wonder, \kbd{nfinit} internally called \kbd{polredabs}.) The second component enables you to switch conveniently to our new polynomial. Namely, call $\theta$ a root of our initial polynomial \kbd{T}, and $\alpha$ a root of the one that \kbd{polred} has found, namely \kbd{A}. These are algebraic numbers, and as already mentioned are represented as polmods. For example, in our special case $\theta$ and $\alpha$ are equal to the polmods \bprog THETA = Mod(x, x^4 + 24*x^2 + 585*x + 1791) ALPHA = Mod(x, x^4 - x^3 - 21*x^2 + 17*x + 133) @eprog\noindent respectively. Here we are considering only the algebraic aspect, and hence ignore completely \emph{which} root $\theta$ or $\alpha$ is chosen. Now you may have a number of elements of your number field which are expressed as polmods with respect to your old polynomial, i.e.~as polynomials in $\theta$. Since we are now going to work with $\alpha$ instead, it is necessary to convert these numbers to a representation using $\alpha$. This is what the second component of \kbd{NF} is for: type \kbd{C = NF[2]}, you get \bprog Mod(-10/7*x^3 + 43/7*x^2 + 73/7*x - 64, x^4 - x^3 - 21*x^2 + 17*x + 133) @eprog\noindent meaning that $\theta = -\dfrac{10}{7}\alpha^3+\dfrac{43}{7}\alpha^2+\dfrac{73}{7}\alpha-64$, and hence the conversion from a polynomial in $\theta$ to one in $\alpha$ is easy, using \kbd{subst}. (We could get this polynomial from \kbd{polred} as well, try \kbd{polred(T, 2)}.) If we want the reverse, i.e.~to go back from a representation in $\alpha$ to a representation in $\theta$, we use the function \kbd{modreverse} on this polmod \kbd{C}. Try it. The result has a big denominator (1029) essentially because our initial polynomial \kbd{T} was so bad. By the way, to get that 1029, you should type \kbd{denominator(content(C))}. Trying \kbd{denominator} by itself would not work since the denominator of a polynomial is defined to be 1 (and its numerator is itself). The reason for this is that we think of a polynomial as a special case of a rational function.\smallskip From now on, we forget about \kbd{T}, and use only the polynomial \kbd{A} defining $\alpha$, and the components of the vector \kbd{nf} which gives information on our number field $K$. Type \bprog u = Mod(x^3 - 5*x^2 - 8*x + 56, A) / 7 @eprog\noindent This is an element in $K$. There are three equivalent representations for number field elements: polmod, polynomial, and column vector giving a decomposition in the integral basis \kbd{nf.zk} (\emph{not} on the power basis $(1,x,x^2,\dots)$). All three are equally valid when the number field is understood (is given as first argument to the function). You will be able to use any one of them as long as the function you call requires an \kbd{nf} argument as well. However, most PARI functions will return elements as column vectors. It's an important feature of number theoretic functions that, although they may have a preferred format for input, they will accept a wealth of other different formats. We already saw this for \kbd{nfinit} which accepts either a polynomial or an \kbd{nf}. It will be true for ideals, congruence subgroups, etc. Let's stick with elements for the time being. How does one go from one representation to the other? Between polynomials and polmods, it's easy: \kbd{lift} and \kbd{Mod} will do the job. Next, from polmods/polynomials to column vectors: type \kbd{v = nfalgtobasis(nf, u)}. So $\kbd{u} = \alpha^3- \alpha^2 - \alpha + 8$, right? Wrong! The coordinates of \kbd{u} are given with respect to the \emph{integral basis}, not the power basis $(1,\alpha,\alpha^2,\alpha^3)$ (and they don't coincide, type \kbd{nf.zk} if you forgot what the integral basis looked like). As a polynomial in $\alpha$, we simply have $\kbd{u} = {1\over7}(\alpha^3 - 5\alpha^2-8\alpha+56)$, which is trivially deduced from the original polmod representation! Of course \kbd{v = nfalgtobasis(nf, lift(u))} would work equally well. Indeed we don't need the polmod information since \kbd{nf} already provides the defining polynomial. To go back to polmod representation, use \kbd{nfbasistoalg(nf, v)}. Notice that \kbd{u} is an algebraic integer since \kbd{v} has integer coordinates (try \kbd{denominator(v) == 1}, which is of course overkill here, but not so in a program). Let's try this out. We may for instance compute \kbd{u\pow 3}. Try it. Or, we can type \kbd{1/u}. Better yet, if we want to know the norm from $K$ to $\Q$ of \kbd{u}, we type \kbd{norm(u)} (what else?); \kbd{trace(u)} works as well. Notice that none of this would work on polynomials or column vectors since you don't have the opportunity to supply \kbd{nf}! But we could use \kbd{nfeltpow(nf,u,3)}, \kbd{nfeltdiv(nf,1,u)} (or \kbd{nfeltpow(nf,u,-1)}) which would work whatever representation was chosen. Of course, there is also an \kbd{nfeltnorm} function (and \kbd{nfelttrace} as well). You can also consider $(u)$ as a principal ideal, and just type \bprog idealnorm(nf,u) @eprog\noindent Of course, in this way, we lose the \emph{sign} information. We will talk about ideals later on. If we want all the symmetric functions of \kbd{u} and not only the norm, we type \kbd{charpoly(u)}. Note that this gives the characteristic polynomial of \kbd{u}, and not in general the minimal polynomial. \misctitle{Exercise} How does one get the minimal polynomial from this? Find a simpler expression for \kbd{u}. \smallskip Now let's work on the field itself. The \kbd{nfinit} command already gave us some information. The field is totally complex (its signature \kbd{nf.sign} is $[0,2]$), its discriminant \kbd{nf.disc} is $18981$ and \kbd{nf.zk} is an integral basis. The Galois group of its Galois closure can be obtained by typing \kbd{polgalois(A)}. The answer (\kbd{[8,-1,1]}, or \kbd{[8,-1,1,"D(4)"]} if the \kbd{galdata} package is installed) shows that it is equal to $D_4$, the dihedral group with 8 elements, i.e.~the group of symmetries of a square. This implies that the field is ``partially Galois'', i.e.~that there exists at least one non-trivial field isomorphism which fixes $K$, exactly one in this case. Type \kbd{nfgaloisconj(nf)}. The result tells us that, apart from the trivial automorphism, the map $$\alpha \mapsto {1\over7}(-\alpha^3+5\alpha^2+\alpha-49)$$ is the only field automorphism. \bprog nfgaloisconj(nf); s = Mod(%[2], A) charpoly(s) @eprog\noindent and we obtain \kbd{A} once again. Let us check that \kbd{s} is of order 2: \kbd{subst(lift(s), x, s)}. It is. We may express it as a matrix: \bprog w = Vec( matid(4) ) \\@com canonical basis v = vector(#w, i, nfgaloisapply(nf, s, w[i])) M = Mat(v) @eprog\noindent The vector \kbd{v} contains the images of the integral basis elements (as column vectors). The last statement concatenates them into a square matrix. So, \kbd{M} gives the action of \kbd{s} on the integral basis. Let's check \kbd{M\pow2}. That's the identity all right. The fixed field of this automorphism is going to be the only non-trivial subfield of $K$. I seem to recall that \kbd{polred} told us this was the third cyclotomic field. Let's check this: type \kbd{nfsubfields(nf)}. Indeed, there's a quadratic subfield, but it's given by \kbd{T = x\pow 2 + 22*x + 133 } and I don't recognize it. But \kbd{nfisisom(T, polcyclo(3))} indeed tells us that the fields $\Q[x]/(T)$ and $\Q[x]/(x^2+x+1)$ are isomorphic. (In fact, \kbd{polred(T)} would tell us the same, but does not correspond to a foolproof test: \kbd{polred} could have returned some other polynomials.) We may also check that \kbd{k = matker(M-1)} is two-dimensional, then \kbd{z = nfbasistoalg(nf, k[,2])} generates the quadratic subfield. Notice that 1, \kbd{z} and \kbd{u} are $\Q$-linearly dependent, and in fact $\Z$-linearly as well. Exercise: how would you check these two assertions in general? (Answer: \kbd{concat}, then respectively \kbd{matrank} or \kbd{matkerint} (or \kbd{qflll})). \kbd{z = charpoly(z)}, \kbd{z = gcd(z,z')} and \kbd{polred(z)} tell us that we found back the same subfield again (as we ought to!). Final check: type \kbd{nfrootsof1(nf)}. Again we find that $K$ contains a cube root of unity, since the torsion subgroup of its unit group has order 6. The given generator happens to be equal to \kbd{u}. \misctitle{Additional comment} (you are no longer supposed to skip this, but do as you wish): Before working with ideals, let us note one more thing. The main part of the work of \kbd{polred} or \kbd{nfinit}$(T)$ is to compute an integral basis, i.e.~a $\Z$-basis of the maximal order $\Z_K$ of $K$. This implies factoring the discriminant of the polynomial $T$, which is often not feasible. The situation may be improved in many ways: 1) First, it is often the case that our number field is of quite a special type. For example, one may know in advance some prime divisors of the discriminant. Hence we can ``help'' PARI by giving it that information. More precisely, we can use the function \kbd{addprimes} to inform PARI to keep on eye for these prime numbers. Do it only for big primes ! (Say, larger than \kbd{primelimit}.) 2) The second way in which the situation may be improved is that often we do not need the complete information on the maximal order, but only require that the order be $p$-maximal for a certain number of primes $p$ --- but then, we may not be able to use functions which require a genuine \kbd{nf}. The function \kbd{nfbasis} specifically computes the integral basis and is not much quicker than \kbd{nfinit} so is not very useful in its standard use. But we can optionnally provide a list of primes: this returns a basis of an order which is $p$-maximal at the given primes. For example coming back to our initial polynomial $T$, the discriminant of the polynomial is $3^7\cdot7^6\cdot19\cdot37$. If we only want a $7$-maximal order, we simply type \bprog nfbasis([T, [7]]) @eprog\noindent Of course, \kbd{nfbasis([T, [2,3,5,7]])} would return an order which is maximal at $2,3,5,7$. A variant offers a nice generalization: \bprog nfbasis([T, 10^5]) @eprog\noindent will return an order which is maximal at all primes less than $10^5$. 3) Building on the previous points, \emph{if} the field discriminant is $y$-smooth (never mind the polynomial discriminant), up to a few big primes known to \kbd{addprimes}, then \kbd{bas = nfbasis(T, y)} returns a basis for the maximal order! We can then input the resulting basis to \kbd{nfinit}, as \kbd{nfinit([T, bas])}. Better: the $[T, \var{listP}]$ format can be directly used with nfinit, where \var{listP} specifies a finite list of primes in one of the above ways (explicit list or primes up to some bound), and the result can be unconditionnally certified, independently of the \var{listP} parameter: \bprog T = polcompositum(x^7-2, polcyclo(5))[1]; K = nfinit( [T, [2,5,7]] ); nfcertify(K) @eprog\noindent The output is a list of composite integers whose complete factorization must be computed in order to certify the result (which may be very hard, hence is not done on the spot). When the list is empty, as here, the result is unconditionnal \kbd{nfcertify(nf)} \subsec{Ideals} We now want to work with ideals and not only with elements. An ideal can be represented in many different ways. First, an element of the field (in any of the various guises seen above) will be considered as a principal ideal. Then the standard representation is a square matrix giving the Hermite Normal Form (HNF) of a $\Z$-basis of the ideal expressed on the integral basis \kbd{nf.zk}. Standard means that most ideal related functions will use this representation for their output. Prime ideals can be represented in a special form as well (see \kbd{idealprimedec}) and all ideal-related functions will accept them. On the other hand, the function \kbd{idealtwoelt} can be used to find a two-element $\Z_K$-basis of a given ideal (as $a\Z_K + b\Z_K$, where $a$ and $b$ belong to $K$), but this is \emph{not} a valid representation for an ideal under \kbd{gp}, and most functions will choke on it (or worse, take it for something else and output a meaningless result). To be able to use such an ideal, you will first have to convert it to HNF form. Whereas it's very easy to go to HNF form (use \kbd{idealhnf(nf,id)} for valid ideals, or \kbd{idealhnf(nf,a,b)} for a two-element representation as above), it's a much more complicated problem to check whether an ideal is principal and find a generator. In fact an \kbd{nf} does not contain enough data for this particular task. We'll need a Buchmann Number Field, or \kbd{bnf}, for that. In particular, we need the class group and fundamental units, at least in some approximate form. More on this later (which will trivialize the end of the present section).\smallskip Let us keep our number field $K$ as above and its \kbd{nf} structure. Type \bprog P = idealprimedec(nf,7) @eprog\noindent This gives the decomposition of the prime number 7 into prime ideals. We have chosen 7 because it divides \kbd{nf.index} (in fact, is equal to it), hence is the most difficult case to treat. The result is a vector with 4 components, showing that 7 is totally split in the field $K$ into prime ideals of norm 7 (you can check: \kbd{idealnorm(nf,P[1])}). Let us take one of these ideals, say the first, so type \bprog pr = P[1] @eprog We obtain its inertia and residue degree as \kbd{pr.e} and \kbd{pr.f}, and its two generators as \kbd{pr.gen}. One of them is $\kbd{pr.p} = 7$, and the other is guaranteed to have valuation $1$ at \kbd{pr}. What is the Hermite Normal Form of this ideal? No problem: \bprog idealhnf(nf,pr) @eprog\noindent and we have the desired HNF. Let's now perform ideal operations. For example type \bprog idealmul(nf, pr, idealmul(nf, pr,pr)) @eprog\noindent or more simply \bprog pr3 = idealpow(nf, pr,3) @eprog\noindent to get the cube of the ideal \kbd{pr}. Since the norm of this ideal is equal to $343=7^3$, to check that it is really the cube of \kbd{pr} and not of other ideals above 7, we can type \bprog for(i=1, #P, print( idealval(nf, pr3, P[i]) )) @eprog\noindent and we see that the valuation at \kbd{pr} is equal to 3, while the others are equal to zero. We could see this as well from \kbd{idealfactor(nf, pr3)}. Let us now work in the class group ``by hand'' (we shall see simpler ways later). We shall work with \emph{extended ideals}: an extended ideal is a pair \kbd{[A, t]}, where $A$ is an ordinary ideal as above, and $t$ a number field element; this pair represents the ideal $(t) A$. \bprog id3 = [pr3, 1] r0 = idealred(nf, id3) @eprog\noindent The input \kbd{id3} is an extended ideal: pr3 together with 1 (trivial factorization). The new extended ideal \kbd{r0} is equal to the old one, in the sense that the products $(t)A$ are the same. It contains a ``reduced'' ideal equivalent to \kbd{pr3} (modulo the principal ideals), and a generator of the principal ideal that was factored out. Now, just for fun type \bprog r = r0; for(i=1,3, r = idealred(nf,r, [1,5]); print(r)) @eprog\noindent The ideals in the third \kbd{r} and initial \kbd{r0} are equal, say $(t) A = (t_0) A$: this means we have found a unit $(t_0/t)$ in our field, and it is easy to extract this unit given the extended component: \bprog t0 = r0[2]; t = r[2]; u = nfeltdiv(nf, t0, t) u = nfbasistoalg(nf, u) @eprog\noindent The last line recovers the unit as an algebraic number. Type \bprog ch = charpoly(u) @eprog\noindent and we obtain the characteristic polynomial \kbd{ch} of $u$ again. (Whose constant coefficient is $1$, hence $u$ is indeed a unit.) There is of course no reason for $u$ to be a fundamental unit. Let us see if it is a square. Type \bprog F = factor(subst(ch, x, x^2)) @eprog\noindent We see that \kbd{ch(x\pow2)} is a product of 2 polynomials of degree 4, hence $u$ is a square. (Why?) We now want to find its square root. A simple method is as follows: \bprog NF = subst(nf,x,y); r = F[1,1] % (x^2 - nfbasistoalg(NF, u)) @eprog\noindent to find the remainder of the characteristic polynomial of \kbd{u2} divided by \kbd{x\pow 2 - $u$}. This is a polynomial of degree 1 in \kbd{x}, with polmod coefficients, and we know that \kbd{u2}, being a root of both polynomials, is the root of \kbd{r}, hence can be obtained by typing \bprog u2 = -polcoeff(r,0) / polcoeff(r,1) @eprog\noindent There is an important technicality in the above: why did we need to substitute \kbd{NF} to \kbd{nf}? The reason is that data related to \kbd{nf} is given in terms of the variable \kbd{x}, seen modulo \kbd{nf.pol}; but we need \kbd{x} as a free variable for our polynomial divisions. Hence the substitution of \kbd{x} by \kbd{y} in our \kbd{nf} data. The most natural method is to try directly \bprog nffactor(nf, y^2 - u) @eprog\noindent Except that this won't work for the same technical reason as above: the main variable of the polynomial to be factored must have \emph{higher} priority than the number field variable. This won't be possible here since \kbd{nf} was defined using the variable \kbd{x} which has the highest possible priority. So we need to substitute variables around: \bprog nffactor(NF, x^2 - nfbasistoalg(NF, subst(lift(u),x,y))) @eprog\noindent (Of course, with better planning, we would just have defined \kbd{nf} in terms of the \kbd{'y} variable, to avoid all these substitutions.) \smallskip A much simpler approach is to consider the above as instances of a \emph{discrete logarithm} problem, where we want to express some elements an abelian group (of finite type) in terms of explicitly given generators, and transfer all computations from abstract groups like $\text{Cl}(K)$ and $\Z_K^*$ to products of simpler groups like $\Z^n$ or $\Z/d\Z$. We shall do exactly that in the next section. Before that, let us mention another famous (but in fact, simpler) \emph{discrete logarithm} problem, namely the one associated to the invertible elements modulo an ideal: $(\Z_K / I)^*$. Just use \kbd{idealstar} (this is an \kbd{init} function) and \kbd{ideallog}. Many more functions on ideals are available. We mention here the complete list, referring to Chapter 3 for detailed explanations: \kbd{idealadd}, \kbd{idealaddtoone}, \kbd{idealappr}, \kbd{idealchinese}, \kbd{idealcoprime}, \kbd{idealdiv}, \kbd{idealfactor}, \kbd{idealhnf}, \kbd{idealintersect}, \kbd{idealinv}, \kbd{ideallist}, \kbd{ideallog}, \kbd{idealmin}, \kbd{idealmul}, \kbd{idealnorm}, \kbd{idealpow}, \kbd{idealprimedec}, \kbd{idealred}, \kbd{idealstar}, \kbd{idealtwoelt}, \kbd{idealval}, \kbd{nfisideal}. We suggest you play with these to get a feel for the algebraic number theory package. Remember that when a matrix (usually in HNF) is output, it is always a $\Z$-basis of the result expressed on the \emph{integral basis} \kbd{nf.zk} of the number field, which is usually \emph{not} a power basis. \subsec{Class groups and units, \kbd{bnf}} Apart from the above functions you have at your disposal the powerful function \kbd{bnfinit}, which initializes a \kbd{bnf} structure, i.e.~a number field with all its invariants (including class group and units), and enough technical data to solve discrete logarithm problems in the class and unit groups. First type \kbd{setrand(1)}: this resets the random seed (to make sure we and you get the exact same results). Now type \bprog bnf = bnfinit(NF); @eprog\noindent where \kbd{NF} is the same number field as before. You do not want to see the output clutter a number of screens so don't forget the semi-colon. (Well if you insist, it is about three screenful in this case, but may require several Megabytes for larger degrees.) Note that \kbd{NF} is now expressed in terms of the variable \kbd{y}, to avoid later problems with variable priorities. A word of warning: both the \kbd{bnf} and all results obtained from it are \emph{conditional} on a Riemann Hypothesis at this point; the \kbd{bnf} must be certified before the following statements become actual theorems. \smallskip Member functions are still available for \kbd{bnf} structures. So, let's try them: \kbd{bnf.pol} gives \kbd{A}, \kbd{bnf.sign}, \kbd{bnf.disc}, \kbd{bnf.zk}, ok nothing really exciting. In fact, an \kbd{nf} is included in the \kbd{bnf} structure: \kbd{bnf.nf} should be identical to \kbd{NF}. Thus, all functions which took an \kbd{nf} as first argument, will equally accept a \kbd{bnf} (and a \kbd{bnr} as well which contains even more data). Anyway, new members are available now: \kbd{bnf.no} tells us the class number is 4, \kbd{bnf.cyc} that it is cyclic (of order 4 but that we already knew), \kbd{bnf.gen} that it is generated by the ideal \kbd{g = bnf.gen[1]}. If you \kbd{idealfactor(bnf, g)}, you recognize \kbd{P[2]}. (You may also play in the other direction with \kbd{idealhnf}.) The regulator \kbd{bnf.reg} is equal to $3.794\dots$. \kbd{bnf.tu} tells us that the roots of unity in $K$ are exactly the sixth roots of 1 and gives a primitive root $\zeta = {1\over7}(\alpha^3 - 5\alpha^2 - 8\alpha + 56)$, which we have seen already. Finally \kbd{bnf.fu} gives us a fundamental unit $\epsilon = {1\over7}(\alpha^3 - 5\alpha^2 - \alpha + 28)$, which must be linked to the units \kbd{u} and \kbd{u2} found above since the unit rank is~1. To find these relations, type \bprog bnfisunit(bnf, u) bnfisunit(bnf, u2) @eprog\noindent Lo and behold, \kbd{u = $\zeta^2\epsilon^2$} and \kbd{u2 = $\zeta^{4}\epsilon^1$}. \misctitle{Note} Since the fundamental unit obtained depends on the random seed, you could have obtained another unit than $\epsilon$, had you not reset the random seed before the computation. This was the purpose of the initial \kbd{setrand} instruction, which was otherwise unnecessary.\medskip We are now ready to perform operations in the class group. First and foremost, let us certify the result: type \kbd{bnfcertify(bnf)}. The output is \kbd{1} if all went well; in fact no other output is possible, whether the input is correct or not, but you can get an error message (or in exceedingly rare cases an infinite loop) if it is incorrect. It means that we now know the class group and fundamental units unconditionally (no more GRH then!). In this case, the certification process takes a very short time, and you might wonder why it is not built in as a final check in the \kbd{bnfinit} function. The answer is that as the regulator gets bigger this process gets increasingly difficult, and becomes soon impractical, while \kbd{bnfinit} still happily spits out results. So it makes sense to dissociate the two: you can always check afterwards, if the result is interesting enough. Looking at the tentative regulator, you know in advance whether the certification can possibly succeed: if \kbd{bnf.reg} is large, don't waste your time. Now that we feel safe about the \kbd{bnf} output, let's do some real work. For example, let us take again our prime ideal \kbd{pr} above 7. Since we know that the class group is of order 4, we deduce that \kbd{pr} raised to the fourth power must be principal. Type \bprog pr4 = idealpow(nf, pr, 4) v = bnfisprincipal(bnf, pr4) @eprog\noindent The first component gives the factorization of the ideal in the class group. Here, \kbd{[0]} means that it is up to equivalence equal to the 0-th power of the generator \kbd{g} given in \kbd{bnf.gen}, in other words that it is a principal ideal. The second component gives us the algebraic number $\alpha$ such that $\kbd{pr4}=\alpha\Z_K$, $\alpha$ being as usual expressed on the integral basis. Type \kbd{alpha = v[2]}. Let us check that the result is correct: first, type \kbd{idealnorm(bnf, alpha)}. (Note that we can use a \kbd{bnf} with all the \kbd{nf} functions; but not the other way round, of course.) It is indeed equal to $7^4 = 2401$, which is the norm of \kbd{pr4}. This is only a first check. The complete check is obtained by computing the HNF of the principal ideal generated by \kbd{alpha}. To do this, type \kbd{idealhnf(bnf, alpha) == pr4}. Since the equality is true, \kbd{alpha} is correct (not that there was any doubt!). But \kbd{bnfisprincipal} also gives us information for non-principal ideals. For example, type \bprog v = bnfisprincipal(bnf, pr) @eprog\noindent The component \kbd{v[1]} is now equal to \kbd{[3]}, and tells us that \kbd{pr} is ideal-equivalent to the cube of the generator \kbd{g}. Of course we already knew this since the product of \kbd{P[3]} and \kbd{P[4]} was principal (generated by \kbd{al}), as well as the product of all the \kbd{P[$i$]} (generated by 7), and we noticed that \kbd{P[2]} was equal to \kbd{g}, which has order 4. The second component \kbd{v[2]} gives us $\alpha$ on the integral basis such that $\kbd{pr}=\alpha \kbd{g}^3$. Note that if you \emph{don't} want this $\alpha$, which may be large and whose computation may take some time, you can just add the flag $1$ (see the online help) to the arguments of \kbd{bnfisprincipal}, so that it only returns the position of \kbd{pr} in the class group. \smallskip \subsec{Class field theory, \kbd{bnr}} We now survey quickly some class field theoretic routines. We must first initialize a Buchmann Number Ray, or \kbd{bnr}, structure, associated to a \kbd{bnf} base field and a modulus. Let's keep $K$, and try a finite modulus ${\goth f} = 7\Z_K$. (See the manual for how to include infinite places in the modulus.) Since $K$ will now become a base field over which we want to build relative extensions, the associated \kbd{bnf} needs to have variables of lower priority than the polynomials defining the extensions. Fortunately, we already took care that, but it would have been easy to deal with the problem now (as easy as \kbd{bnf = subst(bnf, x, y)}). Then type \bprog bnr = bnrinit(bnf, 7, 1); bnr.cyc @eprog\noindent tells us the ray class group modulo ${\goth f}$ is isomorphic to $\Z/24\Z \times \Z/6\Z \times \Z/2\Z $. The associated generators are \kbd{bnr.gen}. Just as a \kbd{bnf} contained an \kbd{nf}, a \kbd{bnr} contains a \kbd{bnf} (hence an \kbd{nf}), namely \kbd{bnr.bnf}. Here \kbd{bnr.clgp} refers to the ray class group, while \kbd{bnr.bnf.clgp} refers to the class group. \bprog rnfkummer(bnr,, 2) rnfkummer(bnr,, 3) @eprog\noindent outputs defining polynomials for the $2$ abelian extensions of $K$ of degree $2$ (resp.~$3$), whose conductor is exactly equal to ${\goth f}$ (the modulus used to define \kbd{bnr}). (In the current implementation of \kbd{rnfkummer}, these degrees must be \emph{prime}.) What about other extensions of degree $2$ for instance? \bprog L0= subgrouplist(bnr, [2]) L = subgrouplist(bnr, [2], 1) @eprog\noindent \kbd{L0}, resp.~\kbd{L} is the list of those subgroups of the full ray class group mod $7$, whose index is $2$, and whose conductor is $7$, resp.~arbitrary. (Subgroups are given by a matrix of generators, in terms of \kbd{bnr.gen}.) \kbd{L0} has $2$ elements, associated to the $2$ extensions we already know. \kbd{L} has $7$ elements, the $2$ from \kbd{L0}, and $5$ new ones: \bprog L1 = setminus(Set(L), Set(L0)) @eprog\noindent The conductors are \bprog vector(#L1, i, bnrconductor(bnr, L1[i])) @eprog\noindent among which one sees the identity matrix, i.e. the trivial ideal. (It is \kbd{L1[3]} in my session, maybe not in yours. Take the right one!) Indeed, the class group was cyclic of order $4$ and there exists a unique unramified quadratic extension. We could find it directly by recomputing a \kbd{bnr} with trivial conductor, but we can also use \bprog rnfkummer(bnr, L1[3]) \\ @com pick the subgroup with trivial conductor! @eprog\noindent directly which outputs the (unique by Takagi's theorem) class field associated to the subgroup \kbd{L1[3]}. In fact, it is of the form $K(\sqrt{-\epsilon})$. We can check this directly: \bprog rnfconductor(bnf, x^2 + bnf.fu[1]) @eprog\noindent \subsec{Galois theory over $\Q$} PARI includes a nearly complete set of routines to compute with Galois extensions of $\Q$. We start with a very simple example. Let $\zeta$ a $8$th-root of unity and $K=\Q(\zeta)$. The minimal polynomial of $\zeta$ is the 8$th$ cyclotomic polynomial, namely \kbd{polcyclo(8)} (=$x^4+1$). We issue the command \bprog G = galoisinit(x^4 + 1); @eprog\noindent to compute $G=\text{Gal}(K/\Q)$. The command \kbd{galoisisabelian(G)} returns \kbd{[2,0;0,2]} so $G$ is an abelian group, isomorphic to $(\Z/2\Z)^2$, generated by $\sigma$=\kbd{G.gen[1]} and $\tau$=\kbd{G.gen[2]}. These automorphisms are given by their actions on the roots of $x^4+1$ in a suitable $p$-adic extension. To get the explicit action on $\zeta$, we use \kbd{galoispermtopol(G,G.gen[i])} for $i=1,2$ and get $\sigma(\zeta)=-\zeta$ and $\tau(\zeta)=\zeta^3$. The last non-trivial automorphism is $\sigma\tau$=\kbd{G.gen[1]*G.gen[2]} and we have $\sigma\tau(\zeta)=-\zeta^3$. (At least in my version, yours may return a different set of generators, rename accordingly.) We compute the fixed field of $K$ by the subgroup generated by $\tau$ with \bprog galoisfixedfield(G, G.gen[2], 1) @eprog\noindent and get $x^2 + 2$. Now we want the factorisation of $x^4+1$ over that subfield. Of course, we could use \kbd{nffactor}, but here we have a much simpler option: \kbd{galoisfixedfield(G, G.gen[1], 2)} outputs \bprog [x^2 + 2, Mod(x^3 + x, x^4 + 1), [x^2 - y*x - 1, x^2 + y*x - 1]] @eprog\noindent which means that $x^4+1=(x^2-\alpha\*x-1)(x^2+\alpha\*x-1)$ where $\alpha$ is a root of $x^2+2$, and more precisely, $\alpha=\zeta^3+\zeta$. So we recover the well-known factorisation: $$x^4+1=(x^2-\sqrt{-2}\*x-1)(x^2+\sqrt{-2}\*x-1)$$ For our second example, let us take the field $K$ defined by the polynomial \bprog P = x^18 - 3*x^15 + 115*x^12 + 104*x^9 + 511*x^6 + 196*x^3 + 343; G = galoisinit(P); @eprog\noindent Since \kbd{galoisinit} succeeds, the extension $K/\Q$ is Galois. This time \kbd{galoisisabelian(G)} return $0$, so the extension is not abelian, however we can still put a name on the underlying abstract group. Use \kbd{galoisidentify(G)}, which return $[18, 3]$. By looking at the GAP4 classification we find that $[18, 3]$ is $S_3\times\Z/3\Z$. This time, the subgroups of $G$ are not obvious, fortunately we can ask PARI : \kbd{galoissubgroups(G)}. Let us look for a polynomial $Q$ with the property that $K$ is the splitting field of $Q(x^2)$. For that purpose, let us take $\sigma$=\kbd{G.gen[3]}. We check that \kbd{G.gen[3]\^{}2} is the identity, so $\sigma$ is of order $2$. We now compute the fixed field $K^\sigma$ and the relative factorisation of $P$ over $K^\sigma$: \bprog F = galoisfixedfield(G, G.gen[3], 2); @eprog\noindent So $K$ is a quadratic extension of $K^\sigma$ defined by the polynomial \kbd{R=F[3][1]}. It is well-known that $K$ is also defined by $x^2-D$ where $D$ is the discriminant of $R$ (over $K^\sigma$). To compute $D$ we issue: \bprog D = poldisc(F[3][1]) * Mod(1,subst(F[1],x,y)); @eprog\noindent Note that since \kbd{y} in \kbd{F[3][1]} denotes a root of \kbd{F[1]}, we have to use \kbd{subst(,x,y)}. Now we hope that $D$ generate $K^\sigma$ and compute \kbd{Q=charpoly(D)}. We check that $Q=x^9+270\*x^6+12393\*x^3+19683$ is irreducible with \kbd{polisirreducible(Q)}. (Were it not the case, we would multiply $D$ by a random square.) So $D$ is a generator of $K^\sigma$ and $\sqrt{D}$ is a generator of $K$. The result is that $K$ is the splitting field of $Q(x^2)$. We can check that with \kbd{nfisisom(P,subst(Q,x,x\^{}2))}. \section{Plotting} PARI supports high and low-level graphing functions, on a variety of output devices: a special purpose window under standard graphical environments (the \kbd{X Windows} system, Mac OS X, Microsoft Windows), or a \kbd{PostScript} file ready for the printer. These functions use a multitude of flags, which are mostly power-of-2. To simplify understanding we first give these flags symbolic names. \bprog /* Relative positioning of graphic objects: */ nw = 0; se = 4; relative = 1; sw = 2; ne = 6; /* String positioning: */ /* V */ bottom = 0; /* H */ left = 0; /* Fine tuning */ hgap = 16; vcenter = 4; center = 1; vgap = 32; top = 8; right = 2; @eprog\noindent We also decrease drastically the default precision. \bprog \p 9 @eprog\noindent This is very important, since plotting involves calculation of functions at a huge number of points, and a relative precision of 38 significant digits is an obvious overkill: the output device resolution certainly won't reach $10^{38} \times 10^{38}$ pixels! Start with a simple plot: \bprog ploth(X = -2, 2, sin(X^7)) @eprog\noindent You can see the limitations of the ``straightforward'' mode of plotting: while the first several cycles of \kbd{sin} reach $-1$ and $1$, the cycles which are closer to the left and right border do not. This is understandable, since PARI is calculating $\sin(X^7)$ at many (evenly spaced) points, but these points have no direct relationship to the ``interesting'' points on the graph of this function. No value close enough to the maxima and minima are calculated, which leads to wrong turning points in the graph. To fix this, one may use variable steps which are smaller where the function varies rapidly: \bprog ploth(X = -2, 2, sin(X^7), "Recursive") @eprog\noindent The precision near the edges of the graph is much better now. However, the recursive plotting (named so since PARI subdivides intervals until the graph becomes almost straight) has its own pitfalls. Try \bprog ploth(X = -2, 2, sin(X*7), "Recursive") @eprog\noindent The graph looks correct far away, but it has a straight interval near the origin, and some sharp corners as well. This happens because the graph is symmetric with respect to the origin, thus the middle 3 points calculated during the initial subdivision of $[-2,2]$ are exactly on the same line. To PARI this indicates that no further subdivision is needed, and it plots the graph on this subinterval as a straight line. There are many ways to circumvent this. Say, one can make the right limit 2.1. Or one can ask PARI for an initial subdivision into 16 points instead of default 15: \bprog ploth(X = -2, 2, sin(X*7), "Recursive", 16) @eprog\noindent All these arrangements break the symmetry of the initial subdivision, thus make the problem go away. Eventually PARI will be able to better detect such pathological cases, but currently some manual intervention may be required. The function \kbd{ploth} has some additional enhancements which allow graphing in situations when the calculation of the function takes a lot of time. Let us plot $\zeta({1\over 2} + it)$: \bprog ploth(t = 100, 110, real(zeta(0.5+I*t)), /*empty*/, 1000) @eprog\noindent This can take quite some time. (1000 is close to the default for many plotting devices, we want to specify it explicitly so that the result does not depend on the output device.) Try the recursive plot: \bprog ploth(t = 100, 110, real(zeta(0.5+I*t)), "Recursive") @eprog\noindent It takes approximately the same time. Now try specifying fewer points, but make PARI approximate the data by a smooth curve: \bprog ploth(t = 100, 110, real(zeta(0.5+I*t)), "Splines", 100) @eprog\noindent This takes much less time, and the output is practically the same. How to compare these two outputs? We will see it shortly. Right now let us plot both real and complex parts of $\zeta$ on the same graph: \bprog f(t) = my(z = zeta(0.5+I*t)); [real(z),imag(z)]; ploth(t = 100, 110, f(t), , 1000) @eprog\noindent (Note the use of the temporary variable \kbd{z}; \kbd{my} declares it local to the function's body.) Note how one half of the roots of the real and imaginary parts coincide. Why did we define a function \kbd{f(t)}? To avoid calculation of $\zeta({1\over2} + it)$ twice for the same value of t. Similarly, we can plot parametric graphs: \bprog ploth(t = 100, 110, f(t), "Parametric", 1000) @eprog\noindent In that case (parametric plot of the real and imaginary parts of a complex function), we can also use directly \bprog ploth(t = 100, 110, zeta(0.5+I*t), "Complex", 1000) ploth(t = 100, 110, zeta(0.5+I*t), "Complex|Splines", 100) @eprog If your plotting device supports it, you may ask PARI to show the points in which it calculated your function: \bprog ploth(t = 100, 110, f(t), "Parametric|Splines|Points_too", 100) @eprog As you can see, the points are very dense on the graph. To see some crude graph, one can even decrease the number of points to 30. However, if you decrease the number of points to 20, you can see that the approximation to the graph now misses zero. Using splines, one can create reasonable graphs for larger values of t, say with \bprog ploth(t = 10000, 10004, f(t), "Parametric|Splines|Points_too", 50) @eprog How can we compare two graphs of the same function plotted by different methods? Documentation shows that \kbd{ploth} does not provide any direct method to do so. However, it is possible, and even not very complicated. The solution comes from the other direction. PARI has a power mix of high level plotting function with low level plotting functions, and these functions can be combined together to obtain many different effects. Return back to the graph of $\sin(X^7)$. Suppose we want to create an additional rectangular frame around our graph. No problem! First, all low-level graphing work takes place in some virtual drawing boards (numbered from 0 to 15), called ``rectangles'' (or ``rectwindows''). So we create an empty ``rectangle'' and name it rectangle 2 (any number between 0 and 15 would do): \bprog plotinit(2) plotscale(2, 0,1, 0,1) @eprog This creates a rectwindow whose size exactly fits the size of the output device, and makes the coordinate system inside it go from 0 to 1 (for both $x$ and $y$). Create a rectangular frame along the boundary of this rectangle: \bprog plotmove(2, 0,0) plotbox(2, 1,1) @eprog Suppose we want to draw the graph inside a subrectangle of this with upper and left margins of $0.10$ (so 10\% of the full rectwindow width), and lower and top margins of $0.02$, just to make it more interesting. That makes it an $0.88 \times 0.88$ subrectangle; so we create another rectangle (call it 3) of linear size 0.88 of the size of the initial rectangle and graph the function in there: \bprog plotinit(3, 0.88, 0.88, relative) plotrecth(3, X = -2, 2, sin(X^7), "Recursive") @eprog (nothing is output yet, these commands only fills the virtual drawing boards with PARI graphic objects). Finally, output rectangles 2 and 3 on the same plot, with the required offsets (counted from upper-left corner): \bprog plotdraw([2, 0,0, 3, 0.1,0.02], relative) @eprog \noindent The output misses something comparing to the output of \kbd{ploth}: there are no coordinates of the corners of the internal rectangle. If your output device supports mouse operations (only \kbd{gnuplot} does), you can find coordinates of particular points of the graph, but it is nice to have something printed on a hard copy too. However, it is easy to put $x$- and $y$-limits on the graph. In the coordinate system of the rectangle 2 the corners are $(0.1,0.1)$, $(0.1,0.98)$, $(0.98,0.1)$, $(0.98,0.98)$. We can mark lower $x$-limit by doing \bprog plotmove(2, 0.1,0.1) plotstring(2, "-2.000", left+top+vgap) @eprog\noindent Computing the minimal and maximal $y$-coordinates might be trickier, since in principle we do not know the range in advance (though for $\sin(X^7)$ it is easy to guess!). Fortunately, \kbd{plotrecth} returns the $x$- and $y$-limits. Here is the complete program: \bprog plotinit(3, 0.88, 0.88, relative) lims = plotrecth(3, X = -2, 2, sin(X^7), "Recursive") \p 3 \\ @com $3$ significant digits for the bounding box are enough plotinit(2); plotscale(2, 0,1, 0,1) plotmove(2, 0,0); plotbox(2, 1,1) plotmove(2, 0.1,0.1); plotstring(2, lims[1], left+top+vgap) plotstring(2, lims[3], bottom+vgap+right+hgap) plotmove(2, 0.98,0.1); plotstring(2, lims[2], right+top+vgap) plotmove(2, 0.1,0.98); plotstring(2, lims[4], right+hgap+top) plotdraw([2, 0,0, 3, 0.1,0.02], relative) @eprog We started with a trivial requirement: have an additional frame around the graph, and it took some effort to do so. But at least it was possible, and PARI did the hardest part: creating the actual graph. Now do a different thing: plot together the ``exact'' graph of $\zeta({1/2}+it)$ together with one obtained from splines approximation. We can emit these graphs into two rectangles, say 0 and 1, then put these two rectangles together on one plot. Or we can emit these graphs into one rectangle 0. However, a problem arises: note how we introduced a coordinate system in rectangle 2 of the above example, but we did not introduce a coordinate system in rectangle 3. Plotting a graph into rectangle 3 automatically created a coordinate system inside this rectangle (you could see this coordinate system in action if your output device supports mouse operations). If we use two different methods of graphing, the bounding boxes of the graphs will not be exactly the same, thus outputting the rectangles may be tricky. Thus during the second plotting we ask \kbd{plotrecth} to use the coordinate system of the first plotting. Let us add another plotting with fewer points too: \bprog plotinit(0, 0.9,0.9, relative) plotrecth(0, t=100,110, f(t), "Parametric",300) plotrecth(0, t=100,110, f(t), "Parametric|Splines|Points_too|no_Rescale",30); plotrecth(0, t=100,110, f(t), "Parametric|Splines|Points_too|no_Rescale",20); plotdraw([0, 0.05,0.05], relative) @eprog This achieves what we wanted: we may compare different ways to plot a graph, but the picture is confusing: which graph is what, and why there are multiple boxes around the graph? At least with some output devices one can control how the output curves look like, so we can use this to distinguish different graphs. And the mystery of multiple boxes is also not that hard to solve: they are bounding boxes for calculated points on each graph. We can disable output of bounding boxes with appropriate options for \kbd{plotrect}. With these frills the script becomes: \bprog plotinit(0, 0.9,0.9, relative) plotpointtype(-1, 0) \\@com set color of graph points plotpointsize(0, 0.4) \\@com use tiny markers (if available) plotrecth(0, t=100,110, f(t), "Parametric|no_Lines", 300) plotpointsize(0, 1) \\@com normal-size markers plotlinetype(-1, 1) \\@com set color of graph lines plotpointtype(-1, 1) \\@com set color of graph points opts="Parametric|Splines|Points_too|no_Rescale|no_Frame|no_X_axis|no_Y_axis"; plotrecth(0, t=100,110,f(t), opts, 30); plotlinetype(-1, 2) \\@com set color of graph lines plotpointtype(-1, 2) \\@com set color of graph points plotrecth(0, t=100,110,f(t), opts, 20); plotdraw([0, 0.05,0.05], relative) @eprog \noindent Plotting axes on the second and third graph would not hurt, but is not needed either, so we omit them. One can see that the discrepancies between the exact graph and one based on 30 points exist, but are pretty small. On the other hand, decreasing the number of points to 20 makes quite a noticeable difference. Keep in mind that \kbd{plotlinetype}, \kbd{plotpointtype}, \kbd{plotpointsize} may do nothing on some terminals. Additionally, one can ask PARI to output a plot into a PS file: just use the command \kbd{psdraw} instead of \kbd{plotdraw} in the above examples (or \kbd{psploth} instead of \kbd{ploth}). See \kbd{psfile} argument to \kbd{default} for how to change the output file for this operation. Keep in mind that the precision of PARI PS output will be the same as for the current output device. Now suppose we want to join many different small graphs into one picture. We cannot use one rectangle for all the output as we did in the example with $\zeta({1/2}+it)$, since the graphs should go into different places. Rectangles are a scarce commodity in PARI, since only 16 of them are user-accessible. Does it mean that we cannot have more than 16 graphs on one picture? Thanks to an additional operation of PARI plotting engine, there is no such restrictions. This operation is \kbd{plotcopy}. The following script puts 4 different graphs on one plot using 2 rectangles only, \kbd{A} and \kbd{T}: \bprog A = 2; \\@com accumulator T = 3; \\@com temporary target plotinit(A); plotscale(A, 0, 1, 0, 1) plotinit(T, 0.42, 0.42, relative); plotrecth(T, x= -5, 5, sin(x), "Recursive") plotcopy(T, 2, 0.05, 0.05, relative + nw) plotmove(A, 0.05 + 0.42/2, 1 - 0.05/2) plotstring(A,"Graph", center + vcenter) plotinit(T, 0.42, 0.42, relative); plotrecth(T, x= -5, 5, [sin(x),cos(2*x)], 0) plotcopy(T, 2, 0.05, 0.05, relative + ne) plotmove(A, 1 - 0.05 - 0.42/2, 1 - 0.05/2) plotstring(A,"Multigraph", center + vcenter) plotinit(T, 0.42, 0.42, relative); plotrecth(T, x= -5, 5, [sin(3*x), cos(2*x)], "Parametric") plotcopy(T, 2, 0.05, 0.05, relative + sw) plotmove(A, 0.05 + 0.42/2, 0.5) plotstring(A,"Parametric", center + vcenter) plotinit(T, 0.42, 0.42, relative); plotrecth(T, x= -5, 5, [sin(x), cos(x), sin(3*x),cos(2*x)], "Parametric") plotcopy(T, 2, 0.05, 0.05, relative + se) plotmove(A, 1 - 0.05 - 0.42/2, 0.5) plotstring(A,"Multiparametric", center + vcenter) plotlinetype(A, 3) plotmove(A, 0, 0) plotbox(A, 1, 1) plotdraw([A, 0, 0]) \\ psdraw([A, 0, 0], relative) \\ @com if hard copy is needed @eprog The rectangle \kbd{A} plays the role of accumulator, rectangle \kbd{T} is used as a target to \kbd{plotrecth} only. Immediately after plotting into rectangle \kbd{T} the contents is copied to accumulator. Let us explain numbers which appear in this example: we want to create 4 internal rectangles with a gap 0.06 between them, and the outside gap 0.05 (of the size of the plot). This leads to the size 0.42 for each rectangle. We also put captions above each graph, centered in the middle of each gap. There is no need to have a special rectangle for captions: they go into the accumulator too. To simplify positioning of the rectangles, the above example uses relative ``geographic'' notation: the last argument of \kbd{plotcopy} specifies the corner of the graph (say, northwest) one counts offset from. (Positive offsets go into the rectangle.) To demonstrate yet another useful plotting function, design a program to plot Taylor polynomials for a $\sin x$ about 0. For simplicity, make the program good for any function, but assume that a function is odd, so only odd-numbered Taylor series about 0 should be plotted. Start with defining some useful shortcuts \bprog xlim = 13; ordlim = 25; f(x) = sin(x); default(seriesprecision,ordlim) farray(t) = vector((ordlim+1)/2, k, truncate( f(1.*t + O(t^(2*k+1)) ))); FARRAY = farray('t); \\@com\kbd{'t} to make sure \kbd{t} is a free variable @eprog\noindent \kbd{farray(x)} returns a vector of Taylor polynomials for $f(x)$, which we store in \kbd{FARRAY}. We want to plot $f(x)$ into a rectangle, then make the rectangle which is 1.2 times higher, and plot Taylor polynomials into the larger rectangle. Assume that the larger rectangle takes 0.9 of the final plot. First of all, we need to measure the height of the smaller rectangle: \bprog plotinit(3, 0.9, 0.9/1.2, 1); opts = "Recursive | no_X_axis|no_Y_axis|no_Frame"; lims = plotrecth(3, x= -xlim, xlim, f(x), opts,16); h = lims[4] - lims[3]; @eprog\noindent Next step is to create a larger rectangle, and plot the Taylor polynomials into the larger rectangle: \bprog plotinit(4, 0.9,0.9, relative); plotscale(4, lims[1], lims[2], lims[3] - h/10, lims[4] + h/10) plotrecth(4, x = -xlim, xlim, subst(FARRAY,t,x), "no_Rescale"); @eprog Here comes the central command of this example: \bprog plotclip(4) @eprog\noindent What does it do? The command \kbd{plotrecth(\dots, "no\_Rescale")} scales the graphs according to coordinate system in the rectangle, but it does not pay any other attention to the size of the rectangle. Since \kbd{xlim} is 13, the Taylor polynomials take very large values in the interval \kbd{-xlim...xlim}. In particular, significant part of the graphs is going to be \emph{outside} of the rectangle. \kbd{plotclip} removes the parts of the plottings which fall off the rectangle boundary \bprog plotinit(2) plotscale(2, 0.0, 1.0, 0.0, 1.0) plotmove(2,0.5,0.975) plotstring(2,"Multiple Taylor Approximations",center+vcenter) plotdraw([2, 0, 0, 3, 0.05, 0.05 + 0.9/12, 4, 0.05, 0.05], relative) @eprog\noindent These commands draw a caption, and combine 3 rectangles (one with the caption, one with the graph of the function, and one with graph of Taylor polynomials) together. The plots are not very beautiful with the default colors. See \kbd{examples/taylor.gp} for a user function encapsulating the above example, and a colormap generator. This finishes our survey of PARI plotting functions, but let us add some remarks. First of all, for a typical output device the picture is composed of small colored squares (pixels), as a very large checkerboard. Each output rectangle is a disjoint union of such squares. Each drop of paint in the rectangle will color a whole square in it. Since the rectangle has a coordinate system, it is important to know how this coordinate system is positioned with respect to the boundaries of these squares. The command \kbd{plotscale} describes a range of $x$ and $y$ in the rectangle. The limit values of $x$ and $y$ in the coordinate system are coordinates \emph{of the centers} of corner squares. In particular, if ranges of $x$ and $y$ are $[0,1]$, then the segment which connects (0,0) with (0,1) goes along the \emph{middle} of the left column of the rectangle. In particular, if we made tiny errors in calculation of endpoints of this segment, this will not change which squares the segment intersects, thus the resulting picture will be the same. (It is important to know such details since many calculations are approximate.) Another consideration is that all examples we did in this section were using relative sizes and positions for the rectangles. This is nice, since different output devices will have very similar pictures, while we did not need to care about particular resolution of the output device. On the other hand, using relative positions does not guarantee that the pictures will be similar. Why? Even if two output devices have the same resolution, the picture may be different. The devices may use fonts of different size, or may have a different ``unit of length''. The information about the device in PARI is encoded in 6 numbers: resolution, size of a character cell of the font, and unit of length, all separately for horizontal and vertical direction. These sizes are expressed as numbers of pixels. To inspect these numbers one may use the function \kbd{plothsizes}. The ``units of length'' are currently used to calculate right and top gaps near graph rectangle of \kbd{ploth}, and gaps for \kbd{plotstring}. Left and bottom gaps near graph rectangle are calculate using both units of length, and sizes of character boxes (so that there is enough place to print limits of the graphs). What does it show? Using relative sizes during plotting produces \var{approximately} the same plotting on different devices, but does not ensure that the plottings ``look the same''. Moreover, ``looking the same'' is not a desirable target, ``looking tuned for the environment'' will be much better. If you want to produce such fine-tuned plottings, you need to abandon a relative-size model, and do your plottings in pixel units. To do this one removes flag \kbd{relative} from the above examples, which will make size and offset arguments interpreted this way. After querying sizes with \kbd{plothsizes} one can fine-tune sizes and locations of subrectangles to the details of an arbitrary plotting device. To check how good your fine-tuning is, you may test your graphs with a medium-resolution plotting (as many display output devices are), and with a low-resolution plotting (say, with \kbd{plotterm("dumb")} of gnuplot). \section{GP Programming} Do we really need such a section after all we have learnt so far? We now know how to write scripts and feed them to \kbd{gp}, in particular how to define functions. It's possible to define \emph{member} function as well, but we trust you to find them in the manual. We have seen most control statements: the missing ones (\kbd{while}, \kbd{break}, \kbd{next}, \kbd{return} and various \kbd{for} loops) should be straightforward. (You 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. \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) and \kbd{dbg\_err} (to access all components of an error context). To reach grandwizard status, you may need to understand the all powerful \kbd{install} function, which imports into \kbd{gp} an (almost) arbitrary function from the PARI library (and elsewhere too!), or how to use the \kbd{gp2c} compiler and its extended types. But both are beyond the scope of the present document. Have fun! \bye pari-2.7.5/doc/usersch2.tex0000644000175000017500000040720212605245104014137 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{The gp Calculator} \section{Introduction} Originally, \tet{gp} was designed as a debugging device for the PARI system library. Over the years, it has become a powerful user-friendly stand-alone calculator. The mathematical functions available in PARI and \kbd{gp} are described in the next chapter. In the present one, we describe the specific use of the \kbd{gp} programmable calculator. \emacs If you have GNU Emacs and use the PariEmacs package, you can work in a special Emacs shell, described in \secref{se:emacs}. Specific features of this Emacs shell are indicated by an EMACS sign in the left margin. \subsec{Startup} To start the calculator, the general command line syntax is: \kbd{gp [-D \var{key}=\var{val}] [\var{files}]} \noindent where items within brackets are optional. The [\var{files}] argument is a list of files written in the GP scripting language, which will be loaded on startup. There can be any number of arguments of the form \kbd{-D \var{key}=\var{val}}, setting some internal parameters of \kbd{gp}, or \var{defaults}: each sets the default \var{key} to the value \var{val}. See \secref{se:defaults} below for a list and explanation of all defaults. These defaults can be changed by adding parameters to the input line as above, or interactively during a \kbd{gp} session, or in a preferences file also known as \tet{gprc}. If a \idx{preferences file} (to be discussed in \secref{se:gprc}) is found, \kbd{gp} then reads it and executes the commands it contains. This provides an easy way to customize \kbd{gp}. The \var{files} argument is processed right after the \kbd{gprc}. A copyright banner then appears which includes the version number, and a lot of useful technical information. After the copyright, the computer writes the top-level help information, some initial defaults, and then waits after printing its prompt, which is '\kbd{?~}' by default . Whether extended on-line help and line editing are available or not is indicated in this \kbd{gp} banner, between the version number and the copyright message. Consider investigating the matter with the person who installed \kbd{gp} if they are not. Do this as well if there is no mention of the GMP kernel. \subsec{Getting help} To get help, type a \kbd{?} and hit return. A menu appears, describing the main categories of available functions and how to get more detailed help. If you now type \kbd{?$n$} with $1\le n\le11$, you get the list of commands corresponding to category $n$ and simultaneously to Section $3.n$ of this manual. If you type \kbd{?}\var{functionname} where \var{functionname} is the name of a PARI function, you will get a short explanation of this function. If extended help (see \secref{se:exthelp}) is available on your system, you can double or triple the \kbd{?} sign to get much more: respectively the complete description of the function (e.g.~\kbd{??sqrt}), or a list of \kbd{gp} functions relevant to your query (e.g.~ \kbd{???"elliptic curve"} or \kbd{???"quadratic field"}). If \kbd{gp} was properly installed (see Appendix~A), a line editor is available to correct the command line, get automatic completions, and so on. See \secref{se:readline} or \kbd{??readline} for a short summary of the line editor's commands. If you type \kbd{?\bs} you will get a short description of the metacommands (keyboard shortcuts). Finally, typing \kbd{?.} will return the list of available (pre-defined) member functions. These are functions attached to specific kind of objects, used to retrieve easily some information from complicated structures (you can define your own but they won't be shown here). We will soon describe these commands in more detail. More generally, commands starting with the symbols \b\ or \kbd{?}, are not computing commands, but are metacommands which allow you to exchange information with \kbd{gp}. The available metacommands can be divided into default setting commands (explained below) and simple commands (or keyboard shortcuts, to be dealt with in \secref{se:meta}). \subsec{Input} Just type in an instruction, e.g. \kbd{1 + 1}, or \kbd{Pi}. No action is undertaken until you hit the \kbd{} key. Then computation starts, and a result is eventually printed. To suppress printing of the result, end the expression with a \kbd{;} sign. Note that many systems use \kbd{;} to indicate end of input. Not so in \kbd{gp}: a final semicolon means the result should not be printed. (Which is certainly useful if it occupies several screens.) \subsec{Interrupt, Quit} Typing \kbd{quit} at the prompt ends the session and exits \kbd{gp}. At any point you can type \kbd{Ctrl-C} (that is press simultaneously the \kbd{Control} and \kbd{C} keys): the current computation is interrupted and control given back to you at the \kbd{gp} prompt, together with a message like \bprog *** at top-level: gcd(a,b) *** ^-------- *** gcd: user interrupt after 236 ms. @eprog\noindent telling you how much time elapsed since the last command was typed in and in which GP function the computation was aborted. It does not mean that that much time was spent in the function, only that the evaluator was busy processing that specific function when you stopped it. \section{The general gp input line} The \kbd{gp} calculator uses a purely interpreted language GP. The structure of this language is reminiscent of LISP with a functional notation, \kbd{f(x,y)} rather than \kbd{(f x y)}: all programming constructs, such as \kbd{if}, \kbd{while,} etc\dots are functions\footnote{*}{Not exactly, since not all their arguments need be evaluated. For instance it would be stupid to evaluate both branches of an \kbd{if} statement: since only one will apply, only this one is evaluated.}, and the main loop does not really execute, but rather evaluates (sequences of) expressions. Of course, it is by no means a true LISP, and has been strongly influenced by C and Perl since then. \subsec{Introduction} User interaction with a \kbd{gp} session proceeds as follows. First, one types a sequence of characters at the \kbd{gp} prompt; see \secref{se:readline} for a description of the line editor. When you hit the \kbd{} key, \kbd{gp} gets your input, evaluates it, then prints the result and assigns it to an ``history'' array. More precisely, the input is case-sensitive and, outside of character strings, blanks are completely ignored. Inputs are either metacommands or sequences of expressions. Metacommands are shortcuts designed to alter gp's internal state, such as the working precision or general verbosity level; we shall describe them in \secref{se:meta}, and ignore them for the time being. The evaluation of a sequence of instructions proceeds in two phases: your input is first digested (byte-compiled) to a bytecode suitable for fast evaluation, in particular loop bodies are compiled only once but a priori evaluated many times; then the bytecode is evaluated. An \idx{expression}\sidx{expression sequence} is formed by combining constants, variables, operator symbols, functions and control statements. It is evaluated using the conventions about operator priorities and left to right associativity. An expression always has a value, which can be any PARI object: \bprog ? 1 + 1 %1 = 2 \\@com an ordinary integer ? x %2 = x \\@com a polynomial of degree 1 in the unknown \kbd{x} ? print("Hello") Hello \\@com \kbd{void} return value ? f(x) = x^2 %3 = (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}, which conceptually returns nothing. But in fact procedures return a special \kbd{void} object, meant to be ignored (but which evaluates to $0$ in a numeric context, and stored as $0$ in the history or results). The final example assigns to the variable \kbd{f} the function $x\mapsto x^2$, the alternative form \kbd{f = x->x\pow2} achieving the same effect; the return value of a function definition is, unsurprisingly, a function object (of type \typ{CLOSURE}). Several expressions are combined on a single line by separating them with semicolons ('\kbd{;}'). Such an expression sequence will be called a \var{seq}. A \var{seq} also has a value, which is the value of the last expression in the sequence. Under \kbd{gp}, the value of the \var{seq}, and only this last value, becomes an history entry. The values of the other expressions in the \var{seq} are discarded after the execution of the \var{seq} is complete, except of course if they were assigned into variables. In addition, the value of the \var{seq} is printed if the line does not end with a semicolon \kbd{;}. \subsec{The gp history of results} This is not to be confused with the history of your \emph{commands}, maintained by \kbd{readline}. The \kbd{gp} history contains the \emph{results} they produced, in sequence. The successive elements of the history array are called \kbd{\%1}, \kbd{\%2}, \dots As a shortcut, the latest computed expression can also be called \kbd{\%}, the previous one \kbd{\%`}, the one before that \kbd{\%``} and so on. When you suppress the printing of the result with a semicolon, it is still stored in the history, but its history number will not appear either. It is a better idea to assign it to a variable for later use than to mentally recompute what its number is. Of course, on the next line, you may just use \kbd{\%}. The time used to compute that history entry is also stored as part of the entry and can be recovered using the \kbd{\%\#} operator: \kbd{\%\#1}, \kbd{\%\#2}, \kbd{\%\#`}; \kbd{\%\#} by itself returns the time needed to compute the last result (the one returned by \kbd{\%}). \misctitle{Remark} The history ``array'' is in fact better thought of as a queue: its size is limited to 5000 entries by default, after which \kbd{gp} starts forgetting the initial entries. So \kbd{\%1} becomes unavailable as \kbd{gp} prints \kbd{\%5001}. You can modify the history size using \tet{histsize}. \subsec{Special editing characters}\sidx{editing characters} A GP program can of course have more than one line. Since your commands are executed as soon as you have finished typing them, there must be a way to tell \kbd{gp} to wait for the next line or lines of input before doing anything. There are three ways of doing this. The first one is to use the \idx{backslash character} \kbd{\bs} at the end of the line that you are typing, just before hitting \kbd{}. This tells \kbd{gp} that what you will write on the next line is the physical continuation of what you have just written. In other words, it makes \kbd{gp} forget your newline character. You can type a \kbd{\bs} anywhere. It is interpreted as above only if (apart from ignored whitespace characters) it is immediately followed by a newline. For example, you can type \bprog ? 3 + \ 4 @eprog \noindent instead of typing \kbd{3 + 4}. The second one is a variation on the first, and is mostly useful when defining a user function (see \secref{se:user_defined}): since an equal sign can never end a valid expression, \kbd{gp} disregards a newline immediately following an \kbd{=}. \bprog ? a = 123 %1 = 123 @eprog The third one is in general much more useful, and uses braces \kbd{\obr} and \kbd{\cbr}.\sidx{brace characters} An opening brace \kbd{\obr} signals that you are typing a multi-line command, and newlines are ignored until you type a closing brace \kbd{\cbr}. There are two important, but easily obeyed, restrictions: first, braces do not nest; second, inside an open brace-close brace pair, all input lines are concatenated, suppressing any newlines. Thus, all newlines should occur after a semicolon (\kbd{;}), a comma (\kbd{,}) or an operator (for clarity's sake, never split an identifier over two lines in this way). For instance, the following program \bprog { a = b b = c } @eprog \noindent would silently produce garbage, since this is interpreted as \kbd{a=bb=c} which assigns the value of \kbd{c} to both \kbd{bb} and \kbd{a}. It should have been written \bprog { a = b; b = c; } @eprog \section{The PARI types} \noindent We see here how to input values of the different data types known to PARI. Recall that blanks are ignored in any expression which is not a string (see below). \misctitle{A note on efficiency} The following types are provided for convenience, not for speed: \typ{INTMOD}, \typ{FRAC}, \typ{PADIC}, \typ{QUAD}, \typ{POLMOD}, \typ{RFRAC}. Indeed, they always perform a reduction of some kind after each basic operation, even though it is usually more efficient to perform a single reduction at the end of some complex computation. For instance, in a convolution product $\sum_{i+j = n} x_i y_j$ in $\Z/N\Z$ --- common when multiplying polynomials! ---, it is quite wasteful to perform $n$ reductions modulo $N$. In short, basic individual operations on these types are fast, but recursive objects with such components could be handled more efficiently: programming with libpari will save large constant factors here, compared to GP. \subsec{Integers (\typ{INT})}% \sidx{integer}\kbdsidx{t_INT} After an (optional) leading \kbd{+} or \kbd{-}, type in the decimal digits of your integer. No decimal point! \bprog ? 1234567 %1 = 1234567 ? -3 %2 = -3 ? 1. \\@com oops, not an integer %3 = 1.000000000000000000000000000 @eprog \subsec{Real numbers (\typ{REAL})}% \sidx{real number}\kbdsidx{t_REAL} Real numbers are represented (approximately) in a floating point system, internally in base 2, but converted to base 10 for input / output purposes. A \typ{REAL} object has a given \emph{accuracy} (or \emph{precision}) $\ell \geq 0$; it comprises \item a sign $s$: $+1$, $-1$ or $0$; \item a mantissa $m$: a multiprecision integer, $0\leq m < 10^\ell$; \item an exponent $e$: a small integer in $[-E,E]$, where $E \approx 2^B \log_{10} 2$, and $B = 32$ on a 32-bit machine and 64 otherwise. This data may represent any real number $x$ such that $$|x - s m 10^e| < 10^{e-\ell}.$$ We consider that a \typ{REAL} with sign $s = 0$ has accuracy $\ell = 0$, so that its mantissa is useless, but it still has an exponent $e$ and acts like a machine epsilon for all accuracies $< e$. After an (optional) leading \kbd{+} or \kbd{-}, type a number with a decimal point. Leading zeroes may be omitted, up to the decimal point, but trailing zeroes are important: your \typ{REAL} is assigned an internal precision, which is the supremum of the input precision, one more than the number of decimal digits input, and the default precision. For example, if the default precision is 28 digits, typing \kbd{2.} yields a precision of 28 digits, but \kbd{2.0\dots0} with 45 zeros gives a number with internal precision at least 45, although less may be printed. You can also use scientific notation with the letter \kbd{E} or \kbd{e}. As usual, \kbd{e$n$} is interpreted as $\times 10^n$ for all integers $n$. Since the result is converted to a \typ{REAL}, you may often omit the decimal point in this case: \kbd{6.02 E 23} or \kbd{1e-5} are fine, but \kbd{e10} is not. By definition, \kbd{0.E $n$} returns a real $0$ of exponent $n$, whereas \kbd{0.} returns a real 0 ``of default precision'' (of exponent $-\tet{realprecision}$), see \secref{se:whatzero}, behaving like the machine epsilon for the current default accuracy: any float of smaller absolute value is indistinguishable from $0$. \misctitle{Note on output formats} A zero real number is printed in \kbd{e} format as $0.Exx$ where $xx$ is the (usually negative) \emph{decimal} exponent of the number (cf.~\secref{se:whatzero}). This allows the user to check the accuracy of that particular zero. When the integer part of a real number $x$ is not known exactly because the exponent of $x$ is greater than the internal precision, the real number is printed in \kbd{e} format. \subsec{Intmods (\typ{INTMOD})}% \sidx{intmod}\kbdsidx{t_INTMOD} To create the image of the integer $a$ in $\Z/b\Z$ (for some non-zero integer $b$), type \kbd{Mod(a,b)}; \emph{not} \kbd{a\%b}. Internally, all operations are done on integer representatives belonging to $[0,b-1]$. Note that this type is available for convenience, not for speed: each elementary operation involves a reduction modulo $b$. If $x$ is a \typ{INTMOD} \kbd{Mod(a,b)}, the following member function is defined: \kbd{x.mod}: return the modulus \kbd{b}. \subsec{Rational numbers (\typ{FRAC})}% \sidx{rational number}\kbdsidx{t_FRAC} All fractions are automatically reduced to lowest terms, so it is impossible to work with reducible fractions. To enter $n/m$ just type it as written. As explained in \secref{se:gdiv}, floating point division is \emph{not} performed, only reduction to lowest terms.\label{se:FRAC} Note that rational computation are almost never the fastest method to proceed: in the PARI implementation, each elementary operation involves computing a gcd. It is generally a little more efficient to cancel denominators and work with integers only: \bprog ? P = Pol( vector(10^3,i, 1/i) ); \\@com big polynomial with small rational coeffs ? P^2 time = 1,392 ms. ? c = content(P); c^2 * (P/c)^2; \\@com same computation in integers time = 1,116 ms. @eprog\noindent And much more efficient (but harder to setup) to use homomorphic imaging schemes and modular computations. As the simple example below indicates, if you only need modular information, it is very worthwhile to work with \typ{INTMOD}s directly, rather than deal with \typ{FRAC}s all the way through: \bprog ? p = nextprime(10^7); ? sum(i=1, 10^5, 1/i) % p time = 13,288 ms. %1 = 2759492 ? sum(i=1, 10^5, Mod(1/i, p)) time = 60 ms. %2 = Mod(2759492, 10000019) @eprog\noindent \subsec{Finite field elements (\typ{FFELT})}% \sidx{finite field element}\kbdsidx{t_FFELT} Let $T\in\F_p[X]$ be a monic irreducible polynomial defining your finite field over $\F_p$, for instance obtained using \tet{ffinit}. Then the \tet{ffgen} function creates a generator of the finite field as an $\F_p$-algebra, namely the class of $X$ in $\F_p[X]/(T)$, from which you can build all other elements. For instance, to create the field $\F_{2^8}$, we write \bprog ? T = ffinit(2, 8); ? y = ffgen(T, 'y); ? y^0 \\ the unit element in the field %3 = 1 ? y^8 %4 = y^6 + y^5 + y^4 + y^3 + y + 1 @eprog\noindent The second (optional) parameter to \tet{ffgen} is only used to display the result; it is customary to use the name of the variable we assign the generator to. If \kbd{g} is a \typ{FFELT}, the following member functions are defined: \kbd{g.pol}: the polynomial (with reduced integer coefficients) expressing \kbd{g} in term of the field generator. \kbd{g.p}: the characteristic of the finite field. \kbd{g.f}: the dimension of the definition field over its prime field; the cardinality of the definition field is thus $p^f$. \kbd{g.mod}: the minimal polynomial (with reduced integer coefficients) of the field generator. \subsec{Complex numbers (\typ{COMPLEX})}% \sidx{complex number}\kbdsidx{t_COMPLEX} To enter $x+iy$, type \kbd{x + I*y}. (That's \kbd{I}, \emph{not} \kbd{i}!) The letter \tet{I} stands for $\sqrt{-1}$. The ``real'' and ``imaginary'' parts $x$ and $y$ can be of type \typ{INT}, \typ{REAL}, \typ{INTMOD}, \typ{FRAC}, or \typ{PADIC}. \subsec{$p$-adic numbers (\typ{PADIC}):}% \sidx{p-adic number}\label{se:padic}\kbdsidx{t_PADIC} Typing \kbd{O($p$\pow $k$)}, where $p$ and $k$ are integers, yields a $p$-adic $0$ of accuracy~$k$, representing any $p$-adic number whose valuation is $\geq k$. To input a general non-0 $p$-adic number, write a suitably precise rational or integer approximation and add \kbd{O($p$\pow $k$)} to it. Note that it is not checked whether $p$ is indeed prime but results are undefined if this is not the case: you can work on $10$-adics if you want, but disasters will happen as soon as you do something non-trivial like taking a square root. Note that \kbd{O(25)} is not the same as \kbd{O(5\pow 2)}; you want the latter! For example, you can type in the $7$-adic number \kbd{2*7\pow(-1) + 3 + 4*7 + 2*7\pow 2 + O(7\pow3)} \noindent exactly as shown, or equivalently as \kbd{905/7 + O(7\pow3)}. If $a$ is a \typ{PADIC}, the following member functions are defined: \kbd{a.mod}: returns the modulus $p^k$. \kbd{a.p}: returns $p$. Note that this type is available for convenience, not for speed: internally, \typ{PADIC}s are stored as $p$-adic units modulo some $p^k$. Each elementary operation involves updating $p^k$ (multiplying or dividing by powers of $p$) and a reduction mod $p^k$. In particular, additions are slow. \bprog ? n = 1+O(2^20); for (i=1,10^6, n++) time = 841 ms. ? n = Mod(1,2^20); for (i=1,10^6, n++) time = 441 ms. ? n = 1; for (i=1,10^6, n++) time = 328 ms. @eprog\noindent The penalty associated with maintaining $p^k$ decreases steeply as $p$ increases (and updates become very rare). But \typ{INTMOD}s remain at least 25\% more efficient. (But they do not have denominators!) % n = 1+O(1009^2); for (i=1,10^6, n++) % n = Mod(1,1009^2); for (i=1,10^6, n++) \subsec{Quadratic numbers (\typ{QUAD})}% \sidx{quadratic number}\kbdsidx{t_QUAD} This type is used to work in the quadratic order of \emph{discriminant} \kbd{d}, where \kbd{d} is a non-square integer congruent to $0$ or $1$ (modulo $4$). The command \bprog w = quadgen(d) @eprog\noindent assigns to \kbd{w} the ``canonical'' generator for the integer basis of the order of discriminant $d$, i.e.~$w=\sqrt{d}/2$ if $d\equiv 0 \mod 4$, and $w=(1+\sqrt{d})/2$ if $d\equiv 1 \mod 4$. The name \kbd{w} is of course just a suggestion, but corresponds to traditional usage. You can use any variable name that you like, but \kbd{quadgen(d)} is always printed as \kbd{w}, regardless of the discriminant. So beware, two \typ{QUAD}s can be printed in the same way and not be equal; however, \kbd{gp} will refuse to add or multiply them for example. Since the order is $\Z + \kbd{w}\Z$, any other element can be input as \kbd{z = $x$+$y$*w} for some integers $x$ and $y$. In fact, you may work in its fraction field $\Q(\sqrt{d})$ and use \typ{FRAC} values for $x$ and $y$. The member function \kbd{z.disc} retrieves the discriminant $d$; $x$ and $y$ are obtained via \kbd{real(z)} and \kbd{imag(z)} respectively. \subsec{Polmods (\typ{POLMOD})}% \sidx{polmod}\kbdsidx{t_POLMOD} Exactly as for intmods, to enter $x \mod y$ (where $x$ and $y$ are polynomials), type \kbd{Mod(x,y)}, not \kbd{x\%y}. Note that when $y$ is an irreducible polynomial in one variable, polmods whose modulus is $y$ are simply algebraic numbers in the finite extension defined by the polynomial $y$. This allows us to work easily in \idx{number field}s, finite extensions of the $p$-adic field $\Q_p$, or \idx{finite field}s. Note that this type is available for convenience, not for speed: each elementary operation involves a reduction modulo $y$. If $p$ is a \typ{POLMOD}, the following member functions are defined: \kbd{p.pol}: return a representative of the polynomial class of minimal degree. \kbd{p.mod}: return the modulus. \label{se:rempolmod} \misctitle{Important remark}\sidx{variable (priority)} Mathematically, the variables\sidx{variable} occurring in a polmod are not free variables. But internally, a congruence class in $R[t]/(y)$ is represented by its representative of lowest degree, which is a \typ{POL} in $R[t]$, and computations occur with polynomials in the variable $t$. PARI will not recognize that \kbd{Mod(y, y\pow2 + 1)} is ``the same'' as \kbd{Mod(x, x\pow2 + 1)}, since \kbd{x} and \kbd{y} are different variables. To avoid inconsistencies, polmods must use the same variable in internal operations (i.e.~between polmods) and variables of lower priority for external operations, typically between a polynomial and a polmod. See \secref{se:priority} for a definition of ``priority'' and a discussion of (PARI's idea of) multivariate polynomial arithmetic. For instance: \bprog ? Mod(x, x^2+ 1) + Mod(x, x^2 + 1) %1 = Mod(2*x, x^2 + 1) \\@com $2i$ (or $-2i$), with $i^2=-1$ ? x + Mod(y, y^2 + 1) %2 = x + Mod(y, y^2 + 1) \\@com in $\Q(i)[x]$ ? y + Mod(x, x^2 + 1) %3 = Mod(x + y, x^2 + 1) \\@com in $\Q(y)[i]$ @eprog\noindent The first two are straightforward, but the last one may not be what you want: \kbd{y} is treated here as a numerical parameter, not as a polynomial variable. If the main variables are the same, it is allowed to mix \typ{POL} and \typ{POLMOD}s. The result is the expected \typ{POLMOD}. For instance \bprog ? x + Mod(x, x^2 + 1) %1 = Mod(2*x, x^2 + 1) @eprog \subsec{Polynomials (\typ{POL})}% \sidx{polynomial}\label{se:pol}\kbdsidx{t_POL} Type the polynomial in a natural way, not forgetting to put a ``$*$'' between a coefficient and a formal variable; \bprog ? 1 + 2*x + 3*x^2 %1 = 3*x^2 + 2*x + 1 @eprog\noindent This assumes that \kbd{x} is still a ''free variable''. \bprog ? x = 1; 1 + 2*x + 3*x^2 %2 = 6 @eprog\noindent generates an integer, not a polynomial! It is good practice to never assign values to polynomial variables to avoid the above problem, but a foolproof construction is available using \kbd{'x} instead of~\kbd{x}: \kbd{'x} is a constant evaluating to the free variable with name \kbd{x}, independently of the current value of~\kbd{x}. \bprog ? x = 1; 1 + 2*'x + 3*'x^2 %3 = 1 + 2*x + 3*x^2 ? x = 'x; 1 + 2*x + 3*x^2 %4 = 1 + 2*x + 3*x^2 @eprog\noindent You may also use the functions \kbd{Pol} or \kbd{Polrev}: \bprog ? Pol([1,2,3]) \\@com \kbd{Pol} creates a polynomial in \kbd{x} by default %1 = x^2 + 2*x + 3 ? Polrev([1,2,3]) %2 = 3*x^2 + 2*x + 1 ? Pol([1,2,3], 'y) \\@com we use \kbd{'y}, safer than \kbd{y} %3 = y^2 + 2*y + 3 @eprog\noindent The latter two are much more efficient constructors than an explicit summation (the latter is quadratic in the degree, the former linear): \bprog ? for (i=1, 10^4, Polrev( vector(100, i,i) ) ) time = 124ms ? for (i=1, 10^4, sum(i = 1, 100, (i+1) * 'x^i) ) time = 3,985ms @eprog Polynomials are always printed as \emph{univariate} polynomials, with monomials sorted by decreasing degree: \bprog ? (x+y+1)^2 %1 = x^2 + (2*y + 2)*x + (y^2 + 2*y + 1) @eprog\noindent (Univariate polynomial in \kbd{x} whose coefficients are polynomials in \kbd{y}.) See \secref{se:varsymb} for valid variable names, and a discussion of multivariate polynomial rings. \subsec{Power series (\typ{SER})}% \sidx{power series}\kbdsidx{t_SER}\label{se:series} Typing \kbd{O(X\pow $k$)}, where $k$ is an integer, yields an $X$-adic $0$ of accuracy~$k$, representing any power series in \kbd{X} whose valuation is $\geq k$. Of course, \kbd{X} can be replaced by any other variable name! To input a general non-0 power series, type in a polynomial or rational function (in \kbd{X}, say), and add \kbd{O(X\pow $k$)} to it. The discussion in the \typ{POL} section about variables remains valid; a constructor \tet{Ser} replaces \tet{Pol} and \tet{Polrev}. \misctitle{Caveat} Power series with inexact coefficients sometimes have a non-intuitive behavior: if $k$ significant terms are requested, an inexact zero is counted as significant, even if it is the coefficient of lowest degree. This means that useful higher order terms may be disregarded. If a series with a zero leading coefficient must be inverted, then as a desperation measure that coefficient is discarded, and a warning is issued: \bprog ? C = 0. + y + O(y^2); ? 1/C *** _/_: Warning: normalizing a series with 0 leading term. %2 = y^-1 + O(1) @eprog\noindent The last output could be construed as a bug since it is a priori impossible to deduce such a result from the input ($0.$ represents any sufficiently small real number). But it was thought more useful to try and go on with an approximate computation than to raise an early exception. If the series precision is insufficient, errors may occur (mostly division by $0$), which could have been avoided by a better global understanding of the computation: \bprog ? A = 1/(y + 0.); B = 1. + O(y); ? B * denominator(A) %2 = 0.E-28 + O(y) ? A/B *** _/_: Warning: normalizing a series with 0 leading term. %3 = 1.000000000000000000000000000*y^-1 + O(1) ? A*B *** _*_: Warning: normalizing a series with 0 leading term. %4 = 1.000000000000000000000000000*y^-1 + O(1) @eprog \subsec{Rational functions (\typ{RFRAC})}% \sidx{rational function}\kbdsidx{t_RFRAC} As for fractions, all rational functions are automatically reduced to lowest terms. All that was said about fractions in \secref{se:FRAC} remains valid here. \subsec{Binary quadratic forms of positive or negative discriminant (\typ{QFR} and \typ{QFI})}% \sidx{binary quadratic form}\kbdsidx{t_QFR}\kbdsidx{t_QFI} These are input using the function \kbd{Qfb}. For example \kbd{Qfb(1,2,3)} creates the binary form $q = x^2+2xy+3y^2$. It is imaginary (of internal type \typ{QFI}) since its discriminant $2^2 - 4\times 3 = -8$ is negative. Although imaginary forms could be positive or negative definite, only positive definite forms are implemented. The discriminant can be retrieved via \kbd{poldisc} or \kbd{q.disc}. The individual components are obtained via either of \bprog [a,b,c] = Vec(q); a = component(q,1); b = component(q,2); c = component(q,3); @eprog In the case of forms with positive discriminant (\typ{QFR}), you may add an optional fourth component (related to the regulator, more precisely to Shanks and Lenstra's ``distance''), which must be a real number. See also the function \kbd{qfbprimeform} which directly creates a prime form of given discriminant. \subsec{Row and column vectors (\typ{VEC} and \typ{COL})}% \sidx{row vector}\sidx{column vector}\kbdsidx{t_VEC}\kbdsidx{t_COL}) To enter a row vector, type the components separated by commas ``\kbd{,}'', and enclosed between brackets ``\kbd{[}$\,$'' and ``$\,$\kbd{]}'', e.g.~\kbd{[1,2,3]}. To enter a column vector, type the vector horizontally, and add a tilde ``\til'' to transpose. \kbd{[ ]} yields the empty (row) vector. The function \tet{Vec} can be used to transform any object into a vector (see Chapter~3). The construction $[i..j]$, where $i \leq j$ are two integers returns the vector $[i, i+1,\dots, j-1, j]$ \bprog ? [1,2,3] %1 = [1, 2, 3] ? [-2..3] %2 = [-2, -1, 0, 1, 2, 3] @eprog Let the variable $v$ contain a (row or column) vector: \item \kbd{v[m]} refers to its $m$-th entry; you can assign any value to \kbd{v[m]}, i.e.~write something like $v[m]=\var{expr}$. \item \kbd{v[i..j]}, where $i \leq j$, returns the vector slice containing elements $v[i],\dots, v[j]$; you can \emph{not} assign a result to \kbd{v[i..j]}. \item \kbd{v[\pow i]} returns the vector whose $i$-th entry has been removed; you can \emph{not} assign a result to \kbd{v[\pow i]}. \noindent In the last two constructions \kbd{v[i..j]} and \kbd{v[\pow i]}, $i$ and $j$ are allowed to be negative integers, in which case, we start counting from the end of the vector: e.g., $-1$ is the index of the last element. \bprog ? v = [1,2,3,4]; ? v[2..4] %2 = [2, 3, 4] ? v[^3] %3 = [1, 2, 4] ? v[^-1] %3 = [1, 2, 3] ? v[-3..-1] %4 = [2, 3, 4] @eprog \misctitle{Remark} \tet{vector} is the standard constructor for row vectors whose $i$-th entry is given by a simple function of $i$; \tet{vectorv} is similar for column vectors: \bprog ? vector(10, i, i^2+1) %1 = [2, 5, 10, 17, 26, 37, 50, 65, 82, 101] @eprog The functions \tet{Vec} and \tet{Col} convert objects to row and column vectors respectively (as well as \tet{Vecrev} and \tet{Colrev}, which revert the indexing): \bprog ? T = poltchebi(5) \\ 5-th Chebyshev polynomial %1 = 16*x^5 - 20*x^3 + 5*x ? Vec(T) %2 = [16, 0, -20, 0, 5, 0] \\ coefficients of T ? Vecrev(T) %3 = [0, 5, 0, -20, 0, 16] \\ ... in reverse order @eprog \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively, and may serve as \typ{VEC} constructors: \bprog ? [ p | p <- primes(10), isprime(p+2) ] %2 = [3, 5, 11, 17, 29] @eprog\noindent returns the primes $p$ (among the first 10 primes) such that $(p, p+2)$ is a twin pair; \bprog ? [ p^2 | p <- primes(10), p % 4 == 1 ] %1 = [25, 169, 289, 841] @eprog\noindent returns the squares of the primes congruent to $1$ modulo $4$, where $p$ runs among the first 10 primes. \subsec{Matrices (\typ{MAT})}% \sidx{matrix}\kbdsidx{t_MAT} To enter a matrix, type the components row by row, the components being separated by commas ``\kbd{,}'', the rows by semicolons ``\kbd{;}'', and everything enclosed in brackets ``\kbd{[}$\,$'' and ``$\,$\kbd{]}'', e.g. \kbd{[x,y; z,t; u,v]}. \kbd{[;]} yields an empty ($0 \times 0$) matrix. The function \tet{Mat} transforms any object into a matrix, and \tet{matrix} creates matrices whose $(i,j)$-th entry is described by a function $f(i,j)$: \bprog ? Mat(1) %1 = [1] ? matrix(2,2, i,j, 2*i+j) %2 = [3 4] [5 6] @eprog \noindent Let the variable $M$ contain a matrix, and let $i,j,k,l$ denote four integers: \item \kbd{M[i,j]} refers to its $(i,j)$-th entry; you can assign any result to \kbd{M[i,j]}. \item \kbd{M[i,]} refers to its $i$-th row; you can assign a \typ{VEC} of the right dimension to \kbd{M[i,]}. \item \kbd{M[,j]} refers to its $j$-th column; you can assign a \typ{COL} of the right dimension to \kbd{M[,j]}. \noindent \emph{But} \kbd{M[i]} is meaningless and triggers an error. The ``range'' $i..j$ and ``caret'' \kbd{\pow}$c$ notations are available as for vectors; you can not \emph{assign} to any of these: \item \kbd{M[i..j, k..l]}, $i\leq j$, $k\leq l$, returns the submatrix built from the rows $i$ to $j$ and columns $k$ to $l$ of $M$. assign to \kbd{M[i..j, j..l]}. \item \kbd{M[i..j,]} returns the submatrix built from the rows $i$ to $j$ of $M$. \item \kbd{M[,i..j]} returns the submatrix built from the columns $i$ to $j$ of $M$. \item \kbd{M[i..j, \pow k]}, $i\leq j$, returns the submatrix built from the rows $i$ to $j$ and column $k$ removed. \item \kbd{M[\pow k,]} returns the submatrix with row $k$ removed. \item \kbd{M[,\pow k]} returns the submatrix with column $k$ removed. \noindent Finally, \item \kbd{M[i..j, k]} returns the \typ{COL} built from the $k$-th column (entries $i$ to $j$). \item \kbd{M[\pow i, k]} returns the \typ{COL} built from the $k$-th column (entry $i$ removed). \item \kbd{M[k, i..j]} returns the \typ{VEC} built from the $k$-th row (entries $i$ to $j$). \item \kbd{M[k, \pow i]} returns the \typ{VEC} built from the $k$-th row (entry $i$ removed). \bprog ? M = [1,2,3;4,5,6;7,8,9]; ? M[1..2, 2..3] %2 = [2 3] [5 6] ? M[1..2,] %3 = [1 2 3] [4 5 6] ? M[,2..3] %4 = [2 3] [5 6] [8 9] @eprog All this is recursive, so if \kbd{M} is a matrix of matrices of \dots, an expression such as \kbd{M[1,1][,3][4] = 1} is perfectly valid (and actually identical to \kbd{M[1,1][4,3] = 1}), assuming that all matrices along the way have compatible dimensions. \misctitle{Technical note (design flaw)} Matrices are internally represented as a vector of columns. All matrices with $0$ columns are thus represented by the same object (internally, an empty vector), and there is no way to distinguish between them. Thus it is not possible to create or represent matrices with zero columns and an actual nonzero number of rows. The empty matrix \kbd{[;]} is handled as though it had an arbitrary number of rows, exactly as many as needed for the current computation to make sense: \bprog ? [1,2,3; 4,5,6] * [;] %1 = [;] @eprog\noindent The empty matrix on the first line is understood as a $3\times 0$ matrix, and the result as a $2\times 0$ matrix. On the other hand, it is possible to create matrices with a given positive number of columns, each of which has zero rows, e.g.~using \kbd{Mat} as above or using the \kbd{matrix} function. Note that although the internal representation is essentially the same, a row vector of column vectors is \emph{not} a matrix; for example, multiplication will not work in the same way. It is easy to go from one representation to the other using \tet{Vec} / \tet{Mat}, though: \bprog ? [1,2,3;4,5,6] %1 = [1 2 3] [4 5 6] ? Vec(%) %2 = [[1, 4]~, [2, 5]~, [3, 6]~] ? Mat(%) %3 = [1 2 3] [4 5 6] @eprog \subsec{Lists (\typ{LIST})}% \sidx{list}\kbdsidx{t_LIST} Lists can be input directly, as in \kbd{List([1,2,3,4])}; but in most cases, one creates an empty list, then appends elements using \kbd{listput}: \bprog ? a = List(); listput(a,1); listput(a,2); ? a %2 = List([1, 2]) @eprog\noindent Elements can be accessed directly as with the vector types described above. \subsec{Strings (\typ{STR})}% \sidx{string}\sidx{character string}\kbdsidx{t_STR} To enter a string, enclose it between double quotes \kbd{"}, like this: \kbd{"this is a string"}. The function \kbd{Str} can be used to transform any object into a string. \subsec{Small vectors (\typ{VECSMALL})}% \kbdsidx{t_VECSMALL} This is an internal type, used to code in an efficient way vectors containing only small integers, such as permutations. Most \kbd{gp} functions will refuse to operate on these objects. \subsec{Functions (\typ{CLOSURE})}% \kbdsidx{t_CLOSURE} We will explain this at length in \secref{se:user_defined}. For the time being, suffice it to say that functions can be assigned to variables, as any other object, and the following equivalent basic forms are available to create new ones \bprog f = (x,y) -> x^2 + y^2 f(x,y) = x^2 + y^2 @eprog \subsec{Error contexts (\typ{ERROR})}% \kbdsidx{t_ERROR} An object of this type is created whenever an error occurs: it contains some information about the error and the error context. Usually, an appropriate error is printed immediately, the computation is aborted, and GP enters the ``break loop'': \bprog ? 1/0; 1 + 1 *** at top-level: 1/0;1+1 *** ^------ *** _/_: division by a non-invertible object *** Break loop: type 'break' to go back to the GP prompt @eprog\noindent Here the computation is aborted as soon as we try to evaluate $1/0$, and $1 + 1$ is never executed. Exceptions can be trapped using \tet{iferr}, however: we can evaluate some expression and either recover an ordinary result (no error occurred), or an exception (an error did occur). \bprog ? i = Mod(6,12); iferr(1/i, E, print(E)); 1 + 1 error("impossible inverse modulo: Mod(6, 12).") %1 = 2 @eprog\noindent One can ignore the exception, print it as above, or extract non trivial information from the error context: \bprog ? i = Mod(6,12); iferr(1/i, E, print(component(E,1))); Mod(6, 12) @eprog\noindent We can also rethrow the exception: \kbd{error(E)}. \section{GP operators}\label{se:operators} \noindent Loosely speaking, an \idx{operator} is a function, usually associated to basic arithmetic operations, whose name contains only non-alphanumeric characters. For instance \kbd{+} or \kbd{-}, but also \kbd{=} or \kbd{+=}, or even \kbd{[ ]} (the selection operator). As all functions, operators take arguments, and return a value; \emph{assignment} operators also have side effects: besides returning a value, they change the value of some variable. Each operator has a fixed and unchangeable priority, which means that, in a given expression, the operations with the highest priority is performed first. Unless mentioned otherwise, operators at the same priority level are left-associative (performed from left to right), unless they are assignments, in which case they are right-associative. Anything enclosed between parenthesis is considered a complete subexpression, and is resolved recursively, independently of the surrounding context. For instance, \bprog a + b + c --> (a + b) + c \\@com left-associative a = b = c --> a = (b = c) \\@com right-associative @eprog\noindent Assuming that \var{op}$_1$, \var{op}$_2$, \var{op}$_3$ are binary operators with increasing priorities (think of \kbd{+}, \kbd{*}, \kbd{\pow}), $$ x~\var{op}_1~y~\var{op}_2~z~\var{op}_2~x~\var{op}_3~y $$ is equivalent to $$ x~\var{op}_1~((y~\var{op}_2~z)~\var{op}_2~ (x~\var{op}_3~y)).$$ GP contains many different operators, either unary (having only one argument) or binary, plus a few special selection operators. Unary operators are defined as either \emph{prefix} or \emph{postfix}, meaning that they respectively precede (\var{op}~$x$) and follow ($x$~\var{op}) their single argument. Some symbols are syntactically correct in both positions, like \kbd{!}, but then represent different operators: the \kbd{!} symbol represents the negation and factorial operators when in prefix and postfix position respectively. Binary operators all use the (infix) syntax $x$~\var{op}~$y$. Most operators are standard (\kbd{+}, \kbd{\%}, \kbd{=}), some are borrowed from the C language (\kbd{++}, \kbd{<<}), and a few are specific to GP (\kbd{\bs}, \kbd{\#}). Beware that some GP operators differ slightly from their C counterparts. For instance, GP's postfix \kbd{++} returns the \emph{new} value, like the prefix \kbd{++} of~C, and the binary shifts \kbd{<<}, \kbd{>>} have a priority which is different from (higher than) that of their C counterparts. When in doubt, just surround everything by parentheses; besides, your code will be more legible. \noindent Here is the list of available operators, ordered by decreasing \idx{priority}, binary and left-associative unless mentioned otherwise. An expression is an \tev{lvalue} if something can be assigned to it. (The name comes from left-value, to the left of a \kbd{=} operator; e.g. \kbd{x}, or \kbd{v[1]} are lvalues, but \kbd{x + 1} is not.) \def\point#1{\noindent\item #1\hfill\break\indent\strut} \point{Priority 14} % \kbd{:} as in \kbd{x:small}, is used to indicate to the GP2C compiler that the variable on the left-hand side always contains objects of the type specified on the right hand-side (here, a small integer) in order to produce more efficient or more readable C code. This is ignored by GP. % \point{Priority 13} \kbd{( )} is the function call operator. If $f$ is a closure and \var{args} is a comma-separated list of arguments (possibly empty), $f\kbd{(\var{args})}$ evaluates $f$ on those arguments. \point{Priority 12} % \kbd{++} and \kbd{--} (unary, postfix): if $x$ is an \tet{lvalue}, \kbd{$x$++} assigns the value $x+1$ to $x$, then returns the new value of $x$. This corresponds to the C statement \kbd{++$x$}: there is no prefix \kbd{++} operator in GP. \kbd{$x$--} does the same with $x-1$. These operators are not associative, i.e. \kbd{x++++} is invalid, since \kbd{x++} is not an lvalue. \point{Priority 11} % \kbd{.}\var{member} (unary, postfix): \kbd{$x$.\var{member}} extracts \var{member} from structure $x$ (see~\secref{se:member}). \kbd{[ ]} is the selection operator. \kbd{$x$[$i$]} returns the $i$-th component of vector $x$; \kbd{$x$[$i$,$j$]}, \kbd{$x$[,$j$]} and \kbd{$x$[$i$,]} respectively return the entry of coordinates $(i,j)$, the $j$-th column, and the $i$-th row of matrix $x$. If the assignment operator (\kbd{=}) immediately follows a sequence of selections, it assigns its right hand side to the selected component. E.g \kbd{x[1][1] = 0} is valid; but beware that \kbd{(x[1])[1] = 0} is not (because the parentheses force the complete evaluation of \kbd{x[1]}, and the result is not modifiable). \point{Priority 10} % \kbd{'} (unary, postfix): derivative with respect to the main variable. If $f$ is a function (\typ{CLOSURE}), $f'$ is allowed and defines a new function, which will perform \idx{numerical derivation} when evaluated at a scalar $x$; this is defined as $(f(x+\varepsilon) - f(x-\varepsilon)) / 2\varepsilon$ for a suitably small epsilon depending on current precision. \bprog ? (x^2 + y*x + y^2)' \\@com derive with respect to main variable \kbd{x} %1 = 2*x + y ? SIN = cos' %2 = cos' ? SIN(Pi/6) \\@com numerical derivation %3 = -0.5000000000000000000000000000 ? cos'(Pi/6) \\@com works directly: no need for intermediate \kbd{SIN} %4 = -0.5000000000000000000000000000 @eprog \strut\kbd{\til} (unary, postfix): vector/matrix transpose. \kbd{!} (unary, postfix): factorial. $x\kbd{!}=x(x-1)\cdots 1$. \kbd{!} (unary, prefix): logical \var{not}. \kbd{!$x$} returns $1$ if $x$ is equal to $0$ (specifically, if \kbd{gequal0($x$)==1}), and $0$ otherwise. \point{Priority 9} % \kbd{\#} (unary, prefix): cardinality; \kbd{\#$x$} returns \kbd{length($x$)}. \point{Priority 8} % \kbd{\pow}: powering. This operator is right associative: \kbd{2 \pow 3\pow 4} is understood as \kbd{2 \pow (3\pow 4)}. \point{Priority 7} % \kbd{+}, \kbd{-} (unary, prefix): \kbd{-} toggles the sign of its argument, \kbd{+} has no effect whatsoever. \point{Priority 6} % \kbd{*}: multiplication. \kbd{/}: exact division (\kbd{3/2} yields $3/2$, not $1.5$). \kbd{\bs}, \kbd{\%}: Euclidean quotient and remainder, i.e.~if $x = qy + r$, then $\kbd{x \b{ } y} = q$, $\kbd{x\%y} = r$. If $x$ and $y$ are scalars, then $q$ is an integer and $r$ satisfies $0\le r < y$; if $x$ and $y$ are polynomials, then $q$ and $r$ are polynomials such that $\deg r< \deg y$ and the leading terms of $r$ and $x$ have the same sign. \kbd{\bs/}: rounded Euclidean quotient for integers (rounded towards $+\infty$ when the exact quotient would be a half-integer). \kbd{<<}, \kbd{>>}: left and right binary shift. By definition, \kbd{x<0$, and $\kbd{truncate}(x 2^{-n})$ otherwise. Right shift is defined by \kbd{x>>n}$~=~$\kbd{x<<(-n)}. \point{Priority 5} % \kbd{+}, \kbd{-}: addition/subtraction. \point{Priority 4} % \kbd{<}, \kbd{>}, \kbd{<=}, \kbd{>=}: the usual comparison operators, returning 1 for \kbd{true} and 0 for \kbd{false}. For instance, \kbd{x<=1} returns $1$ if $x\le 1$ and $0$ otherwise. \kbd{<>}, \kbd{!=}: test for (exact) inequality. \kbd{==}: test for (exact) equality. \typ{QFR} having the same coefficients but a different distance component are tested as equal. \kbd{===}: test whether two objects are identical component-wise. This is stricter than \kbd{==}: for instance, the integer 0, a 0 polynomial or a vector with 0 entries, are all tested equal by \kbd{==}, but they are not identical. \point{Priority 3} % \kbd{\&\&}: logical \var{and}. \kbd{||}: logical (inclusive) \var{or}. Any sequence of logical \var{or} and \var{and} operations is evaluated from left to right, and aborted as soon as the final truth value is known. Thus, for instance, \bprog x == 0 || test(1/x) @eprog\noindent will never produce an error since \kbd{test(1/x)} is not even evaluated when the first test is true (hence the final truth value is true). Similarly \bprog type(p) == "t_INT" && isprime(p) @eprog\noindent does not evaluate \kbd{isprime(p)} if \kbd{p} is not an integer. \point{Priority 2} % \kbd{=} (assignment, \var{lvalue} \kbd{=} \var{expr}). The result of \kbd{x~=~$y$} is the value of the expression~$y$, which is also assigned to the variable~\kbd{x}. This assignment operator is right-associative. This is \emph{not} the equality test operator; a statement like \kbd{x~=~1} is always true (i.e.~non-zero), and sets \kbd{x} to~1; the equality test would be \kbd{x == 1}. The right hand side of the assignment operator is evaluated before the left hand side. It is crucial that the left hand-side be an \var{lvalue} there, it avoids ambiguities in expressions like \kbd{1 + x = 1}. The latter evaluates as \kbd{1 + (x = 1)}, not as \kbd{(1 + x) = 1}, even though the priority of \kbd{=} is lower than the priority of \kbd{+}: \kbd{1 + x} is not an lvalue. 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 *** ^-- @eprog \leavevmode \kbd{\var{op}=}, where \var{op} is any binary operator among \kbd{+}, \kbd{-}, \kbd{*}, \kbd{\%}, \kbd{/}, \kbd{\bs}, \kbd{\bs/}, \kbd{<<}, or \kbd{>>} (composed assignment \var{lvalue} \var{op}\kbd{=} \var{expr}). The expression \kbd{x~\var{op}=~$y$} assigns $(\kbd{x}~\var{op}~y)$ to~\kbd{x}, and returns the new value of~\kbd{x}. The result is \emph{not} an \tev{lvalue}; thus \bprog (x += 2) = 3 @eprog\noindent is invalid. These assignment operators are right-associative: \bprog ? x = 'x; x += x *= 2 %1 = 3*x @eprog \point{Priority 1} \kbd{->} (function definition): \kbd{(\var{vars})->\var{expr}} returns a function object, of type \typ{CLOSURE}. \misctitle{Remark} Use the \var{op}\kbd{=} operators as often as possible since they make complex assignments more legible: one needs not parse complicated expressions twice to make sure they are indeed identical. Compare \bprog v[i+j-1] = v[i+j-1] + 1 --> v[i+j-1]++ M[i,i+j] = M[i,i+j] * 2 --> M[i,i+j] *= 2 @eprog \misctitle{Remark} Less important but still interesting. The \kbd{++}, \kbd{--} and \var{op}\kbd{=} operators are slightly more efficient: \bprog ? a = 10^6; ? i = 0; while(i n, return(failure)); @eprog\noindent is incorrect, since the value of $i$ tested by the $(i > n)$ is quite unrelated to the loop index. One ugly workaround is \bprog for(i = 1, n, if (ok(i), isave = i; break); ); if (isave > n, return(failure)); @eprog\noindent But it is usually more natural to wrap the loop in a user function and use \kbd{return} instead of \kbd{break}: \bprog try() = { for(i = 1, n, if (ok(i), return (i)); ); 0 \\ failure } @eprog A list of variables can be lexically or dynamically scoped (to the block between the declaration and the end of the innermost enclosing scope) using a \kbd{my} or \kbd{local} declaration: \bprog for (i = 1, 10, my(x, y, z, i2 = i^2); \\ temps needed within the loop body ... ) @eprog\noindent Note how the declaration can include (optional) initial values, \kbd{i2 = i\pow 2} in the above. Variables for which no explicit default value is given in the declaration are initialized to $0$. It would be more natural to initialize them to free variables, but this would break backward compatibility. To obtain this behavior, you may explicitly use the quoting operator: \bprog my(x = 'x, y = 'y, z = 'z); @eprog\noindent A more complicated example: \bprog for (i = 1, 3, print("main loop"); my(x = i); \\ local to the outermost loop for (j = 1, 3, my (y = x^2); \\ local to the innermost loop print (y + y^2); x++; ) ) @eprog\noindent When we leave the loops, the values of \kbd{x}, \kbd{y}, \kbd{i}, \kbd{j} are the same as before they were started. Note that \tet{eval} is evaluated in the given scope, and can access values of lexical variables: \bprog ? x = 1; ? my(x = 0); eval("x") %2 = 0 \\@com we see the local \kbd{x} scoped to this command line, not the global one @eprog Variables dynamically scoped using \kbd{local} should more appropriately be called \emph{temporary values} since they are in fact local to the function declaring them \emph{and} any subroutine called from within. In practice, you almost certainly want true private variables, hence should use almost exclusively \kbd{my}. We strongly recommended to explicitly scope (lexically) all variables to the smallest possible block. Should you forget this, in expressions involving such ``rogue'' variables, the value used will be the one which happens to be on top of the value stack at the time of the call; which depends on the whole calling context in a non-trivial way. This is in general \emph{not} what you want. \section{User defined functions}\sidx{user defined functions} \label{se:user_defined} The most important thing to understand about user-defined functions is that they are ordinary GP objects, bound to variables just like any other object. Those variables are subject to scoping rules as any other: while you can define all your functions in global scope, it is usually possible and cleaner to lexically scope your private helper functions to the block of text where they will be needed. Whenever gp meets a construction of the form \kbd{expr(\var{argument list})} and the expression \kbd{expr} evaluates to a function (an object of type \typ{CLOSURE}), the function is called with the proper arguments. For instance, constructions like \kbd{funcs[i](x)} are perfectly valid, assuming \kbd{funcs} is an array of functions. \subsec{Defining a function}\label{se:userfundef} A user function is defined as follows: \kbd{(\var{list of formal variables}) -> \var{seq}}. \noindent The list of formal variables is a comma-separated list of \emph{distinct} variable names and allowed to be empty. It there is a single formal variable, the parentheses are optional. This list corresponds to the list of parameters you will supply to your function when calling it. In most cases you want to assign a function to a variable immediately, as in \bprog R = (x,y) -> sqrt( x^2+y^2 ); sq = x -> x^2; \\@com or equivalently \kbd{(x) -> x\pow2} @eprog\noindent but it is quite possible to define (a priori short-lived) anonymous functions. The trailing semicolon is not part of the definition, but as usual prevents \kbd{gp} from printing the result of the evaluation, i.e. the function object. The construction \kbd{f(\var{list of formal variables}) = \var{seq}} \noindent is available as an alias for \kbd{f = (\var{list of formal variables}) -> \var{seq}} \noindent Using that syntax, it is not possible to define anonymous functions (obviously), and the above two examples become: \bprog R(x,y) = sqrt( x^2+y^2 ); sq(x) = x^2; @eprog\noindent The semicolon serves the same purpose as above: preventing the printing of the resulting function object; compare \bprog ? sq(x) = x^2; \\@com no output ? sq(x) = x^2 \\@com print the result: a function object %2 = (x)->x^2 @eprog\noindent Of course, the sequence \var{seq} can be arbitrarily complicated, in which case it will look better written on consecutive lines, with properly scoped variables: \bprogpart { f($x_0$, $x_1$, @dots) = my($t_0$, $t_1$, @dots); \\@com variables lexically scoped to the function body @dots } @eprog \noindent Note that the following variant would also work: \bprogpart f($x_0$, $x_1$, @dots) = { my($t_0$, $t_1$, @dots); \\@com variables lexically scoped to the function body @dots } @eprog \noindent (the first newline is disregarded due to the preceding \kbd{=} sign, and the others because of the enclosing braces). The \tet{my} statements can actually occur anywhere within the function body, scoping the variables to more restricted blocks than the whole function body. Arguments are passed by value, not as variables: modifying a function's argument in the function body is allowed, but does not modify its value in the calling scope. In fact, a \emph{copy} of the actual parameter is assigned to the formal parameter when the function is called. Formal parameters are lexically scoped to the function body. It is not allowed to use the same variable name for different parameters of your function: \bprog ? f(x,x) = 1 *** variable declared twice: f(x,x)=1 *** ^---- @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}} will print the definition of the function \var{name}: the list of arguments, as well as their default values, the text of \var{seq} as you input it. Just as \b{c} prints the list of all built-in commands, \b{u} outputs the list of all user-defined functions. \misctitle{Backward compatibility (lexical scope)} Lexically scoped variables were introduced in version~2.4.2. Before that, the formal parameters were dynamically scoped. If your script depends on this behavior, you may use the following trick: replace the initial \kbd{f(x) =} \ by \bprog f(x_orig) = local(x = x_orig) @eprog \misctitle{Backward compatibility (disjoint namespaces)} Before version 2.4.2, variables and functions lived in disjoint namespaces and it was not possible to have a variable and a function share the same name. Hence the need for a \kbd{kill} function allowing to reuse symbols. This is no longer the case. There is now no distinction between variable and function names: we have PARI objects (functions of type \typ{CLOSURE}, or more mundane mathematical entities, like \typ{INT}, etc.) and variables bound to them. There is nothing wrong with the following sequence of assignments: \bprog ? f = 1 \\@com assigns the integer 1 to \kbd{f} %1 = 1; ? f() = 1 \\@com a function with a constant value %2 = ()->1 ? f = x^2 \\@com \kbd{f} now holds a polynomial %3 = x^2 ? f(x) = x^2 \\@com \dots and now a polynomial function %4 = (x)->x^2 ? g(fun) = fun(Pi);\\@com a function taking a function as argument ? g(cos) %6 = -1.000000000000000000000000000 @eprog\noindent Previously used names can be recycled as above: you are just redefining the variable. The previous definition is lost of course. \misctitle{Important technical note} Built-in functions are a special case since they are read-only (you cannot overwrite their default meaning), and they use features not available to user functions, in particular pointer arguments. In the present version \vers{}, it is possible to assign a built-in function to a variable, or to use a built-in function name to create an anonymous function, but some special argument combinations may not be available: \bprog ? issquare(9, &e) %1 = 1 ? e %2 = 3 ? g = issquare; ? g(9) %4 = 1 ? g(9, &e) \\@com pointers are not implemented for user functions *** unexpected &: g(9,&e) *** ^--- @eprog \subsec{Function call, Default arguments} You may now call your function, as in \kbd{f(1,2)}, supplying values for the formal variables. The number of parameters actually supplied may be \emph{less} than the number of formal variables in the function definition. An uninitialized formal variable is given an implicit default value of (the integer)~0, i.e. after the definition \bprog f(x, y) = ... @eprog\noindent you may call \kbd{f(1, 2)}, supplying values for the two formal parameters, or for example \settabs\+\indent&xxxxxxxxx& equivalent to xxxx &\cr \+& \kbd{f(2)} & equivalent to &\kbd{f(2,0)},\cr \+& \kbd{f()} & & \kbd{f(0,0)},\cr \+& \kbd{f(,3)} & &\kbd{f(0,3)}. (``Empty argument'' trick)\cr \noindent This \emph{implicit} default value of $0$, is actually deprecated and setting \bprog default(strictargs, 1) @eprog\noindent allows to disable it (see \secref{se:def,strictargs}).\kbdsidx{strictargs} The recommended practice is to \emph{explicitly} set a default value: in the function definition, you can append \kbd{=}\var{expr} to a formal parameter, to give that variable a default value. The expression gets evaluated the moment the function is called, and may involve the preceding function parameters: a default value for $x_i$ may involve $x_j$ for $j < i$. For instance, after \bprog f(x = 1, y = 2, z = y+1) = .... @eprog\noindent typing in \kbd{f(3,4)} would give you \kbd{f(3,4,5)}. In the rare case when you want to set some far away argument, and leave the defaults in between as they stand, use the ``empty argument'' trick: \kbd{f(6,,1)} would yield \kbd{f(6,2,1)}. Of course, \kbd{f()} by itself yields \kbd{f(1,2,3)} as was to be expected. In short, the argument list is filled with user supplied values, in order. A comma or closing parenthesis, where a value should have been, signals we must use a default value. When no input arguments are left, the defaults are used instead to fill in remaining formal parameters. A final example: \bprog f(x, y=2, z=3) = print(x, ":", y, ":", z); @eprog \noindent defines a function which prints its arguments (at most three of them), separated by colons. \bprog ? f(6,7) 6:7:3 ? f(,5) 0:5:3 ? f() 0:2:3 @eprog\noindent If \kbd{strictargs} is set (recommended), $x$ is now a mandatory argument, and the above becomes: \bprog ? default(strictargs,1) ? f(6,7) 6:7:3 ? f(,5) *** at top-level: f(,5) *** ^----- *** in function f: x,y=2,z=3 *** ^--------- *** missing mandatory argument 'x' in user function. @eprog \misctitle{Example} We conclude with an amusing example, intended to illustrate both user-defined functions and the power of the \kbd{sumalt} function. Although the \idx{Riemann zeta-function} is included (as \kbd{zeta}) among the standard functions, let us assume that we want to check other implementations. Since we are highly interested in the critical strip, we use the classical formula $$ (2^{1-s} - 1)\zeta(s) = \sum_{n\geq 1} (-1)^n n^{-s}, \qquad\Re s > 0.$$ The implementation is obvious:\sidx{zeta function} \bprog ZETA(s) = sumalt(n=1, (-1)^n*n^(-s)) / (2^(1-s) - 1) @eprog \noindent Note that \kbd{n} is automatically lexically scoped to the \kbd{sumalt} ``loop'', so that it is unnecessary to add a \kbd{my(n)} declaration to the function body. Surprisingly, this gives very good accuracy in a larger region than expected: \bprog ? check = z -> ZETA(z) / zeta(z); ? check(2) %1 = 1.000000000000000000000000000 ? check(200) %2 = 1.000000000000000000000000000 ? check(0) %3 = 0.9999999999999999999999999994 ? check(-5) %4 = 1.00000000000000007549266557 ? check(-11) %5 = 0.9999752641047824902660847745 ? check(1/2+14.134*I) \\@com very close to a non-trivial zero %6 = 1.000000000000000000003747432 + 7.62329066 E-21*I ? check(-1+10*I) %7 = 1.000000000000000000000002511 + 2.989950968 E-24*I @eprog\noindent Now wait a minute; not only are we summing a series which is certainly no longer alternating (it has complex coefficients), but we are also way outside of the region of convergence, and still get decent results! No programming mistake this time: \kbd{sumalt} is a ``magic'' function\footnote{*}{\kbd{sumalt} is heuristic, but its use can be rigorously justified for a given function, in particular our $\zeta(s)$ formula. Indeed, Peter Borwein (\emph{An efficient algorithm for the Riemann zeta function}, CMS Conf.~Proc.~{\bf 27} (2000), pp.~29--34) proved that the formula used in \kbd{sumalt} with $n$ terms computes $(1-2^{1-s})\zeta(s)$ with a relative error of the order of $(3+\sqrt{8})^{-n}|\Gamma(s)|^{-1}$.}, providing very good convergence acceleration; in effect, we are computing the analytic continuation of our original function. To convince ourselves that \kbd{sumalt} is a non-trivial implementation, let us try a simpler example: \bprog ? sum(n=1, 10^7, (-1)^n/n, 0.) / (-log(2)) \\@com approximates the well-known formula time = 7,417 ms. %1 = 0.9999999278652515622893405457 ? sumalt(n=1, (-1)^n/n) / (-log(2)) \\@com accurate and fast time = 0 ms. %2 = 1.000000000000000000000000000 @eprog\noindent No, we are not using a powerful simplification tool here, only numerical computations. Remember, PARI is not a computer algebra system! \subsec{Beware scopes}\label{se:bewarescope} Be extra careful with the scopes of variables. What is wrong with the following definition? \bprog FirstPrimeDiv(x) = { my(p); forprime(p=2, x, if (x%p == 0, break)); p } ? FirstPrimeDiv(10) %1 = 0 @eprog\noindent \misctitle{Hint} The function body is equivalent to \bprog { my(newp = 0); forprime(p=2, x, if (x%p == 0, break)); newp } @eprog\noindent \misctitle{Detailed explanation} The index \kbd{p} in the \kbd{forprime} loop is lexically scoped to the loop and is not visible to the outside world. Hence, it will not survive the \kbd{break} statement. More precisely, at this point the loop index is restored to its preceding value. The initial \kbd{my(p)}, although well-meant, adds to the confusion: it indeed scopes \kbd{p} to the function body, with initial value $0$, but the \kbd{forprime} loop introduces \emph{another} variable, unfortunately also called \kbd{p}, scoped to the loop body, which shadows the one we wanted. So we always return $0$, since the value of the \kbd{p} scoped to the function body never changes and is initially $0$. To sum up, the routine returns the \kbd{p} declared local to it, not the one which was local to \kbd{forprime} and ran through consecutive prime numbers. Here is a corrected version: \bprog ? FirstPrimeDiv(x) = forprime(p=2, x, if (x%p == 0, return(p))) @eprog \subsec{Recursive functions} Recursive functions\sidx{recursion} can easily be written as long as one pays proper attention to variable scope. Here is an example, used to retrieve the coefficient array of a multivariate polynomial (a non-trivial task due to PARI's unsophisticated representation for those objects): \sidx{multivariate polynomial} \bprog coeffs(P, nbvar) = { if (type(P) != "t_POL", for (i=1, nbvar, P = [P]); return (P) ); vector(poldegree(P)+1, i, coeffs(polcoeff(P, i-1), nbvar-1)) } @eprog \noindent If $P$ is a polynomial in $k$ variables, show that after the assignment {\tt v = coeffs(P,k)}, the coefficient of $x_1^{n_1}\dots x_k^{n_k}$ in P is given by {\tt v[$n_1$+1][\dots][$n_k$+1]}. The operating system automatically limits the \idx{recursion depth}: \sidx{deep recursion} \bprog ? dive(n) = dive(n+1) ? dive(0); *** [...] at: dive(n+1) *** ^--------- *** in function dive: dive(n+1) *** ^--------- \\@com (last 2 lines repeated 19 times) *** deep recursion. @eprog\noindent There is no way to increase the recursion limit (which may be different on your machine) from within \kbd{gp}. To increase it before launching \kbd{gp}, you can use \tet{ulimit} or \tet{limit}, depending on your shell, and raise the process available stack space (increase \tet{stacksize}). \subsec{Function which take functions as parameters} This is done as follows: \bprog ? calc(f, x) = f(x) ? calc(sin, Pi) %2 = -5.04870979 E-29 ? g(x) = x^2; ? calc(g, 3) %4 = 9 @eprog \noindent If we do not need \kbd{g} elsewhere, we should use an anonymous function here, \kbd{calc(x->x\pow 2, 3)}. Here is a variation: \bprog ? funs = [cos, sin, tan, x->x^3+1]; \\@com an array of functions ? call(i, x) = funs[i](x) @eprog\noindent evaluates the appropriate function on argument \kbd{x}, provided $1\leq i\leq 4$. Finally, a more useful example: \bprog APPLY(f, v) = vector(#v, i, f(v[i])) @eprog\noindent applies the function \kbd{f} to every element in the vector \kbd{v}. (The built-in function \kbd{apply} is more powerful since it also applies to lists and matrices.) \subsec{Defining functions within a function} Defining a single function is easy: \bprog init(x) = (add = y -> x+y); @eprog\noindent Basically, we are defining a global variable \kbd{add} whose value is the function \kbd{y->x+y}. The parentheses were added for clarity and are not mandatory. \bprog ? init(5); ? add(2) %2 = 7 @eprog\noindent A more refined approach is to avoid global variables and \emph{return} the function: \bprog init(x) = y -> x+y add = init(5) @eprog\noindent Then \kbd{add(2)} still returns 7, as expected! Of course, if \kbd{add} is in global scope, there is no gain, but we can lexically scope it to the place where it is useful: \bprog my ( add = init(5) ); @eprog How about multiple functions then? We can use the last idea and return a vector of functions, but if we insist on global variables? The first idea \bprog init(x) = add(y) = x+y; mul(y) = x*y; @eprog \noindent does not work since in the construction \kbd{f() = }\var{seq}, the function body contains everything until the end of the expression. Hence executing \kbd{init} defines the wrong function \kbd{add} (itself defining a function \kbd{mul}). The way out is to use parentheses for grouping, so that enclosed subexpressions will be evaluated independently: \bprog ? init(x) = ( add(y) = x+y ); ( mul(y) = x*y ); ? init(5); ? add(2) %3 = 7 ? mul(3) %4 = 15 @eprog\noindent This defines two global functions which have access to the lexical variables private to \kbd{init}! The following would work in exactly the same way: \bprog ? init5() = my(x = 5); ( add(y) = x+y ); ( mul(y) = x*y ); @eprog \subsec{Closures as Objects} Contrary to what you might think after the preceding examples, GP's closures may not be used to simulate true ``objects'', with private and public parts and methods to access and manipulate them. In fact, closures indeed incorporate an existing context (they may access lexical variables that existed at the time of their definition), but then may not change it. More precisely, they access a copy, which they are welcome to change, but a further function call still accesses the original context, as it existed at the time the function was defined: \bprog init() = { my(count = 0); inc()=count++; dec()=count--; } ? inc() %1 = 1 ? inc() %2 = 1 ? inc() %3 = 1 @eprog \section{Member functions}\sidx{member functions} \label{se:member} Member functions use the `dot' notation to retrieve information from complicated structures. The built-in structures are \tev{bid}, \tev{ell}, \tev{galois}, \tev{ff}, \tev{nf}, \tev{bnf}, \tev{bnr} and \tev{prid}, which will be described at length in Chapter~3. The syntax \kbd{structure.member} is taken to mean: retrieve \kbd{member} from \kbd{structure}, e.g.~\kbd{E.j} returns the $j$-invariant of the elliptic curve \kbd{E}, or outputs an error message if \kbd{E} is not a proper \tev{ell} structure. To define your own member functions, use the syntax \ \kbd{\var{var}.\var{member} = \var{seq}}, \noindent where the formal variable \var{var} is scoped to the function body \var{seq}. This is of course reminiscent of a user function with a single formal variable \var{var}. For instance, the current implementation of the \kbd{ell} type is a vector, the $j$-invariant being the thirteenth component. It could be implemented as \bprog x.j = { if (type(x) != "t_VEC" || #x < 14, error("not an elliptic curve: " x)); x[13] } @eprog\noindent As for user functions, you can redefine your member functions simply by typing new definitions. On the other hand, as a safety measure, you cannot redefine the built-in member functions, so attempting to redefine \kbd{x.j} as above would in fact produce an error; you would have to call it e.g.~\kbd{x.myj} in order for \kbd{gp} to accept it. \misctitle{Rationale} In most cases, member functions are simple accessors of the form \bprog x.a = x[1]; x.b = x[2]; x.c = x[3]; @eprog\noindent where \kbd{x} is a vector containing relevant data. There are at least three alternative approaches to the above member functions: 1) hardcode \kbd{x[1]}, etc. in the program text, 2) define constant global variables \kbd{AINDEX = 1}, \kbd{BINDEX = 2} and hardcode \kbd{x[AINDEX]}, 3) user functions \kbd{a(x) = x[1]} and so on. Even if 2) improves on 1), these solutions are neither elegant nor flexible, and they scale badly. 3) is a genuine possibility, but the main advantage of member functions is that their namespace is independent from the variables (and functions) namespace, hence we can use very short identifiers without risk. The $j$-invariant is a good example: it would clearly not be a good idea to define \kbd{j(E) = E[13]}, because clashes with loop indices are likely. \misctitle{Note} Typing \b{um} will output all user-defined member functions. \misctitle{Member function names} A valid name starts with a letter followed by any number of keyword characters: \kbd{\_} or alphanumeric characters ([\kbd{A-Za-z0-9}]). The built-in member function names are reserved and cannot be used (see the list with \kbd{?.}). Finally, names starting with \kbd{e} or \kbd{E} followed by a digit are forbidden, due to a clash with the floating point exponent notation: we understand \kbd{1.e2} as $100.000\dots$, not as extracting member \kbd{e2} of object \kbd{1}. \section{Strings and Keywords}\sidx{string}\sidx{keyword} \label{se:strings} \subsec{Strings} GP variables can hold values of type character string (internal type \typ{STR}). This section describes how they are actually used, as well as some convenient tricks (automatic concatenation and expansion, keywords) valid in string context. As explained above, the general way to input a string is to enclose characters between quotes~\kbd{"}. This is the only input construct where whitespace characters are significant: the string will contain the exact number of spaces you typed in. Besides, you can ``escape'' characters by putting a \kbd{\bs} just before them; the translation is as follows \bprog \e: \n: \t: @eprog For any other character $x$, \b{$x$} is expanded to $x$. In particular, the only way to put a \kbd{"} into a string is to escape it. Thus, for instance, \kbd{"\bs"a\bs""} would produce the string whose content is ``a''. This is definitely \emph{not} the same thing as typing \kbd{"a"}, whose content is merely the one-letter string a. You can concatenate two strings using the \tet{concat} function. If either argument is a string, the other is automatically converted to a string if necessary (it will be evaluated first). \bprog ? concat("ex", 1+1) %1 = "ex2" ? a = 2; b = "ex"; concat(b, a) %2 = "ex2" ? concat(a, b) %3 = "2ex" @eprog Some functions expect strings for some of their arguments: \tet{print} would be an obvious example, \tet{Str} is a less obvious but useful one (see the end of this section for a complete list). While typing in such an argument, you will be said to be in \tev{string context}. The rest of this section is devoted to special syntactical tricks which can be used with such arguments (and only here; you will get an error message if you try these outside of string context): \item Writing two strings alongside one another will just concatenate them, producing a longer string. Thus it is equivalent to type in \kbd{"a " "b"} or \kbd{"a b"}. A little tricky point in the first expression: the first whitespace is enclosed between quotes, and so is part of a string; while the second (before the \kbd{"b"}) is completely optional and \kbd{gp} actually suppresses it, as it would with any number of whitespace characters at this point (i.e.~outside of any string). \item If you insert any expression when a string is expected, it gets ``expanded'': it is evaluated as a standard GP expression, and the final result (as would have been printed if you had typed it by itself) is then converted to a string, as if you had typed it directly. For instance \kbd{"a" 1+1 "b"} is equivalent to \kbd{"a2b"}: three strings get created, the middle one being the expansion of \kbd{1+1}, and these are then concatenated according to the rule described above. Another tricky point here: assume you did not assign a value to \kbd{aaa} in a GP expression before. Then typing \kbd{aaa} by itself in a string context will actually produce the correct output (i.e.~the string whose content is aaa), but in a fortuitous way. This \kbd{aaa} gets expanded to the monomial of degree one in the variable \kbd{aaa}, which is of course printed as \kbd{aaa}, and thus will expand to the three letters you were expecting. \misctitle{Warning} Expression involving strings are not handled in a special way; even in string context, the largest possible expression is evaluated, hence \kbd{print("a"[1])} is incorrect since \kbd{"a"} is not an object whose first component can be extracted. On the other hand \kbd{print("a", [1])} is correct (two distinct argument, each converted to a string), and so is \kbd{print("a" 1)} (since \kbd{"a"1} is not a valid expression, only \kbd{"a"} gets expanded, then \kbd{1}, and the result is concatenated as explained above). \subsec{Keywords} Since there are cases where expansion is not desirable, we now distinguish between ``Keywords'' and ``Strings''. String is what has been described so far. Keywords are special relatives of Strings which are automatically assumed to be quoted, whether you actually type in the quotes or not. Thus expansion is never performed on them. They get concatenated, though. The analyzer supplies automatically the quotes you have ``forgotten'' and treats Keywords just as normal strings otherwise. For instance, if you type \kbd{"a"b+b} in Keyword context, you will get the string whose contents are ab+b. In String context, on the other hand, you would get a2\kbd{*}b. All GP functions have prototypes (described in Chapter~3 below) which specify the types of arguments they expect: either generic PARI objects (GEN), or strings, or keywords, or unevaluated expression sequences. In the keyword case, only a very small set of words will actually be meaningful (the \kbd{default} function is a prominent example). \misctitle{Reference} The arguments of the following functions are processed in string context: \settabs\+\indent&\cr \+&\tet{Str}\cr \+&\tet{addhelp} (second argument)\cr \+&\tet{default} (second argument)\cr \+&\tet{error}\cr \+&\tet{extern}\cr \+&\tet{plotstring} (second argument)\cr \+&\tet{plotterm} (first argument)\cr \+&\tet{read} and \tet{readvec}\cr \+&\tet{system}\cr \+&all the \tet{print}\var{xxx} functions\cr \+&all the \tet{write}\var{xxx} functions\cr \noindent The arguments of the following functions are processed as keywords: \+&\tet{alias}\cr \+&\tet{default} (first argument)\cr \+&\tet{install} (all arguments but the last)\cr \+&\tet{trap} (first argument)\cr \+&\tet{whatnow}\cr \subsec{Useful examples} The function \kbd{Str} converts its arguments into strings and concatenate them. Coupled with \tet{eval}, it is very powerful. The following example creates generic matrices\sidx{generic matrix}\sidx{matrix}: \bprog ? genmat(u,v,s="x") = matrix(u,v,i,j, eval( Str(s,i,j) )) ? genmat(2,3) + genmat(2,3,"m") %1 = [x11 + m11 x12 + m12 x13 + m13] [x21 + m21 x22 + m22 x23 + m23] @eprog\noindent Two last examples: \kbd{hist(10,20)} returns all \idx{history} entries from \kbd{\%10} to \kbd{\%20} neatly packed into a single vector; \kbd{histlast(10)} returns the last $10$ history entries: \bprog hist(a,b) = vector(b-a+1, i, eval(Str("%", a-1+i))) histlast(n) = vector(n, i, eval(Str("%", %#-i+1))) @eprog \section{Errors and error recovery} \subsec{Errors} Your input program is first compiled to a more efficient 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. When reporting a \emph{syntax error}, \kbd{gp} gives meaningful context by copying (part of) the expression it was trying to compile, indicating where the error occurred with a caret \kbd{\pow-}, as in \bprog ? factor() *** too few arguments: factor() *** ^- ? 1+ *** syntax error, unexpected $end: 1+ *** ^- @eprog\noindent possibly enlarged to a full arrow given enough trailing context \bprog ? if (isprime(1+, do_something()) *** syntax error, unexpected ',': if(isprime(1+,do_something())) *** ^---------------- @eprog\noindent These error messages may be mysterious, because \kbd{gp} cannot guess what you were trying to do, and the error may occur once \kbd{gp} has been sidetracked. The first error is straightforward: \kbd{factor} has one mandatory argument, which is missing. The other two are simple typos involving an ill-formed addition \kbd{1 + } missing its second operand. The error messages differ because the parsing context is slightly different: in the first case we reach the end of input (\kbd{\$end}) while still expecting a token, and in the second one, we received an unexpected token (the comma). Here is a more complicated one: \bprog ? factor(x *** syntax error, unexpected $end, expecting )-> or ',' or ')': factor(x *** ^- @eprog\noindent The error is a missing parenthesis, but from \kbd{gp}'s point of view, you might as well have intended to give further arguments to \kbd{factor} (this is possible and useful, see the description of the function). In fact \kbd{gp} expected either a closing parenthesis, or a second argument separated from the first by a comma. And this is essentially what the error message says: we reached the end of the input (\kbd{\$end}) while expecting a \kbd{')'} or a \kbd{','}. Actually, a third possibility is mentioned in the error message \kbd{)->}, which could never be valid in the above context, but a subexpression like \kbd{(x)->sin(x)}, defining an inline closure would be valid, and the parser is not clever enough to rule that out, so we get the same message as in \bprog ? (x *** syntax error, unexpected $end, expecting )-> or ',' or ')': (x *** ^- @eprog\noindent where all three proposed continuations would be valid. \emph{Runtime errors} from the evaluator are nicer because they answer a correctly worded query, otherwise the bytecode compiler would have protested first; here is a slightly pathological case: \bprog ? if (siN(x) < eps, do_something()) *** at top-level: if(siN(x)}). You can type in a \kbd{gp} command, which is evaluated when you hit the \kbd{} key, and the result is printed as during the main \kbd{gp} loop, except that no history of results is kept. Then the break loop prompt reappears and you can type further commands as long as you do not exit the loop. If you are using readline, the history of commands is kept, and line editing is available as usual. If you type in a command that results in an error, you are sent back to the break loop prompt: errors do \var{not} terminate the loop. To get out of a break loop, you can use \tet{next}, \tet{break}, \tet{return}, or type \kbd{C-d} (\kbd{EOF}), any of which will let \kbd{gp} perform its usual cleanup, and send you back to the \kbd{gp} prompt. Note that \kbd{C-d} is slightly dangerous, since typing it \emph{twice} will not only send you back to the \kbd{gp} prompt, but to your shell prompt! (Since \kbd{C-d} at the \kbd{gp} prompt exits the gp session.) If the break loop was started by a user interrupt \kbd{Control-C}, and not by an error, inputting an empty line, i.e hitting the \kbd{} key at the \kbd{break>} prompt, resumes the temporarily interrupted computation. A single empty line has no effect in case of a fatal error, to avoid getting get out of the loop prematurely, thereby losing valuable debugging data. Any of \tet{next}, \tet{break}, \tet{return}, or \kbd{C-d} will abort the computation and send you back to the \kbd{gp} prompt as above. Break loops are useful as a debugging tool. You may inspect the values of \kbd{gp} variables to understand why an error occurred, or change \kbd{gp}'s state in the middle of a computation (increase debugging level, start storing results in a log file, set variables to different values\dots): hit \kbd{C-c}, type in your modifications, then let the computation go on as explained above. A break loop looks like this: \bprog ? v = 0; 1/v *** at top-level: v=0;1/v *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop (type 'break' to go back to the GP prompt) break> @eprog \noindent So the standard error message is printed first. The \kbd{break>} at the bottom is a prompt, and hitting \kbd{v} then \kbd{}, we see: \bprog break> v 0 @eprog\noindent explaining the problem. We could have typed any \kbd{gp} command, not only the name of a variable, of course. Lexically-scoped variables are accessible to the evaluator during the break loop: \bprog ? for(v = -2, 2, print(1/v)) -1/2 -1 *** at top-level: for(v=-2,2,print(1/v)) *** ^---- *** _/_: impossible inverse in gdiv: 0. *** Break loop (type 'break' to go back to the GP prompt) break> v 0 @eprog\noindent Even though loop indices are automatically lexically scoped and no longer exist when the break loop is run, enough debugging information is retained in the bytecode to reconstruct the evaluation context. Of course, when the error occurs in a nested chain of user function calls, lexically scoped variables are available only in the corresponding frame: \bprog ? f(x) = 1/x; ? g(x) = for(i = 1, 10, f(x+i)); ? for(j = -5,5, g(j)) *** at top-level: for(j=-5,5,g(j)) *** ^----- *** in function g: for(i=1,10,f(x+i)) *** ^------- *** in function f: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> [i,j,x] \\ @com the $x$ in $f$'s body. [i, j, 0] break> dbg_up \\ @com go up one frame *** at top-level: for(j=-5,5,g(j)) *** ^----- *** in function g: for(i=1,10,f(x+i)) *** ^------- break> [i,j,x] \\ @com the $x$ in $g$'s body, $i$ in the for loop. [5, j, -5] @eprog The following GP commands are available during a break loop to help debugging: \tet{dbg_up}$(n)$: go up $n$ frames, as seen above. \tet{dbg_down}$(n)$: go down $n$ frames, cancelling previous \kbd{dbg\_up}'s. \tet{dbg_x}$(t)$: examine $t$, as \kbd{\bs x} but more flexible. \tet{dbg_err}$()$: returns the current error context \typ{ERROR}. The error components often provide useful additional information: \bprog ? O(2) + O(3) *** at top-level: O(2)+O(3) *** ^----- *** _+_: inconsistent addition t_PADIC + t_PADIC. *** Break loop: type 'break' to go back to GP prompt break> E = dbg_err() error("inconsistent addition t_PADIC + t_PADIC.") break> Vec(E) ["e_OP", "+", O(2), O(3)] @eprog \misctitle{Note} The debugger is enabled by default, and fires up as soon as a runtime error occurs. If you do not like this behavior, you may disable it by setting the default \tet{breakloop} to 0 in for \kbd{gprc}. A runtime error will send you back to the prompt. Note that the break loop is automatically disabled when running \kbd{gp} in non interactive mode, i.e.~when the program's standard input is not attached to a terminal. \misctitle{Technical Note} When you enter a break loop due to a PARI stack overflow, the PARI stack is reset so that you can run commands. Otherwise the stack would immediately overflow again! Still, as explained above, you do not lose the value of any \kbd{gp} variable in the process. \subsec{Protecting code} The expression \kbd{iferr(\var{statements}, ERR, \var{recovery})} \noindent evaluates and returns the value of \var{statements}, unless an error occurs during the evaluation in which case the value of \var{recovery} is returned. As in an if/else clause, with the difference that \var{statements} has been partially evaluated, with possible side effects. We shall give a lot more details about the \kbd{ERR} argument shortly; it is the name of a variable, lexically scoped to the \var{recovery} expression sequence, whose value is set by the exception handler to help the recovery code decide what to do about the error. For instance one can define a fault tolerant inversion function as follows: \bprog ? inv(x) = iferr(1/x, ERR, "oo") \\ ERR is unused... ? for (i=-1,1, print(inv(i))) -1 oo 1 @eprog\noindent Protected codes can be nested without adverse effect. Let's now see how \kbd{ERR} can be used; as written, \kbd{inv} is too tolerant: \bprog ? inv("blah") %2 = "oo" @eprog Let's improve it by checking that we caught a ``division by 0'' exception, and not an unrelated one like the type error \kbd{1 / "blah"}. \bprog ? inv2(x) = { iferr(1/x, ERR, if (errname(ERR) != "e_INV", error(ERR)); "oo") } ? inv2(0) %3 = "oo" \\ as before ? inv2("blah") *** at top-level: inv2("blah") *** ^------------ *** in function inv2: ...f(errname(ERR)!="e_INV",error(ERR));"oo") *** ^----------------- *** error: forbidden division t_INT / t_STR. @eprog\noindent In the \kbd{inv2("blah")} example, the error type was not expected, so we rethrow the exception: \kbd{error(ERR)} triggers the original error that we mistakenly trapped. Since the recovery code should always check whether the error is the one expected, this construction is very common and can be simplified to \bprog ? inv3(x) = iferr(1/x, ERR, "oo", errname(ERR) == "e_INV") @eprog\noindent More generally \kbd{iferr(\var{statements}, ERR, \var{recovery}, \var{predicate})} \noindent only catches the exception if \var{predicate} (allowed to check various things about \kbd{ERR}, not only its name) is non-zero. Rather than trapping everything, then rethrowing whatever we do not like, we advise to only trap errors of a specific kind, as above. Of course, sometimes, one just want to trap \emph{everything} because we do not know what to expect. The following function check whether \tet{install} works correctly in your \kbd{gp}: \bprog broken_install() = { \\ can we install? iferr(install(addii,GG), ERR, return ("OS")); \\ can we use the installed function? iferr(if (addii(1,1) != 2, return("BROKEN")), ERR, return("USE")); return (0); } @eprog \noindent The function returns \kbd{OS} if the operating system does not support \kbd{install}, \kbd{USE} if using an installed function triggers an error, \kbd{BROKEN} if the installed function did not behave as expected, and 0 if everything works. The \kbd{ERR} formal parameter contains more useful data than just the error name, which we recovered using \kbd{errname(ERR)}. In fact, a \typ{ERROR} object usually has extra components, which can be accessed as \kbd{component(ERR,1)}, \kbd{component(ERR,2)}, and so on. Or globally by casting the error to a \typ{VEC}: \kbd{Vec(ERR)} returns the vector of all components at once. See \secref{se:iferr} for the list of all exception types, and the corresponding contents of \kbd{ERR}. \section{Interfacing GP with other languages} \noindent The PARI library was meant to be interfaced with C programs. This specific use is dealt with extensively in the \emph{User's guide to the PARI library}. Of course, \kbd{gp} itself provides a convenient interpreter to execute rather intricate scripts (see \secref{se:programming}). Scripts, when properly written, tend to be shorter and clearer than C programs, and are certainly easier to write, maintain or debug. You don't need to deal with memory management, garbage collection, pointers, declarations, and so on. Because of their intrinsic simplicity, they are more robust as well. They are unfortunately somewhat slower. Thus their use will remain complementary: it is suggested that you test and debug your algorithms using scripts, before actually coding them in C if speed is paramount. The GP2C compiler often eases this part. The \kbd{install} command (see~\secref{se:install}) efficiently imports foreign functions for use under \kbd{gp}, which can of course be written using other libraries than PARI. Thus you may code only critical parts of your program in C, and still maintain most of the program as a GP script. 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 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 Haible, Marcus Daniels and others; this interface has been updated for pari-2 by Sam Steingold. These provide interfaces to \kbd{gp} functions for use in \kbd{python}, \kbd{perl}, or \kbd{Lisp}\sidx{Perl}\sidx{Python}\sidx{Lisp} programs, respectively. \section{Defaults}\sidx{defaults} \label{se:defaults} \noindent There are many internal variables in \kbd{gp}, defining how the system will behave in certain situations, unless a specific override has been given. Most of them are a matter of basic customization (colors, prompt) and will be set once and for all in your \idx{preferences file} (see \secref{se:gprc}), but some of them are useful interactively (set timer on, increase precision, etc.). The function used to manipulate these values is called \kbd{default}, which is described in \secref{se:default}. The basic syntax is \kbd{default(\var{def}, \var{value})}, \noindent which sets the default \var{def} to \var{value}. In interactive 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}. \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. \misctitle{(somewhat technical) Note} As we saw in \secref{se:strings}, the second argument to \kbd{default} is subject to string context expansion, which means you can use run-time values. In other words, something like \bprog a = 3; default(logfile, "file" a ".log") @eprog logs the output in \kbd{file3.log}. Some special defaults, corresponding to file names and prompts, expand further the resulting value at the time they are set. Two kinds of expansions may be performed: \item \teb{time expansion}: the string is sent through the library function \tet{strftime}. This means that \kbd{\%}\var{char} combinations have a special meaning, usually related to the time and date. For instance, \kbd{\%H} = hour (24-hour clock) and \kbd{\%M} = minute [00,59] (on a Unix system, you can try \kbd{man strftime} at your shell prompt to get a complete list). This is applied to \kbd{prompt}, \kbd{psfile}, and \kbd{logfile}. For instance, \kbd{default(prompt,"(\%H:\%M) ? ")} \noindent will prepend the time of day, in the form \kbd{(\var{hh}:\var{mm})} to \kbd{gp}'s usual prompt. \item \teb{environment expansion}: When the string contains a sequence of the form \kbd{\$\var{SOMEVAR}}, e.g.~\kbd{\$HOME}, the environment is searched and if \var{SOMEVAR} is defined, the sequence is replaced by the corresponding value. Also the \kbd{\til} symbol has the same meaning as in 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 Simple metacommands are meant as shortcuts and should not be used in GP scripts (see \secref{se:programming}). Beware that these, as all of \kbd{gp} input, are \emph{case sensitive}. For example, \b{Q} is not identical to \b{q}. In the following list, braces are used to denote optional arguments, with their default values when applicable, e.g.~$\{n=0\}$ means that if $n$ is not there, it is assumed to be~$0$. Whitespace (or spaces) between the metacommand and its arguments and within arguments is optional. (This can cause problems only with \b{w}, when you insist on having a file name whose first character is a digit, and with \b{r} or \b{w}, if the file name itself contains a space. In such cases, just use the underlying \tet{read} or \tet{write} function; see~\secref{se:write}). \subseckbd{?$\{\var{command}\}$} The \kbd{gp} on-line help interface. If you type \kbd{?$n$} where $n$ is a number from 1 to 11, you will get the list of functions in Section $3.n$ of the manual (the list of sections being obtained by simply typing \kbd{?}). \label{se:exthelp} These names are in general not informative enough. More details can be obtained by typing \kbd{?\var{function}}, which gives a short explanation of the function's calling convention and effects. Of course, to have complete information, read Chapter 3 of this manual (the source code is at your disposal as well, though a trifle less readable). If the line before the copyright message indicates that extended help is available (this means \kbd{perl} is present on your system and the PARI distribution was correctly installed), you can add more \kbd{?} signs for extended functionality: \kbd{??~\var{keyword}} yields the function description as it stands in this manual, usually in Chapter~2 or~3. If you're not satisfied with the default chapter chosen, you can impose a given chapter by ending the keyword with \kbd{@} followed by the chapter number, e.g.~\kbd{??~Hello@2} will look in Chapter~2 for section heading \kbd{Hello} (which doesn't exist, by the way). All operators (e.g.~\kbd{+}, \kbd{\&\&}, etc.) are accepted by this extended help, as well as a few other keywords describing key \kbd{gp} concepts, e.g.~\kbd{readline} (the line editor), \kbd{integer}, \kbd{nf} (``number field'' as used in most algebraic number theory computations), \kbd{ell} (elliptic curves), etc. In case of conflicts between \emph{function} and \emph{default} names (e.g \tet{log}, \tet{simplify}), the function has higher priority. To get the \emph{default} help, use \bprog ?? default(log) ?? default(simplify) @eprog \kbd{???~\var{pattern}} produces a list of sections in Chapter~3 of the manual related to your query. As before, if \var{pattern} ends by \kbd{@} followed by a chapter number, that chapter is searched instead; you also have the option to append a simple \kbd{@} (without a chapter number) to browse through the whole manual. If your query contains dangerous characters (e.g \kbd{?} or blanks) it is advisable to enclose it within double quotes, as for GP strings (e.g \kbd{???~"elliptic curve"}). Note that extended help is much more powerful than the short help, since it knows about operators as well: you can type \kbd{??~*} or \kbd{??~\&\&}, whereas a single \kbd{?} would just yield a not too helpful \bprog &&: unknown identifier.} @eprog\noindent message. Also, you can ask for extended help on section number~$n$ in Chapter~3, just by typing \kbd{??~$n$} (where \kbd{?$n$} would yield merely a list of functions). Finally, a few key concepts in \kbd{gp} are documented in this way: metacommands (e.g \kbd{??~"??"}), defaults (e.g \kbd{??~psfile}) and type names (e.g \typ{INT} or \kbd{integer}), as well as various miscellaneous keywords such as \kbd{edit} (short summary of line editor commands), \kbd{operator}, \kbd{member}, \kbd{"user defined"}, \kbd{nf}, \kbd{ell}, \dots Last but not least: \kbd{??} without argument will open a \kbd{dvi} previewer (\kbd{xdvi} by default, \kbd{\$GPXDVI} if it is defined in your environment) containing the full user's manual. \kbd{??tutorial} and \kbd{??refcard} do the same with the \idx{tutorial} and \idx{reference card} respectively. \misctitle{Technical note} This functionality is provided by an external \kbd{perl} script that you are free to use outside any \kbd{gp} session (and modify to your liking, if you are perl-knowledgeable). It is called \tet{gphelp}, lies in the \kbd{doc} subdirectory of your distribution (just make sure you run \kbd{Configure} first, see Appendix~A) and is really two programs in one. The one which is used from within \kbd{gp} is \kbd{gphelp} which runs \TeX\ on a selected part of this manual, then opens a previewer. \kbd{gphelp -detex} is a text mode equivalent, which looks often nicer especially on a colour-capable terminal (see \kbd{misc/gprc.dft} for examples). The default \kbd{help} selects which help program will be used from within \kbd{gp}. You are welcome to improve this help script, or write new ones (and we would like to know about it so that we may include them in future distributions). By the way, outside of \kbd{gp} you can give more than one keyword as argument to \kbd{gphelp}. \subseckbd{/*...*/} A comment. Everything between the stars is ignored by \kbd{gp}. These comments can span any number of lines. \subseckbd{\bs\bs} A one-line comment. The rest of the line is ignored by \kbd{gp}. \subsec{\b{a} $\{n\}$} Prints the object number $n$ ($\%n$) in raw format. If the number $n$ is omitted, print the latest computed object ($\%$). \label{se:history} \subsec{\b{c}}\sidx{available commands} Prints the list of all available hardcoded functions under \kbd{gp}, not including operators written as special symbols (see \secref{se:operators}). More information can be obtained using the \kbd{?} metacommand (see above). For user-defined functions / member functions, see \b{u} and \b{um}. \subsec{\b{d}} Prints the \idx{defaults} as described in the previous section (shortcut for \kbd{default()}, see \secref{se:default}). \subsec{\b{e} $\{n\}$} Switches the \tet{echo} mode on (1) or off (0). If $n$ is explicitly given, set echo to $n$. \subsec{\b{g} $\{n\}$} Sets the debugging level \tet{debug} to the non-negative integer $n$. \subsec{\b{gf} $\{n\}$} Sets the file usage debugging level \tet{debugfiles} to the non-negative integer $n$. \subsec{\b{gm} $\{n\}$} Sets the memory debugging level \tet{debugmem} to the non-negative integer $n$. \subsec{\b{h} $\{m$\kbd{-}$n\}$} Outputs some debugging info about the hashtable. If the argument is a number $n$, outputs the contents of cell $n$. Ranges can be given in the form $m$\kbd{-}$n$ (from cell $m$ to cell $n$, \$ = last cell). If a function name is given instead of a number or range, outputs info on the internal structure of the hash cell this function occupies (a \kbd{struct entree} in C). If the range is reduced to a dash ('\kbd{-}'), outputs statistics about hash cell usage. \subsec{\b{l} $\{$\var{logfile}$\}$} Switches \tet{log} mode on and off. If a \var{logfile} argument is given, change the default logfile name to \var{logfile} and switch log mode on. \subsec{\b{m}} As \b{a}, but using prettymatrix format. \subsec{\b{o} $\{n\}$} Sets \tet{output} mode to $n$ ($0$: raw, $1$: prettymatrix, $3$: external prettyprint). \subsec{\b{p} $\{n\}$} Sets \tet{realprecision} to $n$ decimal digits. Prints its current value if $n$ is omitted. \subsec{\b{ps} $\{n\}$} Sets \tet{seriesprecision} to $n$ significant terms. Prints its current value if $n$ is omitted. \subsec{\b{q}} Quits the \kbd{gp} session and returns to the system. Shortcut for \tet{quit}\kbd{()} (see \secref{se:quit}). \subsec{\b{r} $\{$\var{filename}$\}$} Reads into \kbd{gp} all the commands contained in the named file as if they had been typed from the keyboard, one line after the other. Can be used in combination with the \b{w} command (see below). Related but not equivalent to the function \kbd{read} (see \secref{se:read}); in particular, if the file contains more than one line of input, there will be one history entry for each of them, whereas \kbd{read} would only record the last one. If \var{filename} is omitted, re-read the previously used input file (fails if no file has ever been successfully read in the current session). If a \kbd{gp} \tet{binary file} (see \secref{se:writebin}) is read using this command, it is silently loaded, without cluttering the history. Assuming \kbd{gp} figures how to decompress files on your machine, this command accepts compressed files in \tet{compress}ed (\kbd{.Z}) or \tet{gzip}ped (\kbd{.gz} or \kbd{.z}) format. They will be uncompressed on the fly as \kbd{gp} reads them, without changing the files themselves. \subsec{\b{s}} Prints the state of the PARI \tev{stack} and \tev{heap}. This is used primarily as a debugging device for PARI. \subsec{\b{t}} Prints the \idx{internal longword format} of all the PARI types. The detailed bit or byte format of the initial codeword(s) is explained in Chapter~4, but its knowledge is not necessary for a \kbd{gp} user. \subsec{\b{u}} Prints the definitions of all user-defined functions. \subsec{\b{um}} Prints the definitions of all user-defined member functions. \subsec{\b{v}} Prints the \idx{version number} and implementation architecture (680x0, Sparc, Alpha, other) of the \kbd{gp} executable you are using. \subsec{\b{w} $\{n\}$ $\{$\var{filename}$\}$} Writes the object number $n$ ( $\%n$ ) into the named file, in raw format. If the number $n$ is omitted, writes the latest computed object ( $\%$ ). If \var{filename} is omitted, appends to \kbd{logfile} (the GP function \tet{write} is a trifle more powerful, as you can have arbitrary file names). \subsec{\b{x} $\{n\}$} Prints the complete tree with addresses and contents (in hexadecimal) of the \idx{internal representation} of the object number $n$ ( $\%n$ ). If the number $n$ is omitted, uses the latest computed object in \kbd{gp}. As for \b{s}, this is used primarily as a debugging device for PARI, and the format should be self-explanatory. The underlying GP function \tet{dbg_x} is more versatile, since it can be applied to other objects than history entries. \subsec{\b{y} $\{n\}$} Switches \kbd{simplify} on (1) or off (0). If $n$ is explicitly given, set simplify to $n$. \subseckbd{\#} Switches the \kbd{timer} on or off. \subseckbd{\#\#} Prints the time taken by the latest computation. Useful when you forgot to turn on the \kbd{timer}. \section{The preferences file}\sidx{startup}\sidx{preferences file} \label{se:gprc} This file, called \tet{gprc} in the sequel, is used to modify or extend \kbd{gp} default behavior, in all \kbd{gp} sessions: e.g customize \kbd{default} values or load common user functions and aliases. \kbd{gp} opens the \kbd{gprc} file and processes the commands in there, \emph{before} doing anything else, e.g.~creating the PARI stack. If the file does not exist or cannot be read, \kbd{gp} will proceed to the initialization phase at once, eventually emitting a prompt. If any explicit command line switches are given, they override the values read from the preferences file. \subsec{Syntax} The syntax in the \kbd{gprc} file (and valid in this file only) is simple-minded, but should be sufficient for most purposes. The file is read line by line; as usual, white space is ignored unless surrounded by quotes and the standard multiline constructions using braces, \kbd{\bs}, or \kbd{=} are available (multiline comments between \kbd{/*~\dots~*/} are also recognized). \subsubsec{Preprocessor:} Two types of lines are first dealt with by a preprocessor: \item comments are removed. This applies to all text surrounded by \kbd{/*~\dots~*/} as well as to everything following \kbd{\bs\bs} on a given line. \item lines starting with \kbd{\#if} \var{boolean} are treated as comments if \var{boolean} evaluates to \kbd{false}, and read normally otherwise. The condition can be negated using either \kbd{\#if not} (or \kbd{\#if !}). If the rest of the current line is empty, the test applies to the next line (same behavior as \kbd{=} under \kbd{gp}). Only three tests can be performed: \kbd{EMACS}: \kbd{true} if \kbd{gp} is running in an Emacs or TeXmacs shell (see \secref{se:emacs}). \kbd{READL}: \kbd{true} if \kbd{gp} is compiled with \kbd{readline} support (see \secref{se:readline}). \kbd{VERSION} \var{op} \var{number}: where \var{op} is in the set $\{ \kbd{>}, \kbd{<}, \kbd{<=}, \kbd{>=} \}$, and \var{number} is a PARI version number of the form \var{Major}.\var{Minor}.\var{patch}, where the 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. \subsubsec{Commands:} After preprocessing, the remaining lines are executed as sequence of expressions (as usual, separated by \kbd{;} if necessary). Only two kinds of expressions are recognized: \item \var{default} \kbd{=} \var{value}, where \var{default} is one of the available defaults (see \secref{se:defaults}), which will be set to \var{value} on actual startup. Don't forget the quotes around strings (e.g.~for \kbd{prompt} or \kbd{help}). \item \kbd{read "\var{some\_GP\_file}"} where \kbd{\var{some\_GP\_file}} is a regular GP script this time, which will be read just before \kbd{gp} prompts you for commands, but after initializing the defaults. In particular, file input is delayed until the \kbd{gprc} has been fully loaded. This is the right place to input files containing \kbd{alias} commands, or your favorite macros. \noindent For instance you could set your prompt in the following portable way: \bprog \\ self modifying prompt looking like @com\hbox{\rm(18:03) \key{gp}\kbd{ >}} prompt = "(%H:%M) \e[1mgp\e[m > " \\ readline wants non-printing characters to be braced between ^A/^B pairs #if READL prompt = "(%H:%M) ^A\e[1m^Bgp^A\e[m^B > " \\ escape sequences not supported under emacs #if EMACS prompt = "(%H:%M) gp > " @eprog \noindent Note that any of the last two lines could be broken in the following way \bprog #if EMACS prompt = "(%H:%M) gp > " @eprog \noindent since the preprocessor directive applies to the next line if the current one is empty. A sample \kbd{gprc} file called \kbd{misc/gprc.dft} is provided in the standard distribution. It is a good idea to have a look at it and customize it to your needs. Since this file does not use multiline constructs, here is one (note the terminating \kbd{;} to separate the expressions): \bprog #if VERSION > 2.2.3 { read "my_scripts"; \\ syntax errors in older versions new_galois_format = 1; \\ default introduced in 2.2.4 } #if ! EMACS { colors = "9, 5, no, no, 4, 1, 2"; help = "gphelp -detex -ch 4 -cb 0 -cu 2"; } @eprog \subsec{The gprc location} When \kbd{gp} is started, it looks for a customization file, or \kbd{gprc} in the following places (in this order, only the first one found will be loaded): \noindent\item \kbd{gp} checks whether the environment variable \tet{GPRC} is set. On Unix, this can be done with something like: \smallskip \settabs\+\indent&\kbd{GPRC=/my/dir/anyname; export GPRC}\quad&\cr \+&\kbd{GPRC=/my/dir/anyname; export GPRC}\quad&in \kbd{sh} syntax (for instance in your \kbd{.profile}),\cr \+&\kbd{setenv GPRC /my/dir/anyname} &in \kbd{csh} syntax (in your \kbd{.login} or \kbd{.cshrc} file).\cr \+&\kbd{env GPRC=/my/dir/anyname gp} &on the command line launching \kbd{gp}.\cr \noindent If so, the file named by \kbd{\$GPRC} is the \kbd{gprc}. \noindent\item If \kbd{GPRC} is not set, and if the environment variable \kbd{HOME} is defined, \kbd{gp} then tries \kbd{\$HOME/.gprc} on a Unix system \kbd{\$HOME\bs gprc.txt} on a DOS, OS/2, or Windows system. \noindent\item If no gprc was found among the user files mentioned above we look for \kbd{/etc/gprc} for a system-wide gprc file (you will need root privileges to set up such a file yourself). \noindent\item Finally, we look in pari's \kbd{datadir} for a file named \kbd{.gprc} on a Unix system \kbd{gprc.txt} on a DOS, OS/2, or Windows system. If you are using our Windows installer, this is where the default preferences file is written. \noindent Note that on Unix systems, the \kbd{gprc}'s default name starts with a '.' and thus is hidden to regular \kbd{ls} commands; you need to type \kbd{ls -a} to list it. \section{Using readline} \sidx{line editor}\sidx{completion} This very useful library provides line editing and contextual completion to \kbd{gp}. You are encouraged to read the \kbd{readline} user manual, but we describe basic usage here. \misctitle{A (too) short introduction to readline}\label{se:readline} In the following, \kbd{C-} stands for ``the \kbd{Control} key combined with another'' and the same for \kbd{M-} with the \kbd{Meta} key; generally \kbd{C-} combinations act on characters, while the \kbd{M-} ones operate on words. The \kbd{Meta} key might be called \kbd{Alt} on some keyboards, will display a black diamond on most others, and can safely be replaced by \kbd{Esc} in any case. Typing any ordinary key inserts text where the cursor stands, the arrow keys enabling you to move in the line. There are many more movement commands, which will be familiar to the Emacs user, for instance \kbd{C-a}/\kbd{C-e} will take you to the start/end of the line, \kbd{M-b}/\kbd{M-f} move the cursor backward/forward by a word, etc. Just press the \kbd{} key at any point to send your command to \kbd{gp}. All the commands you type at the \kbd{gp} prompt are stored in a history, a multiline command being saved as a single concatenated line. The Up and Down arrows (or \kbd{C-p}/\kbd{C-n}) will move you through the history, \kbd{M-<}/\kbd{M->} sending you to the start/end of the history. \kbd{C-r}/\kbd{C-s} will start an incremental backward/forward search. You can kill text (\kbd{C-k} kills till the end of line, \kbd{M-d} to the end of current word) which you can then yank back using the \kbd{C-y} key (\kbd{M-y} will rotate the kill-ring). \kbd{C-\_} will undo your last changes incrementally (\kbd{M-r} undoes all changes made to the current line). \kbd{C-t} and \kbd{M-t} will transpose the character (word) preceding the cursor and the one under the cursor. Keeping the \kbd{M-} key down while you enter an integer (a minus sign meaning reverse behavior) gives an argument to your next readline command (for instance \kbd{M-- C-k} will kill text back to the start of line). If you prefer \idx{Vi}--style editing, \kbd{M-C-j} will toggle you to Vi mode. Of course you can change all these default bindings. For that you need to create a file named \kbd{.inputrc} in your home directory. For instance (notice the embedding conditional in case you would want specific bindings for \kbd{gp}): % \bprog $if Pari-GP set show-all-if-ambiguous "\C-h": backward-delete-char "\e\C-h": backward-kill-word "\C-xd": dump-functions (: "\C-v()\C-b" #@com can be annoying when copy-pasting! [: "\C-v[]\C-b" $endif @eprog \noindent\kbd{C-x C-r} will re-read this init file, incorporating any changes made to it during the current session. \misctitle{Note} By default, \kbd{(} and \kbd{[} are bound to the function \kbd{pari-matched-insert} which, if ``electric parentheses'' are enabled (default: off) will automatically insert the matching closure (respectively \kbd{)} and \kbd{]}). This behavior can be toggled on and off by giving the numeric argument $-2$ to \kbd{(} (\kbd{M--2(}), which is useful if you want, e.g to copy-paste some text into the calculator. If you do not want a toggle, you can use \kbd{M--0} / \kbd{M--1} to specifically switch it on or off). \misctitle{Note} In some versions of readline (2.1 for instance), the \kbd{Alt} or \kbd{Meta} key can give funny results (output 8-bit accented characters for instance). If you do not want to fall back to the \kbd{Esc} combination, put the following two lines in your \kbd{.inputrc}: % \bprog set convert-meta on set output-meta off @eprog \misctitle{Command completion and online help} Hitting \kbd{} will complete words for you. This mechanism is context-dependent: \kbd{gp} will strive to only give you meaningful completions in a given context (it will fail sometimes, but only under rare and restricted 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. If, at any time, only one completion is meaningful, \kbd{gp} will provide it together with \item an ending comma if we are completing a default, \item a pair of parentheses if we are completing a function name. In that case hitting \kbd{} again will provide the argument list as given by the online help\footnote{*}{recall that you can always undo the effect of the preceding keys by hitting \kbd{C-\_}}. Otherwise, hitting \kbd{} once more will give you the list of possible completions. Just experiment with this mechanism as often as possible, you will probably find it very convenient. For instance, you can obtain \kbd{default(seriesprecision,10)}, just by hitting \kbd{defse10}, which saves 18 keystrokes (out of 27). Hitting \kbd{M-h} will give you the usual short online help concerning the word directly beneath the cursor, \kbd{M-H} will yield the extended help corresponding to the \kbd{help} default program (usually opens a \idx{dvi} previewer, or runs a primitive tex-to-ASCII program). None of these disturb the line you were editing. \section{GNU Emacs and PariEmacs} \label{se:emacs} If you install the PariEmacs package (see Appendix A), you may use \kbd{gp} as a subprocess in \idx{Emacs}. You then need to include in your \kbd{.emacs} file the following lines: \bprog (autoload 'gp-mode "pari" nil t) (autoload 'gp-script-mode "pari" nil t) (autoload 'gp "pari" nil t) (autoload 'gpman "pari" nil t) (setq auto-mode-alist (cons '("\\.gp$" . gp-script-mode) auto-mode-alist)) @eprog \noindent which autoloads functions from the PariEmacs package and ensures that file with the \kbd{.gp} suffix are edited in gp-script mode. Once this is done, under GNU Emacs if you type \kbd{M-x gp} (where as usual \kbd{M} is the \kbd{Meta} key), a special shell will be started launching \kbd{gp} with the default stack size and prime limit. You can then work as usual under \kbd{gp}, but with all the facilities of an advanced text editor. See the PariEmacs documentation for customizations, menus, etc. \newpage pari-2.7.5/doc/index.tex0000644000175000017500000000643011636712103013507 0ustar billbill%% %% INDEX (Macros) %% \ifsecondpass\else \condwrite\index{The End} \immediate\condwrite\toc{Index\string\dotfill\the\pageno} \ifPDF \writesecnumbers \fi \expandafter\end % stop here the first time (don't process index) \fi \ifPDF % Add a bookmark entry for the index. CHB \putchapdest \pdfoutline goto name {pdfchap@\the\pdfchapcntr} {Index} \fi \newdimen\fullhsize \fullhsize=\hsize \advance\hsize by -20pt \divide\hsize by 2 \def\fullline{\hbox to\fullhsize} \let\lr=L\newbox\leftcolumn \headline={\hfil\bf Index\hfil\global\headline={\hfil}} \def\makeheadline{\vbox to 0pt{\vskip-22.5pt \fullline{\vbox to8.5pt{}\the\headline}\vss} \nointerlineskip} \def\makefootline{\baselineskip=24pt\fullline{\the\footline}} \output={\if L\lr %cf. The TeXbook, p257 \global\setbox\leftcolumn=\columnbox\global\let\lr=R \else\doubleformat\global\let\lr=L\fi \ifnum\outputpenalty>-20000\else\dosupereject\fi} \def\doubleformat{\shipout\vbox {\makeheadline \fullline{\box\leftcolumn\hfil\columnbox} \makefootline} \advancepageno} \def\columnbox{\leftline{\pagebody}} \def\parse!#1#2!#3!#4!#5 {% \uppercase{\def\theletter{#1}}% \def\theword{#1#2}% \def\thefont{#3}% \def\thepage{#4}% \def\thedest{#5}} \ifPDF %% This puts the hyperlink command in the index, linked to the page %% number. #1 is the usual page number, #2 the pdfcounter. CHB \def\indxjump#1#2{\pdfstartlink attr {/Border [ 0 0 0 ] /H /O} goto name {pdf@#2}\pushcolor{\linkcolor}#1\popcolor\pdfendlink} \else \def\indxjump#1#2{#1} \fi \def\theoldword{} \def\theoldletter{} \def\theoldpage{} \def\theend{The End } % more efficient to parse the glue specs once and keep them in registers % for later use. These govern index lines with too many page numbers to % fit in one line % b: indentation for 2nd and further lines / a: compensation for same, % and shrinkability for the normal word space \newbox\dbox \setbox\dbox=\hbox to 3truemm{\hss.\hss} \newskip\dfillskip \dfillskip=.5em plus .98\hsize \def\dotfill{\leaders\copy\dbox\hskip\dfillskip\relax} \newskip\interskipa \interskipa=-.4\hsize plus -1.5\hsize minus .11em \newskip\interskipb \interskipb= .4\hsize plus 1.5\hsize % cf. The TeXbook, p393: \def\interpage{,\penalty100\kern0.33em%normal space \hskip\interskipa\vadjust{}\penalty10000 \hskip\interskipb\relax} \def\newword{\relax\endgraf% {\csname\thefont\endcsname\theword}\dotfill\indxjump{\thepage}{\thedest}% \let\theoldfont\thefont% \let\theoldword\theword} %% %% INDEX %% \parskip=0pt plus 1pt \parindent=0pt \parfillskip=0pt \catcode`\_=11 % make _ an ordinary char (frequent in function names) \def\li#1{\hbox to\hsize{#1\hfil}} \li{\var{SomeWord} refers to PARI-GP concepts.} \li{\kbd{SomeWord} is a PARI-GP keyword.} \li{SomeWord is a generic index entry.} \checkfile{\jobname.std} \newif\ifmore \loop \read\std to\theline \ifx\theline\theend\morefalse\else\moretrue\fi \ifmore \expandafter\parse\theline \ifx \theletter \theoldletter \else \endgraf \vskip 10pt plus 10pt\centerline{\bf\theletter} \vskip 6pt plus 7pt \fi \ifx \theword \theoldword \ifx \thefont \theoldfont \ifx \thepage \theoldpage \else \interpage \indxjump{\thepage}{\thedest}\fi \else \newword \fi \else \newword \fi \let\theoldletter\theletter \let\theoldpage\thepage \repeat% pari-2.7.5/doc/usersFUNCS.tex0000644000175000017500000017250712405547147014362 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Functions and Operations Available in PARI and GP} \label{se:functions} The functions and operators available in PARI and in the GP/PARI calculator are numerous and ever-expanding. Here is a description of the ones available in version \vers. It should be noted that many of these functions accept quite different types as arguments, but others are more restricted. The list of acceptable types will be given for each function or class of functions. Except when stated otherwise, it is understood that a function or operation which should make natural sense is legal. In this chapter, we will describe the functions according to a rough classification. The general entry looks something like: \key{foo}$(x,\{\fl=0\})$: short description. The library syntax is \kbd{GEN foo(GEN x, long fl = 0)}. \noindent This means that the GP function \kbd{foo} has one mandatory argument $x$, and an optional one, $\fl$, whose default value is 0. (The $\{\}$ should not be typed, it is just a convenient notation we will use throughout to denote optional arguments.) That is, you can type \kbd{foo(x,2)}, or \kbd{foo(x)}, which is then understood to mean \kbd{foo(x,0)}. As well, a comma or closing parenthesis, where an optional argument should have been, signals to GP it should use the default. Thus, the syntax \kbd{foo(x,)} is also accepted as a synonym for our last expression. When a function has more than one optional argument, the argument list is filled with user supplied values, in order. When none are left, the defaults are used instead. Thus, assuming that \kbd{foo}'s prototype had been $$\hbox{% \key{foo}$(\{x=1\},\{y=2\},\{z=3\})$,% }$$ typing in \kbd{foo(6,4)} would give you \kbd{foo(6,4,3)}. In the rare case when you want to set some far away argument, and leave the defaults in between as they stand, you can use the ``empty arg'' trick alluded to above: \kbd{foo(6,,1)} would yield \kbd{foo(6,2,1)}. By the way, \kbd{foo()} by itself yields \kbd{foo(1,2,3)} as was to be expected. In this rather special case of a function having no mandatory argument, you can even omit the $()$: a standalone \kbd{foo} would be enough (though we do not recommend it for your scripts, for the sake of clarity). In defining GP syntax, we strove to put optional arguments at the end of the argument list (of course, since they would not make sense otherwise), and in order of decreasing usefulness so that, most of the time, you will be able to ignore them. Finally, an optional argument (between braces) followed by a star, like $\{\var{x}\}*$, means that any number of such arguments (possibly none) can be given. This is in particular used by the various \kbd{print} routines. \misctitle{Flags} A \tev{flag} is an argument which, rather than conveying actual information to the routine, instructs it to change its default behavior, e.g.~return more or less information. All such flags are optional, and will be called \fl\ in the function descriptions to follow. There are two different kind of flags \item generic: all valid values for the flag are individually described (``If \fl\ is equal to $1$, then\dots''). \item binary:\sidx{binary flag} use customary binary notation as a compact way to represent many toggles with just one integer. Let $(p_0,\dots,p_n)$ be a list of switches (i.e.~of properties which take either the value $0$ or~$1$), the number $2^3 + 2^5 = 40$ means that $p_3$ and $p_5$ are set (that is, set to $1$), and none of the others are (that is, they are set to $0$). This is announced as ``The binary digits of $\fl$ mean 1: $p_0$, 2: $p_1$, 4: $p_2$'', and so on, using the available consecutive powers of~$2$. \misctitle{Mnemonics for flags} Numeric flags as mentioned above are obscure, error-prone, and quite rigid: should the authors want to adopt a new flag numbering scheme (for instance when noticing flags with the same meaning but different numeric values across a set of routines), it would break backward compatibility. The only advantage of explicit numeric values is that they are fast to type, so their use is only advised when using the calculator \kbd{gp}. As an alternative, one can replace a numeric flag by a character string containing symbolic identifiers. For a generic flag, the mnemonic corresponding to the numeric identifier is given after it as in \bprog fun(x, {flag = 0} ): If flag is equal to 1 = AGM, use an agm formula ... @eprog\noindent which means that one can use indifferently \kbd{fun($x$, 1)} or \kbd{fun($x$, "AGM")}. For a binary flag, mnemonics corresponding to the various toggles are given after each of them. They can be negated by prepending \kbd{no\_} to the mnemonic, or by removing such a prefix. These toggles are grouped together using any punctuation character (such as ',' or ';'). For instance (taken from description of $\tet{ploth}(X=a,b,\var{expr},\{\fl=0\},\{n=0\})$) \centerline{Binary digits of flags mean: $1=\kbd{Parametric}$, $2=\kbd{Recursive}$, \dots} \noindent so that, instead of $1$, one could use the mnemonic \kbd{"Parametric; no\_Recursive"}, or simply \kbd{"Parametric"} since \kbd{Recursive} is unset by default (default value of $\fl$ is $0$, i.e.~everything unset). People used to the bit-or notation in languages like C may also use the form \kbd{"Parametric | no\_Recursive"}. \misctitle{Pointers} \varsidx{pointer} If a parameter in the function prototype is prefixed with a \& sign, as in \key{foo}$(x,\&e)$ \noindent it means that, besides the normal return value, the function may assign a value to $e$ as a side effect. When passing the argument, the \& sign has to be typed in explicitly. As of version \vers, this \tev{pointer} argument is optional for all documented functions, hence the \& will always appear between brackets as in \kbd{Z\_issquare}$(x,\{\&e\})$. \misctitle{About library programming} The \var{library} function \kbd{foo}, as defined at the beginning of this section, is seen to have two mandatory arguments, $x$ and \fl: no function seen in the present chapter has been implemented so as to accept a variable number of arguments, so all arguments are mandatory when programming with the library (usually, variants are provided corresponding to the various flag values). We include an \kbd{= default value} token in the prototype to signal how a missing argument should be encoded. Most of the time, it will be a \kbd{NULL} pointer, or -1 for a variable number. Refer to the \emph{User's Guide to the PARI library} for general background and details. \section{Standard monadic or dyadic operators} \subseckbd{+$/$-} The expressions \kbd{+}$x$ and \kbd{-}$x$ refer to monadic operators (the first does nothing, the second negates $x$). The library syntax is \fun{GEN}{gneg}{GEN x} for \kbd{-}$x$. \subseckbd{+} The expression $x$ \kbd{+} $y$ is the \idx{sum} of $x$ and $y$. Addition between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] + x, y[2],\dots]$ and $y + x \text{Id}$. Other additions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gadd}{GEN x, GEN y}. \subseckbd{-} The expression $x$ \kbd{-} $y$ is the \idx{difference} of $x$ and $y$. Subtraction between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] - x, y[2],\dots]$ and $y - x \text{Id}$. Other subtractions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gsub}{GEN x, GEN y} for $x$ \kbd{-} $y$. \subseckbd{*} The expression $x$ \kbd{*} $y$ is the \idx{product} of $x$ and $y$. Among the prominent impossibilities are multiplication between vector/matrices of incompatible sizes, between a \typ{INTMOD} or \typ{PADIC} Restricted to scalars, \kbd{*} is commutative; because of vector and matrix operations, it is not commutative in general. Multiplication between two \typ{VEC}s or two \typ{COL}s is not allowed; to take the \idx{scalar product} of two vectors of the same length, transpose one of the vectors (using the operator \kbd{\til} or the function \kbd{mattranspose}, see \secref{se:linear_algebra}) and multiply a line vector by a column vector: \bprog ? a = [1,2,3]; ? a * a *** at top-level: a*a *** ^-- *** _*_: forbidden multiplication t_VEC * t_VEC. ? a * a~ %2 = 14 @eprog If $x,y$ are binary quadratic forms, compose them; see also \kbd{qfbnucomp} and \kbd{qfbnupow}. If $x,y$ are \typ{VECSMALL} of the same length, understand them as permutations and compose them. The library syntax is \fun{GEN}{gmul}{GEN x, GEN y} for $x$ \kbd{*} $y$. Also available is \fun{GEN}{gsqr}{GEN x} for $x$ \kbd{*} $x$. \subseckbd{/} The expression $x$ \kbd{/} $y$ is the \idx{quotient} of $x$ and $y$. In addition to the impossibilities for multiplication, note that if the divisor is a matrix, it must be an invertible square matrix, and in that case the result is $x*y^{-1}$. Furthermore note that the result is as exact as possible: in particular, division of two integers always gives a rational number (which may be an integer if the quotient is exact) and \emph{not} the Euclidean quotient (see $x$ \kbd{\bs} $y$ for that), and similarly the quotient of two polynomials is a rational function in general. To obtain the approximate real value of the quotient of two integers, add \kbd{0.} to the result; to obtain the approximate $p$-adic value of the quotient of two integers, add \kbd{O(p\pow k)} to the result; finally, to obtain the \idx{Taylor series} expansion of the quotient of two polynomials, add \kbd{O(X\pow k)} to the result or use the \kbd{taylor} function (see \secref{se:taylor}). \label{se:gdiv} The library syntax is \fun{GEN}{gdiv}{GEN x, GEN y} for $x$ \kbd{/} $y$. \subseckbd{\bs} The expression \kbd{$x$ \bs\ $y$} is the \idx{Euclidean quotient} of $x$ and $y$. If $y$ is a real scalar, this is defined as \kbd{floor($x$/$y$)} if $y > 0$, and \kbd{ceil($x$/$y$)} if $y < 0$ and the division is not exact. Hence the remainder \kbd{$x$ - ($x$\bs$y$)*$y$} is in $[0, |y|[$. Note that when $y$ is an integer and $x$ a polynomial, $y$ is first promoted to a polynomial of degree $0$. When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gdivent}{GEN x, GEN y} for $x$ \kbd{\bs} $y$. \subseckbd{\bs/} The expression $x$ \b{/} $y$ evaluates to the rounded \idx{Euclidean quotient} of $x$ and $y$. This is the same as \kbd{$x$ \bs\ $y$} except for scalar division: the quotient is such that the corresponding remainder is smallest in absolute value and in case of a tie the quotient closest to $+\infty$ is chosen (hence the remainder would belong to $]{-}|y|/2, |y|/2]$). When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gdivround}{GEN x, GEN y} for $x$ \b{/} $y$. \subseckbd{\%} The expression \kbd{$x$ \% $y$} evaluates to the modular \idx{Euclidean remainder} of $x$ and $y$, which we now define. When $x$ or $y$ is a non-integral real number, \kbd{$x$\%$y$} is defined as \kbd{$x$ - ($x$\bs$y$)*$y$}. Otherwise, if $y$ is an integer, this is the smallest non-negative integer congruent to $x$ modulo $y$. (This actually coincides with the previous definition if and only if $x$ is an integer.) If $y$ is a polynomial, this is the polynomial of smallest degree congruent to $x$ modulo $y$. For instance: \bprog ? (1/2) % 3 %1 = 2 ? 0.5 % 3 %2 = 0.5000000000000000000000000000 ? (1/2) % 3.0 %3 = 1/2 @eprog Note that when $y$ is an integer and $x$ a polynomial, $y$ is first promoted to a polynomial of degree $0$. When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gmod}{GEN x, GEN y} for $x$ \kbd{\%} $y$. \subseckbd{\pow} The expression $x\hbox{\kbd{\pow}}n$ is \idx{powering}. If the exponent is an integer, then exact operations are performed using binary (left-shift) powering techniques. In particular, in this case $x$ cannot be a vector or matrix unless it is a square matrix (invertible if the exponent is negative). If $x$ is a $p$-adic number, its precision will increase if $v_p(n) > 0$. Powering a binary quadratic form (types \typ{QFI} and \typ{QFR}) returns a reduced representative of the class, provided the input is reduced. In particular, $x\hbox{\kbd{\pow}}1$ is identical to $x$. PARI is able to rewrite the multiplication $x * x$ of two \emph{identical} objects as $x^2$, or $\kbd{sqr}(x)$. Here, identical means the operands are two different labels referencing the same chunk of memory; no equality test is performed. This is no longer true when more than two arguments are involved. If the exponent is not of type integer, this is treated as a transcendental function (see \secref{se:trans}), and in particular has the effect of componentwise powering on vector or matrices. As an exception, if the exponent is a rational number $p/q$ and $x$ an integer modulo a prime or a $p$-adic number, return a solution $y$ of $y^q=x^p$ if it exists. Currently, $q$ must not have large prime factors. Beware that \bprog ? Mod(7,19)^(1/2) %1 = Mod(11, 19) /* is any square root */ ? sqrt(Mod(7,19)) %2 = Mod(8, 19) /* is the smallest square root */ ? Mod(7,19)^(3/5) %3 = Mod(1, 19) ? %3^(5/3) %4 = Mod(1, 19) /* Mod(7,19) is just another cubic root */ @eprog If the exponent is a negative integer, an \idx{inverse} must be computed. For non-invertible \typ{INTMOD}, this will fail and implicitly exhibit a non trivial factor of the modulus: \bprog ? Mod(4,6)^(-1) *** at top-level: Mod(4,6)^(-1) *** ^----- *** _^_: impossible inverse modulo: Mod(2, 6). @eprog\noindent (Here, a factor 2 is obtained directly. In general, take the gcd of the representative and the modulus.) This is most useful when performing complicated operations modulo an integer $N$ whose factorization is unknown. Either the computation succeeds and all is well, or a factor $d$ is discovered and the computation may be restarted modulo $d$ or $N/d$. For non-invertible \typ{POLMOD}, this will fail without exhibiting a factor. \bprog ? Mod(x^2, x^3-x)^(-1) *** at top-level: Mod(x^2,x^3-x)^(-1) *** ^----- *** _^_: non-invertible polynomial in RgXQ_inv. ? a = Mod(3,4)*y^3 + Mod(1,4); b = y^6+y^5+y^4+y^3+y^2+y+1; ? Mod(a, b)^(-1); *** at top-level: Mod(a,b)^(-1) *** ^----- *** _^_: impossible inverse modulo: Mod(0, 4). @eprog\noindent In fact the latter polynomial is invertible, but the algorithm used (subresultant) assumes the base ring is a domain. If it is not the case, as here for $\Z/4\Z$, a result will be correct but chances are an error will occur first. In this specific case, one should work with $2$-adics. In general, one can try the following approach \bprog ? inversemod(a, b) = { my(m); m = polsylvestermatrix(polrecip(a), polrecip(b)); m = matinverseimage(m, matid(#m)[,1]); Polrev( vecextract(m, Str("..", poldegree(b))), variable(b) ) } ? inversemod(a,b) %2 = Mod(2,4)*y^5 + Mod(3,4)*y^3 + Mod(1,4)*y^2 + Mod(3,4)*y + Mod(2,4) @eprog\noindent This is not guaranteed to work either since it must invert pivots. See \secref{se:linear_algebra}. The library syntax is \fun{GEN}{gpow}{GEN x, GEN n, long prec} for $x\hbox{\kbd{\pow}}n$. %SECTION: operators \subsec{Comparison and Boolean operators}\sidx{Boolean operators} The six standard \idx{comparison operators} \kbd{<=}, \kbd{<}, \kbd{>=}, \kbd{>}, \kbd{==}, \kbd{!=} are available in GP. The result is 1 if the comparison is true, 0 if it is false. The operator \kbd{==} is quite liberal : for instance, the integer 0, a 0 polynomial, and a vector with 0 entries are all tested equal. 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. 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. The standard boolean operators \kbd{||} (\idx{inclusive or}), \kbd{\&\&} (\idx{and})\sidx{or} and \kbd{!} (\idx{not}) are also available. \section{Conversions and similar elementary functions or commands} \label{se:conversion} \noindent Many of the conversion functions are rounding or truncating operations. In this case, if the argument is a rational function, the result is the Euclidean quotient of the numerator by the denominator, and if the argument is a vector or a matrix, the operation is done componentwise. This will not be restated for every function. %SECTION: conversions \section{Transcendental functions}\label{se:trans} Since the values of transcendental functions cannot be exactly represented, these functions will always return an inexact object: a real number, a complex number, a $p$-adic number or a power series. All these objects have a certain finite precision. As a general rule, which of course in some cases may have exceptions, transcendental functions operate in the following way: \item If the argument is either a real number or an inexact complex number (like \kbd{1.0 + I} or \kbd{Pi*I} but not \kbd{2 - 3*I}), then the computation is done with the precision of the argument. In the example below, we see that changing the precision to $50$ digits does not matter, because $x$ only had a precision of $19$ digits. \bprog ? \p 15 realprecision = 19 significant digits (15 digits displayed) ? x = Pi/4 %1 = 0.785398163397448 ? \p 50 realprecision = 57 significant digits (50 digits displayed) ? sin(x) %2 = 0.7071067811865475244 @eprog Note that even if the argument is real, the result may be complex (e.g.~$\text{acos}(2.0)$ or $\text{acosh}(0.0)$). See each individual function help for the definition of the branch cuts and choice of principal value. \item If the argument is either an integer, a rational, an exact complex number or a quadratic number, it is first converted to a real or complex number using the current \idx{precision} held in the default \tet{realprecision}. This precision (the number of decimal digits) can be changed using \b{p} or \kbd{default(realprecision,...)}). After this conversion, the computation proceeds as above for real or complex arguments. In library mode, the \kbd{realprecision} does not matter; instead the precision is taken from the \kbd{prec} parameter which every transcendental function has. As in \kbd{gp}, this \kbd{prec} is not used when the argument to a function is already inexact. Note that the argument \var{prec} stands for the length in words of a real number, including codewords. Hence we must have $\var{prec} \geq 3$. Some accuracies attainable on 32-bit machines cannot be attained on 64-bit machines for parity reasons. For example the default \kbd{gp} accuracy is 28 decimal digits on 32-bit machines, corresponding to \var{prec} having the value 5, but this cannot be attained on 64-bit machines. \item If the argument is a polmod (representing an algebraic number), then the function is evaluated for every possible complex embedding of that algebraic number. A column vector of results is returned, with one component for each complex embedding. Therefore, the number of components equals the degree of the \typ{POLMOD} modulus. \item If the argument is an intmod or a $p$-adic, at present only a few functions like \kbd{sqrt} (square root), \kbd{sqr} (square), \kbd{log}, \kbd{exp}, powering, \kbd{teichmuller} (Teichm\"uller character) and \kbd{agm} (arithmetic-geometric mean) are implemented. Note that in the case of a $2$-adic number, $\kbd{sqr}(x)$ may not be identical to $x*x$: for example if $x = 1+O(2^5)$ and $y = 1+O(2^5)$ then $x*y = 1+O(2^5)$ while $\kbd{sqr}(x) = 1+O(2^6)$. Here, $x * x$ yields the same result as $\kbd{sqr}(x)$ since the two operands are known to be \emph{identical}. The same statement holds true for $p$-adics raised to the power $n$, where $v_p(n) > 0$. \misctitle{Remark} If we wanted to be strictly consistent with the PARI philosophy, we should have $x*y = (4 \mod 8)$ and $\kbd{sqr}(x) = (4 \mod 32)$ when both $x$ and $y$ are congruent to $2$ modulo $4$. However, since intmod is an exact object, PARI assumes that the modulus must not change, and the result is hence $(0\, \mod\, 4)$ in both cases. On the other hand, $p$-adics are not exact objects, hence are treated differently. \item If the argument is a polynomial, a power series or a rational function, it is, if necessary, first converted to a power series using the current series precision, held in the default \tet{seriesprecision}. This precision (the number of significant terms) can be changed using \b{ps} or \kbd{default(seriesprecision,...)}. Then the Taylor series expansion of the function around $X=0$ (where $X$ is the main variable) is computed to a number of terms depending on the number of terms of the argument and the function being computed. Under \kbd{gp} this again is transparent to the user. When programming in library mode, however, it is \emph{strongly} advised to perform an explicit conversion to a power series first, as in \kbd{x = gtoser(x, seriesprec)}, where the number of significant terms \kbd{seriesprec} can be specified explicitly. If you do not do this, a global variable \kbd{precdl} is used instead, to convert polynomials and rational functions to a power series with a reasonable number of terms; tampering with the value of this global variable is \emph{deprecated} and strongly discouraged. \item If the argument is a vector or a matrix, the result is the componentwise evaluation of the function. In particular, transcendental functions on square matrices, which are not implemented in the present version \vers, will have a different name if they are implemented some day. \subseckbd{\pow} If $y$ is not of type integer, \kbd{x\pow y} has the same effect as \kbd{exp(y*log(x))}. It can be applied to $p$-adic numbers as well as to the more usual types.\sidx{powering} The library syntax is \fun{GEN}{gpow}{GEN x, GEN n, long prec} for $x\hbox{\kbd{\pow}}n$. %SECTION: transcendental \section{Arithmetic functions}\label{se:arithmetic} These functions are by definition functions whose natural domain of definition is either $\Z$ (or $\Z_{>0}$). The way these functions are used is completely different from transcendental functions in that there are no automatic type conversions: in general only integers are accepted as arguments. An integer argument $N$ can be given in the following alternate formats: \item \typ{MAT}: its factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: a pair \kbd{[$N$, fa]} giving both the integer and its factorization. This allows to compute different arithmetic functions at a given $N$ while factoring the latter only once. \bprog ? N = 10!; faN = factor(N); ? eulerphi(N) %2 = 829440 ? eulerphi(faN) %3 = 829440 ? eulerphi(S = [N, faN]) %4 = 829440 ? sigma(S) %5 = 15334088 @eprog \subsec{Arithmetic functions and the factoring engine} All arithmetic functions in the narrow sense of the word~--- Euler's totient\sidx{Euler totient function} function, the \idx{Moebius} function, the sums over divisors or powers of divisors etc.--- call, after trial division by small primes, the same versatile factoring machinery described under \kbd{factorint}. It includes \idx{Shanks SQUFOF}, \idx{Pollard Rho}, \idx{ECM} and \idx{MPQS} stages, and has an early exit option for the functions \teb{moebius} and (the integer function underlying) \teb{issquarefree}. This machinery relies on a fairly strong probabilistic primality test, see \kbd{ispseudoprime}, but you may also set \bprog default(factor_proven, 1) @eprog\noindent to ensure that all tentative factorizations are fully proven. This should not slow down PARI too much, unless prime numbers with hundreds of decimal digits occur frequently in your application. \subsec{Orders in finite groups and Discrete Logarithm functions} \label{se:DLfun} The following functions compute the order of an element in a finite group: \kbd{ellorder} (the rational points on an elliptic curve defined over a finite field), \kbd{fforder} (the multiplicative group of a finite field), \kbd{znorder} (the invertible elements in $\Z/n\Z$). The following functions compute discrete logarithms in the same groups (whenever this is meaningful) \kbd{elllog}, \kbd{fflog}, \kbd{znlog}. All such functions allow an optional argument specifying an integer $N$, representing the order of the group. (The \emph{order} functions also allows any non-zero multiple of the order, with a minor loss of efficiency.) That optional argument follows the same format as given above: \item \typ{INT}: the integer $N$, \item \typ{MAT}: the factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: this is the preferred format and provides both the integer $N$ and its factorization in a two-component vector \kbd{[$N$, fa]}. When the group is fixed and many orders or discrete logarithms will be computed, it is much more efficient to initialize this data once and for all and pass it to the relevant functions, as in \bprog ? p = nextprime(10^40); ? v = [p-1, factor(p-1)]; \\ data for discrete log & order computations ? znorder(Mod(2,p), v) %3 = 500000000000000000000000000028 ? g = znprimroot(p); ? znlog(2, g, v) %5 = 543038070904014908801878611374 @eprog \bigskip %SECTION: number_theoretical \section{Functions related to elliptic curves} \subsec{Elliptic curve structures} An elliptic curve is given by a Weierstrass model\sidx{Weierstrass equation} $$ y^2+a_1xy+a_3y=x^3+a_2x^2+a_4x+a_6, $$ whose discriminant is non-zero. Affine points on \kbd{E} are represented as two-component vectors \kbd{[x,y]}; the point at infinity, i.e.~the identity element of the group law, is represented by the one-component vector \kbd{[0]}. Given a vector of coefficients $[a_1,a_2,a_3,a_4,a_6]$, the function \tet{ellinit} initializes and returns an \tev{ell} structure. (An additional optional argument allows to specify the base field in case it cannot be inferred from the curve coefficients.) This structure contains data needed by elliptic curve related functions, and is generally passed as a first argument. Expensive data are skipped on initialization: they will be dynamically computed when (and if) needed, and then inserted in the structure. The precise layout of the \tev{ell} structure is left undefined and should never be used directly. The following \idx{member functions} are available, depending on the underlying domain. \subsubsec{All domains} \item \tet{a1}, \tet{a2}, \tet{a3}, \tet{a4}, \tet{a6}: coefficients of the elliptic curve. \item \tet{b2}, \tet{b4}, \tet{b6}, \tet{b8}: $b$-invariants of the curve; in characteristic $\neq 2$, for $Y = 2y + a_1x+a3$, the curve equation becomes $$ Y^2 = 4 x^3 + b_2 x^2 + 2b_4 x + b_6 =: g(x). $$ \item \tet{c4}, \tet{c6}: $c$-invariants of the curve; in characteristic $\neq 2,3$, for $X = x + b_2/12$ and $Y = 2y + a_1x+a3$, the curve equation becomes $$ Y^2 = 4 X^3 - (c_4/12) X - (c_6/216). $$ \item \tet{disc}: discriminant of the curve. This is only required to be non-zero, not necessarily a unit. \item \tet{j}: $j$-invariant of the curve. \noindent These are used as follows: \bprog ? E = ellinit([0,0,0, a4,a6]); ? E.b4 %2 = 2*a4 ? E.disc %3 = -64*a4^3 - 432*a6^2 @eprog \subsubsec{Curves over $\R$} This in particular includes curves defined over $\Q$. All member functions in this section return data, as it is currently stored in the structure, if present; and otherwise compute it to the default accuracy, that was fixed \emph{at the time of ellinit} (via a \typ{REAL} $D$ domain argument, or \kbd{realprecision} by default). The function \tet{ellperiods} allows to recompute (and cache) the following data to \emph{current} \kbd{realprecision}. \item \tet{area}: volume of the complex lattice defining $E$. \item \tet{roots} is a vector whose three components contain the complex roots of the right hand side $g(x)$ of the associated $b$-model $Y^2 = g(x)$. If the roots are all real, they are ordered by decreasing value. If only one is real, it is the first component. \item \tet{omega}: $[\omega_1,\omega_2]$, periods forming a basis of the complex lattice defining $E$. The first component $\omega_1$ is the (positive) real period, in other words the integral of $dx/(2y+a_1x+a_3)$ over the connected component of the identity component of $E(\R)$. The second component $\omega_2$ is a complex period, such that $\tau=\dfrac{\omega_1}{\omega_2}$ belongs to Poincar\'e's half-plane (positive imaginary part); not necessarily to the standard fundamental domain. \item \tet{eta} is a row vector containing the quasi-periods $\eta_1$ and $\eta_2$ such that $\eta_i = 2\zeta(\omega_i/2)$, where $\zeta$ is the Weierstrass zeta function associated to the period lattice; see \tet{ellzeta}. In particular, the Legendre relation holds: $\eta_2\omega_1 - \eta_1\omega_2 = 2i\pi$. \misctitle{Warning} As for the orientation of the basis of the period lattice, beware that many sources use the inverse convention where $\omega_2/\omega_1$ has positive imaginary part and our $\omega_2$ is the negative of theirs. Our convention $\tau = \omega_1/\omega_2$ ensures that the action of $\text{PSL}_2$ is the natural one: $$[a,b;c,d]\cdot\tau = (a\tau+b)/(c\tau+d) = (a \omega_1 + b\omega_2)/(c\omega_1 + d\omega_2),$$ instead of a twisted one. (Our $tau$ is $-1/\tau$ in the above inverse convention.) \subsubsec{Curves over $\Q_p$} We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model. For the time being only curves with multiplicative reduction (split or non-split), i.e. $v_p(j) < 0$, are supported by non-trivial functions. In this case the curve is analytically isomorphic to $\bar{\Q}_p^*/q^\Z := E_q(\bar{\Q}_p)$, for some $p$-adic integer $q$ (the Tate period). In particular, we have $j(q) = j(E)$. \item \tet{p} is the residual characteristic \item \tet{roots} is a vector with a single component, equal to the $p$-adic root $e_1$ of the right hand side $g(x)$ of the associated $b$-model $Y^2 = g(x)$. The point $(e_1,0)$ corresponds to $-1 \in \bar{\Q}_p^*/q^\Z$ under the Tate parametrization. \item \tet{tate} returns $[u^2,u,q,[a,b]]$ in the notation of Henniart-Mestre (CRAS t. 308, p.~391--395, 1989): $q$ is as above, $u\in \Q_p(\sqrt{-c_6})$ is such that $\phi^* dx/(2y + a_1x+a3) = u dt/t$, where $\phi: E_q\to E$ is an isomorphism (well defined up to sign) and $dt/t$ is the canonical invariant differential on the Tate curve; $u^2\in\Q_p$ does not depend on $\phi$. (Technicality: if $u\not\in\Q_p$, it is stored as a quadratic \typ{POLMOD}.) Finally, $[a,b]$ satisfy $4u^2 b \cdot \text{agm}(\sqrt{a/b},1)^2 = 1$ as in Theorem~2 (\emph{loc.~cit.}). \subsubsec{Curves over $\F_q$} \item \tet{p} is the characteristic of $\F_q$. \item \tet{no} is $\#E(\F_q)$. \item \tet{cyc} gives the cycle structure of $E(\F_q)$. \item \tet{gen} returns the generators of $E(\F_q)$. \item \tet{group} returns $[\kbd{no},\kbd{cyc},\kbd{gen}]$, i.e. $E(\F_q)$ as an abelian group structure. \subsubsec{Curves over $\Q$} All functions should return a correct result, whether the model is minimal or not, but it is a good idea to stick to minimal models whenever $\gcd(c_4,c_6)$ is easy to factor (minor speed-up). The construction \bprog E = ellminimalmodel(E0, &v) @eprog\noindent replaces the original model $E_0$ by a minimal model $E$, and the variable change $v$ allows to go between the two models: \bprog ellchangepoint(P0, v) ellchangepointinv(P, v) @eprog\noindent respectively map the point $P_0$ on $E_0$ to its image on $E$, and the point $P$ on $E$ to its pre-image on $E_0$. A few routines --- namely \tet{ellgenerators}, \tet{ellidentify}, \tet{ellsearch}, \tet{forell} --- require the optional package \tet{elldata} (John Cremona's database) to be installed. In that case, the function \tet{ellinit} will allow alternative inputs, e.g.~\kbd{ellinit("11a1")}. Functions using this package need to load chunks of a large database in 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) %SECTION: elliptic_curves \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). \subsec{Number field structures} Let $K = \Q[X] / (T)$ a number field, $\Z_K$ its ring of integers, $T\in\Z[X]$ is monic. Three basic number field structures can be associated to $K$ in GP: \item $\tev{nf}$ denotes a number field, i.e.~a data structure output by \tet{nfinit}. This contains the basic arithmetic data associated to the number field: signature, maximal order (given by a basis \kbd{nf.zk}), discriminant, defining polynomial $T$, etc. \item $\tev{bnf}$ denotes a ``Buchmann's number field'', i.e.~a data structure output by \tet{bnfinit}. This contains $\var{nf}$ and the deeper invariants of the field: units $U(K)$, class group $\Cl(K)$, as well as technical data required to solve the two associated discrete logarithm problems. \item $\tev{bnr}$ denotes a ``ray number field'', i.e.~a data structure output by \kbd{bnrinit}, corresponding to the ray class group structure of the field, for some modulus $f$. It contains a \var{bnf}, the modulus $f$, the ray class group $\Cl_f(K)$ and data associated to the discrete logarithm problem therein. \subsec{Algebraic numbers and ideals} \noindent An \tev{algebraic number} belonging to $K = \Q[X]/(T)$ is given as \item a \typ{INT}, \typ{FRAC} or \typ{POL} (implicitly modulo $T$), or \item a \typ{POLMOD} (modulo $T$), or \item a \typ{COL}~\kbd{v} of dimension $N = [K:\Q]$, representing the element in terms of the computed integral basis, as \kbd{sum(i = 1, N,~v[i] * nf.zk[i])}. Note that a \typ{VEC} will not be recognized. \medskip \noindent An \tev{ideal} is given in any of the following ways: \item an algebraic number in one of the above forms, defining a principal ideal. \item a prime ideal, i.e.~a 5-component vector in the format output by \kbd{idealprimedec} or \kbd{idealfactor}. \item a \typ{MAT}, square and in Hermite Normal Form (or at least upper triangular with non-negative coefficients), whose columns represent a $\Z$-basis of the ideal. One may use \kbd{idealhnf} to convert any ideal to the last (preferred) format. \item an \emph{extended ideal} \sidx{ideal (extended)} is a 2-component vector $[I, t]$, where $I$ is an ideal as above and $t$ is an algebraic number, representing the ideal $(t)I$. This is useful whenever \tet{idealred} is involved, implicitly working in the ideal class group, while keeping track of principal ideals. Ideal operations suitably update the principal part when it makes sense (in a multiplicative context), e.g.~using \kbd{idealmul} on $[I,t]$, $[J,u]$, we obtain $[IJ, tu]$. When it does not make sense, the extended part is silently discarded, e.g.~using \kbd{idealadd} with the above input produces $I+J$. The ``principal part'' $t$ in an extended ideal may be represented in any of the above forms, and \emph{also} as a factorization matrix (in terms of number field elements, not ideals!), possibly the empty matrix \kbd{[;]} representing $1$. In the latter case, elements stay in factored form, or \tev{famat} for \emph{fa}ctorization \emph{mat}rix, which is a convenient way to avoid coefficient explosion. To recover the conventional expanded form, try \tet{nffactorback}; but many functions already accept \var{famat}s as input, for instance \tet{ideallog}, so expanding huge elements should never be necessary. \subsec{Finite abelian groups} A finite abelian group $G$ in user-readable format is given by its Smith Normal Form as a pair $[h,d]$ or triple $[h,d,g]$. Here $h$ is the cardinality of $G$, $(d_i)$ is the vector of elementary divisors, and $(g_i)$ is a vector of generators. In short, $G = \oplus_{i\leq n} (\Z/d_i\Z) g_i$, with $d_n \mid \dots \mid d_2 \mid d_1$ and $\prod d_i = h$. This information can also be retrieved as $G.\kbd{no}$, $G.\kbd{cyc}$ and $G.\kbd{gen}$. \item a \tev{character} on the abelian group $\oplus (\Z/d_i\Z) g_i$ is given by a row vector $\chi = [a_1,\ldots,a_n]$ such that $\chi(\prod g_i^{n_i}) = \exp(2i\pi\sum a_i n_i / d_i)$. \item given such a structure, a \tev{subgroup} $H$ is input as a square matrix in HNF, whose columns express generators of $H$ on the given generators $g_i$. Note that the determinant of that matrix is equal to the index $(G:H)$. \subsec{Relative extensions} We now have a look at data structures associated to relative extensions of number fields $L/K$, and to projective $\Z_K$-modules. When defining a relative extension $L/K$, the $\var{nf}$ associated to the base field $K$ must be defined by a variable having a lower priority (see \secref{se:priority}) than the variable defining the extension. For example, you may use the variable name $y$ to define the base field $K$, and $x$ to define the relative extension $L/K$. \subsubsec{Basic definitions}\label{se:ZKmodules} \item $\tev{rnf}$ denotes a relative number field, i.e.~a data structure output by \kbd{rnfinit}, associated to the extension $L/K$. The \var{nf} associated to be base field $K$ is \kbd{rnf.nf}. \item A \emph{relative matrix} is an $m\times n$ matrix whose entries are elements of $K$, in any form. Its $m$ columns $A_j$ represent elements in $K^n$. \item An \tev{ideal list} is a row vector of fractional ideals of the number field $\var{nf}$. \item A \tev{pseudo-matrix} is a 2-component row vector $(A,I)$ where $A$ is a relative $m\times n$ matrix and $I$ an ideal list of length $n$. If $I = \{{\Bbb a}_1,\dots, {\Bbb a}_n\}$ and the columns of $A$ are $(A_1,\dots, A_n)$, this data defines the torsion-free (projective) $\Z_K$-module ${\Bbb a}_1 A_1\oplus {\Bbb a}_n A_n$. \item An \tev{integral pseudo-matrix} is a 3-component row vector w$(A,I,J)$ where $A = (a_{i,j})$ is an $m\times n$ relative matrix and $I = ({\Bbb b}_1,\dots, {\Bbb b}_m)$, $J = ({\Bbb a}_1,\dots, {\Bbb a}_n)$ are ideal lists, such that $a_{i,j} \in {\Bbb b}_i {\Bbb a}_j^{-1}$ for all $i,j$. This data defines two abstract projective $\Z_K$-modules $N = {\Bbb a_1}\omega_1\oplus \cdots\oplus {\Bbb a_n}\omega_n $ in $K^n$, $P = {\Bbb b_1}\eta_1\oplus \cdots\oplus {\Bbb b_m}\eta_m$ in $K^m$, and a $\Z_K$-linear map $f:N\to P$ given by $$ f(\sum \alpha_j\omega_j) = \sum_i \Big(a_{i,j}\alpha_j\Big) \eta_i.$$ This data defines the $\Z_K$-module $M = P/f(N)$. \item Any \emph{projective} $\Z_K$-module\varsidx{projective module} $M$ of finite type in $K^m$ can be given by a pseudo matrix $(A,I)$. \item An arbitrary $\Z_K$ modules of finite type in $K^m$, with non-trivial torsion, is given by an integral pseudo-matrix $(A,I,J)$ \subsubsec{Pseudo-bases, determinant} \item The pair $(A,I)$ is a \tev{pseudo-basis} of the module it generates if the ${\Bbb a_j}$ are non-zero, and the $A_j$ are $K$-linearly independent. We call $n$ the \emph{size} of the pseudo-basis. If $A$ is a relative matrix, the latter condition means it is square with non-zero determinant; we say that it is in Hermite Normal Form\sidx{Hermite normal form} (HNF) if it is upper triangular and all the elements of the diagonal are equal to 1. \item For instance, the relative integer basis \kbd{rnf.zk} is a pseudo-basis $(A,I)$ of $\Z_L$, where $A = \kbd{rnf.zk[1]}$ is a vector of elements of $L$, which are $K$-linearly independent. Most \var{rnf} routines return and handle $\Z_K$-modules contained in $L$ (e.g.~$\Z_L$-ideals) via a pseudo-basis $(A',I')$, where $A'$ is a relative matrix representing a vector of elements of $L$ in terms of the fixed basis \kbd{rnf.zk[1]} \item The \emph{determinant} of a pseudo-basis $(A,I)$ is the ideal equal to the product of the determinant of $A$ by all the ideals of $I$. The determinant of a pseudo-matrix is the determinant of any pseudo-basis of the module it generates. \subsec{Class field theory}\label{se:CFT} A $\tev{modulus}$, in the sense of class field theory, is a divisor supported on the non-complex places of $K$. In PARI terms, this means either an ordinary ideal $I$ as above (no Archimedean component), or a pair $[I,a]$, where $a$ is a vector with $r_1$ $\{0,1\}$-components, corresponding to the infinite part of the divisor. More precisely, the $i$-th component of $a$ corresponds to the real embedding associated to the $i$-th real root of \kbd{K.roots}. (That ordering is not canonical, but well defined once a defining polynomial for $K$ is chosen.) For instance, \kbd{[1, [1,1]]} is a modulus for a real quadratic field, allowing ramification at any of the two places at infinity, and nowhere else. A \tev{bid} or ``big ideal'' is a structure output by \kbd{idealstar} needed to compute in $(\Z_K/I)^*$, where $I$ is a modulus in the above sense. It is a finite abelian group as described above, supplemented by technical data needed to solve discrete log problems. Finally we explain how to input ray number fields (or \var{bnr}), using class field theory. These are defined by a triple $A$, $B$, $C$, where the defining set $[A,B,C]$ can have any of the following forms: $[\var{bnr}]$, $[\var{bnr},\var{subgroup}]$, $[\var{bnf},\var{mod}]$, $[\var{bnf},\var{mod},\var{subgroup}]$. The last two forms are kept for backward compatibility, but no longer serve any real purpose (see example below); no newly written function will accept them. \item $\var{bnf}$ is as output by \kbd{bnfinit}, where units are mandatory unless the modulus is trivial; \var{bnr} is as output by \kbd{bnrinit}. This is the ground field $K$. \item \emph{mod} is a modulus $\goth{f}$, as described above. \item \emph{subgroup} a subgroup of the ray class group modulo $\goth{f}$ of $K$. As described above, this is input as a square matrix expressing generators of a subgroup of the ray class group \kbd{\var{bnr}.clgp} on the given generators. The corresponding \var{bnr} is the subfield of the ray class field of $K$ modulo $\goth{f}$, fixed by the given subgroup. \bprog ? K = bnfinit(y^2+1); ? bnr = bnrinit(K, 13) ? %.clgp %3 = [36, [12, 3]] ? bnrdisc(bnr); \\ discriminant of the full ray class field ? bnrdisc(bnr, [3,1;0,1]); \\ discriminant of cyclic cubic extension of K @eprog\noindent We could have written directly \bprog ? bnrdisc(K, 13); ? bnrdisc(K, 13, [3,1;0,1]); @eprog\noindent avoiding one \tet{bnrinit}, but this would actually be slower since the \kbd{bnrinit} is called internally anyway. And now twice! \subsec{General use} All the functions which are specific to relative extensions, number fields, Buchmann's number fields, Buchmann's number rays, share the prefix \kbd{rnf}, \kbd{nf}, \kbd{bnf}, \kbd{bnr} respectively. They take as first argument a number field of that precise type, respectively output by \kbd{rnfinit}, \kbd{nfinit}, \kbd{bnfinit}, and \kbd{bnrinit}. However, and even though it may not be specified in the descriptions of the functions below, it is permissible, if the function expects a $\var{nf}$, to use a $\var{bnf}$ instead, which contains much more information. On the other hand, if the function requires a \kbd{bnf}, it will \emph{not} launch \kbd{bnfinit} for you, which is a costly operation. Instead, it will give you a specific error message. In short, the types $$ \kbd{nf} \leq \kbd{bnf} \leq \kbd{bnr}$$ are ordered, each function requires a minimal type to work properly, but you may always substitute a larger type. The data types corresponding to the structures described above are rather complicated. Thus, as we already have seen it with elliptic curves, GP provides ``member functions'' to retrieve data from these structures (once they have been initialized of course). The relevant types of number fields are indicated between parentheses: \smallskip \sidx{member functions} \settabs\+xxxxxxx&(\var{bnr},x&\var{bnf},x&nf\hskip2pt&)x&: &\cr \+\tet{bid} &(\var{bnr}&&&)&: & bid ideal structure.\cr \+\tet{bnf} &(\var{bnr},& \var{bnf}&&)&: & Buchmann's number field.\cr \+\tet{clgp} &(\var{bnr},& \var{bnf}&&)&: & classgroup. This one admits the following three subclasses:\cr \+ \quad \tet{cyc} &&&&&: & \quad cyclic decomposition (SNF)\sidx{Smith normal form}.\cr \+ \quad \kbd{gen}\sidx{gen (member function)} &&&&&: & \quad generators.\cr \+ \quad \tet{no} &&&&&: & \quad number of elements.\cr \+\tet{diff} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the different ideal.\cr \+\tet{codiff}&(\var{bnr},& \var{bnf},& \var{nf}&)&: & the codifferent (inverse of the different in the ideal group).\cr \+\tet{disc} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & discriminant.\cr \+\tet{fu} &(\var{bnr},& \var{bnf}&&)&: & \idx{fundamental units}.\cr \+\tet{index} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & \idx{index} of the power order in the ring of integers.\cr \+\tet{mod} &(\var{bnr}&&&)&: & modulus.\cr \+\tet{nf} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & number field.\cr \+\tet{pol} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & defining polynomial.\cr \+\tet{r1} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the number of real embeddings.\cr \+\tet{r2} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the number of pairs of complex embeddings.\cr \+\tet{reg} &(\var{bnr},& \var{bnf}&&)&: & regulator.\cr \+\tet{roots}&(\var{bnr},& \var{bnf},& \var{nf}&)&: & roots of the polynomial generating the field.\cr \+\tet{sign} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & signature $[r1,r2]$.\cr \+\tet{t2} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the $T_2$ matrix (see \kbd{nfinit}).\cr \+\tet{tu} &(\var{bnr},& \var{bnf}&&)&: & a generator for the torsion units.\cr \+\tet{zk} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & integral basis, i.e.~a $\Z$-basis of the maximal order.\cr \+\tet{zkst} &(\var{bnr}&&&)&: & structure of $(\Z_K/m)^*$.\cr \misctitle{Deprecated} The following member functions are still available, but deprecated and should not be used in new scripts : \+\tet{futu} &(\var{bnr},& \var{bnf},&&)&: & $[u_1,...,u_r,w]$, $(u_i)$ is a vector of fundamental units,\cr \+&&&&&& $w$ generates the torsion units.\cr \+\tet{tufu} &(\var{bnr},& \var{bnf},&&)&: & $[w,u_1,...,u_r]$, $(u_i)$ is a vector of fundamental units,\cr \+&&&&&& $w$ generates the torsion units.\cr For instance, assume that $\var{bnf} = \kbd{bnfinit}(\var{pol})$, for some polynomial. Then \kbd{\var{bnf}.clgp} retrieves the class group, and \kbd{\var{bnf}.clgp.no} the class number. If we had set $\var{bnf} = \kbd{nfinit}(\var{pol})$, both would have output an error message. All these functions are completely recursive, thus for instance \kbd{\var{bnr}.bnf.nf.zk} will yield the maximal order of \var{bnr}, which you could get directly with a simple \kbd{\var{bnr}.zk}. \subsec{Class group, units, and the GRH}\label{se:GRHbnf} Some of the functions starting with \kbd{bnf} are implementations of the sub-exponential algorithms for finding class and unit groups under \idx{GRH}, due to Hafner-McCurley, \idx{Buchmann} and Cohen-Diaz-Olivier. The general call to the functions concerning class groups of general number fields (i.e.~excluding \kbd{quadclassunit}) involves a polynomial $P$ and a technical vector $$\var{tech} = [c_1, c_2, \var{nrpid} ],$$ where the parameters are to be understood as follows: $P$ is the defining polynomial for the number field, which must be in $\Z[X]$, irreducible and monic. In fact, if you supply a non-monic polynomial at this point, \kbd{gp} issues a warning, then \emph{transforms your polynomial} so that it becomes monic. The \kbd{nfinit} routine will return a different result in this case: instead of \kbd{res}, you get a vector \kbd{[res,Mod(a,Q)]}, where \kbd{Mod(a,Q) = Mod(X,P)} gives the change of variables. In all other routines, the variable change is simply lost. The \var{tech} interface is obsolete and you should not tamper with these parameters. Indeed, from version 2.4.0 on, \item the results are always rigorous under \idx{GRH} (before that version, they relied on a heuristic strengthening, hence the need for overrides). \item the influence of these parameters on execution time and stack size is marginal. They \emph{can} be useful to fine-tune and experiment with the \kbd{bnfinit} code, but you will be better off modifying all tuning parameters in the C code (there are many more than just those three). We nevertheless describe it for completeness. The numbers $c_1 \leq c_2$ are non-negative real numbers. By default they are chosen so that the result is correct under GRH. For $i = 1,2$, let $B_i = c_i(\log |d_K|)^2$, and denote by $S(B)$ the set of maximal ideals of $K$ whose norm is less than $B$. We want $S(B_1)$ to generate $\Cl(K)$ and hope that $S(B_2)$ can be \emph{proven} to generate $\Cl(K)$. More precisely, $S(B_1)$ is a factorbase used to compute a tentative $\Cl(K)$ by generators and relations. We then check explicitly, using essentially \kbd{bnfisprincipal}, that the elements of $S(B_2)$ belong to the span of $S(B_1)$. Under the assumption that $S(B_2)$ generates $\Cl(K)$, we are done. User-supplied $c_i$ are only used to compute initial guesses for the bounds $B_i$, and the algorithm increases them until one can \emph{prove} under GRH that $S(B_2)$ generates $\Cl(K)$. A uniform result of Bach says that $c_2 = 12$ is always suitable, but this bound is very pessimistic and a direct algorithm due to Belabas-Diaz-Friedman is used to check the condition, assuming GRH. The default values are $c_1 = c_2 = 0$. When $c_1$ is equal to $0$ the algorithm takes it equal to $c_2$. $\var{nrpid}$ is the maximal number of small norm relations associated to each ideal in the factor base. Set it to $0$ to disable the search for small norm relations. Otherwise, reasonable values are between 4 and 20. The default is 4. \misctitle{Warning} Make sure you understand the above! By default, most of the \kbd{bnf} routines depend on the correctness of the GRH. In particular, any of the class number, class group structure, class group generators, regulator and fundamental units may be wrong, independently of each other. Any result computed from such a \kbd{bnf} may be wrong. The only guarantee is that the units given generate a subgroup of finite index in the full unit group. You must use \kbd{bnfcertify} to certify the computations unconditionally. \misctitle{Remarks} You do not need to supply the technical parameters (under the library you still need to send at least an empty vector, coded as \kbd{NULL}). However, should you choose to set some of them, they \emph{must} be given in the requested order. For example, if you want to specify a given value of \var{nrpid}, you must give some values as well for $c_1$ and $c_2$, and provide a vector $[c_1,c_2,\var{nrpid}]$. Note also that you can use an $\var{nf}$ instead of $P$, which avoids recomputing the integral basis and analogous quantities. \smallskip %SECTION: number_fields \section{Polynomials and power series} We group here all functions which are specific to polynomials or power series. Many other functions which can be applied on these objects are described in the other sections. Also, some of the functions described here can be applied to other types. %SECTION: polynomials \section{Vectors, matrices, linear algebra and sets} \label{se:linear_algebra} Note that most linear algebra functions operating on subspaces defined by generating sets (such as \tet{mathnf}, \tet{qflll}, etc.) take matrices as arguments. As usual, the generating vectors are taken to be the \emph{columns} of the given matrix. Since PARI does not have a strong typing system, scalars live in unspecified commutative base rings. It is very difficult to write robust linear algebra routines in such a general setting. We thus assume that the base ring is a domain and work over its field of fractions. If the base ring is \emph{not} a domain, one gets an error as soon as a non-zero pivot turns out to be non-invertible. Some functions, e.g.~\kbd{mathnf} or \kbd{mathnfmod}, specifically assume that the base ring is $\Z$. %SECTION: linear_algebra \section{Sums, products, integrals and similar functions} \label{se:sums} Although the \kbd{gp} calculator is programmable, it is useful to have a number of preprogrammed loops, including sums, products, and a certain number of recursions. Also, a number of functions from numerical analysis like numerical integration and summation of series will be described here. One of the parameters in these loops must be the control variable, hence a simple variable name. In the descriptions, the letter $X$ will always denote any simple variable name, and represents the formal parameter used in the function. The expression to be summed, integrated, etc. is any legal PARI expression, including of course expressions using loops. \misctitle{Library mode} Since it is easier to program directly the loops in library mode, these functions are mainly useful for GP programming. On the other hand, numerical routines code a function (to be integrated, summed, etc.) with two parameters named \bprog GEN (*eval)(void*,GEN) void *E; \\ context: eval(E, x) must evaluate your function at x. @eprog\noindent see the Libpari manual for details. \misctitle{Numerical integration}\sidx{numerical integration} Starting with version 2.2.9 the ``double exponential'' univariate integration method is implemented in \tet{intnum} and its variants. Romberg integration is still available under the name \kbd{intnumromb}, but superseded. It is possible to compute numerically integrals to thousands of decimal places in reasonable time, as long as the integrand is regular. It is also reasonable to compute numerically integrals in several variables, although more than two becomes lengthy. The integration domain may be non-compact, and the integrand may have reasonable singularities at endpoints. To use \kbd{intnum}, you must split the integral into a sum of subintegrals where the function has no singularities except at the endpoints. Polynomials in logarithms are not considered singular, and neglecting these logs, singularities are assumed to be algebraic (asymptotic to $C(x-a)^{-\alpha}$ for some $\alpha > -1$ when $x$ is close to $a$), or to correspond to simple discontinuities of some (higher) derivative of the function. For instance, the point $0$ is a singularity of $\text{abs}(x)$. See also the discrete summation methods below, sharing the prefix \kbd{sum}. %SECTION: sums \section{Plotting functions} Although plotting is not even a side purpose of PARI, a number of plotting functions are provided. Moreover, a lot of people \footnote{*}{Among these, special thanks go to Klaus-Peter Nischke who suggested the recursive plotting and forking/resizing stuff the graphical window, and Ilya Zakharevich who rewrote the graphic code from scratch implementing many new primitives (splines, clipping). Nils Skoruppa and Bill Allombert wrote the \tet{Qt} and \tet{fltk} graphic drivers respectively.} suggested ideas or submitted patches for this section of the code. There are three types of graphic functions. \subsec{High-level plotting functions} (all the functions starting with \kbd{ploth}) in which the user has little to do but explain what type of plot he wants, and whose syntax is similar to the one used in the preceding section. \subsec{Low-level plotting functions} (called \var{rectplot} functions, sharing the prefix \kbd{plot}), where every drawing primitive (point, line, box, etc.) is specified by the user. These low-level functions work as follows. You have at your disposal 16 virtual windows which are filled independently, and can then be physically ORed on a single window at user-defined positions. These windows are numbered from 0 to 15, and must be initialized before being used by the function \kbd{plotinit}, which specifies the height and width of the virtual window (called a \var{rectwindow} in the sequel). At all times, a virtual cursor (initialized at $[0,0]$) is associated to the window, and its current value can be obtained using the function \kbd{plotcursor}. A number of primitive graphic objects (called \var{rect} objects) can then be drawn in these windows, using a default color associated to that window (which can be changed using the \kbd{plotcolor} function) and only the part of the object which is inside the window will be drawn, with the exception of polygons and strings which are drawn entirely. The ones sharing the prefix \kbd{plotr} draw relatively to the current position of the virtual cursor, the others use absolute coordinates. Those having the prefix \kbd{plotrecth} put in the rectwindow a large batch of rect objects corresponding to the output of the related \kbd{ploth} function. Finally, the actual physical drawing is done using \kbd{plotdraw}. The rectwindows are preserved so that further drawings using the same windows at different positions or different windows can be done without extra work. To erase a window, use \kbd{plotkill}. It is not possible to partially erase a window: erase it completely, initialize it again, then fill it with the graphic objects that you want to keep. In addition to initializing the window, you may use a scaled window to avoid unnecessary conversions. For this, use \kbd{plotscale}. As long as this function is not called, the scaling is simply the number of pixels, the origin being at the upper left and the $y$-coordinates going downwards. Plotting functions are platform independent, but a number of graphical drivers are available for screen output: X11-windows (hence also for GUI's based on X11 such as Openwindows and Motif), and the Qt and FLTK graphical libraries. The physical window opened by \kbd{plotdraw} or any of the \kbd{ploth*} functions is completely separated from \kbd{gp} (technically, a \kbd{fork} is done, and the non-graphical memory is immediately freed in the child process), which means you can go on working in the current \kbd{gp} session, without having to kill the window first. This window can be closed, enlarged or reduced using the standard window manager functions. No zooming procedure is implemented though (yet). \subsec{Functions for PostScript output} in the same way that \kbd{printtex} allows you to have a \TeX\ output corresponding to printed results, the functions starting with \kbd{ps} allow you to have \tet{PostScript} output of the plots. This will not be identical with the screen output, but sufficiently close. Note that you can use PostScript output even if you do not have the plotting routines enabled. The PostScript output is written in a file whose name is derived from the \tet{psfile} default (\kbd{./pari.ps} if you did not tamper with it). Each time a new PostScript output is asked for, the PostScript output is appended to that file. Hence you probably want to remove this file, or change the value of \kbd{psfile}, in between plots. On the other hand, in this manner, as many plots as desired can be kept in a single file. \smallskip \subsec{Library mode} \emph{None of the graphic functions are available within the PARI library, you must be under \kbd{gp} to use them}. The reason for that is that you really should not use PARI for heavy-duty graphical work, there are better specialized alternatives around. This whole set of routines was only meant as a convenient, but simple-minded, visual aid. If you really insist on using these in your program (we warned you), the source (\kbd{plot*.c}) should be readable enough for you to achieve something. %SECTION: graphic \section{Programming in GP: control statements} \sidx{programming}\label{se:programming} A number of control statements are available in GP. They are simpler and have a syntax slightly different from their C counterparts, but are quite powerful enough to write any kind of program. Some of them are specific to GP, since they are made for number theorists. As usual, $X$ will denote any simple variable name, and \var{seq} will always denote a sequence of expressions, including the empty sequence. \misctitle{Caveat} In constructs like \bprog for (X = a,b, seq) @eprog\noindent the variable \kbd{X} is lexically scoped to the loop, leading to possibly unexpected behavior: \bprog n = 5; for (n = 1, 10, if (something_nice(), break); ); \\ @com at this point \kbd{n} is 5 ! @eprog\noindent If the sequence \kbd{seq} modifies the loop index, then the loop is modified accordingly: \bprog ? for (n = 1, 10, n += 2; print(n)) 3 6 9 12 @eprog %SECTION: programming/control \section{Programming in GP: other specific functions} \label{se:gp_program} In addition to the general PARI functions, it is necessary to have some functions which will be of use specifically for \kbd{gp}, though a few of these can be accessed under library mode. Before we start describing these, we recall the difference between \emph{strings} and \emph{keywords} (see \secref{se:strings}): the latter don't get expanded at all, and you can type them without any enclosing quotes. The former are dynamic objects, where everything outside quotes gets immediately expanded. %SECTION: programming/specific \section{Parallel programming} These function are only available if PARI was configured using \kbd{Configure --mt=\dots}. Two multithread interfaces are supported: \item POSIX threads \item Message passing interface (MPI) As a rule, POSIX threads are well-suited for single systems, while MPI is used by most clusters. However the parallel GP interface does not depend on the chosen multithread interface: a properly written GP program will work identically with both. %SECTION: programming/parallel \section{GP defaults} \label{se:gp_defaults} This section documents the GP defaults %SECTION: default \vfill\eject pari-2.7.5/doc/usersch5.tex0000644000175000017500000157063612460252321014155 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Technical Reference Guide: the basics} In the following chapters, we describe all public low-level functions of the PARI library. These include specialized functions for handling all the PARI types. Simple higher level functions, such as arithmetic or transcendental functions, are described in Chapter~3 of the GP user's manual; we will eventually see more general or flexible versions in the chapters to come. A general introduction to the major concepts of PARI programming can be found in Chapter~4, which you should really read first. We shall now study specialized functions, more efficient than the library wrappers, but sloppier on argument checking and damage control; besides speed, their main advantage is to give finer control about the inner workings of generic routines, offering more options to the programmer. \misctitle{Important advice} Generic routines eventually call lower level functions. Optimize your algorithms first, not overhead and conversion costs between PARI routines. For generic operations, use generic routines first; do not waste time looking for the most specialized one available unless you identify a genuine bottleneck, or you need some special behavior the generic routine does not offer. The PARI source code is part of the documentation; look for inspiration there.\smallskip The type \kbd{long} denotes a \tet{BITS_IN_LONG}-bit signed long integer (32 or 64 bits). The type \tet{ulong} is defined as \kbd{unsigned long}. The word \emph{stack} always refer to the PARI stack, allocated through an initial \kbd{pari\_init} call. Refer to Chapters 1--2 and~4 for general background. \kbdsidx{BIL} We shall often refer to the notion of \tev{shallow} function, which means that some components of the result may point to components of the input, which is more efficient than a \emph{deep} copy (full recursive copy of the object tree). Such outputs are not suitable for \kbd{gerepileupto} and particular care must be taken when garbage collecting objects which have been input to shallow functions: corresponding outputs also become invalid and should no longer be accessed. A function is \emph{not stack clean} if it leaves intermediate data on the stack besides its output, for efficiency reasons. \section{Initializing the library} The following functions enable you to start using the PARI functions in a program, and cleanup without exiting the whole program. \subsec{General purpose} \fun{void}{pari_init}{size_t size, ulong maxprime} initialize the library, with a stack of \kbd{size} bytes and a prime table up to the maximum of \kbd{maxprime} and $2^{16}$. Unless otherwise mentioned, no PARI function will function properly before such an initialization. \fun{void}{pari_close}{void} stop using the library (assuming it was initialized with \kbd{pari\_init}) and frees all allocated objects. \subsec{Technical functions}\label{se:pari_init_tech} \fun{void}{pari_init_opts}{size_t size, ulong maxprime, ulong opts} as \kbd{pari\_init}, more flexible. \kbd{opts} is a mask of flags among the following: \kbd{INIT\_JMPm}: install PARI error handler. When an exception is raised, the program is terminated with \kbd{exit(1)}. \kbd{INIT\_SIGm}: install PARI signal handler. \kbd{INIT\_DFTm}: initialize the \kbd{GP\_DATA} environment structure. This one \emph{must} be enabled once. If you close pari, then restart it, you need not reinitialize \kbd{GP\_DATA}; if you do not, then old values are restored. \kbd{INIT\_noPRIMEm}: do not compute the prime table (ignore the \kbd{maxprime} argument). The user \emph{must} call \tet{initprimetable} later. \kbd{INIT\_noIMTm}: (technical, see \kbd{pari\_mt\_init} in the Developer's Guide for detail). Do not call \tet{pari_mt_init} to initialize the multi-thread engine. If this flag is set, \kbd{pari\_mt\_init()} will need to be called manually. See \kbd{examples/pari-mt.c} for an example. \fun{void}{pari_close_opts}{ulong init_opts} as \kbd{pari\_close}, for a library initialized with a mask of options using \kbd{pari\_init\_opts}. \kbd{opts} is a mask of flags among \kbd{INIT\_SIGm}: restore \kbd{SIG\_DFL} default action for signals tampered with by PARI signal handler. \kbd{INIT\_DFTm}: frees the \kbd{GP\_DATA} environment structure. \kbd{INIT\_noIMTm}: (technical, see \kbd{pari\_mt\_init} in the Developer's Guide for detail). Do not call \tet{pari_mt_close} to close the multi-thread engine. \fun{void}{pari_sig_init}{void (*f)(int)} install the signal handler \kbd{f} (see \kbd{signal(2)}): the signals \kbd{SIGBUS}, \kbd{SIGFPE}, \kbd{SIGINT}, \kbd{SIGBREAK}, \kbd{SIGPIPE} and \kbd{SIGSEGV} are concerned. \fun{void}{pari_stackcheck_init}{void *stackbase} controls the system stack exhaustion checking code in the GP interpreter. This should be used when the system stack base address change or when the address seen by \kbd{pari\_init} is too far from the base address. If \kbd{stackbase} is \kbd{NULL}, disable the check, else set the base address to \kbd{stackbase}. It is normally used this way \bprog int thread_start (...) { long first_item_on_the_stack; ... pari_stackcheck_init(&first_item_on_the_stack); } @eprog \fun{int}{pari_daemon}{void} fork a PARI daemon, detaching from the main process group. The function returns 1 in the parent, and 0 in the forked son. \subsec{Notions specific to the GP interpreter} An \kbd{entree} is the generic object associated to an identifier (a name) in GP's interpreter, be it a built-in or user function, or a variable. For a function, it has at least the following fields: \kbd{char *name}: the name under which the interpreter knows us. \kbd{void *value}: a pointer to the C function to call. \kbd{long menu}: an integer from 1 to 11 (to which group of function help do we belong). \kbd{char *code}: the prototype code. \kbd{char *help}: the help text for the function. A routine in GP is described to the analyzer by an \kbd{entree} structure. Built-in PARI routines are grouped in \emph{modules}, which are arrays of \kbd{entree} structs, the last of which satisfy \kbd{name = NULL} (sentinel). There are currently five modules in PARI/GP: general functions (\tet{functions_basic}, known to \kbd{libpari}), gp-specific functions (\tet{functions_gp}), gp-specific highlevel functions (\tet{functions_highlevel}), and two modules of obsolete functions. The function \kbd{pari\_init} initializes the interpreter and declares all symbols in \kbd{functions\_basic}. You may declare further functions on a case by case basis or as a whole module using \fun{void}{pari_add_function}{entree *ep} adds a single routine to the table of symbols in the interpreter. It assumes \kbd{pari\_init} has been called. \fun{void}{pari_add_module}{entree *mod} adds all the routines in module \kbd{mod} to the table of symbols in the interpreter. It assumes \kbd{pari\_init} has been called. \noindent For instance, gp implements a number of private routines, which it adds to the default set via the calls \bprog pari_add_module(functions_gp); 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. \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 been called. From this point on, all defaults in module \kbd{mod} are known to \tet{setdefault} and friends. \subsec{Public callbacks} The \kbd{gp} calculator associates elaborate functions (for instance the break loop handler) to the following callbacks, and so can you: \doc{cb_pari_ask_confirm}{void (*cb_pari_ask_confirm)(const char *s)} 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)} 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. \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"); @eprog \doc{cb_pari_pre_recover}{extern 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)} 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 it is called with argument $-1$. \doc{cb_pari_whatnow}{int (*cb_pari_whatnow)(PariOUT *out, const char *s, int flag)} initialized to \kbd{NULL}. If not \kbd{NULL}, must check whether $s$ existed in older versions of \kbd{pari} (the \kbd{gp} callback checks against \kbd{pari-1.39.15}). All output must be done via \kbd{out} methods. \item $\fl = 0$: should print verbosely the answer, including help text if available. \item $\fl = 1$: must return $0$ if the function did not change, and a non-$0$ result otherwise. May print a help message. \subsec{Configuration variables} \tet{pari_library_path}: If set, It should be a path to the libpari library. 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} \fun{void}{pari_ask_confirm}{const char *s} raise an error if the callback \tet{cb_pari_ask_confirm} is \kbd{NULL}. Otherwise calls \bprog cb_pari_ask_confirm(s); @eprog \subsec{Saving and restoring the GP context} \fun{void}{gp_context_save}{struct gp_context* rec} save the current GP context. \fun{void}{gp_context_restore}{struct gp_context* rec} restore a GP context. The new context must be an ancestor of the current context. \subsec{GP history} These functions allow to control the GP history (the \kbd{\%} operator). \fun{void}{pari_add_hist}{GEN x, long t} adds \kbd{x} as the last history entry; $t$ is the time we used to compute it. \fun{GEN}{pari_get_hist}{long p}, if $p>0$ returns entry of index $p$ (i.e. \kbd{\%p}), else returns entry of index $n+p$ where $n$ is the index of the last entry (used for \kbd{\%}, \kbd{\%`}, \kbd{\%``}, etc.). \fun{long}{pari_get_histtime}{long p} as \tet{pari_get_hist}, returning the time used to compute the history entry, instead of the entry itself. \fun{ulong}{pari_nb_hist}{void} return the index of the last entry. \section{Handling \kbd{GEN}s} \noindent Almost all these functions are either macros or inlined. Unless mentioned otherwise, they do not evaluate their arguments twice. Most of them are specific to a set of types, although no consistency checks are made: e.g.~one may access the \kbd{sign} of a \typ{PADIC}, but the result is meaningless. \subsec{Allocation} \fun{GEN}{cgetg}{long l, long t} allocates (the root of) a \kbd{GEN} of type $t$ and length $l$. Sets $z[0]$. \fun{GEN}{cgeti}{long l} allocates a \typ{INT} of length $l$ (including the 2 codewords). Sets $z[0]$ only. \fun{GEN}{cgetr}{long l} allocates a \typ{REAL} of length $l$ (including the 2 codewords). Sets $z[0]$ only. \fun{GEN}{cgetc}{long prec} allocates a \typ{COMPLEX} whose real and imaginary parts are \typ{REAL}s of length \kbd{prec}. \fun{GEN}{cgetg_copy}{GEN x, long *lx} fast version of \kbd{cgetg}: allocate a \kbd{GEN} with the same type and length as $x$, setting \kbd{*lx} to \kbd{lg(x)} as a side-effect. (Only sets the first codeword.) This is a little faster than \kbd{cgetg} since we may reuse the bitmask in $x[0]$ instead of recomputing it, and we do not need to check that the length does not overflow the possibilities of the implementation (since an object with that length already exists). Note that \kbd{cgetg} with arguments known at compile time, as in \bprog cgetg(3, t_INTMOD) @eprog\noindent will be even faster since the compiler will directly perform all computations and checks. \fun{GEN}{vectrunc_init}{long l} perform \kbd{cgetg(l,t\_VEC)}, then set the length to $1$ and return the result. This is used to implement vectors whose final length is easily bounded at creation time, that we intend to fill gradually using: \fun{void}{vectrunc_append}{GEN x, GEN y} assuming $x$ was allocated using \tet{vectrunc_init}, appends $y$ as the last element of $x$, which grows in the process. The function is shallow: we append $y$, not a copy; it is equivalent to \bprog long lx = lg(x); gel(x,lx) = y; setlg(x, lx+1); @eprog\noindent Beware that the maximal size of $x$ (the $l$ argument to \tet{vectrunc_init}) is unknown, hence unchecked, and stack corruption will occur if we append more than $l-1$ elements to $x$. Use the safer (but slower) \kbd{shallowconcat} when $l$ is not easy to bound in advance. An other possibility is simply to allocate using \kbd{cgetg(l, t)} then fill the components as they become available: this time the downside is that we do not obtain a correct \kbd{GEN} until the vector is complete. Almost no PARI function will be able to operate on it. \fun{void}{vectrunc_append_batch}{GEN x, GEN y} successively apply \bprog vectrunc_append(x, gel(y, i)) @eprog for all elements of the vector $y$. \fun{GEN}{vecsmalltrunc_init}{long l} \fun{void}{vecsmalltrunc_append}{GEN x, long t} analog to the above for a \typ{VECSMALL} container. \subsec{Length conversions} These routines convert a non-negative length to different units. Their behavior is undefined at negative integers. \fun{long}{ndec2nlong}{long x} converts a number of decimal digits to a number of words. Returns $ 1 + \kbd{floor}(x \times \B \log_2 10)$. \fun{long}{ndec2prec}{long x} converts a number of decimal digits to a number of codewords. This is equal to 2 + \kbd{ndec2nlong(x)}. \fun{long}{prec2ndec}{long x} converts a number of of codewords to a number of decimal digits. \fun{long}{nbits2nlong}{long x} converts a number of bits to a number of words. Returns the smallest word count containing $x$ bits, i.e $ \kbd{ceil}(x / \B)$. \fun{long}{nbits2prec}{long x} converts a number of bits to a number of codewords. This is equal to 2 + \kbd{nbits2nlong(x)}. \fun{long}{nchar2nlong}{long x} converts a number of bytes to number of words. Returns the smallest word count containing $x$ bytes, i.e $\kbd{ceil}(x / \kbd{sizeof(long)})$. \fun{long}{bit_accuracy}{long x} converts a \typ{REAL} length into a number of significant bits. Returns $(x - 2)\B$. \fun{double}{bit_accuracy_mul}{long x, double y} returns $(x - 2)\B \times y$. \subsec{Read type-dependent information} \fun{long}{typ}{GEN x} returns the type number of~\kbd{x}. The header files included through \kbd{pari.h} define symbolic constants for the \kbd{GEN} types: \typ{INT} etc. Never use their actual numerical values. E.g to determine whether \kbd{x} is a \typ{INT}, simply check \bprog if (typ(x) == t_INT) { } @eprog\noindent The types are internally ordered and this simplifies the implementation of commutative binary operations (e.g addition, gcd). Avoid using the ordering directly, as it may change in the future; use type grouping functions instead (\secref{se:typegroup}). \fun{const char*}{type_name}{long t} given a type number \kbd{t} this routine returns a string containing its symbolic name. E.g \kbd{type\_name(\typ{INT})} returns \kbd{"\typ{INT}"}. The return value is read-only. \fun{long}{lg}{GEN x} returns the length of~\kbd{x} in \B-bit words. \fun{long}{lgefint}{GEN x} returns the effective length of the \typ{INT} \kbd{x} in \B-bit words. \fun{long}{signe}{GEN x} returns the sign ($-1$, 0 or 1) of~\kbd{x}. Can be used for \typ{INT}, \typ{REAL}, \typ{POL} and \typ{SER} (for the last two types, only 0 or 1 are possible). \fun{long}{gsigne}{GEN x} returns the sign of a real number $x$, valid for \typ{INT}, \typ{REAL} as \kbd{signe}, but also for \typ{FRAC}. Raise a type error if \kbd{typ(x)} is not among those three. \fun{long}{expi}{GEN x} returns the binary exponent of the real number equal to the \typ{INT}~\kbd{x}. This is a special case of \kbd{gexpo}. \fun{long}{expo}{GEN x} returns the binary exponent of the \typ{REAL}~\kbd{x}. \fun{long}{mpexpo}{GEN x} returns the binary exponent of the \typ{INT} or \typ{REAL}~\kbd{x}. \fun{long}{gexpo}{GEN x} same as \kbd{expo}, but also valid when \kbd{x} is not a \typ{REAL} (returns the largest exponent found among the components of \kbd{x}). When \kbd{x} is an exact~0, this returns \hbox{\kbd{-HIGHEXPOBIT}}, which is lower than any valid exponent. \fun{long}{valp}{GEN x} returns the $p$-adic valuation (for a \typ{PADIC}) or $X$-adic valuation (for a \typ{SER}, taken with respect to the main variable) of~\kbd{x}. \fun{long}{precp}{GEN x} returns the precision of the \typ{PADIC}~\kbd{x}. \fun{long}{varn}{GEN x} returns the variable number of the \typ{POL} or \typ{SER}~\kbd{x} (between 0 and \kbd{MAXVARN}). \fun{long}{gvar}{GEN x} returns the main variable number when any variable at all occurs in the composite object~\kbd{x} (the smallest variable number which occurs), and \tet{NO_VARIABLE} otherwise. \fun{long}{gvar2}{GEN x} returns the variable number for the ring over which $x$ is defined, e.g. if $x\in \Z[a][b]$ return (the variable number for) $a$. Return \tet{NO_VARIABLE} if $x$ has no variable or is not defined over a polynomial ring. \fun{long}{degpol}{GEN x} is a simple macro returning \kbd{lg(x) - 3}. This is the degree of the \typ{POL}~\kbd{x} with respect to its main variable, \emph{if} its leading coefficient is non-zero (a rational $0$ is impossible, but an inexact $0$ is allowed, as well as an exact modular $0$, e.g. \kbd{Mod(0,2)}). If $x$ has no coefficients (rational $0$ polynomial), its length is $2$ and we return the expected $-1$. \fun{long}{lgpol}{GEN x} is equal to \kbd{degpol(x) + 1}. Used to loop over the coefficients of a \typ{POL} in the following situation: \bprog GEN xd = x + 2; long i, l = lgpol(x); for (i = 0; i < l; i++) foo( xd[i] ). @eprog \fun{long}{precision}{GEN x} If \kbd{x} is of type \typ{REAL}, returns the precision of~\kbd{x}, namely the length of \kbd{x} in \B-bit words if \kbd{x} is not zero, and a reasonable quantity obtained from the exponent of \kbd{x} if \kbd{x} is numerically equal to zero. If \kbd{x} is of type \typ{COMPLEX}, returns the minimum of the precisions of the real and imaginary part. Otherwise, returns~0 (which stands for infinite precision). \fun{long}{lgcols}{GEN x} is equal to \kbd{lg(gel(x,1))}. This is the length of the columns of a \typ{MAT} with at least one column. \fun{long}{nbrows}{GEN x} is equal to \kbd{lg(gel(x,1))-1}. This is the number of rows of a \typ{MAT} with at least one column. \fun{long}{gprecision}{GEN x} as \kbd{precision} for scalars. Returns the lowest precision encountered among the components otherwise. \fun{long}{sizedigit}{GEN x} returns 0 if \kbd{x} is exactly~0. Otherwise, returns \kbd{\key{gexpo}(x)} multiplied by $\log_{10}(2)$. This gives a crude estimate for the maximal number of decimal digits of the components of~\kbd{x}. \subsec{Eval type-dependent information} These routines convert type-dependent information to bitmask to fill the codewords of \kbd{GEN} objects (see \secref{se:impl}). E.g for a \typ{REAL}~\kbd{z}: \bprog z[1] = evalsigne(-1) | evalexpo(2) @eprog Compatible components of a codeword for a given type can be OR-ed as above. \fun{ulong}{evaltyp}{long x} convert type~\kbd{x} to bitmask (first codeword of all \kbd{GEN}s) \fun{long}{evallg}{long x} convert length~\kbd{x} to bitmask (first codeword of all \kbd{GEN}s). Raise overflow error if \kbd{x} is so large that the corresponding length cannot be represented \fun{long}{_evallg}{long x} as \kbd{evallg} \emph{without} the overflow check. \fun{ulong}{evalvarn}{long x} convert variable number~\kbd{x} to bitmask (second codeword of \typ{POL} and \typ{SER}) \fun{long}{evalsigne}{long x} convert sign~\kbd{x} (in $-1,0,1$) to bitmask (second codeword of \typ{INT}, \typ{REAL}, \typ{POL}, \typ{SER}) \fun{long}{evalprecp}{long x} convert $p$-adic ($X$-adic) precision~\kbd{x} to bitmask (second codeword of \typ{PADIC}, \typ{SER}). Raise overflow error if \kbd{x} is so large that the corresponding precision cannot be represented. \fun{long}{_evalprecp}{long x} same as \kbd{evalprecp} \emph{without} the overflow check. \fun{long}{evalvalp}{long x} convert $p$-adic ($X$-adic) valuation~\kbd{x} to bitmask (second codeword of \typ{PADIC}, \typ{SER}). Raise overflow error if \kbd{x} is so large that the corresponding valuation cannot be represented. \fun{long}{_evalvalp}{long x} same as \kbd{evalvalp} \emph{without} the overflow check. \fun{long}{evalexpo}{long x} convert exponent~\kbd{x} to bitmask (second codeword of \typ{REAL}). Raise overflow error if \kbd{x} is so large that the corresponding exponent cannot be represented \fun{long}{_evalexpo}{long x} same as \kbd{evalexpo} \emph{without} the overflow check. \fun{long}{evallgefint}{long x} convert effective length~\kbd{x} to bitmask (second codeword \typ{INT}). This should be less or equal than the length of the \typ{INT}, hence there is no overflow check for the effective length. \subsec{Set type-dependent information} Use these functions and macros with extreme care since usually the corresponding information is set otherwise, and the components and further codeword fields (which are left unchanged) may not be compatible with the new information. \fun{void}{settyp}{GEN x, long s} sets the type number of~\kbd{x} to~\kbd{s}. \fun{void}{setlg}{GEN x, long s} sets the length of~\kbd{x} to~\kbd{s}. This is an efficient way of truncating vectors, matrices or polynomials. \fun{void}{setlgefint}{GEN x, long s} sets the effective length of the \typ{INT} \kbd{x} to~\kbd{s}. The number \kbd{s} must be less than or equal to the length of~\kbd{x}. \fun{void}{setsigne}{GEN x, long s} sets the sign of~\kbd{x} to~\kbd{s}. If \kbd{x} is a \typ{INT} or \typ{REAL}, \kbd{s} must be equal to $-1$, 0 or~1, and if \kbd{x} is a \typ{POL} or \typ{SER}, \kbd{s} must be equal to 0 or~1. No sanity check is made; in particular, setting the sign of a $0$ \typ{INT} to $\pm1$ creates an invalid object. \fun{void}{togglesign}{GEN x} sets the sign $s$ of~\kbd{x} to $-s$, in place. \fun{void}{togglesign_safe}{GEN *x} sets the $s$ sign of~\kbd{*x} to $-s$, in place, unless \kbd{*x} is one of the integer universal constants in which case replace \kbd{*x} by its negation (e.g.~replace \kbd{gen\_1} by \kbd{gen\_m1}). \fun{void}{setabssign}{GEN x} sets the sign $s$ of~\kbd{x} to $|s|$, in place. \fun{void}{affectsign}{GEN x, GEN y} shortcut for \kbd{setsigne(y, signe(x))}. No sanity check is made; in particular, setting the sign of a $0$ \typ{INT} to $\pm1$ creates an invalid object. \fun{void}{affectsign_safe}{GEN x, GEN *y} sets the sign of~\kbd{*y} to that of~\kbd{x}, in place, unless \kbd{*y} is one of the integer universal constants in which case replace \kbd{*y} by its negation if needed (e.g.~replace \kbd{gen\_1} by \kbd{gen\_m1} if \kbd{x} is negative). No other sanity check is made; in particular, setting the sign of a $0$ \typ{INT} to $\pm1$ creates an invalid object. \fun{void}{normalize_frac}{GEN z} assuming $z$ is of the form \kbd{mkfrac(a,b)} with $b\neq 0$, make sure that $b > 0$ by changing the sign of $a$ in place if needed (use \kbd{togglesign}). \fun{void}{setexpo}{GEN x, long s} sets the binary exponent of the \typ{REAL}~\kbd{x} to \kbd{s}. The value \kbd{s} must be a 24-bit signed number. \fun{void}{setvalp}{GEN x, long s} sets the $p$-adic or $X$-adic valuation of~\kbd{x} to~\kbd{s}, if \kbd{x} is a \typ{PADIC} or a \typ{SER}, respectively. \fun{void}{setprecp}{GEN x, long s} sets the $p$-adic precision of the \typ{PADIC}~\kbd{x} to~\kbd{s}. \fun{void}{setvarn}{GEN x, long s} sets the variable number of the \typ{POL} or \typ{SER}~\kbd{x} to~\kbd{s} (where $0\le \kbd{s}\le\kbd{MAXVARN}$). \subsec{Type groups}\label{se:typegroup} In the following functions, \kbd{t} denotes the type of a \kbd{GEN}. They used to be implemented as macros, which could evaluate their argument twice; \emph{no longer}: it is not inefficient to write \bprog is_intreal_t(typ(x)) @eprog \fun{int}{is_recursive_t}{long t} \kbd{true} iff \kbd{t} is a recursive type (the non-recursive types are \typ{INT}, \typ{REAL}, \typ{STR}, \typ{VECSMALL}). Somewhat contrary to intuition, \typ{LIST} is also non-recursive, ; see the Developer's guide for details. \fun{int}{is_intreal_t}{long t} \kbd{true} iff \kbd{t} is \typ{INT} or \typ{REAL}. \fun{int}{is_rational_t}{long t} \kbd{true} iff \kbd{t} is \typ{INT} or \typ{FRAC}. \fun{int}{is_vec_t}{long t} \kbd{true} iff \kbd{t} is \typ{VEC} or \typ{COL}. \fun{int}{is_matvec_t}{long t} \kbd{true} iff \kbd{t} is \typ{MAT}, \typ{VEC} or \typ{COL}. \fun{int}{is_scalar_t}{long t} \kbd{true} iff \kbd{t} is a scalar, i.e a \typ{INT}, a \typ{REAL}, a \typ{INTMOD}, a \typ{FRAC}, a \typ{COMPLEX}, a \typ{PADIC}, a \typ{QUAD}, or a \typ{POLMOD}. \fun{int}{is_extscalar_t}{long t} \kbd{true} iff \kbd{t} is a scalar (see \kbd{is\_scalar\_t}) or \kbd{t} is \typ{POL}. \fun{int}{is_const_t}{long t} \kbd{true} iff \kbd{t} is a scalar which is not \typ{POLMOD}. \fun{int}{is_noncalc_t}{long t} true if generic operations (\kbd{gadd}, \kbd{gmul}) do not make sense for $t$: corresponds to types \typ{LIST}, \typ{STR}, \typ{VECSMALL}, \typ{CLOSURE} \subsec{Accessors and components}\label{se:accessors} The first two functions return \kbd{GEN} components as copies on the stack: \fun{GEN}{compo}{GEN x, long n} creates a copy of the \kbd{n}-th true component (i.e.\ not counting the codewords) of the object~\kbd{x}. \fun{GEN}{truecoeff}{GEN x, long n} creates a copy of the coefficient of degree~\kbd{n} of~\kbd{x} if \kbd{x} is a scalar, \typ{POL} or \typ{SER}, and otherwise of the \kbd{n}-th component of~\kbd{x}. \smallskip \noindent On the contrary, the following routines return the address of a \kbd{GEN} component. No copy is made on the stack: \fun{GEN}{constant_term}{GEN x} returns the address of the constant coefficient of \typ{POL}~\kbd{x}. By convention, a $0$ polynomial (whose \kbd{sign} is $0$) has \kbd{gen\_0} constant term. \fun{GEN}{leading_term}{GEN x} returns the address of the leading coefficient of \typ{POL}~\kbd{x}, i.e. the coefficient of largest index stored in the array representing $x$. This may be an inexact $0$. By convention, return \kbd{gen\_0} if the coefficient array is empty. \fun{GEN}{gel}{GEN x, long i} returns the address of the \kbd{x[i]} entry of~\kbd{x}. (\kbd{el} stands for element.) \fun{GEN}{gcoeff}{GEN x, long i, long j} returns the address of the \kbd{x[i,j]} entry of \typ{MAT}~\kbd{x}, i.e.~the coefficient at row~\kbd{i} and column~\kbd{j}. \fun{GEN}{gmael}{GEN x, long i, long j} returns the address of the \kbd{x[i][j]} entry of~\kbd{x}. (\kbd{mael} stands for multidimensional array element.) \fun{GEN}{gmael2}{GEN A, long x1, long x2} is an alias for \kbd{gmael}. Similar macros \tet{gmael3}, \tet{gmael4}, \tet{gmael5} are available. \section{Global numerical constants} These are defined in the various public PARI headers. \subsec{Constants related to word size} \noindent \kbd{long} $\tet{BITS_IN_LONG} = 2^{\tet{TWOPOTBITS_IN_LONG}}$: number of bits in a \kbd{long} (32 or 64). \noindent \kbd{long} \tet{BITS_IN_HALFULONG}: \kbd{BITS\_IN\_LONG} divided by $2$. \noindent \kbd{long} \tet{LONG_MAX}: the largest positive \kbd{long}. \noindent \kbd{ulong} \tet{ULONG_MAX}: the largest \kbd{ulong}. \noindent \kbd{long} \tet{DEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 64 bits of accuracy \noindent \kbd{long} \tet{MEDDEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 128 bits of accuracy \noindent \kbd{long} \tet{BIGDEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 192 bits of accuracy \noindent \kbd{ulong} \tet{HIGHBIT}: the largest power of $2$ fitting in an \kbd{ulong}. \noindent \kbd{ulong} \tet{LOWMASK}: bitmask yielding the least significant bits. \noindent \kbd{ulong} \tet{HIGHMASK}: bitmask yielding the most significant bits. \noindent The last two are used to implement the following convenience macros, returning half the bits of their operand: \fun{ulong}{LOWWORD}{ulong a} returns least significant bits. \fun{ulong}{HIGHWORD}{ulong a} returns most significant bits. \noindent Finally \fun{long}{divsBIL}{long n} returns the Euclidean quotient of $n$ by \kbd{BITS\_IN\_LONG} (with non-negative remainder). \fun{long}{remsBIL}{n} returns the (non-negative) Euclidean remainder of $n$ by \kbd{BITS\_IN\_LONG} \fun{long}{dvmdsBIL}{long n, long *r} \fun{ulong}{dvmduBIL}{ulong n, ulong *r} sets $r$ to \kbd{remsBIL(n)} and returns \kbd{divsBIL(n)}. \subsec{Masks used to implement the \kbd{GEN} type} These constants are used by higher level macros, like \kbd{typ} or \kbd{lg}: \noindent \tet{EXPOnumBITS}, \tet{LGnumBITS}, \tet{SIGNnumBITS}, \tet{TYPnumBITS}, \tet{VALPnumBITS}, \tet{VARNnumBITS}: number of bits used to encode \kbd{expo}, \kbd{lg}, \kbd{signe}, \kbd{typ}, \kbd{valp}, \kbd{varn}. \noindent \tet{PRECPSHIFT}, \tet{SIGNSHIFT}, \tet{TYPSHIFT}, \tet{VARNSHIFT}: shifts used to recover or encode \kbd{precp}, \kbd{varn}, \kbd{typ}, \kbd{signe} \noindent \tet{CLONEBIT}, \tet{EXPOBITS}, \tet{LGBITS}, \tet{PRECPBITS}, \tet{SIGNBITS}, \tet{TYPBITS}, \tet{VALPBITS}, \tet{VARNBITS}: bitmasks used to extract \kbd{isclone}, \kbd{expo}, \kbd{lg}, \kbd{precp}, \kbd{signe}, \kbd{typ}, \kbd{valp}, \kbd{varn} from \kbd{GEN} codewords. \noindent \tet{MAXVARN}: the largest possible variable number. \noindent \tet{NO_VARIABLE}: sentinel returned by \kbd{gvar(x)} when \kbd{x} does not contain any polynomial; has a lower priority than any valid variable number. \noindent \tet{HIGHEXPOBIT}: a power of $2$, one more that the largest possible exponent for a \typ{REAL}. \noindent \tet{HIGHVALPBIT}: a power of $2$, one more that the largest possible valuation for a \typ{PADIC} or a \typ{SER}. \subsec{$\log 2$, $\pi$} These are \kbd{double} approximations to useful constants: \noindent \tet{LOG2}: $\log 2$. \noindent \tet{LOG10_2}: $\log 2 / \log 10$. \noindent \tet{LOG2_10}: $\log 10 / \log 2$. \noindent \tet{PI}: $\pi$. \section{Iterating over small primes, low-level interface} \label{se:primetable} One of the methods used by the high-level prime iterator (see \secref{se:primeiter}), is a precomputed table. Its direct use is deprecated, but documented here. After \kbd{pari\_init(size, maxprime)}, a ``prime table'' is initialized with the successive \emph{differences} of primes up to (possibly just a little beyond) \kbd{maxprime}. The prime table occupies roughly $\kbd{maxprime}/\log(\kbd{maxprime})$ bytes in memory, so be sensible when choosing \kbd{maxprime}; it is $500000$ by default under \kbd{gp} and there is no real benefit in choosing a much larger value: the high-level iterator provide \emph{fast} access to primes up to the \emph{square} of \kbd{maxprime}. In any case, the implementation requires that $\tet{maxprime} < 2^{\B} - 2048$, whatever memory is available. PARI currently guarantees that the first 6547 primes, up to and including 65557, are present in the table, even if you set \kbd{maxprime} to zero. in the \kbd{pari\_init} call. \noindent Some convenience functions: \fun{ulong}{maxprime}{} the largest prime computable using our prime table. \fun{void}{maxprime_check}{ulong B} raise an error if \kbd{maxprime()} is $< B$. After the following initializations (the names $p$ and \var{ptr} are arbitrary of course) \bprog byteptr ptr = diffptr; ulong p = 0; @eprog \noindent calling the macro \tet{NEXT_PRIME_VIADIFF_CHECK}$(p, \var{ptr})$ repeatedly will assign the successive prime numbers to $p$. Overrunning the prime table boundary will raise the error \tet{e_MAXPRIME}, which will just print the error message: \kbd{*** not enough precomputed primes, need primelimit \til $c$} \noindent (for some numerical value $c$), then abort the computation. The alternative macro \tet{NEXT_PRIME_VIADIFF} operates in the same way, but will omit that check, and is slightly faster. It should be used in the following way: % \bprog byteptr ptr = diffptr; ulong p = 0; if (maxprime() < goal) pari_err_MAXPRIME(goal); /*@Ccom not enough primes */ while (p <= goal) /*@Ccom run through all primes up to \kbd{goal} */ { NEXT_PRIME_VIADIFF(p, ptr); ... } @eprog\noindent Here, we use the general error handling function \kbd{pari\_err} (see \secref{se:err}), with the codeword \kbd{e\_MAXPRIME}, raising the ``not enough primes'' error. This could be rewritten as \bprog maxprime_check(goal); while (p <= goal) /*@Ccom run through all primes up to \kbd{goal} */ { NEXT_PRIME_VIADIFF(p, ptr); ... } @eprog \fun{bytepr}{initprimes}{ulong maxprime, long *L, ulong *lastp} computes a (malloc'ed) ``prime table'', in fact a table of all prime differences for $p < \kbd{maxprime}$ (and possibly a little beyond). Set $L$ to the table length (argument to \kbd{malloc}), and \var{lastp} to the last prime in the table. \fun{void}{initprimetable}{ulong maxprime} computes a prime table (of all prime differences for $p < \kbd{maxprime}$) and assign it to the global variable \kbd{diffptr}. Don't change \kbd{diffptr} directly, call this function instead. This calls \kbd{initprimes} and updates internal data recording the table size. \fun{ulong}{init_primepointer_geq}{ulong a, byteptr *pd} returns the smallest prime $p \geq a$, and sets \kbd{*pd} to the proper offset of \kbd{diffptr} so that \kbd{NEXT\_PRIME\_VIADIFF(p, *pd)} correctly returns \kbd{unextprime(p + 1)}. \fun{ulong}{init_primepointer_gt}{ulong a, byteptr *pd} returns the smallest prime $p > a$. \fun{ulong}{init_primepointer_leq}{ulong a, byteptr *pd} returns the largest prime $p \leq a$. \fun{ulong}{init_primepointer_lt}{ulong a, byteptr *pd} returns the largest prime $p < a$. \section{Handling the PARI stack} \subsec{Allocating memory on the stack} \fun{GEN}{cgetg}{long n, long t} allocates memory on the stack for an object of length \kbd{n} and type~\kbd{t}, and initializes its first codeword. \fun{GEN}{cgeti}{long n} allocates memory on the stack for a \typ{INT} of length~\kbd{n}, and initializes its first codeword. Identical to \kbd{cgetg(n,\typ{INT})}. \fun{GEN}{cgetr}{long n} allocates memory on the stack for a \typ{REAL} of length~\kbd{n}, and initializes its first codeword. Identical to \kbd{cgetg(n,\typ{REAL})}. \fun{GEN}{cgetc}{long n} allocates memory on the stack for a \typ{COMPLEX}, whose real and imaginary parts are \typ{REAL}s of length~\kbd{n}. \fun{GEN}{cgetp}{GEN x} creates space sufficient to hold the \typ{PADIC}~\kbd{x}, and sets the prime $p$ and the $p$-adic precision to those of~\kbd{x}, but does not copy (the $p$-adic unit or zero representative and the modulus of)~\kbd{x}. \fun{GEN}{new_chunk}{size_t n} allocates a \kbd{GEN} with $n$ components, \emph{without} filling the required code words. This is the low-level constructor underlying \kbd{cgetg}, which calls \kbd{new\_chunk} then sets the first code word. It works by simply returning the address \kbd{((GEN)avma) - n}, after checking that it is larger than \kbd{(GEN)bot}. \fun{char*}{stack_malloc}{size_t n} allocates memory on the stack for $n$ chars (\emph{not} $n$ \kbd{GEN}s). This is faster than using \kbd{malloc}, and easier to use in most situations when temporary storage is needed. In particular there is no need to \kbd{free} individually all variables thus allocated: a simple \kbd{avma = oldavma} might be enough. On the other hand, beware that this is not permanent independent storage, but part of the stack. \fun{char*}{stack_calloc}{size_t n} as \kbd{stack\_malloc}, setting the memory to zero. \noindent Objects allocated through these last three functions cannot be \kbd{gerepile}'d, since they are not yet valid \kbd{GEN}s: their codewords must be filled first. \fun{GEN}{cgetalloc}{long t, size_t l}, same as \kbd{cgetg(t, l)}, except that the result is allocated using \tet{pari_malloc} instead of the PARI stack. The resulting \kbd{GEN} is now impervious to garbage collecting routines, but should be freed using \tet{pari_free}. \subsec{Stack-independent binary objects} \fun{GENbin*}{copy_bin}{GEN x} copies $x$ into a malloc'ed structure suitable for stack-independent binary transmission or storage. The object obtained is architecture independent provided, \kbd{sizeof(long)} remains the same on all PARI instances involved, as well as the multiprecision kernel (either native or GMP). \fun{GENbin*}{copy_bin_canon}{GEN x} as \kbd{copy\_bin}, ensuring furthermore that the binary object is independent of the multiprecision kernel. Slower than \kbd{copy\_bin}. \fun{GEN}{bin_copy}{GENbin *p} assuming $p$ was created by \kbd{copy\_bin(x)} (not necessarily by the same PARI instance: transmission or external storage may be involved), restores $x$ on the PARI stack. \noindent The routine \kbd{bin\_copy} transparently encapsulate the following functions: \fun{GEN}{GENbinbase}{GENbin *p} the \kbd{GEN} data actually stored in $p$. All addresses are stored as offsets with respect to a common reference point, so the resulting \kbd{GEN} is unusable unless it is a non-recursive type; private low-level routines must be called first to restore absolute addresses. \fun{void}{shiftaddress}{GEN x, long dec} converts relative addresses to absolute ones. \fun{void}{shiftaddress_canon}{GEN x, long dec} converts relative addresses to absolute ones, and converts leaves from a canonical form to the one specific to the multiprecision kernel in use. The \kbd{GENbin} type stores whether leaves are stored in canonical form, so \kbd{bin\_copy} can call the right variant. \noindent Objects containing closures are harder to e.g. copy and save to disk, since closures contain pointers to libpari functions that will not be valid in another gp instance: there is little chance for them to be loaded at the exact same address in memory. Such objects must be saved along with a linking table. \fun{GEN}{copybin_unlink}{GEN C} returns a linking table allowing to safely store and transmit \typ{CLOSURE} objects in $C$. If $C = \kbd{NULL}$ return a linking table corresponding to the content of all gp variables. $C$ may then be dumped to disk in binary form, for instance. \fun{void}{bincopy_relink}{GEN C, GEN V} given a binary object $C$, as dumped by writebin and read back into a session, and a linking table $V$, restore all closures contained in $C$ (function pointers are translated to their current value). \subsec{Garbage collection} See \secref{se:garbage} for a detailed explanation and many examples. \fun{void}{cgiv}{GEN x} frees object \kbd{x}, assuming it is the last created on the stack. \fun{GEN}{gerepile}{pari_sp p, pari_sp q, GEN x} general garbage collector for the stack. \fun{void}{gerepileall}{pari_sp av, int n, ...} cleans up the stack from \kbd{av} on (i.e from \kbd{avma} to \kbd{av}), preserving the \kbd{n} objects which follow in the argument list (of type \kbd{GEN*}). For instance, \kbd{gerepileall(av, 2, \&x, \&y)} preserves \kbd{x} and \kbd{y}. \fun{void}{gerepileallsp}{pari_sp av, pari_sp ltop, int n, ...} cleans up the stack between \kbd{av} and \kbd{ltop}, updating the \kbd{n} elements which follow \kbd{n} in the argument list (of type \kbd{GEN*}). Check that the elements of \kbd{g} have no component between \kbd{av} and \kbd{ltop}, and assumes that no garbage is present between \kbd{avma} and \kbd{ltop}. Analogous to (but faster than) \kbd{gerepileall} otherwise. \fun{GEN}{gerepilecopy}{pari_sp av, GEN x} cleans up the stack from \kbd{av} on, preserving the object \kbd{x}. Special case of \kbd{gerepileall} (case $\kbd{n} = 1$), except that the routine returns the preserved \kbd{GEN} instead of updating its address through a pointer. \fun{void}{gerepilemany}{pari_sp av, GEN* g[], int n} alternative interface to \kbd{gerepileall}. The preserved \kbd{GEN}s are the elements of the array \kbd{g} of length $n$: \kbd{g[0]}, \kbd{g[1]}, \dots, \kbd{g[$n$-1]}. Obsolete: no more efficient than \kbd{gerepileall}, error-prone, and clumsy (need to declare an extra \kbd{GEN *g}). \fun{void}{gerepilemanysp}{pari_sp av, pari_sp ltop, GEN* g[], int n} alternative interface to \kbd{gerepileallsp}. Obsolete. \fun{void}{gerepilecoeffs}{pari_sp av, GEN x, int n} cleans up the stack from \kbd{av} on, preserving \kbd{x[0]}, \dots, \kbd{x[n-1]} (which are \kbd{GEN}s). \fun{void}{gerepilecoeffssp}{pari_sp av, pari_sp ltop, GEN x, int n} cleans up the stack from \kbd{av} to \kbd{ltop}, preserving \kbd{x[0]}, \dots, \kbd{x[n-1]} (which are \kbd{GEN}s). Same assumptions as in \kbd{gerepilemanysp}, of which this is a variant. For instance \bprog z = cgetg(3, t_COMPLEX); av = avma; garbage(); ltop = avma; z[1] = fun1(); z[2] = fun2(); gerepilecoeffssp(av, ltop, z + 1, 2); return z; @eprog\noindent cleans up the garbage between \kbd{av} and \kbd{ltop}, and connects \kbd{z} and its two components. This is marginally more efficient than the standard \bprog av = avma; garbage(); ltop = avma; z = cgetg(3, t_COMPLEX); z[1] = fun1(); z[2] = fun2(); return gerepile(av, ltop, z); @eprog\noindent \fun{GEN}{gerepileupto}{pari_sp av, GEN q} analogous to (but faster than) \kbd{gerepilecopy}. Assumes that \kbd{q} is connected and that its root was created before any component. If \kbd{q} is not on the stack, this is equivalent to \kbd{avma = av}; in particular, sentinels which are not even proper \kbd{GEN}s such as \kbd{q = NULL} are allowed. \fun{GEN}{gerepileuptoint}{pari_sp av, GEN q} analogous to (but faster than) \kbd{gerepileupto}. Assumes further that \kbd{q} is a \typ{INT}. The length and effective length of the resulting \typ{INT} are equal. \fun{GEN}{gerepileuptoleaf}{pari_sp av, GEN q} analogous to (but faster than) \kbd{gerepileupto}. Assumes further that \kbd{q} is a leaf, i.e a non-recursive type (\kbd{is\_recursive\_t(typ(q))} is non-zero). Contrary to \kbd{gerepileuptoint} and \kbd{gerepileupto}, \kbd{gerepileuptoleaf} leaves length and effective length of a \typ{INT} unchanged. \subsec{Garbage collection: advanced use} \fun{void}{stackdummy}{pari_sp av, pari_sp ltop} inhibits the memory area between \kbd{av} \emph{included} and \kbd{ltop} \emph{excluded} with respect to \kbd{gerepile}, in order to avoid a call to \kbd{gerepile(av, ltop,...)}. The stack space is not reclaimed though. More precisely, this routine assumes that \kbd{av} is recorded earlier than \kbd{ltop}, then marks the specified stack segment as a non-recursive type of the correct length. Thus gerepile will not inspect the zone, at most copy it. To be used in the following situation: \bprog av0 = avma; z = cgetg(t_VEC, 3); gel(z,1) = HUGE(); av = avma; garbage(); ltop = avma; gel(z,2) = HUGE(); stackdummy(av, ltop); @eprog\noindent Compared to the orthodox \bprog gel(z,2) = gerepile(av, ltop, gel(z,2)); @eprog\noindent or even more wasteful \bprog z = gerepilecopy(av0, z); @eprog\noindent we temporarily lose $(\kbd{av} - \kbd{ltop})$ words but save a costly \kbd{gerepile}. In principle, a garbage collection higher up the call chain should reclaim this later anyway. Without the \kbd{stackdummy}, if the $[\kbd{av}, \kbd{ltop}]$ zone is arbitrary (not even valid \kbd{GEN}s as could happen after direct truncation via \kbd{setlg}), we would leave dangerous data in the middle of~\kbd{z}, which would be a problem for a later \bprog gerepile(..., ... , z); @eprog\noindent And even if it were made of valid \kbd{GEN}s, inhibiting the area makes sure \kbd{gerepile} will not inspect their components, saving time. Another natural use in low-level routines is to ``shorten'' an existing \kbd{GEN} \kbd{z} to its first $\kbd{n}-1$ components: \bprog setlg(z, n); stackdummy((pari_sp)(z + lg(z)), (pari_sp)(z + n)); @eprog\noindent or to its last \kbd{n} components: \bprog long L = lg(z) - n, tz = typ(z); stackdummy((pari_sp)(z + L), (pari_sp)z); z += L; z[0] = evaltyp(tz) | evallg(L); @eprog The first scenario (safe shortening an existing \kbd{GEN}) is in fact so common, that we provide a function for this: \fun{void}{fixlg}{GEN z, long ly} a safe variant of \kbd{setlg(z, ly)}. If \kbd{ly} is larger than \kbd{lg(z)} do nothing. Otherwise, shorten $z$ in place, using \kbd{stackdummy} to avoid later \kbd{gerepile} problems. \fun{GEN}{gcopy_avma}{GEN x, pari_sp *AVMA} return a copy of $x$ as from \kbd{gcopy}, except that we pretend that initially \kbd{avma} is \kbd{*AVMA}, and that \kbd{*AVMA} is updated accordingly (so that the total size of $x$ is the difference between the two successive values of \kbd{*AVMA}). It is not necessary for \kbd{*AVMA} to initially point on the stack: \tet{gclone} is implemented using this mechanism. \fun{GEN}{icopy_avma}{GEN x, pari_sp av} analogous to \kbd{gcopy\_avma} but simpler: assume $x$ is a \typ{INT} and return a copy allocated as if initially we had \kbd{avma} equal to \kbd{av}. There is no need to pass a pointer and update the value of the second argument: the new (fictitious) \kbd{avma} is just the return value (typecast to \kbd{pari\_sp}). \subsec{Debugging the PARI stack} \fun{int}{chk_gerepileupto}{GEN x} returns 1 if \kbd{x} is suitable for \kbd{gerepileupto}, and 0 otherwise. In the latter case, print a warning explaining the problem. \fun{void}{dbg_gerepile}{pari_sp ltop} outputs the list of all objects on the stack between \kbd{avma} and \kbd{ltop}, i.e. the ones that would be inspected in a call to \kbd{gerepile(...,ltop,...)}. \fun{void}{dbg_gerepileupto}{GEN q} outputs the list of all objects on the stack that would be inspected in a call to \kbd{gerepileupto(...,q)}. \subsec{Copies} \fun{GEN}{gcopy}{GEN x} creates a new copy of $x$ on the stack. \fun{GEN}{gcopy_lg}{GEN x, long l} creates a new copy of $x$ on the stack, pretending that \kbd{lg(x)} is $l$, which must be less than or equal to \kbd{lg(x)}. If equal, the function is equivalent to \kbd{gcopy(x)}. \fun{int}{isonstack}{GEN x} \kbd{true} iff $x$ belongs to the stack. \fun{void}{copyifstack}{GEN x, GEN y} sets \kbd{y = gcopy(x)} if $x$ belongs to the stack, and \kbd{y = x} otherwise. This macro evaluates its arguments once, contrary to \bprog y = isonstack(x)? gcopy(x): x; @eprog \fun{void}{icopyifstack}{GEN x, GEN y} as \kbd{copyifstack} assuming \kbd{x} is a \typ{INT}. \subsec{Simplify} \fun{GEN}{simplify}{GEN x} you should not need that function in library mode. One rather uses: \fun{GEN}{simplify_shallow}{GEN x} shallow, faster, version of \tet{simplify}. \section{The PARI heap} \subsec{Introduction} It is implemented as a doubly-linked list of \kbd{malloc}'ed blocks of memory, equipped with reference counts. Each block has type \kbd{GEN} but need not be a valid \kbd{GEN}: it is a chunk of data preceded by a hidden header (meaning that we allocate $x$ and return $x + \kbd{header size}$). A \tev{clone}, created by \tet{gclone}, is a block which is a valid \kbd{GEN} and whose \emph{clone bit} is set. \subsec{Public interface} \fun{GEN}{newblock}{size_t n} allocates a block of $n$ \emph{words} (not bytes). \fun{void}{killblock}{GEN x} deletes the block~$x$ created by \kbd{newblock}. Fatal error if $x$ not a block. \fun{GEN}{gclone}{GEN x} creates a new permanent copy of $x$ on the heap (allocated using \kbd{newblock}). The \emph{clone bit} of the result is set. \fun{GEN}{gcloneref}{GEN x} if $x$ is not a clone, clone it and return the result; otherwise, increase the clone reference count and return $x$. \fun{void}{gunclone}{GEN x} deletes a clone. Deletion at first only decreases the reference count by $1$. If the count remains positive, no further action is taken; if the count becomes zero, then the clone is actually deleted. In the current implementation, this is an alias for \kbd{killblock}, but it is cleaner to kill clones (valid \kbd{GEN}s) using this function, and other blocks using \kbd{killblock}. \fun{void}{gunclone_deep}{GEN x} is only useful in the context of the GP interpreter which may replace arbitrary components of container types (\typ{VEC}, \typ{COL}, \typ{MAT}, \typ{LIST}) by clones. If $x$ is such a container, the function recursively deletes all clones among the components of $x$, then unclones $x$. Useless in library mode: simply use \kbd{gunclone}. \fun{void}{traverseheap}{void(*f)(GEN, void *), void *data} this applies \kbd{f($x$, data)} to each object $x$ on the PARI heap, most recent first. Mostly for debugging purposes. \fun{GEN}{getheap}{} a simple wrapper around \kbd{traverseheap}. Returns a two-component row vector giving the number of objects on the heap and the amount of memory they occupy in long words. \fun{GEN}{cgetg_block}{long x, long y} as \kbd{cgetg(x,y)}, creating the return value as a \kbd{block}, not on the PARI stack. \fun{GEN}{cgetr_block}{long prec} as \kbd{cgetr(prec)}, creating the return value as a \kbd{block}, not on the PARI stack. \subsec{Implementation note} The hidden block header is manipulated using the following private functions: \fun{void*}{bl_base}{GEN x} returns the pointer that was actually allocated by \kbd{malloc} (can be freed). \fun{long}{bl_refc}{GEN x} the reference count of $x$: the number of pointers to this block. Decremented in \kbd{killblock}, incremented by the private function \fun{void}{gclone_refc}{GEN x}; block is freed when the reference count reaches $0$. \fun{long}{bl_num}{GEN x} the index of this block in the list of all blocks allocated so far (including freed blocks). Uniquely identifies a block until $2^\B$ blocks have been allocated and this wraps around. \fun{GEN}{bl_next}{GEN x} the block \emph{after} $x$ in the linked list of blocks (\kbd{NULL} if $x$ is the last block allocated not yet killed). \fun{GEN}{bl_prev}{GEN x} the block allocated \emph{before} $x$ (never \kbd{NULL}). We documented the last four routines as functions for clarity (and type checking) but they are actually macros yielding valid lvalues. It is allowed to write \kbd{bl\_refc(x)++} for instance. \section{Handling user and temp variables} Low-level implementation of user / temporary variables is liable to change. We describe it nevertheless for completeness. Currently variables are implemented by a single array of values divided in 3 zones: 0--\kbd{nvar} (user variables), \kbd{max\_avail}--\kbd{MAXVARN} (temporary variables), and \kbd{nvar+1}--\kbd{max\_avail-1} (pool of free variable numbers). \subsec{Low-level} \fun{void}{pari_var_init}{}: a small part of \kbd{pari\_init}. Resets variable counters \kbd{nvar} and \kbd{max\_avail}, notwithstanding existing variables! In effect, this even deletes \kbd{x}. Don't use it. \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}. \noindent The obsolete function \fun{long}{manage_var}{long n, entree *ep} is kept for backward compatibility only. Don't use it. \subsec{User variables} \fun{long}{fetch_user_var}{char *s} returns a user variable whose name 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. \fun{entree*}{is_entry}{const char *s} returns the \kbd{entree*} associated to an identifier \kbd{s} (variable or function), from the interpreter hashtables. Return \kbd{NULL} is the identifier is unknown. \subsec{Temporary variables} \fun{long}{fetch_var}{void} returns the number of a new temporary variable (decreasing \kbd{max\_avail}). \fun{long}{delete_var}{void} delete latest temp variable created and return 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. \section{Adding functions to PARI} \subsec{Nota Bene} % As mentioned in the \kbd{COPYING} file, modified versions of the PARI package can be distributed under the conditions of the GNU General Public License. If you do modify PARI, however, it is certainly for a good reason, and we would like to know about it, so that everyone can benefit from your changes. There is then a good chance that your improvements are incorporated into the next release. We classify changes to PARI into four rough classes, where changes of the first three types are almost certain to be accepted. The first type includes all improvements to the documentation, in a broad sense. This includes correcting typos or inaccuracies of course, but also items which are not really covered in this document, e.g.~if you happen to write a tutorial, or pieces of code exemplifying fine points unduly omitted in the present manual. The second type is to expand or modify the configuration routines and skeleton files (the \kbd{Configure} script and anything in the \kbd{config/} subdirectory) so that compilation is possible (or easier, or more efficient) on an operating system previously not catered for. This includes discovering and removing idiosyncrasies in the code that would hinder its portability. The third type is to modify existing (mathematical) code, either to correct bugs, to add new functionality to existing functions, or to improve their efficiency. Finally the last type is to add new functions to PARI. We explain here how to do this, so that in particular the new function can be called from \kbd{gp}. \subsec{Coding guidelines}\label{se:coding_guidelines} \noindent Code your function in a file of its own, using as a guide other functions in the PARI sources. One important thing to remember is to clean the stack before exiting your main function, since otherwise successive calls to the function clutters the stack with unnecessary garbage, and stack overflow occurs sooner. Also, if it returns a \kbd{GEN} and you want it to be accessible to \kbd{gp}, you have to make sure this \kbd{GEN} is suitable for \kbd{gerepileupto} (see \secref{se:garbage}). If error messages or warnings are to be generated in your function, use \kbd{pari\_err} and \kbd{pari\_warn} respectively. Recall that \kbd{pari\_err} does not return but ends with a \kbd{longjmp} statement. As well, instead of explicit \kbd{printf}~/ \kbd{fprintf} statements, use the following encapsulated variants: \fun{void}{pari_putc}{char c}: write character \kbd{c} to the output stream. \fun{void}{pari_puts}{char *s}: write \kbd{s} to the output stream. \fun{void}{pari_printf}{const char *fmt, ...}: write following arguments to the output stream, according to the conversion specifications in format \kbd{fmt} (see \tet{printf}). \fun{void}{err_printf}{const char *fmt, ...}: as \tet{pari_printf}, writing to PARI's current error stream. \fun{void}{err_flush}{void} flush error stream. Declare all public functions in an appropriate header file, if you want to access them from C. The other functions should be declared \kbd{static} in your file. Your function is now ready to be used in library mode after compilation and creation of the library. If possible, compile it as a shared library (see the \kbd{Makefile} coming with the \kbd{extgcd} example in the distribution). It is however still inaccessible from \kbd{gp}.\smallskip \subsec{GP prototypes, parser codes} \label{se:gp.interface} A \tev{GP prototype} is a character string describing all the GP parser needs to know about the function prototype. It contains a sequence of the following atoms: \settabs\+\indent&\kbd{Dxxx}\quad&\cr \noindent\item Return type: \kbd{GEN} by default (must be valid for \kbd{gerepileupto}), otherwise the following can appear as the \emph{first} char of the code string: % \+& \kbd{i} & return \kbd{int}\cr \+& \kbd{l} & return \kbd{long}\cr \+& \kbd{v} & return \kbd{void}\cr \+& \kbd{m} & return a \kbd{GEN} which is not \kbd{gerepile}-safe.\cr The \kbd{m} code is used for member functions, to avoid unnecessary copies. A copy opcode is generated by the compiler if the result needs to be kept safe for later use. \noindent\item Mandatory arguments, appearing in the same order as the 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{V} & loop variable\cr \+& \kbd{n} & variable, expects a \idx{variable number} (a \kbd{long}, not an \kbd{*entree})\cr \+& \kbd{W} & a \kbd{GEN} which is a lvalue to be modified in place (for \typ{LIST})\cr \+& \kbd{r} & raw input (treated as a string without quotes). Quoted args are copied as strings\cr \+&&\quad Stops at first unquoted \kbd{')'} or \kbd{','}. Special chars can be quoted using \kbd{'\bs'}\cr \+&&\quad Example: \kbd{aa"b\bs n)"c} yields the string \kbd{"aab\bs{n})c"}\cr \+& \kbd{s} & expanded string. Example: \kbd{Pi"x"2} yields \kbd{"3.142x2"}\cr \+&&\quad Unquoted components can be of any PARI type, converted to string following\cr \+&&\quad current output format\cr \+& \kbd{I} & closure whose value is ignored, as in \kbd{for} loops,\cr \+&&\quad to be processed by \fun{void}{closure_evalvoid}{GEN C}\cr \+& \kbd{E} & closure whose value is used, as in \kbd{sum} loops,\cr \+&&\quad to be processed by \fun{void}{closure_evalgen}{GEN C}\cr \+& \kbd{J} & implicit function of arity $1$, as in \kbd{parsum} loops,\cr \+&&\quad to be processed by \fun{void}{closure_callgen1}{GEN C}\cr \noindent A \tev{closure} is a GP function in compiled (bytecode) form. It can be efficiently evaluated using the \kbd{closure\_eval}$xxx$ functions. \noindent\item Automatic arguments: % \+& \kbd{f} & Fake \kbd{*long}. C function requires a pointer but we 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.: % \+& \kbd{=} & separator \kbd{=} required at this point (between two arguments)\cr \noindent\item Optional arguments and default values: % \+& \kbd{E*} & any number of expressions, possibly 0 (see \kbd{E})\cr \+& \kbd{s*} & any number of strings, possibly 0 (see \kbd{s})\cr \+& \kbd{D\var{xxx}} & argument can be omitted and has a default value\cr The \kbd{E*} code reads all remaining arguments in closure context and passes them as a single \typ{VEC}. The \kbd{s*} code reads all remaining arguments in \tev{string context} (see \secref{se:strings}), and passes the list of strings as a single \typ{VEC}. The automatic concatenation rules in string context are implemented so that adjacent strings are read as different arguments, as if they had been comma-separated. For instance, if the remaining argument sequence is: \kbd{"xx" 1, "yy"}, the \kbd{s*} atom sends \kbd{[a, b, c]}, where $a$, $b$, $c$ are \kbd{GEN}s of type \typ{STR} (content \kbd{"xx"}), \typ{INT} (equal to $1$) and \typ{STR} (content \kbd{"yy"}). The format to indicate a default value (atom starts with a \kbd{D}) is ``\kbd{D\var{value},\var{type},}'', where \var{type} is the code for any mandatory atom (previous group), \var{value} is any valid GP expression which is converted according to \var{type}, and the ending comma is mandatory. For instance \kbd{D0,L,} stands for ``this optional argument is converted to a \kbd{long}, and is \kbd{0} by default''. So if the user-given argument reads \kbd{1 + 3} at this point, \kbd{4L} is sent to the function; and \kbd{0L} if the argument is omitted. The following special notations are available: \settabs\+\indent\indent&\kbd{Dxxx}\quad& optional \kbd{*GEN},&\cr \+&\kbd{DG}& optional \kbd{GEN}, & send \kbd{NULL} if argument omitted.\cr \+&\kbd{D\&}& optional \kbd{*GEN}, send \kbd{NULL} if argument omitted.\cr \+&&\quad The argument must be prefixed by \kbd{\&}.\cr \+&\kbd{Dr}& optional raw string, send \kbd{NULL} if argument omitted.\cr \+&\kbd{Ds}& optional \kbd{char *}, send \kbd{NULL} if argument omitted.\cr \+&\kbd{DV}& optional \kbd{*entree}, send \kbd{NULL} if argument omitted.\cr \+&\kbd{DI}, \kbd{DE}& optional closure, send \kbd{NULL} if argument omitted.\cr \+&\kbd{Dn}& optional variable number, $-1$ if omitted.\cr \misctitle{Hardcoded limit} C functions using more than 20 arguments are not supported. Use vectors if you really need that many parameters. When the function is called under \kbd{gp}, the prototype is scanned and each time an atom corresponding to a mandatory argument is met, a user-given argument is read (\kbd{gp} outputs an error message it the argument was missing). Each time an optional atom is met, a default value is inserted if the user omits the argument. The ``automatic'' atoms fill in the argument list transparently, supplying the current value of the corresponding variable (or a dummy pointer). For instance, here is how you would code the following prototypes, which do not involve default values: \bprog GEN f(GEN x, GEN y, long prec) ----> "GGp" void f(GEN x, GEN y, long prec) ----> "vGGp" void f(GEN x, long y, long prec) ----> "vGLp" long f(GEN x) ----> "lG" int f(long x) ----> "iL" @eprog\noindent If you want more examples, \kbd{gp} gives you easy access to the parser codes associated to all GP functions: just type \kbd{\b{h} \var{function}}. You can then compare with the C prototypes as they stand in \kbd{paridecl.h}. \misctitle{Remark} If you need to implement complicated control statements (probably for some improved summation functions), you need to know how the parser implements closures and lexicals and how the evaluator lets you deal with them, in particular the \tet{push_lex} and \tet{pop_lex} functions. Check their descriptions and adapt the source code in \kbd{language/sumiter.c} and \kbd{language/intnum.c}. \subsec{Integration with \kbd{gp} as a shared module} In this section we assume that your Operating System is supported by \tet{install}. You have written a function in C following the guidelines is \secref{se:coding_guidelines}; in case the function returns a \kbd{GEN}, it must satisfy \kbd{gerepileupto} assumptions (see \secref{se:garbage}). You then succeeded in building it as part of a shared library and want to finally tell \kbd{gp} about your function. First, find a name for it. It does not have to match the one used in library mode, but consistency is nice. It has to be a valid GP identifier, i.e.~use only alphabetic characters, digits and the underscore character (\kbd{\_}), the first character being alphabetic. Then figure out the correct \idx{parser code} corresponding to the function prototype (as explained in~\secref{se:gp.interface}) and write a GP script like the following: \bprog install(libname, code, gpname, library) addhelp(gpname, "some help text") @eprog \noindent(see \secref{se:addhelp} and~\ref{se:install}). The \idx{addhelp} part is not mandatory, but very useful if you want others to use your module. \kbd{libname} is how the function is named in the library, usually the same name as one visible from C. Read that file from your \kbd{gp} session, for instance from your \idx{preferences file} (\secref{se:gprc}), and that's it. You can now use the new function \var{gpname} under \kbd{gp}, and we would very much like to hear about it! \smallskip \misctitle{Example} A complete description could look like this: \bprog { install(bnfinit0, "GD0,L,DGp", ClassGroupInit, "libpari.so"); addhelp(ClassGroupInit, "ClassGroupInit(P,{flag=0},{data=[]}): compute the necessary data for ..."); } @eprog\noindent which means we have a function \kbd{ClassGroupInit} under \kbd{gp}, which calls the library function \kbd{bnfinit0} . The function has one mandatory argument, and possibly two more (two \kbd{'D'} in the code), plus the current real precision. More precisely, the first argument is a \kbd{GEN}, the second one is converted to a \kbd{long} using \kbd{itos} (\kbd{0} is passed if it is omitted), and the third one is also a \kbd{GEN}, but we pass \kbd{NULL} if no argument was supplied by the user. This matches the C prototype (from \kbd{paridecl.h}): % \bprog GEN bnfinit0(GEN P, long flag, GEN data, long prec) @eprog\noindent This function is in fact coded in \kbd{basemath/buch2.c}, and is in this case completely identical to the GP function \kbd{bnfinit} but \kbd{gp} does not need to know about this, only that it can be found somewhere in the shared library \kbd{libpari.so}. \misctitle{Important note} You see in this example that it is the function's responsibility to correctly interpret its operands: \kbd{data = NULL} is interpreted \emph{by the function} as an empty vector. Note that since \kbd{NULL} is never a valid \kbd{GEN} pointer, this trick always enables you to distinguish between a default value and actual input: the user could explicitly supply an empty vector! \subsec{Library interface for \kbd{install}} There is a corresponding library interface for this \kbd{install} functionality, letting you expand the GP parser/evaluator available in the library with new functions from your C source code. Functions such as \tet{gp_read_str} may then evaluate a GP expression sequence involving calls to these new function! \fun{entree *}{install}{void *f, const char *gpname, const char *code} \noindent where \kbd{f} is the (address of the) function (cast to \kbd{void*}), \kbd{gpname} is the name by which you want to access your function from within your GP expressions, and \kbd{code} is as above. \subsec{Integration by patching \kbd{gp}} If \tet{install} is not available, and installing Linux or a BSD operating system is not an option (why?), you have to hardcode your function in the \kbd{gp} binary. Here is what needs to be done: \item Fetch the complete sources of the PARI distribution. \item Drop the function source code module in an appropriate directory (a priori \kbd{src/modules}), and declare all public functions in \kbd{src/headers/paridecl.h}. \item Choose a help section and add a file \kbd{src/functions/\var{section}/\var{gpname}} containing the following, keeping the notation above: \bprog Function: @com\var{gpname} Section: @com\var{section} C-Name: @com\var{libname} Prototype: @com\var{code} Help: @com\var{some help text} @eprog\noindent (If the help text does not fit on a single line, continuation lines must start by a whitespace character.) Two GP2C-related fields (\kbd{Description} and \kbd{Wrapper}) are also available to improve the code GP2C generates when compiling scripts involving your function. See the GP2C documentation for details. \item Launch \kbd{Configure}, which should pick up your C files and build an appropriate \kbd{Makefile}. At this point you can recompile \kbd{gp}, which will first rebuild the functions database. \misctitle{Example} We reuse the \kbd{ClassGroupInit} / \kbd{bnfinit0} from the preceding section. Since the C source code is already part of PARI, we only need to add a file \kbd{functions/number\_fields/ClassGroupInit} \noindent containing the following: \bprog Function: ClassGroupInit Section: number_fields C-Name: bnfinit0 Prototype: GD0,L,DGp Help: ClassGroupInit(P,{flag=0},{tech=[]}): this routine does @com\dots @eprog\noindent and recompile \kbd{gp}. \section{Globals related to PARI configuration} \subsec{PARI version numbers} \noindent \tet{paricfg_version_code} encodes in a single \kbd{long}, the Major and minor version numbers as well as the patchlevel. \fun{long}{PARI_VERSION}{long M, long m, long p} produces the version code associated to release $M.m.p$. Each code identifies a unique PARI release, and corresponds to the natural total order on the set of releases (bigger code number means more recent release). \noindent \tet{PARI_VERSION_SHIFT} is the number of bits used to store each of the integers $M$, $m$, $p$ in the version code. \noindent \tet{paricfg_vcsversion} is a version string related to the revision control system used to handle your sources, if any. For instance \kbd{git-}\emph{commit hash} if compiled from a git repository. The two character strings \tet{paricfg_version} and \tet{paricfg_buildinfo}, correspond to the first two lines printed by \kbd{gp} just before the Copyright message. The character string \tet{paricfg_compiledate} is the date of compilation which appears on the next line. The character string \tet{paricfg_mt_engine} is the name of the threading engine on the next line. \fun{GEN}{pari_version}{} returns the version number as a PARI object, a \typ{VEC} with three \typ{INT} and one \typ{STR} components. \subsec{Miscellaneous} \tet{paricfg_datadir}: character string. The location of PARI's \tet{datadir}. \newpage \chapter{Arithmetic kernel: Level 0 and 1} \section{Level 0 kernel (operations on ulongs)} \subsec{Micro-kernel} The Level 0 kernel simulates basic operations of the 68020 processor on which PARI was originally implemented. They need ``global'' \kbd{ulong} variables \kbd{overflow} (which will contain only 0 or 1) and \kbd{hiremainder} to function properly. A routine using one of these lowest-level functions where the description mentions either \kbd{hiremainder} or \kbd{overflow} must declare the corresponding \bprog LOCAL_HIREMAINDER; /* provides 'hiremainder' */ LOCAL_OVERFLOW; /* provides 'overflow' */ @eprog\noindent in a declaration block. Variables \kbd{hiremainder} and \kbd{overflow} then become available in the enclosing block. For instance a loop over the powers of an \kbd{ulong}~\kbd{p} protected from overflows could read \bprog while (pk < lim) { LOCAL_HIREMAINDER; ... pk = mulll(pk, p); if (hiremainder) break; } @eprog\noindent For most architectures, the functions mentioned below are really chunks of inlined assembler code, and the above `global' variables are actually local register values. \fun{ulong}{addll}{ulong x, ulong y} adds \kbd{x} and \kbd{y}, returns the lower \B\ bits and puts the carry bit into \kbd{overflow}. \fun{ulong}{addllx}{ulong x, ulong y} adds \kbd{overflow} to the sum of the \kbd{x} and \kbd{y}, returns the lower \B\ bits and puts the carry bit into \kbd{overflow}. \fun{ulong}{subll}{ulong x, ulong y} subtracts \kbd{x} and \kbd{y}, returns the lower \B\ bits and put the carry (borrow) bit into \kbd{overflow}. \fun{ulong}{subllx}{ulong x, ulong y} subtracts \kbd{overflow} from the difference of \kbd{x} and \kbd{y}, returns the lower \B\ bits and puts the carry (borrow) bit into \kbd{overflow}. \fun{int}{bfffo}{ulong x} returns the number of leading zero bits in \kbd{x}. That is, the number of bit positions by which it would have to be shifted left until its leftmost bit first becomes equal to~1, which can be between 0 and $\B-1$ for nonzero \kbd{x}. When \kbd{x} is~0, the result is undefined. \fun{ulong}{mulll}{ulong x, ulong y} multiplies \kbd{x} by \kbd{y}, returns the lower \B\ bits and stores the high-order \B\ bits into \kbd{hiremainder}. \fun{ulong}{addmul}{ulong x, ulong y} adds \kbd{hiremainder} to the product of \kbd{x} and \kbd{y}, returns the lower \B\ bits and stores the high-order \B\ bits into \kbd{hiremainder}. \fun{ulong}{divll}{ulong x, ulong y} returns the quotient of $ \left(\kbd{hiremainder} * 2^{\B}\right) + \kbd{x} $ by \kbd{y} and stores the remainder into \kbd{hiremainder}. An error occurs if the quotient cannot be represented by an \kbd{ulong}, i.e.~if initially $\kbd{hiremainder}\ge\kbd{y}$. \misctitle{Obsolete routines} Those functions are awkward and no longer used; they are only provided for backward compatibility: \fun{ulong}{shiftl}{ulong x, ulong y} returns $x$ shifted left by $y$ bits, i.e.~\kbd{$x$ << $y$}, where we assume that $0\leq y\leq\B$. The global variable \kbd{hiremainder} receives the bits that were shifted out, i.e.~\kbd{$x$ >> $(\B - y)$}. \fun{ulong}{shiftlr}{ulong x, ulong y} returns $x$ shifted right by $y$ bits, i.e.~\kbd{$x$ >> $y$}, where we assume that $0\leq y\leq\B$. The global variable \kbd{hiremainder} receives the bits that were shifted out, i.e.~\kbd{$x$ << $(\B - y)$}. \subsec{Modular kernel} The following routines are not part of the level 0 kernel per se, but implement modular operations on words in terms of the above. They are written so that no overflow may occur. Let $m \geq 1$ be the modulus; all operands representing classes modulo $m$ are assumed to belong to $[0,m-1]$. The result may be wrong for a number of reasons otherwise: it may not be reduced, overflow can occur, etc. \fun{int}{odd}{ulong x} returns 1 if $x$ is odd, and 0 otherwise. \fun{int}{both_odd}{ulong x, ulong y} returns 1 if $x$ and $y$ are both odd, and 0 otherwise. \fun{ulong}{invmod2BIL}{ulong x} returns the smallest positive representative of $x^{-1}$ mod $2^\B$, assuming $x$ is odd. \fun{ulong}{Fl_add}{ulong x, ulong y, ulong m} returns the smallest positive representative of $x + y$ modulo $m$. \fun{ulong}{Fl_neg}{ulong x, ulong m} returns the smallest positive representative of $-x$ modulo $m$. \fun{ulong}{Fl_sub}{ulong x, ulong y, ulong m} returns the smallest positive representative of $x - y$ modulo $m$. \fun{long}{Fl_center}{ulong x, ulong m, ulong mo2} returns the representative in $]-m/2,m/2]$ of $x$ modulo $m$. Assume $0 \leq x < m$ and $\kbd{mo2} = m >> 1$. \fun{ulong}{Fl_mul}{ulong x, ulong y, ulong m} returns the smallest positive representative of $x y$ modulo $m$. \fun{ulong}{Fl_double}{ulong x, ulong m} returns $2x$ modulo $m$. \fun{ulong}{Fl_triple}{ulong x, ulong m} returns $3x$ modulo $m$. \fun{ulong}{Fl_sqr}{ulong x, ulong m} returns the smallest positive representative of $x^2$ modulo $m$. \fun{ulong}{Fl_inv}{ulong x, ulong m} returns the smallest positive representative of $x^{-1}$ modulo $m$. If $x$ is not invertible mod~$m$, raise an exception. \fun{ulong}{Fl_invsafe}{ulong x, ulong m} returns the smallest 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_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. \fun{ulong}{Fl_powu}{ulong x, ulong n, ulong m} returns the smallest positive representative of $x^n$ modulo $m$. \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_order}{ulong a, ulong o, ulong p} returns the order of the \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 distributed in $0, 1, \dots p-1$. \fun{ulong}{pgener_Fl}{ulong p} returns the smallest \idx{primitive root} modulo \kbd{p}, assuming \kbd{p} is prime. \fun{ulong}{pgener_Zl}{ulong p} returns the smallest primitive root modulo $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{Switching between Fl\_xxx and standard operators} Even though the \kbd{Fl\_xxx} routines are efficient, they are slower than ordinary \kbd{long} operations, using the standard \kbd{+}, \kbd{\%}, etc. operators. The following macro is used to choose in a portable way the most efficient functions for given operands: \fun{int}{SMALL_ULONG}{ulong p} true if $2p^2 <2^\B$. In that case, it is possible to use ordinary operators efficiently. If $p < 2^\B$, one may still use the \kbd{Fl\_xxx} routines. Otherwise, one must use generic routines. For instance, the scalar product of the \kbd{GEN}s $x$ and $y$ mod $p$ could be computed as follows. \bprog long i, l = lg(x); if (lgefint(p) > 3) { /* arbitrary */ GEN s = gen_0; for (i = 1; i < l; i++) s = addii(s, mulii(gel(x,i), gel(y,i))); return modii(s, p). } else { ulong s = 0, pp = itou(p); x = ZV_to_Flv(x, pp); y = ZV_to_Flv(y, pp); if (SMALL_ULONG(pp)) { /* very small */ for (i = 1; i < l; i++) { s += x[i] * y[i]; if (s & HIGHBIT) s %= pp; } s %= pp; } else { /* small */ for (i = 1; i < l; i++) s = Fl_add(s, Fl_mul(x[i], y[i], pp), pp); } return utoi(s); } @eprog\noindent In effect, we have three versions of the same code: very small, small, and arbitrary inputs. The very small and arbitrary variants use lazy reduction and reduce only when it becomes necessary: when overflow might occur (very small), and at the very end (very small, arbitrary). \section{Level 1 kernel (operations on longs, integers and reals)} \misctitle{Note} Some functions consist of an elementary operation, immediately followed by an assignment statement. They will be introduced as in the following example: \fun{GEN}{gadd[z]}{GEN x, GEN y[, GEN z]} followed by the explicit description of the function \fun{GEN}{gadd}{GEN x, GEN y} \noindent which creates its result on the stack, returning a \kbd{GEN} pointer to it, and the parts in brackets indicate that there exists also a function \fun{void}{gaddz}{GEN x, GEN y, GEN z} \noindent which assigns its result to the pre-existing object \kbd{z}, leaving the stack unchanged. These assignment variants are kept for backward compatibility but are inefficient: don't use them. \subsec{Creation} \fun{GEN}{cgeti}{long n} allocates memory on the PARI stack for a \typ{INT} of length~\kbd{n}, and initializes its first codeword. Identical to \kbd{cgetg(n,\typ{INT})}. \fun{GEN}{cgetipos}{long n} allocates memory on the PARI stack for a \typ{INT} of length~\kbd{n}, and initializes its two codewords. The sign of \kbd{n} is set to $1$. \fun{GEN}{cgetineg}{long n} allocates memory on the PARI stack for a negative \typ{INT} of length~\kbd{n}, and initializes its two codewords. The sign of \kbd{n} is set to $-1$. \fun{GEN}{cgetr}{long n} allocates memory on the PARI stack for a \typ{REAL} of length~\kbd{n}, and initializes its first codeword. Identical to \kbd{cgetg(n,\typ{REAL})}. \fun{GEN}{cgetc}{long n} allocates memory on the PARI stack for a \typ{COMPLEX}, whose real and imaginary parts are \typ{REAL}s of length~\kbd{n}. \fun{GEN}{real_1}{long prec} create a \typ{REAL} equal to $1$ to \kbd{prec} words of accuracy. \fun{GEN}{real_m1}{long prec} create a \typ{REAL} equal to $-1$ to \kbd{prec} words of accuracy. \fun{GEN}{real_0_bit}{long bit} create a \typ{REAL} equal to $0$ with exponent $-\kbd{bit}$. \fun{GEN}{real_0}{long prec} is a shorthand for \bprog real_0_bit( -bit_accuracy(prec) ) @eprog \fun{GEN}{int2n}{long n} creates a \typ{INT} equal to \kbd{1< 2$. \fun{void}{affii}{GEN x, GEN z} assigns the \typ{INT} \kbd{x} into the \typ{INT}~\kbd{z}. \fun{void}{affir}{GEN x, GEN z} assigns the \typ{INT} \kbd{x} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affiz}{GEN x, GEN z} assigns \typ{INT}~\kbd{x} into \typ{INT} or \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsi}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{INT}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsr}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsz}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{INT} or \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affui}{ulong u, GEN z} assigns the \kbd{ulong}~\kbd{u} into the \typ{INT}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affur}{ulong u, GEN z} assigns the \kbd{ulong}~\kbd{u} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affrr}{GEN x, GEN z} assigns the \typ{REAL}~\kbd{x} into the \typ{REAL}~\kbd{z}. \fun{void}{affgr}{GEN x, GEN z} assigns the scalar \kbd{x} into the \typ{REAL}~\kbd{z}, if possible. \noindent The function \kbd{affrs} and \kbd{affri} do not exist. So don't use them. \fun{void}{affrr_fixlg}{GEN y, GEN z} a variant of \kbd{affrr}. First shorten $z$ so that it is no longer than $y$, then assigns $y$ to $z$. This is used in the following scenario: room is reserved for the result but, due to cancellation, fewer words of accuracy are available than had been anticipated; instead of appending meaningless $0$s to the mantissa, we store what was actually computed. Note that shortening $z$ is not quite straightforward, since \kbd{setlg(z, ly)} would leave garbage on the stack, which \kbd{gerepile} might later inspect. It is done using \fun{void}{fixlg}{GEN z, long ly} see \tet{stackdummy} and the examples that follow. \subsec{Copy} \fun{GEN}{icopy}{GEN x} copy relevant words of the \typ{INT}~\kbd{x} on the stack: the length and effective length of the copy are equal. \fun{GEN}{rcopy}{GEN x} copy the \typ{REAL}~\kbd{x} on the stack. \fun{GEN}{leafcopy}{GEN x} copy the leaf~\kbd{x} on the stack (works in particular for \typ{INT}s and \typ{REAL}s). Contrary to \kbd{icopy}, \kbd{leafcopy} preserves the original length of a \typ{INT}. The obsolete form \fun{GEN}{mpcopy}{GEN x} is still provided for backward compatibility. This function also works on recursive types, copying them as if they were leaves, i.e.~making a shallow copy in that case: the components of the copy point to the same data as the component of the source; see also \kbd{shallowcopy}. \fun{GEN}{leafcopy_avma}{GEN x, pari_sp av} analogous to \kbd{gcopy\_avma} but simpler: assume $x$ is a leaf and return a copy allocated as if initially we had \kbd{avma} equal to \kbd{av}. There is no need to pass a pointer and update the value of the second argument: the new (fictitious) \kbd{avma} is just the return value (typecast to \kbd{pari\_sp}). \fun{GEN}{icopyspec}{GEN x, long nx} copy the \kbd{nx} words \kbd{x[2]}, \dots, \kbd{x[nx+1]} to make up a new \typ{INT}. Set the sign to $1$. \subsec{Conversions} \fun{GEN}{itor}{GEN x, long prec} converts the \typ{INT}~\kbd{x} to a \typ{REAL} of length \kbd{prec} and return the latter. Assumes that $\kbd{prec} > 2$. \fun{long}{itos}{GEN x} converts the \typ{INT}~\kbd{x} to a \kbd{long} if possible, otherwise raise an exception. \fun{long}{itos_or_0}{GEN x} converts the \typ{INT}~\kbd{x} to a \kbd{long} if possible, otherwise return $0$. \fun{int}{is_bigint}{GEN n} true if \kbd{itos(n)} would succeed. \fun{int}{is_bigint_lg}{GEN n, long l} true if \kbd{itos(n)} would succeed. Assumes \kbd{lgefint(n)} is equal to \kbd{l}. \fun{ulong}{itou}{GEN x} converts the \typ{INT}~\kbd{|x|} to an \kbd{ulong} if possible, otherwise raise an exception. \fun{long}{itou_or_0}{GEN x} converts the \typ{INT}~\kbd{|x|} to an \kbd{ulong} if possible, otherwise return $0$. \fun{GEN}{stoi}{long s} creates the \typ{INT} corresponding to the \kbd{long}~\kbd{s}. \fun{GEN}{stor}{long s, long prec} converts the \kbd{long}~\kbd{s} into a \typ{REAL} of length \kbd{prec} and return the latter. Assumes that $\kbd{prec} > 2$. \fun{GEN}{utoi}{ulong s} converts the \kbd{ulong}~\kbd{s} into a \typ{INT} and return the latter. \fun{GEN}{utoipos}{ulong s} converts the \emph{non-zero} \kbd{ulong}~\kbd{s} into a \typ{INT} and return the latter. \fun{GEN}{utoineg}{ulong s} converts the \emph{non-zero} \kbd{ulong}~\kbd{s} into the \typ{INT} $-s$ and return the latter. \fun{GEN}{utor}{ulong s, long prec} converts the \kbd{ulong}~\kbd{s} into a \typ{REAL} of length \kbd{prec} and return the latter. Assumes that $\kbd{prec} > 2$. \fun{GEN}{rtor}{GEN x, long prec} converts the \typ{REAL}~\kbd{x} to a \typ{REAL} of length \kbd{prec} and return the latter. If $\kbd{prec} < \kbd{lg(x)}$, round properly. If $\kbd{prec} > \kbd{lg(x)}$, pad with zeroes. Assumes that $\kbd{prec} > 2$. \noindent The following function is also available as a special case of \tet{mkintn}: \fun{GEN}{uu32toi}{ulong a, ulong b} returns the \kbd{GEN} equal to $2^{32} a + b$, \emph{assuming} that $a,b < 2^{32}$. This does not depend on \kbd{sizeof(long)}: the behavior is as above on both $32$ and $64$-bit machines. \fun{GEN}{uutoi}{ulong a, ulong b} returns the \kbd{GEN} equal to $2^{\B} a + b$. \fun{GEN}{uutoineg}{ulong a, ulong b} returns the \kbd{GEN} equal to $-(2^{\B} a + b)$. \subsec{Integer parts} The following four functions implement the conversion from \typ{REAL} to \typ{INT} using standard rounding modes. Contrary to usual semantics (complement the mantissa with an infinite number of 0), they will raise an error \emph{precision loss in truncation} if the \typ{REAL} represents a range containing more than one integer. \fun{GEN}{ceilr}{GEN x} smallest integer larger or equal to the \typ{REAL}~\kbd{x} (i.e.~the \kbd{ceil} function). \fun{GEN}{floorr}{GEN x} largest integer smaller or equal to the \typ{REAL}~\kbd{x} (i.e.~the \kbd{floor} function). \fun{GEN}{roundr}{GEN x} rounds the \typ{REAL} \kbd{x} to the nearest integer (towards~$+\infty$ in case of tie). \fun{GEN}{truncr}{GEN x} truncates the \typ{REAL}~\kbd{x} (not the same as \kbd{floorr} if \kbd{x} is negative). The following four function are analogous, but can also treat the trivial case when the argument is a \typ{INT}: \fun{GEN}{mpceil}{GEN x} as \kbd{ceilr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mpfloor}{GEN x} as \kbd{floorr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mpround}{GEN x} as \kbd{roundr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mptrunc}{GEN x} as \kbd{truncr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{diviiround}{GEN x, GEN y} if \kbd{x} and \kbd{y} are \typ{INT}s, returns the quotient $\kbd{x}/\kbd{y}$ of \kbd{x} and~\kbd{y}, rounded to the nearest integer. If $\kbd{x}/\kbd{y}$ falls exactly halfway between two consecutive integers, then it is rounded towards~$+\infty$ (as for \tet{roundr}). \fun{GEN}{ceil_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the smallest integer which is larger than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) Note that \kbd{gceil} raises an exception if the input accuracy is too low compared to its magnitude. \fun{GEN}{floor_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the largest integer which is smaller than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) Note that \kbd{gfloor} raises an exception if the input accuracy is too low compared to its magnitude. \fun{GEN}{trunc_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the integer with the largest absolute value, which is closer to $0$ than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) \fun{GEN}{roundr_safe}{GEN x} rounds the \typ{REAL} \kbd{x} to the nearest integer (towards~$+\infty$). Complement the mantissa with an infinite number of $0$ before rounding, hence never raise an exception. \subsec{$2$-adic valuations and shifts} \fun{long}{vals}{long s} 2-adic valuation of the \kbd{long}~\kbd{s}. Returns $-1$ if \kbd{s} is equal to 0. \fun{long}{vali}{GEN x} 2-adic valuation of the \typ{INT}~\kbd{x}. Returns $-1$ if \kbd{x} is equal to 0. \fun{GEN}{mpshift}{GEN x, long n} shifts the~\typ{INT} or \typ{REAL} \kbd{x} by~\kbd{n}. If \kbd{n} is positive, this is a left shift, i.e.~multiplication by $2^{\kbd{n}}$. If \kbd{n} is negative, it is a right shift by~$-\kbd{n}$, which amounts to the truncation of the quotient of \kbd{x} by~$2^{-\kbd{n}}$. \fun{GEN}{shifti}{GEN x, long n} shifts the \typ{INT}~$x$ by~$n$. \fun{GEN}{shiftr}{GEN x, long n} shifts the \typ{REAL}~$x$ by~$n$. \fun{void}{shiftr_inplace}{GEN x, long n} shifts the \typ{REAL}~$x$ by~$n$, in place. \fun{GEN}{trunc2nr}{GEN x, long n} given a \typ{REAL} $x$, returns \kbd{truncr(shiftr(x,n))}, but faster, without leaving garbage on the stack and never raising a \emph{precision loss in truncation} error. Called by \tet{gtrunc2n}. \fun{GEN}{trunc2nr_lg}{GEN x, long lx, long n} given a \typ{REAL} $x$, returns \kbd{trunc2nr(x,n)}, pretending that the length of $x$ is \kbd{lx}, which must be $\leq \kbd{lg}(x)$. \fun{GEN}{mantissa2nr}{GEN x, long n} given a \typ{REAL} $x$, returns the mantissa of $x 2^n$ (disregards the exponent of $x$). Equivalent to \bprog trunc2nr(x, n-expo(x)+bit_prec(x)-1) @eprog \fun{GEN}{mantissa_real}{GEN z, long *e} returns the mantissa $m$ of $z$, and sets \kbd{*e} to the exponent $\kbd{bit\_accuracy(lg(z))}-1-\kbd{expo}(z)$, so that $z = m / 2^e$. \misctitle{Low-level} In the following two functions, $s$(ource) and $t$(arget) need not be valid \kbd{GEN}s (in practice, they usually point to some part of a \typ{REAL} mantissa): they are considered as arrays of words representing some mantissa, and we shift globally $s$ by $n > 0$ bits, storing the result in $t$. We assume that $m\leq M$ and only access $s[m], s[m+1],\ldots s[M]$ (read) and likewise for $t$ (write); we may have $s = t$ but more general overlaps are not allowed. The word $f$ is concatenated to $s$ to supply extra bits. \fun{void}{shift_left}{GEN t, GEN s, long m, long M, ulong f, ulong n} shifts the mantissa $$s[m], s[m+1],\ldots s[M], f$$ left by $n$ bits. \fun{void}{shift_right}{GEN t, GEN s, long m, long M, ulong f, ulong n} shifts the mantissa $$f, s[m], s[m+1],\ldots s[M]$$ right by $n$ bits. \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$. If $p$ is prime, this is the ordinary valuation of $x$ at $p$. \fun{long}{Z_pvalrem}{GEN x, GEN p, GEN *r} applied to \typ{INT}s $\kbd{x}\neq 0$ and~\kbd{p}, $|\kbd{p}| > 1$, returns $e := v_p(x)$ The quotient $\kbd{x}/\kbd{p}^e$ is returned in~\kbd{*r}. If $|\kbd{p}|$ is a prime, \kbd{*r} is the prime-to-\kbd{p} part of~\kbd{x}. \fun{long}{Z_pval}{GEN x, GEN p} as \kbd{Z\_pvalrem} but only returns $v_p(x)$. \fun{long}{Z_lvalrem}{GEN x, ulong p, GEN *r} as \kbd{Z\_pvalrem}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{Z_lvalrem_stop}{GEN *x, ulong p, int *stop} returns $e := v_p(x)$ and replaces $x$ by $x / p^e$. Set \kbd{stop} to $1$ if the new value of $x$ is $ < p^2$ (and $0$ otherwise). To be used when trial dividing $x$ by successive primes: the \kbd{stop} condition is cheaply tested while testing whether $p$ divides $x$ (is the quotient less than $p$?), and allows to decide that $n$ is prime if no prime $< p$ divides $n$. Not memory-clean. \fun{long}{Z_lval}{GEN x, ulong p} as \kbd{Z\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{u_lvalrem}{ulong x, ulong p, ulong *r} as \kbd{Z\_pvalrem}, except the inputs/outputs are now \kbd{ulong}s. \fun{long}{u_lvalrem_stop}{ulong *n, ulong p, int *stop} as \kbd{Z\_pvalrem\_stop}. \fun{long}{u_pvalrem}{ulong x, GEN p, ulong *r} as \kbd{Z\_pvalrem}, except \kbd{x} and \kbd{r} are now \kbd{ulong}s. \fun{long}{u_lval}{ulong x, ulong p} as \kbd{Z\_pval}, except the inputs are now \kbd{ulong}s. \fun{long}{u_pval}{ulong x, GEN p} as \kbd{Z\_pval}, except \kbd{x} is now an \kbd{ulong}. \fun{long}{z_lval}{long x, ulong p} as \kbd{u\_lval}, for signed \kbd{x}. \fun{long}{z_lvalrem}{long x, ulong p} as \kbd{u\_lvalrem}, for signed \kbd{x}. \fun{long}{z_pval}{long x, GEN p} as \kbd{Z\_pval}, except \kbd{x} is now a \kbd{long}. \fun{long}{z_pvalrem}{long x, GEN p} as \kbd{Z\_pvalrem}, except \kbd{x} is now a \kbd{long}. \fun{long}{Q_pval}{GEN x, GEN p} valuation at the \typ{INT} \kbd{p} of the \typ{INT} or \typ{FRAC}~\kbd{x}. \fun{long}{factorial_lval}{ulong n, ulong p} returns $v_p(n!)$, assuming $p$ is prime. The following convenience functions generalize \kbd{Z\_pval} and its variants to ``containers'' (\kbd{ZV} and \kbd{ZX}): \fun{long}{ZV_pvalrem}{GEN x, GEN p, GEN *r} $x$ being a \kbd{ZV} (a vector of \typ{INT}s), return the min $v$ of the valuations of its components and set \kbd{*r} to $x/p^v$. Infinite loop if $x$ is the zero vector. This function is not stack clean. \fun{long}{ZV_pval}{GEN x, GEN p} as \kbd{ZV\_pvalrem} but only returns the ``valuation''. \fun{int}{ZV_Z_dvd}{GEN x, GEN p} returns $1$ if $p$ divides all components of $x$ and $0$ otherwise. Faster than testing \kbd{ZV\_pval(x,p) >= 1}. \fun{long}{ZV_lvalrem}{GEN x, ulong p, GEN *px} as \kbd{ZV\_pvalrem}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). This function is not stack-clean. \fun{long}{ZV_lval}{GEN x, ulong p} as \kbd{ZV\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{ZX_pvalrem}{GEN x, GEN p, GEN *r} as \kbd{ZV\_pvalrem}, for a \kbd{ZX} $x$ (a \typ{POL} with \typ{INT} coefficients). This function is not stack-clean. \fun{long}{ZX_pval}{GEN x, GEN p} as \kbd{ZV\_pval} for a \kbd{ZX} $x$. \fun{long}{ZX_lvalrem}{GEN x, ulong p, GEN *px} as \kbd{ZV\_lvalrem}, a \kbd{ZX} $x$. This function is not stack-clean. \fun{long}{ZX_lval}{GEN x, ulong p} as \kbd{ZX\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \subsec{Generic unary operators} Let ``\op'' be a unary operation among \item \key{neg}: negation ($-x$). \item \key{abs}: absolute value ($|x|$). \item \key{sqr}: square ($x^2$). \noindent The names and prototypes of the low-level functions corresponding to \op\ are as follows. The result is of the same type as~\kbd{x}. \funno{GEN}{\op i}{GEN x} creates the result of \op\ applied to the \typ{INT}~\kbd{x}. \funno{GEN}{\op r}{GEN x} creates the result of \op\ applied to the \typ{REAL}~\kbd{x}. \funno{GEN}{mp\op}{GEN x} creates the result of \op\ applied to the \typ{INT} or \typ{REAL}~\kbd{x}. \noindent Complete list of available functions: \fun{GEN}{absi}{GEN x}, \fun{GEN}{absr}{GEN x}, \fun{GEN}{mpabs}{GEN x} \fun{GEN}{negi}{GEN x}, \fun{GEN}{negr}{GEN x}, \fun{GEN}{mpneg}{GEN x} \fun{GEN}{sqri}{GEN x}, \fun{GEN}{sqrr}{GEN x}, \fun{GEN}{mpsqr}{GEN x} \fun{GEN}{absi_shallow}{GEN x} $x$ being a \typ{INT}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{negi($x$)} otherwise. \fun{GEN}{mpabs_shallow}{GEN x} $x$ being a \typ{INT} or a \typ{REAL}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{mpneg($x$)} otherwise. \noindent Some miscellaneous routines: \fun{GEN}{sqrs}{long x} returns $x^2$. \fun{GEN}{sqru}{ulong x} returns $x^2$. \subsec{Comparison operators} \fun{long}{minss}{long x, long y} \fun{ulong}{minuu}{ulong x, ulong y} \fun{double}{mindd}{double x, double y} returns the \kbd{min} of $x$ and $y$. \fun{long}{maxss}{long x, long y} \fun{ulong}{maxuu}{ulong x, ulong y} \fun{double}{maxdd}{double x, double y} returns the \kbd{max} of $x$ and $y$. \smallskip \fun{int}{mpcmp}{GEN x, GEN y} compares the \typ{INT} or \typ{REAL}~\kbd{x} to the \typ{INT} or \typ{REAL}~\kbd{y}. The result is the sign of $\kbd{x}-\kbd{y}$. \fun{int}{cmpii}{GEN x, GEN y} compares the \typ{INT} \kbd{x} to the \typ{INT}~\kbd{y}. \fun{int}{cmpir}{GEN x, GEN y} compares the \typ{INT} \kbd{x} to the \typ{REAL}~\kbd{y}. \fun{int}{cmpis}{GEN x, long s} compares the \typ{INT}~\kbd{x} to the \kbd{long}~\kbd{s}. \fun{int}{cmpsi}{long s, GEN x} compares the \kbd{long}~\kbd{s} to the \typ{INT}~\kbd{x}. \fun{int}{cmpsr}{long s, GEN x} compares the \kbd{long}~\kbd{s} to the \typ{REAL}~\kbd{x}. \fun{int}{cmpri}{GEN x, GEN y} compares the \typ{REAL}~\kbd{x} to the \typ{INT}~\kbd{y}. \fun{int}{cmprr}{GEN x, GEN y} compares the \typ{REAL}~\kbd{x} to the \typ{REAL}~\kbd{y}. \fun{int}{cmprs}{GEN x, long s} compares the \typ{REAL}~\kbd{x} to the \kbd{long}~\kbd{s}. \fun{int}{equalii}{GEN x, GEN y} compares the \typ{INT}s \kbd{x} and~\kbd{y}. The result is $1$ if $\kbd{x} = \kbd{y}$, $0$ otherwise. \fun{int}{equalrr}{GEN x, GEN y} compares the \typ{REAL}s \kbd{x} and~\kbd{y}. The result is $1$ if $\kbd{x} = \kbd{y}$, $0$ otherwise. Equality is decided according to the following rules: all real zeroes are equal, and different from a non-zero real; two non-zero reals are equal if all their digits coincide up to the length of the shortest of the two, and the remaining words in the mantissa of the longest are all $0$. \fun{int}{equalsi}{long s, GEN x} \fun{int}{equalis}{GEN x, long s} compare the \typ{INT} \kbd{x} and the \kbd{long}~\kbd{s}. The result is $1$ if $\kbd{x} = \kbd{y}$, $0$ otherwise. The remaining comparison operators disregard the sign of their operands: \fun{int}{equalui}{ulong s, GEN x} \fun{int}{equaliu}{GEN x, ulong s} compare the absolute value of the \typ{INT} \kbd{x} and the \kbd{ulong}~\kbd{s}. The result is $1$ if $|\kbd{x}| = \kbd{y}$, $0$ otherwise. \fun{int}{cmpui}{ulong u, GEN x} \fun{int}{cmpiu}{GEN x, ulong u} compare the absolute value of the \typ{INT} \kbd{x} and the \kbd{ulong}~\kbd{s}. \fun{int}{absi_cmp}{GEN x, GEN y} compares the \typ{INT}s \kbd{x} and~\kbd{y}. The result is the sign of $|\kbd{x}| - |\kbd{y}|$. \fun{int}{absi_equal}{GEN x, GEN y} compares the \typ{INT}s \kbd{x} and~\kbd{y}. The result is $1$ if $|\kbd{x}| = |\kbd{y}|$, $0$ otherwise. \fun{int}{absr_cmp}{GEN x, GEN y} compares the \typ{REAL}s \kbd{x} and~\kbd{y}. The result is the sign of $|\kbd{x}| - |\kbd{y}|$. \fun{int}{absrnz_equal2n}{GEN x} tests whether a non-zero \typ{REAL} \kbd{x} is equal to $\pm 2^e$ for some integer $e$. \fun{int}{absrnz_equal1}{GEN x} tests whether a non-zero \typ{REAL} \kbd{x} is equal to $\pm 1$. \subsec{Generic binary operators}\label{se:genbinop} The operators in this section have arguments of C-type \kbd{GEN}, \kbd{long}, and \kbd{ulong}, and only \typ{INT} and \typ{REAL} \kbd{GEN}s are allowed. We say an argument is a real type if it is a \typ{REAL} \kbd{GEN}, and an integer type otherwise. The result is always a \typ{REAL} unless both \kbd{x} and \kbd{y} are integer types. Let ``\op'' be a binary operation among \item \key{add}: addition (\kbd{x + y}). \item \key{sub}: subtraction (\kbd{x - y}). \item \key{mul}: multiplication (\kbd{x * y}). \item \key{div}: division (\kbd{x / y}). In the case where \kbd{x} and \kbd{y} are both integer types, the result is the Euclidean quotient, where the remainder has the same sign as the dividend~\kbd{x}. It is the ordinary division otherwise. A division-by-$0$ error occurs if \kbd{y} is equal to $0$. The last two generic operations are defined only when arguments have integer types; and the result is a \typ{INT}: \item \key{rem}: remainder (``\kbd{x \% y}''). The result is the Euclidean remainder corresponding to \kbd{div},~i.e. its sign is that of the dividend~\kbd{x}. \item \key{mod}: true remainder (\kbd{x \% y}). The result is the true Euclidean remainder, i.e.~non-negative and less than the absolute value of~\kbd{y}. \misctitle{Important technical note} The rules given above fixing the output type (to \typ{REAL} unless both inputs are integer types) are subtly incompatible with the general rules obeyed by PARI's generic functions, such as \kbd{gmul} or \kbd{gdiv} for instance: the latter return a result containing as much information as could be deduced from the inputs, so it is not true that if $x$ is a \typ{INT} and $y$ a \typ{REAL}, then \kbd{gmul(x,y)} is always the same as \kbd{mulir(x,y)}. The exception is $x = 0$, in that case we can deduce that the result is an exact $0$, so \kbd{gmul} returns \kbd{gen\_0}, while \kbd{mulir} returns a \typ{REAL} $0$. Specifically, the one resulting from the conversion of \kbd{gen\_0} to a \typ{REAL} of precision \kbd{precision(y)}, multiplied by $y$; this determines the exponent of the real $0$ we obtain. The reason for the discrepancy between the two rules is that we use the two sets of functions in different contexts: generic functions allow to write high-level code forgetting about types, letting PARI return results which are sensible and as simple as possible; type specific functions are used in kernel programming, where we do care about types and need to maintain strict consistency: it is much easier to compute the types of results when they are determined from the types of the inputs only (without taking into account further arithmetic properties, like being non-0). \smallskip The names and prototypes of the low-level functions corresponding to \op\ are as follows. In this section, the \kbd{z} argument in the \kbd{z}-functions must be of type \typ{INT} when no \kbd{r} or \kbd{mp} appears in the argument code (no \typ{REAL} operand is involved, only integer types), and of type \typ{REAL} otherwise. \funno{GEN}{mp\op[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT} or \typ{REAL} \kbd{x} and~\kbd{y}. The function \kbd{mpdivz} does not exist (its semantic would change drastically depending on the type of the \kbd{z} argument), and neither do \kbd{mprem[z]} nor \kbd{mpmod[z]} (specific to integers). \funno{GEN}{\op si[z]}{long s, GEN x[, GEN z]} applies \op\ to the \kbd{long}~\kbd{s} and the \typ{INT}~\kbd{x}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op sr[z]}{long s, GEN x[, GEN z]} applies \op\ to the \kbd{long}~\kbd{s} and the \typ{REAL}~\kbd{x}. \funno{GEN}{\op ss[z]}{long s, long t[, GEN z]} applies \op\ to the longs \kbd{s} and~\kbd{t}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ii[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT}s \kbd{x} and~\kbd{y}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ir[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT} \kbd{x} and the \typ{REAL}~\kbd{y}. \funno{GEN}{\op is[z]}{GEN x, long s[, GEN z]} applies \op\ to the \typ{INT}~\kbd{x} and the \kbd{long}~\kbd{s}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ri[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{REAL}~\kbd{x} and the \typ{INT}~\kbd{y}. \funno{GEN}{\op rr[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{REAL}s~\kbd{x} and~\kbd{y}. \funno{GEN}{\op rs[z]}{GEN x, long s[, GEN z]} applies \op\ to the \typ{REAL}~\kbd{x} and the \kbd{long}~\kbd{s}. \noindent Some miscellaneous routines: \fun{long}{expu}{ulong x} assuming $x > 0$, returns the binary exponent of the real number equal to $x$. This is a special case of \kbd{gexpo}. \fun{GEN}{adduu}{ulong x, ulong y} \fun{GEN}{addiu}{GEN x, ulong y} \fun{GEN}{addui}{ulong x, GEN y} adds \kbd{x} and \kbd{y}. \fun{GEN}{subuu}{ulong x, ulong y} \fun{GEN}{subiu}{GEN x, ulong y} \fun{GEN}{subui}{ulong x, GEN y} subtracts \kbd{x} by \kbd{y}. \fun{GEN}{muluu}{ulong x, ulong y} multiplies \kbd{x} by \kbd{y}. \fun{GEN}{mului}{ulong x, GEN y} multiplies \kbd{x} by \kbd{y}. \fun{GEN}{muluui}{ulong x, ulong y, GEN z} return $xyz$. \fun{GEN}{muliu}{GEN x, ulong y} multiplies \kbd{x} by \kbd{y}. \fun{void}{addumului}{ulong a, ulong b, GEN x} return $a + b|X|$. \fun{GEN}{addmuliu}{GEN x, GEN y, ulong u} returns $x +yu$. \fun{GEN}{addmulii}{GEN x, GEN y, GEN z} returns $x + yz$. \fun{GEN}{addmulii_inplace}{GEN x, GEN y, GEN z} returns $x + yz$, but returns $x$ itself and not a copy if $yz = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{addmuliu_inplace}{GEN x, GEN y, ulong u} returns $x +yu$, but returns $x$ itself and not a copy if $yu = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{submuliu_inplace}{GEN x, GEN y, ulong u} returns $x- yu$, but returns $x$ itself and not a copy if $yu = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{lincombii}{GEN u, GEN v, GEN x, GEN y} returns $ux + vy$. \fun{GEN}{mulsubii}{GEN y, GEN z, GEN x} returns $yz - x$. \fun{GEN}{submulii}{GEN x, GEN y, GEN z} returns $x - yz$. \fun{GEN}{submuliu}{GEN x, GEN y, ulong u} returns $x -yu$. \fun{GEN}{mulu_interval}{ulong a, ulong b} returns $a(a+1)\cdots b$, assuming that $a \leq b$. Very inefficient when $a = 0$. \fun{GEN}{invr}{GEN x} returns the inverse of the non-zero \typ{REAL}~$x$. \fun{GEN}{truedivii}{GEN x, GEN y} returns the true Euclidean quotient (with non-negative remainder less than $|y|$). \fun{GEN}{truedivis}{GEN x, long y} returns the true Euclidean quotient (with non-negative remainder less than $|y|$). \fun{GEN}{truedivsi}{long x, GEN y} returns the true Euclidean quotient (with non-negative remainder less than $|y|$). \fun{GEN}{centermodii}{GEN x, GEN y, GEN y2}, given \typ{INT}s \kbd{x}, \kbd{y}, returns $z$ congruent to \kbd{x} modulo \kbd{y}, such that $-\kbd{y}/2 \leq z < \kbd{y}/2$. The function requires an extra argument \kbd{y2}, such that \kbd{y2 = shifti(y, -1)}. (In most cases, \kbd{y} is constant for many reductions and \kbd{y2} need only be computed once.) \fun{GEN}{remi2n}{GEN x, long n} returns \kbd{x} mod $2^n$. \fun{GEN}{addii_sign}{GEN x, long sx, GEN y, long sy} add the \typ{INT}s $x$ and $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addir_sign}{GEN x, long sx, GEN y, long sy} add the \typ{INT} $x$ and the \typ{REAL} $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addrr_sign}{GEN x, long sx, GEN y, long sy} add the \typ{REAL}s $x$ and $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addsi_sign}{long x, GEN y, long sy} add $x$ and the \typ{INT} $y$ as if its sign was \kbd{sy}. \fun{GEN}{addui_sign}{ulong x, GEN y, long sy} add $x$ and the \typ{INT} $y$ as if its sign was \kbd{sy}. \subsec{Exact division and divisibility} \fun{GEN}{diviiexact}{GEN x, GEN y} returns the Euclidean quotient $\kbd{x} / \kbd{y}$, assuming $\kbd{y}$ divides $\kbd{x}$. Uses Jebelean algorithm (Jebelean-Krandick bidirectional exact division is not implemented). \fun{GEN}{diviuexact}{GEN x, ulong y} returns the Euclidean quotient $\kbd{x} / \kbd{y}$, assuming $\kbd{y}$ divides $\kbd{x}$ and $\kbd{y}$ is non-zero. \fun{GEN}{diviuuexact}{GEN x, ulong y, ulong z} returns the Euclidean quotient $x/(yz)$, assuming $yz$ divides $x$ and $yz \neq 0$. The following routines return 1 (true) if \kbd{y} divides \kbd{x}, and 0 otherwise. (Error if $y$ is $0$, even if $x$ is $0$.) All \kbd{GEN} are assumed to be \typ{INT}s: \fun{int}{dvdii}{GEN x, GEN y}, \fun{int}{dvdis}{GEN x, long y}, \fun{int}{dvdiu}{GEN x, ulong y}, \fun{int}{dvdsi}{long x, GEN y}, \fun{int}{dvdui}{ulong x, GEN y}. The following routines return 1 (true) if \kbd{y} divides \kbd{x}, and in that case assign the quotient to \kbd{z}; otherwise they return 0. All \kbd{GEN} are assumed to be \typ{INT}s: \fun{int}{dvdiiz}{GEN x, GEN y, GEN z}, \fun{int}{dvdisz}{GEN x, long y, GEN z}. \fun{int}{dvdiuz}{GEN x, ulong y, GEN z} if \kbd{y} divides \kbd{x}, assigns the quotient $|\kbd{x}|/\kbd{y}$ to \kbd{z} and returns 1 (true), otherwise returns 0 (false). \subsec{Division with integral operands and \typ{REAL} result} \fun{GEN}{rdivii}{GEN x, GEN y, long prec}, assuming $x$ and $y$ are both of type \typ{INT}, return the quotient $x/y$ as a \typ{REAL} of precision \kbd{prec}. \fun{GEN}{rdiviiz}{GEN x, GEN y, GEN z}, assuming $x$ and $y$ are both of type \typ{INT}, and $z$ is a \typ{REAL}, assign the quotient $x/y$ to $z$. \fun{GEN}{rdivis}{GEN x, long y, long prec}, assuming \kbd{x} is of type \typ{INT}, return the quotient x/y as a \typ{REAL} of precision \kbd{prec}. \fun{GEN}{rdivsi}{long x, GEN y, long prec}, assuming \kbd{y} is of type \typ{INT}, return the quotient x/y as a \typ{REAL} of precision \kbd{prec}. \fun{GEN}{rdivss}{long x, long y, long prec}, return the quotient x/y as a \typ{REAL} of precision \kbd{prec}. \subsec{Division with remainder} The following functions return two objects, unless specifically asked for only one of them~--- a quotient and a remainder. The quotient is returned and the remainder is returned through the variable whose address is passed as the \kbd{r} argument. The term \emph{true Euclidean remainder} refers to the non-negative one (\kbd{mod}), and \emph{Euclidean remainder} by itself to the one with the same sign as the dividend (\kbd{rem}). All \kbd{GEN}s, whether returned directly or through a pointer, are created on the stack. \fun{GEN}{dvmdii}{GEN x, GEN y, GEN *r} returns the Euclidean quotient of the \typ{INT}~\kbd{x} by a \typ{INT}~\kbd{y} and puts the remainder into~\kbd{*r}. If \kbd{r} is equal to \kbd{NULL}, the remainder is not created, and if \kbd{r} is equal to \kbd{ONLY\_REM}, only the remainder is created and returned. In the generic case, the remainder is created after the quotient and can be disposed of individually with a \kbd{cgiv(r)}. The remainder is always of the sign of the dividend~\kbd{x}. If the remainder is $0$ set \kbd{r = gen\_0}. \fun{void}{dvmdiiz}{GEN x, GEN y, GEN z, GEN t} assigns the Euclidean quotient of the \typ{INT}s \kbd{x} and \kbd{y} into the \typ{INT}~\kbd{z}, and the Euclidean remainder into the \typ{INT}~\kbd{t}. \noindent Analogous routines \tet{dvmdis}\kbd{[z]}, \tet{dvmdsi}\kbd{[z]}, \tet{dvmdss}\kbd{[z]} are available, where \kbd{s} denotes a \kbd{long} argument. But the following routines are in general more flexible: \fun{long}{sdivss_rem}{long s, long t, long *r} computes the Euclidean quotient and remainder of the longs \kbd{s} and~\kbd{t}. Puts the remainder into \kbd{*r}, and returns the quotient. The remainder is of the sign of the dividend~\kbd{s}, and has strictly smaller absolute value than~\kbd{t}. \fun{long}{sdivsi_rem}{long s, GEN x, long *r} computes the Euclidean quotient and remainder of the \kbd{long}~\kbd{s} by the \typ{INT}~\kbd{x}. As \kbd{sdivss\_rem} otherwise. \fun{long}{sdivsi}{long s, GEN x} as \kbd{sdivsi\_rem}, without remainder. \fun{GEN}{divis_rem}{GEN x, long s, long *r} computes the Euclidean quotient and remainder of the \typ{INT}~\kbd{x} by the \kbd{long}~\kbd{s}. As \kbd{sdivss\_rem} otherwise. \fun{GEN}{diviu_rem}{GEN x, ulong s, ulong *r} computes the Euclidean quotient and remainder of \emph{absolute value} of the \typ{INT}~\kbd{x} by the \kbd{ulong}~\kbd{s}. As \kbd{sdivss\_rem} otherwise. \fun{ulong}{udiviu_rem}{GEN n, ulong d, ulong *r} as \tet{diviu_rem}, assuming that $|n|/d$ fits into an \kbd{ulong}. \fun{ulong}{udivui_rem}{ulong x, GEN y, ulong *rem} computes the Euclidean quotient and remainder of $x$ by $y$. As \kbd{sdivss\_rem} otherwise. \fun{ulong}{udivuu_rem}{ulong x, ulong y, ulong *rem} computes the Euclidean quotient and remainder of $x$ by $y$. As \kbd{sdivss\_rem} otherwise. \fun{GEN}{divsi_rem}{long s, GEN y, long *r} computes the Euclidean quotient and remainder of the \typ{long}~\kbd{s} by the \kbd{GEN}~\kbd{y}. As \kbd{sdivss\_rem} otherwise. \fun{GEN}{divss_rem}{long x, long y, long *r} computes the Euclidean quotient and remainder of the \typ{long}~\kbd{x} by the \kbd{long}~\kbd{y}. As \kbd{sdivss\_rem} otherwise. \smallskip \fun{GEN}{truedvmdii}{GEN x, GEN y, GEN *r}, as \kbd{dvmdii} but with a non-negative remainder. \fun{GEN}{truedvmdis}{GEN x, long y, GEN *z}, as \kbd{dvmdis} but with a non-negative remainder. \fun{GEN}{truedvmdsi}{long x, GEN y, GEN *z}, as \kbd{dvmdsi} but with a non-negative remainder. \subsec{Modulo to longs} The following variants of \kbd{modii} do not clutter the stack: \fun{long}{smodis}{GEN x, long y} computes the true Euclidean remainder of the \typ{INT}~\kbd{x} by the \kbd{long}~\kbd{y}. This is the non-negative remainder, not the one whose sign is the sign of \kbd{x} 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}{umodiu}{GEN x, ulong y} computes the true Euclidean remainder of the \typ{INT}~\kbd{x} by the \kbd{ulong}~\kbd{y}. \fun{ulong}{umodui}{ulong x, GEN y} computes the true Euclidean remainder of the \kbd{ulong}~\kbd{x} by the \typ{INT}~\kbd{|y|}. The routine \tet{smodsi} does not exist, since it would not always be defined: for a \emph{negative} \kbd{x}, if the quotient is $\pm1$, the result \kbd{x + |y|} would in general not fit into a \kbd{long}. Use either \kbd{umodui} or \kbd{modsi}. \subsec{Powering, Square root} \fun{GEN}{powii}{GEN x, GEN n}, assumes $x$ and $n$ are \typ{INT}s and returns $x^n$. \fun{GEN}{powuu}{ulong x, ulong n}, returns $x^n$. \fun{GEN}{powiu}{GEN x, ulong n}, assumes $x$ is a \typ{INT} and returns $x^n$. \fun{GEN}{powis}{GEN x, long n}, assumes $x$ is a \typ{INT} and returns $x^n$ (possibly a \typ{FRAC} if $n < 0$). \fun{GEN}{powrs}{GEN x, long n}, assumes $x$ is a \typ{REAL} and returns $x^n$. This is considered as a sequence of \kbd{mulrr}, possibly empty: as such the result has type \typ{REAL}, even if $n = 0$. Note that the generic function \kbd{gpowgs(x,0)} would return \kbd{gen\_1}, 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}{powrshalf}{GEN x, long n}, assumes $x$ is a \typ{REAL} and returns $x^{n/2}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powruhalf}{GEN x, ulong n}, assumes $x$ is a \typ{REAL} and returns $x^{n/2}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powrfrac}{GEN x, long n, long d}, assumes $x$ is a \typ{REAL} and returns $x^{n/d}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powIs}{long n} returns $I^n\in\{1,I,-1,-I\}$ (\typ{INT} for even $n$, \typ{COMPLEX} otherwise). \fun{ulong}{upowuu}{ulong x, ulong n}, returns $x^n$ when $< 2^\B$, and $0$ otherwise (overflow). \fun{GEN}{sqrtremi}{GEN N, GEN *r}, returns the integer square root $S$ of the non-negative \typ{INT}~\kbd{N} (rounded towards 0) and puts the remainder $R$ into~\kbd{*r}. Precisely, $N = S^2 + R$ with $0\leq R \leq 2S$. If \kbd{r} is equal to \kbd{NULL}, the remainder is not created. In the generic case, the remainder is created after the quotient and can be disposed of individually with \kbd{cgiv(R)}. If the remainder is $0$ set \kbd{R = gen\_0}. Uses a divide and conquer algorithm (discrete variant of Newton iteration) due to Paul Zimmermann (``Karatsuba Square Root'', INRIA Research Report 3805 (1999)). \fun{GEN}{sqrti}{GEN N}, returns the integer square root $S$ of the non-negative \typ{INT}~\kbd{N} (rounded towards 0). This is identical to \kbd{sqrtremi(N, NULL)}. \subsec{GCD, extended GCD and LCM} \fun{long}{cgcd}{long x, long y} returns the GCD of \kbd{x} and \kbd{y}. \fun{ulong}{ugcd}{ulong x, ulong y} returns the GCD of \kbd{x} and \kbd{y}. \fun{long}{clcm}{long x, long y} returns the LCM of \kbd{x} and \kbd{y}, provided it fits into a \kbd{long}. Silently overflows otherwise. \fun{GEN}{gcdii}{GEN x, GEN y}, returns the GCD of the \typ{INT}s \kbd{x} and \kbd{y}. \fun{GEN}{lcmii}{GEN x, GEN y}, returns the LCM of the \typ{INT}s \kbd{x} and \kbd{y}. \fun{GEN}{bezout}{GEN a,GEN b, GEN *u,GEN *v}, returns the GCD $d$ of \typ{INT}s \kbd{a} and \kbd{b} and sets \kbd{u}, \kbd{v} to the Bezout coefficients such that $\kbd{au} + \kbd{bv} = d$. \fun{long}{cbezout}{long a,long b, long *u,long *v}, returns the GCD $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, 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{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 restarted using \tet{getrand} and \tet{setrand}. \fun{void}{setrand}{GEN seed} reseeds the random number generator using the seed $n$. The seed is either a technical array output by \kbd{getrand} or a small positive integer, used to generate deterministically a suitable state array. For instance, running a randomized computation starting by \kbd{setrand(1)} twice will generate the exact same output. \fun{GEN}{getrand}{void} returns the current value of the seed used by the pseudo-random number generator \tet{random}. Useful mainly for debugging purposes, to reproduce a specific chain of computations. The returned value is technical (reproduces an internal state array of type \typ{VECSMALL}), and can only be used as an argument to \tet{setrand}. \fun{ulong}{pari_rand}{void} returns a random $0 \leq x < 2^\B$. \fun{long}{random_bits}{long k} returns a random $0 \leq x < 2^k$. Assumes that $0 \leq k \leq \B$. \fun{ulong}{random_Fl}{ulong p} returns a pseudo-random integer in $0, 1, \dots p-1$. \fun{GEN}{randomi}{GEN n} returns a random \typ{INT} between $0$ and $\kbd{n} - 1$. \fun{GEN}{randomr}{long prec} returns a random \typ{REAL} in $[0,1[$, with precision \kbd{prec}. \subsec{Modular operations} In this subsection, all \kbd{GEN}s are \typ{INT} \fun{GEN}{Fp_red}{GEN a, GEN m} returns \kbd{a} modulo \kbd{m} (smallest non-negative residue). (This is identical to modii). \fun{GEN}{Fp_neg}{GEN a, GEN m} returns $-$\kbd{a} modulo \kbd{m} (smallest non-negative residue). \fun{GEN}{Fp_add}{GEN a, GEN b, GEN m} returns the sum of \kbd{a} and \kbd{b} modulo \kbd{m} (smallest non-negative residue). \fun{GEN}{Fp_sub}{GEN a, GEN b, GEN m} returns the difference of \kbd{a} and \kbd{b} modulo \kbd{m} (smallest non-negative residue). \fun{GEN}{Fp_center}{GEN a, GEN p, GEN pov2} assuming that \kbd{pov2} is \kbd{shifti(p,-1)} and that \kbd{a} is between $0$ and $\kbd{p} - 1$ and, returns the representative of \kbd{a} in the symmetric residue system. \fun{GEN}{Fp_mul}{GEN a, GEN b, GEN m} returns the product of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest non-negative residue). \fun{GEN}{Fp_addmul}{GEN x, GEN y, GEN z, GEN p} returns $x + yz$. \fun{GEN}{Fp_mulu}{GEN a, ulong b, GEN m} returns the product of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest non-negative residue). \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_sqr}{GEN a, GEN m} returns $\kbd{a}^2$ modulo \kbd{m} (smallest non-negative residue). \fun{ulong}{Fp_powu}{GEN x, ulong n, GEN m} raises \kbd{x} to the \kbd{n}-th power modulo \kbd{m} (smallest non-negative residue). Not memory-clean, but suitable for \kbd{gerepileupto}. \fun{ulong}{Fp_pows}{GEN x, long n, GEN m} raises \kbd{x} to the \kbd{n}-th power modulo \kbd{m} (smallest non-negative residue). A negative \kbd{n} is 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_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. \fun{GEN}{Fp_invsafe}{GEN a, GEN m} as \kbd{Fp\_inv}, but return \kbd{NULL} if \kbd{a} is not invertible. \fun{GEN}{FpV_inv}{GEN x, GEN m} $x$ being a vector of \typ{INT}s, return the vector of inverses of the $x[i]$ mod $m$. The routine uses Montgomery's trick, and involves a single inversion mod $m$, plus $3(N-1)$ multiplications for $N$ entries. The routine is not stack-clean: $2N$ integers mod $m$ are left on stack, besides the $N$ in the result. \fun{GEN}{Fp_div}{GEN a, GEN b, GEN m} returns the quotient of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest non-negative residue). Raise an error if \kbd{b} is not invertible. \fun{int}{invmod}{GEN a, GEN m, GEN *g}, return $1$ if \kbd{a} modulo \kbd{m} is invertible, else return $0$ and set $\kbd{g} = \gcd(\kbd{a},\kbd{m})$. \fun{GEN}{Fp_log}{GEN a, GEN g, GEN ord, GEN p} Let $g$ such that $g^{ord} \equiv 1 \pmod{p}$. Return an integer $e$ such that $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 \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. \fun{GEN}{Fp_factored_order}{GEN a, GEN N, GEN p} returns $[o,F]$, where $o$ is the multiplicative order of the \kbd{Fp} $a$ in $\F_p^*$, and $F$ is the factorization of $o$. 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. \fun{int}{Fp_issquare}{GEN x, GEN p} returns $1$ if \kbd{x} is a square modulo \kbd{p}, and $0$ otherwise. \fun{int}{Fp_ispower}{GEN x, GEN n, GEN p} returns $1$ if \kbd{x} is an $n$-th power modulo \kbd{p}, and $0$ otherwise. \fun{GEN}{Fp_sqrt}{GEN x, GEN p} returns a square root of \kbd{x} modulo \kbd{p} (the smallest non-negative residue), where \kbd{x}, \kbd{p} are \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}{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} is either a \typ{INT} or is given by its factorisation matrix. Return \kbd{NULL} if no such square root exist. \fun{long}{kross}{long x, long y} returns the \idx{Kronecker symbol} $(x|y)$, i.e.$-1$, $0$ or $1$. If \kbd{y} is an odd prime, this is the \idx{Legendre symbol}. (Contrary to \kbd{krouu}, \kbd{kross} also supports $\kbd{y} = 0$) \fun{long}{krouu}{ulong x, ulong y} returns the \idx{Kronecker symbol} $(x|y)$, i.e.~$-1$, $0$ or $1$. Assumes \kbd{y} is non-zero. If \kbd{y} is an odd prime, this is the \idx{Legendre symbol}. \fun{long}{krois}{GEN x, long y} returns the \idx{Kronecker symbol} $(x|y)$ of \typ{INT}~x and \kbd{long}~\kbd{y}. As \kbd{kross} otherwise. \fun{long}{kroiu}{GEN x, ulong y} returns the \idx{Kronecker symbol} $(x|y)$ 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}{kronecker}{GEN x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$ of \typ{INT}s~x and~\kbd{y}. As \kbd{kross} otherwise. \fun{GEN}{pgener_Fp}{GEN p} returns the smallest primitive root modulo \kbd{p}, assuming \kbd{p} is prime. \fun{GEN}{pgener_Zp}{GEN p} returns the smallest primitive root modulo $p^k$, $k > 1$, assuming \kbd{p} is an odd prime. \fun{long}{Zp_issquare}{GEN x, GEN p} returns 1 if the \typ{INT} $x$ is a $p$-adic square, $0$ otherwise. \fun{long}{Zn_issquare}{GEN x, GEN n} returns 1 if \typ{INT} $x$ is a square modulo \kbd{n} (possibly not prime), where $n$ is either a \typ{INT} or is given by its factorisation matrix. Return $0$ otherwise. \fun{long}{Zn_ispower}{GEN x, GEN n, GEN K, GEN *py} returns 1 if \typ{INT} $x$ is a $K$-th power modulo \kbd{n} (possibly not prime), where $n$ is either a \typ{INT} or is given by its factorisation matrix. Return $0$ otherwise. If \kbd{py} is not \kbd{NULL}, set it to $y$ such that $y^K = x$ modulo $n$. \fun{GEN}{pgener_Fp_local}{GEN p, GEN L}, \kbd{L} being a vector of primes dividing $p - 1$, returns the smallest integer $x > 1$ which is a generator of the $\ell$-Sylow of $\F_p^*$ for every $\ell$ in \kbd{L}. In other words, $x^{(p-1)/\ell} \neq 1$ for all such $\ell$. In particular, returns \kbd{pgener\_Fp(p)} if \kbd{L} contains all primes dividing $p - 1$. It is not necessary, and in fact slightly inefficient, to include $\ell=2$, since 2 is treated separately in any case, i.e. the generator obtained is never a square. \fun{GEN}{rootsof1_Fp}{GEN n, GEN p} returns a primitive $n$-th root modulo the prime $p$. \fun{GEN}{rootsof1u_Fp}{ulong n, GEN p} returns a primitive $n$-th root modulo the prime $p$. \fun{ulong}{rootsof1_Fl}{ulong n, ulong p} returns a primitive $n$-th root modulo the prime $p$. \subsec{Extending functions to vector inputs} The following functions apply $f$ to the given arguments, recursively if they are of vector / matrix type: \fun{GEN}{map_proto_G}{GEN (*f)(GEN), GEN x} For instance, if $x$ is a \typ{VEC}, return a \typ{VEC} whose components are the $f(x[i])$. \fun{GEN}{map_proto_lG}{long (*f)(GEN), GEN x} As above, applying the function \kbd{stoi( f() )}. \fun{GEN}{map_proto_GL}{GEN (*f)(GEN,long), GEN x, long y} \fun{GEN}{map_proto_lGL}{long (*f)(GEN,long), GEN x, long y} In the last function, $f$ implements an associative binary operator, which we extend naturally to an $n$-ary operator $f_n$ for any $n$: by convention, $f_0() = 1$, $f_1(x) = x$, and $$ f_n(x_1,\dots,x_n) = f( f_{n-1}(x_1,\dots,x_{n-1}), x_n)),$$ for $n \geq 2$. \fun{GEN}{gassoc_proto}{GEN (*f)(GEN,GEN),GEN x, GEN y} If $y$ is not \kbd{NULL}, return $f(x,y)$. Otherwise, $x$ must be of vector type, and we return the result of $f$ applied to its components, computed using a divide-and-conquer algorithm. More precisely, return $$f( f(x_1,\kbd{NULL}), f(x_2,\kbd{NULL}) ),$$ where $x_1$, $x_2$ are the two halves of $x$. \subsec{Miscellaneous arithmetic functions} \fun{ulong}{coreu}{ulong n}, unique squarefree integer $d$ dividing $n$ such that $n/d$ is a square. \fun{ulong}{eulerphiu}{ulong n}, Euler's totient function of $n$. \fun{ulong}{eulerphiu_fact}{GEN fa}, Euler's totient function of the \kbd{ulong} $n$, where \kbd{fa} is \kbd{factoru(n)}. \fun{long}{moebiusu}{ulong n}, Moebius $\mu$-function of $n$. \fun{GEN}{divisorsu}{ulong n}, returns the divisors of $n$ in a \typ{VECSMALL}, sorted by increasing order. \fun{long}{uissquarefree}{ulong n} returns $1$ if \kbd{n} is square-free, and $0$ otherwise. \fun{ulong}{uissquarefree_fact}{GEN fa} returns \kbd{uissquarefree(n)}, where \kbd{fa} is \kbd{factoru(n)}. \fun{long}{uposisfundamental}{ulong x} return $1$ is $x$ is a fundamental discriminant, and $0$ otherwise. \fun{long}{unegisfundamental}{ulong x} return $1$ is $-x$ is a fundamental discriminant, and $0$ otherwise. \fun{int}{uis_357_power}{ulong x, ulong *pt, ulong *mask} as \tet{is_357_power} for \kbd{ulong} $x$. \fun{int}{uis_357_powermod}{ulong x, ulong *mask} as \tet{uis_357_power}, but only check for 3rd, 5th or 7th powers modulo $211\times209\times61\times203\times117\times31\times43\times71$. \fun{long}{uisprimepower}{ulong n, ulong *p} as \tet{isprimepower}, for \kbd{ulong} $n$. \fun{int}{uislucaspsp}{ulong n} returns $1$ if the \kbd{ulong} $n$ fails Lucas compositeness test (it thus may be prime or composite), and $0$ otherwise (proving that $n$ is composite). \fun{ulong}{sumdigitsu}{ulong n} returns the sum of decimal digits of $u$. \fun{GEN}{usumdivkvec}{ulong n, GEN K} $K$ being a \typ{VECSMALL} of positive integers. Returns the vector of \kbd{sumdivk}$(n, K[i])$. \fun{GEN}{hilbertii}{GEN x, GEN y, GEN p}, returns the Hilbert symbol $(x,y)$ at the prime $p$ (\kbd{NULL} for the place at infinity); $x$ and $y$ are \typ{INT}s. \fun{GEN}{sumdedekind}{GEN h, GEN k} returns the Dedekind sum associated to the \typ{INT} $h$ and $k$, $k > 0$. \fun{GEN}{sumdedekind_coprime}{GEN h, GEN k} as \kbd{sumdedekind}, except that $h$ and $k$ are assumed to be coprime \typ{INT}s. \fun{GEN}{u_sumdedekind_coprime}{long h, long k} Let $k > 0$, $0 \leq h < k$, $(h,k) = 1$. Returns $[s_1,s_2]$ in a \typ{VECSMALL}, such that $s(h,k) = (s_2 + k s_1) / (12k)$. Requires $\max(h + k/2, k) < \kbd{LONG\_MAX}$ to avoid overflow, in particular $k \leq (2/3)\kbd{LONG\_MAX}$ is fine. \newpage \chapter{Level 2 kernel} These functions deal with modular arithmetic, linear algebra and polynomials where assumptions can be made about the types of the coefficients. \section{Naming scheme}\label{se:level2names} A function name is built in the following way: $A_1\kbd{\_}\dots\kbd{\_}A_n\var{fun}$ for an operation \var{fun} with $n$ arguments of class $A_1$,\dots, $A_n$. A class name is given by a base ring followed by a number of code letters. Base rings are among \kbd{Fl}: $\Z/l\Z$ where $l < 2^{\B}$ is not necessarily prime. Implemented using \kbd{ulong}s \kbd{Fp}: $\Z/p\Z$ where $p$ is a \typ{INT}, not necessarily prime. Implemented as \typ{INT}s $z$, preferably satisfying $0 \leq z < p$. More precisely, any \typ{INT} can be used as an \kbd{Fp}, but reduced inputs are treated more efficiently. Outputs from \kbd{Fp}xxx routines are reduced. \kbd{Fq}: $\Z[X]/(p,T(X))$, $p$ a \typ{INT}, $T$ a \typ{POL} with \kbd{Fp} coefficients or \kbd{NULL} (in which case no reduction modulo \kbd{T} is performed). Implemented as \typ{POL}s $z$ with \kbd{Fp} coefficients, $\deg(z) < \deg \kbd{T}$, although $z$ a \typ{INT} is allowed for elements in the prime field. \kbd{Z}: the integers $\Z$, implemented as \typ{INT}s. \kbd{z}: the integers $\Z$, implemented using (signed) \kbd{long}s. \kbd{Q}: the rational numbers $\Q$, implemented as \typ{INT}s and \typ{FRAC}s. \kbd{Rg}: a commutative ring, whose elements can be \kbd{gadd}-ed, \kbd{gmul}-ed, etc. \noindent Possible letters are: \kbd{X}: polynomial in $X$ (\typ{POL} in a fixed variable), e.g. \kbd{FpX} means $\Z/p\Z[X]$ \kbd{Y}: polynomial in $Y\neq X$. This is used to resolve ambiguities. E.g. \kbd{FpXY} means $((\Z/p\Z)[X])[Y]$. \kbd{V}: vector (\typ{VEC} or \typ{COL}), treated as a line vector (independently of the actual type). E.g. \kbd{ZV} means $\Z^k$ for some $k$. \kbd{C}: vector (\typ{VEC} or \typ{COL}), treated as a column vector (independently of the actual type). The difference with \kbd{V} is purely semantic: if the result is a vector, it will be of type \typ{COL} unless mentioned otherwise. For instance the function \kbd{ZC\_add} receives two integral vectors (\typ{COL} or \typ{VEC}, possibly different types) of the same length and returns a \typ{COL} whose entries are the sums of the input coefficients. \kbd{M}: matrix (\typ{MAT}). E.g. \kbd{QM} means a matrix with rational entries \kbd{T}: Trees. Either a leaf or a \typ{VEC} of trees. \kbd{E}: point over an elliptic curve, represented as two-component vectors \kbd{[x,y]}, except for the represented by the one-component vector \kbd{[0]}. Not all curve models are supported. \kbd{Q}: representative (\typ{POL}) of a class in a polynomial quotient ring. E.g.~an \kbd{FpXQ} belongs to $(\Z/p\Z)[X]/(T(X))$, \kbd{FpXQV} 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. \kbd{x} and \kbd{y} (and \kbd{q}) are implemented by a \typ{VECSMALL} whose first coefficient is used as a code-word and the following are the coefficients , similarly to a \typ{POL}. This is known as a 'POLSMALL'. \kbd{m} are implemented by a \typ{MAT} whose components (columns) are \typ{VECSMALL}s. This is known as a 'MATSMALL'. \kbd{v} and \kbd{c} are regular \typ{VECSMALL}s. Difference between the two is purely semantic. \noindent Omitting the letter means the argument is a scalar in the base ring. Standard functions \var{fun} are \kbd{add}: add \kbd{sub}: subtract \kbd{mul}: multiply \kbd{sqr}: square \kbd{div}: divide (Euclidean quotient) \kbd{rem}: Euclidean remainder \kbd{divrem}: return Euclidean quotient, store remainder in a pointer argument. Three special values of that pointer argument modify the default behavior: \kbd{NULL} (do not store the remainder, used to implement \kbd{div}), \tet{ONLY_REM} (return the remainder, used to implement \kbd{rem}), \tet{ONLY_DIVIDES} (return the quotient if the division is exact, and \kbd{NULL} otherwise). \kbd{gcd}: GCD \kbd{extgcd}: return GCD, store Bezout coefficients in pointer arguments \kbd{pow}: exponentiate \kbd{eval}: evaluation / composition \section{Modular arithmetic} \noindent These routines implement univariate polynomial arithmetic and linear algebra over finite fields, in fact over finite rings of the form $(\Z/p\Z)[X]/(T)$, where $p$ is not necessarily prime and $T\in(\Z/p\Z)[X]$ is possibly reducible; and finite extensions thereof. All this can be emulated with \typ{INTMOD} and \typ{POLMOD} coefficients and using generic routines, at a considerable loss of efficiency. Also, specialized routines are available that have no obvious generic equivalent. \subsec{\kbd{FpC} / \kbd{FpV}, \kbd{FpM}} A \kbd{ZV} (resp.~a~\kbd{ZM}) is a \typ{VEC} or \typ{COL} (resp.~\typ{MAT}) with \typ{INT} coefficients. An \kbd{FpV} or \kbd{FpM}, with respect to a given \typ{INT}~\kbd{p}, is the same with \kbd{Fp} coordinates; operations are understood over $\Z/p\Z$. \subsubsec{Conversions} \fun{int}{Rg_is_Fp}{GEN z, GEN *p}, checks if \kbd{z} can be mapped to $\Z/p\Z$: a \typ{INT} or a \typ{INTMOD} whose modulus is equal to \kbd{*p}, (if \kbd{*p} not \kbd{NULL}), in that case return $1$, else $0$. If a modulus is found it is put in \kbd{*p}, else \kbd{*p} is left unchanged. \fun{int}{RgV_is_FpV}{GEN z, GEN *p}, \kbd{z} a \typ{VEC} (resp. \typ{COL}), checks if it can be mapped to a \kbd{FpV} (resp. \kbd{FpC}), by checking \kbd{Rg\_is\_Fp} coefficientwise. \fun{int}{RgM_is_FpM}{GEN z, GEN *p}, \kbd{z} a \typ{MAT}, checks if it can be mapped to a \kbd{FpM}, by checking \kbd{RgV\_is\_FpV} columnwise. \fun{GEN}{Rg_to_Fp}{GEN z, GEN p}, \kbd{z} a scalar which can be mapped to $\Z/p\Z$: a \typ{INT}, a \typ{INTMOD} whose modulus is divisible by $p$, a \typ{FRAC} whose denominator is coprime to $p$, or a \typ{PADIC} with underlying prime $\ell$ satisfying $p = \ell^n$ for some $n$ (less than the accuracy of the input). Returns \kbd{lift(z * Mod(1,p))}, normalized. \fun{GEN}{padic_to_Fp}{GEN x, GEN p} special case of \tet{Rg_to_Fp}, for a $x$ a \typ{PADIC}. \fun{GEN}{RgV_to_FpV}{GEN z, GEN p}, \kbd{z} a \typ{VEC} or \typ{COL}, returns the \kbd{FpV} (as a \typ{VEC}) obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{RgC_to_FpC}{GEN z, GEN p}, \kbd{z} a \typ{VEC} or \typ{COL}, returns the \kbd{FpC} (as a \typ{COL}) obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{RgM_to_FpM}{GEN z, GEN p}, \kbd{z} a \typ{MAT}, returns the \kbd{FpM} obtained by applying \kbd{RgC\_to\_FpC} columnwise. \fun{GEN}{RgM_Fp_init}{GEN z, GEN p, ulong *pp}, given an \kbd{RgM} $z$, whose entries can be mapped to $\F_p$ (as per \tet{Rg_to_Fp}), and a prime number $p$. This routine returns a normal form of $z$: either an \kbd{F2m} ($p = 2$), an \kbd{Flm} ($p$ fits into an \kbd{ulong}) or an \kbd{FpM}. In the first two cases, \kbd{pp} is set to \kbd{itou}$(p)$, and to $0$ in the last. The functions above are generally used as follow: \bprog GEN add(GEN x, GEN y) { GEN p = NULL; if (Rg_is_Fp(x, &p) && Rg_is_Fp(y, &p) && p) { x = Rg_to_Fp(x, p); y = Rg_to_Fp(y, p); z = Fp_add(x, y, p); return Fp_to_mod(z); } else return gadd(x, y); } @eprog \fun{GEN}{FpC_red}{GEN z, GEN p}, \kbd{z} a \kbd{ZC}. Returns \kbd{lift(Col(z) * Mod(1,p))}, hence a \typ{COL}. \fun{GEN}{FpV_red}{GEN z, GEN p}, \kbd{z} a \kbd{ZV}. Returns \kbd{lift(Vec(z) * Mod(1,p))}, hence a \typ{VEC} \fun{GEN}{FpM_red}{GEN z, GEN p}, \kbd{z} a \kbd{ZM}. Returns \kbd{lift(z * Mod(1,p))}, which is an \kbd{FpM}. \subsubsec{Basic operations} \fun{GEN}{FpC_center}{GEN z, GEN p, GEN pov2} returns a \typ{COL} whose 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{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}{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}. \fun{GEN}{FpV_sub}{GEN x, GEN y, GEN p} same as \kbd{FpC\_sub}, returning and \kbd{FpV}. \fun{GEN}{FpC_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZC}~\kbd{x} (seen as a column vector) by the \typ{INT}~\kbd{y} and reduce modulo \kbd{p} to obtain an \kbd{FpC}. \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 an \kbd{FpM}. \fun{GEN}{FpM_mul}{GEN x, GEN y, GEN p} multiplies 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}{FpM_powu}{GEN x, ulong n, GEN p} computes $x^n$ where $x$ is a square \kbd{FpM}. \fun{GEN}{FpM_FpC_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpC}. \fun{GEN}{FpM_FpC_mul_FpX}{GEN x, GEN y, GEN p, long v} is a memory-clean version of \bprog GEN tmp = FpM_FpC_mul(x,y,p); return RgV_to_RgX(tmp, v); @eprog \fun{GEN}{FpV_FpC_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZV}~\kbd{x} (seen as a row vector) by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{Fp}. \fun{GEN}{FpV_dotproduct}{GEN x,GEN y,GEN p} scalar product of $x$ and $y$ (assumed to have the same length). \fun{GEN}{FpV_dotsquare}{GEN x, GEN p} scalar product of $x$ with itself. has \typ{INT} entries. \subsubsec{\kbd{Fp}-linear algebra} The implementations are not asymptotically efficient ($O(n^3)$ standard algorithms). \fun{GEN}{FpM_deplin}{GEN x, GEN p} returns a non-trivial kernel vector, or \kbd{NULL} if none exist. \fun{GEN}{FpM_det}{GEN x, GEN p} as \kbd{det} \fun{GEN}{FpM_gauss}{GEN a, GEN b, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FpM}. \fun{GEN}{FpM_FpC_gauss}{GEN a, GEN b, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FpC}. \fun{GEN}{FpM_image}{GEN x, GEN p} as \kbd{image} \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_FpC_invimage}{GEN m, GEN v, GEN p} given an \kbd{FpM} $x$ 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} if no such matrix exist. \fun{GEN}{FpM_ker}{GEN x, GEN p} as \kbd{ker} \fun{long}{FpM_rank}{GEN x, GEN p} as \kbd{rank} \fun{GEN}{FpM_indexrank}{GEN x, GEN p} as \kbd{indexrank} \fun{GEN}{FpM_suppl}{GEN x, GEN p} as \kbd{suppl} \fun{GEN}{FpM_hess}{GEN x, GEN p} upper Hessenberg form of $x$ over $\F_p$. \fun{GEN}{FpM_charpoly}{GEN x, GEN p} characteristic polynomial of $x$. \subsubsec{\kbd{FqC}, \kbd{FqM} and \kbd{Fq}-linear algebra} An \kbd{FqM} (resp. \kbd{FqC}) is a matrix (resp a \typ{COL}) with \kbd{Fq} coefficients (with respect to given \kbd{T}, \kbd{p}), not necessarily reduced (i.e arbitrary \typ{INT}s and \kbd{ZX}s in the same variable as \kbd{T}). \fun{GEN}{FqC_add}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqC_sub}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqC_Fq_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_deplin}{GEN x, GEN T, GEN p} returns a non-trivial kernel vector, or \kbd{NULL} if none exist. \fun{GEN}{FqM_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FqM}. \fun{GEN}{FqM_FqC_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FqC}. \fun{GEN}{FqM_FqC_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_ker}{GEN x, GEN T, GEN p} as \kbd{ker} \fun{GEN}{FqM_image}{GEN x, GEN T, GEN p} as \kbd{image} \fun{GEN}{FqM_inv}{GEN x, GEN T, GEN p} returns the inverse of \kbd{x}, or \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FqM_mul}{GEN a, GEN b, GEN T, GEN p} \fun{long}{FqM_rank}{GEN x, GEN T, GEN p} as \kbd{rank} \fun{GEN}{FqM_suppl}{GEN x, GEN T, GEN p} as \kbd{suppl} \fun{GEN}{FqM_det}{GEN x, GEN T, GEN p} as \kbd{det} \subsec{\kbd{Flc} / \kbd{Flv}, \kbd{Flm}} See \kbd{FpV}, \kbd{FpM} operations. \fun{GEN}{Flv_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{Flv_center}{GEN z, ulong p, ulong ps2} \fun{GEN}{Flm_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{matid_Flm}{long n} returns an \kbd{Flm} which is an $n \times n$ identity matrix. \fun{GEN}{scalar_Flm}{long s, long n} returns an \kbd{Flm} which is $s$ times the $n \times n$ identity matrix. \fun{GEN}{Flm_center}{GEN z, ulong p, ulong ps2} \fun{GEN}{Flm_Fl_add}{GEN x, ulong y, ulong p} returns $x + y*\text{Id}$ ($x$ must be square). \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_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flm} \kbd{x} by \kbd{y}. \fun{GEN}{Flm_neg}{GEN x, ulong p} negates the \kbd{Flm} \kbd{x}. \fun{void}{Flm_Fl_mul_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flm} \kbd{x} by $\kbd{x}*\kbd{y}$. \fun{GEN}{Flc_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flv} \kbd{x} by \kbd{y}. \fun{void}{Flc_Fl_mul_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flc} \kbd{x} by $\kbd{x}*\kbd{y}$. \fun{void}{Flc_Fl_mul_part_inplace}{GEN x, ulong y, ulong p, long l} multiplies $x[1..l]$ by $y$ modulo $p$. In place. \fun{GEN}{Flc_Fl_div}{GEN x, ulong y, ulong p} divides the \kbd{Flv} \kbd{x} by \kbd{y}. \fun{void}{Flc_Fl_div_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flv} \kbd{x} by $\kbd{x}/\kbd{y}$. \fun{void}{Flc_lincomb1_inplace}{GEN X, GEN Y, ulong v, ulong q} sets $X\leftarrow X + vY$, where $X,Y$ are \kbd{Flc}. Memory efficient (e.g. no-op if $v = 0$), and gerepile-safe. \fun{GEN}{Flv_add}{GEN x, GEN y, ulong p} adds two \kbd{Flv}. \fun{void}{Flv_add_inplace}{GEN x, GEN y, ulong p} replaces $x$ by $x+y$. \fun{GEN}{Flv_sub}{GEN x, GEN y, ulong p} subtracts \kbd{y} to \kbd{x}. \fun{void}{Flv_sub_inplace}{GEN x, GEN y, ulong p} replaces $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_sum}{GEN x, ulong p} returns the sums of the components of $x$. \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 all columns. \fun{GEN}{zero_Flm_copy}{long m, long n} creates a \kbd{Flm} with \kbd{m} x \kbd{n} components set to $0$. \fun{GEN}{zero_Flv}{long n} creates a \kbd{Flv} with \kbd{n} components set to $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_mul}{GEN x, GEN y, ulong p} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{Flm_powu}{GEN x, ulong n, ulong p} computes $x^n$ where $x$ is a square \kbd{Flm}. \fun{GEN}{Flm_charpoly}{GEN x, ulong p} return the characteristic polynomial of the square \kbd{Flm} $x$, as a \kbd{Flx}. \fun{GEN}{Flm_deplin}{GEN x, ulong p} \fun{ulong}{Flm_det}{GEN x, ulong p} \fun{ulong}{Flm_det_sp}{GEN x, ulong p}, as \kbd{Flm\_det}, in place (destroys~\kbd{x}). \fun{GEN}{Flm_gauss}{GEN a, GEN b, ulong p} as \kbd{gauss}, where $b$ is a \kbd{Flm}. \fun{GEN}{Flm_Flc_gauss}{GEN a, GEN b, ulong p} as \kbd{gauss}, where $b$ is a \kbd{Flc}. \fun{GEN}{Flm_indexrank}{GEN x, ulong p} \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} 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} if no such matrix exist. \fun{GEN}{Flm_ker}{GEN x, ulong p} \fun{GEN}{Flm_ker_sp}{GEN x, ulong p, long deplin}, as \kbd{Flm\_ker} (if \kbd{deplin=0}) or \kbd{Flm\_deplin} (if \kbd{deplin=1}) , in place (destroys~\kbd{x}). \fun{long}{Flm_rank}{GEN x, ulong p} \fun{long}{Flm_suppl}{GEN x, ulong p} \fun{GEN}{Flm_image}{GEN x, ulong p} \fun{GEN}{Flm_transpose}{GEN x} \fun{GEN}{Flm_hess}{GEN x, ulong p} upper Hessenberg form of $x$ over $\F_p$. \subsec{\kbd{F2c} / \kbd{F2v}, \kbd{F2m}} An \kbd{F2v}~\kbd{v} is a \typ{VECSMALL} representing a vector over $\F_2$. Specifically \kbd{z[0]} is the usual codeword, \kbd{z[1]} is the number of components of $v$ and the coefficients are given by the bits of remaining words by increasing indices. \fun{ulong}{F2v_coeff}{GEN x, long i} returns the coefficient $i\ge 1$ of $x$. \fun{void}{F2v_clear}{GEN x, long i} sets the coefficient $i\ge 1$ of $x$ to $0$. \fun{void}{F2v_flip}{GEN x, long i} adds $1$ to the coefficient $i\ge 1$ of $x$. \fun{void}{F2v_set}{GEN x, long i} sets the coefficient $i\ge 1$ of $x$ to $1$. \fun{void}{F2v_copy}{GEN x} returns a copy of $x$. \fun{GEN}{F2v_slice}{GEN x, long a, long b} returns the \kbd{F2v} with entries $x[a]$, \dots, $x[b]$. Assumes $a \leq b$. \fun{ulong}{F2m_coeff}{GEN x, long i, long j} returns the coefficient $(i,j)$ of $x$. \fun{void}{F2m_clear}{GEN x, long i, long j} sets the coefficient $(i,j)$ of $x$ to $0$. \fun{void}{F2m_flip}{GEN x, long i, long j} adds $1$ to the coefficient $(i,j)$ of $x$. \fun{void}{F2m_set}{GEN x, long i, long j} sets the coefficient $(i,j)$ of $x$ to $1$. \fun{void}{F2m_copy}{GEN x} returns a copy of $x$. \fun{GEN}{F2m_rowslice}{GEN x, long a, long b} returns the \kbd{F2m} built from the $a$-th to $b$-th rows of the \kbd{F2m} $x$. Assumes $a \leq b$. \fun{GEN}{F2m_F2c_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{F2m_image}{GEN x} gives a subset of the columns of $x$ that generate the image of $x$. \fun{GEN}{F2m_invimage}{GEN A, GEN B} \fun{GEN}{F2m_F2c_invimage}{GEN A, GEN y} \fun{GEN}{F2m_gauss}{GEN a, GEN b} as \kbd{gauss}, where $b$ is a \kbd{F2m}. \fun{GEN}{F2m_F2c_gauss}{GEN a, GEN b} as \kbd{gauss}, where $b$ is a \kbd{F2c}. \fun{GEN}{F2m_indexrank}{GEN x} $x$ being a matrix of rank $r$, returns a vector with two \typ{VECSMALL} components $y$ and $z$ of length $r$ giving a list of rows and columns respectively (starting from 1) such that the extracted matrix obtained from these two vectors using \kbd{vecextract}$(x,y,z)$ is invertible. \fun{GEN}{F2m_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{F2m_powu}{GEN x, ulong n} computes $x^n$ where $x$ is a square \kbd{F2m}. \fun{long}{F2m_rank}{GEN x} as \kbd{rank}. \fun{long}{F2m_suppl}{GEN x} as \kbd{suppl}. \fun{GEN}{matid_F2m}{long n} returns an \kbd{F2m} which is an $n \times n$ identity matrix. \fun{GEN}{zero_F2v}{long n} creates a \kbd{F2v} with \kbd{n} components set to $0$. \fun{GEN}{F2v_ei}{long n, long i} creates a \kbd{F2v} with \kbd{n} components set to $0$, but for the $i$-th one, which is set to $1$ ($i$-th vector in the canonical basis). \fun{GEN}{zero_F2m}{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 all columns. \fun{GEN}{zero_F2m_copy}{long m, long n} creates a \kbd{F2m} with \kbd{m} x \kbd{n} components set to $0$. \fun{GEN}{F2c_to_Flc}{GEN x} \fun{GEN}{F2c_to_ZC}{GEN x} \fun{GEN}{ZV_to_F2v}{GEN x} \fun{GEN}{RgV_to_F2v}{GEN x} \fun{GEN}{F2m_to_Flm}{GEN x} \fun{GEN}{F2m_to_ZM}{GEN x} \fun{GEN}{Flv_to_F2v}{GEN x} \fun{GEN}{Flm_to_F2m}{GEN x} \fun{GEN}{ZM_to_F2m}{GEN x} \fun{GEN}{RgM_to_F2m}{GEN x} \fun{void}{F2v_add_inplace}{GEN x, GEN y} replaces $x$ by $x+y$. It is allowed for $y$ to be shorter than $x$. \fun{ulong}{F2m_det}{GEN x} \fun{ulong}{F2m_det_sp}{GEN x}, as \kbd{F2m\_det}, in place (destroys~\kbd{x}). \fun{GEN}{F2m_deplin}{GEN x} \fun{ulong}{F2v_dotproduct}{GEN x, GEN y} returns the scalar product of \kbd{x} and \kbd{y} \fun{GEN}{F2m_inv}{GEN x} \fun{GEN}{F2m_ker}{GEN x} \fun{GEN}{F2m_ker_sp}{GEN x, long deplin}, as \kbd{F2m\_ker} (if \kbd{deplin=0}) or \kbd{F2m\_deplin} (if \kbd{deplin=1}), in place (destroys~\kbd{x}). \subsec{\kbd{FlxqV}, \kbd{FlxqM}} See \kbd{FqV}, \kbd{FqM} operations. \fun{GEN}{FlxqV_dotproduct}{GEN x, GEN y, GEN T, ulong p} as \kbd{FpV\_dotproduct}. \fun{GEN}{FlxM_Flx_add_shallow}{GEN x, GEN y, ulong p} as \kbd{RgM\_Rg\_add\_shallow}. \fun{GEN}{FlxqM_gauss}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_FlxqC_gauss}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_FlxqC_mul}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_ker}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_image}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_det}{GEN a, GEN T, ulong p} \fun{GEN}{FlxqM_inv}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_mul}{GEN a, GEN b, GEN T, ulong p} \fun{long}{FlxqM_rank}{GEN x, GEN T, ulong p} \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 to $[0, \kbd{p}-1]$; an \kbd{FpX} is a \typ{POL} in a fixed variable whose coefficients are \kbd{Fp} objects. Unless mentioned otherwise, all outputs in this section are \kbd{FpX}s. All operations are understood to take place in $(\Z/\kbd{p}\Z)[X]$. \subsubsec{Conversions} In what follows \kbd{p} is always a \typ{INT}, not necessarily prime. \fun{int}{RgX_is_FpX}{GEN z, GEN *p}, \kbd{z} a \typ{POL}, checks if it can be mapped to a \kbd{FpX}, by checking \kbd{Rg\_is\_Fp} coefficientwise. \fun{GEN}{RgX_to_FpX}{GEN z, GEN p}, \kbd{z} a \typ{POL}, returns the \kbd{FpX} obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{FpX_red}{GEN z, GEN p}, \kbd{z} a \kbd{ZX}, returns \kbd{lift(z * Mod(1,p))}, normalized. \fun{GEN}{FpXV_red}{GEN z, GEN p}, \kbd{z} a \typ{VEC} of \kbd{ZX}. Applies \kbd{FpX\_red} componentwise and returns the result (and we obtain a vector of \kbd{FpX}s). \fun{GEN}{FpXT_red}{GEN z, GEN p}, \kbd{z} a tree of \kbd{ZX}. Applies \kbd{FpX\_red} to each leaf and returns the result (and we obtain a tree of \kbd{FpX}s). \subsubsec{Basic operations} In what follows \kbd{p} is always a \typ{INT}, not necessarily prime. \noindent Now, except for \kbd{p}, the operands and outputs are all \kbd{FpX} objects. Results are undefined on other inputs. \fun{GEN}{FpX_add}{GEN x,GEN y, GEN p} adds \kbd{x} and \kbd{y}. \fun{GEN}{FpX_neg}{GEN x,GEN p} returns $-\kbd{x}$, the components are between $0$ and $p$ if this is the case for the components of $x$. \fun{GEN}{FpX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{FpX_sub}{GEN x,GEN y,GEN p} returns $x-y$. \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} see \kbd{ZX\_mulspec} \fun{GEN}{FpX_sqr}{GEN x,GEN p} returns $\kbd{x}^2$. \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. \fun{GEN}{FpX_div}{GEN x, GEN y, GEN p} returns the quotient of \kbd{x} by \kbd{y}. \fun{GEN}{FpX_div_by_X_x}{GEN A, GEN a, GEN p, GEN *r} returns the quotient of the \kbd{FpX}~\kbd{A} by $(X - \kbd{a})$, and sets \kbd{r} to the remainder $\kbd{A}(\kbd{a})$. \fun{GEN}{FpX_rem}{GEN x, GEN y, GEN p} returns the remainder \kbd{x} mod \kbd{y}. \fun{long}{FpX_valrem}{GEN x, GEN t, GEN p, GEN *r} The arguments \kbd{x} and \kbd{e} being non-zero \kbd{FpX} returns the highest exponent $e$ such that $\kbd{t}^{e}$ divides~\kbd{x}. The quotient $\kbd{x}/\kbd{t}^{e}$ is returned in~\kbd{*r}. In particular, if \kbd{t} is irreducible, this returns the valuation at \kbd{t} of~\kbd{x}, and \kbd{*r} is the prime-to-\kbd{t} part of~\kbd{x}. \fun{GEN}{FpX_deriv}{GEN x, GEN p} returns the derivative of \kbd{x}. This function is not memory-clean, but nevertheless suitable for \kbd{gerepileupto}. \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)$. \fun{GEN}{FpX_gcd}{GEN x, GEN y, GEN p} returns a (not necessarily monic) greatest common divisor of $x$ and $y$. \fun{GEN}{FpX_halfgcd}{GEN x, GEN y, GEN p} returns a two-by-two \kbd{FpXM} $M$ with determinant $\pm 1$ such that the image $(a,b)$ of $(x,y)$ by $M$ has the property that $\deg a \geq {\deg x \over 2} > \deg b$. \fun{GEN}{FpX_extgcd}{GEN x, GEN y, GEN p, GEN *u, GEN *v} returns $d = \text{GCD}(\kbd{x},\kbd{y})$ (not necessarily monic), and sets \kbd{*u}, \kbd{*v} to the Bezout coefficients such that $\kbd{*ux} + \kbd{*vy} = d$. If \kbd{*u} is set to \kbd{NULL}, it is not computed which is a bit faster. This is useful when computing the inverse of $y$ modulo $x$. \fun{GEN}{FpX_center}{GEN z, GEN p, GEN pov2} returns the polynomial whose 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)}. \subsubsec{Mixed operations} The following functions implement arithmetic operations between \kbd{FpX} and \kbd{Fp} operands, the result being of type \kbd{FpX}. The integer \kbd{p} need not be prime. \fun{GEN}{Z_to_FpX}{GEN x, GEN p, long v} converts a \typ{INT} to a scalar polynomial in variable $v$, reduced modulo $p$. \fun{GEN}{FpX_Fp_add}{GEN y, GEN x, GEN p} add the \kbd{Fp}~\kbd{x} to the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpX_Fp_add_shallow}{GEN y, GEN x, GEN p} add the \kbd{Fp}~\kbd{x} to the \kbd{FpX}~\kbd{y}, using a shallow copy (result not suitable for \kbd{gerepileupto}) \fun{GEN}{FpX_Fp_sub}{GEN y, GEN x, GEN p} subtract the \kbd{Fp}~\kbd{x} from the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpX_Fp_sub_shallow}{GEN y, GEN x, GEN p} subtract the \kbd{Fp}~\kbd{x} from the \kbd{FpX}~\kbd{y}, using a shallow copy (result not suitable for \kbd{gerepileupto}) \fun{GEN}{Fp_FpX_sub}{GEN x,GEN y,GEN p} returns $x - y$, where $x$ is a \typ{INT} and $y$ an \kbd{FpX}. \fun{GEN}{FpX_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{FpX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \fun{GEN}{FpX_Fp_mulspec}{GEN x, GEN y, GEN p, long lx} see \kbd{ZX\_mulspec} \fun{GEN}{FpX_mulu}{GEN x, ulong y, GEN p} multiplies the \kbd{FpX}~\kbd{x} by \kbd{y}. \fun{GEN}{FpX_Fp_mul_to_monic}{GEN y,GEN x,GEN p} returns $y\*x$ assuming the result is monic of the same degree as $y$ (in particular $x\neq 0$). \subsubsec{Miscellaneous operations} \fun{GEN}{FpX_normalize}{GEN z, GEN p} divides the \kbd{FpX}~\kbd{z} by its leading coefficient. If the latter is~$1$, \kbd{z} itself is returned, not a copy. If not, the inverse remains uncollected on the stack. \fun{GEN}{FpX_invBarrett}{GEN T, GEN p}, returns the Barrett inverse $M$ of $T$ defined by $M(x)\*x^n\*T(1/x)\equiv 1\pmod{x^{n-1}}$ where $n$ is the degree of $T$. \fun{GEN}{FpX_rescale}{GEN P, GEN h, GEN p} returns $h^{\deg(P)} P(x/h)$. \kbd{P} is an \kbd{FpX} and \kbd{h} is a non-zero \kbd{Fp} (the routine would work with any non-zero \typ{INT} but is not efficient in this case). \fun{GEN}{FpX_eval}{GEN x, GEN y, GEN p} evaluates the \kbd{FpX}~\kbd{x} at the \kbd{Fp}~\kbd{y}. The result is an~\kbd{Fp}. \fun{GEN}{FpXV_FpC_mul}{GEN V, GEN W, GEN p} multiplies a non-empty line vector of\kbd{FpX} by a column vector of \kbd{Fp} of compatible dimensions. The result is an~\kbd{FpX}. \fun{GEN}{FpXV_prod}{GEN V, GEN p}, \kbd{V} being a vector of \kbd{FpX}, returns their product. \fun{GEN}{FpV_roots_to_pol}{GEN V, GEN p, long v}, \kbd{V} being a vector of \kbd{INT}s, returns the monic \kbd{FpX} $\prod_i (\kbd{pol\_x[v]} - \kbd{V[i]})$. \fun{GEN}{FpX_chinese_coprime}{GEN x,GEN y, GEN Tx,GEN Ty, GEN Tz, GEN p}: returns an \kbd{FpX}, congruent to \kbd{x} mod \kbd{Tx} and to \kbd{y} mod \kbd{Ty}. Assumes \kbd{Tx} and \kbd{Ty} are coprime, and \kbd{Tz = Tx * Ty} or \kbd{NULL} (in which case it is computed within). \fun{GEN}{FpV_polint}{GEN x, GEN y, GEN p} returns the \kbd{FpX} interpolation polynomial with value \kbd{y[i]} at \kbd{x[i]}. Assumes lengths are the same, components are \typ{INT}s, and the \kbd{x[i]} are distinct modulo \kbd{p}. \fun{int}{FpX_is_squarefree}{GEN f, GEN p} returns $1$ if the \kbd{FpX}~\kbd{f} is squarefree, $0$ otherwise. \fun{int}{FpX_is_irred}{GEN f, GEN p} returns $1$ if the \kbd{FpX}~\kbd{f} is irreducible, $0$ otherwise. Assumes that \kbd{p} is prime. If~\kbd{f} has few factors, \kbd{FpX\_nbfact(f,p) == 1} is much faster. \fun{int}{FpX_is_totally_split}{GEN f, GEN p} returns $1$ if the \kbd{FpX}~\kbd{f} splits into a product of distinct linear factors, $0$ otherwise. Assumes that \kbd{p} is prime. \fun{GEN}{FpX_factor}{GEN f, GEN p}, factors the \kbd{FpX}~\kbd{f}. Assumes that \kbd{p} is prime. The returned value \kbd{v} is a \typ{VEC} with two components: \kbd{v[1]} is a vector of distinct irreducible (\kbd{FpX}) factors, and \kbd{v[2]} is a \typ{VECSMALL} of corresponding exponents. The order of the factors is deterministic (the computation is not). \fun{long}{FpX_nbfact}{GEN f, GEN p}, assuming the \kbd{FpX}~f is squarefree, returns the number of its irreducible factors. Assumes that \kbd{p} is prime. \fun{long}{FpX_degfact}{GEN f, GEN p}, as \kbd{FpX\_factor}, but the degrees of the irreducible factors are returned instead of the factors themselves (as a \typ{VECSMALL}). Assumes that \kbd{p} is prime. \fun{long}{FpX_nbroots}{GEN f, GEN p} returns the number of distinct roots in \kbd{\Z/p\Z} of the \kbd{FpX}~\kbd{f}. Assumes that \kbd{p} is prime. \fun{GEN}{FpX_oneroot}{GEN f, GEN p} returns one root in \kbd{\Z/p\Z} of the \kbd{FpX}~\kbd{f}. Return \kbd{NULL} if no root exists. Assumes that \kbd{p} is prime. \fun{GEN}{FpX_roots}{GEN f, GEN p} returns the roots in \kbd{\Z/p\Z} of the \kbd{FpX}~\kbd{f} (without multiplicity, as a vector of \kbd{Fp}s). Assumes that \kbd{p} is prime. \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}. \fun{GEN}{FpX_resultant}{GEN x, GEN y, GEN p} returns the resultant of \kbd{x} and \kbd{y}, both \kbd{FpX}. The result is a \typ{INT} belonging to $[0,p-1]$. \fun{GEN}{FpX_disc}{GEN x, GEN p} returns the discriminant of the \kbd{FpX} \kbd{x}. The result is a \typ{INT} belonging to $[0,p-1]$. \fun{GEN}{FpX_FpXY_resultant}{GEN a, GEN b, GEN p}, \kbd{a} a \typ{POL} of \typ{INT}s (say in variable $X$), \kbd{b} a \typ{POL} (say in variable $X$) whose coefficients are either \typ{POL}s in $\Z[Y]$ or \typ{INT}s. Returns $\text{Res}_X(a, b)$ in $\F_p[Y]$ as an \kbd{FpY}. The function assumes that $X$ has lower priority than $Y$. \subsec{\kbd{FpXQ}, \kbd{Fq}} Let \kbd{p} a \typ{INT} and \kbd{T} an \kbd{FpX} for \kbd{p}, both to be given in the function arguments; an \kbd{FpXQ} object is an \kbd{FpX} whose degree is strictly less than the degree of \kbd{T}. An \kbd{Fq} is either an \kbd{FpXQ} or an \kbd{Fp}. Both represent a class in $(\Z/\kbd{p}\Z)[X] / (T)$, in which all operations below take place. In addition, \kbd{Fq} routines also allow $\kbd{T} = \kbd{NULL}$, in which case no reduction mod \kbd{T} is performed on the result. For efficiency, the routines in this section may leave small unused objects behind on the stack (their output is still suitable for \kbd{gerepileupto}). Besides \kbd{T} and \kbd{p}, arguments are either \kbd{FpXQ} or \kbd{Fq} depending on the function name. (All \kbd{Fq} routines accept \kbd{FpXQ}s by definition, not the other way round.) \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{T} can be replaced by an extended modulus, which is an \kbd{FpXT}, in all \kbd{FpXQ}- and \kbd{Fq}-classes functions, and in \kbd{FpX\_rem} and \kbd{FpX\_divrem}. \fun{GEN}{FpX_get_red}{GEN T, GEN p} returns the extended modulus \kbd{eT}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_FpX_mod}{GEN eT} returns the underlying modulus \kbd{T}. \fun{GEN}{get_FpX_var}{GEN eT} returns the variable number of the modulus. \fun{GEN}{get_FpX_degree}{GEN eT} returns the degree of the modulus. Furthermore, \kbd{ZXT\_to\_FlxT} allows to convert an extended modulus for a \kbd{FpX} to an extended modulus for the corresponding \kbd{Flx}. \subsubsec{Conversions} \fun{GEN}{Rg_is_FpXQ}{GEN z, GEN *T, GEN *p}, checks if \kbd{z} is a \kbd{GEN} 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}). 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 \kbd{*T} is left unchanged. \fun{int}{RgX_is_FpXQX}{GEN z, GEN *T, GEN *p}, \kbd{z} a \typ{POL}, checks if it can be mapped to a \kbd{FpXQX}, by checking \kbd{Rg\_is\_FpXQ} coefficientwise. \fun{GEN}{Rg_to_FpXQ}{GEN z, GEN T, GEN p}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_p[X]/(T)$: anything \kbd{Rg\_to\_Fp} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_FpX} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{FpX}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{FpXQ}, normalized. \fun{GEN}{RgX_to_FpXQX}{GEN z, GEN T, GEN p}, \kbd{z} a \typ{POL}, returns the \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} coefficientwise and simplifying scalars to \typ{INT}s. \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}). \fun{GEN}{FqX_red}{GEN x, GEN T, GEN p}, \kbd{x} a \typ{POL} whose coefficients are \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{Fq}s. (If $\kbd{T} = \kbd{NULL}$, as \kbd{FpXX\_red(x, p)}.) \fun{GEN}{FqV_red}{GEN x, GEN T, GEN p}, \kbd{x} a vector of \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{Fq}s. (If $\kbd{T} = \kbd{NULL}$, only reduce components mod \kbd{p} to \kbd{FpX}s or \kbd{Fp}s.) \fun{GEN}{FpXQ_red}{GEN x, GEN T,GEN p} \kbd{x} a \typ{POL} whose coefficients are \typ{INT}s, reduce them to \kbd{FpXQ}s. \subsec{\kbd{FpXQ}} \fun{GEN}{FpXQ_add}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_sub}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_mul}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{FpXQ_div}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_inv}{GEN x, GEN T, GEN p} computes the inverse of \kbd{x} \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}$ for small $n$. \fun{GEN}{FpXQ_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. Assumes that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{Fp_FpXQ_log}{GEN a, GEN g, GEN ord, GEN T, GEN p} As \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 \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}. \fun{int}{FpXQ_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}. \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}. \subsec{\kbd{Fq}} \fun{GEN}{Fq_add}{GEN x, GEN y, GEN T/*unused*/, GEN p} \fun{GEN}{Fq_sub}{GEN x, GEN y, GEN T/*unused*/, GEN p} \fun{GEN}{Fq_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{Fq_Fp_mul}{GEN x, GEN y, GEN T, GEN p} multiplies the \kbd{Fq} $x$ 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_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{Fq_neg}{GEN x, GEN T, GEN p} \fun{GEN}{Fq_neg_inv}{GEN x, GEN T, GEN p} computes $-\kbd{x}^{-1}$ \fun{GEN}{Fq_inv}{GEN x, GEN pol, GEN p} computes $\kbd{x}^{-1}$, raising an error if \kbd{x} is not invertible. \fun{GEN}{Fq_invsafe}{GEN x, GEN pol, GEN p} as \kbd{Fq\_inv}, but returns \kbd{NULL} 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 \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 stack, besides the $N$ in the result. \fun{GEN}{Fq_pow}{GEN x, GEN n, GEN pol, GEN p} returns $\kbd{x}^\kbd{n}$. \fun{GEN}{Fq_powu}{GEN x, ulong n, GEN pol, GEN p} returns $\kbd{x}^\kbd{n}$ for small $n$. \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}. \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}{FpXQ_charpoly}{GEN x, GEN T, GEN p} returns the characteristic polynomial of \kbd{x} \fun{GEN}{FpXQ_minpoly}{GEN x, GEN T, GEN p} returns the minimal polynomial of \kbd{x} \fun{GEN}{FpXQ_norm}{GEN x, GEN T, GEN p} returns the norm of \kbd{x} \fun{GEN}{FpXQ_trace}{GEN x, GEN T, GEN p} returns the trace of \kbd{x} \fun{GEN}{FpXQ_conjvec}{GEN x, GEN T, GEN p} returns the vector of conjugates $[x,x^p,x^{p^2},\ldots,x^{p^{n-1}}]$ where $n$ is the degree of $T$. \fun{GEN}{gener_FpXQ}{GEN T, GEN p, GEN *po} returns a primitive root modulo $(T,p)$. $T$ is an \kbd{FpX} assumed to be irreducible modulo the prime $p$. If \kbd{po} is not \kbd{NULL} it is set to $[o,\var{fa}]$, where $o$ is the order of the multiplicative group of the finite field, and \var{fa} is its factorization. \fun{GEN}{gener_FpXQ_local}{GEN T, GEN p, GEN L}, \kbd{L} being a vector of primes dividing $p^{\deg T} - 1$, returns an element of $G:=\F_p[x]/(T)$ which is a generator of the $\ell$-Sylow of $G$ for every $\ell$ in \kbd{L}. It is not necessary, and in fact slightly inefficient, to include $\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}{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. \fun{GEN}{FpXQ_matrix_pow}{GEN x, long m, long n, GEN T, GEN p}, as \kbd{FpXQ\_powers}$(x, n-1, T, p)$, but returns the powers as a an $m\times n$ matrix. Usually, we have $m = n = \deg T$. \fun{GEN}{FpXQ_autpow}{GEN a, ulong n, GEN T, GEN p} computes $\sigma^n(X)$ assuming $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_p[X]/T(X)$. \fun{GEN}{FpXQ_autsum}{GEN a, ulong 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]$. \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 $\kbd{f}(\kbd{x})$. \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})$. \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 \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. \fun{GEN}{FpXX_red}{GEN z, GEN p}, \kbd{z} a \typ{POL} whose coefficients are either \kbd{ZX}s or \typ{INT}s. Returns the \typ{POL} equal to \kbd{z} with all components reduced modulo \kbd{p}. \fun{GEN}{FpXX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{FpXX_add}{GEN x, GEN y, GEN p} adds \kbd{x} and \kbd{y}. \fun{GEN}{FpXX_sub}{GEN x, GEN y, GEN p} returns $\kbd{x}-\kbd{y}$. \fun{GEN}{FpXX_neg}{GEN x, GEN p} returns $-\kbd{x}$. \fun{GEN}{FpXX_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{FpXX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \fun{GEN}{FpXX_FpX_mul}{GEN x, GEN y, GEN p} multiplies the coefficients of the \kbd{FpXX}~\kbd{x} by the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpXX_mulu}{GEN x, GEN y, GEN p} multiplies the \kbd{FpXX}~\kbd{x} by the scalar \kbd{y}. \fun{GEN}{FpXY_eval}{GEN Q, GEN y, GEN x, GEN p} $Q$ being an \kbd{FpXY}, i.e.~a \typ{POL} with \kbd{Fp} or \kbd{FpX} coefficients representing an element of $\F_p[X][Y]$. Returns the \kbd{Fp} $Q(x,y)$. \fun{GEN}{FpXY_evalx}{GEN Q, GEN x, GEN p} $Q$ being an \kbd{FpXY}, returns the \kbd{FpX} $Q(x,Y)$, where $Y$ is the main variable of $Q$. \fun{GEN}{FpXY_evaly}{GEN Q, GEN y, GEN p, long vx} $Q$ an \kbd{FpXY}, returns the \kbd{FpX} $Q(X,y)$, where $X$ is the second variable of $Q$, and \kbd{vx} is the variable number of $X$. \fun{GEN}{FpXY_Fq_evaly}{GEN Q, GEN y, GEN T, GEN p, long vx} $Q$ an \kbd{FpXY} 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 first variable of $Q$. \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}$. \subsec{\kbd{FpXQX}, \kbd{FqX}} Contrary to what the name implies, an \kbd{FpXQX} is a \typ{POL} whose coefficients are \kbd{Fq}s. So the only difference between \kbd{FqX} and \kbd{FpXQX} routines is that $\kbd{T} = \kbd{NULL}$ is not allowed in the latter. (It was thought more useful to allow \typ{INT} components than to enforce strict consistency, which would not imply any efficiency gain.) \subsubsec{Basic operations} \fun{GEN}{FqX_add}{GEN x,GEN y,GEN T,GEN p} \fun{GEN}{FqX_Fq_add}{GEN x, GEN y, GEN T, GEN p} adds the \kbd{Fq}~\kbd{y} to the \kbd{FqX}~\kbd{x}. \fun{GEN}{FqX_neg}{GEN x,GEN T,GEN p} \fun{GEN}{FqX_sub}{GEN x,GEN y,GEN T,GEN p} \fun{GEN}{FqX_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FqX_Fq_mul}{GEN x, GEN y, GEN T, GEN p} multiplies the \kbd{FqX}~\kbd{x} by the \kbd{Fq}~\kbd{y}. \fun{GEN}{FqX_mulu}{GEN x, ulong y, GEN T, GEN p} multiplies the \kbd{FqX}~\kbd{x} by the scalar~\kbd{y}. \fun{GEN}{FqX_Fp_mul}{GEN x, GEN y, GEN T, GEN p} multiplies the \kbd{FqX}~\kbd{x} by the \typ{INT}~\kbd{y}. \fun{GEN}{FqX_Fq_mul_to_monic}{GEN x, GEN y, GEN T, GEN p} returns $x\*y$ assuming the result is monic of the same degree as $x$ (in particular $y\neq 0$). \fun{GEN}{FqX_normalize}{GEN z, GEN T, GEN p} divides the \kbd{FqX}~\kbd{z} 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_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_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}. (This function is suitable for \kbd{gerepilupto} but not memory-clean.) \fun{GEN}{FqX_translate}{GEN P, GEN c, GEN T, GEN p} let $c$ be an \kbd{Fq} defined modulo $(p, T)$, and let $P$ be an \kbd{FqX}; returns the translated \kbd{FqX} of $P(X+c)$. \fun{GEN}{FqX_gcd}{GEN P, GEN Q, GEN T, GEN p} returns a (not necessarily monic) greatest common divisor of $x$ and $y$. \fun{GEN}{FqX_extgcd}{GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv} returns $d = \text{GCD}(\kbd{x},\kbd{y})$ (not necessarily monic), and sets \kbd{*u}, \kbd{*v} to the Bezout coefficients such that $\kbd{*ux} + \kbd{*vy} = d$. \fun{GEN}{FqX_eval}{GEN x, GEN y, GEN T, GEN p} evaluates the \kbd{FqX}~\kbd{x} at the \kbd{Fq}~\kbd{y}. The result is an~\kbd{Fq}. \fun{GEN}{FqXY_eval}{GEN Q, GEN y, GEN x, GEN T, GEN p} $Q$ an \kbd{FqXY}, i.e.~a \typ{POL} with \kbd{Fq} or \kbd{FqX} coefficients representing an 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_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. \fun{GEN}{FpXQX_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{Kronecker_to_FpXQX}{GEN z, GEN T, GEN p}. Let $n = \deg T$ and let $P(X,Y)\in \Z[X,Y]$ lift a polynomial in $K[Y]$, where $K := \F_p[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 $Q\in \Z[X,t]$ such that $Q$ is congruent to $P(X,t)$ mod $(p, T(X))$, $\deg_X Q < n$, and all coefficients are in $[0,p[$. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \fun{GEN}{FpXQX_FpXQ_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{FpXQX_divrem}{GEN x, GEN y, GEN T, GEN p, GEN *pr} \fun{GEN}{FpXQX_div}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_rem}{GEN x, GEN y, 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})$. \fun{GEN}{FpXQX_rem_Barrett}{GEN x, GEN iy, GEN y, GEN T, GEN p} returns $x$ mod $y$, assuming \kbd{iy} is the Barrett inverse of $y$. \fun{GEN}{FpXQX_divrem_Barrett}{GEN x, GEN iy, GEN y, GEN T, GEN p, GEN *pr} performs the Euclidean division of $x$ by $y$, assuming \kbd{iy} is the Barrett inverse of $y$. Returns the quotient and set \kbd{*pr} to the remainder. \fun{GEN}{FpXQXV_prod}{GEN V, GEN T, GEN p}, \kbd{V} being a vector of \kbd{FpXQX}, returns their product. \fun{GEN}{FpXQX_gcd}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_extgcd}{GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv} \fun{GEN}{FpXQX_FpXQXQ_eval}{GEN f,GEN x,GEN S, GEN T,GEN p} returns $\kbd{f}(\kbd{x})$. \fun{GEN}{FpXQX_FpXQXQV_eval}{GEN f,GEN V,GEN S,GEN T,GEN p} returns $\kbd{f}(\kbd{x})$, assuming that \kbd{V} was computed by $\kbd{FpXQXQ\_powers}(\kbd{x}, n, \kbd{S}, \kbd{T}, \kbd{p})$. \fun{GEN}{FpXQXQ_div}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}*\kbd{y}^{-1}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_inv}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^{-1}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_invsafe}{GEN x, GEN S, GEN T,GEN p}, as \kbd{FpXQXQ\_inv}, returning \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FpXQXQ_mul}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}\*\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_sqr}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^2$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^\kbd{n}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_powers}{GEN x, long n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FpXQXQ}s. \fun{GEN}{FpXQXQ_matrix_pow}{GEN x, long m, long n, GEN S, GEN T, GEN p} returns the same powers of \kbd{x} as \kbd{FpXQXQ\_powers}$(x, n-1,S, T, p)$, but as an $m\times n$ matrix. \fun{GEN}{FpXQXQV_autpow}{GEN a, long n, GEN S, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, $\sigma(Y)=a[2]\pmod{S(X,Y),T(X)}$, returns $[\sigma^n(X),\sigma^n(Y)]$. \fun{GEN}{FpXQXQV_autsum}{GEN a, long n, GEN S, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, $\sigma(Y)=a[2]\pmod{S(X,Y),T(X)}$, returns the vector $[\sigma^n(X),\sigma^n(Y),b\sigma(b)\ldots\sigma^{n-1}(b)]$ where $b=a[3]$. % FqXQ \fun{GEN}{FqXQ_add}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x} + \kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_sub}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x} - \kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_mul}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}\*\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_div}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}/\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_inv}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^{-1}$ modulo \kbd{S}. \fun{GEN}{FqXQ_invsafe}{GEN x, GEN S, GEN T, GEN p} , as \kbd{FqXQ\_inv}, returning \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FqXQ_sqr}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^2$ modulo \kbd{S}. \fun{GEN}{FqXQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^\kbd{n}$ modulo \kbd{S}. \fun{GEN}{FqXQ_powers}{GEN x, long n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FqXQ}s. \fun{GEN}{FqXQ_matrix_pow}{GEN x, long m, long n, GEN S, GEN T, GEN p} returns the same powers of \kbd{x} as \kbd{FqXQ\_powers}$(x, n-1,S, T, p)$, but as an $m\times n$ matrix. \fun{GEN}{FqV_roots_to_pol}{GEN V, GEN T, GEN p, long v}, \kbd{V} being a vector of \kbd{Fq}s, returns the monic \kbd{FqX} $\prod_i (\kbd{pol\_x[v]} - \kbd{V[i]})$. \subsubsec{Miscellaneous operations} \fun{GEN}{init_Fq}{GEN p, long n, long v} returns an irreducible polynomial of degree $\kbd{n} > 0$ over $\F_p$, in variable \kbd{v}. \fun{int}{FqX_is_squarefree}{GEN P, GEN T, GEN p} \fun{GEN}{FqX_roots}{GEN x, GEN T, GEN p} return the roots of \kbd{x} in $\F_p[X]/(T)$. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FqX_factor}{GEN x, GEN T, GEN p} same output convention as \kbd{FpX\_factor}. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FpX_factorff}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Factor the \kbd{FpX} \kbd{P} over the finite field $\F_p[Y]/(T(Y))$. See \kbd{FpX\_factorff\_irred} if \kbd{P} is known to be irreducible of $\F_p$. \fun{GEN}{FpX_rootsff}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Returns the roots of the \kbd{FpX} \kbd{P} belonging to the finite field $\F_p[Y]/(T(Y))$. \fun{GEN}{FpX_factorff_irred}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Factors the \emph{irreducible} \kbd{FpX} \kbd{P} over the finite field $\F_p[Y]/(T(Y))$ and returns the vector of irreducible \kbd{FqX}s factors (the exponents, being all equal to $1$, are not included). \fun{GEN}{FpX_ffisom}{GEN P, GEN Q, GEN p}. Assumes \kbd{p} prime, \kbd{P}, \kbd{Q} are \kbd{ZX}s, both irreducible mod \kbd{p}, and $\deg(P) \mid \deg Q$. Outputs a monomorphism between $\F_p[X]/(P)$ and $\F_p[X]/(Q)$, as a polynomial $R$ such that $\kbd{Q} \mid \kbd{P}(R)$ in $\F_p[X]$. If \kbd{P} and \kbd{Q} have the same degree, it is of course an isomorphism. \fun{void}{FpX_ffintersect}{GEN P, GEN Q, long n, GEN p, GEN *SP,GEN *SQ, GEN MA,GEN MB}\hfil\break Assumes \kbd{p} is prime, \kbd{P}, \kbd{Q} are \kbd{ZX}s, both irreducible mod \kbd{p}, and \kbd{n} divides both the degree of \kbd{P} and \kbd{Q}. Compute \kbd{SP} and \kbd{SQ} such that the subfield of $\F_p[X]/(P)$ generated by \kbd{SP} and the subfield of $\F_p[X]/(Q)$ generated by \kbd{SQ} are isomorphic of degree \kbd{n}. The polynomials \kbd{P} and \kbd{Q} do not need to be of the same variable. If \kbd{MA} (resp. \kbd{MB}) is not \kbd{NULL}, it must be the matrix of the Frobenius map in $\F_p[X]/(P)$ (resp.~$\F_p[X]/(Q)$). \fun{GEN}{FpXQ_ffisom_inv}{GEN S, GEN T, GEN p}. Assumes \kbd{p} is prime, \kbd{T} a \kbd{ZX}, which is irreducible modulo \kbd{p}, \kbd{S} a \kbd{ZX} representing an automorphism of $\F_q := \F_p[X]/(\kbd{T})$. ($\kbd{S}(X)$ is the image of $X$ by the automorphism.) Returns the inverse automorphism of \kbd{S}, in the same format, i.e.~an \kbd{FpX}~$H$ such that $H(\kbd{S}) \equiv X$ modulo $(\kbd{T}, \kbd{p})$. \fun{long}{FpXQX_nbfact}{GEN S, GEN T, GEN p} returns the number of irreducible factors of the polynomial $S$ over the finite field $\F_q$ defined by $T$ and $p$. \fun{long}{FqX_nbfact}{GEN S, GEN T, GEN p} as above but accept \kbd{T=NULL}. \fun{long}{FpXQX_nbroots}{GEN S, GEN T, GEN p} returns the number of roots of the polynomial $S$ over the finite field $\F_q$ defined by $T$ and $p$. \fun{long}{FqX_nbroots}{GEN S, GEN T, GEN p} as above but accept \kbd{T=NULL}. \fun{GEN}{FpXQX_Frobenius}{GEN S, GEN T, GEN p} returns $X^{q}\pmod{S(X)}$ over the finite field $\F_q$ defined by $T$ and $p$, thus $q=p^n$ where $n$ is the degree of $T$. \fun{GEN}{FpXQXQ_halfFrobenius}{GEN A, GEN S, GEN T, GEN p} returns $A(X)^{(q-1)/2}\pmod{S(X)}$ over the finite field $\F_q$ defined by $T$ and $p$, thus $q=p^n$ where $n$ is the degree of $T$. \subsec{\kbd{Flx}} Let \kbd{p} an understood \kbd{ulong}, assumed to be prime, to be given the the function arguments; an \kbd{Fl} is an \kbd{ulong} belonging to $[0,\kbd{p}-1]$, an \kbd{Flx}~\kbd{z} is a \typ{VECSMALL} representing a polynomial with small integer coefficients. Specifically \kbd{z[0]} is the usual codeword, \kbd{z[1] = evalvarn($v$)} for some variable $v$, then the coefficients by increasing degree. An \kbd{FlxX} is a \typ{POL} whose coefficients are \kbd{Flx}s. \noindent In the following, an argument called \kbd{sv} is of the form \kbd{evalvarn}$(v)$ for some variable number~$v$. \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{T} can be replaced by an extended modulus, which is an \kbd{FlxT}, in all \kbd{Flxq}-classes functions, and in \kbd{Flx\_divrem}. \fun{GEN}{Flx_get_red}{GEN T, ulong p} returns the extended modulus \kbd{eT}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_Flx_mod}{GEN eT} returns the underlying modulus \kbd{T}. \fun{GEN}{get_Flx_var}{GEN eT} returns the variable number of the modulus. \fun{GEN}{get_Flx_degree}{GEN eT} returns the degree of the modulus. Furthermore, \kbd{ZXT\_to\_FlxT} allows to convert an extended modulus for a \kbd{FpX} to an extended modulus for the corresponding \kbd{Flx}. \subsubsec{Basic operations} \fun{ulong}{Flx_lead}{GEN x} returns the leading coefficient of $x$ as a \kbd{ulong} (return $0$ for the zero polynomial). \fun{GEN}{Flx_red}{GEN z, ulong p} converts from \kbd{zx} with non-negative coefficients to \kbd{Flx} (by reducing them mod \kbd{p}). \fun{int}{Flx_equal1}{GEN x} returns 1 (true) if the \kbd{Flx} $x$ is equal to~1, 0~(false) otherwise. \fun{int}{Flx_equal}{GEN x, GEN y} returns 1 (true) if the \kbd{Flx} $x$ and $y$ are equal, and 0~(false) otherwise. \fun{GEN}{Flx_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{Flx_add}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_Fl_add}{GEN y, ulong x, ulong p} \fun{GEN}{Flx_neg}{GEN x, ulong p} \fun{GEN}{Flx_neg_inplace}{GEN x, ulong p}, same as \kbd{Flx\_neg}, in place (\kbd{x} is destroyed). \fun{GEN}{Flx_sub}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_mul}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_Fl_mul}{GEN y, ulong x, ulong p} \fun{GEN}{Flx_double}{GEN y, ulong p} returns $2\*y$. \fun{GEN}{Flx_triple}{GEN y, ulong p} returns $3\*y$. \fun{GEN}{Flx_mulu}{GEN y, ulong x, ulong p} as \kbd{Flx\_Fl\_mul} but do not assume that $x \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. \fun{ulong}{Flx_oneroot}{GEN f, ulong p} returns one root $0 \leq r < p$ of the \kbd{Flx}~\kbd{f} in \kbd{\Z/p\Z}. Return $p$ if no root exists. Assumes that \kbd{p} is prime. \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$ ! \fun{GEN}{Flx_factor}{GEN f, ulong p} \fun{GEN}{Flx_mod_Xn1}{GEN T, ulong n, ulong p} return $T$ modulo $(X^n + 1, p)$. Shallow function. \fun{GEN}{Flx_mod_Xnm1}{GEN T, ulong n, ulong p} return $T$ modulo $(X^n - 1, p)$. Shallow function. \fun{GEN}{Flx_degfact}{GEN f, ulong p} as \tet{FpX_degfact}. \fun{GEN}{Flx_factorff_irred}{GEN P, GEN Q, ulong p} as \tet{FpX_factorff_irred}. \fun{GEN}{Flx_ffisom}{GEN P,GEN Q,ulong l} as \tet{FpX_ffisom}. \subsubsec{Miscellaneous operations} \fun{GEN}{pol0_Flx}{long sv} returns a zero \kbd{Flx} in variable $v$. \fun{GEN}{zero_Flx}{long sv} alias for \kbd{pol0\_Flx} \fun{GEN}{pol1_Flx}{long sv} returns the unit \kbd{Flx} in variable $v$. \fun{GEN}{polx_Flx}{long sv} returns the variable $v$ as degree~1~\kbd{Flx}. \fun{GEN}{Flx_normalize}{GEN z, ulong p}, as \kbd{FpX\_normalize}. \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}. \fun{GEN}{Flx_recip}{GEN x}, returns the reciprocal polynomial \fun{ulong}{Flx_resultant}{GEN a, GEN b, ulong p}, returns the resultant of \kbd{a} and \kbd{b} \fun{ulong}{Flx_extresultant}{GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV} given two \kbd{Flx} \kbd{a} and \kbd{b}, returns their resultant and sets Bezout coefficients (if the resultant is 0, the latter are not set). \fun{GEN}{Flx_invBarrett}{GEN T, ulong p}, returns the Barrett inverse $M$ of $T$ defined by $M(x)\*x^n\*T(1/x)\equiv 1\pmod{x^{n-1}}$ where $n$ is the degree of $T$. \fun{GEN}{Flx_renormalize}{GEN x, long l}, as \kbd{FpX\_renormalize}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{Flx_shift}{GEN T, long n} returns $\kbd{T} * x^n$ if $n\geq 0$, and $\kbd{T} \bs x^{-n}$ otherwise. \fun{long}{Flx_val}{GEN x} returns the valuation of \kbd{x}, i.e. the multiplicity of the $0$ root. \fun{long}{Flx_valrem}{GEN x, GEN *Z} as \kbd{RgX\_valrem}, returns the valuation of \kbd{x}. In particular, if the valuation is $0$, set \kbd{*Z} to $x$, not a copy. \fun{GEN}{Flx_div_by_X_x}{GEN A, ulong a, ulong p, ulong *rem}, returns the Euclidean quotient of the \kbd{Flx}~\kbd{A} by $X - \kbd{a}$, and sets \kbd{rem} to the remainder $ \kbd{A}(\kbd{a})$. \fun{ulong}{Flx_eval}{GEN x, ulong y, ulong p}, as \kbd{FpX\_eval}. \fun{GEN}{Flx_deflate}{GEN P, long d} assuming $P$ is a polynomial of the form $Q(X^d)$, return $Q$. \fun{GEN}{Flx_splitting}{GEN p, long k}, as \tet{RgX_splitting}. \fun{GEN}{Flx_inflate}{GEN P, long d} returns $P(X^d)$. \fun{int}{Flx_is_squarefree}{GEN z, ulong p} \fun{int}{Flx_is_irred}{GEN f, ulong p}, as \kbd{FpX\_is\_irred}. \fun{int}{Flx_is_smooth}{GEN f, long r, ulong p} return $1$ if all irreducible factors of $f$ are of degree at most $r$, $0$ otherwise. \fun{long}{Flx_nbroots}{GEN f, ulong p}, as \kbd{FpX\_nbroots}. \fun{long}{Flx_nbfact}{GEN z, ulong p}, as \kbd{FpX\_nbfact}. \fun{GEN}{Flx_degfact}{GEN f, ulong p}, as \kbd{FpX\_degfact}. \fun{GEN}{Flx_nbfact_by_degree}{GEN z, long *nb, ulong p} Assume that the \kbd{Flx} $z$ is squarefree mod the prime $p$. Returns a \typ{VECSMALL} $D$ with $\deg z$ entries, such that $D[i]$ is the number of irreducible factors of degree $i$. Set \kbd{nb} to the total number of irreducible factors (the sum of the $D[i]$). \fun{void}{Flx_ffintersect}{GEN P,GEN Q, long n, ulong p, GEN*SP, GEN*SQ, GEN MA,GEN MB},\hfil\break 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_roots_to_pol}{GEN a, ulong p, long sv} as \kbd{FpV\_roots\_to\_pol} returning an \kbd{Flx} in variable $v$. \subsec{\kbd{FlxV}} See \kbd{FpXV} operations. \fun{GEN}{FlxV_Flc_mul}{GEN V, GEN W, ulong p}, as \kbd{FpXV\_FpC\_mul}. \fun{GEN}{FlxV_red}{GEN V, ulong p} reduces each components with \kbd{Flx\_red}. \subsec{\kbd{FlxT}} See \kbd{FpXT} operations. \fun{GEN}{FlxT_red}{GEN V, ulong p} reduces each leaf with \kbd{Flx\_red}. \subsec{\kbd{Flxq}} See \kbd{FpXQ} operations. \fun{GEN}{Flxq_add}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{Flxq_sub}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{Flxq_mul}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{Flxq_sqr}{GEN y, GEN T, ulong p} \fun{GEN}{Flxq_inv}{GEN x, GEN T, ulong p} \fun{GEN}{Flxq_invsafe}{GEN x, GEN T, ulong p} \fun{GEN}{Flxq_div}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{Flxq_pow}{GEN x, GEN n, GEN T, ulong p} \fun{GEN}{Flxq_powu}{GEN x, ulong n, GEN T, ulong p} \fun{GEN}{Flxq_powers}{GEN x, long n, GEN T, ulong p} \fun{GEN}{Flxq_matrix_pow}{GEN x, long m, long n, GEN T, ulong p}, see \kbd{FpXQ\_matrix\_pow}. \fun{GEN}{Flxq_autpow}{GEN a, long n, GEN T, ulong p} see \kbd{FpXQ\_autpow}. \fun{GEN}{Flxq_autsum}{GEN a, long n, GEN T, GEN p} see \kbd{Flxq\_autsum}. \fun{GEN}{Flxq_ffisom_inv}{GEN S, GEN T, ulong p}, as \kbd{FpXQ\_ffisom\_inv}. \fun{GEN}{Flx_Flxq_eval}{GEN f, GEN x, GEN T, ulong p} returns $\kbd{f}(\kbd{x})$. \fun{GEN}{Flx_FlxqV_eval}{GEN f, GEN x, GEN T, ulong p}, see \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{FlxqV_roots_to_pol}{GEN V, GEN T, ulong p, long v} as \kbd{FqV\_roots\_to\_pol} returning an \kbd{FlxqX} in variable $v$. \fun{GEN}{Flxq_order}{GEN a, GEN ord, GEN T, ulong p} returns the order of the \typ{Flxq} \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. \fun{int}{Flxq_issquare}{GEN x, GEN T, ulong p} returns $1$ if $x$ is a square and $0$ otherwise. Assume that \kbd{T} is irreducible mod \kbd{p}. \fun{int}{Flxq_is2npower}{GEN x, long n, GEN T, ulong p} returns $1$ if $x$ is a $2^n$-th power and $0$ otherwise. Assume that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{Flxq_log}{GEN a, GEN g, GEN ord, GEN T, ulong p} Let $g$ of exact 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_sqrt}{GEN x, GEN T, ulong p} returns a square root of \kbd{x}. Return \kbd{NULL} if \kbd{x} is not a square. \fun{GEN}{Flxq_lroot}{GEN a, GEN T, ulong p} returns $x$ such that $x^p = a$. \fun{GEN}{Flxq_lroot_fast}{GEN a, GEN V, GEN T, ulong p} assuming that \kbd{V=Flxq\_powers(s,p-1,T,p)} where $s(x)^p \equiv x\pmod{T(x),p}$, returns $b$ such that $b^p=a$. Only useful if $p$ is less than the degree of $T$. \fun{GEN}{Flxq_charpoly}{GEN x, GEN T, ulong p} returns the characteristic polynomial of \kbd{x} \fun{GEN}{Flxq_minpoly}{GEN x, GEN T, ulong p} returns the minimal polynomial of \kbd{x} \fun{ulong}{Flxq_norm}{GEN x, GEN T, ulong p} returns the norm of \kbd{x} \fun{ulong}{Flxq_trace}{GEN x, GEN T, ulong p} returns the trace of \kbd{x} \fun{GEN}{Flxq_conjvec}{GEN x, GEN T, ulong p} returns the conjugates $[x,x^p,x^{p^2},\ldots,x^{p^{n-1}}]$ where $n$ is the degree of $T$. \fun{GEN}{gener_Flxq}{GEN T, ulong p, GEN *po} returns a primitive root modulo $(T,p)$. $T$ is an \kbd{Flx} assumed to be irreducible modulo the prime $p$. If \kbd{po} is not \kbd{NULL} it is set to $[o,\var{fa}]$, where $o$ is the order of the multiplicative group of the finite field, and \var{fa} is its factorization. \subsec{\kbd{FlxX}} See \kbd{FpXX} operations. \fun{GEN}{pol1_FlxX}{long vX, long sx} returns the unit \kbd{FlxX} as a \typ{POL} in variable \kbd{vX} which only coefficient is \kbd{pol1\_Flx(sx)}. \fun{GEN}{polx_FlxX}{long vX, long sx} returns the variable $X$ as a degree~1~\typ{POL} with \kbd{Flx} coefficients in the variable $x$. \fun{GEN}{FlxX_add}{GEN P, GEN Q, ulong p} \fun{GEN}{FlxX_sub}{GEN P, GEN Q, ulong p} \fun{GEN}{FlxX_Fl_mul}{GEN x, ulong y, ulong p} \fun{GEN}{FlxX_double}{GEN x, ulong p} \fun{GEN}{FlxX_triple}{GEN x, ulong p} \fun{GEN}{FlxX_neg}{GEN x, ulong p} \fun{GEN}{FlxX_Flx_add}{GEN y, GEN x, ulong p} \fun{GEN}{FlxX_Flx_mul}{GEN x, GEN y, ulong p} \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_Flxq_evalx}{GEN x, GEN y, ulong p} \fun{GEN}{FlxX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{FlxX_resultant}{GEN u, GEN v, ulong p, long sv} Returns $\text{Res}_X(u, v)$, which is an \kbd{Flx}. The coefficients of \kbd{u} and \kbd{v} are assumed to be in the variable $v$. \fun{GEN}{Flx_FlxY_resultant}{GEN a, GEN b, ulong p} Returns $\text{Res}_x(a, b)$, which is an \kbd{Flx} in the main variable of \kbd{b}. \fun{GEN}{FlxX_shift}{GEN a, long n} \fun{GEN}{FlxX_swap}{GEN x, long n, long ws}, as \kbd{RgXY\_swap}. \fun{GEN}{FlxYqq_pow}{GEN x, GEN n, GEN S, GEN T, ulong p}, as \kbd{FpXYQQ\_pow}. \subsec{\kbd{FlxqX}} See \kbd{FpXQX} operations. \fun{GEN}{zxX_to_Kronecker}{GEN P, GEN Q} assuming $P(X,Y)$ is a polynomial of degree in $X$ strictly less than $n$, returns $P(X,X^{2*n-1})$, the Kronecker form of $P$. \fun{GEN}{Kronecker_to_FlxqX}{GEN z, GEN T, ulong p}. Let $n = \deg T$ and let $P(X,Y)\in \Z[X,Y]$ lift a polynomial in $K[Y]$, where $K := \F_p[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 $Q\in \Z[X,t]$ such that $Q$ is congruent to $P(X,t)$ mod $(p, T(X))$, $\deg_X Q < n$, and all coefficients are in $[0,p[$. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \fun{GEN}{FlxqX_red}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_normalize}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_mul}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_Flxq_mul}{GEN P, GEN U, GEN T, ulong p} \fun{GEN}{FlxqX_Flxq_mul_to_monic}{GEN P, GEN U, GEN T, ulong p} returns $P*U$ assuming the result is monic of the same degree as $P$ (in particular $U\neq 0$). \fun{GEN}{FlxqX_sqr}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqX_pow}{GEN x, long n, GEN T, ulong p} \fun{GEN}{FlxqX_divrem}{GEN x, GEN y, GEN T, ulong p, GEN *pr} \fun{GEN}{FlxqX_div}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_rem}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_invBarrett}{GEN T, GEN Q, ulong p} \fun{GEN}{FlxqX_rem_Barrett}{GEN x, GEN mg, GEN T, GEN Q, ulong p} \fun{GEN}{FlxqX_gcd}{GEN x, GEN y, ulong p} returns a (not necessarily monic) greatest common divisor of $x$ and $y$. \fun{GEN}{FlxqX_extgcd}{GEN x, GEN y, GEN T, ulong p, GEN *ptu, GEN *ptv} \fun{GEN}{FlxqXV_prod}{GEN V, GEN T, ulong p} \fun{GEN}{FlxqX_safegcd}{GEN P, GEN Q, GEN T, ulong p} Returns the \emph{monic} GCD of $P$ and $Q$ if Euclid's algorithm succeeds and \kbd{NULL} otherwise. In particular, if $p$ is not prime or $T$ is not irreducible over $\F_p[X]$, the routine may still be used (but will fail if non-invertible leading terms occur). \fun{GEN}{FlxqX_Frobenius}{GEN S, GEN T, GEN p}, as \kbd{FpXQX\_Frobenius} \fun{GEN}{FlxqXQ_halfFrobenius}{GEN A, GEN S, GEN T, GEN p}, as \kbd{FpXQXQ\_halfFrobenius} \fun{long}{FlxqX_nbroots}{GEN S, GEN T, GEN p}, as \kbd{FpX\_nbroots}. \fun{GEN}{FlxqX_FlxqXQ_eval}{GEN Q, GEN x, GEN S, GEN T, ulong p} as \kbd{FpX\_FpXQ\_eval}. \fun{GEN}{FlxqX_FlxqXQV_eval}{GEN P, GEN V, GEN S, GEN T, ulong p} as \kbd{FpX\_FpXQV\_eval}. \subsec{\kbd{FlxqXQ}} See \kbd{FpXQXQ} operations. \fun{GEN}{FlxqXQ_mul}{GEN x, GEN y, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_sqr}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_inv}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_invsafe}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_div}{GEN x, GEN y, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_pow}{GEN x, GEN n, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_powers}{GEN x, long n, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_matrix_pow}{GEN x, long n, long m, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQV_autpow}{GEN a, long n, GEN S, GEN T, ulong p} as \kbd{FpXQXQV\_autpow} \fun{GEN}{FlxqXQV_autsum}{GEN a, long n, GEN S, GEN T, ulong p} as \kbd{FpXQXQV\_autsum} \subsec{\kbd{F2x}} An \kbd{F2x}~\kbd{z} is a \typ{VECSMALL} representing a polynomial over $\F_2[X]$. Specifically \kbd{z[0]} is the usual codeword, \kbd{z[1] = evalvarn($v$)} for some variable $v$ and the coefficients are given by the bits of remaining words by increasing degree. \subsubsec{Basic operations} \fun{ulong}{F2x_coeff}{GEN x, long i} returns the coefficient $i\ge 0$ of $x$. \fun{void}{F2x_clear}{GEN x, long i} sets the coefficient $i\ge 0$ of $x$ to $0$. \fun{void}{F2x_flip}{GEN x, long i} adds $1$ to the coefficient $i\ge 0$ of $x$. \fun{void}{F2x_set}{GEN x, long i} sets the coefficient $i\ge 0$ of $x$ to $1$. \fun{GEN}{Flx_to_F2x}{GEN x} \fun{GEN}{Z_to_F2x}{GEN x, long v} \fun{GEN}{ZX_to_F2x}{GEN x} \fun{GEN}{F2v_to_F2x}{GEN x, long sv} \fun{GEN}{ZXX_to_F2xX}{GEN x, long v} \fun{GEN}{F2x_to_Flx}{GEN x} \fun{GEN}{F2x_to_ZX}{GEN x} \fun{GEN}{pol0_F2x}{long sv} returns a zero \kbd{F2x} in variable $v$. \fun{GEN}{zero_F2x}{long sv} alias for \kbd{pol0\_F2x}. \fun{GEN}{pol1_F2x}{long sv} returns the \kbd{F2x} in variable $v$ constant to $1$. \fun{GEN}{polx_F2x}{long sv} returns the variable $v$ as degree~1~\kbd{F2x}. \fun{GEN}{random_F2x}{long d, long sv} returns a random \kbd{F2x} in variable \kbd{v}, of degree less than~\kbd{d}. \fun{long}{F2x_degree}{GEN x} returns the degree of the \kbd{F2x x}. The degree of $0$ is defined as $-1$. \fun{int}{F2x_equal1}{GEN x} \fun{int}{F2x_equal}{GEN x, GEN y} \fun{GEN}{F2x_1_add}{GEN y} returns \kbd{y+1} where \kbd{y} is a \kbd{Flx}. \fun{GEN}{F2x_add}{GEN x, GEN y} \fun{GEN}{F2x_mul}{GEN x, GEN y} \fun{GEN}{F2x_sqr}{GEN x} \fun{GEN}{F2x_divrem}{GEN x, GEN y, GEN *pr} \fun{GEN}{F2x_rem}{GEN x, GEN y} \fun{GEN}{F2x_div}{GEN x, GEN y} \fun{GEN}{F2x_renormalize}{GEN x, long lx} \fun{GEN}{F2x_deriv}{GEN x} \fun{GEN}{F2x_deflate}{GEN x, long d} \fun{void}{F2x_shift}{GEN x, long d} as \tet{RgX_shift} \fun{void}{F2x_even_odd}{GEN p, GEN *pe, GEN *po} as \tet{RgX_even_odd} \fun{long}{F2x_valrem}{GEN x, GEN *Z} \fun{GEN}{F2x_extgcd}{GEN a, GEN b, GEN *ptu, GEN *ptv} \fun{GEN}{F2x_gcd}{GEN a, GEN b} \fun{GEN}{F2x_halfgcd}{GEN a, GEN b} \fun{int}{F2x_issquare}{GEN x} returns $1$ if $x$ is a square of a \kbd{F2x} and $0$ otherwise. \fun{int}{F2x_is_irred}{GEN f}, as \tet{FpX_is_irred}. \fun{GEN}{F2x_sqrt}{GEN x} returns the squareroot of $x$, assuming $x$ is a square of a \kbd{F2x}. \fun{GEN}{F2x_factor}{GEN f} \subsec{\kbd{F2xq}} See \kbd{FpXQ} operations. \fun{GEN}{F2xq_mul}{GEN x, GEN y, GEN pol} \fun{GEN}{F2xq_sqr}{GEN x,GEN pol} \fun{GEN}{F2xq_div}{GEN x,GEN y,GEN T} \fun{GEN}{F2xq_inv}{GEN x, GEN T} \fun{GEN}{F2xq_invsafe}{GEN x, GEN T} \fun{GEN}{F2xq_pow}{GEN x, GEN n, GEN pol} \fun{GEN}{F2xq_powu}{GEN x, ulong n, GEN pol} \fun{ulong}{F2xq_trace}{GEN x, GEN T} \fun{GEN}{F2xq_conjvec}{GEN x, GEN T} returns the vector of conjugates $[x,x^2,x^{2^2},\ldots,x^{2^{n-1}}]$ where $n$ is the degree of $T$. \fun{GEN}{F2xq_log}{GEN a, GEN g, GEN ord, GEN T} \fun{GEN}{F2xq_order}{GEN a, GEN ord, GEN T} \fun{GEN}{F2xq_Artin_Schreier}{GEN a, GEN T} returns a solution of $x^2+x=a$, assuming it exists. \fun{GEN}{F2xq_sqrt}{GEN a, GEN T} \fun{GEN}{F2xq_sqrt_fast}{GEN a, GEN s, GEN T} assuming that $s^2 \equiv x\pmod{T(x)}$, computes $b \equiv a(s)\pmod{T}$ so that $b^2=a$. \fun{GEN}{F2xq_sqrtn}{GEN a, GEN n, GEN T, GEN *zeta} \fun{GEN}{gener_F2xq}{GEN T, GEN *po} \fun{GEN}{F2xq_powers}{GEN x, long n, GEN T} \fun{GEN}{F2xq_matrix_pow}{GEN x, long m, long n, GEN T} \fun{GEN}{F2x_F2xq_eval}{GEN f, GEN x, GEN T} \fun{GEN}{F2x_F2xqV_eval}{GEN f, GEN x, GEN T}, see \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{F2xq_autpow}{GEN a, long n, GEN T} computes $\sigma^n(X)$ assuming $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_2[X]/T(X)$. \subsec{\kbd{F2xqV}, \kbd{F2xqM}}. See \kbd{FqV}, \kbd{FqM} operations. \fun{GEN}{F2xqM_F2xqC_mul}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_ker}{GEN x, GEN T} \fun{GEN}{F2xqM_det}{GEN a, GEN T} \fun{GEN}{F2xqM_image}{GEN x, GEN T} \fun{GEN}{F2xqM_inv}{GEN a, GEN T} \fun{GEN}{F2xqM_mul}{GEN a, GEN b, GEN T} \fun{long}{F2xqM_rank}{GEN x, GEN T} \fun{GEN}{matid_F2xqM}{long n, GEN T} \subsec{Functions returning objects with \typ{INTMOD} coefficients} Those functions are mostly needed for interface reasons: \typ{INTMOD}s should not be used in library mode since the modular kernel is more flexible and more efficient, but GP users do not have access to the modular kernel. We document them for completeness: \fun{GEN}{Fp_to_mod}{GEN z, GEN p}, \kbd{z} a \typ{INT}. Returns \kbd{z * Mod(1,p)}, normalized. Hence the returned value is a \typ{INTMOD}. \fun{GEN}{FpX_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZX}. Returns \kbd{z * Mod(1,p)}, normalized. Hence the returned value has \typ{INTMOD} coefficients. \fun{GEN}{FpC_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZC}. Returns \kbd{Col(z) * Mod(1,p)}, a \typ{COL} with \typ{INTMOD} coefficients. \fun{GEN}{FpV_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZV}. Returns \kbd{Vec(z) * Mod(1,p)}, a \typ{VEC} with \typ{INTMOD} coefficients. \fun{GEN}{FpVV_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZVV}. Returns \kbd{Vec(z) * Mod(1,p)}, a \typ{VEC} of \typ{VEC} with \typ{INTMOD} coefficients. \fun{GEN}{FpM_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZM}. Returns \kbd{z * Mod(1,p)}, with \typ{INTMOD} coefficients. \fun{GEN}{F2c_to_mod}{GEN x} \fun{GEN}{F2m_to_mod}{GEN x} \fun{GEN}{Flc_to_mod}{GEN z} \fun{GEN}{Flm_to_mod}{GEN z} \fun{GEN}{FpXQC_to_mod}{GEN V, GEN T, GEN p} $V$ being a vector of \kbd{FpXQ}, converts each entry to a \typ{POLMOD} with \typ{INTMOD} coefficients, and return a \typ{COL}. \fun{GEN}{QXQV_to_mod}{GEN V, GEN T} $V$ a vector of \kbd{QXQ}, which are lifted representatives of elements of $\Q[X]/(T)$ (number field elements in most applications) and $T$ is in $\Z[X]$. Return a vector where all non-rational entries are converted to \typ{POLMOD} modulo $T$; no reduction mod $T$ is attempted: the representatives should be already reduced. Used to normalize the output of \kbd{nfroots}. \fun{GEN}{QXQXV_to_mod}{GEN V, GEN T} $V$ a vector of polynomials whose coefficients are \kbd{QXQ}. Analogous to \kbd{QXQV\_to\_mod}. Used to normalize the output of \kbd{nffactor}. \fun{GEN}{QXQX_to_mod_shallow}{GEN z, GEN T} $v$ a polynomial with \kbd{QXQ} coefficients; replace them by \kbd{mkpolmod(.,T)}. Shallow function. The following functions are obsolete and should not be used: they receive a polynomial with arbitrary coefficients, apply \kbd{RgX\_to\_FpX}, a function from the modular kernel, then \kbd{*\_to\_mod}: \fun{GEN}{rootmod}{GEN f, GEN p}, applies \kbd{FpX\_roots}. \fun{GEN}{rootmod2}{GEN f, GEN p}, applies \kbd{ZX\_to\_flx} then \kbd{Flx\_roots\_naive}. \fun{GEN}{factmod}{GEN f, GEN p} applies \kbd{FpX\_factor}. \fun{GEN}{simplefactmod}{GEN f, GEN p} applies \kbd{FpX\_degfact}. \subsec{Chinese remainder theorem over $\Z$} \fun{GEN}{Z_chinese}{GEN a, GEN b, GEN A, GEN B} returns the integer in $[0, \lcm(A,B)[$ congruent to $a$ mod $A$ and $b$ mod $B$, assuming it exists; in other words, that $a$ and $b$ are congruent mod $\gcd(A,B)$. \fun{GEN}{Z_chinese_all}{GEN a, GEN b, GEN A, GEN B, GEN *pC} as \kbd{Z\_chinese}, setting \kbd{*pC} to the lcm of $A$ and $B$. \fun{GEN}{Z_chinese_coprime}{GEN a, GEN b, GEN A, GEN B, GEN C}, as \kbd{Z\_chinese}, assuming that $\gcd(A,B) = 1$ and that $C = \lcm(A,B) = AB$. \fun{void}{Z_chinese_pre}{GEN A, GEN B, GEN *pC, GEN *pU, GEN *pd} initializes chinese remainder computations modulo $A$ and $B$. Sets \kbd{*pC} to $\lcm(A,B)$, \kbd{*pd} to $\gcd(A,B)$, \kbd{*pU} to an integer congruent to $0$ mod $(A/d)$ and $1$ mod $(B/d)$. It is allowed to set \kbd{pd = NULL}, in which case, $d$ is still computed, but not saved. \fun{GEN}{Z_chinese_post}{GEN a, GEN b, GEN C, GEN U, GEN d} returns the solution to the chinese remainder problem $x$ congruent to $a$ mod $A$ and $b$ mod $B$, where $C, U, d$ were set in \kbd{Z\_chinese\_pre}. If $d$ is \kbd{NULL}, assume the problem has a solution. Otherwise, return \kbd{NULL} if it has no solution. \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 satisfies $|H| < B$ for some known bound $B$; we are given pairs $(H_p, p)$ with $H$ congruent to $H_p$ mod $p$ and all $p$ pairwise coprime. Given \kbd{H} congruent to $H_p$ modulo a number of $p$, whose product is $q$, and a new pair $(\kbd{Hp}, \kbd{p})$, \kbd{p} coprime to $q$, the following incremental functions use the chinese remainder theorem (CRT) to find a new \kbd{H}, congruent to the preceding one modulo $q$, but also to \kbd{Hp} modulo \kbd{p}. It is defined uniquely modulo $qp$, and we choose the centered representative. When $P$ is larger than $2B$, we have $\kbd{H} = H$, but of course, the value of \kbd{H} may stabilize sooner. In many applications it is possible to directly check that such a partial result is correct. \fun{GEN}{Z_init_CRT}{ulong Hp, ulong p} given a \kbd{Fl} \kbd{Hp} in $[0, p-1]$, returns the centered representative \kbd{H} congruent to \kbd{Hp} modulo \kbd{p}. \fun{int}{Z_incremental_CRT}{GEN *H, ulong Hp, GEN *q, ulong p} given a \typ{INT} \kbd{*H}, centered modulo \kbd{*q}, a new pair $(\kbd{Hp}, \kbd{p})$ with \kbd{p} coprime to \kbd{q}, this function updates \kbd{*H} so that it also becomes congruent to $(\kbd{Hp}, \kbd{p})$, and \kbd{*q} to the product$\kbd{qp} = \kbd{p} \cdot \kbd{*q}$. It returns $1$ if the new value is equal to the old one, and $0$ otherwise. \fun{GEN}{chinese1_coprime_Z}{GEN v} an alternative divide-and-conquer implementation: $v$ is a vector of \typ{INTMOD} with pairwise coprime moduli. Return the \typ{INTMOD} solving the corresponding chinese remainder problem. This is a streamlined version of \fun{GEN}{chinese1}{GEN v}, which solves a general chinese remainder problem (not necessarily over $\Z$, moduli not assumed coprime). As above, for $H$ a \kbd{ZM}: we assume that $H$ and all \kbd{Hp} have dimension $> 0$. The original \kbd{*H} is destroyed. \fun{GEN}{ZM_init_CRT}{GEN Hp, ulong p} \fun{int}{ZM_incremental_CRT}{GEN *H, GEN Hp, GEN *q, ulong p} As above for $H$ a \kbd{ZX}: note that the degree may increase or decrease. The original \kbd{*H} is destroyed. \fun{GEN}{ZX_init_CRT}{GEN Hp, ulong p, long v} \fun{int}{ZX_incremental_CRT}{GEN *H, GEN Hp, GEN *q, ulong p} \subsec{Rational reconstruction} \fun{int}{Fp_ratlift}{GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b}. Assuming that $0 \leq x < m$, $\kbd{amax} \geq 0$, and $\kbd{bmax} > 0$ are \typ{INT}s, and that $2 \kbd{amax} \kbd{bmax} < m$, attempts to recognize $x$ as a rational $a/b$, i.e. to find \typ{INT}s $a$ and $b$ such that \item $a \equiv b x$ modulo $m$, \item $|a| \leq \kbd{amax}$, $0 < b \leq \kbd{bmax}$, \item $\gcd(m,b) = \gcd(a,b)$. \noindent If unsuccessful, the routine returns $0$ and leaves $a$, $b$ unchanged; otherwise it returns $1$ and sets $a$ and $b$. In almost all applications, we actually know that a solution exists, as well as a non-zero multiple $B$ of $b$, and $m = p^\ell$ is a prime power, for a prime $p$ chosen coprime to $B$ hence to $b$. Under the single assumption $\gcd(m,b) = 1$, if a solution $a,b$ exists satisfying the three conditions above, then it is unique. \fun{GEN}{FpM_ratlift}{GEN M, GEN m, GEN amax, GEN bmax, GEN denom} given an \kbd{FpM} modulo $m$ with reduced or \kbd{Fp\_center}-ed entries, reconstructs a matrix with rational coefficients by applying \kbd{Fp\_ratlift} to all entries. Assume that all preconditions for \kbd{Fp\_ratlift} are satisfied, as well $\gcd(m,b) = 1$ (so that the solution is unique if it exists). Return \kbd{NULL} if the reconstruction fails, and the rational matrix otherwise. If \kbd{denom} is not \kbd{NULL} check further that all denominators divide \kbd{denom}. The functions is not stack clean if one coefficients of $M$ is negative (centered residues), but still suitable for \kbd{gerepileupto}. \fun{GEN}{FpX_ratlift}{GEN P, GEN m, GEN amax, GEN bmax, GEN denom} as \kbd{FpM\_ratlift}, where $P$ is an \kbd{FpX}. \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} \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$. Returns a \typ{INT} $A$ such that $A^2 \equiv b \mod p^e$. Special case of \tet{Zp_sqrtnlift}. \fun{GEN}{Zp_sqrtnlift}{GEN b, GEN n, GEN a, GEN p, long e} let $a,b,n,p$ be \typ{INT}s, with $n,p > 1$, and $p$ coprime to $n$, such that $a^n \equiv b \mod p$. Returns a \typ{INT} $A$ such that $A^n \equiv b \mod p^e$. Special case of \tet{ZpX_liftroot}. \fun{GEN}{Zp_teichmuller}{GEN x, GEN p, long e, GEN pe} for $p$ an odd prime, $x$ a \typ{INT} coprime to $p$, and $pe = p^e$, returns the $(p-1)$-th root of $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}. \fun{GEN}{rootpadicfast}{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}. \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 $v_p(f'(a))=0$. Return a \typ{INT} which is the root of $f$ mod $p^e$ congruent to $a$ mod $p$. \fun{GEN}{ZX_Zp_root}{GEN f, GEN a, GEN p, long e} same as \tet{ZpX_liftroot} without the assumption $v_p(f'(a)) = 0$. Return a \typ{VEC} of \typ{INT}s, which are the $p$-adic roots of $f$ congruent to $a$ mod $p$ (given modulo $p^e$). \fun{GEN}{ZpX_liftroots}{GEN f, GEN S, GEN p, long e} $f$ a \kbd{ZX} with 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}) or a non-prime finite field ($T$ an \kbd{FpX}). $A$ is a polynomial in $\Z[X]$ ($T$ \kbd{NULL}) or $\Z[X,Y]$, whose leading coefficient is non-zero in $\F_q$. $B$ is a vector of monic \kbd{FpX} ($T$ \kbd{NULL}) or \kbd{FqX}, pairwise coprime in $\F_q[X]$, whose product is congruent to $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 */ @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; @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{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} and that $p$ is a prime number. Proceeds by dynamically increasing the $p$-adic accuracy; infinite loop if the discriminant of $f$ is $0$. \fun{long}{ZpX_resultant_val}{GEN f, GEN g, GEN p, long M} returns the valuation at $p$ of $\text{Res}(f,g)$. Assume $f,g$ are both \kbd{ZX}, and that $p$ is a prime number coprime to the leading coefficient of $f$. Proceeds by dynamically increasing the $p$-adic accuracy. To avoid an infinite loop when the resultant is $0$, we return $M$ if the Sylvester matrix mod $p^M$ still does not have maximal rank. \fun{GEN}{ZpX_gcd}{GEN f,GEN g, GEN p, GEN pm} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $\kbd{pm} = p^m$ a prime power. There is a unique integer $r\geq 0$ and a monic $h\in \Q_p[X]$ such that $$p^rh\Z_p[X] + p^m\Z_p[X] = f\Z_p[X] + g\Z_p[X] + p^m\Z_p[X].$$ Return the $0$ polynomial if $r\geq m$ and a monic $h\in\Z[1/p][X]$ otherwise (whose valuation at $p$ is $> -m$). \fun{GEN}{ZpX_reduced_resultant}{GEN f, GEN g, GEN p, GEN pm} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $\kbd{pm} = p^m$ a prime power. The $p$-adic \emph{reduced resultant}\varsidx{resultant (reduced)} of $f$ and $g$ is $0$ if $f$, $g$ not coprime in $\Z_p[X]$, and otherwise the generator of the form $p^d$ of $$ (f\Z_p[X] + g\Z_p[X])\cap \Z_p. $$ Return the reduced resultant modulo $p^m$. \fun{GEN}{ZpX_reduced_resultant_fast}{GEN f, GEN g, GEN p, long M} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $p$ a prime. Returns the the $p$-adic reduced resultant of $f$ and $g$ modulo $p^M$. This function computes resultants for a sequence of increasing $p$-adic accuracies (up to $M$ $p$-adic digits), returning as soon as it obtains a non-zero 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. \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_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} \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$. \subsec{Conversions involving single precision objects} \subsubsec{To single precision} \fun{ulong}{Rg_to_Fl}{GEN z, ulong p}, \kbd{z} which can be mapped to $\Z/p\Z$: a \typ{INT}, a \typ{INTMOD} whose modulus is divisible by $p$, a \typ{FRAC} whose denominator is coprime to $p$, or a \typ{PADIC} with underlying prime $\ell$ satisfying $p = \ell^n$ for some $n$ (less than the accuracy of the input). Returns \kbd{lift(z * Mod(1,p))}, normalized, as an \kbd{Fl}. \fun{ulong}{Rg_to_F2}{GEN z}, as \tet{Rg_to_Fl} for $p = 2$. \fun{ulong}{padic_to_Fl}{GEN x, ulong p} special case of \tet{Rg_to_Fl}, for a $x$ a \typ{PADIC}. \fun{GEN}{RgX_to_F2x}{GEN x}, \kbd{x} a \typ{POL}, returns the \kbd{F2x} obtained by applying \kbd{Rg\_to\_Fl} coefficientwise. \fun{GEN}{RgX_to_Flx}{GEN x, ulong p}, \kbd{x} a \typ{POL}, returns the \kbd{Flx} obtained by applying \kbd{Rg\_to\_Fl} coefficientwise. \fun{GEN}{Rg_to_F2xq}{GEN z, GEN T}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_2[X]/(T)$: anything \kbd{Rg\_to\_Fl} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_F2x} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{F2x}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{F2xq}, normalized. \fun{GEN}{Rg_to_Flxq}{GEN z, GEN T, ulong p}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_p[X]/(T)$: anything \kbd{Rg\_to\_Fl} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_Flx} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{Flx}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{Flxq}, normalized. \fun{GEN}{ZX_to_Flx}{GEN x, ulong p} reduce \kbd{ZX}~\kbd{x} modulo \kbd{p} (yielding an \kbd{Flx}). Faster than \kbd{RgX\_to\_Flx}. \fun{GEN}{ZV_to_Flv}{GEN x, ulong p} reduce \kbd{ZV}~\kbd{x} modulo \kbd{p} (yielding an \kbd{Flv}). \fun{GEN}{ZXV_to_FlxV}{GEN v, ulong p}, as \kbd{ZX\_to\_Flx}, repeatedly called on the vector's coefficients. \fun{GEN}{ZXT_to_FlxT}{GEN v, ulong p}, as \kbd{ZX\_to\_Flx}, repeatedly 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}{ZXXV_to_FlxXV}{GEN V, ulong p, long v}, as \kbd{ZXX\_to\_FlxX}, repeatedly called on the vector's coefficients. \fun{GEN}{RgC_to_Flc}{GEN x, ulong p} reduce the \typ{VEC}/\typ{COL} $x$ modulo $p$, yielding a \typ{VECSMALL}. \fun{GEN}{RgM_to_Flm}{GEN x, ulong p} reduce the \typ{MAT} $x$ modulo $p$. \fun{GEN}{ZM_to_Flm}{GEN x, ulong p} reduce \kbd{ZM}~$x$ modulo $p$ (yielding an \kbd{Flm}). \fun{GEN}{ZV_to_zv}{GEN z}, converts coefficients using \kbd{itos} \fun{GEN}{ZV_to_nv}{GEN z}, converts coefficients using \kbd{itou} \fun{GEN}{ZM_to_zm}{GEN z}, converts coefficients using \kbd{itos} \fun{GEN}{FqC_to_FlxC}{GEN x, GEN T, GEN p}, converts coefficients in \kbd{Fq} to coefficient in Flx, result being a column vector. \fun{GEN}{FqV_to_FlxV}{GEN x, GEN T, GEN p}, converts coefficients in \kbd{Fq} to coefficient in Flx, result being a line vector. \fun{GEN}{FqM_to_FlxM}{GEN x, GEN T, GEN p}, converts coefficients in \kbd{Fq} to coefficient in Flx. \subsubsec{From single precision} \fun{GEN}{Flx_to_ZX}{GEN z}, converts to \kbd{ZX} (\typ{POL} of non-negative \typ{INT}s in this case) \fun{GEN}{Flx_to_FlxX}{GEN z}, converts to \kbd{FlxX} (\typ{POL} of constant \kbd{Flx} in this case). \fun{GEN}{Flx_to_ZX_inplace}{GEN z}, same as \kbd{Flx\_to\_ZX}, in place (\kbd{z} is destroyed). \fun{GEN}{FlxX_to_ZXX}{GEN B}, converts an \kbd{FlxX} to a polynomial with \kbd{ZX} or \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}). \fun{GEN}{FlxC_to_ZXC}{GEN x}, converts a vector of \kbd{Flx} to a column vector of polynomials with \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}). \fun{GEN}{FlxV_to_ZXV}{GEN x}, as above but return a \typ{VEC}. \fun{void}{F2xV_to_FlxV_inplace}{GEN v} v is destroyed. \fun{void}{F2xV_to_ZXV_inplace}{GEN v} v is destroyed. \fun{void}{FlxV_to_ZXV_inplace}{GEN v} v is destroyed. \fun{GEN}{FlxM_to_ZXM}{GEN z}, converts a matrix of \kbd{Flx} to a matrix of 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. \fun{GEN}{Flc_to_ZC}{GEN z}, converts to \kbd{ZC} (\typ{COL} of non-negative \typ{INT}s in this case) \fun{GEN}{Flv_to_ZV}{GEN z}, converts to \kbd{ZV} (\typ{VEC} of non-negative \typ{INT}s in this case) \fun{GEN}{Flm_to_ZM}{GEN z}, converts to \kbd{ZM} (\typ{MAT} with non-negative \typ{INT}s coefficients in this case) \fun{GEN}{zc_to_ZC}{GEN z} as \kbd{Flc\_to\_ZC}, without assuming coefficients are non-negative. \fun{GEN}{zv_to_ZV}{GEN z} as \kbd{Flv\_to\_ZV}, without assuming coefficients are non-negative. \fun{GEN}{zm_to_ZM}{GEN z} as \kbd{Flm\_to\_ZM}, without assuming coefficients are non-negative. \fun{GEN}{zv_to_Flv}{GEN z, ulong p} \fun{GEN}{zm_to_Flm}{GEN z, ulong p} \subsubsec{Mixed precision linear algebra} Assumes dimensions are compatible. Multiply a multiprecision object by a single-precision one. \fun{GEN}{RgM_zc_mul}{GEN x, GEN y} \fun{GEN}{RgM_zm_mul}{GEN x, GEN y} \fun{GEN}{RgV_zc_mul}{GEN x, GEN y} \fun{GEN}{RgV_zm_mul}{GEN x, GEN y} \fun{GEN}{ZM_zc_mul}{GEN x, GEN y} \fun{GEN}{ZM_zm_mul}{GEN x, GEN y} \fun{GEN}{ZC_z_mul}{GEN x, long y} \fun{GEN}{ZM_nm_mul}{GEN x, GEN y} the entries of $y$ are \kbd{ulong}s. \fun{GEN}{nm_Z_mul}{GEN y, GEN c} the entries of $y$ are \kbd{ulong}s. \subsubsec{Miscellaneous involving Fl} \fun{GEN}{Fl_to_Flx}{ulong x, long evx} converts a \kbd{unsigned long} to a scalar \kbd{Flx}. Assume that \kbd{evx = evalvarn(vx)} for some variable number \kbd{vx}. \fun{GEN}{Z_to_Flx}{GEN x, ulong p, long v} converts a \typ{INT} to a scalar polynomial in variable $v$. \fun{GEN}{Flx_to_Flv}{GEN x, long n} converts from \kbd{Flx} to \kbd{Flv} with \kbd{n} components (assumed larger than the number of coefficients of \kbd{x}). \fun{GEN}{zx_to_zv}{GEN x, long n} as \kbd{Flx\_to\_Flv}. \fun{GEN}{Flv_to_Flx}{GEN x, long sv} converts from vector (coefficient array) to (normalized) polynomial in variable $v$. \fun{GEN}{zv_to_zx}{GEN x, long n} as \kbd{Flv\_to\_Flx}. \fun{GEN}{Flm_to_FlxV}{GEN x, long sv} converts the columns of \kbd{Flm}~\kbd{x} to an array of \kbd{Flx} in the variable $v$ (repeated calls to \kbd{Flv\_to\_Flx}). \fun{GEN}{zm_to_zxV}{GEN x, long n} as \kbd{Flm\_to\_FlxV}. \fun{GEN}{Flm_to_FlxX}{GEN x, long sw, long sv} same as \kbd{Flm\_to\_FlxV(x,sv)} but returns the result as a (normalized) polynomial in variable $w$. \fun{GEN}{FlxV_to_Flm}{GEN v, long n} reverse \kbd{Flm\_to\_FlxV}, to obtain an \kbd{Flm} with \kbd{n} rows (repeated calls to \kbd{Flx\_to\_Flv}). \fun{GEN}{FlxX_to_Flm}{GEN v, long n} reverse \kbd{Flm\_to\_FlxX}, to obtain an \kbd{Flm} with \kbd{n} rows (repeated calls to \kbd{Flx\_to\_Flv}). \fun{GEN}{FlxX_to_FlxC}{GEN B, long n, long sv} see \kbd{RgX\_to\_RgV}. The coefficients of \kbd{B} are assumed to be in the variable $v$. \fun{GEN}{FlxXV_to_FlxM}{GEN V, long n, long sv} see \kbd{RgXV\_to\_RgM}. The coefficients of \kbd{V[i]} are assumed to be in the variable $v$. \fun{GEN}{Fly_to_FlxY}{GEN a, long sv} convert coefficients of \kbd{a} to constant \kbd{Flx} in variable $v$. \subsubsec{Miscellaneous involving \kbd{F2x}} \fun{GEN}{F2x_to_F2v}{GEN x, long n} converts from \kbd{F2x} to \kbd{F2v} with \kbd{n} components (assumed larger than the number of coefficients of \kbd{x}). \fun{GEN}{F2xC_to_ZXC}{GEN x}, converts a vector of \kbd{F2x} to a column vector of polynomials with \typ{INT} coefficients (repeated calls to \kbd{F2x\_to\_ZX}). \fun{GEN}{F2xV_to_F2m}{GEN v, long n} \kbd{F2x\_to\_F2v} to each polynomial to get an \kbd{F2m} with \kbd{n} rows. \section{Higher arithmetic over $\Z$: primes, factorization} \subsec{Pure powers} \fun{long}{Z_issquare}{GEN n} returns $1$ if the \typ{INT} $n$ is a square, and $0$ otherwise. This is tested first modulo small prime powers, then \kbd{sqrtremi} is called. \fun{long}{Z_issquareall}{GEN n, GEN *sqrtn} as \kbd{Z\_issquare}. If $n$ is indeed a square, set \kbd{sqrtn} to its integer square root. Uses a fast congruence test mod $64\times 63\times 65\times 11$ before computing an integer square root. \fun{long}{Z_ispow2}{GEN x} returns $1$ if the \typ{INT} $x$ is a power of $2$, and $0$ otherwise. \fun{long}{uissquare}{ulong n} as \kbd{Z\_issquare}, for an \kbd{ulong} operand \kbd{n}. \fun{long}{uissquareall}{ulong n, ulong *sqrtn} as \kbd{Z\_issquareall}, for an \kbd{ulong} operand \kbd{n}. \fun{ulong}{usqrt}{ulong a} returns the floor of the square root of $a$. \fun{ulong}{usqrtn}{ulong a, ulong n} returns the floor of the $n$-th root of $a$. \fun{long}{Z_ispower}{GEN x, ulong k} returns $1$ if the \typ{INT} $n$ is a $k$-th power, and $0$ otherwise; assume that $k > 1$. \fun{long}{Z_ispowerall}{GEN x, ulong k, GEN *pt} as \kbd{Z\_ispower}. If $n$ is indeed a $k$-th power, set \kbd{*pt} to its integer $k$-th root. \fun{long}{Z_isanypower}{GEN x, GEN *ptn} returns the maximal $k\geq 2$ such that the \typ{INT} $x = n^k$ is a perfect power, or $0$ if no such $k$ exist; in particular \kbd{ispower(1)}, \kbd{ispower(0)}, \kbd{ispower(-1)} all return 0. If the return value $k$ is not $0$ (so that $x = n^k$) and \kbd{ptn} is not \kbd{NULL}, set \kbd{*ptn} to $n$. The following low-level functions are called by \tet{Z_isanypower} but can be directly useful: \fun{int}{is_357_power}{GEN x, GEN *ptn, ulong *pmask} tests whether the integer $x > 0$ is a $3$-rd, $5$-th or $7$-th power. The bits of \kbd{*mask} initially indicate which test is to be performed; bit $0$: $3$-rd, bit $1$: $5$-th, bit $2$: $7$-th (e.g.~$\kbd{*pmask} = 7$ performs all tests). They are updated during the call: if the ``$i$-th power'' bit is set to $0$ then $x$ is not a $k$-th power. The function returns $0$ (not a $3$-rd, $5$-th or $7$-th power), $3$ ($3$-rd power, not a $5$-th or $7$-th power), $5$ ($5$-th power, not a $7$-th power), or $7$ ($7$-th power); if an $i$-th power bit is initially set to $0$, we take it at face value and assume $x$ is not an $i$-th power without performing any test. If the return value $k$ is non-zero, set \kbd{*ptn} to $n$ such that $x = n^k$. \fun{int}{is_pth_power}{GEN x, GEN *ptn, forprime_t *T, ulong cutoff} let $x > 0$ be an integer, $\kbd{cutoff} > 0$ and $T$ be an iterator over primes $\geq 11$, we look for the smallest prime $p$ such that $x = n^p$ (advancing $T$ as we go along). The $11$ is due to the fact that \tet{is_357_power} and \kbd{issquare} are faster than the generic version for $p < 11$. Fail and return $0$ when the existence of $p$ would imply $2^{\kbd{cutoff}} > x^{1/p}$, meaning that a possible $n$ is so small that it should have been found by trial division; for maximal speed, you should start by a round of trial division, but the cut-off may also be set to $1$ for a rigorous result without any trial division. Otherwise returns the smallest suitable prime power $p^i$ and set \kbd{*ptn} to the $p^i$-th root of $x$ (which is now not a $p$-th power). We may immediately recall the function with the same parameters after setting $x = \kbd{*ptn}$: it will start at the next prime. \subsec{Factorization} \fun{GEN}{Z_factor}{GEN n} factors the \typ{INT} \kbd{n}. The ``primes'' in the factorization are actually strong pseudoprimes. \fun{GEN}{absi_factor}{GEN n} returns \kbd{Z\_factor(absi(n))}. \fun{long}{Z_issmooth}{GEN n, ulong lim} returns $1$ if all the prime factors of the \typ{INT} $n$ are less or equal to $lim$. \fun{GEN}{Z_issmooth_fact}{GEN n, ulong lim} returns \kbd{NULL} if a prime factor of the \typ{INT} $n$ is $> lim$, and returns the factorization of $n$ otherwise, as a \typ{MAT} with \typ{VECSMALL} columns (word-size primes and exponents). Neither memory-clean nor suitable for \kbd{gerepileupto}. \fun{GEN}{Z_factor_until}{GEN n, GEN lim} as \kbd{Z\_factor}, but stop the factorization process as soon as the unfactored part is smaller than \kbd{lim}. The resulting factorization matrix only contains the factors found. No other assumptions can be made on the remaining factors. \fun{GEN}{Z_factor_limit}{GEN n, ulong lim} trial divide $n$ by all primes $p < \kbd{lim}$ in the precomputed list of prime numbers and return the corresponding factorization matrix. In this case, the last ``prime'' divisor in the first column of the factorization matrix may well be a proven composite. If $\kbd{lim} = 0$, the effect is the same as setting $\kbd{lim} = \kbd{maxprime()} + 1$: use all precomputed primes. \fun{GEN}{absi_factor_limit}{GEN n, ulong all}returns \kbd{Z\_factor\_limit(absi(n))}. \fun{GEN}{boundfact}{GEN x, ulong lim} as \tet{Z_factor_limit}, applying to \typ{INT} or \typ{FRAC} inputs. \fun{GEN}{Z_smoothen}{GEN n, GEN L, GEN *pP, GEN *pE} given a \typ{VECSMALL} $L$ containing a list of small primes and a \typ{INT} $n$, trial divide $n$ by the elements of $L$ and return the cofactor. Return \kbd{NULL} if the cofactor is $\pm 1$. \kbd{*P} and \kbd{*E} contain the list of prime divisors found and their exponents, as \typ{VECSMALL}s. Neither memory-clean, nor suitable for \tet{gerepileupto}. \fun{GEN}{Z_factor_listP}{GEN N, GEN L} given a \typ{INT} $N$, a vector or primes $L$ containing all prime divisors of $N$ (and possibly others). Return \kbd{factor(N)}. Neither memory-clean, nor suitable for \tet{gerepileupto}. \fun{GEN}{factor_pn_1}{GEN p, ulong n} returns the factorization of $p^n-1$, where $p$ is prime and $n$ is a positive integer. \fun{GEN}{factor_pn_1_limit}{GEN p, ulong n, ulong B} returns a partial factorization of $p^n-1$, where $p$ is prime and $n$ is a positive integer. Don't actively search for prime divisors $p > B$, but we may find still find some due to Aurifeuillian factorizations. Any entry $> B^2$ in the output factorization matrix is \emph{a priori} not a prime (but may well be). \fun{GEN}{factor_Aurifeuille_prime}{GEN p, long n} an Aurifeuillian factor of $\phi_n(p)$, assuming $p$ prime and an Aurifeuillian factor exists ($p \zeta_n$ is a square in $\Q(\zeta_n)$). \fun{GEN}{factor_Aurifeuille}{GEN a, long d} an Aurifeuillian factor of $\phi_n(a)$, assuming $a$ is a non-zero integer and $n > 2$. Returns $1$ if no Aurifeuillian factor exists. \fun{GEN}{odd_prime_divisors}{GEN a} \typ{VEC} of all prime divisors of the \typ{INT} $a$. \fun{GEN}{factoru}{ulong n}, returns the factorization of $n$. The result is a $2$-component vector $[P,E]$, where $P$ and $E$ are \typ{VECSMALL} containing the prime divisors of $n$, and the $v_p(n)$. \fun{GEN}{factoru_pow}{ulong n}, returns the factorization of $n$. The result is a $3$-component vector $[P,E,C]$, where $P$, $E$ and $C$ are \typ{VECSMALL} containing the prime divisors of $n$, the $v_p(n)$ and the $p^{v_p(n)}$. \fun{ulong}{tridiv_bound}{GEN n} returns the trial division bound used by \tet{Z_factor}$(n)$. \subsec{Checks associated to arithmetic functions} Arithmetic functions accept arguments of the following kind: a plain positive integer $N$ (\typ{INT}), the factorization \var{fa} of a positive integer (a \typ{MAT} with two columns containing respectively primes and exponents), or a vector $[N,\var{fa}]$. A few functions accept non-zero integers (e.g.~\tet{omega}), and some others arbitrary integers (e.g.~\tet{factorint}, \dots). \fun{int}{is_Z_factorpos}{GEN f} returns $1$ if $f$ looks like the factorization of a positive integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof. Specifically, this routine checks that $f$ is a two-column matrix all of whose entries are positive integers. It does \emph{not} check that entries in the first column (``primes'') are prime, or even pairwise coprime, nor that they are stricly increasing. \fun{int}{is_Z_factornon0}{GEN f} returns $1$ if $f$ looks like the factorization of a non-zero integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof, analogous to \tet{is_Z_factorpos}. (Entries in the first column need only be non-zero integers.) \fun{int}{is_Z_factor}{GEN f} returns $1$ if $f$ looks like the factorization of an integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof. Specifically, this routine checks that $f$ is a two-column matrix all of whose entries are integers. Entries in the second column (``exponents'') are all positive. Either it encodes the ``factorization'' $0^e$, $e > 0$, or entries in the first column (``primes'') are all non-zero. \fun{GEN}{clean_Z_factor}{GEN f} assuming $f$ is the factorization of an integer $n$, return the factorization of $|n|$, i.e.~remove $-1$ from the factorization. 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. \fun{GEN}{check_arith_pos}{GEN n, const char *f} check whether $n$ is associated to the factorization of a positive integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. May raise an \tet{e_DOMAIN} ($n \leq 0$) or an \tet{e_TYPE} exception (other failures). \fun{GEN}{check_arith_non0}{GEN n, const char *f} check whether $n$ is associated to the factorization of a non-$0$ integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. May raise an \tet{e_TYPE} exception. \fun{GEN}{check_arith_all}{GEN n, const char *f} is associated to the factorization of an integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. \subsec{Incremental integer factorization} Routines associated to the dynamic factorization of an integer $n$, iterating over successive prime divisors. This is useful to implement high-level routines allowed to take shortcuts given enough partial information: e.g. \kbd{moebius}$(n)$ can be trivially computed if we hit $p$ such that $p^2 \mid n$. For efficiency, trial division by small primes should have already taken place. In any case, the functions below assume that no prime $< 2^{14}$ divides $n$. \fun{GEN}{ifac_start}{GEN n, int moebius} schedules a new factorization attempt for the integer $n$. If \kbd{moebius} is non-zero, the factorization will be aborted as soon as a repeated factor is detected (Moebius mode). The function assumes that $n > 1$ is a \emph{composite} \typ{INT} whose prime divisors satisfy $p > 2^{14}$ \emph{and} that one can write to $n$ in place. This function stores data on the stack, no \kbd{gerepile} call should delete this data until the factorization is complete. Returns \kbd{partial}, a data structure recording the partial factorization state. \fun{int}{ifac_next}{GEN *partial, GEN *p, long *e} deletes a primary factor $p^e$ from \kbd{partial} and sets \kbd{p} (prime) and \kbd{e} (exponent), and normally returns $1$. Whatever remains in the \kbd{partial} structure is now coprime to $p$. Returns $0$ if all primary factors have been used already, so we are done with the factorization. In this case $p$ is set to \kbd{NULL}. If we ran in Moebius mode and the factorization was in fact aborted, we have $e = 1$, otherwise $e = 0$. \fun{int}{ifac_read}{GEN part, GEN *k, long *e} peeks at the next integer to be factored in the list $k^e$, where $k$ is not necessarily prime and can be a perfect power as well, but will be factored by the next call to \tet{ifac_next}. You can remove this factorization from the schedule by calling: \fun{void}{ifac_skip}{GEN part} removes the next scheduled factorization. \fun{int}{ifac_isprime}{GEN n} given $n$ whose prime divisors are $> 2^{14}$, returns the decision the factoring engine would take about the compositeness of $n$: $0$ if $n$ is a proven composite, and $1$ if we believe it to be prime; more precisely, $n$ is a proven prime if \tet{factor_proven} is set, and only a BPSW-pseudoprime otherwise. \subsec{Integer core, squarefree factorization} \fun{long}{Z_issquarefree}{GEN n} returns $1$ if the \typ{INT} \kbd{n} is square-free, and $0$ otherwise. \fun{long}{Z_isfundamental}{GEN x} returns $1$ if the \typ{INT} \kbd{x} is a fundamental discriminant, and $0$ otherwise. \fun{GEN}{core}{GEN n} unique squarefree integer $d$ dividing $n$ such that $n/d$ is a square. The core of $0$ is defined to be $0$. \fun{GEN}{core2}{GEN n} return $[d,f]$ with $d$ squarefree and $n = df^2$. \fun{GEN}{corepartial}{GEN n, long lim} as \kbd{core}, using \kbd{boundfact(n,lim)} to partially factor \kbd{n}. The result is not necessarily squarefree, but $p^2 \mid n$ implies $p > \kbd{lim}$. \fun{GEN}{core2partial}{GEN n, long lim} as \kbd{core2}, using \kbd{boundfact(n,lim)} to partially factor \kbd{n}. The resulting $d$ is not necessarily squarefree, but $p^2 \mid n$ implies $p > \kbd{lim}$. \subsec{Primes, primality and compositeness tests} \subsubsec{Chebyshev's $\pi$ function, bounds} \fun{ulong}{uprimepi}{ulong n}, returns the number of primes $p\leq n$ (Chebyshev's $\pi$ function). \fun{double}{primepi_upper_bound}{double x} return a quick upper bound for $\pi(x)$, using Dusart bounds. \fun{GEN}{gprimepi_upper_bound}{GEN x} as \tet{primepi_upper_bound}, returns a \typ{REAL}. \fun{double}{primepi_lower_bound}{double x} return a quick lower bound for $\pi(x)$, using Dusart bounds. \fun{GEN}{gprimepi_lower_bound}{GEN x} as \tet{primepi_lower_bound}, returns a \typ{REAL} or \kbd{gen\_0}. \subsubsec{Primes, primes in intervals} \fun{ulong}{unextprime}{ulong n}, returns the smallest prime $\geq n$. Return $0$ if it cannot be represented as an \kbd{ulong} ($n$ bigger than $2^{64} - 59$ or $2^{32} - 5$ depending on the word size). \fun{ulong}{uprecprime}{ulong n}, returns the largest prime $\leq n$. Return $0$ if $n\leq 1$. \fun{ulong}{uprime}{long n} returns the $n$-th prime, assuming it fits in an \kbd{ulong} (overflow error otherwise). \fun{GEN}{prime}{long n} same as \kbd{utoi(uprime(n))}. \fun{GEN}{primes_zv}{long m} returns the first $m$ primes, in a \typ{VECSMALL}. \fun{GEN}{primes}{long m} return the first $m$ primes, as a \typ{VEC} of \typ{INT}s. \fun{GEN}{primes_interval}{GEN a, GEN b} return the primes in the interval $[a,b]$, as a \typ{VEC} of \typ{INT}s. \fun{GEN}{primes_interval_zv}{ulong a, ulong b} return the primes in the interval $[a,b]$, as a \typ{VECSMALL} of \kbd{ulongs}s. \fun{GEN}{primes_upto_zv}{ulong b} return the primes in the interval $[2,b]$, as a \typ{VECSMALL} of \kbd{ulongs}s. \subsubsec{Tests} \fun{int}{uisprime}{ulong p}, returns $1$ if \kbd{p} is a prime number and $0$ otherwise. \fun{int}{isprime}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a (fully proven) prime number and $0$ otherwise. \fun{long}{isprimeAPRCL}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a prime number and $0$ otherwise, using only the APRCL test --- not even trial division or compositeness tests. The workhorse \kbd{isprime} should be faster on average, especially if non-primes are included! \fun{long}{BPSW_psp}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a Baillie-Pomerance-Selfridge-Wagstaff pseudoprime, and $0$ otherwise (proven composite). \fun{int}{BPSW_isprime}{GEN x} assuming $x$ is a BPSW-pseudoprime, rigorously prove its primality. The function \tet{isprime} is currently implemented as \bprog BPSW_psp(x) && BPSW_isprime(x) @eprog \fun{long}{millerrabin}{GEN n, long k} performs $k$ strong Rabin-Miller compositeness tests on the \typ{INT} $n$, using $k$ random bases. This function also caches square roots of $-1$ that are encountered during the successive tests and stops as soon as three distinct square roots have been produced; we have in principle factored $n$ at this point, but unfortunately, there is currently no way for the factoring machinery to become aware of it. (It is highly implausible that hard to find factors would be exhibited in this way, though.) This should be slower than \tet{BPSW_psp} for $k\geq 4$ and we would expect it to be less reliable. \subsec{Iterators over primes} \fun{int}{forprime_init}{forprime_t *T, GEN a, GEN b} initialize an iterator $T$ over primes in $[a,b]$; over primes $\geq a$ if $b = \kbd{NULL}$. Return $0$ if the range is known to be empty from the start (as if $b < a$ or $b < 0$), and return $1$ otherwise. \fun{GEN}{forprime_next}{forprime_t *T} returns the next prime in the range, assuming that $T$ was initialized by \tet{forprime_init}. \fun{int}{u_forprime_init}{forprime_t *T, ulong a, ulong b} \fun{ulong}{u_forprime_next}{forprime_t *T} \fun{void}{u_forprime_restrict}{forprime_t *T, ulong c} let $T$ an iterator over primes initialized via \kbd{u\_forprime\_init(\&T, a, b)}, possibly followed by a number of calls to \tet{u_forprime_next}, and $a \leq c \leq b$. Restrict the range of primes considered to $[a,c]$. \fun{int}{u_forprime_arith_init}{forprime_t *T, ulong a,ulong b, ulong c,ulong q} initialize an iterator over primes in $[a,b]$, congruent to $c$ modulo $q$. Assume $0 \leq c < q$ and $(c,q) = 1$. Subsequent calls to \tet{u_forprime_next} will only return primes congruent to $c$ modulo $q$. \section{Integral, rational and generic linear algebra} \subsec{\kbd{ZC} / \kbd{ZV}, \kbd{ZM}} A \kbd{ZV} (resp.~a~\kbd{ZM}, resp.~a~\kbd{ZX}) is a \typ{VEC} or \typ{COL} (resp.~\typ{MAT}, resp.~\typ{POL}) with \typ{INT} coefficients. \subsubsec{\kbd{ZC} / \kbd{ZV}} \fun{void}{RgV_check_ZV}{GEN x, const char *s} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} raise an error if it is not a \kbd{ZV} ($s$ should point to the name of the caller). \fun{int}{RgV_is_ZV}{GEN x} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} return $1$ if it is a \kbd{ZV}, and $0$ otherwise. \fun{int}{RgV_is_QV}{GEN P} return 1 is the \kbd{RgV}~$P$ has only \typ{INT} and \typ{FRAC} coefficients, and 0 otherwise. \fun{int}{ZV_equal0}{GEN x} returns 1 if all entries of the \kbd{ZV} $x$ are zero, and $0$ otherwise. \fun{int}{ZV_cmp}{GEN x, GEN y} compare two \kbd{ZV}, which we assume have the same length (lexicographic order, comparing absolute values). \fun{int}{ZV_abscmp}{GEN x, GEN y} compare two \kbd{ZV}, which we assume have the same length (lexicographic order). \fun{int}{ZV_equal}{GEN x, GEN y} returns $1$ if the two \kbd{ZV} are equal and $0$ otherwise. A \typ{COL} and a \typ{VEC} with the same entries are declared equal. \fun{GEN}{ZC_add}{GEN x, GEN y} adds \kbd{x} and \kbd{y}. \fun{GEN}{ZC_sub}{GEN x, GEN y} subtracts \kbd{x} and \kbd{y}. \fun{GEN}{ZC_Z_add}{GEN x, GEN y} adds \kbd{y} to \kbd{x[1]}. \fun{GEN}{ZC_Z_sub}{GEN x, GEN y} subtracts \kbd{y} to \kbd{x[1]}. \fun{GEN}{ZC_copy}{GEN x} returns a (\typ{COL}) copy of \kbd{x}. \fun{GEN}{ZC_neg}{GEN x} returns $-\kbd{x}$ as a \typ{COL}. \fun{void}{ZV_neg_inplace}{GEN x} negates the \kbd{ZV} \kbd{x} in place, by replacing each component by its opposite (the type of \kbd{x} remains the same, \typ{COL} or \typ{COL}). If you want to save even more memory by avoiding the implicit component copies, use \kbd{ZV\_togglesign}. \fun{void}{ZV_togglesign}{GEN x} negates \kbd{x} in place, by toggling the sign of its integer components. Universal constants \kbd{gen\_1}, \kbd{gen\_m1}, \kbd{gen\_2} and \kbd{gen\_m2} are handled specially and will not be corrupted. (We use \tet{togglesign_safe}.) \fun{GEN}{ZC_Z_mul}{GEN x, GEN y} multiplies the \kbd{ZC} or \kbd{ZV}~\kbd{x} (which can be a column or row vector) by the \typ{INT}~\kbd{y}, returning a \kbd{ZC}. \fun{GEN}{ZC_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZV_dotproduct}{GEN x,GEN y} as \kbd{RgV\_dotproduct} assuming $x$ and $y$ have \typ{INT} entries. \fun{GEN}{ZV_dotsquare}{GEN x} as \kbd{RgV\_dotsquare} assuming $x$ has \typ{INT} entries. \fun{GEN}{ZC_lincomb}{GEN u, GEN v, GEN x, GEN y} returns $ux + vy$, where $u$, $v$ are \typ{INT} and $x,y$ are \kbd{ZC} or \kbd{ZV}. Return a \kbd{ZC} \fun{void}{ZC_lincomb1_inplace}{GEN X, GEN Y, GEN v} sets $X\leftarrow X + vY$, where $v$ is a \typ{INT} and $X,Y$ are \kbd{ZC} or \kbd{ZV}. (The result has the type of $X$.) Memory efficient (e.g. no-op if $v = 0$), but not gerepile-safe. \fun{GEN}{ZC_ZV_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). \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, 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]$. \fun{GEN}{ZV_prod}{GEN x} returns the product of all the components of~\kbd{x} ($1$ for the empty vector). \fun{GEN}{ZV_sum}{GEN x} returns the sum of all the components of~\kbd{x} ($0$ for the empty vector). \fun{long}{ZV_max_lg}{GEN x} returns the effective length of the longest entry in $x$. \fun{int}{ZV_dvd}{GEN x, GEN y} assuming $x$, $y$ are two \kbd{ZV}s of the same length, return $1$ if $y[i]$ divides $x[i]$ for all $i$ and $0$ otherwise. Error if one of the $y[i]$ is $0$. \fun{GEN}{ZV_sort}{GEN L} sort the \kbd{ZV} $L$. Returns a vector with the same type as $L$. \fun{GEN}{ZV_sort_uniq}{GEN L} sort the \kbd{ZV} $L$, removing duplicate entries. Returns a vector with the same type as $L$. \fun{long}{ZV_search}{GEN L, GEN y} look for the \typ{INT} $y$ in the sorted \kbd{ZV} $L$. Return an index $i$ such that $L[i] = y$, and $0$ otherwise. \fun{GEN}{ZV_indexsort}{GEN L} returns the permutation which, applied to the \kbd{ZV} $L$, would sort the vector. The result is a \typ{VECSMALL}. \fun{GEN}{ZV_union_shallow}{GEN x, GEN y} given two \emph{sorted} ZV (as per \tet{ZV_sort}, returns the union of $x$ and $y$. Shallow function. In case two entries are equal in $x$ and $y$, include the one from $x$. \subsubsec{\kbd{ZM}} \fun{void}{RgM_check_ZM}{GEN A, const char *s} Assuming \kbd{x} is a \typ{MAT} raise an error if it is not a \kbd{ZM} ($s$ should point to the name of the caller). \fun{GEN}{ZM_copy}{GEN x} returns a copy of \kbd{x}. \fun{int}{ZM_equal}{GEN A, GEN B} returns $1$ if the two \kbd{ZM} are equal and $0$ otherwise. \fun{GEN}{ZM_add}{GEN x, GEN y} returns $\kbd{x} + \kbd{y}$ (assumed to have compatible dimensions). \fun{GEN}{ZM_sub}{GEN x, GEN y} returns $\kbd{x} - \kbd{y}$ (assumed to have compatible dimensions). \fun{GEN}{ZM_neg}{GEN x} returns $-\kbd{x}$. \fun{void}{ZM_togglesign}{GEN x} negates \kbd{x} in place, by toggling the sign of its integer components. Universal constants \kbd{gen\_1}, \kbd{gen\_m1}, \kbd{gen\_2} and \kbd{gen\_m2} are handled specially and will 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_Z_mul}{GEN x, GEN y} multiplies the \kbd{ZM}~\kbd{x} by the \typ{INT}~\kbd{y}. \fun{GEN}{ZM_ZC_mul}{GEN x, GEN y} multiplies the \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions). \fun{GEN}{ZM_multosym}{GEN x, GEN y} \fun{GEN}{ZM_transmultosym}{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 $0 < i < \kbd{lg(x[1])}$. \fun{GEN}{ZV_ZM_mul}{GEN x, GEN y} multiplies the \kbd{ZV}~\kbd{x} 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_pow}{GEN x, GEN n} returns $\kbd{x}^\kbd{n}$, assuming \kbd{x} is a square \kbd{ZM} and $\kbd{n}\geq 0$. \fun{GEN}{ZM_powu}{GEN x, ulong n} returns $\kbd{x}^\kbd{n}$, assuming \kbd{x} is a square \kbd{ZM} and $\kbd{n}\geq 0$. \fun{GEN}{ZM_det}{GEN M} if \kbd{M} is a \kbd{ZM}, returns the determinant of $M$. This is the function underlying \tet{matdet} whenever $M$ is a \kbd{ZM}. \fun{GEN}{ZM_detmult}{GEN M} if \kbd{M} is a \kbd{ZM}, returns a multiple of the determinant of the lattice generated by its columns. This is the function underlying \tet{detint}. \fun{GEN}{ZM_supnorm}{GEN x} return the sup norm of the \kbd{ZM} $x$. \fun{GEN}{ZM_charpoly}{GEN M} returns the characteristic polynomial (in variable $0$) of the \kbd{ZM} $M$. \fun{GEN}{ZM_imagecompl}{GEN x} returns \kbd{matimagecompl(x)}. \fun{long}{ZM_rank}{GEN x} returns \kbd{matrank(x)}. \fun{GEN}{ZM_indexrank}{GEN x} returns \kbd{matindexrank(x)}. \fun{GEN}{ZM_indeximage}{GEN x} returns \kbd{gel(ZM\_indexrank(x), 2)}. \fun{long}{ZM_max_lg}{GEN x} returns the effective length of the longest entry in $x$. \fun{GEN}{ZM_inv}{GEN M, GEN d} if \kbd{M} is a \kbd{ZM} and \kbd{d} is a \typ{INT} such that $M' := \kbd{d}\kbd{M}^{-1}$ is integral, return $M'$. It is allowed to set \kbd{d = NULL}, in which case, the determinant of \kbd{M} is used instead. \fun{GEN}{QM_inv}{GEN M, GEN d} as above, with \kbd{M} a \kbd{QM}. We 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 \kbd{ZM} $x$ is the identity matrix, and 0 otherwise. \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$. \subsec{\kbd{zv}, \kbd{zm}} \fun{GEN}{zv_neg}{GEN x} return $-x$. No check for overflow is done, which occurs in the fringe case where an entry is equal to $2^{\B-1}$. \fun{GEN}{zv_neg_inplace}{GEN x} negates $x$ in place and return it. No check for overflow is done, which occurs in the fringe case where an entry is equal to $2^{\B-1}$. \fun{GEN}{zm_zc_mul}{GEN x, GEN y} \fun{GEN}{zm_mul}{GEN x, GEN y} \fun{GEN}{zv_z_mul}{GEN x, long n} return $n\*x$. No check for overflow is done. \fun{long}{zv_content}{GEN x} returns the gcd of the entries of $x$. \fun{long}{zv_dotproduct}{GEN x, GEN y} \fun{long}{zv_prod}{GEN x} returns the product of all the components of~\kbd{x} (assumes no overflow occurs). \fun{GEN}{zv_prod_Z}{GEN x} returns the product of all the components of~\kbd{x}; consider all $x[i]$ as \kbd{ulong}s. \fun{long}{zv_sum}{GEN x} returns the sum of all the components of~\kbd{x} (assumes no overflow occurs). \fun{int}{zv_cmp0}{GEN x} returns 1 if all entries of the \kbd{zv} $x$ are $0$, and $0$ otherwise. \fun{int}{zv_equal}{GEN x, GEN y} returns $1$ if the two \kbd{zv} are equal and $0$ otherwise. \fun{int}{zv_equal0}{GEN x} returns $1$ if all entries are $0$, and return $0$ otherwise. \fun{long}{zv_search}{GEN L, long y} look for $y$ in the sorted \kbd{zv} $L$. Return an index $i$ such that $L[i] = y$, and $0$ otherwise. \fun{GEN}{zv_copy}{GEN x} as \kbd{Flv\_copy}. \fun{GEN}{zm_transpose}{GEN x} as \kbd{Flm\_transpose}. \fun{GEN}{zm_copy}{GEN x} as \kbd{Flm\_copy}. \fun{GEN}{zero_zm}{long m, long n} as \kbd{zero\_Flm}. \fun{GEN}{zero_zv}{long n} as \kbd{zero\_Flv}. \fun{GEN}{row_zm}{GEN A, long x0} as \kbd{row\_Flm}. \fun{int}{zvV_equal}{GEN x, GEN y} returns $1$ if the two \kbd{zvV} (vectors of \kbd{zv}) are equal and $0$ otherwise. \subsec{\kbd{ZMV} / \kbd{zmV} (vectors of \kbd{ZM}/\kbd{zm})} \fun{int}{RgV_is_ZMV}{GEN x} Assuming \kbd{x} is a \typ{VEC} 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_ZMV}{GEN z} \subsec{\kbd{RgC} / \kbd{RgV}, \kbd{RgM}} \kbd{RgC} and \kbd{RgV} routines assume the inputs are \kbd{VEC} or \kbd{COL} of the same dimension. \kbd{RgM} assume the inputs are \kbd{MAT} of compatible dimensions. \subsubsec{Matrix arithmetic} \fun{void}{RgM_dimensions}{GEN}{x, long *m, long *n} sets $m$, resp.~$n$, to the number of rows, resp.~columns of the \typ{MAT} $x$. \fun{GEN}{RgC_add}{GEN x, GEN y} returns $x + y$ as a \typ{COL}. \fun{GEN}{RgC_neg}{GEN x} returns $-x$ as a \typ{COL}. \fun{GEN}{RgC_sub}{GEN x, GEN y} returns $x - y$ as a \typ{COL}. \fun{GEN}{RgV_add}{GEN x, GEN y} returns $x + y$ as a \typ{VEC}. \fun{GEN}{RgV_neg}{GEN x} returns $-x$ as a \typ{VEC}. \fun{GEN}{RgV_sub}{GEN x, GEN y} returns $x - y$ as a \typ{VEC}. \fun{GEN}{RgM_add}{GEN x, GEN y} return $x+y$. \fun{GEN}{RgM_neg}{GEN x} returns $-x$. \fun{GEN}{RgM_sub}{GEN x, GEN y} returns $x-y$. \fun{GEN}{RgM_Rg_add}{GEN x, GEN y} assuming $x$ is a square matrix and $y$ a scalar, returns the square matrix $x + y*\text{Id}$. \fun{GEN}{RgM_Rg_add_shallow}{GEN x, GEN y} as \kbd{RgM\_Rg\_add} with much fewer copies. Not suitable for \kbd{gerepileupto}. \fun{GEN}{RgM_Rg_sub}{GEN x, GEN y} assuming $x$ is a square matrix and $y$ a scalar, returns the square matrix $x - y*\text{Id}$. \fun{GEN}{RgM_Rg_sub_shallow}{GEN x, GEN y} as \kbd{RgM\_Rg\_sub} with much fewer copies. Not suitable for \kbd{gerepileupto}. \fun{GEN}{RgC_Rg_add}{GEN x, GEN y} assuming $x$ is a non-empty column vector and $y$ a scalar, returns the vector $[x_1 + y, x_2,\dots,x_n]$. \fun{GEN}{RgC_Rg_div}{GEN x, GEN y} \fun{GEN}{RgM_Rg_div}{GEN x, GEN y} returns $x/y$ ($y$ treated as a scalar). \fun{GEN}{RgC_Rg_mul}{GEN x, GEN y} \fun{GEN}{RgV_Rg_mul}{GEN x, GEN y} \fun{GEN}{RgM_Rg_mul}{GEN x, GEN y} returns $x\times y$ ($y$ treated as a scalar). \fun{GEN}{RgV_RgC_mul}{GEN x, GEN y} returns $x\times y$. \fun{GEN}{RgV_RgM_mul}{GEN x, GEN y} returns $x\times y$. \fun{GEN}{RgM_RgC_mul}{GEN x, GEN y} returns $x\times y$. \fun{GEN}{RgM_mul}{GEN x, GEN y} returns $x\times y$. \fun{GEN}{RgM_transmul}{GEN x, GEN y} returns $x\til \times y$. \fun{GEN}{RgM_multosym}{GEN x, GEN y} returns $x\times y$, assuming the result is a symmetric matrix (about twice faster than a generic matrix multiplication). \fun{GEN}{RgM_transmultosym}{GEN x, GEN y} returns $x\til \times y$, assuming the result is a symmetric matrix (about twice faster than a generic matrix multiplication). \fun{GEN}{RgMrow_RgC_mul}{GEN x, GEN y, long i} multiplies the $i$-th row of \kbd{RgM}~\kbd{x} by the \kbd{RgC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions). Assumes that $x$ is non-empty and $0 < i < \kbd{lg(x[1])}$. \fun{GEN}{RgM_mulreal}{GEN x, GEN y} returns the real part of $x\times y$ (whose entries are \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}). \fun{GEN}{RgM_sqr}{GEN x} returns $x^2$. \fun{GEN}{RgC_RgV_mul}{GEN x, GEN y} returns $x\times y$ (the square matrix $(x_iy_j)$). The following two functions are not well defined in general and only provided for convenience in specific cases: \fun{GEN}{RgC_RgM_mul}{GEN x, GEN y} returns $x\times y[1,]$ if $y$ is a row matrix $1\times n$, error otherwise. \fun{GEN}{RgM_RgV_mul}{GEN x, GEN y} returns $x\times y[,1]$ if $y$ is a column matrix $n\times 1$, error otherwise. \fun{GEN}{RgM_powers}{GEN x, long n} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{RgM}s. \smallskip \fun{GEN}{RgV_sum}{GEN v} sum of the entries of $v$ \fun{GEN}{RgV_sumpart}{GEN v, long n} returns the sum $v[1] + \dots + v[n]$ (assumes that \kbd{lg}$(v) > n$). \fun{GEN}{RgV_sumpart2}{GEN v, long m, long n} returns the sum $v[m] + \dots + v[n]$ (assumes that \kbd{lg}$(v) > n$ and $m > 0$). Returns \kbd{gen\_0} when $m > n$. \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. \fun{GEN}{gram_matrix}{GEN v} returns the \idx{Gram matrix} $(v_i\cdot v_j)$ associated to the entries of $v$ (matrix, or vector of vectors). \fun{GEN}{RgV_polint}{GEN X, GEN Y, long v} $X$ and $Y$ being two vectors of the same length, returns the polynomial $T$ in variable $v$ such that $T(X[i]) = Y[i]$ for all $i$. The special case $X = \kbd{NULL}$ corresponds to $X = [1,2,\dots,n]$, where $n$ is the length of $Y$. \subsubsec{Special shapes} The following routines check whether matrices or vectors have a special shape, using \kbd{gequal1} and \kbd{gequal0} to test components. (This makes a difference when components are inexact.) \fun{int}{RgV_isscalar}{GEN x} return 1 if all the entries of $x$ are $0$ (as per \kbd{gequal0}), except possibly the first one. The name comes from vectors expressing polynomials on the standard basis $1,T,\dots, T^{n-1}$, or on \kbd{nf.zk} (whose first element is $1$). \fun{int}{QV_isscalar}{GEN x} as \kbd{RgV\_isscalar}, assuming $x$ is a \kbd{QV} (\typ{INT} and \typ{FRAC} entries only). \fun{int}{ZV_isscalar}{GEN x} as \kbd{RgV\_isscalar}, assuming $x$ is a \kbd{ZV} (\typ{INT} entries only). \fun{int}{RgM_isscalar}{GEN x, GEN s} return 1 if $x$ is the scalar matrix equal to $s$ times the identity, and 0 otherwise. If $s$ is \kbd{NULL}, test whether $x$ is an arbitrary scalar matrix. \fun{int}{RgM_isidentity}{GEN x} return 1 is the \typ{MAT} $x$ is the 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{int}{RgM_is_ZM}{GEN x} return 1 is the \typ{MAT}~$x$ has only \typ{INT} coefficients, and 0 otherwise. \fun{long}{RgV_isin}{GEN v, GEN x} return the first index $i$ such that $v[i] = x$ if it exists, and $0$ otherwise. Naive search in linear time, does not assume that \kbd{v} is sorted. \fun{GEN}{RgM_diagonal}{GEN m} returns the diagonal of $m$ as a \typ{VEC}. \fun{GEN}{RgM_diagonal_shallow}{GEN m} shallow version of \kbd{RgM\_diagonal} \subsubsec{Conversion to floating point entries} \fun{GEN}{RgC_gtofp}{GEN x, GEN prec} returns the \typ{COL} obtained by applying \kbd{gtofp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgC_gtomp}{GEN x, long prec} returns the \typ{COL} obtained by applying \kbd{gtomp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgC_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog gnorml2( RgC_gtofp(x, prec) ) @eprog \fun{GEN}{RgM_gtofp}{GEN x, GEN prec} returns the \typ{MAT} obtained by applying \kbd{gtofp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgM_gtomp}{GEN x, long prec} returns the \typ{MAT} obtained by applying \kbd{gtomp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgM_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog gnorml2( RgM_gtofp(x, prec) ) @eprog \subsubsec{Linear algebra, linear systems} \fun{GEN}{RgM_inv}{GEN a} returns a left inverse of $a$ (which needs not be square), or \kbd{NULL} if this turns out to be impossible. The latter happens when the matrix does not have maximal rank (or when rounding errors make it appear so). \fun{GEN}{RgM_inv_upper}{GEN a} as \kbd{RgM\_inv}, assuming that $a$ is a non-empty invertible upper triangular matrix, hence a little faster. \fun{GEN}{RgM_RgC_invimage}{GEN A, GEN B} returns a \typ{COL} $X$ such that $A X = B$ if one such exists, and \kbd{NULL} otherwise. \fun{GEN}{RgM_invimage}{GEN A, GEN B} returns a \typ{MAT} $X$ such that $A X = B$ if one such exists, and \kbd{NULL} otherwise. \fun{GEN}{RgM_Hadamard}{GEN a} returns a upper bound for the absolute value of $\text{det}(a)$. The bound is a \typ{INT}. \fun{GEN}{RgM_solve}{GEN a, GEN b} returns $a^{-1}b$ where $a$ is a square \typ{MAT} and $b$ is a \typ{COL} or \typ{MAT}. Returns \kbd{NULL} if $a^{-1}$ cannot be computed, see \tet{RgM_inv}. If $b = \kbd{NULL}$, the matrix $a$ need no longer be square, and we strive to return a left inverse for $a$ (\kbd{NULL} if it does not exist). \fun{GEN}{RgM_solve_realimag}{GEN M, GEN b} $M$ being a \typ{MAT} with $r_1+r_2$ rows and $r_1+2r_2$ columns, $y$ a \typ{COL} or \typ{MAT} such that the equation $Mx = y$ makes sense, returns $x$ under the following simplifying assumptions: the first $r_1$ rows of $M$ and $y$ are real (the $r_2$ others are complex), and $x$ is real. This is stabler and faster than calling $\kbd{RgM\_solve}(M, b)$ over $\C$. In most applications, $M$ approximates the complex embeddings of an integer basis in a number field, and $x$ is actually rational. \fun{GEN}{split_realimag}{GEN x, long r1, long r2} $x$ is a \typ{COL} or \typ{MAT} with $r_1 + r_2$ rows, whose first $r_1$ rows have real entries (the $r_2$ others are complex). Return an object of the same type as $x$ and $r_1 + 2r_2$ rows, such that the first $r_1 + r_2$ rows contain the real part of $x$, and the $r_2$ following ones contain the imaginary part of the last $r_2$ rows of $x$. Called by \tet{RgM_solve_realimag}. \fun{GEN}{RgM_det_triangular}{GEN x} returns the product of the diagonal 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}. \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. Sets \kbd{*pB} to the vector of squared lengths of the $x[i]$, \kbd{*pL} to the Gram-Schmidt coefficients and \kbd{*pQ} to a vector of successive Householder transforms. If $R$ denotes the transpose of $L$ and $Q$ is the result of applying \kbd{*pQ} to the identity matrix, then $x = QR$ is the QR decomposition of $x$. Returns $0$ is $x$ is not invertible or we hit a precision problem, and $1$ otherwise. \fun{int}{QR_init}{GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec} as \kbd{RgM\_QR\_init}, assuming further that $x$ has \typ{INT} or \typ{REAL} coefficients. \fun{GEN}{R_from_QR}{GEN x, long prec} assuming that $x$ is a square invertible \typ{MAT} with \typ{INT} or \typ{REAL} coefficients, return the upper triangular $R$ from the $QR$ docomposition of $x$. Not memory clean. If the matrix is not known to have \typ{INT} or \typ{REAL} coefficients, apply \tet{RgM_gtomp} first. \fun{GEN}{gaussred_from_QR}{GEN x, long prec} assuming that $x$ is a square invertible \typ{MAT} with \typ{INT} or \typ{REAL} coefficients, returns \kbd{qfgaussred(x\til * x)}; this is essentially the upper triangular $R$ matrix from the $QR$ decomposition of $x$, renormalized to accomodate \kbd{qfgaussred} conventions. Not memory clean. \subsec{Blackbox linear algebra} A sparse column \kbd{zCs} $v$ is a \typ{COL} with two components $C$ and $E$ which are \typ{VECSMALL} of the same length, representing $\sum_i E[i]*e_{C[i]}$, where $(e_j)$ is the canonical basis. A sparse matrix (\kbd{zMs}) is a \typ{VEC} of \kbd{zCs}. \kbd{FpCs} and \kbd{FpMs} are identical to the above, but $E[i]$ is now interpreted as a \emph{signed} C long integer representing an element of $\F_p$. This is important since $p$ can be so large that $p+E[i]$ would not fit in a C long. \kbd{RgCs} and \kbd{RgMs} are similar, except that the type of the components of $E$ is now unspecified. Functions handling those later objects must not depend on the type of those components. It is not possible to derive the space dimension (number of rows) from the above data. Thus most functions take an argument \kbd{nbrow} which is the number of rows of the corresponding column/matrix in dense representation. \fun{GEN}{zCs_to_ZC}{GEN C, long nbrow} convert the sparse vector $C$ to a dense \kbd{ZC} of dimension \kbd{nbrow}. \fun{GEN}{zMs_to_ZM}{GEN M, long nbrow} convert the sparse matrix $M$ to a dense \kbd{ZM} whose columns have dimension \kbd{nbrow}. \fun{GEN}{FpMs_FpC_mul}{GEN M, GEN B, GEN p} multiply the sparse matrix $M$ (over $\F_p$) by the sparse vector $B$. The result is an \kbd{FpC}, i.e.~a dense vector. \fun{GEN}{zMs_ZC_mul}{GEN M, GEN B, GEN p} multiply the sparse matrix $M$ by the sparse vector $B$ (over $\Z$). The result is an \kbd{ZC}, i.e.~a dense vector. \fun{GEN}{FpV_FpMs_mul}{GEN B, GEN M, GEN p} multiply the sparse vector $B$ by the sparse matrix $M$ (over $\F_p$). The result is an \kbd{FpV}, i.e.~a dense vector. \fun{GEN}{ZV_zMs_mul}{GEN B, GEN M, GEN p} multiply the sparse vector $B$ (over $\Z$) by the sparse matrix $M$. The result is an \kbd{ZV}, i.e.~a dense vector. \fun{void}{RgMs_structelim}{GEN M, long nbrow, GEN A, GEN *p_col, GEN *p_row} $M$ being a RgMs with \kbd{nbrow} rows, $A$ being a list of row indices, Perform structured elimination on $M$ by removing some rows and columns until the number of effectively present rows is equal to the number of columns. the result is stored in two \typ{VECSMALL}s, \kbd{*p\_col} and \kbd{*p\_row}: \kbd{*p\_col} is a map from the new columns indices to the old one. \kbd{*p\_row} is a map from the old rows indices to the new one ($0$ if removed). \fun{GEN}{FpMs_leftkernel_elt}{GEN M, long nbrow, GEN p} $M$ being a sparse matrix over $\F_p$, return a non-zero kbd{FpV} $X$ such that $X\*M$ components are almost all $0$. \fun{GEN}{FpMs_FpCs_solve}{GEN M, GEN B, long nbrow, GEN p} solve the equation $M\*X = B$, where $M$ is a sparse matrix and $B$ is a sparse vector, both over $\F_p$. Return either a solution as a \typ{COL} (dense vector), the index of a column which is linearly dependent from the others as a \typ{VECSMALL} with a single component, or \kbd{NULL} (can happen if $B$ is not in the image of $M$). \fun{GEN}{FpMs_FpCs_solve_safe}{GEN M, GEN B, long nbrow, GEN p} as above, but in the event that $p$ is not a prime and an impossible division occurs, return \kbd{NULL}. \fun{GEN}{ZpMs_ZpCs_solve}{GEN M, GEN B, long nbrow, GEN p, long e} solve the equation $MX = B$, where $M$ is a sparse matrix and $B$ is a sparse vector, both over $\Z/p^e\Z$. Return either a solution as a \typ{COL} (dense vector), or the index of a column which is linearly dependent from the others as a \typ{VECSMALL} with a single component. \fun{GEN}{gen_FpM_Wiedemann}{void *E, GEN (*f)(void*, GEN), GEN B, GEN p} solve the equation $f(X) = B$ over $\F_p$, where $B$ is a \kbd{FpV}, and $f$ is a blackbox endomorphism, where $f(E, X)$ computes the value of $f$ at the (dense) column vector $X$. Returns either a solution \typ{COL}, or a kernel vector as a \typ{VEC}. \fun{GEN}{gen_ZpM_Dixon}{void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e} solve equation $f(X) = B$ over $\Z/p^e\Z$, where $B$ is a \kbd{ZV}, and $f$ is a blackbox endomorphism, where $f(E, X)$ computes the value of $f$ at the (dense) column vector $X$. Returns either a solution \typ{COL}, or a kernel vector as a \typ{VEC}. \subsec{Obsolete functions} The functions in this section are kept for backward compatibility only and will eventually disappear. \fun{GEN}{image2}{GEN x} compute the image of $x$ using a very slow algorithm. Use \tet{image} instead. \section{Integral, rational and generic polynomial arithmetic} \subsec{\kbd{ZX}} \fun{void}{RgX_check_ZX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it is not a \kbd{ZX} ($s$ should point to the name of the caller). \fun{GEN}{ZX_copy}{GEN x,GEN p} returns a copy of \kbd{x}. \fun{long}{ZX_max_lg}{GEN x} returns the effective length of the longest component in $x$. \fun{GEN}{scalar_ZX}{GEN x, long v} returns the constant \kbd{ZX} in variable $v$ equal to the \typ{INT} $x$. \fun{GEN}{scalar_ZX_shallow}{GEN x, long v} returns the constant \kbd{ZX} in variable $v$ equal to the \typ{INT} $x$. Shallow function not suitable for \kbd{gerepile} and friends. \fun{GEN}{ZX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{int}{ZX_equal}{GEN x, GEN y} returns $1$ if the two \kbd{ZX} have the same \kbd{degpol} and their coefficients are equal. Variable numbers are not checked. \fun{int}{ZX_equal1}{GEN x} returns $1$ if the \kbd{ZX} is equal to $1$ and $0$ otherwise. \fun{GEN}{ZX_add}{GEN x,GEN y} adds \kbd{x} and \kbd{y}. \fun{GEN}{ZX_sub}{GEN x,GEN y} subtracts \kbd{x} and \kbd{y}. \fun{GEN}{ZX_neg}{GEN x,GEN p} returns $-\kbd{x}$. \fun{GEN}{ZX_Z_add}{GEN x,GEN y} adds the integer \kbd{y} to the \kbd{ZX}~\kbd{x}. \fun{GEN}{ZX_Z_add_shallow}{GEN x,GEN y} shallow version of \tet{ZX_Z_add}. \fun{GEN}{ZX_Z_sub}{GEN x,GEN y} subtracts the integer \kbd{y} to the \kbd{ZX}~\kbd{x}. \fun{GEN}{Z_ZX_sub}{GEN x,GEN y} subtracts the \kbd{ZX} \kbd{y} to the integer \kbd{x}. \fun{GEN}{ZX_Z_mul}{GEN x,GEN y} multiplies the \kbd{ZX} \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZX_mulu}{GEN x, ulong y} multiplies \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZX_shifti}{GEN x, long n} shifts all coefficients of \kbd{x} by $n$ bits, which can be negative. \fun{GEN}{ZX_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZX_remi2n}{GEN x, long n} reduces all coefficients of \kbd{x} to $n$ bits, using \tet{remi2n}. \fun{GEN}{ZX_mul}{GEN x,GEN y} multiplies \kbd{x} and \kbd{y}. \fun{GEN}{ZX_sqr}{GEN x,GEN p} returns $\kbd{x}^2$. \fun{GEN}{ZX_mulspec}{GEN a, GEN b, long na, long nb}. Internal routine: \kbd{a} and \kbd{b} are arrays of coefficients representing polynomials $\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}{ZX_sqrspec}{GEN a, long na}. Internal routine: \kbd{a} is an array of coefficients representing polynomial $\sum_{i = 0}^{\kbd{na-1}} \kbd{a}[i] X^i$. Return its square (as a true \kbd{GEN}). \fun{GEN}{ZX_rem}{GEN x, GEN y} returns the remainder of the Euclidean division of $x$ mod $y$. Assume that $x$, $y$ are two \kbd{ZX} and that $y$ is monic. \fun{GEN}{ZX_mod_Xnm1}{GEN T, ulong n} return $T$ modulo $X^n - 1)$. Shallow function. \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}. \fun{GEN}{ZX_gcd_all}{GEN x, GEN y, GEN *pX}. returns a gcd $d$ of $x$ and $y$. If \kbd{pX} is not \kbd{NULL}, set $\kbd{*pX}$ to a (non-zero) integer multiple of $x/d$. If $x$ and $y$ are both monic, then $d$ is monic and \kbd{*pX} is exactly $x/d$. Not memory clean if the gcd is $1$ (in that case \kbd{*pX} is set to $x$). \fun{GEN}{ZX_content}{GEN x} returns the content of the \kbd{ZX} $x$. \fun{long}{ZX_val}{GEN P} as \kbd{RgX\_val}, but assumes \kbd{P} has \typ{INT} coefficients. \fun{long}{ZX_valrem}{GEN P, GEN *z} as \kbd{RgX\_valrem}, but assumes \kbd{P} has \typ{INT} coefficients. \fun{GEN}{ZX_to_monic}{GEN q GEN *L} given $q$ a non-zero \kbd{ZX}, returns a monic integral polynomial $Q$ such that $Q(x) = C q(x/L)$, for some rational $C$ and positive integer $L > 0$. If $\kbd{L}$ is not \kbd{NULL}, set \kbd{*L} to $L$; if $L = 1$, \kbd{*L} is set to \kbd{gen\_1}. Not suitable for gerepileupto. \fun{GEN}{ZX_primitive_to_monic}{GEN q, GEN *L} as \tet{ZX_to_monic} except $q$ is assumed to have trivial content, which avoids recomputing it. The result is suboptimal if $q$ is not primitive ($L$ larger than necessary), but remains correct. \fun{GEN}{ZX_Z_normalize}{GEN q, GEN *L} a restricted version of \kbd{ZX\_primitive\_to\_monic}, where $q$ is a \emph{monic} \kbd{ZX} of degree $> 0$. Finds the largest integer $L > 0$ such that $Q(X) := L^{-\deg q} q(Lx)$ is integral and return $Q$; this is not well-defined if $q$ is a monomial, in that case, set $L=1$ and $Q = q$. If \kbd{L} is not \kbd{NULL}, set \kbd{*L} to $L$. \fun{GEN}{ZX_Q_normalize}{GEN q, GEN *L} a variant of \tet{ZX_Z_normalize} where $L > 0$ is allowed to be rational, the monic $Q\in \Z[X]$ has possibly smaller coefficients. \fun{GEN}{ZX_rescale}{GEN P, GEN h} returns $h^{\deg(P)} P(x/h)$. \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_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 \kbd{gerepileupto}. \fun{GEN}{ZX_translate}{GEN P, GEN c} assume $P$ is a \kbd{ZX} and $c$ an 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_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. \fun{GEN}{ZX_eval1}{GEN P} returns the integer $P(1)$. \fun{GEN}{ZX_graeffe}{GEN p} returns the Graeffe transform of $p$, i.e. the \kbd{ZX} $q$ such that $p(x)p(-x) = q(x^2)$. \fun{GEN}{ZX_deriv}{GEN x} returns the derivative of \kbd{x}. \fun{GEN}{ZX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{ZX}~\kbd{A} and \kbd{B}. \fun{GEN}{ZX_disc}{GEN T} returns the discriminant of the \kbd{ZX} \kbd{T}. \fun{GEN}{ZX_factor}{GEN T} returns the factorization of the primitive part of \kbd{T} over $\Q[X]$ (the content is lost). \fun{int}{ZX_is_squarefree}{GEN T} returns $1$ if the \kbd{ZX}~\kbd{T} is squarefree, $0$ otherwise. \fun{long}{ZX_is_irred}{GEN T} returns 1 it \kbd{T} is irreducible, and 0 otherwise. \fun{GEN}{ZX_squff}{GEN T, GEN *E} write $T$ as a product $\prod T_i^{e_i}$ 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}. \subsec{\kbd{ZXQ}} \fun{GEN}{ZXQ_mul}{GEN x,GEN y,GEN T} returns $x*y$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_sqr}{GEN x,GEN T} returns $x^2$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_charpoly}{GEN A, GEN T, long v}: let \kbd{T} and \kbd{A} be \kbd{ZX}s, returns the characteristic polynomial of \kbd{Mod(A, T)}. More generally, \kbd{A} is allowed to be a \kbd{QX}, hence possibly has rational coefficients, \emph{assuming} the result is a \kbd{ZX}, i.e.~the algebraic number \kbd{Mod(A,T)} is integral over \kbd{Z}. \fun{GEN}{ZX_ZXY_resultant}{GEN A, GEN B} under the assumption that \kbd{A} in $\Z[Y]$, \kbd{B} in $\Q[Y][X]$, and $R = \text{Res}_Y(A, B) \in \Z[X]$, returns the resultant $R$. \fun{GEN}{ZX_compositum_disjoint}{GEN A, GEN B} given two irreducible \kbd{ZX} defining linearly disjoint extensions, returns a \kbd{ZX} defining their compositum. \fun{GEN}{ZX_ZXY_rnfequation}{GEN A, GEN B, long *lambda}, assume \kbd{A} in $\Z[Y]$, \kbd{B} in $\Q[Y][X]$, and $R = \text{Res}_Y(A, B) \in \Z[X]$. If \kbd{lambda = NULL}, returns $R$ as in \kbd{ZY\_ZXY\_resultant}. Otherwise, \kbd{lambda} must point to some integer, e.g. $0$ which is used as a seed. The function then finds a small $\lambda \in \Z$ (starting from \kbd{*lambda}) such that $R_\lambda(X) := \text{Res}_Y(A, B(X + \lambda Y))$ is squarefree, resets \kbd{*lambda} to the chosen value and returns $R_{\lambda}$. \subsec{\kbd{ZXV}} \fun{GEN}{ZXV_equal}{GEN x,GEN y} returns $1$ if the two vectors of \kbd{ZX} are equal, as per \tet{ZX_equal} (variables are not checked to be equal) and $0$ otherwise. \fun{GEN}{ZXV_Z_mul}{GEN x,GEN y} multiplies the vector of \kbd{ZX} \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZXV_remi2n}{GEN x, long n} applies \kbd{ZX\_remi2n} to all coefficients of \kbd{x}. \fun{GEN}{ZXV_dotproduct}{GEN x,GEN y} as \kbd{RgV\_dotproduct} assuming $x$ and $y$ have \kbd{ZX} entries. \subsec{\kbd{ZXT}} \fun{GEN}{ZXT_remi2n}{GEN x, long n} applies \kbd{ZX\_remi2n} to all leaves of the tree \kbd{x}. \subsec{\kbd{ZXX}} \fun{void}{RgX_check_ZXX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it one of its coefficients is not an integer or a \kbd{ZX} ($s$ should point to the name of the caller). \fun{GEN}{ZXX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\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_divexact}{GEN x, GEN y} returns $x/y$ assuming all integer divisions are exact. \fun{GEN}{ZXX_to_Kronecker}{GEN P, long n} Assuming $P(X,Y)$ is a polynomial of degree in $X$ strictly less than $n$, returns $P(X,X^{2*n-1})$, the Kronecker form of $P$. Shallow function. \fun{GEN}{ZXX_to_Kronecker_spec}{GEN Q, long lQ, long n} return \tet{ZXX_to_Kronecker}$(P, n)$, where $P$ is the polynomial $\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 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}$ of $P$ and $Q$. Not memory clean. \subsec{\kbd{QX}} \fun{void}{RgX_check_QX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it is not a \kbd{QX} ($s$ should point to the name of the caller). \fun{GEN}{QX_gcd}{GEN x,GEN y} returns a gcd of the \kbd{QX} $x$ and $y$. \fun{GEN}{QX_disc}{GEN T} returns the discriminant of the \kbd{QX} \kbd{T}. \fun{GEN}{QX_factor}{GEN T} as \kbd{ZX\_factor}. \fun{GEN}{QX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{QX}~\kbd{A} and \kbd{B}. \fun{GEN}{QX_complex_roots}{GEN p, long l} returns the complex roots of the \kbd{QX} $p$ at accuracy $l$, where real roots are returned as \typ{REAL}s. More efficient when $p$ is irreducible and primitive. Special case of \tet{cleanroots}. \subsec{\kbd{QXQ}} \fun{GEN}{QXQ_norm}{GEN A, GEN B} $A$ being a \kbd{QX} and $B$ being a \kbd{ZX}, returns the norm of the algebraic number $A \mod B$, using a modular algorithm. To ensure that $B$ is a \kbd{ZX}, one may replace it by \kbd{Q\_primpart(B)}, which of course does not change the norm. If $A$ is not a \kbd{ZX} --- it has a denominator ---, but the result is nevertheless known to be an integer, it is much more efficient to call \tet{QXQ_intnorm} instead. \fun{GEN}{QXQ_intnorm}{GEN A, GEN B} $A$ being a \kbd{QX} and $B$ being a \kbd{ZX}, returns the norm of the algebraic number $A \mod B$, \emph{assuming} that the result is an integer, which is for instance the case is $A\mod B$ is an algebraic integer, in particular if $A$ is a \kbd{ZX}. To ensure that $B$ is a \kbd{ZX}, one may replace it by \kbd{Q\_primpart(B)} (which of course does not change the norm). If the result is not known to be an integer, you must use \tet{QXQ_norm} instead, which is slower. \fun{GEN}{QXQ_inv}{GEN A, GEN B} returns the inverse of $A$ modulo $B$ where $A$ is a \kbd{QX} and $B$ is a \kbd{ZX}. Should you need this for a \kbd{QX} $B$, just use \bprog QXQ_inv(A, Q_primpart(B)); @eprog\noindent But in all cases where modular arithmetic modulo $B$ is desired, it is much more efficient to replace $B$ by \kbd{Q\_primpart$(B)$} once and for all. \fun{GEN}{QXQ_powers}{GEN x, long n, GEN T} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as \kbd{RgXQ\_powers} would, but in a more efficient way when $x$ has a huge integer denominator (we start by removing that denominator). Meant to be used to precompute powers of algebraic integers in $\Q[t]/(T)$. The current implementation does not require $x$ to be a \kbd{QX}: any polynomial to which \kbd{Q\_remove\_denom} can be applied is fine. \fun{GEN}{QXQ_reverse}{GEN f, GEN T} as \kbd{RgXQ\_reverse}, assuming $f$ is a \kbd{QX}. \fun{GEN}{QX_ZXQV_eval}{GEN f, GEN nV, GEN dV} as \kbd{RgX\_RgXQV\_eval}, except that $f$ is assumed to be a \kbd{QX}, $V$ is given implicitly by a numerator \kbd{nV} (\kbd{ZV}) and denominator \kbd{dV} (a positive \typ{INT} or \kbd{NULL} for trivial denominator). Not memory clean, but suitable for \kbd{gerepileupto}. \fun{GEN}{QXV_QXQ_eval}{GEN v, GEN a, GEN T} $v$ is a vector of \kbd{QX}s (possibly scalars, i.e.~rational numbers, for convenience), $a$ and $T$ both \kbd{QX}. Return the vector of evaluations at $a$ modulo $T$. Not memory clean, nor suitable for \kbd{gerepileupto}. \fun{GEN}{QXX_QXQ_eval}{GEN P, GEN a, GEN T} $P(X,Y)$ is a \typ{POL} with \kbd{QX} coefficients (possibly scalars, i.e.~rational numbers, for convenience) , $a$ and $T$ both \kbd{QX}. Return the \kbd{QX} $P(X, a \mod T)$. Not memory clean, nor suitable for \kbd{gerepileupto}. \fun{GEN}{nfgcd}{GEN P, GEN Q, GEN T, GEN den} given $P$ and $Q$ in $\Z[X,Y]$, $T$ monic irreducible in $\Z[Y]$, returns the primitive $d$ in $\Z[X,Y]$ which is a gcd of $P$, $Q$ in $K[X]$, where $K$ is the number field $\Q[Y]/(T)$. If not \kbd{NULL}, \kbd{den} is a multiple of the integral denominator of the (monic) gcd of $P,Q$ in $K[X]$. \fun{GEN}{nfgcd_all}{GEN P, GEN Q, GEN T, GEN den, GEN *Pnew} as \kbd{nfgcd}. If \kbd{Pnew} is not \kbd{NULL}, set \kbd{*Pnew} to a non-zero integer multiple of $P/d$. If $P$ and $Q$ are both monic, then $d$ is monic and \kbd{*Pnew} is exactly $P/d$. Not memory clean if the gcd is $1$ (in that case \kbd{*Pnew} is set to $P$). \subsec{\kbd{zx}} \fun{GEN}{zero_zx}{long sv} returns a zero \kbd{zx} in variable $v$. \fun{GEN}{polx_zx}{long sv} returns the variable $v$ as degree~1~\kbd{Flx}. \fun{GEN}{zx_renormalize}{GEN x, long l}, as \kbd{Flx\_renormalize}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{zx_shift}{GEN T, long n} returns \kbd{T} multiplied by $\kbd{x}^n$, assuming $n\geq 0$. \subsec{\kbd{RgX}} \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 (e.g. $\F_p$ and $\F_q$ for primes $p\neq q$, $\F_p[X]/(T)$ and $\F_p[X]/(U)$ for $T\neq U$). Minor discrepancies are supported if they make general sense (e.g. $\F_p$ and $\F_{p^k}$, but not $\F_p$ and $\Q_p$); \typ{FFELT} and \typ{POLMOD} of \typ{INTMOD}s are considered inconsistent, even if they define the same field: if you need to use simultaneously these different finite field implementations, multiply the polynomial by a \typ{FFELT} equal to $1$ first. \item 0: none of the others (presumably multivariate, possibly inconsistent). \item \typ{INT}: defined over $\Q$ (not necessarily $\Z$). \item \typ{INTMOD}: defined over $\Z/p\Z$, where \kbd{*ptp} is set to $p$. It is not checked whether $p$ is prime. \item \typ{COMPLEX}: defined over $\C$ (at least one \typ{COMPLEX} with at least one inexact floating point \typ{REAL} component). Set \kbd{*ptprec} to the minimal accuracy (as per \kbd{precision}) of inexact components. \item \typ{REAL}: defined over $\R$ (at least one inexact floating point \typ{REAL} component). Set \kbd{*ptprec} to the minimal accuracy (as per \kbd{precision}) of inexact components. \item \typ{PADIC}: defined over $\Q_p$, where \kbd{*ptp} is set to $p$ and \kbd{*ptprec} to the $p$-adic accuracy. \item \typ{FFELT}: defined over a finite field $\F_{p^k}$, where \kbd{*ptp} is set to the field characteristic $p$ and \kbd{*ptpol} is set to a \typ{FFELT} belonging to the field. \item other values are composite corresponding to quotients $R[X]/(T)$, with one primary type \kbd{t1}, describing the form of the quotient, and a secondary type \kbd{t2}, describing $R$. If \kbd{t} is the \kbd{RgX\_type}, \kbd{t1} and \kbd{t2} are recovered using \fun{void}{RgX_type_decode}{long t, long *t1, long *t2} \kbd{t1} is one of \typ{POLMOD}: at least one \typ{POLMOD} component, set \kbd{*ppol} to the modulus, \typ{QUAD}: no \typ{POLMOD}, at least one \typ{QUAD} component, set \kbd{*ppol} to the modulus (\kbd{$-$.pol}) of the \typ{QUAD}, \typ{COMPLEX}: no \typ{POLMOD} or \typ{QUAD}, at least one \typ{COMPLEX} component, set \kbd{*ppol} to $y^2 + 1$. and the underlying base ring $R$ is given by \kbd{t2}, which is one of \typ{INT}, \typ{INTMOD} (set \kbd{*ptp}) or \typ{PADIC} (set \kbd{*ptp} and \kbd{*ptprec}), with the same meaning as above. \fun{int}{RgX_type_is_composite}{long t} $t$ as returned by \kbd{RgX\_type}, return 1 if $t$ is a composite type, and 0 otherwise. \fun{GEN}{RgX_get_0}{GEN x} returns $0$ in the base ring over which $x$ is defined, to the proper accuracy (e.g. \kbd{0}, \kbd{Mod(0,3)}, \kbd{O(5\pow 10)}). \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)}, \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_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. \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}. \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. \fun{GEN}{RgX_copy}{GEN x} returns (a deep copy of) $\kbd{x}$. \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}. \fun{GEN}{RgX_neg}{GEN x} returns $-\kbd{x}$. \fun{GEN}{RgX_Rg_add}{GEN y, GEN x} returns $x+y$. \fun{GEN}{RgX_Rg_add_shallow}{GEN y, GEN x} returns $x+y$; shallow function. \fun{GEN}{Rg_RgX_sub}{GEN x, GEN y} \fun{GEN}{RgX_Rg_sub}{GEN y, GEN x} returns $x-y$ \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. \fun{GEN}{RgX_mul_normalized}{GEN A, long a, GEN B, long b} returns $(X^a + A)(X^b + B) - X^(a+b)$, where we assume that $\deg A < a$ and $\deg B < b$ are polynomials in the same variable $X$. \fun{GEN}{RgX_mulspec}{GEN a, GEN b, long na, long nb}. Internal routine: \kbd{a} and \kbd{b} are arrays of coefficients representing polynomials $\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. \fun{GEN}{RgX_sqrspec}{GEN a, long na}. Internal routine: \kbd{a} is an array of coefficients representing polynomial $\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 \item \kbd{NULL}: do not store the remainder, used to implement \kbd{RgX\_div}, \item \tet{ONLY_REM}: return the remainder, used to implement \kbd{RgX\_rem}, \item \tet{ONLY_DIVIDES}: return the quotient if the division is exact, and \kbd{NULL} otherwise. \fun{GEN}{RgX_div}{GEN x, GEN y} \fun{GEN}{RgX_div_by_X_x}{GEN A, GEN a, GEN *r} returns the quotient of the \kbd{RgX}~\kbd{A} by $(X - \kbd{a})$, and sets \kbd{r} to the remainder $\kbd{A}(\kbd{a})$. \fun{GEN}{RgX_rem}{GEN x, GEN y} \fun{GEN}{RgX_pseudodivrem}{GEN x, GEN y, GEN *ptr} compute a pseudo-quotient $q$ and pseudo-remainder $r$ such that $\kbd{lc}(y)^{\deg(x) - \deg(y) + 1}x = qy + r$. Return $q$ and set \kbd{*ptr} to $r$. \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)$. \fun{int}{ZXQX_dvd}{GEN x, GEN y, GEN T} let $T$ be a monic irreducible \kbd{ZX}, let $x, y$ be \typ{POL} whose coefficients are either \typ{INT}s or \kbd{ZX} in the same variable as $T$. Assume further that the leading coefficient of $y$ is an integer. Return $1$ if $y | x$ in $(\Z[Y]/(T))[X]$, and $0$ otherwise. \fun{GEN}{RgXQX_pseudodivrem}{GEN x, GEN y, GEN T, GEN *ptr} compute a pseudo-quotient $q$ and pseudo-remainder $r$ such that $\kbd{lc}(y)^{\deg(x) - \deg(y) + 1}x = qy + r$ in $R[X]/(T)$. Return $q$ and set \kbd{*ptr} to $r$. \fun{GEN}{RgX_mulXn}{GEN x, long n} returns $\kbd{x} * t^n$. This may 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); @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. \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. \fun{GEN}{RgX_gcd_simple}{GEN x, GEN y} as \tet{RgX_gcd} using a standard extended Euclidean algorithm. Usually slower than \tet{RgX_gcd}. \fun{GEN}{RgX_extgcd}{GEN x, GEN y, GEN *u, GEN *v} returns $d = \text{GCD}(\kbd{x},\kbd{y})$, and sets \kbd{*u}, \kbd{*v} to the Bezout coefficients such that $\kbd{*ux} + \kbd{*vy} = d$. Uses a generic subresultant algorithm. \fun{GEN}{RgX_extgcd_simple}{GEN x, GEN y, GEN *u, GEN *v} as \tet{RgX_extgcd} using a standard extended Euclidean algorithm. Usually slower than \tet{RgX_extgcd}. \fun{GEN}{RgX_disc}{GEN x} returns the discriminant of the \typ{POL} \kbd{x} with respect to its main variable. \fun{GEN}{RgX_resultant_all}{GEN x, GEN y, GEN *sol} returns \kbd{resultant(x,y)}. If \kbd{sol} is not \kbd{NULL}, sets it to the last non-constant remainder in the polynomial remainder sequence if it exists and to \kbd{gen\_0} otherwise (e.g. one polynomial has degree 0). Compared 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)}$. \fun{GEN}{RgX_gtofp}{GEN x, GEN prec} returns the polynomial obtained by applying \bprog gtofp(gel(x,i), prec) @eprog\noindent to all coefficients of $x$. \fun{GEN}{RgX_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog 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_inflate}{GEN P, long d} return $P(X^d)$. Shallow function, not suitable for \kbd{gerepileupto}. \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 stack. Suitable but inefficient for \kbd{gerepileupto}.) \fun{GEN}{RgX_unscale}{GEN P, GEN h} returns $P(h x)$. (Leaves small objects 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{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$. \smallskip \fun{GEN}{RgXQ_mul}{GEN y, GEN x, GEN T} computes $xy$ mod $T$ \fun{GEN}{RgXQ_sqr}{GEN x, GEN T} computes $x^2$ mod $T$ \fun{GEN}{RgXQ_inv}{GEN x, GEN T} return the inverse of $x$ mod $T$. \fun{GEN}{RgXQ_pow}{GEN x, GEN n, GEN T} computes $x^n$ mod $T$ \fun{GEN}{RgXQ_powu}{GEN x, ulong n, GEN T} computes $x^n$ mod $T$, $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{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 \item $P \equiv Q x$ modulo $T$, \item $\deg P \leq \kbd{amax}$, $\deg Q \leq \kbd{bmax}$, \item $\gcd(T,P) = \gcd(P,Q)$. \noindent If unsuccessful, the routine returns $0$ and leaves $P$, $Q$ unchanged; otherwise it returns $1$ and sets $P$ and $Q$. \fun{GEN}{RgXQ_reverse}{GEN f, GEN T} returns a \typ{POL} $g$ of degree $< n = \text{deg}~T$ such that $T(x)$ divides $(g \circ f)(x) - x$, by solving a linear system. Low-level function underlying \tet{modreverse}: it returns a lift of \kbd[modreverse(f,T)]; faster than the high-level function since it 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)))$. \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 \kbd{RgXQ}s (applying \kbd{grem} coefficientwise) in a \typ{COL}. \fun{GEN}{RgXQV_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) in a \typ{VEC}. \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}. \fun{GEN}{RgXQX_sqr}{GEN x, GEN T} \fun{GEN}{RgXQX_divrem}{GEN x, GEN y, GEN T, GEN *pr} \fun{GEN}{RgXQX_div}{GEN x, GEN y, GEN T, GEN *r} \fun{GEN}{RgXQX_rem}{GEN x, GEN y, GEN T, GEN *r} \newpage \chapter{Operations on general PARI objects} \section{Assignment} It is in general easier to use a direct conversion, e.g.~\kbd{y = stoi(s)}, than to allocate a target of correct type and sufficient size, then assign to it: \bprog GEN y = cgeti(3); affsi(s, y); @eprog\noindent These functions can still be moderately useful in complicated garbage collecting scenarios but you will be better off not using them. \fun{void}{gaffsg}{long s, GEN x} assigns the \kbd{long}~\kbd{s} into the object~\kbd{x}. \fun{void}{gaffect}{GEN x, GEN y} assigns the object \kbd{x} into the object~\kbd{y}. Both \kbd{x} and \kbd{y} must be scalar types. Type conversions (e.g.~from \typ{INT} to \typ{REAL} or \typ{INTMOD}) occur if legitimate. \fun{int}{is_universal_constant}{GEN x} returns $1$ if $x$ is a global PARI constant you should never assign to (such as \kbd{gen\_1}), and $0$ otherwise. \section{Conversions} \subsec{Scalars} \fun{double}{rtodbl}{GEN x} applied to a \typ{REAL}~\kbd{x}, converts \kbd{x} into a \kbd{double} if possible. \fun{GEN}{dbltor}{double x} converts the \kbd{double} \kbd{x} into a \typ{REAL}. \fun{long}{dblexpo}{double x} returns \kbd{expo(dbltor(x))}, but faster and without cluttering the stack. \fun{ulong}{dblmantissa}{double x} returns the most significant word in the mantissa of \kbd{dbltor(x)}. \fun{double}{gtodouble}{GEN x} if \kbd{x} is a real number (not necessarily a~\typ{REAL}), converts \kbd{x} into a \kbd{double} if possible. \fun{long}{gtos}{GEN x} converts the \typ{INT} \kbd{x} to a small integer if possible, otherwise raise an exception. This function is similar to \tet{itos}, slightly slower since it checks the type of \kbd{x}. \fun{double}{dbllog2r}{GEN x} assuming \kbd{x} is a non-zero \typ{REAL}, returns an approximation to \kbd{log2(|x|)}. \fun{long}{gtolong}{GEN x} if \kbd{x} is an integer (not necessarily a~\typ{INT}), converts \kbd{x} into a \kbd{long} if possible. \fun{GEN}{fractor}{GEN x, long l} applied to a \typ{FRAC}~\kbd{x}, converts \kbd{x} into a \typ{REAL} of length \kbd{prec}. \fun{GEN}{quadtofp}{GEN x, long l} applied to a \typ{QUAD}~\kbd{x}, converts \kbd{x} into a \typ{REAL} or \typ{COMPLEX} depending on the sign of the discriminant of~\kbd{x}, to precision \hbox{\kbd{l} \B-bit} words. % forbid line brk at hyphen here [GN] \fun{GEN}{cxtofp}{GEN x, long prec} converts the \typ{COMPLEX}~\kbd{x} to a a complex whose real and imaginary parts are \typ{REAL} of length \kbd{prec} (special case of~\kbd{gtofp}. \fun{GEN}{cxcompotor}{GEN x, long prec} converts the \typ{INT}, \typ{REAL} or \typ{FRAC} $x$ to a \typ{REAL} of length \kbd{prec}. These are all the real types which may occur as components of a \typ{COMPLEX}; special case of~\kbd{gtofp} (introduced so that the latter is not recursive and can thus be inlined). \fun{GEN}{gtofp}{GEN x, long prec} converts the complex number~\kbd{x} (\typ{INT}, \typ{REAL}, \typ{FRAC}, \typ{QUAD} or \typ{COMPLEX}) to either a \typ{REAL} or \typ{COMPLEX} whose components are \typ{REAL} of precision \kbd{prec}; not necessarily of \emph{length} \kbd{prec}: a real $0$ may be given as \kbd{real\_0(...)}). If the result is a \typ{COMPLEX} extra care is taken so that its modulus really has accuracy \kbd{prec}: there is a problem if the real part of the input is an exact $0$; indeed, converting it to \kbd{real\_0(prec)} would be wrong if the imaginary part is tiny, since the modulus would then become equal to $0$, as in $1.E-100 + 0.E-28 = 0.E-28$. \fun{GEN}{gtomp}{GEN z, long prec} converts the real number~\kbd{x} (\typ{INT}, \typ{REAL}, \typ{FRAC}, real \typ{QUAD}) to either a \typ{INT} or a \typ{REAL} of precision \kbd{prec}. Not memory clean if $x$ is a \typ{INT}: we return $x$ itself and not a copy. \fun{GEN}{gcvtop}{GEN x, GEN p, long l} converts $x$ into a \typ{PADIC} of precision~$l$. Works componentwise on recursive objects, e.g.~\typ{POL} or \typ{VEC}. Converting $0$ yields $O(p^l)$; converting a non-zero number yield a result well defined modulo $p^{v_p(x) + l}$. \fun{GEN}{cvtop}{GEN x, GEN p, long l} as \kbd{gcvtop}, assuming that $x$ is a scalar. \fun{GEN}{cvtop2}{GEN x, GEN y} $y$ being a $p$-adic, converts the scalar $x$ to a $p$-adic of the same accuracy. Shallow function. \fun{GEN}{cvstop2}{long s, GEN y} $y$ being a $p$-adic, converts the scalar $s$ to a $p$-adic of the same accuracy. Shallow function. \fun{GEN}{gprec}{GEN x, long l} returns a copy of $x$ whose precision is changed to $l$ digits. The precision change is done recursively on all components of $x$. Digits means \emph{decimal}, $p$-adic and $X$-adic digits for \typ{REAL}, \typ{SER}, \typ{PADIC} components, respectively. \fun{GEN}{gprec_w}{GEN x, long l} returns a shallow copy of $x$ whose \typ{REAL} components have their precision changed to $l$ \emph{words}. This is often more useful than \kbd{gprec}. \fun{GEN}{gprec_wtrunc}{GEN x, long l} returns a shallow copy of $x$ whose \typ{REAL} components have their precision \emph{truncated} to $l$ \emph{words}. Contrary to \kbd{gprec\_w}, this function may never increase the precision of~$x$. \subsec{Modular objects / lifts} \fun{GEN}{gmodulo}{GEN x, GEN y} creates the object \kbd{\key{Mod}(x,y)} on the PARI stack, where \kbd{x} and \kbd{y} are either both \typ{INT}s, and the result is a \typ{INTMOD}, or \kbd{x} is a scalar or a \typ{POL} and \kbd{y} a \typ{POL}, and the result is a \typ{POLMOD}. \fun{GEN}{gmodulgs}{GEN x, long y} same as \key{gmodulo} except \kbd{y} is a \kbd{long}. \fun{GEN}{gmodulsg}{long x, GEN y} same as \key{gmodulo} except \kbd{x} is a \kbd{long}. \fun{GEN}{gmodulss}{long x, long y} same as \key{gmodulo} except both \kbd{x} and \kbd{y} are \kbd{long}s. \fun{GEN}{liftall_shallow}{GEN x} shallow version of \tet{liftall} \fun{GEN}{liftint_shallow}{GEN x} shallow version of \tet{liftint} \fun{GEN}{liftpol_shallow}{GEN x} shallow version of \tet{liftpol} \fun{GEN}{centerlift0}{GEN x,long v} DEPRECATED, kept for backward compatibility only: use either \tet{lift0}$(x,v)$ or \tet{centerlift}$(x)$. \subsec{Between polynomials and coefficient arrays} \fun{GEN}{gtopoly}{GEN x, long v} converts or truncates the object~\kbd{x} into a \typ{POL} with main variable number~\kbd{v}. A common application would be the conversion of coefficient vectors (coefficients are given by decreasing degree). E.g.~\kbd{[2,3]} goes to \kbd{2*v + 3} \fun{GEN}{gtopolyrev}{GEN x, long v} converts or truncates the object~\kbd{x} into a \typ{POL} with main variable number~\kbd{v}, but vectors are converted in reverse order compared to \kbd{gtopoly} (coefficients are given by increasing degree). E.g.~\kbd{[2,3]} goes to \kbd{3*v + 2}. In other words the vector represents a polynomial in the basis $(1,v,v^2,v^3,\dots)$. \fun{GEN}{normalizepol}{GEN x} applied to an unnormalized \typ{POL}~\kbd{x} (with all coefficients correctly set except that \kbd{leading\_term(x)} might be zero), normalizes \kbd{x} correctly in place and returns~\kbd{x}. For internal use. Normalizing means deleting all leading \emph{exact} zeroes (as per \kbd{isexactzero}), except if the polynomial turns out to be $0$, in which case we try to find a coefficient $c$ which is a non-rational zero, and return the constant polynomial $c$. (We do this so that information about the base ring is not lost.) \fun{GEN}{normalizepol_lg}{GEN x, long l} applies \kbd{normalizepol} to \kbd{x}, pretending that \kbd{lg(x)} is $l$, which must be less than or equal to \kbd{lg(x)}. If equal, the function is equivalent to \kbd{normalizepol(x)}. \fun{GEN}{normalizepol_approx}{GEN x, long lx} as \kbd{normalizepol\_lg}, with the difference that we just delete all leading zeroes (as per \kbd{gequal0}). This rougher normalization is used when we have no other choice, for instance before attempting a Euclidean division by $x$. The following routines do \emph{not} copy coefficients on the stack (they only move pointers around), hence are very fast but not suitable for \kbd{gerepile} calls. Recall that an \kbd{RgV} (resp.~an \kbd{RgX}, resp.~an \kbd{RgM}) is a \typ{VEC} or \typ{COL} (resp.~a \typ{POL}, resp.~a \typ{MAT}) with arbitrary components. Similarly, an \kbd{RgXV} is a \typ{VEC} or \typ{COL} with \kbd{RgX} components, etc. \fun{GEN}{RgV_to_RgX}{GEN x, long v} converts the \kbd{RgV}~\kbd{x} to a (normalized) polynomial in variable~\kbd{v} (as \kbd{gtopolyrev}, without copy). \fun{GEN}{RgV_to_RgX_reverse}{GEN x, long v} converts the \kbd{RgV}~\kbd{x} 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 \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 types than \typ{POL} are allowed for \kbd{x}, which is then considered as a constant polynomial. \fun{GEN}{RgM_to_RgXV}{GEN x, long v} converts the \kbd{RgM}~\kbd{x} to a \typ{VEC} of \kbd{RgX}, by repeated calls to \kbd{RgV\_to\_RgX}. \fun{GEN}{RgV_to_RgM}{GEN v, long N} converts the vector~\kbd{v} to a~\typ{MAT} with \kbd{N}~rows, by repeated calls to \kbd{Rg\_to\_RgV}. \fun{GEN}{RgXV_to_RgM}{GEN v, long N} converts the vector of \kbd{RgX}~\kbd{v} to a~\typ{MAT} with \kbd{N}~rows, by repeated calls to \kbd{RgX\_to\_RgV}. \fun{GEN}{RgM_to_RgXX}{GEN x, long v,long w} converts the \kbd{RgM}~\kbd{x} into a \typ{POL} in variable~\kbd{v}, whose coefficients are \typ{POL}s in variable~\kbd{w}. This is a shortcut for \bprog RgV_to_RgX( RgM_to_RgXV(x, w), v ); @eprog\noindent There are no consistency checks with respect to variable 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{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 $\deg_v(\kbd{P})$. \fun{GEN}{RgXY_swapspec}{GEN C, long n, long w, long lP} as \kbd{RgXY\_swap} where the coefficients of $P$ are given by \kbd{gel(C,0),\dots,gel(C,lP-1)}. \fun{GEN}{RgX_to_ser}{GEN x, long l} applied to a \typ{POL}~\kbd{x}, creates a \emph{shallow} \typ{SER} of length~$l\geq 2$ starting with~\kbd{x}. Unless the polynomial is an exact zero, the coefficient of lowest degree $T^d$ of the result is not an exact zero (as per \kbd{isexactzero}). The remainder is $O(T^{d+l})$. \fun{GEN}{RgX_to_ser_inexact}{GEN x, long l} applied to a \typ{POL}~\kbd{x}, creates a \emph{shallow} \typ{SER} of length~\kbd{l} starting with~\kbd{x}. Unless the polynomial is zero, the coefficient of lowest degree $T^d$ of the result is not zero (as per \kbd{gequal0}). The remainder is $O(T^{d+l})$. \fun{GEN}{rfrac_to_ser}{GEN x, long l} applied to a \typ{RFRAC}~\kbd{x}, creates a \typ{SER} of length~\kbd{l} congruent to $x$. Not memory-clean but suitable for \kbd{gerepileupto}. \fun{GEN}{gtoser}{GEN s, long v, long d} converts the object~$s$ into a \typ{SER} with main variable number~\kbd{v} and $d > 0$ significant terms. More precisely \item if $s$ is a scalar, we return a constant power series with $d$ significant terms. \item if $s$ is a \typ{POL}, it is truncated to $d$ terms if needed. \item If $s$ is a vector, the coefficients of the vector are understood to be the coefficients of the power series starting from the constant term (as in \tet{Polrev}), and the precision $d$ is \emph{ignored}. \item If $s$ is already a power series in $v$, we retur a copy, and the precision $d$ is again \emph{ignored}. \fun{GEN}{gtocol}{GEN x} converts the object~\kbd{x} into a \typ{COL} \fun{GEN}{gtomat}{GEN x} converts the object~\kbd{x} into a \typ{MAT}. \fun{GEN}{gtovec}{GEN x} converts the object~\kbd{x} into a \typ{VEC}. \fun{GEN}{gtovecsmall}{GEN x} converts the object~\kbd{x} into a \typ{VECSMALL}. \fun{GEN}{normalize}{GEN x} applied to an unnormalized \typ{SER}~\kbd{x} (i.e.~type \typ{SER} with all coefficients correctly set except that \kbd{x[2]} might be zero), normalizes \kbd{x} correctly in place. Returns~\kbd{x}. For internal use. \fun{GEN}{serchop0}{GEN s} given a \typ{SER} of the form $x^v s(x)$, with $s(0)\neq 0$, return $x^v(s - s(0))$. Shallow function. \section{Constructors} \subsec{Clean constructors}\label{se:clean} \fun{GEN}{zeropadic}{GEN p, long n} creates a $0$ \typ{PADIC} equal to $O(\kbd{p}^\kbd{n})$. \fun{GEN}{zeroser}{long v, long n} creates a $0$ \typ{SER} in variable \kbd{v} equal to $O(X^\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. \fun{GEN}{pol_0}{long v} Returns the constant polynomial $0$ in variable $v$. \fun{GEN}{pol_1}{long v} Returns the constant polynomial $1$ in variable $v$. \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. \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}. \fun{GEN}{deg1pol}{GEN a, GEN b,long v} creates the degree 1 \typ{POL} $a \kbd{pol\_x}(v) + b$ \fun{GEN}{zeropol}{long v} is identical \kbd{pol\_0}. \fun{GEN}{zerocol}{long n} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{zerovec}{long n} creates a \typ{VEC} with \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{col_ei}{long n, long i} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{gen\_1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{vec_ei}{long n, long i} creates a \typ{VEC} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{gen\_1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{trivial_fact}{void} returns the trivial (empty) factorization \kbd{Mat([]\til,[]\til)} \fun{GEN}{prime_fact}{GEN x} returns the factorization \kbd{Mat([x]\til, [1]\til)} \fun{GEN}{Rg_col_ei}{GEN x, long n, long i} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{x}. \fun{GEN}{vecsmall_ei}{long n, long i} creates a \typ{VECSMALL} with \kbd{n} components set to \kbd{0}, but for the \kbd{i}-th one which is set to \kbd{1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{scalarcol}{GEN x, long n} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but the first one which is set to a copy of \kbd{x}. (The name comes from \kbd{RgV\_isscalar}.) \smallskip \fun{GEN}{mkintmodu}{ulong x, ulong y} creates the \typ{INTMOD} \kbd{Mod(x, y)}. The inputs must satisfy $x < y$. \fun{GEN}{zeromat}{long m, long n} creates a \typ{MAT} with \kbd{m} x \kbd{n} components set to \kbd{gen\_0}. Note that the result allocates a \emph{single} column, so modifying an entry in one column modifies it in all columns. To fully allocate a matrix initialized with zero entries, use \kbd{zeromatcopy}. \fun{GEN}{zeromatcopy}{long m, long n} creates a \typ{MAT} with \kbd{m} x \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{matid}{long n} identity matrix in dimension \kbd{n} (with components \kbd{gen\_1} and\kbd{gen\_0}). \fun{GEN}{scalarmat}{GEN x, long n} scalar matrix, \kbd{x} times the identity. \fun{GEN}{scalarmat_s}{long x, long n} scalar matrix, \kbd{stoi(x)} times the identity. \fun{GEN}{vecrange}{GEN a, GEN b} returns the \typ{VEC} $[a..b]$. \fun{GEN}{vecrangess}{long a, long b} returns the \typ{VEC} $[a..b]$. \smallskip See also next section for analogs of the following functions: \fun{GEN}{mkfraccopy}{GEN x, GEN y} creates the \typ{FRAC} $x/y$. Assumes that $y > 1$ and $(x,y) = 1$. \fun{GEN}{mkrfraccopy}{GEN x, GEN y} creates the \typ{RFRAC} $x/y$. Assumes that $y$ is a \typ{POL}, $x$ a compatible type whose variable has lower or same priority, with $(x,y) = 1$. \fun{GEN}{mkcolcopy}{GEN x} creates a 1-dimensional \typ{COL} containing \kbd{x}. \fun{GEN}{mkmatcopy}{GEN x} creates a 1-by-1 \typ{MAT} wrapping the \typ{COL} \kbd{x}. \fun{GEN}{mkveccopy}{GEN x} creates a 1-dimensional \typ{VEC} containing \kbd{x}. \fun{GEN}{mkvec2copy}{GEN x, GEN y} creates a 2-dimensional \typ{VEC} equal to \kbd{[x,y]}. \fun{GEN}{mkcols}{long x} creates a 1-dimensional \typ{COL} containing \kbd{stoi(x)}. \fun{GEN}{mkcol2s}{long x, long y} creates a 2-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y)]~}. \fun{GEN}{mkcol3s}{long x, long y, long z} creates a 3-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y), stoi(z)]~}. \fun{GEN}{mkcol4s}{long x, long y, long z, long t} creates a 4-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y), stoi(z), stoi(t)]~}. \fun{GEN}{mkvecs}{long x} creates a 1-dimensional \typ{VEC} containing \kbd{stoi(x)}. \fun{GEN}{mkvec2s}{long x, long y} creates a 2-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y)]}. \fun{GEN}{mkvec3s}{long x, long y, long z} creates a 3-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y), stoi(z)]}. \fun{GEN}{mkvec4s}{long x, long y, long z, long t} creates a 4-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y), stoi(z), stoi(t)]}. \fun{GEN}{mkvecsmall}{long x} creates a 1-dimensional \typ{VECSMALL} containing \kbd{x}. \fun{GEN}{mkvecsmall2}{long x, long y} creates a 2-dimensional \typ{VECSMALL} containing \kbd{[x, y]}. \fun{GEN}{mkvecsmall3}{long x, long y, long z} creates a 3-dimensional \typ{VECSMALL} containing \kbd{[x, y, z]}. \fun{GEN}{mkvecsmall4}{long x, long y, long z, long t} creates a 4-dimensional \typ{VECSMALL} containing \kbd{[x, y, z, t]}. \fun{GEN}{mkvecsmalln}{long n, ...} returns the \typ{VECSMALL} whose $n$ coefficients (\kbd{long}) follow. \subsec{Unclean constructors}\label{se:unclean} Contrary to the policy of general PARI functions, the functions in this subsection do \emph{not} copy their arguments, nor do they produce an object a priori suitable for \tet{gerepileupto}. In particular, they are faster than their clean equivalent (which may not exist). \emph{If} you restrict their arguments to universal objects (e.g \kbd{gen\_0}), then the above warning does not apply. \fun{GEN}{mkcomplex}{GEN x, GEN y} creates the \typ{COMPLEX} $x + iy$. \fun{GEN}{mulcxI}{GEN x} creates the \typ{COMPLEX} $ix$. The result in general contains data pointing back to the original $x$. Use \kbd{gcopy} if this is a problem. But in most cases, the result is to be used immediately, before $x$ is subject to garbage collection. \fun{GEN}{mulcxmI}{GEN x}, as \tet{mulcxI}, but returns the \typ{COMPLEX} $-ix$. \fun{GEN}{mkquad}{GEN n, GEN x, GEN y} creates the \typ{QUAD} $x + yw$, where $w$ is a root of $n$, which is of the form \kbd{quadpoly(D)}. \fun{GEN}{mkfrac}{GEN x, GEN y} creates the \typ{FRAC} $x/y$. Assumes that $y > 1$ and $(x,y) = 1$. \fun{GEN}{mkrfrac}{GEN x, GEN y} creates the \typ{RFRAC} $x/y$. Assumes that $y$ is a \typ{POL}, $x$ a compatible type whose variable has lower or same priority, with $(x,y) = 1$. \fun{GEN}{mkcol}{GEN x} creates a 1-dimensional \typ{COL} containing \kbd{x}. \fun{GEN}{mkcol2}{GEN x, GEN y} creates a 2-dimensional \typ{COL} equal to \kbd{[x,y]}. \fun{GEN}{mkcol3}{GEN x, GEN y, GEN z} creates a 3-dimensional \typ{COL} equal to \kbd{[x,y,z]}. \fun{GEN}{mkcol4}{GEN x, GEN y, GEN z, GEN t} creates a 4-dimensional \typ{COL} 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}{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$. \fun{GEN}{mkpolmod}{GEN x, GEN y} creates the \typ{POLMOD} \kbd{Mod(x, y)}. The input must satisfy $\deg x < \deg y$ with respect to the main variable of the \typ{POL} $y$. $x$ may be a scalar. \fun{GEN}{mkmat}{GEN x} creates a 1-column \typ{MAT} with column $x$ (a \typ{COL}). \fun{GEN}{mkmat2}{GEN x, GEN y} creates a 2-column \typ{MAT} with columns $x$, $y$ (\typ{COL}s of the same length). \fun{GEN}{mkmat3}{GEN x, GEN y, GEN z} creates a 3-column \typ{MAT} with columns $x$, $y$, $z$ (\typ{COL}s of the same length). \fun{GEN}{mkmat4}{GEN x, GEN y, GEN z, GEN t} creates a 4-column \typ{MAT} with columns $x$, $y$, $z$, $t$ (\typ{COL}s of the same length). \fun{GEN}{mkmat5}{GEN x, GEN y, GEN z, GEN t, GEN u} creates a 5-column \typ{MAT} with columns $x$, $y$, $z$, $t$, $u$ (\typ{COL}s of the same length). \fun{GEN}{mkvec}{GEN x} creates a 1-dimensional \typ{VEC} containing \kbd{x}. \fun{GEN}{mkvec2}{GEN x, GEN y} creates a 2-dimensional \typ{VEC} equal to \kbd{[x,y]}. \fun{GEN}{mkvec3}{GEN x, GEN y, GEN z} creates a 3-dimensional \typ{VEC} equal to \kbd{[x,y,z]}. \fun{GEN}{mkvec4}{GEN x, GEN y, GEN z, GEN t} creates a 4-dimensional \typ{VEC} equal to \kbd{[x,y,z,t]}. \fun{GEN}{mkvec5}{GEN a1, GEN a2, GEN a3, GEN a4, GEN a5} creates the 5-dimensional \typ{VEC} equal to $[a_1,a_2,a_3,a_4,a_5]$. \fun{GEN}{mkqfi}{GEN x, GEN y, GEN z} creates \typ{QFI} equal to \kbd{Qfb(x,y,z)}, assuming that $y^2 - 4xz < 0$. \fun{GEN}{mkerr}{long n} returns a \typ{ERROR} with error code $n$ (\kbd{enum err\_list}). \smallskip It is sometimes useful to return such a container whose entries are not universal objects, but nonetheless suitable for \tet{gerepileupto}. If the entries can be computed at the time the result is returned, the following macros achieve this effect: \fun{GEN}{retmkvec}{GEN x} returns a vector containing the single entry $x$, where the vector root is created just before the function argument $x$ is evaluated. Expands to \bprog { GEN res = cgetg(2, t_VEC); gel(res, 1) = x; /* @Ccom or rather, the \emph{expansion} of $x$ */ return res; } @eprog\noindent For instance, the \kbd{retmkvec(gcopy(x))} returns a clean object, just like \kbd{return mkveccopy(x)} would. \fun{GEN}{retmkvec2}{GEN x, GEN y} returns the $2$-dimensional \typ{VEC} \kbd{[x,y]}. \fun{GEN}{retmkvec3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{VEC} \kbd{[x,y,z]}. \fun{GEN}{retmkvec4}{GEN x, GEN y, GEN z, GEN t} returns the $4$-dimensional \typ{VEC} \kbd{[x,y,z,t]}. \fun{GEN}{retmkvec5}{GEN x, GEN y, GEN z, GEN t, GEN u} returns the $5$-dimensional row vector \kbd{[x,y,z,t,u]}. \fun{GEN}{retconst_vec}{long n, GEN x} returns the $n$-dimensional \typ{VEC} whose entries are constant and all equal to $x$. \fun{GEN}{retmkcol}{GEN x} returns the $1$-dimensional \typ{COL} \kbd{[x]~}. \fun{GEN}{retmkcol2}{GEN x, GEN y} returns the $2$-dimensional \typ{COL} \kbd{[x,y]~}. \fun{GEN}{retmkcol3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{COL} \kbd{[x,y,z]~}. \fun{GEN}{retmkcol4}{GEN x, GEN y, GEN z, GEN t} 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}{retconst_col}{long n, GEN x} returns the $n$-dimensional \typ{COL} whose entries are constant and all equal to $x$. \fun{GEN}{retmkmat}{GEN x} returns the $1$-column \typ{MAT} with colum \kbd{x}. \fun{GEN}{retmkmat2}{GEN x, GEN y} returns the $2$-column \typ{MAT} with columns \kbd{x}, \kbd{y}. \fun{GEN}{retmkmat3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}. \fun{GEN}{retmkmat4}{GEN x, GEN y, GEN z, GEN t} returns the $4$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}, \kbd{t}. \fun{GEN}{retmkmat5}{GEN x, GEN y, GEN z, GEN t, GEN u} returns the $5$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}, \kbd{t}, \kbd{u}. \fun{GEN}{retmkcomplex}{GEN x, GEN y} returns the \typ{COMPLEX} \kbd{x + I*y}. \fun{GEN}{retmkfrac}{GEN x, GEN y} returns the \typ{FRAC} \kbd{x / y}. Assume $x$ and $y$ are coprime and $y > 1$. \fun{GEN}{retmkintmod}{GEN x, GEN y} returns the \typ{INTMOD} \kbd{Mod(x, y)}. \fun{GEN}{retmkqfi}{GEN a, GEN b, GEN c}. \fun{GEN}{retmkqfr}{GEN a, GEN b, GEN c, GEN d}. \fun{GEN}{retmkquad}{GEN n, GEN a, GEN b}. \fun{GEN}{retmkpolmod}{GEN x, GEN y} 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). \bprog mkintn(3, a2, a1, a0); @eprog \noindent returns $a_2 2^{64} + a_1 2^{32} + a_0$. \fun{GEN}{mkpoln}{long n, ...} Returns the \typ{POL} whose $n$ coefficients (\kbd{GEN}) follow, in order of decreasing degree. \bprog mkpoln(3, gen_1, gen_2, gen_0); @eprog \noindent returns the polynomial $X^2 + 2X$ (in variable $0$, use \tet{setvarn} if you want other variable numbers). Beware that $n$ is the number of coefficients, hence \emph{one more} than the degree. \fun{GEN}{mkvecn}{long n, ...} returns the \typ{VEC} whose $n$ coefficients (\kbd{GEN}) follow. \fun{GEN}{mkcoln}{long n, ...} returns the \typ{COL} whose $n$ coefficients (\kbd{GEN}) follow. \fun{GEN}{scalarcol_shallow}{GEN x, long n} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but the first one which is set to a shallow copy of \kbd{x}. (The name comes from \kbd{RgV\_isscalar}.) \fun{GEN}{scalarmat_shallow}{GEN x, long n} creates an $n\times n$ scalar matrix whose diagonal is set to shallow copies of the scalar \kbd{x}. \fun{GEN}{diagonal_shallow}{GEN x} returns a diagonal matrix whose diagonal is given by the vector $x$. Shallow function. \fun{GEN}{scalarpol_shallow}{GEN a, long v} returns the degree 0 \typ{POL} $a \kbd{pol\_x}(v)^0$. \fun{GEN}{deg1pol_shallow}{GEN a, GEN b,long v} returns the degree 1 \typ{POL} $a\kbd{pol\_x}(v) + b$ \fun{GEN}{zeropadic_shallow}{GEN p, long n} returns a (shallow) $0$ \typ{PADIC} equal to $O(\kbd{p}^\kbd{n})$. \subsec{From roots to polynomials} \fun{GEN}{deg1_from_roots}{GEN L, long v} given a vector $L$ of scalars, returns the vector of monic linear polynomials in variable $v$ whose roots are the $L[i]$, i.e. the $x - L[i]$. \fun{GEN}{roots_from_deg1}{GEN L} given a vector $L$ of monic linear polynomials, return their roots, i.e. the $- L[i](0)$. \fun{GEN}{roots_to_pol}{GEN L, long v} given a vector of scalars $L$, returns the monic polynomial in variable $v$ whose roots are the $L[i]$. Calls \tet{divide_conquer_prod}, so leaves some garbage on stack, but suitable for \kbd{gerepileupto}. \fun{GEN}{roots_to_pol_r1}{GEN L, long v, long r1} as \kbd{roots\_to\_pol} assuming the first $r_1$ roots are ``real'', and the following ones are representatives of conjugate pairs of ``complex'' roots. So if $L$ has $r_1 + r_2$ elements, we obtain a polynomial of degree $r_1 + 2r_2$. In most applications, the roots are indeed real and complex, but the implementation assumes only that each ``complex'' root $z$ introduces a quadratic factor $X^2 - \kbd{trace}(z) X + \kbd{norm}(z)$. Calls \tet{divide_conquer_prod}. Calls \tet{divide_conquer_prod}, so leaves some garbage on stack, but suitable for \kbd{gerepileupto}. \section{Integer parts} \fun{GEN}{gfloor}{GEN x} creates the floor of~\kbd{x}, i.e.\ the (true) integral part. \fun{GEN}{gfrac}{GEN x} creates the fractional part of~\kbd{x}, i.e.\ \kbd{x} minus the floor of~\kbd{x}. \fun{GEN}{gceil}{GEN x} creates the ceiling of~\kbd{x}. \fun{GEN}{ground}{GEN x} rounds towards~$+\infty$ the components of \kbd{x} to the nearest integers. \fun{GEN}{grndtoi}{GEN x, long *e} same as \kbd{ground}, but in addition sets \kbd{*e} to the binary exponent of $x - \kbd{ground}(x)$. If this is positive, all significant bits are lost. This kind of situation raises an error message in \key{ground} but not in \key{grndtoi}. \fun{GEN}{gtrunc}{GEN x} truncates~\kbd{x}. This is the false integer part if \kbd{x} is a real number (i.e.~the unique integer closest to \kbd{x} among those between 0 and~\kbd{x}). If \kbd{x} is a \typ{SER}, it is truncated to a \typ{POL}; if \kbd{x} is a \typ{RFRAC}, this takes the polynomial part. \fun{GEN}{gtrunc2n}{GEN x, long n} creates the floor of~$2^n$\kbd{x}, this is only implemented for \typ{INT}, \typ{REAL}, \typ{FRAC} and \typ{COMPLEX} of those. \fun{GEN}{gcvtoi}{GEN x, long *e} analogous to \key{grndtoi} for \typ{REAL} inputs except that rounding is replaced by truncation. Also applies componentwise for vector or matrix inputs; otherwise, sets \kbd{*e} to \kbd{-HIGHEXPOBIT} (infinite real accuracy) and return \kbd{gtrunc(x)}. \section{Valuation and shift} \fun{GEN}{gshift[z]}{GEN x, long n[, GEN z]} yields the result of shifting (the components of) \kbd{x} left by \kbd{n} (if \kbd{n} is non-negative) or right by $-\kbd{n}$ (if \kbd{n} is negative). Applies only to \typ{INT} and vectors/matrices of such. For other types, it is simply multiplication by~$2^{\kbd{n}}$. \fun{GEN}{gmul2n[z]}{GEN x, long n[, GEN z]} yields the product of \kbd{x} and~$2^{\kbd{n}}$. This is different from \kbd{gshift} when \kbd{n} is negative and \kbd{x} is a \typ{INT}: \key{gshift} truncates, while \key{gmul2n} creates a fraction if necessary. \fun{long}{gvaluation}{GEN x, GEN p} returns the greatest exponent~$e$ such that $\kbd{p}^e$ divides~\kbd{x}, when this makes sense. \fun{long}{gval}{GEN x, long v} returns the highest power of the variable number \kbd{v} dividing the \typ{POL}~\kbd{x}. \section{Comparison operators} \subsec{Generic} \fun{long}{gcmp}{GEN x, GEN y} comparison of \kbd{x} with \kbd{y}: returns $1$ ($x > y$), $0$ ($x = y$) or $-1$ ($x < y$). Two \typ{STR} are compared using the standard lexicographic ordering; a \typ{STR} is considered strictly larger than any non-string type. If neither $x$ nor $y$ is a \typ{STR}, their allowed types are \typ{INT}, \typ{REAL} or \typ{FRAC}. Used \tet{cmp_universal} to compare arbitrary \kbd{GEN}s. \fun{long}{lexcmp}{GEN x, GEN y} comparison of \kbd{x} with \kbd{y} for the lexicographic ordering; when comparing objects of different lengths whose components are all equal up to the smallest of their length, consider that the longest is largest. Consider scalars as $1$-component vectors. Return \kbd{gcmp}$(x,y)$ if both arguments are scalars. \fun{int}{gequalX}{GEN x} return 1 (true) if \kbd{x} is a variable (monomial of degree $1$ with \typ{INT} coefficients equal to $1$ and $0$), and $0$ otherwise \fun{long}{gequal}{GEN x, GEN y} returns 1 (true) if \kbd{x} is equal to~\kbd{y}, 0~otherwise. A priori, this makes sense only if \kbd{x} and \kbd{y} have the same type, in which case they are recursively compared componentwise. When the types are different, a \kbd{true} result means that \kbd{x - y} was successfully computed and that \kbd{gequal0} found it equal to $0$. In particular \bprog gequal(cgetg(1, t_VEC), gen_0) @eprog\noindent is true, and the relation is not transitive. E.g.~an empty \typ{COL} and an empty \typ{VEC} are not equal but are both equal to \kbd{gen\_0}. \fun{long}{gidentical}{GEN x, GEN y} returns 1 (true) if \kbd{x} is identical to~\kbd{y}, 0~otherwise. In particular, the types and length of \kbd{x} and \kbd{y} must be equal. This test is much stricter than \tet{gequal}, in particular, \typ{REAL} with different accuracies are tested different. This relation is transitive. \subsec{Comparison with a small integer} \fun{int}{isexactzero}{GEN x} returns 1 (true) if \kbd{x} is exactly equal to~0 (including \typ{INTMOD}s like \kbd{Mod(0,2)}), and 0~(false) otherwise. This includes recursive objects, for instance vectors, whose components are $0$. \fun{int}{isrationalzero}{GEN x} returns 1 (true) if \kbd{x} is equal to an integer~0 (excluding \typ{INTMOD}s like \kbd{Mod(0,2)}), and 0~(false) otherwise. Contrary to \kbd{isintzero}, this includes recursive objects, for instance vectors, whose components are $0$. \fun{int}{ismpzero}{GEN x} returns 1 (true) if \kbd{x} is a \typ{INT} or a \typ{REAL} equal to~0. \fun{int}{isintzero}{GEN x} returns 1 (true) if \kbd{x} is a \typ{INT} equal to~0. \fun{int}{isint1}{GEN x} returns 1 (true) if \kbd{x} is a \typ{INT} equal to~1. \fun{int}{isintm1}{GEN x} returns 1 (true) if \kbd{x} is a \typ{INT} equal to~$-1$. \fun{int}{equali1}{GEN n} Assuming that \kbd{x} is a \typ{INT}, return 1 (true) if \kbd{x} is equal to $1$, and return 0~(false) otherwise. \fun{int}{equalim1}{GEN n} Assuming that \kbd{x} is a \typ{INT}, return 1 (true) if \kbd{x} is equal to $-1$, and return 0~(false) otherwise. \fun{int}{is_pm1}{GEN x}. Assuming that \kbd{x} is a \emph{non-zero} \typ{INT}, return 1 (true) if \kbd{x} is equal to $-1$ or $1$, and return 0~(false) otherwise. \fun{int}{gequal0}{GEN x} returns 1 (true) if \kbd{x} is equal to~0, 0~(false) otherwise. \fun{int}{gequal1}{GEN x} returns 1 (true) if \kbd{x} is equal to~1, 0~(false) otherwise. \fun{int}{gequalm1}{GEN x} returns 1 (true) if \kbd{x} is equal to~$-1$, 0~(false) otherwise. \fun{long}{gcmpsg}{long s, GEN x} \fun{long}{gcmpgs}{GEN x, long s} comparison of \kbd{x} with the \kbd{long}~\kbd{s}. \fun{GEN}{gmaxsg}{long s, GEN x} \fun{GEN}{gmaxgs}{GEN x, long s} returns the largest of \kbd{x} and the \kbd{long}~\kbd{s} (converted to \kbd{GEN}) \fun{GEN}{gminsg}{long s, GEN x} \fun{GEN}{gmings}{GEN x, long s} returns the smallest of \kbd{x} and the \kbd{long}~\kbd{s} (converted to \kbd{GEN}) \fun{long}{gequalsg}{long s, GEN x} \fun{long}{gequalgs}{GEN x, long s} returns 1 (true) if \kbd{x} is equal to the \kbd{long}~\kbd{s}, 0~otherwise. \section{Miscellaneous Boolean functions} \fun{int}{isrationalzeroscalar}{GEN x} equivalent to, but faster than, \bprog is_scalar_t(typ(x)) && isrationalzero(x) @eprog \fun{int}{isinexact}{GEN x} returns 1 (true) if $x$ has an inexact component, and 0 (false) otherwise. \fun{int}{isinexactreal}{GEN x} return 1 if $x$ has an inexact \typ{REAL} component, and 0 otherwise. \fun{int}{isrealappr}{GEN x, long e} applies (recursively) to complex inputs; returns $1$ if $x$ is approximately real to the bit accuracy $e$, and 0 otherwise. This means that any \typ{COMPLEX} component must have imaginary part $t$ satisfying $\kbd{gexpo}(t) < e$. \fun{int}{isint}{GEN x, GEN *n} returns 0 (false) if \kbd{x} does not round to an integer. Otherwise, returns 1 (true) and set \kbd{n} to the rounded value. \fun{int}{issmall}{GEN x, long *n} returns 0 (false) if \kbd{x} does not round to a small integer (suitable for \kbd{itos}). Otherwise, returns 1 (true) and set \kbd{n} to the rounded value. \fun{long}{iscomplex}{GEN x} returns 1 (true) if \kbd{x} is a complex number (of component types embeddable into the reals) but is not itself real, 0~if \kbd{x} is a real (not necessarily of type \typ{REAL}), or raises an error if \kbd{x} is not embeddable into the complex numbers. \subsec{Obsolete} The following less convenient comparison functions and Boolean operators were used by the historical GP interpreter. They are provided for backward compatibility only and should not be used: \fun{GEN}{gle}{GEN x, GEN y} \fun{GEN}{glt}{GEN x, GEN y} \fun{GEN}{gge}{GEN x, GEN y} \fun{GEN}{ggt}{GEN x, GEN y} \fun{GEN}{geq}{GEN x, GEN y} \fun{GEN}{gne}{GEN x, GEN y} \fun{GEN}{gor}{GEN x, GEN y} \fun{GEN}{gand}{GEN x, GEN y} \fun{GEN}{gnot}{GEN x, GEN y} \section{Sorting} \subsec{Basic sort} \fun{GEN}{sort}{GEN x} sorts the vector \kbd{x} in ascending order using a mergesort algorithm, and \kbd{gcmp} as the underlying comparison routine (returns the sorted vector). This routine copies all components of $x$, use \kbd{gen\_sort\_inplace} for a more memory-efficient function. \fun{GEN}{lexsort}{GEN x}, as \kbd{sort}, using \kbd{lexcmp} instead of \kbd{gcmp} as the underlying comparison routine. \fun{GEN}{vecsort}{GEN x, GEN k}, as \kbd{sort}, but sorts the vector \kbd{x} in ascending \emph{lexicographic} order, according to the entries of the \typ{VECSMALL} \kbd{k}. For example, if $\kbd{k} = [2,1,3]$, sorting will be done with respect to the second component, and when these are equal, with respect to the first, and when these are equal, with respect to the third. \subsec{Indirect sorting} \fun{GEN}{indexsort}{GEN x} as \kbd{sort}, but only returns the permutation which, applied to \kbd{x}, would sort the vector. The result is a \typ{VECSMALL}. \fun{GEN}{indexlexsort}{GEN x}, as \kbd{indexsort}, using \kbd{lexcmp} instead of \kbd{gcmp} as the underlying comparison routine. \fun{GEN}{indexvecsort}{GEN x, GEN k}, as \kbd{vecsort}, but only returns the permutation that would sort the vector \kbd{x}. \fun{long}{vecindexmin}{GEN x} returns the index for a maximal element of $x$ (\typ{VEC}, \typ{COL} or \typ{VECSMALL}). \fun{long}{vecindexmax}{GEN x} returns the index for a maximal element of $x$ (\typ{VEC}, \typ{COL} or \typ{VECSMALL}). \fun{long}{vecindexmax}{GEN x} \subsec{Generic sort and search} The following routines allow to use an arbitrary comparison function \kbd{int (*cmp)(void* data, GEN x, GEN y)}, such that \kbd{cmp(data,x,y)} returns a negative result if $x < y$, a positive one if $x > y$ and 0 if $x = y$. The \kbd{data} argument is there in case your \kbd{cmp} requires additional context. \fun{GEN}{gen_sort}{GEN x, void *data, int (*cmp)(void *,GEN,GEN)}, as \kbd{sort}, with an explicit comparison routine. \fun{GEN}{gen_sort_uniq}{GEN x, void *data, int (*cmp)(void *,GEN,GEN)}, as \kbd{gen\_sort}, removing duplicate entries. \fun{GEN}{gen_indexsort}{GEN x, void *data, int (*cmp)(void*,GEN,GEN)}, as \kbd{indexsort}. \fun{GEN}{gen_indexsort_uniq}{GEN x, void *data, int (*cmp)(void*,GEN,GEN)}, as \kbd{indexsort}, removing duplicate entries. \fun{void}{gen_sort_inplace}{GEN x, void *data, int (*cmp)(void*,GEN,GEN), GEN *perm} sort \kbd{x} in place, without copying its components. If \kbd{perm} is non-\kbd{NULL}, it is set to the permutation that would sort the original \kbd{x}. \fun{GEN}{gen_setminus}{GEN A, GEN B, int (*cmp)(GEN,GEN)} given two sorted vectors $A$ and $B$, returns the vector of elements of $A$ not belonging to $B$. \fun{GEN}{sort_factor}{GEN y, void *data, int (*cmp)(void *,GEN,GEN)}: assuming \kbd{y} is a factorization matrix, sorts its rows in place (no copy is made) according to the comparison function \kbd{cmp} applied to its first column. \fun{GEN}{merge_sort_uniq}{GEN x,GEN y, void *data, int (*cmp)(void *,GEN,GEN)} assuming \kbd{x} and \kbd{y} are sorted vectors, with respect to the \kbd{cmp} 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$. \fun{long}{gen_search}{GEN v, GEN y, long flag, void *data, int (*cmp)(void*,GEN,GEN)}.\hfil\break Let \kbd{v} be a vector sorted according to \kbd{cmp(data,a,b)}; look for an index $i$ such that \kbd{v[$i$]} is equal to \kbd{y}. \kbd{flag} has the same meaning as in \kbd{setsearch}: if \kbd{flag} is 0, return $i$ if it exists and 0 otherwise; if \kbd{flag} is non-zero, return $0$ if $i$ exists and the index where \kbd{y} should be inserted otherwise. \fun{long}{tablesearch}{GEN T, GEN x, int (*cmp)(GEN,GEN)} is a faster implementation for the common case \kbd{gen\_search(T,x,0,cmp,cmp\_nodata)}. \subsec{Further useful comparison functions} \fun{int}{cmp_universal}{GEN x, GEN y} a somewhat arbitrary universal comparison function, devoid of sensible mathematical meaning. It is transitive, and returns 0 if and only if \kbd{gidentical(x,y)} is true. Useful to sort and search vectors of arbitrary data. \fun{int}{cmp_nodata}{void *data, GEN x, GEN y}. This function is a hack used to pass an existing basic comparison function lacking the \kbd{data} argument, i.e. with prototype \kbd{int (*cmp)(GEN x, GEN y)}. Instead of \kbd{gen\_sort(x, NULL, cmp)} which may or may not work depending on how your compiler handles typecasts between incompatible function pointers, one should use \kbd{gen\_sort(x, (void*)cmp, cmp\_nodata)}. Here are a few basic comparison functions, to be used with \kbd{cmp\_nodata}: \fun{int}{ZV_cmp}{GEN x, GEN y} compare two \kbd{ZV}, which we assume have the same length (lexicographic order). \fun{int}{cmp_RgX}{GEN x, GEN y} compare two polynomials, which we assume have the same main variable (lexicographic order). The coefficients are compared using \kbd{gcmp}. \fun{int}{cmp_prime_over_p}{GEN x, GEN y} compare two prime ideals, which we assume divide the same prime number. The comparison is ad hoc but orders according to increasing residue degrees. \fun{int}{cmp_prime_ideal}{GEN x, GEN y} compare two prime ideals in the same \var{nf}. Orders by increasing primes, breaking ties using \kbd{cmp\_prime\_over\_p}. Finally a more elaborate comparison function: \fun{int}{gen_cmp_RgX}{void *data, GEN x, GEN y} compare two polynomials, ordering first by increasing degree, then according to the coefficient comparison function: \bprog int (*cmp_coeff)(GEN,GEN) = (int(*)(GEN,GEN)) data; @eprog \section{Divisibility, Euclidean division} \fun{GEN}{gdivexact}{GEN x, GEN y} returns the quotient $\kbd{x} / \kbd{y}$, assuming $\kbd{y}$ divides $\kbd{x}$. Not stack clean if $y = 1$ (we return $x$, not a copy). \fun{int}{gdvd}{GEN x, GEN y} returns 1 (true) if \kbd{y} divides~\kbd{x}, 0~otherwise. \fun{GEN}{gdiventres}{GEN x, GEN y} creates a 2-component vertical vector whose components are the true Euclidean quotient and remainder of \kbd{x} and~\kbd{y}. \fun{GEN}{gdivent[z]}{GEN x, GEN y[, GEN z]} yields the true Euclidean quotient of \kbd{x} and the \typ{INT} or \typ{POL}~\kbd{y}. \fun{GEN}{gdiventsg}{long s, GEN y[, GEN z]}, as \kbd{gdivent} except that \kbd{x} is a \kbd{long}. \fun{GEN}{gdiventgs[z]}{GEN x, long s[, GEN z]}, as \kbd{gdivent} except that \kbd{y} is a \kbd{long}. \fun{GEN}{gmod[z]}{GEN x, GEN y[, GEN z]} yields the remainder of \kbd{x} modulo the \typ{INT} or \typ{POL}~\kbd{y}. A \typ{REAL} or \typ{FRAC} \kbd{y} is also allowed, in which case the remainder is the unique real $r$ such that $0 \leq r < |\kbd{y}|$ and $\kbd{y} = q\kbd{x} + r$ for some (in fact unique) integer $q$. \fun{GEN}{gmodsg}{long s, GEN y[, GEN z]} as \kbd{gmod}, except \kbd{x} is a \kbd{long}. \fun{GEN}{gmodgs}{GEN x, long s[, GEN z]} as \kbd{gmod}, except \kbd{y} is a \kbd{long}. \fun{GEN}{gdivmod}{GEN x, GEN y, GEN *r} If \kbd{r} is not equal to \kbd{NULL} or \kbd{ONLY\_REM}, creates the (false) Euclidean quotient of \kbd{x} and~\kbd{y}, and puts (the address of) the remainder into~\kbd{*r}. If \kbd{r} is equal to \kbd{NULL}, do not create the remainder, and if \kbd{r} is equal to \kbd{ONLY\_REM}, create and output only the remainder. The remainder is created after the quotient and can be disposed of individually with a \kbd{cgiv(r)}. \fun{GEN}{poldivrem}{GEN x, GEN y, GEN *r} same as \key{gdivmod} but specifically for \typ{POL}s~\kbd{x} and~\kbd{y}, not necessarily in the same variable. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{gdeuc}{GEN x, GEN y} creates the Euclidean quotient of the \typ{POL}s~\kbd{x} and~\kbd{y}. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{grem}{GEN x, GEN y} creates the Euclidean remainder of the \typ{POL}~\kbd{x} divided by the \typ{POL}~\kbd{y}. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{gdivround}{GEN x, GEN y} if \kbd{x} and \kbd{y} are \typ{INT}, as \kbd{diviiround}. Operate componentwise if \kbd{x} is a \typ{COL}, \typ{VEC} or \typ{MAT}. Otherwise as \key{gdivent}. \fun{GEN}{centermod_i}{GEN x, GEN y, GEN y2}, as \kbd{centermodii}, componentwise. \fun{GEN}{centermod}{GEN x, GEN y}, as \kbd{centermod\_i}, except that \kbd{y2} is computed (and left on the stack for efficiency). \fun{GEN}{ginvmod}{GEN x, GEN y} creates the inverse of \kbd{x} modulo \kbd{y} when it exists. \kbd{y} must be of type \typ{INT} (in which case \kbd{x} is of type \typ{INT}) or \typ{POL} (in which case \kbd{x} is either a scalar type or a \typ{POL}). \section{GCD, content and primitive part} \subsec{Generic} \fun{GEN}{resultant}{GEN x, GEN y} creates the resultant of the \typ{POL}s \kbd{x} and~\kbd{y} computed using Sylvester's matrix (inexact inputs), a modular algorithm (inputs in $\Q[X]$) or the subresultant algorithm, as optimized by Lazard and Ducos. Either of \kbd{x} and \kbd{y} may also be scalars (treated as polynomials of degree $0$) \fun{GEN}{ggcd}{GEN x, GEN y} creates the GCD of \kbd{x} and~\kbd{y}. \fun{GEN}{glcm}{GEN x, GEN y} creates the LCM of \kbd{x} and~\kbd{y}. \fun{GEN}{gbezout}{GEN x,GEN y, GEN *u,GEN *v} returns the GCD of \kbd{x} and~\kbd{y}, and puts (the addresses of) objects $u$ and~$v$ such that $u\kbd{x}+v\kbd{y}=\gcd(\kbd{x},\kbd{y})$ into \kbd{*u} and~\kbd{*v}. \fun{GEN}{subresext}{GEN x, GEN y, GEN *U, GEN *V} returns the resultant of \kbd{x} and~\kbd{y}, and puts (the addresses of) polynomials $u$ and~$v$ such that $u\kbd{x}+v\kbd{y}=\text{Res}(\kbd{x},\kbd{y})$ into \kbd{*U} and~\kbd{*V}. \fun{GEN}{content}{GEN x} returns the GCD of all the components of~\kbd{x}. \fun{GEN}{primitive_part}{GEN x, GEN *c} sets \kbd{c} to \kbd{content(x)} and returns the primitive part \kbd{x} / \kbd{c}. A trivial content is set to \kbd{NULL}. \fun{GEN}{primpart}{GEN x} as above but the content is lost. (For efficiency, the content remains on the stack.) \subsec{Over the rationals} \fun{long}{Q_pval}{GEN x, GEN p} valuation at the \typ{INT} \kbd{p} of the \typ{INT} or \typ{FRAC}~\kbd{x}. \fun{long}{Q_pvalrem}{GEN x, GEN p, GEN *r} returns the valuation $e$ at the \typ{INT} \kbd{p} of the \typ{INT} or \typ{FRAC}~\kbd{x}. The quotient $\kbd{x}/\kbd{p}^{e}$ is returned in~\kbd{*r}. \fun{GEN}{Q_abs}{GEN x} absolute value of the \typ{INT} or \typ{FRAC}~\kbd{x}. \fun{GEN}{Q_abs_shallow}{GEN x} $x$ being a \typ{INT} or a \typ{FRAC}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{gneg($x$)} otherwise. \fun{GEN}{Q_gcd}{GEN x, GEN y} gcd of the \typ{INT} or \typ{FRAC}~\kbd{x} and~\kbd{y}. \smallskip In the following functions, arguments belong to a $M\otimes_\Z\Q$ for some natural $\Z$-module $M$, e.g. multivariate polynomials with integer coefficients (or vectors/matrices recursively built from such objects), and an element of $M$ is said to be \emph{integral}. We are interested in contents, denominators, etc. with respect to this canonical integral structure; in particular, contents belong to $\Q$, denominators to $\Z$. For instance the $\Q$-content of $(1/2)xy$ is $(1/2)$, and its $\Q$-denominator is $2$, whereas \kbd{content} would return $y/2$ and \kbd{denom}~1. \fun{GEN}{Q_content}{GEN x} the $\Q$-content of $x$ \fun{GEN}{Q_denom}{GEN x} the $\Q$-denominator of $x$. Shallow function. \fun{GEN}{Q_primitive_part}{GEN x, GEN *c} sets \kbd{c} to the $\Q$-content of \kbd{x} and returns \kbd{x / c}, which is integral. \fun{GEN}{Q_primpart}{GEN x} as above but the content is lost. (For efficiency, the content remains on the stack.) \fun{GEN}{Q_remove_denom}{GEN x, GEN *ptd} sets \kbd{d} to the $\Q$-denominator of \kbd{x} and returns \kbd{x * d}, which is integral. Shallow function. \fun{GEN}{Q_div_to_int}{GEN x, GEN c} returns \kbd{x / c}, assuming $c$ is a rational number (\typ{INT} or \typ{FRAC}) and the result is integral. \fun{GEN}{Q_mul_to_int}{GEN x, GEN c} returns \kbd{x * c}, assuming $c$ is a rational number (\typ{INT} or \typ{FRAC}) and the result is integral. \fun{GEN}{Q_muli_to_int}{GEN x, GEN d} returns \kbd{x * c}, assuming $c$ is a \typ{INT} and the result is integral. \fun{GEN}{mul_content}{GEN cx, GEN cy} \kbd{cx} and \kbd{cy} are as set by \kbd{primitive\_part}: either a \kbd{GEN} or \kbd{NULL} representing the trivial content $1$. Returns their product (either a \kbd{GEN} or \kbd{NULL}). \fun{GEN}{mul_denom}{GEN dx, GEN dy} \kbd{dx} and \kbd{dy} are as set by \kbd{Q\_remove\_denom}: either a \typ{INT} or \kbd{NULL} representing the trivial denominator $1$. Returns their product (either a \typ{INT} or \kbd{NULL}). \section{Generic arithmetic operators} \subsec{Unary operators} \fun{GEN}{gneg[z]}{GEN x[, GEN z]} yields $-\kbd{x}$. \fun{GEN}{gneg_i}{GEN x} shallow function yielding $-\kbd{x}$. \fun{GEN}{gabs[z]}{GEN x[, GEN z]} yields $|\kbd{x}|$. \fun{GEN}{gsqr}{GEN x} creates the square of~\kbd{x}. \fun{GEN}{ginv}{GEN x} creates the inverse of~\kbd{x}. \subsec{Binary operators} Let ``\op'' be a binary operation among \op=\key{add}: addition (\kbd{x + y}). \op=\key{sub}: subtraction (\kbd{x - y}). \op=\key{mul}: multiplication (\kbd{x * y}). \op=\key{div}: division (\kbd{x / y}). \noindent The names and prototypes of the functions corresponding to \op\ are as follows: \funno{GEN}{g\op}{GEN x, GEN y} \funno{GEN}{g\op gs}{GEN x, long s} \funno{GEN}{g\op sg}{long s, GEN y} \noindent Explicitly \fun{GEN}{gadd}{GEN x, GEN y}, \fun{GEN}{gaddgs}{GEN x, long s}, \fun{GEN}{gaddsg}{GEN s, GEN x} \fun{GEN}{gmul}{GEN x, GEN y}, \fun{GEN}{gmulgs}{GEN x, long s}, \fun{GEN}{gmulsg}{GEN s, GEN x} \fun{GEN}{gsub}{GEN x, GEN y}, \fun{GEN}{gsubgs}{GEN x, long s}, \fun{GEN}{gsubsg}{GEN s, GEN x} \fun{GEN}{gdiv}{GEN x, GEN y}, \fun{GEN}{gdivgs}{GEN x, long s}, \fun{GEN}{gdivsg}{GEN s, GEN x} \fun{GEN}{gpow}{GEN x, GEN y, long l} creates $\kbd{x}^{\kbd{y}}$. If \kbd{y} is a \typ{INT}, return \kbd{powgi(x,y)} (the precision \kbd{l} is not taken into account). Otherwise, the result is $\exp(\kbd{y}*\log(\kbd{x}))$ where exact arguments are converted to floats of precision~\kbd{l} in case of need; if there is no need, for instance if $x$ is a \typ{REAL}, $l$ is ignored. Indeed, if $x$ is a \typ{REAL}, the accuracy of $\log x$ is determined from the accuracy of $x$, it is no problem to multiply by $y$, even if it is an exact type, and the accuracy of the exponential is determined, exactly as in the case of the initial $\log x$. \fun{GEN}{gpowgs}{GEN x, long n} creates $\kbd{x}^{\kbd{n}}$ using 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} \item \kbd{Mod(1,N)} if $x$ is a \typ{INTMOD} modulo $N$. \item \kbd{gen\_1} for \typ{COMPLEX}, \typ{QUAD} unless one component is a \typ{INTMOD}, in which case we return \kbd{Mod(1, N)} for a suitable $N$ (the gcd of the moduli that appear). \item \kbd{FF\_1}$(x)$ for a \typ{FFELT}. \item \kbd{RgX\_get\_1}$(x)$ for a \typ{POL}. \item \kbd{qfi\_1}$(x)$ and \kbd{qfr\_1}$(x)$ for \typ{QFI} and \typ{QFR}. \item the identity permutation for \typ{VECSMALL}. \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). \fun{GEN}{powgi}{GEN x, GEN y} creates $\kbd{x}^{\kbd{y}}$, where \kbd{y} is a \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)}. In addition we also have the obsolete forms: \fun{void}{gaddz}{GEN x, GEN y, GEN z} \fun{void}{gsubz}{GEN x, GEN y, GEN z} \fun{void}{gmulz}{GEN x, GEN y, GEN z} \fun{void}{gdivz}{GEN x, GEN y, GEN z} \section{Generic operators: product, powering, factorback} \fun{GEN}{divide_conquer_prod}{GEN v, GEN (*mul)(GEN,GEN)} $v$ is a vector of objects, which can be ``multiplied'' using the \kbd{mul} function. Return the ``product'' of the $v[i]$ using a product tree: by convention return \kbd{gen\_1} if $v$ is the empty vector, a copy of $v[1]$ if it has a single entry; and otherwise apply the function recursively on the vector (twice smaller) \kbd{mul}$(v[1],v[2])$, \kbd{mul}$(v[3],v[4])$, \dots \noindent Only requires that \kbd{mul} is an associative binary operator, which need not correspond to a true multiplication. \kbd{D} is meant to encode an arbitrary evaluation context, set it to \kbd{NULL} in simple cases where you do not need this. Leaves some garbage on stack, but suitable for \kbd{gerepileupto} if \kbd{mul} is. To describe the following functions, we use the following private typedefs to simplify the description: \bprog typedef (*F0)(void *); typedef (*F1)(void *, GEN); typedef (*F2)(void *, GEN, GEN); @eprog \noindent They correspond to generic functions with one and two arguments respectively (the \kbd{void*} argument provides some arbitrary evaluation context). \fun{GEN}{divide_conquer_assoc}{GEN v, void *D, F2 op} general version of \tet{divide_conquer_prod}. Given two objects $x,y$, assume that \kbd{op(D, $x$, $y$)} implements an associative binary operator. If $v$ has $k$ entries, return $$v[1]~\var{op}~v[2]~\var{op}~\ldots ~\var{op}~v[k];$$ returns \kbd{gen\_1} if $k = 0$ and a copy of $v[1]$ if $k = 1$. \fun{GEN}{gen_pow}{GEN x, GEN n, void *D, F1 sqr, F2 mul} $n > 0$ a \typ{INT}, returns $x^n$; \kbd{mul(D, $x$, $y$)} implements the multiplication in the underlying monoid; \kbd{sqr} is a (presumably optimized) shortcut for \kbd{mul(D, $x$, $x$)}. \fun{GEN}{gen_powu}{GEN x, ulong n, void *D, F1 sqr, F2 mul} $n > 0$, returns $x^n$. See \tet{gen_pow}. \fun{GEN}{gen_pow_i}{GEN x, GEN n, void *E, F1 sqr, F2 mul} internal variant of \tet{gen_pow}, not memory-clean. \fun{GEN}{gen_powu_i}{GEN x, ulong n, void *E, F1 sqr, F2 mul} internal variant of \tet{gen_powu}, not memory-clean. \fun{GEN}{gen_pow_fold}{GEN x, GEN n, void *D, F1 sqr, F1 msqr} variant of \tet{gen_pow}, where \kbd{mul} is replaced by \kbd{msqr}, with \kbd{msqr(D, $y$)} returning $xy^2$. In particular \kbd{D} must implicitly contain $x$. \fun{GEN}{gen_pow_fold_i}{GEN x, GEN n, void *E, F1 sqr, F1 msqr} internal variant of the function \tet{gen_pow_fold}, not memory-clean. \fun{GEN}{gen_powu_fold}{GEN x, ulong n, void *D, F1 sqr, F1 msqr}, see \tet{gen_pow_fold}. \fun{GEN}{gen_powu_fold_i}{GEN x, ulong n, void *E, F1 sqr, F1 msqr} see \tet{gen_pow_fold_i}. \fun{GEN}{gen_powers}{GEN x, long n, long usesqr, void *D, F1 sqr, F2 mul, F0 one} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC}; \kbd{mul(D, $x$, $y$)} implements the multiplication in the underlying monoid; \kbd{sqr} is a (presumably optimized) shortcut for \kbd{mul(D, $x$, $x$)}; \kbd{one} returns the monoid unit. The flag \kbd{usesqr} should be set to $1$ if squaring are faster than multiplication by $x$. \fun{GEN}{gen_factorback}{GEN L, GEN e, F2 mul, F2 pow, void *D} generic form of \tet{factorback}. The pair $[L,e]$ is of the form \item \kbd{[fa, NULL]}, \kbd{fa} a two-column factorization matrix: expand it. \item \kbd{[v, NULL]}, $v$ a vector of objects: return their product. \item or \kbd{[v, e]}, $v$ a vector of objects, $e$ a vector of integral exponents: return the product of the $v[i]^{e[i]}$. \noindent \kbd{mul(D, $x$, $y$)} and \kbd{pow(D, $x$, $n$)} return $xy$ and $x^n$ respectively. \section{Matrix and polynomial norms} This section concerns only standard norms of $\R$ and $\C$ vector spaces, not algebraic norms given by the determinant of some multiplication operator. We have already seen type-specific functions like \tet{ZM_supnorm} or \tet{RgM_fpnorml2} and limit ourselves to generic functions assuming nothing about their \kbd{GEN} argument; these functions allow the following scalar types: \typ{INT}, \typ{FRAC}, \typ{REAL}, \typ{COMPLEX}, \typ{QUAD} and are defined recursively (in terms of norms of their components) for the following ``container'' types: \typ{POL}, \typ{VEC}, \typ{COL} and \typ{MAT}. They raise an error if some other type appears in the argument. \fun{GEN}{gnorml2}{GEN x} The norm of a scalar is the square of its complex modulus, the norm of a recursive type is the sum of the norms of its components. For polynomials, vectors or matrices of complex numbers one recovers the \emph{square} of the usual $L^2$ norm. In most applications, the missing square root computation can be skipped. \fun{GEN}{gnorml1}{GEN x, long prec} The norm of a scalar is its complex modulus, the norm of a recursive type is the sum of the norms of its components. For polynomials, vectors or matrices of complex numbers one recovers the the usual $L^1$ norm. One must include a real precision \kbd{prec} in case the inputs include \typ{COMPLEX} or \typ{QUAD} with exact rational components: a square root must be computed and we must choose an accuracy. \fun{GEN}{gnorml1_fake}{GEN x} as \tet{gnorml1}, except that the norm of a \typ{QUAD} $x + wy$ or \typ{COMPLEX} $x + Iy$ is defined as $|x| + |y|$, where we use the ordinary real absolute value. This is still a norm of $\R$ vector spaces, which is easier to compute than \kbd{gnorml1} and can often be used in its place. \fun{GEN}{gsupnorm}{GEN x, long prec} The norm of a scalar is its complex modulus, the norm of a recursive type is the max of the norms of its components. A precision \kbd{prec} must be included for the same reason as in \kbd{gnorml1}. \fun{void}{gsupnorm_aux}{GEN x, GEN *m, GEN *m2, long prec} Low-level function underlying \kbd{gsupnorm}, used as follows: \bprog GEN m = NULL, m2 = NULL; gsupnorm_aux(x, &m, &m2); @eprog After the call, the sup norm of $x$ is the min of \kbd{m} and the square root of \kbd{m2}; one or both of \kbd{m}, \kbd{m2} may be \kbd{NULL}, in which case it must be omitted. You may initially set \kbd{m} and \kbd{m2} to non-\kbd{NULL} values, in which case, the above procedure yields the max of (the initial) \kbd{m}, the square root of (the initial) \kbd{m2}, and the sup norm of $x$. The strange interface is due to the fact that $|z|^2$ is easier to compute than $|z|$ for a \typ{QUAD} or \typ{COMPLEX} $z$: \kbd{m2} is the max of those $|z|^2$, and \kbd{m} is the max of the other $|z|$. \section{Substitution and evaluation} \fun{GEN}{gsubst}{GEN x, long v, GEN y} substitutes the object \kbd{y} into~\kbd{x} for the variable number~\kbd{v}. \fun{GEN}{poleval}{GEN q, GEN x} evaluates the \typ{POL} or \typ{RFRAC} $q$ at $x$. For convenience, a \typ{VEC} or \typ{COL} is also recognized as the \typ{POL} \kbd{gtovecrev(q)}. \fun{GEN}{RgX_RgM_eval}{GEN q, GEN x} evaluates the \typ{POL} $q$ at the square matrix $x$. \fun{GEN}{RgX_RgMV_eval}{GEN f, GEN V} returns the evaluation $\kbd{f}(\kbd{x})$, assuming that \kbd{V} was computed by $\kbd{FpXQ\_powers}(\kbd{x}, n)$ for some $n>1$. \fun{GEN}{RgX_RgM_eval_col}{GEN q, GEN x, long c} evaluates the \typ{POL} $q$ at the square matrix $x$ but only returns the \kbd{c}-th column of the result. \fun{GEN}{qfeval}{GEN q, GEN x} evaluates the quadratic form $q$ (symmetric matrix) at $x$ (column vector of compatible dimensions). \fun{GEN}{qfevalb}{GEN q, GEN x, GEN y} evaluates the polar bilinear form associated to the quadratic form $q$ (symmetric matrix) at $x$, $y$ (column vectors of compatible dimensions). \fun{GEN}{hqfeval}{GEN q, GEN x} evaluates the Hermitian form $q$ (a Hermitian complex matrix) at $x$. \fun{GEN}{qf_apply_RgM}{GEN q, GEN M} $q$ is a symmetric $n\times n$ matrix, $M$ an $n\times k$ matrix, return $M' q M$. \fun{GEN}{qf_apply_ZM}{GEN q, GEN M} as above assuming that both $q$ and $M$ have integer entries. \newpage \chapter{Miscellaneous mathematical functions} \section{Fractions} \fun{GEN}{absfrac}{GEN x} returns the absolute value of the \typ{FRAC} $x$. \fun{GEN}{absfrac_shallow}{GEN x} $x$ being a \typ{FRAC}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{gneg($x$)} otherwise. \fun{GEN}{sqrfrac}{GEN x} returns the square of the \typ{FRAC} $x$. \section{Complex numbers} \fun{GEN}{imag}{GEN x} returns a copy of the imaginary part of \kbd{x}. \fun{GEN}{real}{GEN x} returns a copy of the real part of \kbd{x}. If \kbd{x} is a \typ{QUAD}, returns the coefficient of $1$ in the ``canonical'' integral basis $(1,\omega)$. The last two functions are shallow, and not suitable for \tet{gerepileupto}: \fun{GEN}{imag_i}{GEN x} as \kbd{gimag}, returns a pointer to the imaginary part. \fun{GEN}{real_i}{GEN x} as \kbd{greal}, returns a pointer to the real part. \fun{GEN}{mulreal}{GEN x, GEN} returns the real part of $xy$; $x,y$ have type \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}. See also \kbd{RgM\_mulreal}. \fun{GEN}{cxnorm}{GEN x} norm of the \typ{COMPLEX} $x$ (modulus squared). \fun{GEN}{cxexpm1}{GEN x} returns $\exp(x)-1$, for a \typ{COMPLEX} $x$. \section{Quadratic numbers and binary quadratic forms} \fun{GEN}{quad_disc}{GEN x} returns the discriminant of the \typ{QUAD} $x$. \fun{GEN}{quadnorm}{GEN x} norm of the \typ{QUAD} $x$. \fun{GEN}{qfb_disc}{GEN x} returns the discriminant of the \typ{QFI} or \typ{QFR} \kbd{x}. \fun{GEN}{qfb_disc3}{GEN x, GEN y, GEN z} returns $y^2 - 4xz$ assuming all inputs are \typ{INT}s. Not stack-clean. \section{Polynomials}\label{se:polynomials} \fun{GEN}{truecoeff}{GEN x, long n} returns \kbd{polcoeff0(x,n, -1)}, i.e. the coefficient of the term of degree \kbd{n} in the main variable. \fun{GEN}{polcoeff_i}{GEN x, long n, long v} internal shallow function. Rewrite $x$ as a Laurent polynomial in the variable $v$ and returns its coefficient of degree $n$ (\kbd{gen\_0} if this falls outside the coefficient array). Allow \typ{POL}, \typ{SER}, \typ{RFRAC} and scalars. \fun{long}{degree}{GEN x} returns \kbd{poldegree(x, -1)}, the degree of \kbd{x} with respect to its main variable, with the usual meaning if the leading coefficient of $x$ is non-zero. If the sign of $x$ is $0$, this function always returns $-1$. Otherwise, we return the index of the leading coefficient of $x$, i.e. the coefficient of largest index stored in $x$. For instance the ``degrees'' of \bprog 0. E-38 * x^4 + 0.E-19 * x + 1 Mod(0,2) * x^0 \\ sign is 0 ! @eprog\noindent are $4$ and $-1$ respectively. \fun{long}{degpol}{GEN x} is a simple macro returning \kbd{lg(x) - 3}. This is the degree of the \typ{POL}~\kbd{x} with respect to its main variable, \emph{if} its leading coefficient is non-zero (a rational $0$ is impossible, but an inexact $0$ is allowed, as well as an exact modular $0$, e.g. \kbd{Mod(0,2)}). If $x$ has no coefficients (rational $0$ polynomial), its length is $2$ and we return the expected $-1$. \fun{GEN}{characteristic}{GEN x} returns the characteristic of the base ring over which the polynomial is defined (as defined by \typ{INTMOD} and \typ{FFELT} components). The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. Shallow function. \fun{GEN}{residual_characteristic}{GEN x} returns a kind of ``residual characteristic'' of the base ring over which the polynomial is defined. This is defined as the gcd of all moduli \typ{INTMOD}s occurring in the structure, as well as primes $p$ arising from \typ{PADIC}s or \typ{FFELT}s. The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. Shallow function. \fun{GEN}{resultant}{GEN x,GEN y} resultant of \kbd{x} and \kbd{y}, with respect to the main variable of highest priority. Uses either the subresultant algorithm (generic case), a modular algorithm (inputs in $\Q[X]$) or Sylvester's matrix (inexact inputs). \fun{GEN}{resultant2}{GEN x, GEN y} resultant of \kbd{x} and \kbd{y}, with respect to the main variable of highest priority. Computes the determinant of Sylvester's matrix. \fun{GEN}{resultant_all}{GEN u, GEN v, GEN *sol} returns \kbd{resultant(x,y)}. If \kbd{sol} is not \kbd{NULL}, sets it to the last non-constant remainder in the polynomial remainder sequence if such a sequence was computed, and to \kbd{gen\_0} otherwise (e.g. polynomials of degree 0, $u,v$ in $\Q[X]$). \fun{GEN}{cleanroots}{GEN x, long prec} returns the complex roots of the complex polynomial $x$ (with coefficients \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX} of the above). The roots are returned 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{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}. \section{Power series} \fun{GEN}{derivser}{GEN x} returns the derivative of the \typ{SER} \kbd{x} with respect to its main variable. \fun{GEN}{integser}{GEN x} returns the primitive of the \typ{SER} \kbd{x} with respect to its main variable. \fun{GEN}{truecoeff}{GEN x, long n} returns \kbd{polcoeff0(x,n, -1)}, i.e. the coefficient of the term of degree \kbd{n} in the main variable. \fun{GEN}{ser_unscale}{GEN P, GEN h} return $P(h x)$, not memory clean. \fun{GEN}{ser_normalize}{GEN x} divide $x$ by its ``leading term'' so that the series is either $0$ or equal to $t^v(1+O(t))$. Shallow function if the ``leading term'' is $1$. \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 functions class \kbd{FpXQ} and/or \kbd{Flxq} as appropriate. \fun{GEN}{FF_p}{GEN a} returns the characteristic of the definition field of the \typ{FFELT} element \kbd{a}. \fun{long}{FF_f}{GEN a} returns the dimension of the definition field over 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 \typ{FFELT} element \kbd{a}. \fun{GEN}{FF_mod}{GEN a} returns the polynomial (with reduced \typ{INT} coefficients) defining the finite field, in the variable used to display $a$. \fun{GEN}{FF_to_FpXQ}{GEN a} converts the \typ{FFELT} \kbd{a} to a polynomial $P$ with reduced \typ{INT} coefficients such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. \fun{GEN}{FF_to_FpXQ_i}{GEN a} shallow version of \kbd{FF\_to\_FpXQ}. \fun{GEN}{FF_to_F2xq}{GEN a} converts the \typ{FFELT} \kbd{a} to a \kbd{F2x} $P$ such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. This only work if the characteristic is $2$. \fun{GEN}{FF_to_F2xq_i}{GEN a} shallow version of \kbd{FF\_to\_F2xq}. \fun{GEN}{FF_to_Flxq}{GEN a} converts the \typ{FFELT} \kbd{a} to a \kbd{Flx} $P$ such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. This only work if the characteristic is small enough. \fun{GEN}{FF_to_Flxq_i}{GEN a} shallow version of \kbd{FF\_to\_Flxq}. \fun{GEN}{p_to_FF}{GEN p, long v} returns a \typ{FFELT} equal to $1$ in the 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}{FF_1}{GEN a} returns the unity in the definition field of the \typ{FFELT} element \kbd{a}. \fun{GEN}{FF_zero}{GEN a} returns the zero element of the definition field of the \typ{FFELT} element \kbd{a}. \fun{int}{FF_equal0}{GEN a}, \fun{int}{FF_equal1}{GEN a}, \fun{int}{FF_equalm1}{GEN a} returns $1$ if the \typ{FFELT} \kbd{a} is equal to $0$ (resp. $1$, resp. $-1$) else $0$. \fun{int}{FF_equal}{GEN a, GEN b} return $1$ if the \typ{FFELT} \kbd{a} and \kbd{b} have the same definition field and are equal, else $0$. \fun{int}{FF_samefield}{GEN a, GEN b} return $1$ if the \typ{FFELT} \kbd{a} and \kbd{b} have the same definition field, else $0$. \fun{int}{Rg_is_FF}{GEN c, GEN *ff} to be called successively on many objects, setting \kbd{*ff = NULL} (unset) initially. Returns $1$ as long as $c$ is a \typ{FFELT} defined over the same field as \kbd{*ff} (setting \kbd{*ff = c} if unset), and $0$ otherwise. \fun{int}{RgC_is_FFC}{GEN x, GEN *ff} apply \tet{Rg_is_FF} successively to all components of the \typ{VEC} or \typ{COL} $x$. Return $0$ if one call fails, and $1$ otherwise. \fun{int}{RgM_is_FFM}{GEN x, GEN *ff} apply \tet{Rg_is_FF} to all components of the \typ{MAT}. Return $0$ if one call fails, and $1$ otherwise. \fun{GEN}{FF_add}{GEN a, GEN b} returns $a+b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_Z_add}{GEN a, GEN x} returns $a+x$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_Q_add}{GEN a, GEN x} returns $a+x$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{RFRAC}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_sub}{GEN a, GEN b} returns $a-b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_mul}{GEN a, GEN b} returns $a\*b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_Z_mul}{GEN a, GEN b} returns $a\*b$, where \kbd{a} is a \typ{FFELT}, and \kbd{b} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_div}{GEN a, GEN b} returns $a/b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_neg}{GEN a} returns $-a$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_neg_i}{GEN a} shallow function returning $-a$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_inv}{GEN a} returns $a^{-1}$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_sqr}{GEN a} returns $a^2$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_mul2n}{GEN a, long n} returns $a\*2^n$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_pow}{GEN x, GEN n} returns $a^n$ where \kbd{a} is a \typ{FFELT} and\kbd{n} is a \typ{INT}. \fun{GEN}{FF_Z_Z_muldiv}{GEN a, GEN x, GEN y} returns $a\*y/z$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} and \kbd{y} are \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{Z_FF_div}{GEN x, GEN a} return $x/a$ where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_norm}{GEN a} returns the norm of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_trace}{GEN a} returns the trace of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_conjvec}{GEN a} returns the vector of conjugates $[a,a^p,a^{p^2},\ldots,a^{p^{n-1}}]$ where the \typ{FFELT} \kbd{a} belong to a field with $p^n$ elements. \fun{GEN}{FF_charpoly}{GEN a} returns the characteristic polynomial) of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_minpoly}{GEN a} returns the minimal polynomial of the \typ{FFELT} \kbd{a}. \fun{GEN}{FF_sqrt}{GEN a} returns an \typ{FFELT} $b$ such that $a=b^2$ if it exist, where \kbd{a} is a \typ{FFELT}. \fun{long}{FF_issquareall}{GEN x, GEN *pt} returns $1$ if \kbd{x} is a square, and $0$ otherwise. If \kbd{x} is indeed a square, set \kbd{pt} to its square root. \fun{long}{FF_issquare}{GEN x} returns $1$ if \kbd{x} is a square and $0$ otherwise. \fun{long}{FF_ispower}{GEN x, GEN K, GEN *pt} Given $K$ a positive integer, returns $1$ if \kbd{x} is a $K$-th power, and $0$ otherwise. If \kbd{x} is indeed a $K$-th power, set \kbd{pt} to its $K$-th root. \fun{GEN}{FF_sqrtn}{GEN a, GEN n, GEN *zn} returns an \kbd{n}-th root of $\kbd{a}$ if it exist. If \kbd{zn} is non-\kbd{NULL} set it to a primitive \kbd{n}-th root of the unity. \fun{GEN}{FF_log}{GEN a, GEN g, GEN o} the \typ{FFELT} \kbd{g} being a generator for the definition field of the \typ{FFELT} \kbd{a}, returns a \typ{INT} $e$ such that $a^e=g$. If $e$ does not exists, the result is currently undefined. If \kbd{o} is not \kbd{NULL} it is assumed to be a factorization of the multiplicative order of \kbd{g} (as set by \tet{FF_primroot}) \fun{GEN}{FF_order}{GEN a, GEN o} returns the order of the \typ{FFELT} \kbd{a}. If \kbd{o} is non-\kbd{NULL}, it is assumed that \kbd{o} is a multiple of the order of \kbd{a}. \fun{GEN}{FF_primroot}{GEN a, GEN *o} returns a generator of the multiplicative group of the definition field of the \typ{FFELT} \kbd{a}. If \kbd{o} is not \kbd{NULL}, set it to the factorization of the order of the primitive root (to speed up \tet{FF_log}). \fun{GEN}{FFX_factor}{GEN f, GEN a} returns the factorization of the univariate polynomial \kbd{f} over the definition field of the \typ{FFELT} \kbd{a}. The coefficients of \kbd{f} must be of type \typ{INT}, \typ{INTMOD} or \typ{FFELT} and compatible with \kbd{a}. \fun{GEN}{FFX_roots}{GEN f, GEN a} returns the roots (\typ{FFELT}) of the univariate polynomial \kbd{f} over the definition field of the \typ{FFELT} \kbd{a}. The coefficients of \kbd{f} must be of type \typ{INT}, \typ{INTMOD} or \typ{FFELT} and compatible with \kbd{a}. \fun{GEN}{FFM_FFC_mul}{GEN M, GEN C, GEN ff} returns the product of the matrix~\kbd{M} (\typ{MAT}) and the column vector~\kbd{C} (\typ{COL}) over the finite field given by \kbd{ff} (\typ{FFELT}). \fun{GEN}{FFM_ker}{GEN M, GEN ff} returns the kernel of the \typ{MAT} \kbd{M} defined over the finite field given by the \typ{FFELT} \kbd{ff} (obtained by \tet{RgM_is_FFM(M,\&ff)}). \fun{GEN}{FFM_det}{GEN M, GEN ff} \fun{GEN}{FFM_image}{GEN M, GEN ff} \fun{GEN}{FFM_inv}{GEN M, GEN ff} \fun{GEN}{FFM_mul}{GEN M, GEN N, GEN ff} returns the product of the matrices \kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by \kbd{ff} (\typ{FFELT}). \fun{long}{FFM_rank}{GEN M, GEN ff} \section{Transcendental functions} The following two functions are only useful when interacting with \kbd{gp}, to manipulate its internal default precision (expressed as a number of decimal digits, not in words as used everywhere else): \fun{long}{getrealprecision}{void} returns \kbd{realprecision}. \fun{long}{setrealprecision}{long n, long *prec} sets the new \kbd{realprecision} to $n$, which is returned. As a side effect, set \kbd{prec} to the corresponding number of words \kbd{ndec2prec(n)}. \subsec{Transcendental functions with \typ{REAL} arguments} In the following routines, $x$ is assumed to be a \typ{REAL} and the result is a \typ{REAL} (sometimes a \typ{COMPLEX} with \typ{REAL} components), with the largest accuracy which can be deduced from the input. The naming scheme is inconsistent here, since we sometimes use the prefix \kbd{mp} even though \typ{INT} inputs are forbidden: \fun{GEN}{sqrtr}{GEN x} returns the square 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. \fun{GEN}{mpcos[z]}{GEN x[, GEN z]} returns $\cos(x)$. \fun{GEN}{mpsin[z]}{GEN x[, GEN z]} returns $\sin(x)$. \fun{GEN}{mplog[z]}{GEN x[, GEN z]} returns $\log(x)$. We must have $x > 0$ since the result must be a \typ{REAL}. Use \kbd{glog} for the general case, where you want such computations as $\log(-1) = I$. \fun{GEN}{mpexp[z]}{GEN x[, GEN z]} returns $\exp(x)$. \fun{GEN}{mpexpm1}{GEN x} returns $\exp(x)-1$, but is more accurate than \kbd{subrs(mpexp(x), 1)}, which suffers from catastrophic cancellation if $|x|$ is very small. \fun{void}{mpsincosm1}{GEN x, GEN *s, GEN *c} sets $s$ and $c$ to $\sin(x)$ and $\cos(x)-1$ respectively, where $x$ is a \typ{REAL}; the latter is more accurate than \kbd{subrs(mpcos(y), 1)}, which suffers from catastrophic cancellation if $|x|$ is very small. \fun{GEN}{mpveceint1}{GEN C, GEN eC, long n} as \kbd{veceint1}; assumes that $C > 0$ is a \typ{REAL} and that \kbd{eC} is \kbd{NULL} or \kbd{mpexp(C)}. \fun{GEN}{mpeint1}{GEN x, GEN expx} returns \kbd{eint1}$(x)$, for a \typ{REAL} $x\geq 0$, assuming that \kbd{expx} is \kbd{mpexp}$(x)$. \fun{GEN}{szeta}{long s, long prec} returns the value of Riemann's zeta function at the (possibly negative) integer $s\neq 1$, in relative accuracy \kbd{prec}. \fun{GEN}{mplambertW}{GEN y} solution $x$ of the implicit equation $x \exp(x) = y$, for $y > 0$ a \typ{REAL}. \noindent Useful low-level functions which \emph{disregard} the sign of $x$: \fun{GEN}{sqrtr_abs}{GEN x} returns $\sqrt{|x|}$ 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$. \noindent A few variants on sin and cos: \fun{void}{mpsincos}{GEN x, GEN *s, GEN *c} sets $s$ and $c$ to $\sin(x)$ and $\cos(x)$ respectively, where $x$ is a \typ{REAL} \fun{GEN}{expIr}{GEN x} returns $\exp(ix)$, where $x$ is a \typ{REAL}. The return type is \typ{COMPLEX} unless the imaginary part is equal to $0$ to the current accuracy (its sign is $0$). \fun{GEN}{expIxy}{GEN x, GEN y, long prec} returns $\exp(ixy)$. Efficient when $x$ is real and $y$ pure imaginary. \fun{void}{gsincos}{GEN x, GEN *s, GEN *c, long prec} general case. \noindent A generalization of \tet{affrr_fixlg} \fun{GEN}{affc_fixlg}{GEN x, GEN res} assume \kbd{res} was allocated using \tet{cgetc}, and that $x$ is either a \typ{REAL} or a \typ{COMPLEX} with \typ{REAL} components. Assign $x$ to \kbd{res}, first shortening the components of \kbd{res} if needed (in a \kbd{gerepile}-safe way). Further convert \kbd{res} to a \typ{REAL} if $x$ is a \typ{REAL}. \fun{GEN}{trans_eval}{const char *fun, GEN (*f) (GEN, long), GEN x, long prec} evaluate transcendental function $f$ (named \kbd{"fun"} at the argument $x$ and precision \kbd{prec}. This is a quick way to implement a transcendental function to be made available under GP, starting from a $C$ function handling only \typ{REAL} and \typ{COMPLEX} arguments. This routine first converts $x$ to a suitable type: \item \typ{INT}/\typ{FRAC} to \typ{REAL} of precision \kbd{prec}, \typ{QUAD} to \typ{REAL} or \typ{COMPLEX} of precision \kbd{prec}. \item \typ{POLMOD} to a \typ{COL} of complex embeddings (as in \tet{conjvec}) Then evaluates the function at \typ{VEC}, \typ{COL}, \typ{MAT} arguments coefficientwise. \subsec{Transcendental functions with \typ{PADIC} arguments} \fun{GEN}{Qp_exp}{GEN x} shortcut for \kbd{gexp(x, /*ignored*/prec)} \fun{GEN}{Qp_gamma}{GEN x} shortcut for \kbd{ggamma(x, /*ignored*/prec)} \fun{GEN}{Qp_log}{GEN x} shortcut for \kbd{glog(x, /*ignored*/prec)} \fun{GEN}{Qp_sqrt}{GEN x} shortcut for \kbd{gsqrt(x, /*ignored*/prec)} Return \kbd{NULL} if $x$ is not a square. \fun{GEN}{Qp_sqrtn}{GEN x, GEN n, GEN *z} shortcut for \kbd{gsqrtn(x, n, z, /*ignored*/prec)}. Return \kbd{NULL} if $x$ is not an $n$-th power. \subsec{Cached constants} The cached constant is returned at its current precision, which may be larger than \kbd{prec}. One should always use the \kbd{mp\var{xxx}} variant: \kbd{mppi}, \kbd{mpeuler}, or \kbd{mplog2}. \fun{GEN}{consteuler}{long prec} precomputes Euler-Mascheroni's constant at precision \kbd{prec}. \fun{GEN}{constcatalan}{long prec} precomputes Catalan's constant at precision \kbd{prec}. \fun{GEN}{constpi}{long prec} precomputes $\pi$ at precision \kbd{prec}. \fun{GEN}{constlog2}{long prec} precomputes $\log(2)$ at precision \kbd{prec}. \fun{void}{mpbern}{long n, long prec} precomputes the $n$ even \idx{Bernoulli} numbers $B_2,\dots,B_{2n}$ as \typ{FRAC} or \typ{REAL}s of precision \kbd{prec}. For any $2 \leq k \leq 2n$, if a floating point approximation of $B_k$ to accuracy \kbd{prec} is enough to reconstruct it exactly, a \typ{FRAC} is stored; otherwise a \typ{REAL} at the requested accuracy. No more than $n$ Bernoulli numbers will ever be stored (by \tet{bernfrac} or \tet{bernreal}), unless a subsequent call to \kbd{mpbern} increases the cache. If \kbd{prec} is $0$, the $B_k$ are computed exactly. The following functions use cached data if \kbd{prec} is smaller than the precision of the cached value; otherwise the newly computed data replaces the old cache. \fun{GEN}{mppi}{long prec} returns $\pi$ at precision \kbd{prec}. \fun{GEN}{Pi2n}{long n, long prec} returns $2^n\pi$ at precision \kbd{prec}. \fun{GEN}{PiI2}{long n, long prec} returns the complex number $2\pi i$ at precision \kbd{prec}. \fun{GEN}{PiI2n}{long n, long prec} returns the complex number $2^n\pi i$ at precision \kbd{prec}. \fun{GEN}{mpeuler}{long prec} returns Euler-Mascheroni's constant at precision \kbd{prec}. \fun{GEN}{mpeuler}{long prec} returns Catalan's number at precision \kbd{prec}. \fun{GEN}{mplog2}{long prec} returns $\log 2$ at precision \kbd{prec}. \fun{GEN}{bernreal}{long i, long prec} returns the \idx{Bernoulli} number $B_i$ as a \typ{REAL} at precision \kbd{prec}. If \kbd{mpbern(n, p)} was called previously with $n \geq i$ and $p \geq \kbd{prec}$, then the cached value is (converted to a \typ{REAL} of accuracy \kbd{prec} then) returned. Otherwise, the missing value is computed. In the latter case, if $n \geq i$, the cached table is updated. \fun{GEN}{bernfrac}{long i} returns the \idx{Bernoulli} number $B_i$ as a rational number (\typ{FRAC} or \typ{INT}). If a cached table includes $B_i$ as a rational number, the latter is returned. Otherwise, the missing value is computed. In the latter case, the cached Bernoulli table may be updated. \section{Permutations } \noindent Permutation are represented in two different ways \item (\kbd{perm}) a \typ{VECSMALL} $p$ representing the bijection $i\mapsto p[i]$; unless mentioned otherwise, this is the form used in the functions below for both input and output, \item (\kbd{cyc}) a \typ{VEC} of \typ{VECSMALL}s representing a product of disjoint cycles. \fun{GEN}{identity_perm}{long n} return the identity permutation on $n$ symbols. \fun{GEN}{cyclic_perm}{long n, long d} return the cyclic permutation mapping $i$ to $i+d$ (mod $n$) in $S_n$. Assume that $d \leq n$. \fun{GEN}{perm_mul}{GEN s, GEN t} multiply $s$ and $t$ (composition $s\circ t$) \fun{GEN}{perm_conj}{GEN s, GEN t} return $sts^{-1}$. \fun{int}{perm_commute}{GEN p, GEN q} return $1$ if $p$ and $q$ commute, 0 otherwise. \fun{GEN}{perm_inv}{GEN p} returns the inverse of $p$. \fun{GEN}{perm_pow}{GEN p, long n} returns $p^n$ \fun{GEN}{cyc_pow_perm}{GEN p, long n} the permutation $p$ is given as a product of disjoint cycles (\kbd{cyc}); return $p^n$ (as a \kbd{perm}). \fun{GEN}{cyc_pow}{GEN p, long n} the permutation $p$ is given as a product of disjoint cycles (\kbd{cyc}); return $p^n$ (as a \kbd{cyc}). \fun{GEN}{perm_cycles}{GEN p} return the cyclic decomposition of $p$. \fun{long}{perm_order}{GEN p} returns the order of the permutation $p$ (as the lcm of its cycle lengths). \fun{GEN}{vecperm_orbits}{GEN p, long n} the permutation $p\in S_n$ being given as a product of disjoint cycles, return the orbits of the subgroup generated by $p$ on $\{1,2,\ldots,n\}$. \section{Small groups} The small (finite) groups facility is meant to deal with subgroups of Galois groups obtained by \tet{galoisinit} and thus is currently limited to weakly super-solvable groups. A group \var{grp} of order $n$ is represented by its regular representation (for an arbitrary ordering of its element) in $S_n$. A subgroup of such group is represented by the restriction of the representation to the subgroup. A \emph{small group} can be either a group or a subgroup. Thus it is embedded in some $S_n$, where $n$ is the multiple of the order. Such $n$ is called the \emph{domain} of the small group. The domain of a trivial subgroup cannot be derived from the subgroup data, so some functions require the subgroup domain as argument. The small group \var{grp} is represented by a \typ{VEC} with two components: $\var{grp}[1]$ is a generating subset $[s_1,\ldots,s_g]$ of \var{grp} expressed as a vector of permutation of length $n$. $\var{grp}[2]$ contains the relative orders $[o_1,\ldots,o_g]$ of the generators $\var{grp}[1]$. See \tet{galoisinit} for the technical details. \fun{GEN}{checkgroup}{GEN gal, GEN *elts} checks whether \var{gal} is a small group or a Galois group. Returns the underlying small group and set \var{elts} to the list of elements or to \kbd{NULL} if it is not known. \fun{GEN}{galois_group}{GEN gal} return the underlying small group of the Galois group \var{gal}. \fun{GEN}{cyclicgroup}{GEN g, long s} returns the cyclic group with generator $g$ of order $s$. \fun{GEN}{trivialgroup}{void} returns the trivial group. \fun{GEN}{dicyclicgroup}{GEN g1, GEN g2, long s1, long s2} returns the group with generators \var{g1}, \var{g2} with respecting relative orders \var{s1}, \var{s2}. \fun{GEN}{abelian_group}{GEN v} let v be a \typ{VECSMALL} seen as the SNF of a small abelian group, return its regular representation. \fun{long}{group_domain}{GEN grp} returns the \kbd{domain} of the \emph{non-trivial} small group \var{grp}. Return an error if \var{grp} is trivial. \fun{GEN}{group_elts}{GEN grp, long n} returns the list of elements of the small group \var{grp} of domain \var{n} as permutations. \fun{GEN}{group_set}{GEN grp, long n} returns a \var{F2v} $b$ such that $b[i]$ is set if and only if the small group \var{grp} of domain \var{n} contains a permutation sending $1$ to $i$. \fun{GEN}{groupelts_set}{GEN elts, long n}, where \var{elts} is the list of elements of a small group of domain \var{n}, returns a \var{F2v} $b$ such that $b[i]$ is set if and only if the small group contains a permutation sending $1$ to $i$. \fun{long}{group_order}{GEN grp} returns the order of the small group \var{grp} (which is the product of the relative orders). \fun{long}{group_isabelian}{GEN grp} returns $1$ the the small group \var{grp} is Abelian, else $0$. \fun{GEN}{group_abelianHNF}{GEN grp, GEN elts} if \var{grp} is not Abelian, returns \kbd{NULL}, else returns the HNF matrix of \var{grp} with respect to the generating family $\var{grp}[1]$. If \var{elts} is no \kbd{NULL}, it must be the list of elements of \var{grp}. \fun{GEN}{group_abelianSNF}{GEN grp, GEN elts} if \var{grp} is not Abelian, returns \kbd{NULL}, else returns its cyclic decomposition. If \var{elts} is no \kbd{NULL}, it must be the list of elements of \var{grp}. \fun{long}{group_subgroup_isnormal}{GEN G, GEN H}, $H$ being a subgroup of the small group $G$, returns $1$ if $H$ is normal in $G$, else $0$. \fun{long}{group_isA4S4}{GEN grp} returns $1$ if the small group \var{grp} is isomorphic to $A_4$, $2$ if it is isomorphic to $S_4$ and $0$ else. This is mainly to deal with the idiosyncrasy of the format. \fun{GEN}{group_leftcoset}{GEN G, GEN g} where $G$ is a small group and $g$ a permutation of the same domain, the the left coset $gG$ as a vector of permutations. \fun{GEN}{group_rightcoset}{GEN G, GEN g} where $G$ is a small group and $g$ a permutation of the same domain, the the right coset $Gg$ as a vector of permutations. \fun{long}{group_perm_normalize}{GEN G, GEN g} where $G$ is a small group and $g$ a permutation of the same domain, return $1$ if $gGg^-1=G$, else $0$. \fun{GEN}{group_quotient}{GEN G, GEN H}, where $G$ is a small group and $H$ is a subgroup of $G$, returns the quotient map $G\rightarrow G/H$ as an abstract data structure. \fun{GEN}{quotient_perm}{GEN C, GEN g} where $C$ is the quotient map $G\rightarrow G/H$ for some subgroup $H$ of $G$ and $g$ an element of $G$, return the image of $g$ by $C$ (i.e. the coset $gH$). \fun{GEN}{quotient_group}{GEN C, GEN G} where $C$ is the quotient map $G\rightarrow G/H$ for some \emph{normal} subgroup $H$ of $G$, return the quotient group $G/H$ as a small group. \fun{GEN}{quotient_subgroup_lift}{GEN C, GEN H, GEN S} where $C$ is the quotient map $G\rightarrow G/H$ for some group $G$ normalizing $H$ and $S$ is a subgroup of $G/H$, return the inverse image of $S$ by $C$. \fun{GEN}{group_subgroups}{GEN grp} returns the list of subgroups of the small group \var{grp} as a \typ{VEC}. \fun{GEN}{subgroups_tableset}{GEN S, long n} where $S$ is a vector of subgroups of domain $n$, returns a table which matchs the set of elements of the subgroups against the index of the subgroups. \fun{long}{tableset_find_index}{GEN tbl, GEN set} searchs the set \kbd{set} in the table \kbd{tbl} and returns its associated index, or $0$ if not found. \fun{GEN}{groupelts_abelian_group}{GEN elts} where \var{elts} is the list of elements of an \emph{Abelian} small group, returns the corresponding small group. \fun{GEN}{groupelts_center}{GEN elts} where \var{elts} is the list of elements of a small group, returns the list of elements of the center of the group. \fun{GEN}{group_export}{GEN grp, long format} exports a small group to another format, see \tet{galoisexport}. \fun{long}{group_ident}{GEN grp, GEN elts} returns the index of the small group \var{grp} in the GAP4 Small Group library, see \tet{galoisidentify}. If \var{elts} is not \kbd{NULL}, it must be the list of elements of \var{grp}. \fun{long}{group_ident_trans}{GEN grp, GEN elts} returns the index of the regular representation of the small group \var{grp} in the GAP4 Transitive Group library, see \tet{polgalois}. If \var{elts} is no \kbd{NULL}, it must be the list of elements of \var{grp}. \newpage \chapter{Standard data structures} \section{Character strings} \subsec{Functions returning a \kbd{char *}} \fun{char*}{pari_strdup}{const char *s} returns a malloc'ed copy of $s$ (uses \kbd{pari\_malloc}). \fun{char*}{pari_strndup}{const char *s, long n} returns a malloc'ed copy of at most $n$ chars from $s$ (uses \kbd{pari\_malloc}). If $s$ is longer than $n$, only $n$ characters are copied and a terminal null byte is added. \fun{char*}{stack_strdup}{const char *s} returns a copy of $s$, allocated on the PARI stack (uses \kbd{stack\_malloc}). \fun{char*}{stack_strcat}{const char *s, const char *t} returns the concatenation of $s$ and $t$, allocated on the PARI stack (uses \kbd{stack\_malloc}). \fun{char*}{stack_sprintf}{const char *fmt, ...} runs \kbd{pari\_sprintf} on the given arguments, returning a string allocated on the PARI stack. \fun{char*}{itostr}{GEN x} writes the \typ{INT} $x$ to a \tet{stack_malloc}'ed string. \fun{char*}{GENtostr}{GEN x}, using the current default output format (\kbd{GP\_DATA->fmt}, which contains the output style and the number of significant digits to print), converts $x$ to a malloc'ed string. Simple variant of \tet{pari_sprintf}. \fun{char*}{GENtostr_unquoted}{GEN x} as \tet{GENtostr} with the following differences: 1) a \typ{STR} $x$ is printed without enclosing quotes (to be used by \kbd{print}); 2) the result is allocated on the stack and \emph{must not} be freed. \fun{char*}{GENtoTeXstr}{GEN x}, as \kbd{GENtostr}, except that \tet{f_TEX} overrides the output format from \kbd{GP\_DATA->fmt}. \fun{char*}{RgV_to_str}{GEN g, long flag} $g$ being a vector of \kbd{GEN}s, returns a malloc'ed string, the concatenation of the \kbd{GENtostr} applied to its elements, except that \typ{STR} are printed without enclosing quotes. \kbd{flag} determines the output format: \tet{f_RAW}, \tet{f_PRETTYMAT} or \tet{f_TEX}. \subsec{Functions returning a \typ{STR}} \fun{GEN}{strtoGENstr}{const char *s} returns a \typ{STR} with content $s$. \fun{GEN}{strntoGENstr}{const char *s, long n} returns a \typ{STR} containing the first $n$ characters of $s$. \fun{GEN}{chartoGENstr}{char c} returns a \typ{STR} containing the character $c$. \fun{GEN}{GENtoGENstr}{GEN x} returns a \typ{STR} containing the printed form of $x$ (in \tet{raw} format). This is often easier to use that \tet{GENtostr} (which returns a malloc-ed \kbd{char*}) since there is no need to free the string after use. \fun{GEN}{GENtoGENstr_nospace}{GEN x} as \kbd{GENtoGENstr}, removing all spaces from the output. \fun{GEN}{Str}{GEN g} as \tet{RgV_to_str} with output format \tet{f_RAW}, but returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{Strtex}{GEN g} as \tet{RgV_to_str} with output format \tet{f_TEX}, but returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{Strexpand}{GEN g} as \tet{RgV_to_str} with output format \tet{f_RAW}, performing tilde and environment expansion on the result. Returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{gsprintf}{const char *fmt, ...} equivalent to \kbd{pari\_sprintf(fmt,...}, followed by \tet{strtoGENstr}. Returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{gvsprintf}{const char *fmt, va_list ap} variadic version of \tet{gsprintf} \section{Output} \subsec{Output contexts} An output coutext, of type \tet{PariOUT}, is a \kbd{struct} that models a stream and contains the following function pointers: \bprog void (*putch)(char); /* fputc()-alike */ void (*puts)(const char*); /* fputs()-alike */ void (*flush)(void); /* fflush()-alike */ @eprog\noindent The methods \tet{putch} and \tet{puts} are used to print a character or a string respectively. The method \tet{flush} is called to finalize a messages. The generic functions \tet{pari_putc}, \tet{pari_puts}, \tet{pari_flush} and \tet{pari_printf} print according to a \emph{default output context}, which should be sufficient for most purposes. Lower level functions are available, which take an explicit output context as first argument: \fun{void}{out_putc}{PariOUT *out, char c} essentially equivalent to \kbd{out->putc(c)}. In addition, registers whether the last character printed was a \kbd{\bs n}. \fun{void}{out_puts}{PariOUT *out, const char *s} essentially equivalent to \kbd{out->puts(s)}. In addition, registers whether the last character printed was a \kbd{\bs n}. \fun{void}{out_printf}{PariOUT *out, const char *fmt, ...} \fun{void}{out_vprintf}{PariOUT *out, const char *fmt, va_list ap} \noindent N.B. The function \kbd{out\_flush} does not exist since it would be identical to \kbd{out->flush()} \fun{int}{pari_last_was_newline}{void} returns a non-zero value if the last character printed via \tet{out_putc} or \tet{out_puts} was \kbd{\bs n}, and $0$ otherwise. \fun{void}{pari_set_last_newline}{int last} sets the boolean value to be returned by the function \tet{pari_last_was_newline} to \var{last}. \subsec{Default output context} They are defined by the global variables \tet{pariOut} and \tet{pariErr} for normal outputs and warnings/errors, and you probably do not want to change them. If you \emph{do} change them, diverting output in non-trivial ways, this probably means that you are rewriting \kbd{gp}. For completeness, we document in this section what the default output contexts do. \misctitle{pariOut} writes output to the \kbd{FILE*} \tet{pari_outfile}, initialized to \tet{stdout}. The low-level methods are actually the standard \kbd{putc} / \kbd{fputs}, plus some magic to handle a log file if one is open. \misctitle{pariErr} prints to the \kbd{FILE*} \tet{pari_errfile}, initialized to \tet{stderr}. The low-level methods are as above. You can stick with the default \kbd{pariOut} output context and change PARI's standard output, redirecting \tet{pari_outfile} to another file, using \fun{void}{switchout}{const char *name} where \kbd{name} is a character string giving the name of the file you want to write to; the output is \emph{appended} at the end of the file. To close the file and revert to outputting to \kbd{stdout}, call \kbd{switchout(NULL)}. \subsec{PARI colors} In this section we describe the low-level functions used to implement GP's color scheme, associated to the \tet{colors} default. The following symbolic names are associated to gp's output strings: \item \tet{c_ERR} an error message \item \tet{c_HIST} a history number (as in \kbd{\%1 = ...}) \item \tet{c_PROMPT} a prompt \item \tet{c_INPUT} an input line (minus the prompt part) \item \tet{c_OUTPUT} an output \item \tet{c_HELP} a help message \item \tet{c_TIME} a timer \item \tet{c_NONE} everything else \emph{If} the \tet{colors} default is set to a non-empty value, before gp outputs a string, it first outputs an ANSI colors escape sequence --- understood by most terminals ---, according to the \kbd{colors} specifications. As long as this is in effect, the following strings are rendered in color, possibly in bold or underlined. \fun{void}{term_color}{long c} prints (as if using \tet{pari_puts}) the ANSI color escape sequence associated to output object \kbd{c}. If \kbd{c} is \tet{c_NONE}, revert to default printing style. \fun{void}{out_term_color}{PariOUT *out, long c} as \tet{term_color}, using output context \kbd{out}. \fun{char*}{term_get_color}{char *s, long c} returns as a character string the ANSI color escape sequence associated to output object \kbd{c}. If \kbd{c} is \tet{c_NONE}, the value used to revert to default printing style is returned. The argument \kbd{s} is either \kbd{NULL} (string allocated on the PARI stack), or preallocated storage (in which case, it must be able to hold at least 16 chars, including the final \kbd{\bs 0}). \subsec{Obsolete output functions} These variants of \fun{void}{output}{GEN x}, which prints \kbd{x}, followed by a newline and a buffer flush are complicated to use and less flexible than what we saw above, or than the \tet{pari_printf} variants. They are provided for backward compatibility and are scheduled to disappear. \fun{void}{brute}{GEN x, char format, long dec} \fun{void}{matbrute}{GEN x, char format, long dec} \fun{void}{texe}{GEN x, char format, long dec} \section{Files} The following routines are trivial wrappers around system functions (possibly around one of several functions depending on availability). They are usually integrated within PARI's diagnostics system, printing messages if \kbd{DEBUGFILES} is high enough. \fun{int}{pari_is_dir}{const char *name} returns $1$ if \kbd{name} points to a directory, $0$ otherwise. \fun{int}{pari_is_file}{const char *name} returns $1$ if \kbd{name} points to a directory, $0$ otherwise. \fun{int}{file_is_binary}{FILE *f} returns $1$ if the file $f$ is a binary file (in the \tet{writebin} sense), $0$ otherwise. \fun{void}{pari_unlink}{const char *s} deletes the file named $s$. Warn if the operation fails. \fun{void}{pari_fread_chars}{void *b, size_t n, FILE *f} read $n$ chars from stream $f$, storing the result in pre-allocated buffer $b$ (assumed to be large enough). \fun{char*}{path_expand}{const char *s} perform tilde and environment expansion on $s$. Returns a \kbd{malloc}'ed buffer. \fun{void}{strftime_expand}{const char *s, char *buf, long max} perform time expansion on $s$, storing the result (at most \kbd{max} chars) in buffer \kbd{buf}. Trivial wrapper around \bprog time_t t = time(NULL); strftime(but, max, s, localtime(&t); @eprog \fun{char*}{pari_get_homedir}{const char *user} expands \kbd{\til user} constructs, returning the home directory of user \kbd{user}, or \kbd{NULL} if it could not be determined (in particular if the operating system has no such concept). The return value may point to static area and may be overwritten by subsequent system calls: use immediately or \kbd{strdup} it. \fun{int}{pari_stdin_isatty}{void} returns $1$ if our standard input \kbd{stdin} is attached to a terminal. Trivial wrapper around \kbd{isatty}. \subsec{pariFILE} PARI maintains a linked list of open files, to reclaim resources (file descriptors) on error or interrupts. The corresponding data structure is a \kbd{pariFILE}, which is a wrapper around a standard \kbd{FILE*}, containing further the file name, its type (regular file, pipe, input or output file, etc.). The following functions create and manipulate this structure; they are integrated within PARI's diagnostics system, printing messages if \kbd{DEBUGFILES} is high enough. \fun{pariFILE*}{pari_fopen}{const char *s, const char *mode} wrapper around \kbd{fopen(s, mode)}, return \kbd{NULL} on failure. \fun{pariFILE*}{pari_fopen_or_fail}{const char *s, const char *mode} simple wrapper around \kbd{fopen(s, mode)}; error on failure. \fun{pariFILE*}{pari_fopengz}{const char *s} opens the file whose name is $s$, and associates a (read-only) \kbd{pariFILE} with it. If $s$ is a compressed file (\kbd{.gz} suffix), it is uncompressed on the fly. If $s$ cannot be opened, also try to open \kbd{$s$.gz}. Returns \kbd{NULL} on failure. \fun{void}{pari_fclose}{pariFILE *f} closes the underlying file descriptor and deletes the \kbd{pariFILE} struct. \fun{pariFILE*}{pari_safefopen}{const char *s, const char *mode} creates a \emph{new} file $s$ (a priori for writing) with \kbd{600} permissions. Error if the file already exists. To avoid symlink attacks, a symbolic link exists, regardless of where it points to. \subsec{Temporary files} PARI has its own idea of the system temp directory derived from from an environment variable (\kbd{\$GPTMPDIR}, else \kbd{\$TMPDIR}), or the first writable directory among \kbd{/tmp}, \kbd{/var/tmp} and \kbd{.}. \fun{char*}{pari_unique_dir}{const char *s} creates a ``unique directory'' and return its name built from the string $s$, the user id and process pid (on Unix systems). This directory is itself located in the temp directory mentioned above. The name returned is \tet{malloc}'ed. \fun{char*}{pari_unique_filename}{const char *s} creates a \emph{new} empty file in the temp directory, whose name contains the id-string $s$ (truncated to its first $8$ chars), followed by a system-dependent suffix (incorporating the ids of both the user and the running process, for instance). The function returns the tempfile name. The name returned is \tet{malloc}'ed. \section{Errors}\label{se:errors} This section documents the various error classes, and the corresponding arguments to \tet{pari_err}. The general syntax is \fun{void}{pari_err}{numerr,...} \noindent In the sequel, we mostly use sequences of arguments of the form \bprog const char *s const char *fmt, ... @eprog\noindent where \kbd{fmt} is a PARI format, producing a string $s$ from the remaining arguments. Since providing the correct arguments to \tet{pari_err} is quite error-prone, we also provide specialized routines \kbd{pari\_err\_\var{ERRORCLASS}(\dots)} instead of \kbd{pari\_err(e\_\var{ERRORCLASS}, \dots)} so that the C compiler can check their arguments. \noindent We now inspect the list of valid keywords (error classes) for \kbd{numerr}, and the corresponding required arguments. \subsec{Internal errors, ``system'' errors} \subsubsec{e\_ARCH} A requested feature $s$ is not available on this architecture or operating system. \bprog pari_err(e_ARCH) @eprog\noindent prints the error message: \kbd{sorry, '$s$' not available on this system}. \subsubsec{e\_BUG} A bug in the PARI library, in function $s$. \bprog pari_err(e_BUG, const char *s) pari_err_BUG(const char *s) @eprog\noindent prints the error message: \kbd{Bug in $s$, please report}. \subsubsec{e\_FILE} Error while trying to open a file. \bprog pari_err(e_FILE, const char *what, const char *name) pari_err_FILE(const char *what, const char *name) @eprog\noindent prints the error message: \kbd{error opening \emph{what}: `\emph{name}'}. \subsubsec{e\_IMPL} A requested feature $s$ is not implemented. \bprog pari_err(e_IMPL, const char *s) pari_err_IMPL(const char *s) @eprog\noindent prints the error message: \kbd{sorry, $s$ is not yet implemented}. \subsubsec{e\_PACKAGE} Missing optional package $s$. \bprog pari_err(e_PACKAGE, const char *s) pari_err_PACKAGE(const char *s) @eprog\noindent prints the error message: \kbd{package $s$ is required, please install it} \subsec{Syntax errors, type errors} \subsubsec{e\_DIM} arguments submitted to function $s$ have inconsistent dimensions. E.g., when solving a linear system, or trying to compute the determinant of a non-square matrix. \bprog pari_err(e_DIM, const char *s) pari_err_DIM(const char *s) @eprog\noindent prints the error message: \kbd{inconsistent dimensions in $s$}. \subsubsec{e\_FLAG} A flag argument is out of bounds in function $s$. \bprog pari_err(e_FLAG, const char *s) pari_err_FLAG(const char *s) @eprog\noindent prints the error message: \kbd{invalid flag in $s$}. \subsubsec{e\_NOTFUNC} Generated by the PARI evaluator; tried to use a \kbd{GEN} which is not a \typ{CLOSURE} in a function call syntax (as in \kbd{f = 1; f(2);}). \bprog pari_err(e_NOTFUNC, GEN fun) @eprog\noindent prints the error message: \kbd{not a function in a function call}. \subsubsec{e\_OP} Impossible operation between two objects than cannot be typecast to a sensible common domain for deeper reasons than a type mismatch, usually for arithmetic reasons. As in \kbd{O(2) + O(3)}: it is valid to add two \typ{PADIC}s, provided the underlying prime is the same; so the addition is not forbidden a priori for type reasons, it only becomes so when inspecting the objects and trying to perform the operation. \bprog pari_err(e_OP, const char *op, GEN x, GEN y) pari_err_OP(const char *op, GEN x, GEN y) @eprog\noindent As \kbd{e\_TYPE2}, replacing \kbd{forbidden} by \kbd{inconsistent}. \subsubsec{e\_PRIORITY} object $o$ in function $s$ contains variables whose priority is incompatible with the expected operation. E.g.~\kbd{Pol([x,1], 'y)}: this raises an error because it's not possible to create a polynomial whose coefficients involve variables with higher priority than the main variable. \bprog pari_err(e_PRIORITY, const char *s, GEN o, const char *op, long v) pari_err_PRIORITY(const char *s, GEN o, const char *op, long v) @eprog\noindent prints the error message: \kbd{incorrect priority in $s$, variable $v_o$ \var{op} $v$}, were $v_o$ is \kbd{gvar(o)}. \subsubsec{e\_SYNTAX} Syntax error, generated by the PARI parser. \bprog pari_err(e_SYNTAX, const char *msg, const char *e, const char *entry) @eprog\noindent where \kbd{msg} is a complete error message, and \kbd{e} and \kbd{entry} point into the \emph{same} character string, which is the input that was incorrectly parsed: \kbd{e} points to the character where the parser failed, and $\kbd{entry}\leq \kbd{e}$ points somewhat before. \noindent Prints the error message: \kbd{msg}, followed by a colon, then a part of the input character string (in general \kbd{entry} itself, but an initial segment may be truncated if $\kbd{e}-\kbd{entry}$ is large); a caret points at \kbd{e}, indicating where the error took place. \subsubsec{e\_TYPE} An argument $x$ of function $s$ had an unexpected type. (As in \kbd{factor("blah")}.) \bprog pari_err(e_TYPE, const char *s, GEN x) pari_err_TYPE(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{incorrect type in $s$ (\typ{$x$})}, where \typ{$x$} is the type of $x$. \subsubsec{e\_TYPE2} Forbidden operation between two objects than cannot be typecast to a sensible common domain, because their types do not match up. (As in \kbd{Mod(1,2) + Pi}.) \bprog pari_err(e_TYPE2, const char *op, GEN x, GEN y) pari_err_TYPE2(const char *op, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{forbidden} $s$ \typ{$x$} \var{op} \typ{$y$}, where \typ{$z$} denotes the type of $z$. Here, $s$ denotes the spelled out name of the operator $\var{op}\in\{\kbd{+}, \kbd{*}, \kbd{/}, \kbd{\%}, \kbd{=}\}$, e.g. \emph{addition} for \kbd{"+"} or \emph{assignment} for \kbd{"="}. If \var{op} is not in the above operator, list, it is taken to be the already spelled out name of a function, e.g. \kbd{"gcd"}, and the error message becomes \kbd{forbidden} \var{op} \typ{$x$}, \typ{$y$}. \subsubsec{e\_VAR} polynomials $x$ and $y$ submitted to function $s$ have inconsistent variables. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(x\pow2+1)}. \bprog pari_err(e_VAR, const char *s, GEN x, GEN y) pari_err_VAR(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{inconsistent variables in $s$ $X$ != $Y$}, where $X$ and $Y$ are the names of the variables of $x$ and $y$, respectively. \subsec{Overflows} \subsubsec{e\_COMPONENT} Trying to access an inexistent component in a vector/matrix/list in a function: the index is less than $1$ or greater than the allowed length. \bprog pari_err(e_COMPONENT, const char *f, const char *op, GEN lim, GEN x) pari_err_COMPONENT(const char *f, const char *op, GEN lim, GEN x) @eprog\noindent prints the error message: \kbd{non-existent component in $f$: index \var{op} \var{lim}}. Special case: if $f$ is the empty string (no meaningful public function name can be used), we ignore it and print the message: \kbd{non-existent component: index \var{op} \var{lim}}. \subsubsec{e\_DOMAIN} An argument $x$ is not in the function's domain (as in \kbd{moebius(0)} or \kbd{zeta(1)}). \bprog pari_err(e_DOMAIN, char *f, char *v, char *op, GEN lim, GEN x) pari_err_DOMAIN(char *f, char *v, char *op, GEN lim, GEN x) @eprog\noindent prints the error message: \kbd{domain error in $f$: $v$ \var{op} \var{lim}}. Special case: if \var{op} is the empty string, we ignore \var{lim} and print the error message: \kbd{domain error in $f$: $v$ out of range}. \subsubsec{e\_MAXPRIME} A function using the precomputed list of prime numbers ran out of primes. \bprog pari_err(e_MAXPRIME, ulong c) pari_err_MAXPRIME(ulong c) @eprog\noindent prints the error message: \kbd{not enough precomputed primes, need primelimit \til $c$} if $c$ is non-zero. And simply \kbd{not enough precomputed primes} otherwise. \subsubsec{e\_MEM} A call to \tet{pari_malloc} or \tet{pari_realloc} failed. \bprog pari_err(e_MEM) @eprog\noindent prints the error message: \kbd{not enough memory}. \subsubsec{e\_OVERFLOW} An object in function $s$ becomes too large to be represented within PARI's hardcoded limits. (As in \kbd{2\pow2\pow2\pow10} or \kbd{exp(1e100)}, which overflow in \kbd{lg} and \kbd{expo}.) \bprog pari_err(e_OVERFLOW, const char *s) pari_err_OVERFLOW(const char *s) @eprog\noindent prints the error message: \kbd{overflow in $s$}. \subsubsec{e\_PREC} Function $s$ fails because input accuracy is too low. (As in \kbd{floor(1e100)} at default accuracy.) \bprog pari_err(e_PREC, const char *s) pari_err_PREC(const char *s) @eprog\noindent prints the error message: \kbd{precision too low in $s$}. \subsubsec{e\_STACK} The PARI stack overflows. \bprog pari_err(e_STACK) @eprog\noindent prints the error message: \kbd{the PARI stack overflows !} as well as some statistics concerning stack usage. \subsec{Errors triggered intentionally} \subsubsec{e\_ALARM} A timeout, generated by the \tet{alarm} function. \bprog pari_err(e_ALARM, const char *fmt, ...) @eprog\noindent prints the error message: $s$. \subsubsec{e\_USER} A user error, as triggered by \tet{error}($g_1,\dots,g_n)$ in GP. \bprog pari_err(e_USER, GEN g) @eprog\noindent prints the error message: \kbd{user error:}, then the entries of the vector $g$. \subsec{Mathematical errors} \subsubsec{e\_CONSTPOL} An argument of function $s$ is a constant polynomial, which does not make sense. (As in \kbd{galoisinit(Pol(1))}.) \bprog pari_err(e_CONSTPOL, const char *s) pari_err_CONSTPOL(const char *s) @eprog\noindent prints the error message: \kbd{constant polynomial in $s$}. \subsubsec{e\_COPRIME} Function $s$ expected two coprime arguments, and did receive $x$, $y$ which were not. \bprog pari_err(e_COPRIME, const char *s, GEN x, GEN y) pari_err_COPRIME(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{elements not coprime in $s$: $x, y$}. \subsubsec{e\_INV} Tried to invert a non-invertible object $x$. \bprog pari_err(e_INV, GEN x) pari_err_INV(GEN x) @eprog\noindent prints the error message: \kbd{impossible inverse: $x$}. If $x = \kbd{Mod}(a,b)$ is a \typ{INTMOD} and $a$ is not $0$ mod $b$, this allows to factor the modulus, as \kbd{gcd}$(a,b)$ is a non-trivial divisor of $b$. \subsubsec{e\_IRREDPOL} Function $s$ expected an irreducible polynomial, and did not receive one. (As in \kbd{nfinit(x\pow2-1)}.) \bprog pari_err(e_IRREDPOL, const char *s, GEN x) pari_err_IRREDPOL(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{not an irreducible polynomial in $s$: $x$}. \subsubsec{e\_MISC} Generic uncategorized error. \bprog pari_err(e_MISC, const char *fmt, ...) @eprog\noindent prints the error message: $s$. \subsubsec{e\_MODULUS} moduli $x$ and $y$ submitted to function $s$ are inconsistent. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(t\pow3-2)}. \bprog pari_err(e_MODULUS, const char *s, GEN x, GEN y) pari_err_MODULUS(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{inconsistent moduli in $s$}, then the moduli. \subsubsec{e\_PRIME} Function $s$ expected a prime number, and did receive $p$, which was not. (As in \kbd{idealprimedec(nf, 4)}.) \bprog pari_err(e_PRIME, const char *s, GEN x) pari_err_PRIME(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{not a prime in $s$: $x$}. \subsubsec{e\_ROOTS0} An argument of function $s$ is a zero polynomial, and we need to consider its roots. (As in \kbd{polroots(0)}.) \bprog pari_err(e_ROOTS0, const char *s) pari_err_ROOTS0(const char *s) @eprog\noindent prints the error message: \kbd{zero polynomial in $s$}. \subsubsec{e\_SQRTN} Tried to compute an $n$-th root of $x$, which does not exist, in function $s$. (As in \kbd{sqrt(Mod(-1,3))}.) \bprog pari_err(e_SQRTN, GEN x) pari_err_SQRTN(GEN x) @eprog\noindent prints the error message: \kbd{not an n-th power residue in $s$: $x$}. \subsec{Miscellaneous functions} \fun{long}{name_numerr}{const char *s} return the error number corresponding to an error name. E.g. \kbd{name\_numerr("e\_DIM")} returns \kbd{e\_DIM}. \fun{const char*}{numerr_name}{long errnum} returns the error name corresponding to an error number. E.g. \kbd{name\_numerr(e\_DIM)} returns \kbd{"e\_DIM"}. \fun{char*}{pari_err2str}{GEN err} returns the error message that would be printed on \typ{ERROR} \kbd{err}. The name is allocated on the PARI stack and must not be freed. \section{Hashtables} A \tet{hashtable}, or associative array, is a set of pairs $(k,v)$ of keys and values. PARI implements general extensible hashtables for fast data retrieval: when creating a table, we may either choose to use the PARI stack, or \kbd{malloc} so as to be stack-independent. A hashtable is implemented as a table of linked lists, each list containing all entries sharing the same hash value. The table length is a prime number, which roughly doubles as the table overflows by gaining new entries; both the current number of entries and the threshold before the table grows are stored in the table. Finally the table remembers the functions used to hash the entries's keys and to test for equality two entries hashed to the same value. An entry, or \tet{hashentry}, contains \item a key/value pair $(k,v)$, both of type \kbd{void*} for maximal flexibility, \item the hash value of the key, for the table hash function. This hash is mapped to a table index (by reduction modulo the table length), but it contains more information, and is used to bypass costly general equality tests if possible, \item a link pointer to the next entry sharing the same table cell. \bprog typedef struct { void *key, *val; ulong hash; /* hash(key) */ struct hashentry *next; } hashentry; typedef struct { ulong len; /* table length */ hashentry **table; /* the table */ ulong nb, maxnb; /* number of entries stored and max nb before enlarging */ ulong pindex; /* prime index */ ulong (*hash) (void *k); /* hash function */ int (*eq) (void *k1, void *k2); /* equality test */ int use_stack; /* use the PARI stack, resp. malloc */ } hashtable; @eprog\noindent \fun{hashtable*}{hash_create}{size, hash, eq, use_stack} \vskip -1em % switch to K&R style to avoid atrocious line break \bprog ulong size; ulong (*hash)(void*); int (*eq)(void*,void*); int use_stack; @eprog\noindent creates a hashtable with enough room to contain \kbd{size} entries. The functions \kbd{hash} and \kbd{eq} compute the hash 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{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 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_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{void}{hash_destroy}{hashtable *h} deletes the hashtable, by removing all entries. Some interesting hash functions are available: \fun{ulong}{hash_str}{const char *s} \fun{ulong}{hash_str2}{const char *s} is the historical PARI string hashing function and seems to be generally inferior to \kbd{hash\_str}. \fun{ulong}{hash_GEN}{GEN x} \section{Dynamic arrays} A \teb{dynamic array} is a generic way to manage stacks of data that need to grow dynamically. It allocates memory using \kbd{pari\_malloc}, and is independent of the PARI stack; it even works before the \kbd{pari\_init} call. \subsec{Initialization} To create a stack of objects of type \kbd{foo}, we proceed as follows: \bprog foo *t_foo; pari_stack s_foo; pari_stack_init(&s_foo, sizeof(*t_foo), (void**)t_foo); @eprog\noindent Think of \kbd{s\_foo} as the controlling interface, and \kbd{t\_foo} as the (dynamic) array tied to it. The value of \kbd{t\_foo} may be changed as you add more elements. \subsec{Adding elements} The following function pushes an element on the stack. \bprog /* access globals t_foo and s_foo */ void push_foo(foo x) { long n = pari_stack_new(&s_foo); t_foo[n] = x; } @eprog \subsec{Accessing elements} Elements are accessed naturally through the \kbd{t\_foo} pointer. For example this function swaps two elements: \bprog void swapfoo(long a, long b) { foo x; if (a > s_foo.n || b > s_foo.n) pari_err_BUG("swapfoo"); x = t_foo[a]; t_foo[a] = t_foo[b]; t_foo[b] = x; } @eprog \subsec{Stack of stacks} Changing the address of \kbd{t\_foo} is not supported in general. In particular \kbd{realloc()}'ed array of stacks and stack of stacks are not supported. \subsec{Public interface} Let \kbd{s} be a \kbd{pari\_stack} and \kbd{data} the data linked to it. The following public fields are defined: \item \kbd{s.alloc} is the number of elements allocated for \kbd{data}. \item \kbd{s.n} is the number of elements in the stack and \kbd{data[s.n-1]} is the topmost element of the stack. \kbd{s.n} can be changed as long as $0\leq\kbd{s.n}\leq\kbd{s.alloc}$ holds. \fun{void}{pari_stack_init}{pari_stack *s, size_t size, void **data} links \kbd{*s} to the data pointer \kbd{*data}, where \kbd{size} is the size of data element. The pointer \kbd{*data} is set to \kbd{NULL}, \kbd{s->n} and \kbd{s->alloc} are set to $0$: the array is empty. \fun{void}{pari_stack_alloc}{pari_stack *s, long nb} makes room for \kbd{nb} more elements, i.e.~makes sure that $\kbd{s.alloc}\geq\kbd{s.n} + \kbd{nb}$, possibly reallocating \kbd{data}. \fun{long}{pari_stack_new}{pari_stack *s} increases \kbd{s.n} by one unit, possibly reallocating \kbd{data}, and returns $\kbd{s.n}-1$. \misctitle{Caveat} The following construction is incorrect because \kbd{stack\_new} can change the value of \kbd{t\_foo}: \bprog t_foo[ pari_stack_new(&s_foo) ] = x; @eprog \fun{void}{pari_stack_delete}{pari_stack *s} frees \kbd{data} and resets the stack to the state immediately following \kbd{stack\_init} (\kbd{s->n} and \kbd{s->alloc} are set to $0$). \fun{void *}{pari_stack_pushp}{pari_stack *s, void *u} This function assumes that \kbd{*data} is of pointer type. Pushes the element \kbd{u} on the stack \kbd{s}. \fun{void **}{pari_stack_base}{pari_stack *s} returns the address of \kbd{data}, typecast to a \kbd{void **}. \section{Vectors and Matrices} \subsec{Access and extract} See~\secref{se:clean} and~\secref{se:unclean} for various useful constructors. Coefficients are accessed and set using \tet{gel}, \tet{gcoeff}, see~\secref{se:accessors}. There are many internal functions to extract or manipulate subvectors or submatrices but, like the accessors above, none of them are suitable for \tet{gerepileupto}. Worse, there are no type verification, nor bound checking, so use at your own risk. \fun{GEN}{shallowcopy}{GEN x} returns a \kbd{GEN} whose components are the components of $x$ (no copy is made). The result may now be used to compute in place without destroying $x$. This is essentially equivalent to \bprog GEN y = cgetg(lg(x), typ(x)); for (i = 1; i < lg(x); i++) y[i] = x[i]; return y; @eprog\noindent except that \typ{MAT} is treated specially since shallow copies of all columns are made. The function also works for non-recursive types, but is useless in that case since it makes a deep copy. If $x$ is known to be a \typ{MAT}, you may call \tet{RgM_shallowcopy} directly; if $x$ is known not to be a \typ{MAT}, you may call \tet{leafcopy} directly. \fun{GEN}{RgM_shallowcopy}{GEN x} returns \kbd{shallowcopy(x)}, where $x$ is a \typ{MAT}. \fun{GEN}{shallowtrans}{GEN x} returns the transpose of $x$, \emph{without} copying its components, i.~e.,~it returns a \kbd{GEN} whose components are (physically) the components of $x$. This is the internal function underlying \tet{gtrans}. \fun{GEN}{shallowconcat}{GEN x, GEN y} concatenate $x$ and $y$, \emph{without} copying components, i.~e.,~it returns a \kbd{GEN} whose components are (physically) the components of $x$ and $y$. \fun{GEN}{shallowconcat1}{GEN x} $x$ must be \typ{VEC} or \typ{LIST}, concatenate its elements from left to right. Shallow version of \kbd{concat1}. \fun{GEN}{shallowmatconcat}{GEN v} shallow version of \kbd{matconcat}. \fun{GEN}{shallowextract}{GEN x, GEN y} extract components of the vector or matrix $x$ according to the selection parameter $y$. This is the shallow analog of \kbd{extract0(x, y, NULL)}, see \tet{vecextract}. \kbdsidx{extract0} \fun{GEN}{RgM_minor}{GEN A, long i, long j} given a square \typ{MAT} A, return the matrix with $i$-th row and $j$-th column removed. \fun{GEN}{vconcat}{GEN A, GEN B} concatenate vertically the two \typ{MAT} $A$ and $B$ of compatible dimensions. A \kbd{NULL} pointer is accepted for an empty matrix. See \tet{shallowconcat}. \fun{GEN}{row}{GEN A, long i} return $A[i,]$, the $i$-th row of the \typ{MAT} $A$. \fun{GEN}{row_i}{GEN A, long i, long j1, long j2} return part of the $i$-th row of \typ{MAT}~$A$: $A[i,j_1]$, $A[i,j_1+1]\dots,A[i,j_2]$. Assume $j_1 \leq j_2$. \fun{GEN}{rowcopy}{GEN A, long i} return the row $A[i,]$ of the~\typ{MAT}~$A$. This function is memory clean and suitable for \kbd{gerepileupto}. See \kbd{row} for the shallow equivalent. \fun{GEN}{rowslice}{GEN A, long i1, long i2} return the \typ{MAT} formed by the $i_1$-th through $i_2$-th rows of \typ{MAT} $A$. Assume $i_1 \leq i_2$. \fun{GEN}{rowpermute}{GEN A, GEN p}, $p$ being a \typ{VECSMALL} representing a list $[p_1,\dots,p_n]$ of rows of \typ{MAT} $A$, returns the matrix whose rows are $A[p_1,],\dots, A[p_n,]$. \fun{GEN}{rowslicepermute}{GEN A, GEN p, long x1, long x2}, short for \bprog rowslice(rowpermute(A,p), x1, x2) @eprog\noindent (more efficient). \fun{GEN}{vecslice}{GEN A, long j1, long j2}, return $A[j_1], \dots, A[j_2]$. If $A$ is a \typ{MAT}, these correspond to \emph{columns} of $A$. The object returned has the same type as $A$ (\typ{VEC}, \typ{COL} or \typ{MAT}). Assume $j_1 \leq j_2$. \fun{GEN}{vecsplice}{GEN A, long j} return $A$ with $j$-th entry removed (\typ{VEC}, \typ{COL}) or $j$-th column removed (\typ{MAT}). \fun{GEN}{vecreverse}{GEN A}. Returns a \kbd{GEN} which has the same 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{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}{vecslicepermute}{GEN A, GEN p, long y1, long y2} short for \bprog vecslice(vecpermute(A,p), y1, y2) @eprog\noindent (more efficient). \subsec{Componentwise operations} The following convenience routines automate trivial loops of the form \bprog for (i = 1; i < lg(a); i++) gel(v,i) = f(gel(a,i), gel(b,i)) @eprog\noindent for suitable $f$: \fun{GEN}{vecinv}{GEN a}. Given a vector $a$, returns the vector whose $i$-th component is \kbd{ginv}$(a[i])$. \fun{GEN}{vecmul}{GEN a, GEN b}. Given $a$ and $b$ two vectors of the same length, returns the vector whose $i$-th component is \kbd{gmul}$(a[i], b[i])$. \fun{GEN}{vecdiv}{GEN a, GEN b}. Given $a$ and $b$ two vectors of the same length, returns the vector whose $i$-th component is \kbd{gdiv}$(a[i], b[i])$. \fun{GEN}{vecpow}{GEN a, GEN n}. Given $n$ a \typ{INT}, returns the vector whose $i$-th component is $a[i]^n$. \fun{GEN}{vecmodii}{GEN a, GEN b}. Assuming $a$ and $b$ are two \kbd{ZV} of the same length, returns the vector whose $i$-th component is \kbd{modii}$(a[i], b[i])$. Note that \kbd{vecadd} or \kbd{vecsub} do not exist since \kbd{gadd} and \kbd{gsub} have the expected behavior. On the other hand, \kbd{ginv} does not accept vector types, hence \kbd{vecinv}. \subsec{Low-level vectors and columns functions} These functions handle \typ{VEC} as an abstract container type of \kbd{GEN}s. No specific meaning is attached to the content. They accept both \typ{VEC} and \typ{COL} as input, but \kbd{col} functions always return \typ{COL} and \kbd{vec} functions always return \typ{VEC}. \misctitle{Note} All the functions below are shallow. \fun{GEN}{const_col}{long n, GEN x} returns a \typ{COL} of \kbd{n} components equal to \kbd{x}. \fun{GEN}{const_vec}{long n, GEN x} returns a \typ{VEC} of \kbd{n} components equal to \kbd{x}. \fun{int}{vec_isconst}{GEN v} Returns 1 if all the components of \kbd{v} are equal, else returns 0. \fun{void}{vec_setconst}{GEN v, GEN x} $v$ a pre-existing vector. Set all its components to $x$. \fun{int}{vec_is1to1}{GEN v} Returns 1 if the components of \kbd{v} are pair-wise distinct, i.e. if $i\mapsto v[i]$ is a 1-to-1 mapping, else returns 0. \fun{GEN}{vec_shorten}{GEN v, long n} shortens the vector \kbd{v} to \kbd{n} components. \fun{GEN}{vec_lengthen}{GEN v, long n} lengthens the vector \kbd{v} to \kbd{n} components. The extra components are not initialized. \fun{GEN}{vec_insert}{GEN v, long n, GEN x} inserts $x$ at position $n$ in the vector $v$. \section{Vectors of small integers} \subsec{\typ{VECSMALL}} These functions handle \typ{VECSMALL} as an abstract container type of small signed integers. No specific meaning is attached to the content. \fun{GEN}{const_vecsmall}{long n, long c} returns a \typ{VECSMALL} of \kbd{n} components equal to \kbd{c}. \fun{GEN}{vec_to_vecsmall}{GEN z} identical to \kbd{ZV\_to\_zv(z)}. \fun{GEN}{vecsmall_to_vec}{GEN z} identical to \kbd{zv\_to\_ZV(z)}. \fun{GEN}{vecsmall_to_col}{GEN z} identical to \kbd{zv\_to\_ZC(z)}. \fun{GEN}{vecsmall_copy}{GEN x} makes a copy of \kbd{x} on the stack. \fun{GEN}{vecsmall_shorten}{GEN v, long n} shortens the \typ{VECSMALL} \kbd{v} to \kbd{n} components. \fun{GEN}{vecsmall_lengthen}{GEN v, long n} lengthens the \typ{VECSMALL} \kbd{v} to \kbd{n} components. The extra components are not initialized. \fun{GEN}{vecsmall_indexsort}{GEN x} performs an indirect sort of the components of the \typ{VECSMALL} \kbd{x} and return a permutation stored in a \typ{VECSMALL}. \fun{void}{vecsmall_sort}{GEN v} sorts the \typ{VECSMALL} \kbd{v} in place. \fun{long}{vecsmall_max}{GEN v} returns the maximum of the elements of \typ{VECSMALL} \kbd{v}, assumed non-empty. \fun{long}{vecsmall_indexmax}{GEN v} returns the index of the largest element of \typ{VECSMALL} \kbd{v}, assumed non-empty. \fun{long}{vecsmall_min}{GEN v} returns the minimum of the elements of \typ{VECSMALL} \kbd{v}, assumed non-empty. \fun{long}{vecsmall_indexmin}{GEN v} returns the index of the smallest element of \typ{VECSMALL} \kbd{v}, assumed non-empty. \fun{long}{vecsmall_isin}{GEN v, long x} returns the first index $i$ such that \kbd{v[$i$]} is equal to \kbd{x}. Naive search in linear time, does not assume that \kbd{v} is sorted. \fun{GEN}{vecsmall_uniq}{GEN v} given a \typ{VECSMALL} \kbd{v}, return the vector of unique occurrences. \fun{GEN}{vecsmall_uniq_sorted}{GEN v} same as \kbd{vecsmall\_uniq}, but assumes \kbd{v} sorted. \fun{long}{vecsmall_duplicate}{GEN v} given a \typ{VECSMALL} \kbd{v}, return $0$ if there is no duplicates, or the index of the first duplicate (\kbd{vecsmall\_duplicate([1,1])} returns $2$). \fun{long}{vecsmall_duplicate_sorted}{GEN v} same as \kbd{vecsmall\_duplicate}, but assume \kbd{v} sorted. \fun{int}{vecsmall_lexcmp}{GEN x, GEN y} compares two \typ{VECSMALL} lexically. \fun{int}{vecsmall_prefixcmp}{GEN x, GEN y} truncate the longest \typ{VECSMALL} to the length of the shortest and compares them lexicographically. \fun{GEN}{vecsmall_prepend}{GEN V, long s} prepend \kbd{s} to the \typ{VECSMALL} \kbd{V}. \fun{GEN}{vecsmall_append}{GEN V, long s} append \kbd{s} to the \typ{VECSMALL} \kbd{V}. \fun{GEN}{vecsmall_concat}{GEN u, GEN v} concat the \typ{VECSMALL} \kbd{u} and \kbd{v}. \fun{long}{vecsmall_coincidence}{GEN u, GEN v} returns the numbers of indices where \kbd{u} and \kbd{v} agree. \fun{long}{vecsmall_pack}{GEN v, long base, long mod} handles the \typ{VECSMALL} \kbd{v} as the digit of a number in base \kbd{base} and return this number modulo \kbd{mod}. This can be used as an hash function. \subsec{Vectors of \typ{VECSMALL}} These functions manipulate vectors of \typ{VECSMALL} (vecvecsmall). \fun{GEN}{vecvecsmall_sort}{GEN x} sorts lexicographically the components of the vector \kbd{x}. \fun{GEN}{vecvecsmall_sort_uniq}{GEN x} sorts lexicographically the components of the vector \kbd{x}, removing duplicates entries. \fun{GEN}{vecvecsmall_indexsort}{GEN x} performs an indirect lexicographic sorting of the components of the vector \kbd{x} and return a permutation stored in a \typ{VECSMALL}. \fun{long}{vecvecsmall_search}{GEN x, GEN y, long flag} \kbd{x} being a sorted vecvecsmall and \kbd{y} a \typ{VECSMALL}, search \kbd{y} inside \kbd{x}. \kbd{flag} has the same meaning as for \kbd{setsearch}. \newpage \chapter{Functions related to the GP interpreter} \section{Handling closures}\label{se:closure} \subsec{Functions to evaluate \typ{CLOSURE}} \fun{void}{closure_disassemble}{GEN C} print the \typ{CLOSURE} \kbd{C} in GP assembly format. \fun{GEN}{closure_callgenall}{GEN C, long n, ...} evaluate the \typ{CLOSURE} \kbd{C} with the \kbd{n} arguments (of type \kbd{GEN}) following \kbd{n} in the function call. Assumes \kbd{C} has arity $\geq \kbd{n}$. \fun{GEN}{closure_callgenvec}{GEN C, GEN args} evaluate the \typ{CLOSURE} \kbd{C} with the arguments supplied in the vector \kbd{args}. Assumes \kbd{C} has arity $\geq \kbd{lg(args)-1}$. \fun{GEN}{closure_callgen1}{GEN C, GEN x} evaluate the \typ{CLOSURE} \kbd{C} with argument \kbd{x}. Assumes \kbd{C} has arity $\geq 1$. \fun{GEN}{closure_callgen2}{GEN C, GEN x, GEN y} evaluate the \typ{CLOSURE} \kbd{C} with argument \kbd{x}, \kbd{y}. Assumes \kbd{C} has arity $\geq 2$. \fun{void}{closure_callvoid1}{GEN C, GEN x} evaluate the \typ{CLOSURE} \kbd{C} with argument \kbd{x} and discard the result. Assumes \kbd{C} has arity $\geq 1$. The following technical functions are used to evaluate \emph{inline} closures and closures of arity 0. The control flow statements (break, next and return) will cause the evaluation of the closure to be interrupted; this is called below a \emph{flow change}. When that occurs, the functions below generally return \kbd{NULL}. The caller can then adopt three positions: \item raises an exception (\kbd{closure\_evalnobrk}). \item passes through (by returning NULL itself). \item handles the flow change. \fun{GEN}{closure_evalgen}{GEN code} evaluates a closure and returns the result, or \kbd{NULL} if a flow change occurred. \fun{GEN}{closure_evalnobrk}{GEN code} as \kbd{closure\_evalgen} but raise an exception if a flow change occurs. Meant for iterators where interrupting the closure is meaningless, e.g.~\kbd{intnum} or \kbd{sumnum}. \fun{void}{closure_evalvoid}{GEN code} evaluates a closure whose return value is ignored. The caller has to deal with eventual flow changes by calling \kbd{loop\_break}. The remaining functions below are for exceptional situations: \fun{GEN}{closure_evalres}{GEN code} evaluates a closure and returns the result. The difference with \kbd{closure\_evalgen} being that, if the flow end by a \kbd{return} statement, the result will be the returned value instead of \kbd{NULL}. Used by the main GP loop. \fun{GEN}{closure_evalbrk}{GEN code, long *status} as \kbd{closure\_evalres} but set \kbd{status} to a non-zero value if a flow change occurred. This variant is not stack clean. Used by the break loop. \fun{GEN}{closure_trapgen}{long numerr, GEN code} evaluates closure, while trapping error \kbd{numerr}. Return \kbd{(GEN)1L} if error trapped, and the result otherwise, or \kbd{NULL} if a flow change occurred. Used by trap. \subsec{Functions to handle control flow changes} \fun{long}{loop_break}{void} processes an eventual flow changes inside an iterator. If this function return $1$, the iterator should stop. \subsec{Functions to deal with lexical local variables}\label{se:pushlex} Function using the prototype code \kbd{`V'} need to manually create and delete a lexical variable for each code \kbd{`V'}, which will be given a number $-1, -2, \ldots$. \fun{void}{push_lex}{GEN a, GEN code} creates a new lexical variable whose initial value is $a$ on the top of the stack. This variable get the number $-1$, and the number of the other variables is decreased by one unit. When the first variable of a closure is created, the argument \kbd{code} must be the closure that references this lexical variable. The argument \kbd{code} must be \kbd{NULL} for all subsequent variables (if any). (The closure contains the debugging data for the variable). \fun{void}{pop_lex}{long n} deletes the $n$ topmost lexical variables, increasing the number of other variables by $n$. The argument $n$ must match the number of variables allocated through \kbd{push\_lex}. \fun{GEN}{get_lex}{long vn} get the value of the variable with number \kbd{vn}. \fun{void}{set_lex}{long vn, GEN x} set the value of the variable with number \kbd{vn}. \subsec{Functions returning new closures} \fun{GEN}{compile_str}{const char *s} returns the closure corresponding to the GP expression $s$. \fun{GEN}{closure_deriv}{GEN code} returns a closure corresponding to the numerical derivative of the closure \kbd{code}. \fun{GEN}{snm_closure}{entree *ep, GEN data} Let \kbd{data} be a vector of length $m$, \kbd{ep} be an \kbd{entree} pointing to a C function $f$ of arity $n+m$, returns a \typ{CLOSURE} object $g$ of arity $n$ such that $g(x_1,\ldots,x_n)=f(x_1,\ldots,x_n,gel(data,1),...,gel(data,m))$. If \kbd{data} is \kbd{NULL}, then $m=0$ is assumed. This function has a low overhead since it does not copy \kbd{data}. \fun{GEN}{strtofunction}{char *str} returns a closure corresponding to the built-in or install'ed function named \kbd{str}. \fun{GEN}{strtoclosure}{char *str, long n, ...} returns a closure corresponding to the built-in or install'ed function named \kbd{str} with the $n$ last parameters set to the $n$ \kbd{GEN}s following $n$, see \tet{snm_closure}. This function has an higher overhead since it copies the parameters and does more input validation. In the example code below, \kbd{agm1} is set to the function \kbd{x->agm(x,1)} and \kbd{res} is set to \kbd{agm(2,1)}. \bprog GEN agm1 = strtoclosure("agm",1, gen_1); GEN res = closure_callgen1(agm1, gen_2); @eprog \subsec{Functions used by the gp debugger (break loop)} \fun{long}{closure_context}{long s} restores the compilation context starting at frame \kbd{s+1}, and returns the index of the topmost frame. This allow to compile expressions in the topmost lexical scope. \fun{void}{closure_err}{void} prints a backtrace of the last $20$ stack frames. \subsec{Standard wrappers for iterators} Two families of standard wrappers are provided to interface iterators like \kbd{intnum} or \kbd{sumnum} with GP. \subsubsec{Standard wrappers for inline closures} Theses wrappers are used to implement GP functions taking inline closures as input. The object \kbd{(GEN)E} must be an inline closure which is evaluated with the lexical variable number $-1$ set to $x$. \fun{GEN}{gp_eval}{void *E, GEN x} is used for the prototype code \kbd{`E'}. \fun{long}{gp_evalvoid}{void *E, GEN x} is used for the prototype code \kbd{`I'}. The resulting value is discarded. Return a non-zero value if a control-flow instruction request the iterator to terminate immediately. \fun{long}{gp_evalbool}{void *E, GEN x} returns the boolean \kbd{gp\_eval(E, x)} evaluates to (i.e. true iff the value is non-zero). \fun{GEN}{gp_evalupto}{void *E, GEN x} memory-safe version of \kbd{gp\_eval}, \kbd{gcopy}-ing the result, when the evaluator returns components of previously allocated objects (e.g. member functions). \subsubsec{Standard wrappers for true closures} These wrappers are used to implement GP functions taking true closures as input. \fun{GEN}{gp_call}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on $x$. \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. \fun{long}{gp_callvoid}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on $x$, discarding the result. Return a non-zero value if a control-flow 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{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 default setting functions with string argument \kbd{NULL} and flag \tet{d_ACKNOWLEDGE}. Otherwise, check whether $s$ corresponds to a default and call the corresponding default setting function with arguments $v$ and \fl. We shall describe these functions below: if $v$ is \kbd{NULL}, we only look at the default value (and possibly print or return it, depending on \kbd{flag}); otherwise the value of the default to $v$, possibly after some translation work. The flag is one of \item \tet{d_INITRC} called while reading the \kbd{gprc}: print and return \kbd{gnil}, possibly defer until \kbd{gp} actually starts. \item \tet{d_RETURN} return the current value, as a \typ{INT} if possible, as a \typ{STR} otherwise. \item \tet{d_ACKNOWLEDGE} print the current value, return \kbd{gnil}. \item \tet{d_SILENT} print nothing, return \kbd{gnil}. \noindent Low-level functions called by \kbd{setdefault}: \fun{GEN}{sd_TeXstyle}{const char *v, long flag} \fun{GEN}{sd_colors}{const char *v, long flag} \fun{GEN}{sd_compatible}{const char *v, long flag} \fun{GEN}{sd_datadir}{const char *v, long flag} \fun{GEN}{sd_debug}{const char *v, long flag} \fun{GEN}{sd_debugfiles}{const char *v, long flag} \fun{GEN}{sd_debugmem}{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_histsize}{const char *v, long flag} \fun{GEN}{sd_log}{const char *v, long flag} \fun{GEN}{sd_logfile}{const char *v, long flag} \fun{GEN}{sd_nbthreads}{const char *v, long flag} \fun{GEN}{sd_new_galois_format}{const char *v, long flag} \fun{GEN}{sd_output}{const char *v, long flag} \fun{GEN}{sd_parisize}{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_realprecision}{const char *v, long flag} \fun{GEN}{sd_recover}{const char *v, long flag} \fun{GEN}{sd_secure}{const char *v, long flag} \fun{GEN}{sd_seriesprecision}{const char *v, long flag} \fun{GEN}{sd_simplify}{const char *v, long flag} \fun{GEN}{sd_sopath}{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_threadsize}{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 \item \kbd{v} and \kbd{flag} are the arguments passed to \kbd{default}: \kbd{v} is a new value (or the empty string: no change), and \kbd{flag} is one of \tet{d_INITRC}, \tet{d_RETURN}, etc. \item \kbd{s} is the name of the default being changed, used to display error messages or acknowledgements. \fun{GEN}{sd_toggle}{const char *v, long flag, const char *s, int *ptn} \item if \kbd{v} is neither \kbd{"0"} nor \kbd{"1"}, an error is raised using \tet{pari_err}. \item \kbd{ptn} points to the current numerical value of the toggle (1 or 0), and is set to the new value (when \kbd{v} is non-empty). For instance, here is how the timer default is implemented internally: \bprog GEN sd_timer(const char *v, long flag) { return sd_toggle(v,flag,"timer", &(GP_DATA->chrono)); } @eprog The exact behavior and return value depends on \kbd{flag}: \item \tet{d_RETURN}: returns the new toggle value, as a \kbd{GEN}. \item \tet{d_ACKNOWLEDGE}: prints a message indicating the new toggle value and return \kbd{gnil}. \item other cases: print nothing and return \kbd{gnil}. \fun{GEN}{sd_ulong}{const char *v, long flag, const char *s, ulong *ptn, ulong Min, ulong Max, const char **msg}\hbadness 10000 \item \kbd{ptn} points to the current numerical value of the toggle, and is set to the new value (when \kbd{v} is non-empty). \item \kbd{Min} and \kbd{Max} point to the minimum and maximum values allowed for the default. \item \kbd{v} must translate to an integer in the allowed ranger, a suffix among \kbd{k}/\kbd{K} ($\times 10^3$), \kbd{m}/\kbd{M} ($\times 10^6$), or \kbd{g}/\kbd{G} ($\times 10^9$) is allowed, but no arithmetic expression. \item \kbd{msg} is a \kbd[NULL]-terminated array of messages or \kbd{NULL} (ignored). If \kbd{msg} is not \kbd{NULL}, \kbd{msg}$[i]$ contains a message associated to the value $i$ of the default. The last entry in the \kbd{msg} array is used as a message associated to all subsequent ones. The exact behavior and return value depends on \kbd{flag}: \item \tet{d_RETURN}: returns the new toggle value, as a \kbd{GEN}. \item \tet{d_ACKNOWLEDGE}: prints a message indicating the new value, possibly a message associated to it via the \kbd{msg} argument, and return \kbd{gnil}. \item other cases: print nothing and return \kbd{gnil}. \fun{GEN}{sd_string}{const char *v, long flag, const char *s, char **pstr} \item \kbd{v} is subjet to environment expansion, then time expansion. \item \kbd{pstr} points to the current string value, and is set to the new value (when \kbd{v} is non-empty). \section{Records and Lazy vectors} The functions in this section are used to implement \kbd{ell} structures and analogous objects, which are vectors some of whose components are initialized to dummy values, later computed on demand. We start by initializing the structure: \fun{GEN}{obj_init}{long d, long n} returns an \tev{obj} $S$, a \typ{VEC} with $d$ regular components, accessed as \kbd{gel(S,1)}, \dots, \kbd{gel(S,d)}; together with a record of $n$ members, all initialized to $0$. The arguments $d$ and $n$ must be non-negative. After \kbd{S = obj\_init(d, n)}, the prototype of our other functions are of the form \bprog GEN obj_do(GEN S, long tag, ...) @eprog\noindent The first argument $S$ holds the structure to be managed. The second argument \var{tag} is the index of the struct member (from $1$ to $n$) we operate on. We recommend to define an \kbd{enum} and use descriptive names instead of hardcoded numbers. For instance, if $n = 3$, after defining \bprog enum { TAG_p = 1, TAG_list, TAG_data }; @eprog\noindent one may use \kbd{TAG\_list} or $2$ indifferently as a tag. The former being preferred, of course. \misctitle{Technical note} In the current implementation, $S$ is a \typ{VEC} with $d+1$ entries. The first $d$ components are ordinary \typ{GEN} entries, which you can read or assign to in the customary way. But the last component $\kbd{gel(S, d+1)}$, a \typ{VEC} of length $n$ initialized to \kbd{zerovec}$(n)$, must be handled in a special way: you should never access or modify its components directly, only through the API we are about to describe. Indeed, its entries are meant to contain dynamic data, which will be stored, retrieved and replaced (for instance by a value computed to a higher accuracy), while interacting safely with intermediate \kbd{gerepile} calls. This mechanism allows to simulate C \kbd{struct}s, in a simpler way than with general hashtables, while remaining compatible with the GP language, which knows neither structs nor hashtables. It also serialize the structure in an ordinary \kbd{GEN}, which facilitates copies and garbage collection (use \kbd{gcopy} or \kbd{gerepile}), rather than having to deal with individual components of actual C \kbd{struct}s. \fun{GEN}{obj_check}{GEN S, long tag} if the \emph{tag}-component in $S$ is non empty, return it. Otherwise return \kbd{NULL}. The \typ{INT} $0$ (initial value) is used as a sentinel to indicated an empty component. \fun{GEN}{obj_insert}{GEN S, long tag, GEN O} insert (a clone of) $O$ as \emph{tag}-component of $S$. Any previous value is deleted, and data pointing to it become invalid. \fun{GEN}{obj_insert_shallow}{GEN S, long K, GEN O} as \tet{obj_insert}, inserting $O$ as-is, not via a clone. \fun{GEN}{obj_checkbuild}{GEN S, long tag, GEN (*build)(GEN)} if the \emph{tag}-component of $S$ is non empty, return it. Otherwise insert (a clone of) \kbd{build(S)} as \emph{tag}-component in $S$, and return it. \fun{GEN}{obj_checkbuild_padicprec}{GEN S, long tag, GEN (*build)(GEN,long), long prec} 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 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{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 avoid memory leaks. pari-2.7.5/doc/translations0000644000175000017500000001164612413013142014316 0ustar billbillreadline @se:readline@2 edit @se:readline@2 ? @?@2 ?? @?@2 \\ @\bs\bs@2 \a @\b{a}@2 \b @\b{b}@2 \c @\b{c}@2 \d @\b{d}@2 \e @\b{e}@2 \g @\b{g}@2 \gf @\b{gf}@2 \gm @\b{gm}@2 \h @\b{h}@2 \k @\b{k}@2 \l @\b{l}@2 \m @\b{m}@2 \p @\b{p}@2 \o @\b{o}@2 \ps @\b{ps}@2 \q @\b{q}@2 \r @\b{r}@2 \s @\b{s}@2 \t @\b{t}@2 \u @\b{u}@2 \um @\b{um}@2 \v @\b{v}@2 \w @\b{w}@2 \x @\b{x}@2 \y @\b{y}@2 # @\#@2 ## @\#\#@2 operator @GP operators@2 and @&&@3 or @&&@3 not @&&@3 INT @Integers@2 integer @Integers@2 REAL @Real numbers@2 real number @Real numbers@2 INTMOD @Integermods@2 intmod @Integermods@2 FRAC @Rational numbers@2 fraction @Rational numbers@2 rational @Rational numbers@2 FRACN @Rational numbers@2 COMPLEX @Complex numbers@2 complex @Complex numbers@2 PADIC @$p$-adic numbers@2 padic @$p$-adic numbers@2 QUAD @Quadratic numbers@2 quadratic @Quadratic numbers@2 POLMOD @Polmods@2 polmod @Polmods@2 POL @Polynomials@2 polynomial @Polynomials@2 SER @Power series@2 RFRAC @Rational functions@2 RFRACN @Rational functions@2 RFRACN @Rational functions@2 QFR @Binary quadratic forms of positive or negative discriminant@2 QFI @Binary quadratic forms of positive or negative discriminant@2 VEC @Row and column vectors@2 COL @Row and column vectors@2 MAT @Matrices@2 LIST @Lists@2 STR @Strings@2 VECSMALL @Small vectors@2 ERROR @Error contexts@2 e_SYNTAX @iferr@ e_BUG @iferr@ e_ALARM @iferr@ e_FILE @iferr@ e_MISC @iferr@ e_FLAG @iferr@ e_IMPL @iferr@ e_ARCH @iferr@ e_PACKAGE @iferr@ e_NOTFUNC @iferr@ e_PREC @iferr@ e_TYPE @iferr@ e_DIM @iferr@ e_VAR @iferr@ e_PRIORITY @iferr@ e_USER @iferr@ e_STACK @iferr@ e_OVERFLOW @iferr@ e_DOMAIN @iferr@ e_COMPONENT @iferr@ e_MAXPRIME @iferr@ e_CONSTPOL @iferr@ e_IRREDPOL @iferr@ e_COPRIME @iferr@ e_PRIME @iferr@ e_MODULUS @iferr@ e_ROOTS0 @iferr@ e_OP @iferr@ e_TYPE2 @iferr@ e_INV @iferr@ e_MEM @iferr@ e_SQRTN @iferr@ local @Variables and Scope@2 my @Variables and Scope@2 user defined @User defined functions@2 user defined function @User defined functions@2 member function @Member functions@2 member @Member functions@2 ' @deriv \ @\bs \/ @\bs/ ^ @\pow ! @factorial ~ @mattranspose - @+ % @\% ++ @GP operators@2 -- @GP operators@2 -= @GP operators@2 += @GP operators@2 *= @GP operators@2 /= @GP operators@2 %= @GP operators@2 \/= @GP operators@2 >>= @GP operators@2 <<= @GP operators@2 << @shift >> @shift <> @Comparison and Boolean operators === @Comparison and Boolean operators +/- @+$/$- min @max emacs @Using GP under GNU Emacs@2 Emacs @Using GP under GNU Emacs@2 0 @Functions and Operations Available in PARI and GP 1 @Standard monadic or dyadic operators 2 @Conversions and similar elementary functions or commands 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@2 ell @Functions related to elliptic curves nf @Number field structures bnf @Number field structures bnr @Number field structures rnf @Relative extensions ideal @Algebraic numbers and ideals idele @Algebraic numbers and ideals modulus @Class field theory CFT @Class field theory bid @Class field theory prototype @GP prototypes, parser codes@5 pari-2.7.5/doc/usersch7.tex0000644000175000017500000006132412413013142014135 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Technical Reference Guide for Elliptic curves and arithmetic geometry} This chapter is quite short, but is added as a placeholder, since we expect the library to expand in that direction. \section{Elliptic curves} Elliptic curves are represented in the Weierstrass model $$ (E): y^2z + a_1xyz + a_3 yz = x^3 + a_2 x^2z + a_4 xz^2 + a_6z^3, $$ by the $5$-tuple $[a_1,a_2,a_3,a_4,a_6]$. Points in the projective plane are represented as follows: the point at infinity $(0:1:0)$ is coded as \kbd{[0]}, a finite point $(x:y:1)$ outside the projective line at infinity $z = 0$ is coded as $[x,y]$. Note that other points at infinity than $(0:1:0)$ cannot be represented; this is harmless, since they do not belong to any of the elliptic curves $E$ above. \emph{Points on the curve} are just projective points as described above, they are not tied to a curve in any way: the same point may be used in conjunction with different curves, provided it satisfies their equations (if it does not, the result is usually undefined). In particular, the point at infinity belongs to all elliptic curves. As with \tet{factor} for polynomial factorization, the $5$-tuple $[a_1,a_2,a_3,a_4,a_6]$ implicitly defines a base ring over which the curve is defined. Point coordinates must be operation-compatible with this base ring (\kbd{gadd}, \kbd{gmul}, \kbd{gdiv} involving them should not give errors). \subsec{Types of elliptic curves} We call a $5$-tuble as above an \kbd{ell5}; most functions require an \kbd{ell} structure, as returned by \tet{ellinit}, which contains additional data (usually dynamically computed as needed), depending on the base field. \fun{GEN}{ellinit}{GEN E, GEN D, long prec}, returns an \tet{ell} structure, associated to the elliptic curve $E$ : either an \kbd{ell5}, a pair $[a_4,a_6]$ or a \typ{STR} in Cremona's notation, e.g. \kbd{"11a1"}. The optional $D$ (\kbd{NULL} to omit) describes the domain over which the curve is defined. \subsec{Type checking} \fun{void}{checkell}{GEN e} raise an error unless $e$ is a \var{ell}. \fun{void}{checkell5}{GEN e} raise an error unless $e$ is an \var{ell} or an \var{ell5}. \fun{void}{checkellpt}{GEN z} raise an error unless $z$ is a point (either finite or at infinity). \fun{long}{ell_get_type}{GEN e} returns the domain type over which the curve is defined, one of \tet{t_ELL_Q} the field of rational numbers; \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 \kbd{Fp} (\typ{INT} reduced modulo $p$); \tet{t_ELL_Fq} a non-prime finite field (a prime finite field can also be represented by this subtype, but this is inefficient), base field elements are represented as \typ{FFELT}; \tet{t_ELL_Rg} none of the above. \fun{void}{checkell_Fq}{GEN e} checks whether $e$ is an \kbd{ell}, defined over a finite field (either prime or non-prime), raises \tet{pari_err_TYPE} otherwise. \fun{void}{checkell_Q}{GEN e} checks whether $e$ is an \kbd{ell}, defined 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. \subsec{Extracting info from an \kbd{ell} structure} These functions expect an \kbd{ell} argument. If the required data is not part of the structure, it is computed then inserted, and the new value is returned. \subsubsec{All domains} \fun{GEN}{ell_get_a1}{GEN e} \fun{GEN}{ell_get_a2}{GEN e} \fun{GEN}{ell_get_a3}{GEN e} \fun{GEN}{ell_get_a4}{GEN e} \fun{GEN}{ell_get_a6}{GEN e} \fun{GEN}{ell_get_b2}{GEN e} \fun{GEN}{ell_get_b4}{GEN e} \fun{GEN}{ell_get_b6}{GEN e} \fun{GEN}{ell_get_b8}{GEN e} \fun{GEN}{ell_get_c4}{GEN e} \fun{GEN}{ell_get_c6}{GEN e} \fun{GEN}{ell_get_disc}{GEN e} \fun{GEN}{ell_get_j}{GEN e} \subsubsec{Curves over $\Q$} \fun{GEN}{ellQ_get_N}{GEN e} returns the curve conductor \fun{void}{ellQ_get_Nfa}{GEN e, GEN *N, GEN *faN} sets $N$ to the conductor and \kbd{faN} to its factorization \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}{elldatagenerators}{GEN E} returns generators for $E(\Q)$ extracted from Cremona's table. \fun{GEN}{ellanal_globalred}{GEN e, GEN *v} takes an \var{ell} over $\Q$ and returns a global minimal model $E$ (in \kbd{ellinit} form, over $\Q$) for $e$ suitable for analytic computations related to the curve $L$ series: it contains \kbd{ellglobalred} data, as well as global and local root numbers. If \kbd{v} is not \kbd{NULL}, set \kbd{*v} to the needed change of variable: \kbd{NULL} if $e$ was already the standard minimal model, such that $E = \kbd{ellchangecurve(e,v)}$ otherwise. Compared to the direct use of \kbd{ellchangecurve} followed by \kbd{ellrootno}, this function avoids 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. \subsubsec{Curves over $\Q_p$} \fun{GEN}{ellQp_get_p}{GEN E} returns $p$ \fun{long}{ellQp_get_prec}{GEN E} returns the default $p$-adic accuracy to which we must compute approximate results associated to $E$. \fun{GEN}{ellQp_get_zero}{GEN x} returns $O(p^n)$, where $n$ is the default $p$-adic accuracy as above. The following functions are only defined when $E$ has multiplicative reduction (Tate curves): \fun{GEN}{ellQp_Tate_uniformization}{GEN E, long prec} returns a \typ{VEC} containing $u^2, u, q, [a,b]$, at $p$-adic precision \kbd{prec}. \fun{GEN}{ellQp_u}{GEN E, long prec} returns $u$. \fun{GEN}{ellQp_u2}{GEN E, long prec} returns $u^2$. \fun{GEN}{ellQp_q}{GEN E, long prec} returns the Tate period $q$. \fun{GEN}{ellQp_ab}{GEN E, long prec} returns $[a,b]$. \fun{GEN}{ellQp_root}{GEN E, long prec} returns $e_1$. \subsubsec{Curves over a finite field $\F_q$} \fun{GEN}{ellff_get_p}{GEN E} returns the characteristic \fun{GEN}{ellff_get_field}{GEN E} returns $p$ if $\F_q$ is a prime field, and a \typ{FFELT} belonging to $\F_q$ otherwise. \fun{GEN}{ellff_get_card}{GEN E} returns $\#E(\F_q)$ \fun{GEN}{ellff_get_gens}{GEN E} returns a minimal set of generators for $E(\F_q)$. \fun{GEN}{ellff_get_group}{GEN E} returns \kbd{ellgroup}$(E)$. \fun{GEN}{ellff_get_o}{GEN E} returns $[d, \kbd{factor{d}}]$, where $d$ is the exponent of $E(\F_q)$. \fun{GEN}{ellff_get_a4a6}{GEN E} returns a canonical ``short model'' for $E$, and the corresponding change of variable $[u,r,s,t]$. For $p\neq 2,3$, this is $[A_4,A_6,[u,r,s,t]]$, corresponding to $y^2 = x^3 + A_4x + A_6$, where $A_4 = -27c_4$, $A_6 = -54c_6$, $[u,r,s,t] = [6, 3b_2,3a_1,108a_3]$. \item If $p = 3$ and the curve is ordinary ($b_2\neq 0$), this is $[[b_2], A_6, [1,v,-a_1,-a_3]]$, corresponding to $$y^2 = x^3 + b_2 x + A_6,$$ where $v = b_4/b_2$, $A_6 = b_6 - v(b_4+v^2)$. \item If $p = 3$ and the curve is supersingular ($b_2 = 0$), this is $[-b_4, b_6, [1,0,-a_1,-a_3]]$, corresponding to $$y^2 = x^3 + 2b_4 x + b_6.$$ \item If $p = 2$ and the curve is ordinary ($a_1 \neq 0$), return $[A_2,A_6,[a_1^{-1}, da_1^{-2}, 0, (a_4+d^2)a_1^{-1}]]$, corresponding to $$ y^2 + xy = x^3 + A_2 x^2 + A_6,$$ where $d = a_3/a_1$, $a_1^2 A_2 = (a_2 + d)$ and $$ a_1^6 A_6 = d^3 + a_2 d^2 + a_4 d + a_6 + (a_4^2 + d^4)a_1^{-2}.$$ \item If $p = 2$ and the curve is supersingular ($a_1 = 0$, $a_3\neq 0$), return $[[a_3, A_4, 1/a_3], A_6, [1,a_2,0,0]]$, corresponding to $$ y^2 + a_3 y = x^3 + A_4 x + A_6,$$ where $A_4 = a_2^2 + a_4$, $ A_6 = a_2a_4 + a_6$. The value $1/a_3$ is included in the vector since it is frequently needed in computations. \subsubsec{Curves over $\C$} (This includes curves over $\Q$!) \fun{long}{ellR_get_prec}{GEN E} returns the default accuracy to which we must compute approximate results associated to $E$. \fun{GEN}{ellR_ab}{GEN E, long prec} returns $[a,b]$ \fun{GEN}{ellR_omega}{GEN x, long prec} returns periods $[\omega_1,\omega_2]$. \fun{GEN}{ellR_eta}{GEN E, long prec} returns quasi-periods $[\eta_1,\eta_2]$. \fun{GEN}{ellR_roots}{GEN E, long prec} returns $[e_1,e_2,e_3]$. If $E$ is defined over $\R$, then $e_1$ is real. If furthermore $\disc E > 0$, then $e_1 > e_2 > e_3$. \fun{long}{ellR_get_sign}{GEN E} if $E$ is defined over $\R$ returns the signe of its discriminant, otherwise return $0$. \subsec{Points} \fun{int}{ell_is_inf}{GEN z} tests whether the point $z$ is the point at 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{Functions to handle elliptic curves over finite fields} \subsubsec{Tolerant routines} \fun{GEN}{ellap}{GEN E, GEN p} given a prime number $p$ and an elliptic curve defined over $\Q$ or $\Q_p$ (assumed integral and minimal at $p$), computes the trace of Frobenius $a_p = p+1 - \#E(\F_p)$. If $E$ is defined over 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$. \subsubsec{Curves defined a non-prime finite field} In this subsection, we assume that \tet{ell_get_type}$(E)$ is \tet{t_ELL_Fq}. (As noted above, a curve defined over $\Z/p\Z$ can be represented as a \tet{t_ELL_Fq}.) \fun{GEN}{FF_ellmul}{GEN E, GEN P, GEN n} returns $[n]P$ where $n$ is an integer and $P$ is a point on the curve $E$. \fun{GEN}{FF_ellrandom}{GEN E} returns a random point in $E(\F_q)$. This function never returns the point at infinity, unless this is the only point on the curve. \fun{GEN}{FF_ellorder}{GEN E, GEN P, GEN o} returns the order of the point $P$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FF_ellcard}{GEN E} returns $\#E(\F_q)$. \fun{GEN}{FF_ellgens}{GEN E} returns the generators of the group $E(\F_q)$. \fun{GEN}{FF_elllog}{GEN E, GEN P, GEN G, GEN o} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $[e]P=G$. If $e$ does not exists, the result is undefined. \fun{GEN}{FF_ellgroup}{GEN E} returns the Abelian group $E(\F_q)$ in the form $[h,\kbd{cyc},\kbd{gen}]$. \fun{GEN}{FF_ellweilpairing}{GEN E, GEN P, GEN Q, GEN m} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{FF_elltatepairing}{GEN E, GEN P, GEN Q, GEN m} returns the Tate pairing of $P$ and $Q$, where $[m]P = 0$. \section{Arithmetic on elliptic curve over a finite field in simple form} The functions in this section no longer operate on elliptic curve structures, as seen up to now. They are used to implement those higher-level functions without using cached information and thus require suitable explicitly enumerated data. \subsec{Helper functions} \fun{GEN}{elltrace_extension}{GEN t, long n, GEN q} Let $E$ some elliptic curve over $\F_q$ such that the trace of the Frobenius is $t$, returns the trace of the Frobenius over $\F_q^n$. \subsec{Elliptic curves over $\F_p$, $p>3$} Let $p$ a prime number and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p$. A \kbd{FpE} is a point of $E(\F_p)$. Since an affine point and $a_4$ determine an unique $a6$, most functions do not take $a_6$ as an argument. A \kbd{FpE} is either the point at infinity (\kbd{ellinf()}) or a $FpV$ whith two components. The 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{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}{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$. \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$. \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$ and set $*pt_m=m$. \fun{GEN}{Fp_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p} returns generators of the group $E(\F_p)$ with the base change \kbd{ch} (see \kbd{FpE\_changepoint}), where $D$ and $m$ are as returned by \kbd{Fp\_ellgroup}. \fun{GEN}{Fp_elldivpol}{GEN a4, GEN a6, long n, GEN p} returns the $n$-division polynomial of the elliptic curve $E$. \subsec{\kbd{FpE}} \fun{GEN}{FpE_add}{GEN P, GEN Q, GEN a4, GEN p} returns the sum $P+Q$ in the group $E(\F_p)$, where $E$ is defined by $E:y^2=x^3+a_4\*x+a_6$, for any value of $a_6$ compatible with the points given. \fun{GEN}{FpE_sub}{GEN P, GEN Q, GEN a4, GEN p} returns $P-Q$. \fun{GEN}{FpE_dbl}{GEN P, GEN a4, GEN p} returns $2.P$. \fun{GEN}{FpE_neg}{GEN P, GEN p} returns $-P$. \fun{GEN}{FpE_mul}{GEN P, GEN n, GEN a4, GEN p} return $n.P$. \fun{GEN}{FpE_changepoint}{GEN P, GEN m, GEN a4, GEN p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FpV}). \fun{GEN}{FpE_changepointinv}{GEN P, GEN m, GEN a4, GEN p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FpV}). \fun{GEN}{random_FpE}{GEN a4, GEN a6, GEN p} returns a random point on $E(\F_p)$, where $E$ is defined by $E:y^2=x^3+a_4\*x+a_6$. \fun{GEN}{FpE_order}{GEN P, GEN o, GEN a4, GEN p} returns the order of $P$ in the group $E(\F_p)$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FpE_log}{GEN P, GEN G, GEN o, GEN a4, GEN p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FpE_tatepairing}{GEN P, GEN Q, GEN m, GEN a4, GEN p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FpE_weilpairing}{GEN P, GEN Q, GEN m, GEN a4, GEN p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{FpE_to_mod}{GEN P, GEN p} returns $P$ as a vector of \typ{INTMOD}s. \fun{GEN}{RgE_to_FpE}{GEN P, GEN p} returns the \kbd{FpE} obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \subsec{\kbd{Fle}} 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. \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{GEN}{Fle_add}{GEN P, GEN Q, ulong a4, ulong p} \fun{GEN}{Fle_dbl}{GEN P, ulong a4, ulong p} \fun{GEN}{Fle_sub}{GEN P, GEN Q, ulong a4, ulong p} \fun{GEN}{Fle_mul}{GEN P, GEN n, ulong a4, ulong p} \fun{GEN}{Fle_mulu}{GEN P, ulong n, ulong a4, ulong p} \fun{GEN}{Fle_order}{GEN P, GEN o, ulong a4, ulong p} \fun{GEN}{random_Fle}{ulong a4, ulong a6, ulong p} \subsec{Elliptic curves over $\F_{2^n}$} Let $T$ be an irreducible \kbd{F2x} and $E$ the elliptic curve given by either the equation $E:y^2+x*y=x^3+a_2\*x^2+a_6$, where $a_2, a_6$ are \kbd{F2x} in $\F_2[X]/(T)$ (ordinary case) or $E:y^2+a_3*y=x^3+a_4\*x+a_6$, where $a_3, a_4, a_6$ are \kbd{F2x} in $\F_2[X]/(T)$ (supersingular case). A \kbd{F2xqE} is a point of $E(\F_2[X]/(T))$. In the supersingular case, the parameter \kbd{a2} is actually the \typ{VEC} $[a_3,a_4,a_3^{-1}]$. \fun{GEN}{F2xq_ellcard}{GEN a2, GEN a6, GEN T} Return the order of the group $E(\F_2[X]/(T))$. \fun{GEN}{F2xq_ellgroup}{GEN a2, GEN a6, GEN N, GEN T, GEN *pt_m} Return the group structure $D$ of the group $E(\F_2[X]/(T))$, which is assumed to be of order $N$ and set $*pt_m=m$. \fun{GEN}{F2xq_ellgens}{GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T} Returns generators of the group $E(\F_2[X]/(T))$ with the base change \kbd{ch} (see \kbd{F2xqE\_changepoint}), where $D$ and $m$ are as returned by \kbd{F2xq\_ellgroup}. \subsec{\kbd{F2xqE}} \fun{GEN}{F2xqE_changepoint}{GEN P, GEN m, GEN a2, GEN T} returns the image $Q$ of the point $P$ on the curve $E:y^2+x*y=x^3+a_2\*x^2+a_6$ by the coordinate change $m$ (which is a \kbd{F2xqV}). \fun{GEN}{F2xqE_changepointinv}{GEN P, GEN m, GEN a2, GEN T} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{F2xqV}). \fun{GEN}{F2xqE_add}{GEN P, GEN Q, GEN a2, GEN T} \fun{GEN}{F2xqE_sub}{GEN P, GEN Q, GEN a2, GEN T} \fun{GEN}{F2xqE_dbl}{GEN P, GEN a2, GEN T} \fun{GEN}{F2xqE_neg}{GEN P, GEN a2, GEN T} \fun{GEN}{F2xqE_mul}{GEN P, GEN n, GEN a2, GEN T} \fun{GEN}{random_F2xqE}{GEN a2, GEN a6, GEN T} \fun{GEN}{F2xqE_order}{GEN P, GEN o, GEN a2, GEN T} returns the order of $P$ in the group $E(\F_2[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{F2xqE_log}{GEN P, GEN G, GEN o, GEN a2, GEN T} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{F2xqE_tatepairing}{GEN P, GEN Q, GEN m, GEN a2, GEN T} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{F2xqE_weilpairing}{GEN Q, GEN Q, GEN m, GEN a2, GEN T} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{RgE_to_F2xqE}{GEN P, GEN T} returns the \kbd{F2xqE} obtained by applying \kbd{Rg\_to\_F2xq} coefficientwise. \subsec{Elliptic curves over $\F_q$, small characteristic $p>2$ } Let $p$ be a prime \kbd{ulong}, $T$ an irreducible \kbd{Flx} mod $p$, 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{Flx} in $\F_p[X]/(T)$. A \kbd{FlxqE} is a point of $E(\F_p[X]/(T))$. In the special case $p = 3$, ordinary elliptic curves ($j(E)\neq 0$) cannot be represented as above, but admit a model $E:y^2 = x^3+a_2\*x^2+a_6$ with $a_2$ and $a_6$ being \kbd{Flx} in $\F_3[X]/(T)$. In that case, the parameter \kbd{a2} is actually stored as a \typ{VEC}, $[a_2]$, to avoid ambiguities. \fun{GEN}{Flxq_ellj}{GEN a4, GEN a6, GEN T, ulong p} returns the $j$-invariant of the curve $E$. \fun{GEN}{Flxq_ellcard}{GEN a4, GEN a6, GEN T, ulong p} returns the order of $E(\F_p[X]/(T))$. \fun{GEN}{Flxq_ellgroup}{GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pt_m} returns 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$. \fun{GEN}{Flxq_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p} returns generators of the group $E(\F_p[X]/(T))$ with the base change \kbd{ch} (see \kbd{FlxqE\_changepoint}), where $D$ and $m$ are as returned by \kbd{Flxq\_ellgroup}. \subsec{\kbd{FlxqE}} \fun{GEN}{FlxqE_changepoint}{GEN P, GEN m, GEN a4, GEN T, ulong p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FlxqV}). \fun{GEN}{FlxqE_changepointinv}{GEN P, GEN m, GEN a4, GEN T, ulong p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FlxqV}). \fun{GEN}{FlxqE_add}{GEN P, GEN Q, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_sub}{GEN P, GEN Q, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_dbl}{GEN P, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_neg}{GEN P, GEN T, ulong p} \fun{GEN}{FlxqE_mul}{GEN P, GEN n, GEN a4, GEN T, ulong p} \fun{GEN}{random_FlxqE}{GEN a4, GEN a6, GEN T, ulong p} \fun{GEN}{FlxqE_order}{GEN P, GEN o, GEN a4, GEN T, ulong p} returns the order of $P$ in the group $E(\F_p[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FlxqE_log}{GEN P, GEN G, GEN o, GEN a4, GEN T, ulong p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FlxqE_tatepairing}{GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FlxqE_weilpairing}{GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{RgE_to_FlxqE}{GEN P, GEN T, ulong p} returns the \kbd{FlxqE} obtained by applying \kbd{Rg\_to\_Flxq} coefficientwise. \subsec{Elliptic curves over $\F_q$, large characteristic } Let $p$ be a prime number, $T$ an irreducible polynomial mod $p$, and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$ with $a_4$ and $a_6$ 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{GEN}{FpXQ_ellcard}{GEN a4, GEN a6, GEN T, GEN p} returns the order of $E(\F_p[X]/(T))$. \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$. \fun{GEN}{FpXQ_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p} Returns generators of the group $E(\F_p[X]/(T))$ with the base change \kbd{ch} (see \kbd{FpXQE\_changepoint}), where $D$ and $m$ are as returned by \kbd{FpXQ\_ellgroup}. \fun{GEN}{FpXQ_elldivpol}{GEN a4, GEN a6, long n, GEN T, GEN p} returns the $n$-division polynomial of the elliptic curve $E$. \fun{GEN}{Fq_elldivpolmod}{GEN a4,GEN a6, long n, GEN h, GEN T, GEN p} returns the $n$-division polynomial of the elliptic curve $E$ modulo the polynomial $h$. \subsec{\kbd{FpXQE}} \fun{GEN}{FpXQE_changepoint}{GEN P, GEN m, GEN a4, GEN T, GEN p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FpXQV}). \fun{GEN}{FpXQE_changepointinv}{GEN P, GEN m, GEN a4, GEN T, GEN p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FpXQV}). \fun{GEN}{FpXQE_add}{GEN P, GEN Q, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_sub}{GEN P, GEN Q, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_dbl}{GEN P, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_neg}{GEN P, GEN T, GEN p} \fun{GEN}{FpXQE_mul}{GEN P, GEN n, GEN a4, GEN T, GEN p} \fun{GEN}{random_FpXQE}{GEN a4, GEN a6, GEN T, GEN p} \fun{GEN}{FpXQE_log}{GEN P, GEN G, GEN o, GEN a4, GEN T, GEN p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FpXQE_order}{GEN P, GEN o, GEN a4, GEN T, GEN p} returns the order of $P$ in the group $E(\F_p[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FpXQE_tatepairing}{GEN P,GEN Q, GEN m, GEN a4, GEN T, GEN p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FpXQE_weilpairing}{GEN P,GEN Q, GEN m, GEN a4, GEN T, GEN p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{RgE_to_FpXQE}{GEN P, GEN T, GEN p} returns the \kbd{FpXQE} obtained by applying \kbd{Rg\_to\_FpXQ} coefficientwise. \section{Other curves} The following functions deal with hyperelliptic curves in weighted projective space $\P_{(1,d,1)}$, with coordinates $(x,y,z)$ and a model of the form $ y^2 = T(x,z)$, where $T$ is homogeneous of degree $2d$, and squarefree. Thus the curve is nonsingular of genus $d-1$. \fun{long}{hyperell_locally_soluble}{GEN T, GEN p} assumes that $T\in\Z[X]$ is integral. Returns $1$ if the curve is locally soluble over $\Q_p$, $0$ otherwise. \fun{long}{nf_hyperell_locally_soluble}{GEN nf, GEN T, GEN pr} let $K$ be a number field, associated to \kbd{nf}, \kbd{pr} a \var{prid} associated to some maximal ideal $\goth{p}$; assumes that $T\in\Z_K[X]$ is integral. Returns $1$ if the curve is locally soluble over $K_{\goth{p}}$. \newpage pari-2.7.5/doc/parimacro.tex0000644000175000017500000003130012463145205014351 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \catcode`\@=11 % % GENERAL FORMATTING % \newif\ifSUBSECTOC\SUBSECTOCtrue \newif\ifSUBSECDOT\SUBSECDOTtrue \newif\ifGPHELP \newif\ifPDF \newread\std \def\checkfile#1{\def\@stdfile{#1}\openin\std=#1\relax} \long\def\@ifundef#1#2#3{\expandafter\ifx\csname #1\endcsname\relax#2\else#3\fi} % do we come from gphelp ? \@ifundef{fromgphelp}{\GPHELPfalse}{\GPHELPtrue} \ifGPHELP %YES \overfullrule=0pt \else %NO \magnification=\magstephalf \PDFfalse \ifx\pdfoutput\undefined \else \ifnum\pdfoutput<1 \else \PDFtrue \fi \fi \fi % if paricfg.tex is there (Configure succeeded), input it, otherwise use % default values \checkfile{paricfg.tex} \ifeof\std \checkfile{doc/paricfg.tex} \fi \ifeof\std \ifGPHELP\else% OK for gphelp to use default values \message{paricfg.tex not found. You should run Configure.} \fi \def\vers{2.0.x} \def\includedir{/usr/local/include/pari} \def\libdir{/usr/local/lib} \else \input\@stdfile \fi \font\chaptertitlefont=cmr12 scaled \magstep1 \font\chaptertitlebf=cmbx10 scaled \magstep2 \font\sectiontitlebf=cmbx12 \font\seventt=cmtt8 scaled 875 \scriptfont\ttfam=\seventt % we should really set the \hyphenchar etc first \parskip=6pt plus 3pt minus 1.5pt %\overfullrule=0pt %% %% TABLE OF CONTENTS %% \newwrite\toc \def\tableofcontents{\begintitle \openin\std=\jobname.toc \ifeof\std \else \begingroup \centerline{\bf Table of Contents}\medskip \parskip=0pt plus 1pt \parindent=0pt \catcode`\_=11 % make _ an ordinary char (frequent in function names) \catcode`\@=11 % make @ an ordinary char (appears in \_ expansion) \obeylines\input\jobname.toc \endgroup \fi \openout\toc=\jobname.toc \endtitle} %% %% CROSS REFERENCING & INDEX %% \newif\ifsecondpass \newwrite\out \newwrite\aux \newwrite\index \ifGPHELP % disable crossreferences \def\condwrite#1#2{} \def\idx#1{#1} \def\toindex#1{} \def\tocwrite#1{} \def\label#1{} \def\gphelpref#1{[Label: {\tt #1}]} \def\gphelpsecref#1{Section~\gphelpref{#1}} \def\ref{\let\do=\gphelpref\doverb} \def\secref{\let\do=\gphelpsecref\doverb} \else % none of the following is needed by gphelp \def\typeout#1{\immediate\write\out{#1}} \def\@namedef#1{\expandafter\def\csname#1\endcsname} \def\newlabel#1#2{\@ifundef{r@#1}{}{\message{Label `#1' multiply defined}}\global\@namedef{r@#1}{#2}} \openin\std=\jobname.std \ifeof\std \secondpassfalse \typeout{FIRST PASS} \openout\index=\jobname.idx \let\condwrite=\write \else \secondpasstrue \typeout{SECOND PASS} \let\immediate\relax \def\condwrite#1#2{} \fi %default font for index entry \def\f@nt{rm} %% \toindex{#1} = put #1 in index; use font \f@nt, indicate \pageno. %% If PDF, associate the page to a unique integer (\pdfdestcntr). \ifPDF \def\toindex#1{\putdest \immediate\condwrite\index{!#1!\f@nt!\the\pageno!\number\pdfdestcntr}} \else \def\toindex#1{% \immediate\condwrite\index{!#1!\f@nt!\the\pageno!}} \fi \checkfile{\jobname.aux} \ifeof\std \message{No aux file.} \else \input\@stdfile% input aux file if present \fi % \ref, \label. We need an auxiliary file written during first pass \openout\aux=\jobname.aux \ifx\inputlineno\undefined \let\on@line\empty \else \def\on@line{ on input line \the\inputlineno} \fi \def\@errundef#1{\typeout{Reference `#1' on page \the\pageno \space undefined\on@line}} \def\@car#1#2\@nil{#1} \def\@cdr#1#2\@nil{#2} \def\@ref {\expandafter\@cdr\@temp \@nil\null} \def\@cref{\expandafter\@car\@temp \@nil\null} \def\label#1{\immediate\write\aux{\string \newlabel{#1}{{\the\chapno}{\currentlabel}}}} \def\ref#1{\@ifundef{r@#1} {{\bf ??}\@errundef{#1}} {\edef\@temp{\csname r@#1\endcsname}% \def\lbl{\@ref}\def\chp{\@cref}% \ifx\chp{\the\chapno}\lbl\else\chp.\lbl\fi}} \def\secref#1{Section~\ref{#1}} \fi % end of non-gphelp section %% %% VERBATIM MODE %% % \doverb: setup verbatim mode for the first argument, and execute \do{\arg} \def\setupverb{\def\do##1{\catcode`##1=12}\dospecials \catcode`\ =10% standard space \catcode`\f=13% to break ugly ligatures as in nf{}init, use \EFF instead } % f won't produce any ligature if catcode 13, e.g in verbatim mode (cf above). { \let\GDEF=\gdef \global\let\EFF=f \catcode`\f=13 \GDEFf{\EFF{}}} \begingroup \catcode`<=1\catcode`\{=12 \catcode`>=2\catcode`\}=12 \gdef\d@verb<% \def\next{##1}<\gdef\@va<##1>\endgroup% \do<\@va>>% \@va is the verbatim argument \next> % \gdef\d@verbb<% \def\next{##1}{##2}<\gdef\@va<##1>\gdef\@vb<##2>\endgroup% \do<\@va><\@vb>>% \@vxxx are the verbatim arguments \next> % \gdef\d@verbbb<% \def\next{##1}{##2}{##3}<\gdef\@va<##1>\gdef\@vb<##2>\gdef\@vc<##3>\endgroup% \do<\@va><\@vb><\@vc>>% \@vxxx are the verbatim arguments \next> % \endgroup \def\doverb {\begingroup\setupverb\d@verb} \def\doverbb{\begingroup\setupverb\d@verbb} \def\doverbbb{\begingroup\setupverb\d@verbbb} % argument (silently) goes to index \def\sidx{\gdef\f@nt{rm}\let\do=\toindex\doverb} % \rm \def\kbdsidx{\gdef\f@nt{tt}\let\do=\toindex\doverb}% \tt \def\varsidx{\gdef\f@nt{it}\let\do=\toindex\doverb}% \tt % argument printed + sent to index \def\@idx#1{#1\toindex{#1}} \def\idx{\gdef\f@nt{rm}\let\do=\@idx\doverb} % to index + set up as key (keyword) \def\@keyidx#1{{\bf\@idx{#1}}} \def\teb{\gdef\f@nt{tt}\let\do=\@keyidx\doverb} % to index + set up as kbd (verbatim) \def\@kbdidx#1{{\tt\@idx{#1}}} \def\tet{\gdef\f@nt{tt}\let\do=\@kbdidx\doverb} % to index + set up as var (variable) \def\@kbdvar#1{{\it\@idx{#1}\/}} \def\tev{\gdef\f@nt{it}\let\do=\@kbdvar\doverb} \def\@synt#1#2{\gdef\f@nt{tt}\toindex{#1} The library syntax is \key{#1}({\tt #2})} \def\synt{\let\do=\@synt\doverb} % function prototypes \def\funno#1#2#3{\tolerance 1200\emergencystretch 3em\hbadness 4000\noindent{\tt#1 #2(#3)}} % no index \def\@fun#1#2#3{\gdef\f@nt{tt}\toindex{#2}\funno{#1}{#2}{#3}} \def\fun{\let\do=\@fun\doverbbb} \def\@doc#1#2{\gdef\f@nt{tt}\toindex{#1}\noindent{\tt#2}} \def\doc{\let\do=\@doc\doverbb} %% %% SECTIONS %% \newcount\appno \newcount\chapno \newcount\secno \newcount\subsecno \newcount\subsubsecno \def\newpage{\hbox{}\vfill\eject} %Table of contents. cf TeXBook Exercise 21.10 \def\tocwrite#1{{\let\the=0\edef\next{\condwrite\toc{#1}}\next}} \let\putchapdest\relax \let\sectionhook\relax \def\title#1#2{% \ifodd\pageno\else\newpage\fi \tocwrite{{\bf #1 #2\string\dotfill\the\pageno}} \ifGPHELP\else \putchapdest \centerline{\chaptertitlefont #1}\medskip \fi \centerline{\let\bf\chaptertitlebf \chaptertitlefont #2}\vskip1cm} \def\sectitle#1{% \ifGPHELP\else% \vskip 0pt plus 54pt\penalty-600% good break \vskip 24pt plus -45pt minus 9pt\fi% \putchapdest% \tocwrite{{\hskip0.5cm#1\string\dotfill\the\pageno}}% \leftline{\sectionhook{\sectiontitlebf #1}.} \penalty10000 % impossible break \smallskip}% whatever follows will add a \parskip \def\subsectitle#1{% \ifGPHELP\else% \vskip 0pt plus 45pt\penalty-300 \vskip 6pt plus -42pt minus 3pt\fi% \ifSUBSECTOC\tocwrite{{\sevenrm \hskip1cm#1\string\dotfill\the\pageno}}\fi% \sectionhook\noindent{\bf#1}.} \def\subsubsectitle#1{% a \parskip is being added anyway by \noindent \ifGPHELP\else% \par\vskip 0pt plus 39pt\penalty-200 \vskip 0pt plus -37pt minus 1.5pt\fi% \sectionhook\noindent{\bf#1}.} \ifGPHELP \let\maketitle\relax \else \def\maketitle{% \ifnum\chapno=0 \currentlabel. \else \number\chapno.\currentlabel\ \fi} \fi \def\misctitle#1{\par\vskip 0pt plus 66pt\penalty-400 \vskip 3pt plus -64pt minus 1.5pt\noindent{\bf #1.}} % Chapter headings occupy two lines in the manual (only one in % INSTALL.tex and gphelp-extracted bits). Syntax requirement: After calling % \chapter{...} and possibly \label{...} etc, an empty line _must_ follow % before the first paragraph of text or section heading begins. [GN] \def\chapter#1#2\par{ \secno=0\global\advance\chapno by 1 \title{Chapter \number\chapno:}{#1}#2\noindent\ignorespaces} \def\appendix#1\par{ \chapno=0 \secno=0\global\advance\appno by 1 \def\applet{\ifcase\appno\or A\or B\or C\or D\or E\or F\or G\fi} \title{Appendix \applet:}{#1}\noindent\ignorespaces} \def\section#1{% \subsecno=0\global\advance\secno by 1% \gdef\currentlabel{\number\secno}% \sectitle{\maketitle#1}} \def\subsec#1{ \subsubsecno=0\global\advance\subsecno by 1 \gdef\currentlabel{\number\secno.\number\subsecno} \subsectitle{\maketitle#1}} \def\subsubsec#1{ \global\advance\subsubsecno by 1 \gdef\currentlabel{\number\secno.\number\subsecno.\number\subsubsecno} \subsubsectitle{\maketitle#1}} \def\annotepar#1{\noindent\llap{#1:\ \ }} \def\emacs{\annotepar{EMACS}} \def\subseckbd#1{\subsec{\kbd{#1}}} % % General purpose % \def\begintitle{ \begingroup\nopagenumbers \font\mine=cmb10 scaled 1893 \hbox{} } \def\authors{ \centerline{The PARI Group} \vskip 1.truecm \centerline{Institut de Math\'ematiques de Bordeaux, UMR 5251 du CNRS.} \centerline{Universit\'e Bordeaux 1, 351 Cours de la Lib\'eration} \centerline{F-33405 TALENCE Cedex, FRANCE} \centerline{\tt e-mail: pari@math.u-bordeaux.fr} \vskip 1.5truecm \centerline{\sectiontitlebf Home Page:} \centerline{\kbd{http://pari.math.u-bordeaux.fr/}} \vskip 2.truecm } \def\copyrightpage{ \begintitle \vskip 14cm \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 preserved on all copies. \medskip\par \noindent Permission is granted to copy and distribute modified versions, or 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--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 Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. \endtitle } \def\endtitle{\newpage\endgroup} \newfam\euffam \font\teneuf=eufm10 \font\eighteuf=eufm8 \textfont\euffam=\teneuf \scriptfont\euffam=\eighteuf \def\goth#1{{\fam\euffam#1}} \def\kbd#1{{\tt #1}} \def\key#1{{\bf #1}} \def\emph#1{{\it #1\/}} \def\var#1{\hbox{\it #1\/}} \def\floor#1{\left\lfloor #1 \right\rfloor} \def\ceil#1{\left\lceil #1 \right\rceil} \def\round#1{\left\lfloor #1 \right\rceil} \def\fl{\var{f\kern0pt lag}} \def\Cl{\text{Cl}} \def\gcd{\text{gcd}} \def\lcm{\text{lcm}} \def\Norm{\text{Norm}} \def\Id{\text{Id}} \def\disc{\text{disc}} \def\item{$\bullet$~} \def\bs{{\char'134}} \def\obr{{\char'173}} \def\cbr{{\char'175}} \def\pow{\^{}\hskip0pt} \def\til{\raise-0.3em\hbox{\~{}}} \def\b#1{{\tt \bs#1}} \def\mod{\,{\rm mod}\,} \def\text#1{{\rm#1}} \def\dfrac#1#2{{{#1}\over{#2}}} \def\binom#1#2{\pmatrix{{#1}\cr{#2}}} \def\Bbb#1{{\bf #1}} {\catcode`\_=11 \gdef\typ#1{\kbd{t_#1}}} \def\Z{\Bbb Z} \def\Q{\Bbb Q} \def\F{\Bbb F} \def\P{\Bbb P} \def\R{\Bbb R} \def\C{\Bbb C} \def\dotfill{\leaders\hbox to 3truemm{\hfil.\hfil}\hfill} \def\B{\kbd{BITS\_IN\_LONG}} \def\op{{\it op\/}} % verbatim mode, leave alone $ and _ % @ made active: assume verbatim text doesn't contain it \newif\ifnopar {\catcode`\^=13\global\let^=\pow\obeyspaces\global\let \ } \def\ttverb{% \nopartrue \catcode`\\=12% \catcode`\{=12% \catcode`\}=12% \catcode`\&=12% \catcode`\#=12% \catcode`\%=12% \catcode`\^=13% \catcode`\~=13\def~{{\til}}% \catcode`\@=0% \def\par{\futurelet\next\dopars}% \def\dopars{% \ifnopar \noparfalse% \else% treat two consecutive \par specialy \ifx\next\par \vskip4pt plus 1pt\nopartrue% \else \leavevmode\endgraf\fi\fi}% \obeyspaces\obeylines\tt} % back to normalcy \def\unverb{% \catcode`\\=0% \catcode`\{=1% \catcode`\}=2% \catcode`\$=3% \catcode`\&=4% \catcode`\#=6% \catcode`\^=7% \catcode`\_=8% \catcode`\^^I=10} \def\bprogpart{\begingroup% \vskip 0pt plus 1pt% \leavevmode\parskip=0pt plus 1pt% \interlinepenalty2000\clubpenalty9000\widowpenalty9000% \ttverb} % complete verbatim (including _ and $) \def\bprogfile#1{\bprog\input#1\eprog} \def\bprog{\bprogpart\catcode`\_=12\catcode`\$=12} \def\eprog{\endgroup\par} {\obeylines \gdef\com{\begingroup\unverb\comstart} \gdef\comstart#1^^M{\it#1\endgroup } % newline after @endgroup is important } % comments \def\Ccom{\begingroup\unverb\Ccomstart} \def\Ccomstart#1*/{\rm#1\endgroup*/} \ifPDF \input pdfmacs.tex \fi \catcode`\@=12 pari-2.7.5/doc/libpari.tex0000644000175000017500000000144612366172547014041 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Compile with plain TeX % \def\TITLE{User's Guide to the PARI library} \input parimacro.tex % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine User's Guide} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine the PARI library} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \openin\std=users.aux \ifeof\std \else \input users.aux \fi \chapno=3 { \input usersch4 } { \input usersch5 } { \input usersch6 } { \input usersch7 } { \input appb } { \input appd } \input index\end pari-2.7.5/doc/tex2mail.10000644000175000017500000000372312366172547013504 0ustar billbill.TH TEX2MAIL 1 "26 March 2001" .SH NAME tex2mail \- TeX to ascii math prettyprinter .SH SYNOPSIS .BR tex2mail [-linelength= .IR length ] [-maxdef= .IR number ] [-debug= .IR number ] [-by_par= .IR number ] [-TeX] [-ragged] [-noindent] .SH DESCRIPTION Filter converting TeX or LaTeX math formulae to ASCII art. tex2mail is used by the PARI-GP calculator for output method .I external prettyprint . Under gp, prettyprint mode can be set by .B default(output, 3) (or \\o3). By default, this switches gp main output to TeX format, filtered by .RS tex2mail \-TeX \-noindent \-ragged \-by_par .RE Flags passed to tex2mail can be modified via the .IR prettyprinter default in gp. .SH OPTIONS The following command line options are available: .TP .BI \-linelength=length Wrap text at this column. .TP .BI \-maxdef=number definition loops: croak if more than maxdef substitutions in a given paragraph. .TP .BI \-debug=debuglevel output debugging messages. .TP .BI \-by_par Expect each paragraph to be terminated by *exactly* 2 "\\n", and do not print an extra "\\n" between paragraphs. .TP .BI \-TeX Assume input formulae are in plain TeX format. .TP .BI \-ragged leave right ragged. .TP .BI \-noindent assume \\noindent everywhere. .SH BUGS % at the end of a line followed by \\n\\n is recognized as end of paragraph .SH AUTHOR Ilya Zakharevitch .SH SEE ALSO .IR gp (1), .IR tex (1), .SH COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. pari-2.7.5/doc/gp.10000644000175000017500000002135112366172547012362 0ustar billbill.TH GP 1 "25 September 2013" .SH NAME gp \- The PARI calculator .SH SYNOPSIS .B gp .RB [ -s .IR stacksize ] .RB [ -p .IR primelimit ] .RB [ --emacs ] .RB [ -f | --fast ] .RB [ -q | --quiet ] .RB [ -D | --default .IR key=val ] .RB [ --help ] .RB [ --test ] .RB [ --texmacs ] .RB [ --version ] .RB [ --version-short ] [ file1 file2 ...] .SH DESCRIPTION Invokes the PARI-GP calculator \&\fBgp\fR; gp is an advanced programmable calculator, specializing in number theory, which computes symbolically as long as possible, numerically where needed, and contains a wealth of arithmetic functions: factorizations, elliptic curves, Galois theory, class field theory... Commands, written in the GP scripting language, are input interactively or loaded from files. If present at the end of the command line, files 'file1', 'file2', ... are loaded on startup; they must be written in the GP language. .SH OPTIONS Command line options are available in both short form (-f) and POSIX-like (--fast). Numeric arguments can be followed by a modifier .B k , .B M or .B G at the user's convenience; in that case the argument is multiplied by 10^3, 10^6, or 10^9 respectively. .TP .B \-f, \--fast Fast start (or factory settings). Do not read .B .gprc (see below) upon startup. .TP .B \-p limit [DEPRECATED] Upon startup, gp computes a table of small primes used in number-theoretic applications. If .I primelimit is set, the table include primes up to that bound instead of the default (= 500000). It is now mostly useless to change this value. .TP .B \-q, \--quiet Quiet mode. Do not print headers or history numbers and do not say goodbye. .TP .B \-D, \--default key=val performs .BR default(key, .BR val) ";" on startup, overriding values from the .B gprc preferences file. 'val' must be a constant value and is not allowed to involve any computation (e.g. 1+1 is forbidden). Any number of such default-setting statements may appear on the command line. .TP .B \-s limit Size of gp internal stack allocated on startup. When gp runs out of space, it interrupts the current computation and raises a .BI "stack overflow" exception. If this occurs frequently, start with a bigger stack. The stack size can also be increased from within gp, using .BR default(parisize, limit) ";" it may be convenient to set .B stacksize from your .B .gprc. Note that computations with a .B smaller stack may be more efficient due to better data locality. Most computations should need less than 20MB. .TP .B \--emacs gp can be run in an .I Emacs shell (see GP User's manual for details). This flag is then required for smooth interaction with the .I PariEmacs package (pari.el). It is set automatically by the pari.el package, and will produce nice display oddities if you set it outside of an .I Emacs session. .TP .B \--help print a summary of available command-line options. .TP .B \--test run gp in test mode: suppress printing of history numbers and wrap long output lines (to get readable diff output). For benches only. .TP .B \--texmacs gp can be run from a .I TeXmacs frontend. This flag is set by TeXmacs, to enable special purpose communication channels. Do not set it yourself. .TP .B \--version output version info (banner) then exit. .TP .B \--version-short output version number then exit. .SH USE .TP .B ? to get online help. .TP .B ?? to get extended online help (more precisely, to call the external help program, .B gphelp by default) .TP .B quit (or \\q), or .B EOF (Ctrl-D) to quit .BR gp . .PP The following works only when gp was linked with GNU .IR readline library: .TP arrow keys for editing and viewing the input history. .TP .B TAB for automatic completion .SH MANUALS The following material is included in the standard distribution (originally in TeX format): .TP .I The User's Guide to PARI/GP (users.dvi) .TP .I The User's Guide to the PARI library (library.dvi) .TP .I The Developer's Guide to the PARI library (develop.dvi) .TP .I PARI/GP, a tutorial (tutorial.dvi) .TP .I PARI/GP reference card (refcard.ps): 4 pages, based on an earlier version by Joseph H. Silverman. .SH FILES .TP .I gp main executable .TP .I $HOME/.gprc (or $GPRC if set) user preference file, read at beginning of execution by each .B gp shell. A default gprc .I gprc.dft is provided with the distribution. If this file cannot be found, .I /etc/gprc is checked instead. .TP .I pari.log default logfile (can be changed in the gprc file or interactively using .B default() ) .TP .I pari.ps default psfile used for postscript output (as above) .TP .I gphelp default external help program (as above) .TP .I *.gp GP programs .SH ENVIRONMENT .TP .I $GPRC place to look for the user's preference file (gprc); if the file does not exist, we then check in $HOME/.gprc, /etc/gprc, and finally for a file named 'gprc' in PARI's .B datadir. .TP .I $GP_DATA_DIR directory containing data installed by optional PARI packages. For example, the Galois resolvents files in directory .I galdata/ needed by the .B polgalois function, in degrees 8 to 11; or the modular polynomials in .I seadata/ used by the .B ellap function for large base fields. This environment variable overrides PARI's 'datadir', defined at Configure time. .TP .I $GP_POSTSCRIPT_VIEWER an application able to display PostScript files, used by the .I plotps graphic engine. This engine is a fallback used to output hi-res plots even when no compatible graphical library was available on your platform at Configure time. (Dumps the graph to a temporary file, then open the file.) .TP .I $GPHELP name of the external help program invoked by ?? and ??? shortcuts. .TP .I $GPTMPDIR name of the directory where temporary files will be generated. .SH HOME PAGE PARI's home page resides at .RS .I http://pari.math.u-bordeaux.fr/ .RE .SH MAILING LISTS There are a number of mailing lists devoted to the PARI/GP package, and most feedback should be directed to those. See .RS .I http://pari.math.u-bordeaux1.fr/lists-index.html .RE for details. The most important ones are: .PP - .B pari-announce (moderated): for us to announce major version changes. .PP - .B pari-dev: for everything related to the development of PARI, including suggestions, technical questions, bug reports or patch submissions. .PP - .B pari-users: for discuss about everything else, in particular ask for help. To subscribe, send empty messages with a Subject: containing the word "subscribe" respectively to .PP pari-announce-request@pari.math.u-bordeaux.fr .PP pari-users-request@pari.math.u-bordeaux.fr .PP pari-dev-request@pari.math.u-bordeaux.fr .SH BUG REPORTS Bugs should be submitted online to our Bug Tracking System, available from PARI's home page, or directly from the URL .RS .I http://pari.math.u-bordeaux.fr/Bugs/ .RE Further instructions can be found on that page. .SH TRIVIA Despite the leading G, GP has nothing to do with GNU. The first version was originally called GPC, for Great Programmable Calculator. For some reason, the trailing C was eventually dropped. PARI has nothing to do with the French capital. The name is a pun about the project's early stages when the authors started to implement a library for "Pascal ARIthmetic" in the PASCAL programming language. They quickly switched to C. For the benefit of non-native French speakers, here's a slightly expanded explanation: .B Blaise Pascal (1623-1662) was a famous French mathematician and philosopher who was one of the founders of probability and devised one of the first "arithmetic machines". He once proposed the following "proof" of the existence of God for the unbelievers: whether He exists or not I lose nothing by believing in Him, whereas if He does and I misbehave... This is the so-called "pari de Pascal" (Pascal's Wager). Note that PARI also means "fairy" in Persian. .SH AUTHORS PARI was originally written by Christian Batut, Dominique Bernardi, Henri Cohen, and Michel Olivier in Laboratoire A2X (Universite Bordeaux I, France), and was maintained by Henri Cohen up to version 1.39.15 (1995), and by Karim Belabas since then. A great number of people have contributed to the successive improvements which eventually resulted in the present version. See the AUTHORS file in the distribution. .SH SEE ALSO .IR gap (1), .IR gphelp (1), .IR perl (1), .IR readline (3), .IR sage (1), .IR tex (1), .IR texmacs (1), .SH COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. pari-2.7.5/doc/usersch3.tex0000644000175000017500000245551012605246076014160 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Functions and Operations Available in PARI and GP} \label{se:functions} The functions and operators available in PARI and in the GP/PARI calculator are numerous and ever-expanding. Here is a description of the ones available in version \vers. It should be noted that many of these functions accept quite different types as arguments, but others are more restricted. The list of acceptable types will be given for each function or class of functions. Except when stated otherwise, it is understood that a function or operation which should make natural sense is legal. In this chapter, we will describe the functions according to a rough classification. The general entry looks something like: \key{foo}$(x,\{\fl=0\})$: short description. The library syntax is \kbd{GEN foo(GEN x, long fl = 0)}. \noindent This means that the GP function \kbd{foo} has one mandatory argument $x$, and an optional one, $\fl$, whose default value is 0. (The $\{\}$ should not be typed, it is just a convenient notation we will use throughout to denote optional arguments.) That is, you can type \kbd{foo(x,2)}, or \kbd{foo(x)}, which is then understood to mean \kbd{foo(x,0)}. As well, a comma or closing parenthesis, where an optional argument should have been, signals to GP it should use the default. Thus, the syntax \kbd{foo(x,)} is also accepted as a synonym for our last expression. When a function has more than one optional argument, the argument list is filled with user supplied values, in order. When none are left, the defaults are used instead. Thus, assuming that \kbd{foo}'s prototype had been $$\hbox{% \key{foo}$(\{x=1\},\{y=2\},\{z=3\})$,% }$$ typing in \kbd{foo(6,4)} would give you \kbd{foo(6,4,3)}. In the rare case when you want to set some far away argument, and leave the defaults in between as they stand, you can use the ``empty arg'' trick alluded to above: \kbd{foo(6,,1)} would yield \kbd{foo(6,2,1)}. By the way, \kbd{foo()} by itself yields \kbd{foo(1,2,3)} as was to be expected. In this rather special case of a function having no mandatory argument, you can even omit the $()$: a standalone \kbd{foo} would be enough (though we do not recommend it for your scripts, for the sake of clarity). In defining GP syntax, we strove to put optional arguments at the end of the argument list (of course, since they would not make sense otherwise), and in order of decreasing usefulness so that, most of the time, you will be able to ignore them. Finally, an optional argument (between braces) followed by a star, like $\{\var{x}\}*$, means that any number of such arguments (possibly none) can be given. This is in particular used by the various \kbd{print} routines. \misctitle{Flags} A \tev{flag} is an argument which, rather than conveying actual information to the routine, instructs it to change its default behavior, e.g.~return more or less information. All such flags are optional, and will be called \fl\ in the function descriptions to follow. There are two different kind of flags \item generic: all valid values for the flag are individually described (``If \fl\ is equal to $1$, then\dots''). \item binary:\sidx{binary flag} use customary binary notation as a compact way to represent many toggles with just one integer. Let $(p_0,\dots,p_n)$ be a list of switches (i.e.~of properties which take either the value $0$ or~$1$), the number $2^3 + 2^5 = 40$ means that $p_3$ and $p_5$ are set (that is, set to $1$), and none of the others are (that is, they are set to $0$). This is announced as ``The binary digits of $\fl$ mean 1: $p_0$, 2: $p_1$, 4: $p_2$'', and so on, using the available consecutive powers of~$2$. \misctitle{Mnemonics for flags} Numeric flags as mentioned above are obscure, error-prone, and quite rigid: should the authors want to adopt a new flag numbering scheme (for instance when noticing flags with the same meaning but different numeric values across a set of routines), it would break backward compatibility. The only advantage of explicit numeric values is that they are fast to type, so their use is only advised when using the calculator \kbd{gp}. As an alternative, one can replace a numeric flag by a character string containing symbolic identifiers. For a generic flag, the mnemonic corresponding to the numeric identifier is given after it as in \bprog fun(x, {flag = 0} ): If flag is equal to 1 = AGM, use an agm formula ... @eprog\noindent which means that one can use indifferently \kbd{fun($x$, 1)} or \kbd{fun($x$, "AGM")}. For a binary flag, mnemonics corresponding to the various toggles are given after each of them. They can be negated by prepending \kbd{no\_} to the mnemonic, or by removing such a prefix. These toggles are grouped together using any punctuation character (such as ',' or ';'). For instance (taken from description of $\tet{ploth}(X=a,b,\var{expr},\{\fl=0\},\{n=0\})$) \centerline{Binary digits of flags mean: $1=\kbd{Parametric}$, $2=\kbd{Recursive}$, \dots} \noindent so that, instead of $1$, one could use the mnemonic \kbd{"Parametric; no\_Recursive"}, or simply \kbd{"Parametric"} since \kbd{Recursive} is unset by default (default value of $\fl$ is $0$, i.e.~everything unset). People used to the bit-or notation in languages like C may also use the form \kbd{"Parametric | no\_Recursive"}. \misctitle{Pointers} \varsidx{pointer} If a parameter in the function prototype is prefixed with a \& sign, as in \key{foo}$(x,\&e)$ \noindent it means that, besides the normal return value, the function may assign a value to $e$ as a side effect. When passing the argument, the \& sign has to be typed in explicitly. As of version \vers, this \tev{pointer} argument is optional for all documented functions, hence the \& will always appear between brackets as in \kbd{Z\_issquare}$(x,\{\&e\})$. \misctitle{About library programming} The \var{library} function \kbd{foo}, as defined at the beginning of this section, is seen to have two mandatory arguments, $x$ and \fl: no function seen in the present chapter has been implemented so as to accept a variable number of arguments, so all arguments are mandatory when programming with the library (usually, variants are provided corresponding to the various flag values). We include an \kbd{= default value} token in the prototype to signal how a missing argument should be encoded. Most of the time, it will be a \kbd{NULL} pointer, or -1 for a variable number. Refer to the \emph{User's Guide to the PARI library} for general background and details. \section{Standard monadic or dyadic operators} \subseckbd{+$/$-} The expressions \kbd{+}$x$ and \kbd{-}$x$ refer to monadic operators (the first does nothing, the second negates $x$). The library syntax is \fun{GEN}{gneg}{GEN x} for \kbd{-}$x$. \subseckbd{+} The expression $x$ \kbd{+} $y$ is the \idx{sum} of $x$ and $y$. Addition between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] + x, y[2],\dots]$ and $y + x \text{Id}$. Other additions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gadd}{GEN x, GEN y}. \subseckbd{-} The expression $x$ \kbd{-} $y$ is the \idx{difference} of $x$ and $y$. Subtraction between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] - x, y[2],\dots]$ and $y - x \text{Id}$. Other subtractions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gsub}{GEN x, GEN y} for $x$ \kbd{-} $y$. \subseckbd{*} The expression $x$ \kbd{*} $y$ is the \idx{product} of $x$ and $y$. Among the prominent impossibilities are multiplication between vector/matrices of incompatible sizes, between a \typ{INTMOD} or \typ{PADIC} Restricted to scalars, \kbd{*} is commutative; because of vector and matrix operations, it is not commutative in general. Multiplication between two \typ{VEC}s or two \typ{COL}s is not allowed; to take the \idx{scalar product} of two vectors of the same length, transpose one of the vectors (using the operator \kbd{\til} or the function \kbd{mattranspose}, see \secref{se:linear_algebra}) and multiply a line vector by a column vector: \bprog ? a = [1,2,3]; ? a * a *** at top-level: a*a *** ^-- *** _*_: forbidden multiplication t_VEC * t_VEC. ? a * a~ %2 = 14 @eprog If $x,y$ are binary quadratic forms, compose them; see also \kbd{qfbnucomp} and \kbd{qfbnupow}. If $x,y$ are \typ{VECSMALL} of the same length, understand them as permutations and compose them. The library syntax is \fun{GEN}{gmul}{GEN x, GEN y} for $x$ \kbd{*} $y$. Also available is \fun{GEN}{gsqr}{GEN x} for $x$ \kbd{*} $x$. \subseckbd{/} The expression $x$ \kbd{/} $y$ is the \idx{quotient} of $x$ and $y$. In addition to the impossibilities for multiplication, note that if the divisor is a matrix, it must be an invertible square matrix, and in that case the result is $x*y^{-1}$. Furthermore note that the result is as exact as possible: in particular, division of two integers always gives a rational number (which may be an integer if the quotient is exact) and \emph{not} the Euclidean quotient (see $x$ \kbd{\bs} $y$ for that), and similarly the quotient of two polynomials is a rational function in general. To obtain the approximate real value of the quotient of two integers, add \kbd{0.} to the result; to obtain the approximate $p$-adic value of the quotient of two integers, add \kbd{O(p\pow k)} to the result; finally, to obtain the \idx{Taylor series} expansion of the quotient of two polynomials, add \kbd{O(X\pow k)} to the result or use the \kbd{taylor} function (see \secref{se:taylor}). \label{se:gdiv} The library syntax is \fun{GEN}{gdiv}{GEN x, GEN y} for $x$ \kbd{/} $y$. \subseckbd{\bs} The expression \kbd{$x$ \bs\ $y$} is the \idx{Euclidean quotient} of $x$ and $y$. If $y$ is a real scalar, this is defined as \kbd{floor($x$/$y$)} if $y > 0$, and \kbd{ceil($x$/$y$)} if $y < 0$ and the division is not exact. Hence the remainder \kbd{$x$ - ($x$\bs$y$)*$y$} is in $[0, |y|[$. Note that when $y$ is an integer and $x$ a polynomial, $y$ is first promoted to a polynomial of degree $0$. When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gdivent}{GEN x, GEN y} for $x$ \kbd{\bs} $y$. \subseckbd{\bs/} The expression $x$ \b{/} $y$ evaluates to the rounded \idx{Euclidean quotient} of $x$ and $y$. This is the same as \kbd{$x$ \bs\ $y$} except for scalar division: the quotient is such that the corresponding remainder is smallest in absolute value and in case of a tie the quotient closest to $+\infty$ is chosen (hence the remainder would belong to $]{-}|y|/2, |y|/2]$). When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gdivround}{GEN x, GEN y} for $x$ \b{/} $y$. \subseckbd{\%} The expression \kbd{$x$ \% $y$} evaluates to the modular \idx{Euclidean remainder} of $x$ and $y$, which we now define. When $x$ or $y$ is a non-integral real number, \kbd{$x$\%$y$} is defined as \kbd{$x$ - ($x$\bs$y$)*$y$}. Otherwise, if $y$ is an integer, this is the smallest non-negative integer congruent to $x$ modulo $y$. (This actually coincides with the previous definition if and only if $x$ is an integer.) If $y$ is a polynomial, this is the polynomial of smallest degree congruent to $x$ modulo $y$. For instance: \bprog ? (1/2) % 3 %1 = 2 ? 0.5 % 3 %2 = 0.5000000000000000000000000000 ? (1/2) % 3.0 %3 = 1/2 @eprog Note that when $y$ is an integer and $x$ a polynomial, $y$ is first promoted to a polynomial of degree $0$. When $x$ is a vector or matrix, the operator is applied componentwise. The library syntax is \fun{GEN}{gmod}{GEN x, GEN y} for $x$ \kbd{\%} $y$. \subseckbd{\pow} The expression $x\hbox{\kbd{\pow}}n$ is \idx{powering}. If the exponent is an integer, then exact operations are performed using binary (left-shift) powering techniques. In particular, in this case $x$ cannot be a vector or matrix unless it is a square matrix (invertible if the exponent is negative). If $x$ is a $p$-adic number, its precision will increase if $v_p(n) > 0$. Powering a binary quadratic form (types \typ{QFI} and \typ{QFR}) returns a reduced representative of the class, provided the input is reduced. In particular, $x\hbox{\kbd{\pow}}1$ is identical to $x$. PARI is able to rewrite the multiplication $x * x$ of two \emph{identical} objects as $x^2$, or $\kbd{sqr}(x)$. Here, identical means the operands are two different labels referencing the same chunk of memory; no equality test is performed. This is no longer true when more than two arguments are involved. If the exponent is not of type integer, this is treated as a transcendental function (see \secref{se:trans}), and in particular has the effect of componentwise powering on vector or matrices. As an exception, if the exponent is a rational number $p/q$ and $x$ an integer modulo a prime or a $p$-adic number, return a solution $y$ of $y^q=x^p$ if it exists. Currently, $q$ must not have large prime factors. Beware that \bprog ? Mod(7,19)^(1/2) %1 = Mod(11, 19) /* is any square root */ ? sqrt(Mod(7,19)) %2 = Mod(8, 19) /* is the smallest square root */ ? Mod(7,19)^(3/5) %3 = Mod(1, 19) ? %3^(5/3) %4 = Mod(1, 19) /* Mod(7,19) is just another cubic root */ @eprog If the exponent is a negative integer, an \idx{inverse} must be computed. For non-invertible \typ{INTMOD}, this will fail and implicitly exhibit a non trivial factor of the modulus: \bprog ? Mod(4,6)^(-1) *** at top-level: Mod(4,6)^(-1) *** ^----- *** _^_: impossible inverse modulo: Mod(2, 6). @eprog\noindent (Here, a factor 2 is obtained directly. In general, take the gcd of the representative and the modulus.) This is most useful when performing complicated operations modulo an integer $N$ whose factorization is unknown. Either the computation succeeds and all is well, or a factor $d$ is discovered and the computation may be restarted modulo $d$ or $N/d$. For non-invertible \typ{POLMOD}, this will fail without exhibiting a factor. \bprog ? Mod(x^2, x^3-x)^(-1) *** at top-level: Mod(x^2,x^3-x)^(-1) *** ^----- *** _^_: non-invertible polynomial in RgXQ_inv. ? a = Mod(3,4)*y^3 + Mod(1,4); b = y^6+y^5+y^4+y^3+y^2+y+1; ? Mod(a, b)^(-1); *** at top-level: Mod(a,b)^(-1) *** ^----- *** _^_: impossible inverse modulo: Mod(0, 4). @eprog\noindent In fact the latter polynomial is invertible, but the algorithm used (subresultant) assumes the base ring is a domain. If it is not the case, as here for $\Z/4\Z$, a result will be correct but chances are an error will occur first. In this specific case, one should work with $2$-adics. In general, one can try the following approach \bprog ? inversemod(a, b) = { my(m); m = polsylvestermatrix(polrecip(a), polrecip(b)); m = matinverseimage(m, matid(#m)[,1]); Polrev( vecextract(m, Str("..", poldegree(b))), variable(b) ) } ? inversemod(a,b) %2 = Mod(2,4)*y^5 + Mod(3,4)*y^3 + Mod(1,4)*y^2 + Mod(3,4)*y + Mod(2,4) @eprog\noindent This is not guaranteed to work either since it must invert pivots. See \secref{se:linear_algebra}. The library syntax is \fun{GEN}{gpow}{GEN x, GEN n, long prec} for $x\hbox{\kbd{\pow}}n$. \subsec{cmp$(x,y)$}\kbdsidx{cmp}\label{se:cmp} Gives the result of a comparison between arbitrary objects $x$ and $y$ (as $-1$, $0$ or $1$). The underlying order relation is transitive, the function returns $0$ if and only if $x~\kbd{===}~y$, and its restriction to integers coincides with the customary one. Besides that, it has no useful mathematical meaning. In case all components are equal up to the smallest length of the operands, the more complex is considered to be larger. More precisely, the longest is the largest; when lengths are equal, we have matrix $>$ vector $>$ scalar. For example: \bprog ? cmp(1, 2) %1 = -1 ? cmp(2, 1) %2 = 1 ? cmp(1, 1.0) \\ note that 1 == 1.0, but (1===1.0) is false. %3 = -1 ? cmp(x + Pi, []) %4 = -1 @eprog\noindent This function is mostly useful to handle sorted lists or vectors of arbitrary objects. For instance, if $v$ is a vector, the construction \kbd{vecsort(v, cmp)} is equivalent to \kbd{Set(v)}. The library syntax is \fun{GEN}{cmp_universal}{GEN x, GEN y}. \subsec{divrem$(x,y,\{v\})$}\kbdsidx{divrem}\label{se:divrem} Creates a column vector with two components, the first being the Euclidean quotient (\kbd{$x$ \bs\ $y$}), the second the Euclidean remainder (\kbd{$x$ - ($x$\bs$y$)*$y$}), of the division of $x$ by $y$. This avoids the need to do two divisions if one needs both the quotient and the remainder. If $v$ is present, and $x$, $y$ are multivariate polynomials, divide with respect to the variable $v$. Beware that \kbd{divrem($x$,$y$)[2]} is in general not the same as \kbd{$x$ \% $y$}; no GP operator corresponds to it: \bprog ? divrem(1/2, 3)[2] %1 = 1/2 ? (1/2) % 3 %2 = 2 ? divrem(Mod(2,9), 3)[2] *** at top-level: divrem(Mod(2,9),3)[2 *** ^-------------------- *** forbidden division t_INTMOD \ t_INT. ? Mod(2,9) % 6 %3 = Mod(2,3) @eprog The library syntax is \fun{GEN}{divrem}{GEN x, GEN y, long v = -1}, where \kbd{v} is a variable number. Also available is \fun{GEN}{gdiventres}{GEN x, GEN y} when $v$ is not needed. \subsec{lex$(x,y)$}\kbdsidx{lex}\label{se:lex} Gives the result of a lexicographic comparison between $x$ and $y$ (as $-1$, $0$ or $1$). This is to be interpreted in quite a wide sense: It is admissible to compare objects of different types (scalars, vectors, matrices), provided the scalars can be compared, as well as vectors/matrices of different lengths. The comparison is recursive. In case all components are equal up to the smallest length of the operands, the more complex is considered to be larger. More precisely, the longest is the largest; when lengths are equal, we have matrix $>$ vector $>$ scalar. For example: \bprog ? lex([1,3], [1,2,5]) %1 = 1 ? lex([1,3], [1,3,-1]) %2 = -1 ? lex([1], [[1]]) %3 = -1 ? lex([1], [1]~) %4 = 0 @eprog The library syntax is \fun{GEN}{lexcmp}{GEN x, GEN y}. \subsec{max$(x,y)$}\kbdsidx{max}\label{se:max} Creates the maximum of $x$ and $y$ when they can be compared. The library syntax is \fun{GEN}{gmax}{GEN x, GEN y}. \subsec{min$(x,y)$}\kbdsidx{min}\label{se:min} Creates the minimum of $x$ and $y$ when they can be compared. The library syntax is \fun{GEN}{gmin}{GEN x, GEN y}. \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)$. A left shift by $n$ corresponds to multiplication by $2^n$. A right shift of an integer $x$ by $|n|$ corresponds to a Euclidean division of $x$ by $2^{|n|}$ with a remainder of the same sign as $x$, hence is not the same (in general) as $x \kbd{\bs} 2^n$. The library syntax is \fun{GEN}{gshift}{GEN x, long n}. \subsec{shiftmul$(x,n)$}\kbdsidx{shiftmul}\label{se:shiftmul} Multiplies $x$ by $2^n$. The difference with \kbd{shift} is that when $n<0$, ordinary division takes place, hence for example if $x$ is an integer the result may be a fraction, while for shifts Euclidean division takes place when $n<0$ hence if $x$ is an integer the result is still an integer. The library syntax is \fun{GEN}{gmul2n}{GEN x, long n}. \subsec{sign$(x)$}\kbdsidx{sign}\label{se:sign} \idx{sign} ($0$, $1$ or $-1$) of $x$, which must be of type integer, real or fraction. The library syntax is \fun{GEN}{gsigne}{GEN x}. \subsec{vecmax$(x,\{\&v\})$}\kbdsidx{vecmax}\label{se:vecmax} If $x$ is a vector or a matrix, returns the largest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. If $v$ is given, set it to the index of a largest entry (indirect maximum), when $x$ is a vector. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a largest entry. This flag is ignored if $x$ is not a vector or matrix. \bprog ? vecmax([10, 20, -30, 40]) %1 = 40 ? vecmax([10, 20, -30, 40], &v); v %2 = 4 ? vecmax([10, 20; -30, 40], &v); v %3 = [2, 2] @eprog The library syntax is \fun{GEN}{vecmax0}{GEN x, GEN *v = NULL}. Also available is \fun{GEN}{vecmax}{GEN x}. \subsec{vecmin$(x,\{\&v\})$}\kbdsidx{vecmin}\label{se:vecmin} If $x$ is a vector or a matrix, returns the smallest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. If $v$ is given, set it to the index of a smallest entry (indirect minimum), when $x$ is a vector. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a smallest entry. This is ignored if $x$ is not a vector or matrix. \bprog ? vecmin([10, 20, -30, 40]) %1 = -30 ? vecmin([10, 20, -30, 40], &v); v %2 = 3 ? vecmin([10, 20; -30, 40], &v); v %3 = [2, 1] @eprog The library syntax is \fun{GEN}{vecmin0}{GEN x, GEN *v = NULL}. Also available is \fun{GEN}{vecmin}{GEN x}. %SECTION: operators \subsec{Comparison and Boolean operators}\sidx{Boolean operators} The six standard \idx{comparison operators} \kbd{<=}, \kbd{<}, \kbd{>=}, \kbd{>}, \kbd{==}, \kbd{!=} are available in GP. The result is 1 if the comparison is true, 0 if it is false. The operator \kbd{==} is quite liberal : for instance, the integer 0, a 0 polynomial, and a vector with 0 entries are all tested equal. 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. 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. The standard boolean operators \kbd{||} (\idx{inclusive or}), \kbd{\&\&} (\idx{and})\sidx{or} and \kbd{!} (\idx{not}) are also available. \section{Conversions and similar elementary functions or commands} \label{se:conversion} \noindent Many of the conversion functions are rounding or truncating operations. In this case, if the argument is a rational function, the result is the Euclidean quotient of the numerator by the denominator, and if the argument is a vector or a matrix, the operation is done componentwise. This will not be restated for every function. \subsec{Col$(x, \{n\})$}\kbdsidx{Col}\label{se:Col} Transforms the object $x$ into a column vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form (in which case the resulting vector is simply the initial object considered as a row vector), \item a polynomial or a power series. In the case of a polynomial, the coefficients of the vector start with the leading coefficient of the polynomial, while for power series only the significant coefficients are taken into account, but this time by increasing order of degree. In this last case, \kbd{Vec} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively, \item a matrix (the column of row vector comprising the matrix is returned), \item a character string (a vector of individual characters is returned). In the last two cases (matrix and character string), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. Note that the function \kbd{Colrev} does not exist, use \kbd{Vecrev}. The library syntax is \fun{GEN}{gtocol0}{GEN x, long n}. \fun{GEN}{gtocol}{GEN x} is also available. \subsec{Colrev$(x, \{n\})$}\kbdsidx{Colrev}\label{se:Colrev} As $\kbd{Col}(x, n)$, then reverse the result. In particular The library syntax is \fun{GEN}{gtocolrev0}{GEN x, long n}. \fun{GEN}{gtocolrev}{GEN x} is also available. \subsec{List$(\{x=[\,]\})$}\kbdsidx{List}\label{se:List} Transforms a (row or column) vector $x$ into a list, whose components are the entries of $x$. Similarly for a list, but rather useless in this case. For other types, creates a list with the single element $x$. Note that, except when $x$ is omitted, this function creates a small memory leak; so, either initialize all lists to the empty list, or use them sparingly. The library syntax is \fun{GEN}{gtolist}{GEN x = NULL}. The variant \fun{GEN}{listcreate}{void} creates an empty list. \subsec{Mat$(\{x=[\,]\})$}\kbdsidx{Mat}\label{se:Mat} Transforms the object $x$ into a matrix. If $x$ is already a matrix, a copy of $x$ is created. If $x$ is a row (resp. column) vector, this creates a 1-row (resp. 1-column) matrix, \emph{unless} all elements are column (resp.~row) vectors of the same length, in which case the vectors are concatenated sideways and the associated big matrix is returned. If $x$ is a binary quadratic form, creates the associated $2\times 2$ matrix. Otherwise, this creates a $1\times 1$ matrix containing $x$. \bprog ? Mat(x + 1) %1 = [x + 1] ? Vec( matid(3) ) %2 = [[1, 0, 0]~, [0, 1, 0]~, [0, 0, 1]~] ? Mat(%) %3 = [1 0 0] [0 1 0] [0 0 1] ? Col( [1,2; 3,4] ) %4 = [[1, 2], [3, 4]]~ ? Mat(%) %5 = [1 2] [3 4] ? Mat(Qfb(1,2,3)) %6 = [1 1] [1 3] @eprog The library syntax is \fun{GEN}{gtomat}{GEN x = NULL}. \subsec{Mod$(a,b)$}\kbdsidx{Mod}\label{se:Mod} In its basic form, creates an intmod or a polmod $(a \mod b)$; $b$ must be an integer or a polynomial. We then obtain a \typ{INTMOD} and a \typ{POLMOD} respectively: \bprog ? t = Mod(2,17); t^8 %1 = Mod(1, 17) ? t = Mod(x,x^2+1); t^2 %2 = Mod(-1, x^2+1) @eprog\noindent If $a \% b$ makes sense and yields a result of the appropriate type (\typ{INT} or scalar/\typ{POL}), the operation succeeds as well: \bprog ? Mod(1/2, 5) %3 = Mod(3, 5) ? Mod(7 + O(3^6), 3) %4 = Mod(1, 3) ? Mod(Mod(1,12), 9) %5 = Mod(1, 3) ? Mod(1/x, x^2+1) %6 = Mod(-1, x^2+1) ? Mod(exp(x), x^4) %7 = Mod(1/6*x^3 + 1/2*x^2 + x + 1, x^4) @eprog If $a$ is a complex object, ``base change'' it to $\Z/b\Z$ or $K[x]/(b)$, which is equivalent to, but faster than, multiplying it by \kbd{Mod(1,b)}: \bprog ? Mod([1,2;3,4], 2) %8 = [Mod(1, 2) Mod(0, 2)] [Mod(1, 2) Mod(0, 2)] ? Mod(3*x+5, 2) %9 = Mod(1, 2)*x + Mod(1, 2) ? Mod(x^2 + y*x + y^3, y^2+1) %10 = Mod(1, y^2 + 1)*x^2 + Mod(y, y^2 + 1)*x + Mod(-y, y^2 + 1) @eprog This function is not the same as $x$ \kbd{\%} $y$, the result of which has no knowledge of the intended modulus $y$. Compare \bprog ? x = 4 % 5; x + 1 %1 = 5 ? x = Mod(4,5); x + 1 %2 = Mod(0,5) @eprog The library syntax is \fun{GEN}{gmodulo}{GEN a, GEN b}. \subsec{Pol$(t,\{v='x\})$}\kbdsidx{Pol}\label{se:Pol} Transforms the object $t$ into a polynomial with main variable $v$. If $t$ is a scalar, this gives a constant polynomial. If $t$ is a power series with non-negative valuation or a rational function, the effect is similar to \kbd{truncate}, i.e.~we chop off the $O(X^k)$ or compute the Euclidean quotient of the numerator by the denominator, then change the main variable of the result to $v$. The main use of this function is when $t$ is a vector: it creates the polynomial whose coefficients are given by $t$, with $t[1]$ being the leading coefficient (which can be zero). It is much faster to evaluate \kbd{Pol} on a vector of coefficients in this way, than the corresponding formal expression $a_n X^n + \dots + a_0$, which is evaluated naively exactly as written (linear versus quadratic time in $n$). \tet{Polrev} can be used if one wants $x[1]$ to be the constant coefficient: \bprog ? Pol([1,2,3]) %1 = x^2 + 2*x + 3 ? Polrev([1,2,3]) %2 = 3*x^2 + 2*x + 1 @eprog\noindent The reciprocal function of \kbd{Pol} (resp.~\kbd{Polrev}) is \kbd{Vec} (resp.~ \kbd{Vecrev}). \bprog ? Vec(Pol([1,2,3])) %1 = [1, 2, 3] ? Vecrev( Polrev([1,2,3]) ) %2 = [1, 2, 3] @eprog\noindent \misctitle{Warning} This is \emph{not} a substitution function. It will not transform an object containing variables of higher priority than~$v$. \bprog ? Pol(x + y, y) *** at top-level: Pol(x+y,y) *** ^---------- *** Pol: variable must have higher priority in gtopoly. @eprog The library syntax is \fun{GEN}{gtopoly}{GEN t, long v = -1}, where \kbd{v} is a variable number. \subsec{Polrev$(t,\{v='x\})$}\kbdsidx{Polrev}\label{se:Polrev} Transform the object $t$ into a polynomial with main variable $v$. If $t$ is a scalar, this gives a constant polynomial. If $t$ is a power series, the effect is identical to \kbd{truncate}, i.e.~it chops off the $O(X^k)$. The main use of this function is when $t$ is a vector: it creates the polynomial whose coefficients are given by $t$, with $t[1]$ being the constant term. \tet{Pol} can be used if one wants $t[1]$ to be the leading coefficient: \bprog ? Polrev([1,2,3]) %1 = 3*x^2 + 2*x + 1 ? Pol([1,2,3]) %2 = x^2 + 2*x + 3 @eprog The reciprocal function of \kbd{Pol} (resp.~\kbd{Polrev}) is \kbd{Vec} (resp.~ \kbd{Vecrev}). The library syntax is \fun{GEN}{gtopolyrev}{GEN t, long v = -1}, where \kbd{v} is a variable number. \subsec{Qfb$(a,b,c,\{D=0.\})$}\kbdsidx{Qfb}\label{se:Qfb} Creates the binary quadratic form\sidx{binary quadratic form} $ax^2+bxy+cy^2$. If $b^2-4ac>0$, initialize \idx{Shanks}' distance function to $D$. Negative definite forms are not implemented, use their positive definite counterpart instead. The library syntax is \fun{GEN}{Qfb0}{GEN a, GEN b, GEN c, GEN D = NULL, long prec}. Also available are \fun{GEN}{qfi}{GEN a, GEN b, GEN c} (assumes $b^2-4ac<0$) and \fun{GEN}{qfr}{GEN a, GEN b, GEN c, GEN D} (assumes $b^2-4ac>0$). \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 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 ? Ser(1, 'y, 5) %1 = 1 + O(y^5) ? Ser(x^2,, 5) %2 = x^2 + O(x^7) ? T = polcyclo(100) %3 = x^40 - x^30 + x^20 - x^10 + 1 ? Ser(T, 'x, 11) %4 = 1 - x^10 + O(x^11) @eprog\noindent The function is more or less equivalent with multiplication by $1 + O(v^d)$ in theses cases, only faster. If $s$ is a vector, on the other hand, the coefficients of the vector are understood to be the coefficients of the power series starting from the constant term (as in \tet{Polrev}$(x)$), and the precision $d$ is ignored: in other words, in this case, we convert \typ{VEC} / \typ{COL} to the power series whose significant terms are exactly given by the vector entries. Finally, if $s$ is already a power series in $v$, we return it verbatim, ignoring $d$ again. If $d$ significant terms are desired in the last two cases, convert/truncate to \typ{POL} first. \bprog ? v = [1,2,3]; Ser(v, t, 7) %5 = 1 + 2*t + 3*t^2 + O(t^3) \\ 3 terms: 7 is ignored! ? Ser(Polrev(v,t), t, 7) %6 = 1 + 2*t + 3*t^2 + O(t^7) ? s = 1+x+O(x^2); Ser(s, x, 7) %7 = 1 + x + O(x^2) \\ 2 terms: 7 ignored ? Ser(truncate(s), x, 7) %8 = 1 + x + O(x^7) @eprog\noindent The warning given for \kbd{Pol} also applies here: this is not a substitution function. The library syntax is \fun{GEN}{gtoser}{GEN s, long v = -1, long precdl}, where \kbd{v} is a variable number. \subsec{Set$(\{x=[\,]\})$}\kbdsidx{Set}\label{se:Set} Converts $x$ into a set, i.e.~into a row vector, with strictly increasing entries with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. Standard container types \typ{VEC}, \typ{COL}, \typ{LIST} and \typ{VECSMALL} are converted to the set with corresponding elements. All others are converted to a set with one element. \bprog ? Set([1,2,4,2,1,3]) %1 = [1, 2, 3, 4] ? Set(x) %2 = [x] ? Set(Vecsmall([1,3,2,1,3])) %3 = [1, 2, 3] @eprog The library syntax is \fun{GEN}{gtoset}{GEN x = NULL}. \subsec{Str$(\{x\}*)$}\kbdsidx{Str}\label{se:Str} Converts its argument list into a single character string (type \typ{STR}, the empty string if $x$ is omitted). To recover an ordinary \kbd{GEN} from a string, apply \kbd{eval} to it. The arguments of \kbd{Str} are evaluated in string context, see \secref{se:strings}. \bprog ? x2 = 0; i = 2; Str(x, i) %1 = "x2" ? eval(%) %2 = 0 @eprog\noindent This function is mostly useless in library mode. Use the pair \tet{strtoGEN}/\tet{GENtostr} to convert between \kbd{GEN} and \kbd{char*}. The latter returns a malloced string, which should be freed after usage. %\syn{NO} \subsec{Strchr$(x)$}\kbdsidx{Strchr}\label{se:Strchr} Converts $x$ to a string, translating each integer into a character. \bprog ? Strchr(97) %1 = "a" ? Vecsmall("hello world") %2 = Vecsmall([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]) ? Strchr(%) %3 = "hello world" @eprog The library syntax is \fun{GEN}{Strchr}{GEN x}. \subsec{Strexpand$(\{x\}*)$}\kbdsidx{Strexpand}\label{se:Strexpand} Converts its argument list into a single character string (type \typ{STR}, the empty string if $x$ is omitted). Then perform \idx{environment expansion}, see \secref{se:envir}. This feature can be used to read \idx{environment variable} values. \bprog ? Strexpand("$HOME/doc") %1 = "/home/pari/doc" @eprog The individual arguments are read in string context, see \secref{se:strings}. %\syn{NO} \subsec{Strtex$(\{x\}*)$}\kbdsidx{Strtex}\label{se:Strtex} Translates its arguments to TeX format, and concatenates the results into a single character string (type \typ{STR}, the empty string if $x$ is omitted). The individual arguments are read in string context, see \secref{se:strings}. %\syn{NO} \subsec{Vec$(x, \{n\})$}\kbdsidx{Vec}\label{se:Vec} Transforms the object $x$ into a row vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form (in which case the resulting vector is simply the initial object considered as a row vector), \item a polynomial or a power series. In the case of a polynomial, the coefficients of the vector start with the leading coefficient of the polynomial, while for power series only the significant coefficients are taken into account, but this time by increasing order of degree. In this last case, \kbd{Vec} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively, \item a matrix: return the vector of columns comprising the matrix. \item a character string: return the vector of individual characters. \item an error context (\typ{ERROR}): return the error components, see \tet{iferr}. In the last three cases (matrix, character string, error), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. Variant: \fun{GEN}{gtovec}{GEN x} is also available. The library syntax is \fun{GEN}{gtovec0}{GEN x, long n}. \subsec{Vecrev$(x, \{n\})$}\kbdsidx{Vecrev}\label{se:Vecrev} As $\kbd{Vec}(x, n)$, then reverse the result. In particular In this case, \kbd{Vecrev} is the reciprocal function of \kbd{Polrev}: the coefficients of the vector start with the constant coefficient of the polynomial and the others follow by increasing degree. The library syntax is \fun{GEN}{gtovecrev0}{GEN x, long n}. \fun{GEN}{gtovecrev}{GEN x} is also available. \subsec{Vecsmall$(x, \{n\})$}\kbdsidx{Vecsmall}\label{se:Vecsmall} Transforms the object $x$ into a row vector of type \typ{VECSMALL}. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. This acts as \kbd{Vec}$(x,n)$, but only on a limited set of objects: the result must be representable as a vector of small integers. If $x$ is a character string, a vector of individual characters in ASCII encoding is returned (\tet{Strchr} yields back the character string). The library syntax is \fun{GEN}{gtovecsmall0}{GEN x, long n}. \fun{GEN}{gtovecsmall}{GEN x} is also available. \subsec{binary$(x)$}\kbdsidx{binary}\label{se:binary} Outputs the vector of the binary digits of $|x|$. Here $x$ can be an integer, a real number (in which case the result has two components, one for the integer part, one for the fractional part) or a vector/matrix. The library syntax is \fun{GEN}{binaire}{GEN x}. \subsec{bitand$(x,y)$}\kbdsidx{bitand}\label{se:bitand} Bitwise \tet{and} \sidx{bitwise and}of two integers $x$ and $y$, that is the integer $$\sum_i (x_i~\kbd{and}~y_i) 2^i$$ Negative numbers behave $2$-adically, i.e.~the result is the $2$-adic limit of \kbd{bitand}$(x_n,y_n)$, where $x_n$ and $y_n$ are non-negative integers tending to $x$ and $y$ respectively. (The result is an ordinary integer, possibly negative.) \bprog ? bitand(5, 3) %1 = 1 ? bitand(-5, 3) %2 = 3 ? bitand(-5, -3) %3 = -7 @eprog The library syntax is \fun{GEN}{gbitand}{GEN x, GEN y}. Also available is \fun{GEN}{ibitand}{GEN x, GEN y}, which returns the bitwise \emph{and} of $|x|$ and $|y|$, two integers. \subsec{bitneg$(x,\{n=-1\})$}\kbdsidx{bitneg}\label{se:bitneg} \idx{bitwise negation} of an integer $x$, truncated to $n$ bits, $n\geq 0$, that is the integer $$\sum_{i=0}^{n-1} \kbd{not}(x_i) 2^i.$$ The special case $n=-1$ means no truncation: an infinite sequence of leading $1$ is then represented as a negative number. See \secref{se:bitand} for the behavior for negative arguments. The library syntax is \fun{GEN}{gbitneg}{GEN x, long n}. \subsec{bitnegimply$(x,y)$}\kbdsidx{bitnegimply}\label{se:bitnegimply} Bitwise negated imply of two integers $x$ and $y$ (or \kbd{not} $(x \Rightarrow y)$), that is the integer $$\sum (x_i~\kbd{and not}(y_i)) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. The library syntax is \fun{GEN}{gbitnegimply}{GEN x, GEN y}. Also available is \fun{GEN}{ibitnegimply}{GEN x, GEN y}, which returns the bitwise negated imply of $|x|$ and $|y|$, two integers. \subsec{bitor$(x,y)$}\kbdsidx{bitor}\label{se:bitor} \sidx{bitwise inclusive or}bitwise (inclusive) \tet{or} of two integers $x$ and $y$, that is the integer $$\sum (x_i~\kbd{or}~y_i) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. The library syntax is \fun{GEN}{gbitor}{GEN x, GEN y}. Also available is \fun{GEN}{ibitor}{GEN x, GEN y}, which returns the bitwise \emph{ir} of $|x|$ and $|y|$, two integers. \subsec{bittest$(x,n)$}\kbdsidx{bittest}\label{se:bittest} Outputs the $n^{\text{th}}$ bit of $x$ starting from the right (i.e.~the coefficient of $2^n$ in the binary expansion of $x$). The result is 0 or 1. \bprog ? bittest(7, 3) %1 = 1 \\ the 3rd bit is 1 ? bittest(7, 4) %2 = 0 \\ the 4th bit is 0 @eprog\noindent See \secref{se:bitand} for the behavior at negative arguments. The library syntax is \fun{GEN}{gbittest}{GEN x, long n}. For a \typ{INT} $x$, the variant \fun{long}{bittest}{GEN x, long n} is generally easier to use, and if furthermore $n\ge 0$ the low-level function \fun{ulong}{int_bit}{GEN x, long n} returns \kbd{bittest(abs(x),n)}. \subsec{bitxor$(x,y)$}\kbdsidx{bitxor}\label{se:bitxor} Bitwise (exclusive) \tet{or} \sidx{bitwise exclusive or}of two integers $x$ and $y$, that is the integer $$\sum (x_i~\kbd{xor}~y_i) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. The library syntax is \fun{GEN}{gbitxor}{GEN x, GEN y}. Also available is \fun{GEN}{ibitxor}{GEN x, GEN y}, which returns the bitwise \emph{xor} of $|x|$ and $|y|$, two integers. \subsec{ceil$(x)$}\kbdsidx{ceil}\label{se:ceil} Ceiling of $x$. When $x$ is in $\R$, the result is the smallest integer greater than or equal to $x$. Applied to a rational function, $\kbd{ceil}(x)$ returns the Euclidean quotient of the numerator by the denominator. The library syntax is \fun{GEN}{gceil}{GEN x}. \subsec{centerlift$(x,\{v\})$}\kbdsidx{centerlift}\label{se:centerlift} Same as \tet{lift}, except that \typ{INTMOD} and \typ{PADIC} components are lifted using centered residues: \item for a \typ{INTMOD} $x\in \Z/n\Z$, the lift $y$ is such that $-n/20$), the result is undefined and an error occurs if $e$ was not given. \misctitle{Important remark} Contrary to the other truncation functions, this function operates on every coefficient at every level of a PARI object. For example $$\text{truncate}\left(\dfrac{2.4*X^2-1.7}{X}\right)=2.4*X,$$ whereas $$\text{round}\left(\dfrac{2.4*X^2-1.7}{X}\right)=\dfrac{2*X^2-2}{X}.$$ An important use of \kbd{round} is to get exact results after an approximate computation, when theory tells you that the coefficients must be integers. The library syntax is \fun{GEN}{round0}{GEN x, GEN *e = NULL}. Also available are \fun{GEN}{grndtoi}{GEN x, long *e} and \fun{GEN}{ground}{GEN x}. \subsec{simplify$(x)$}\kbdsidx{simplify}\label{se:simplify} This function simplifies $x$ as much as it can. Specifically, a complex or quadratic number whose imaginary part is the integer 0 (i.e.~not \kbd{Mod(0,2)} or \kbd{0.E-28}) is converted to its real part, and a polynomial of degree $0$ is converted to its constant term. Simplifications occur recursively. This function is especially useful before using arithmetic functions, which expect integer arguments: \bprog ? x = 2 + y - y %1 = 2 ? isprime(x) *** at top-level: isprime(x) *** ^---------- *** isprime: not an integer argument in an arithmetic function ? type(x) %2 = "t_POL" ? type(simplify(x)) %3 = "t_INT" @eprog Note that GP results are simplified as above before they are stored in the history. (Unless you disable automatic simplification with \b{y}, that is.) In particular \bprog ? type(%1) %4 = "t_INT" @eprog The library syntax is \fun{GEN}{simplify}{GEN x}. \subsec{sizebyte$(x)$}\kbdsidx{sizebyte}\label{se:sizebyte} Outputs the total number of bytes occupied by the tree representing the PARI object $x$. The library syntax is \fun{long}{gsizebyte}{GEN x}. 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. The library syntax is \fun{long}{sizedigit}{GEN x}. \subsec{truncate$(x,\{\&e\})$}\kbdsidx{truncate}\label{se:truncate} Truncates $x$ and sets $e$ to the number of error bits. When $x$ is in $\R$, this means that the part after the decimal point is chopped away, $e$ is the binary exponent of the difference between the original and the truncated value (the ``fractional part''). If the exponent of $x$ is too large compared to its precision (i.e.~$e>0$), the result is undefined and an error occurs if $e$ was not given. The function applies componentwise on vector / matrices; $e$ is then the maximal number of error bits. If $x$ is a rational function, the result is the ``integer part'' (Euclidean quotient of numerator by denominator) and $e$ is not set. Note a very special use of \kbd{truncate}: when applied to a power series, it transforms it into a polynomial or a rational function with denominator a power of $X$, by chopping away the $O(X^k)$. Similarly, when applied to a $p$-adic number, it transforms it into an integer or a rational number by chopping away the $O(p^k)$. The library syntax is \fun{GEN}{trunc0}{GEN x, GEN *e = NULL}. The following functions are also available: \fun{GEN}{gtrunc}{GEN x} and \fun{GEN}{gcvtoi}{GEN x, long *e}. \subsec{valuation$(x,p)$}\kbdsidx{valuation}\label{se:valuation} Computes the highest exponent of $p$ dividing $x$. If $p$ is of type integer, $x$ must be an integer, an intmod whose modulus is divisible by $p$, a fraction, a $q$-adic number with $q=p$, or a polynomial or power series in which case the valuation is the minimum of the valuation of the coefficients. If $p$ is of type polynomial, $x$ must be of type polynomial or rational 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 $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}. \subsec{variable$(\{x\})$}\kbdsidx{variable}\label{se:variable} Gives the main variable of the object $x$ (the variable with the highest priority used in $x$), and $p$ if $x$ is a $p$-adic number. Return $0$ if $x$ has no variable associated to it. \bprog ? variable(x^2 + y) %1 = x ? variable(1 + O(5^2)) %2 = 5 ? variable([x,y,z,t]) %3 = x ? variable(1) %4 = 0 @eprog\noindent The construction \bprog if (!variable(x),...) @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.) The library syntax is \fun{GEN}{gpolvar}{GEN x = NULL}. However, in library mode, this function should not be used for $x$ non-\kbd{NULL}, since \tet{gvar} is more appropriate. Instead, for $x$ a $p$-adic (type \typ{PADIC}), $p$ is $gel(x,2)$; otherwise, use \fun{long}{gvar}{GEN x} which returns the variable number of $x$ if 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. %SECTION: conversions \section{Transcendental functions}\label{se:trans} Since the values of transcendental functions cannot be exactly represented, these functions will always return an inexact object: a real number, a complex number, a $p$-adic number or a power series. All these objects have a certain finite precision. As a general rule, which of course in some cases may have exceptions, transcendental functions operate in the following way: \item If the argument is either a real number or an inexact complex number (like \kbd{1.0 + I} or \kbd{Pi*I} but not \kbd{2 - 3*I}), then the computation is done with the precision of the argument. In the example below, we see that changing the precision to $50$ digits does not matter, because $x$ only had a precision of $19$ digits. \bprog ? \p 15 realprecision = 19 significant digits (15 digits displayed) ? x = Pi/4 %1 = 0.785398163397448 ? \p 50 realprecision = 57 significant digits (50 digits displayed) ? sin(x) %2 = 0.7071067811865475244 @eprog Note that even if the argument is real, the result may be complex (e.g.~$\text{acos}(2.0)$ or $\text{acosh}(0.0)$). See each individual function help for the definition of the branch cuts and choice of principal value. \item If the argument is either an integer, a rational, an exact complex number or a quadratic number, it is first converted to a real or complex number using the current \idx{precision} held in the default \tet{realprecision}. This precision (the number of decimal digits) can be changed using \b{p} or \kbd{default(realprecision,...)}). After this conversion, the computation proceeds as above for real or complex arguments. In library mode, the \kbd{realprecision} does not matter; instead the precision is taken from the \kbd{prec} parameter which every transcendental function has. As in \kbd{gp}, this \kbd{prec} is not used when the argument to a function is already inexact. Note that the argument \var{prec} stands for the length in words of a real number, including codewords. Hence we must have $\var{prec} \geq 3$. Some accuracies attainable on 32-bit machines cannot be attained on 64-bit machines for parity reasons. For example the default \kbd{gp} accuracy is 28 decimal digits on 32-bit machines, corresponding to \var{prec} having the value 5, but this cannot be attained on 64-bit machines. \item If the argument is a polmod (representing an algebraic number), then the function is evaluated for every possible complex embedding of that algebraic number. A column vector of results is returned, with one component for each complex embedding. Therefore, the number of components equals the degree of the \typ{POLMOD} modulus. \item If the argument is an intmod or a $p$-adic, at present only a few functions like \kbd{sqrt} (square root), \kbd{sqr} (square), \kbd{log}, \kbd{exp}, powering, \kbd{teichmuller} (Teichm\"uller character) and \kbd{agm} (arithmetic-geometric mean) are implemented. Note that in the case of a $2$-adic number, $\kbd{sqr}(x)$ may not be identical to $x*x$: for example if $x = 1+O(2^5)$ and $y = 1+O(2^5)$ then $x*y = 1+O(2^5)$ while $\kbd{sqr}(x) = 1+O(2^6)$. Here, $x * x$ yields the same result as $\kbd{sqr}(x)$ since the two operands are known to be \emph{identical}. The same statement holds true for $p$-adics raised to the power $n$, where $v_p(n) > 0$. \misctitle{Remark} If we wanted to be strictly consistent with the PARI philosophy, we should have $x*y = (4 \mod 8)$ and $\kbd{sqr}(x) = (4 \mod 32)$ when both $x$ and $y$ are congruent to $2$ modulo $4$. However, since intmod is an exact object, PARI assumes that the modulus must not change, and the result is hence $(0\, \mod\, 4)$ in both cases. On the other hand, $p$-adics are not exact objects, hence are treated differently. \item If the argument is a polynomial, a power series or a rational function, it is, if necessary, first converted to a power series using the current series precision, held in the default \tet{seriesprecision}. This precision (the number of significant terms) can be changed using \b{ps} or \kbd{default(seriesprecision,...)}. Then the Taylor series expansion of the function around $X=0$ (where $X$ is the main variable) is computed to a number of terms depending on the number of terms of the argument and the function being computed. Under \kbd{gp} this again is transparent to the user. When programming in library mode, however, it is \emph{strongly} advised to perform an explicit conversion to a power series first, as in \kbd{x = gtoser(x, seriesprec)}, where the number of significant terms \kbd{seriesprec} can be specified explicitly. If you do not do this, a global variable \kbd{precdl} is used instead, to convert polynomials and rational functions to a power series with a reasonable number of terms; tampering with the value of this global variable is \emph{deprecated} and strongly discouraged. \item If the argument is a vector or a matrix, the result is the componentwise evaluation of the function. In particular, transcendental functions on square matrices, which are not implemented in the present version \vers, will have a different name if they are implemented some day. \subseckbd{\pow} If $y$ is not of type integer, \kbd{x\pow y} has the same effect as \kbd{exp(y*log(x))}. It can be applied to $p$-adic numbers as well as to the more usual types.\sidx{powering} The library syntax is \fun{GEN}{gpow}{GEN x, GEN n, long prec} for $x\hbox{\kbd{\pow}}n$. \subsec{Catalan}\kbdsidx{Catalan}\label{se:Catalan} Catalan's constant $G = \sum_{n>=0}\dfrac{(-1)^n}{(2n+1)^2}=0.91596\cdots$. Note that \kbd{Catalan} is one of the few reserved names which cannot be used for user variables. The library syntax is \fun{GEN}{mpcatalan}{long prec}. \subsec{Euler}\kbdsidx{Euler}\label{se:Euler} Euler's constant $\gamma=0.57721\cdots$. Note that \kbd{Euler} is one of the few reserved names which cannot be used for user variables. The library syntax is \fun{GEN}{mpeuler}{long prec}. \subsec{I}\kbdsidx{I}\label{se:I} The complex number $\sqrt{-1}$. The library syntax is \fun{GEN}{gen_I}{}. \subsec{Pi}\kbdsidx{Pi}\label{se:Pi} The constant $\pi$ ($3.14159\cdots$). Note that \kbd{Pi} is one of the few reserved names which cannot be used for user variables. The library syntax is \fun{GEN}{mppi}{long prec}. \subsec{abs$(x)$}\kbdsidx{abs}\label{se:abs} Absolute value of $x$ (modulus if $x$ is complex). Rational functions are not allowed. Contrary to most transcendental functions, an exact argument is \emph{not} converted to a real number before applying \kbd{abs} and an exact result is returned if possible. \bprog ? abs(-1) %1 = 1 ? abs(3/7 + 4/7*I) %2 = 5/7 ? abs(1 + I) %3 = 1.414213562373095048801688724 @eprog\noindent If $x$ is a polynomial, returns $-x$ if the leading coefficient is real and negative else returns $x$. For a power series, the constant coefficient is considered instead. The library syntax is \fun{GEN}{gabs}{GEN x, long prec}. \subsec{acos$(x)$}\kbdsidx{acos}\label{se:acos} Principal branch of $\text{cos}^{-1}(x) = -i \log (x + i\sqrt{1-x^2})$. In particular, $\text{Re(acos}(x))\in [0,\pi]$ and if $x\in \R$ and $|x|>1$, then $\text{acos}(x)$ is complex. The branch cut is in two pieces: $]-\infty,-1]$ , continuous with quadrant II, and $[1,+\infty[$, continuous with quadrant IV. We have $\text{acos}(x) = \pi/2 - \text{asin}(x)$ for all $x$. The library syntax is \fun{GEN}{gacos}{GEN x, long prec}. \subsec{acosh$(x)$}\kbdsidx{acosh}\label{se:acosh} Principal branch of $\text{cosh}^{-1}(x) = 2 \log(\sqrt{(x+1)/2} + \sqrt{(x-1)/2})$. In particular, $\text{Re}(\text{acosh}(x))\geq 0$ and $\text{In}(\text{acosh}(x))\in ]-\pi,\pi]0$; if $x\in \R$ and $x<1$, then $\text{acosh}(x)$ is complex. The library syntax is \fun{GEN}{gacosh}{GEN x, long prec}. \subsec{agm$(x,y)$}\kbdsidx{agm}\label{se:agm} Arithmetic-geometric mean of $x$ and $y$. In the case of complex or negative numbers, the optimal AGM is returned (the largest in absolute value over all choices of the signs of the square roots). $p$-adic or power series arguments are also allowed. Note that a $p$-adic agm exists only if $x/y$ is congruent to 1 modulo $p$ (modulo 16 for $p=2$). $x$ and $y$ cannot both be vectors or matrices. The library syntax is \fun{GEN}{agm}{GEN x, GEN y, long prec}. \subsec{arg$(x)$}\kbdsidx{arg}\label{se:arg} Argument of the complex number $x$, such that $-\pi<\text{arg}(x)\le\pi$. The library syntax is \fun{GEN}{garg}{GEN x, long prec}. \subsec{asin$(x)$}\kbdsidx{asin}\label{se:asin} Principal branch of $\text{sin}^{-1}(x) = -i \log(ix + \sqrt{1 - x^2})$. In particular, $\text{Re(asin}(x))\in [-\pi/2,\pi/2]$ and if $x\in \R$ and $|x|>1$ then $\text{asin}(x)$ is complex. The branch cut is in two pieces: $]-\infty,-1]$, continuous with quadrant II, and $[1,+\infty[$ continuous with quadrant IV. The function satisfies $i \text{asin}(x) = \text{asinh}(ix)$. The library syntax is \fun{GEN}{gasin}{GEN x, long prec}. \subsec{asinh$(x)$}\kbdsidx{asinh}\label{se:asinh} Principal branch of $\text{sinh}^{-1}(x) = \log(x + \sqrt{1+x^2})$. In particular $\text{Im(asinh}(x))\in [-\pi/2,\pi/2]$. The branch cut is in two pieces: [-i oo ,-i], continuous with quadrant III and [i,+i oo [ continuous with quadrant I. The library syntax is \fun{GEN}{gasinh}{GEN x, long prec}. \subsec{atan$(x)$}\kbdsidx{atan}\label{se:atan} Principal branch of $\text{tan}^{-1}(x) = \log ((1+ix)/(1-ix)) / 2i$. In particular the real part of $\text{atan}(x))$ belongs to $]-\pi/2,\pi/2[$. The branch cut is in two pieces: $]-i\infty,-i[$, continuous with quadrant IV, and $]i,+i \infty[$ continuous with quadrant II. The function satisfies $i \text{atan}(x) = -i\text{atanh}(ix)$ for all $x\neq \pm i$. The library syntax is \fun{GEN}{gatan}{GEN x, long prec}. \subsec{atanh$(x)$}\kbdsidx{atanh}\label{se:atanh} Principal branch of $\text{tanh}^{-1}(x) = log ((1+x)/(1-x)) / 2$. In particular the imaginary part of $\text{atanh}(x)$ belongs to $[-\pi/2,\pi/2]$; if $x\in \R$ and $|x|>1$ then $\text{atanh}(x)$ is complex. The library syntax is \fun{GEN}{gatanh}{GEN x, long prec}. \subsec{bernfrac$(x)$}\kbdsidx{bernfrac}\label{se:bernfrac} Bernoulli number\sidx{Bernoulli numbers} $B_x$, where $B_0=1$, $B_1=-1/2$, $B_2=1/6$,\dots, expressed as a rational number. The argument $x$ should be of type integer. The library syntax is \fun{GEN}{bernfrac}{long x}. \subsec{bernpol$(n, \{v = 'x\})$}\kbdsidx{bernpol}\label{se:bernpol} \idx{Bernoulli polynomial} $B_n$ in variable $v$. \bprog ? bernpol(1) %1 = x - 1/2 ? bernpol(3) %2 = x^3 - 3/2*x^2 + 1/2*x @eprog The library syntax is \fun{GEN}{bernpol}{long n, long v = -1}, where \kbd{v } is a variable number. \subsec{bernreal$(x)$}\kbdsidx{bernreal}\label{se:bernreal} Bernoulli number\sidx{Bernoulli numbers} $B_x$, as \kbd{bernfrac}, but $B_x$ is returned as a real number (with the current precision). The library syntax is \fun{GEN}{bernreal}{long x, long prec}. \subsec{bernvec$(x)$}\kbdsidx{bernvec}\label{se:bernvec} Creates a vector containing, as rational numbers, the \idx{Bernoulli numbers} $B_0$, $B_2$,\dots, $B_{2x}$. This routine is obsolete. Use \kbd{bernfrac} instead each time you need a Bernoulli number in exact form. \misctitle{Note} This routine is implemented using repeated independent calls to \kbd{bernfrac}, which is faster than the standard recursion in exact arithmetic. It is only kept for backward compatibility: it is not faster than individual calls to \kbd{bernfrac}, its output uses a lot of memory space, and coping with the index shift is awkward. The library syntax is \fun{GEN}{bernvec}{long x}. \subsec{besselh1$(\var{nu},x)$}\kbdsidx{besselh1}\label{se:besselh1} $H^1$-Bessel function of index \var{nu} and argument $x$. The library syntax is \fun{GEN}{hbessel1}{GEN nu, GEN x, long prec}. \subsec{besselh2$(\var{nu},x)$}\kbdsidx{besselh2}\label{se:besselh2} $H^2$-Bessel function of index \var{nu} and argument $x$. The library syntax is \fun{GEN}{hbessel2}{GEN nu, GEN x, long prec}. \subsec{besseli$(\var{nu},x)$}\kbdsidx{besseli}\label{se:besseli} $I$-Bessel function of index \var{nu} and argument $x$. If $x$ converts to a power series, the initial factor $(x/2)^\nu/\Gamma(\nu+1)$ is omitted (since it cannot be represented in PARI when $\nu$ is not integral). The library syntax is \fun{GEN}{ibessel}{GEN nu, GEN x, long prec}. \subsec{besselj$(\var{nu},x)$}\kbdsidx{besselj}\label{se:besselj} $J$-Bessel function of index \var{nu} and argument $x$. If $x$ converts to a power series, the initial factor $(x/2)^\nu/\Gamma(\nu+1)$ is omitted (since it cannot be represented in PARI when $\nu$ is not integral). The library syntax is \fun{GEN}{jbessel}{GEN nu, GEN x, long prec}. \subsec{besseljh$(n,x)$}\kbdsidx{besseljh}\label{se:besseljh} $J$-Bessel function of half integral index. More precisely, $\kbd{besseljh}(n,x)$ computes $J_{n+1/2}(x)$ where $n$ must be of type integer, and $x$ is any element of $\C$. In the present version \vers, this function is not very accurate when $x$ is small. The library syntax is \fun{GEN}{jbesselh}{GEN n, GEN x, long prec}. \subsec{besselk$(\var{nu},x)$}\kbdsidx{besselk}\label{se:besselk} $K$-Bessel function of index \var{nu} and argument $x$. The library syntax is \fun{GEN}{kbessel}{GEN nu, GEN x, long prec}. \subsec{besseln$(\var{nu},x)$}\kbdsidx{besseln}\label{se:besseln} $N$-Bessel function of index \var{nu} and argument $x$. The library syntax is \fun{GEN}{nbessel}{GEN nu, GEN x, long prec}. \subsec{cos$(x)$}\kbdsidx{cos}\label{se:cos} Cosine of $x$. The library syntax is \fun{GEN}{gcos}{GEN x, long prec}. \subsec{cosh$(x)$}\kbdsidx{cosh}\label{se:cosh} Hyperbolic cosine of $x$. The library syntax is \fun{GEN}{gcosh}{GEN x, long prec}. \subsec{cotan$(x)$}\kbdsidx{cotan}\label{se:cotan} Cotangent of $x$. The library syntax is \fun{GEN}{gcotan}{GEN x, long prec}. \subsec{dilog$(x)$}\kbdsidx{dilog}\label{se:dilog} Principal branch of the dilogarithm of $x$, i.e.~analytic continuation of the power series $\log_2(x)=\sum_{n\ge1}x^n/n^2$. The library syntax is \fun{GEN}{dilog}{GEN x, long prec}. \subsec{eint1$(x,\{n\})$}\kbdsidx{eint1}\label{se:eint1} Exponential integral $\int_x^\infty \dfrac{e^{-t}}{t}\,dt = \kbd{incgam}(0, x)$, where the latter expression extends the function definition from real $x > 0$ to all complex $x \neq 0$. If $n$ is present, we must have $x > 0$; the function returns the $n$-dimensional vector $[\kbd{eint1}(x),\dots,\kbd{eint1}(nx)]$. Contrary to other transcendental functions, and to the default case ($n$ omitted), the values are correct up to a bounded \emph{absolute}, rather than relative, error $10^-n$, where $n$ is \kbd{precision}$(x)$ if $x$ is a \typ{REAL} and defaults to \kbd{realprecision} otherwise. (In the most important application, to the computation of $L$-functions via approximate functional equations, those values appear as weights in long sums and small individual relative errors are less useful than controlling the absolute error.) This is faster than repeatedly calling \kbd{eint1($i$ * x)}, but less precise. The library syntax is \fun{GEN}{veceint1}{GEN x, GEN n = NULL, long prec}. Also available is \fun{GEN}{eint1}{GEN x, long prec}. \subsec{erfc$(x)$}\kbdsidx{erfc}\label{se:erfc} Complementary error function, analytic continuation of $(2/\sqrt\pi)\int_x^\infty e^{-t^2}\,dt = \kbd{incgam}(1/2,x^2)/\sqrt\pi$, where the latter expression extends the function definition from real $x$ to all complex $x \neq 0$. The library syntax is \fun{GEN}{gerfc}{GEN x, long prec}. \subsec{eta$(z,\{\fl=0\})$}\kbdsidx{eta}\label{se:eta} Variants of \idx{Dedekind}'s $\eta$ function. If $\fl = 0$, return $\prod_{n=1}^\infty(1-q^n)$, where $q$ depends on $x$ in the following way: \item $q = e^{2i\pi x}$ if $x$ is a \emph{complex number} (which must then have positive imaginary part); notice that the factor $q^{1/24}$ is missing! \item $q = x$ if $x$ is a \typ{PADIC}, or can be converted to a \emph{power series} (which must then have positive valuation). If $\fl$ is non-zero, $x$ is converted to a complex number and we return the true $\eta$ function, $q^{1/24}\prod_{n=1}^\infty(1-q^n)$, where $q = e^{2i\pi x}$. The library syntax is \fun{GEN}{eta0}{GEN z, long flag, long prec}. Also available is \fun{GEN}{trueeta}{GEN x, long prec} ($\fl=1$). \subsec{exp$(x)$}\kbdsidx{exp}\label{se:exp} Exponential of $x$. $p$-adic arguments with positive valuation are accepted. The library syntax is \fun{GEN}{gexp}{GEN x, long prec}. For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_exp}{GEN x} is also available. \subsec{expm1$(x)$}\kbdsidx{expm1}\label{se:expm1} Return $\exp(x)-1$, computed in a way that is also accurate when the real part of $x$ is near $0$. Only accept real or complex arguments. A naive direct computation would suffer from catastrophic cancellation; PARI's direct computation of $\exp(x)$ alleviates this well known problem at the expense of computing $\exp(x)$ to a higher accuracy when $x$ is small. Using \kbd{expm1} is recommended instead: \bprog ? default(realprecision, 10000); x = 1e-100; ? a = expm1(x); time = 4 ms. ? b = exp(x)-1; time = 28 ms. ? default(realprecision, 10040); x = 1e-100; ? c = expm1(x); \\ reference point ? abs(a-c)/c \\ relative error in expm1(x) %7 = 0.E-10017 ? abs(b-c)/c \\ relative error in exp(x)-1 %8 = 1.7907031188259675794 E-9919 @eprog\noindent As the example above shows, when $x$ is near $0$, \kbd{expm1} is both faster and more accurate than \kbd{exp(x)-1}. The library syntax is \fun{GEN}{gexpm1}{GEN x, long prec}. \subsec{gamma$(s)$}\kbdsidx{gamma}\label{se:gamma} For $s$ a complex number, evaluates Euler's gamma function \sidx{gamma-function} $$\Gamma(s)=\int_0^\infty t^{s-1}\exp(-t)\,dt.$$ Error if $s$ is a non-positive integer, where $\Gamma$ has a pole. For $s$ a \typ{PADIC}, evaluates the Morita gamma function at $s$, that is the unique continuous $p$-adic function on the $p$-adic integers extending $\Gamma_p(k)=(-1)^k \prod_{j 0$. The library syntax is \fun{GEN}{glambertW}{GEN y, long prec}. \subsec{lngamma$(x)$}\kbdsidx{lngamma}\label{se:lngamma} Principal branch of the logarithm of the gamma function of $x$. This function is analytic on the complex plane with non-positive integers removed, and can have much larger arguments than \kbd{gamma} itself. For $x$ a power series such that $x(0)$ is not a pole of \kbd{gamma}, compute the Taylor expansion. (PARI only knows about regular power series and can't include logarithmic terms.) \bprog ? lngamma(1+x+O(x^2)) %1 = -0.57721566490153286060651209008240243104*x + O(x^2) ? lngamma(x+O(x^2)) *** at top-level: lngamma(x+O(x^2)) *** ^----------------- *** lngamma: domain error in lngamma: valuation != 0 ? lngamma(-1+x+O(x^2)) *** lngamma: Warning: normalizing a series with 0 leading term. *** at top-level: lngamma(-1+x+O(x^2)) *** ^-------------------- *** lngamma: domain error in intformal: residue(series, pole) != 0 @eprog The library syntax is \fun{GEN}{glngamma}{GEN x, long prec}. \subsec{log$(x)$}\kbdsidx{log}\label{se:log} Principal branch of the natural logarithm of $x \in \C^*$, i.e.~such that $\text{Im(log}(x))\in{} ]-\pi,\pi]$. The branch cut lies along the negative real axis, continuous with quadrant 2, i.e.~such that $\lim_{b\to 0^+} \log (a+bi) = \log a$ for $a \in\R^*$. The result is complex (with imaginary part equal to $\pi$) if $x\in \R$ and $x < 0$. In general, the algorithm uses the formula $$\log(x) \approx {\pi\over 2\text{agm}(1, 4/s)} - m \log 2, $$ if $s = x 2^m$ is large enough. (The result is exact to $B$ bits provided $s > 2^{B/2}$.) At low accuracies, the series expansion near $1$ is used. $p$-adic arguments are also accepted for $x$, with the convention that $\log(p)=0$. Hence in particular $\exp(\log(x))/x$ is not in general equal to 1 but to a $(p-1)$-th root of unity (or $\pm1$ if $p=2$) times a power of $p$. The library syntax is \fun{GEN}{glog}{GEN x, long prec}. For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_log}{GEN x} is also available. \subsec{polylog$(m,x,\{\fl=0\})$}\kbdsidx{polylog}\label{se:polylog} One of the different polylogarithms, depending on \fl: If $\fl=0$ or is omitted: $m^\text{th}$ polylogarithm of $x$, i.e.~analytic continuation of the power series $\text{Li}_m(x)=\sum_{n\ge1}x^n/n^m$ ($x < 1$). Uses the functional equation linking the values at $x$ and $1/x$ to restrict to the case $|x|\leq 1$, then the power series when $|x|^2\le1/2$, and the power series expansion in $\log(x)$ otherwise. Using $\fl$, computes a modified $m^\text{th}$ polylogarithm of $x$. We use Zagier's notations; let $\Re_m$ denote $\Re$ or $\Im$ depending on whether $m$ is odd or even: If $\fl=1$: compute $\tilde D_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1} \dfrac{(-\log|x|)^k}{k!}\text{Li}_{m-k}(x) +\dfrac{(-\log|x|)^{m-1}}{m!}\log|1-x|\right).$$ If $\fl=2$: compute $D_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1}\dfrac{(-\log|x|)^k}{k!}\text{Li}_{m-k}(x) -\dfrac{1}{2}\dfrac{(-\log|x|)^m}{m!}\right).$$ If $\fl=3$: compute $P_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1}\dfrac{2^kB_k}{k!}(\log|x|)^k\text{Li}_{m-k}(x) -\dfrac{2^{m-1}B_m}{m!}(\log|x|)^m\right).$$ These three functions satisfy the functional equation $f_m(1/x) = (-1)^{m-1}f_m(x)$. The library syntax is \fun{GEN}{polylog0}{long m, GEN x, long flag, long prec}. Also available is \fun{GEN}{gpolylog}{long m, GEN x, long prec} (\fl = 0). \subsec{psi$(x)$}\kbdsidx{psi}\label{se:psi} The $\psi$-function of $x$, i.e.~the logarithmic derivative $\Gamma'(x)/\Gamma(x)$. The library syntax is \fun{GEN}{gpsi}{GEN x, long prec}. \subsec{sin$(x)$}\kbdsidx{sin}\label{se:sin} Sine of $x$. The library syntax is \fun{GEN}{gsin}{GEN x, long prec}. \subsec{sinh$(x)$}\kbdsidx{sinh}\label{se:sinh} Hyperbolic sine of $x$. The library syntax is \fun{GEN}{gsinh}{GEN x, long prec}. \subsec{sqr$(x)$}\kbdsidx{sqr}\label{se:sqr} Square of $x$. This operation is not completely straightforward, i.e.~identical to $x * x$, since it can usually be computed more efficiently (roughly one-half of the elementary multiplications can be saved). Also, squaring a $2$-adic number increases its precision. For example, \bprog ? (1 + O(2^4))^2 %1 = 1 + O(2^5) ? (1 + O(2^4)) * (1 + O(2^4)) %2 = 1 + O(2^4) @eprog\noindent Note that this function is also called whenever one multiplies two objects which are known to be \emph{identical}, e.g.~they are the value of the same variable, or we are computing a power. \bprog ? x = (1 + O(2^4)); x * x %3 = 1 + O(2^5) ? (1 + O(2^4))^4 %4 = 1 + O(2^6) @eprog\noindent (note the difference between \kbd{\%2} and \kbd{\%3} above). The library syntax is \fun{GEN}{gsqr}{GEN x}. \subsec{sqrt$(x)$}\kbdsidx{sqrt}\label{se:sqrt} Principal branch of the square root of $x$, defined as $\sqrt{x} = \exp(\log x / 2)$. In particular, we have $\text{Arg}(\text{sqrt}(x))\in{} ]-\pi/2, \pi/2]$, and if $x\in \R$ and $x<0$, then the result is complex with positive imaginary part. Intmod a prime $p$, \typ{PADIC} and \typ{FFELT} are allowed as arguments. In the first 2 cases (\typ{INTMOD}, \typ{PADIC}), the square root (if it exists) which is returned is the one whose first $p$-adic digit is in the interval $[0,p/2]$. For other arguments, the result is undefined. The library syntax is \fun{GEN}{gsqrt}{GEN x, long prec}. For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_sqrt}{GEN x} is also available. \subsec{sqrtn$(x,n,\{\&z\})$}\kbdsidx{sqrtn}\label{se:sqrtn} Principal branch of the $n$th root of $x$, i.e.~such that $\text{Arg}(\text{sqrt}(x))\in{} ]-\pi/n, \pi/n]$. Intmod a prime and $p$-adics are allowed as arguments. If $z$ is present, it is set to a suitable root of unity allowing to recover all the other roots. If it was not possible, z is set to zero. In the case this argument is present and no square root exist, $0$ is returned instead or raising an error. \bprog ? sqrtn(Mod(2,7), 2) %1 = Mod(4, 7) ? sqrtn(Mod(2,7), 2, &z); z %2 = Mod(6, 7) ? sqrtn(Mod(2,7), 3) *** at top-level: sqrtn(Mod(2,7),3) *** ^----------------- *** sqrtn: nth-root does not exist in gsqrtn. ? sqrtn(Mod(2,7), 3, &z) %2 = 0 ? z %3 = 0 @eprog The following script computes all roots in all possible cases: \bprog sqrtnall(x,n)= { my(V,r,z,r2); r = sqrtn(x,n, &z); if (!z, error("Impossible case in sqrtn")); if (type(x) == "t_INTMOD" || type(x)=="t_PADIC", r2 = r*z; n = 1; while (r2!=r, r2*=z;n++)); V = vector(n); V[1] = r; for(i=2, n, V[i] = V[i-1]*z); V } addhelp(sqrtnall,"sqrtnall(x,n):compute the vector of nth-roots of x"); @eprog\noindent The library syntax is \fun{GEN}{gsqrtn}{GEN x, GEN n, GEN *z = NULL, long prec}. If $x$ is a \typ{PADIC}, the function \fun{GEN}{Qp_sqrt}{GEN x, GEN n, GEN *z} is also available. \subsec{tan$(x)$}\kbdsidx{tan}\label{se:tan} Tangent of $x$. The library syntax is \fun{GEN}{gtan}{GEN x, long prec}. \subsec{tanh$(x)$}\kbdsidx{tanh}\label{se:tanh} Hyperbolic tangent of $x$. The library syntax is \fun{GEN}{gtanh}{GEN x, long prec}. \subsec{teichmuller$(x)$}\kbdsidx{teichmuller}\label{se:teichmuller} Teichm\"uller character of the $p$-adic number $x$, i.e. the unique $(p-1)$-th root of unity congruent to $x / p^{v_p(x)}$ modulo $p$. The library syntax is \fun{GEN}{teich}{GEN x}. \subsec{theta$(q,z)$}\kbdsidx{theta}\label{se:theta} Jacobi sine theta-function $$ \theta_1(z, q) = 2q^{1/4} \sum_{n\geq 0} (-1)^n q^{n(n+1)} \sin((2n+1)z).$$ The library syntax is \fun{GEN}{theta}{GEN q, GEN z, long prec}. \subsec{thetanullk$(q,k)$}\kbdsidx{thetanullk}\label{se:thetanullk} $k$-th derivative at $z=0$ of $\kbd{theta}(q,z)$. The library syntax is \fun{GEN}{thetanullk}{GEN q, long k, long prec}. \fun{GEN}{vecthetanullk}{GEN q, long k, long prec} returns the vector of all $\dfrac{d^i\theta}{dz^i}(q,0)$ for all odd $i = 1, 3, \dots, 2k-1$. \fun{GEN}{vecthetanullk_tau}{GEN tau, long k, long prec} returns \kbd{vecthetanullk\_tau} at $q = \exp(2i\pi \kbd{tau})$. \subsec{weber$(x,\{\fl=0\})$}\kbdsidx{weber}\label{se:weber} One of Weber's three $f$ functions. If $\fl=0$, returns $$f(x)=\exp(-i\pi/24)\cdot\eta((x+1)/2)\,/\,\eta(x) \quad\hbox{such that}\quad j=(f^{24}-16)^3/f^{24}\,,$$ where $j$ is the elliptic $j$-invariant (see the function \kbd{ellj}). If $\fl=1$, returns $$f_1(x)=\eta(x/2)\,/\,\eta(x)\quad\hbox{such that}\quad j=(f_1^{24}+16)^3/f_1^{24}\,.$$ Finally, if $\fl=2$, returns $$f_2(x)=\sqrt{2}\eta(2x)\,/\,\eta(x)\quad\hbox{such that}\quad j=(f_2^{24}+16)^3/f_2^{24}.$$ Note the identities $f^8=f_1^8+f_2^8$ and $ff_1f_2=\sqrt2$. The library syntax is \fun{GEN}{weber0}{GEN x, long flag, long prec}. Also available are \fun{GEN}{weberf}{GEN x, long prec}, \fun{GEN}{weberf1}{GEN x, long prec} and \fun{GEN}{weberf2}{GEN x, long prec}. \subsec{zeta$(s)$}\kbdsidx{zeta}\label{se:zeta} For $s$ a complex number, Riemann's zeta function \sidx{Riemann zeta-function} $\zeta(s)=\sum_{n\ge1}n^{-s}$, computed using the \idx{Euler-Maclaurin} summation formula, except when $s$ is of type integer, in which case it is computed using Bernoulli numbers\sidx{Bernoulli numbers} for $s\le0$ or $s>0$ and even, and using modular forms for $s>0$ and odd. For $s$ a $p$-adic number, Kubota-Leopoldt zeta function at $s$, that is the unique continuous $p$-adic function on the $p$-adic integers that interpolates the values of $(1 - p^{-k}) \zeta(k)$ at negative integers $k$ such that $k \equiv 1 \pmod{p-1}$ (resp. $k$ is odd) if $p$ is odd (resp. $p = 2$). The library syntax is \fun{GEN}{gzeta}{GEN s, long prec}. %SECTION: transcendental \section{Arithmetic functions}\label{se:arithmetic} These functions are by definition functions whose natural domain of definition is either $\Z$ (or $\Z_{>0}$). The way these functions are used is completely different from transcendental functions in that there are no automatic type conversions: in general only integers are accepted as arguments. An integer argument $N$ can be given in the following alternate formats: \item \typ{MAT}: its factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: a pair \kbd{[$N$, fa]} giving both the integer and its factorization. This allows to compute different arithmetic functions at a given $N$ while factoring the latter only once. \bprog ? N = 10!; faN = factor(N); ? eulerphi(N) %2 = 829440 ? eulerphi(faN) %3 = 829440 ? eulerphi(S = [N, faN]) %4 = 829440 ? sigma(S) %5 = 15334088 @eprog \subsec{Arithmetic functions and the factoring engine} All arithmetic functions in the narrow sense of the word~--- Euler's totient\sidx{Euler totient function} function, the \idx{Moebius} function, the sums over divisors or powers of divisors etc.--- call, after trial division by small primes, the same versatile factoring machinery described under \kbd{factorint}. It includes \idx{Shanks SQUFOF}, \idx{Pollard Rho}, \idx{ECM} and \idx{MPQS} stages, and has an early exit option for the functions \teb{moebius} and (the integer function underlying) \teb{issquarefree}. This machinery relies on a fairly strong probabilistic primality test, see \kbd{ispseudoprime}, but you may also set \bprog default(factor_proven, 1) @eprog\noindent to ensure that all tentative factorizations are fully proven. This should not slow down PARI too much, unless prime numbers with hundreds of decimal digits occur frequently in your application. \subsec{Orders in finite groups and Discrete Logarithm functions} \label{se:DLfun} The following functions compute the order of an element in a finite group: \kbd{ellorder} (the rational points on an elliptic curve defined over a finite field), \kbd{fforder} (the multiplicative group of a finite field), \kbd{znorder} (the invertible elements in $\Z/n\Z$). The following functions compute discrete logarithms in the same groups (whenever this is meaningful) \kbd{elllog}, \kbd{fflog}, \kbd{znlog}. All such functions allow an optional argument specifying an integer $N$, representing the order of the group. (The \emph{order} functions also allows any non-zero multiple of the order, with a minor loss of efficiency.) That optional argument follows the same format as given above: \item \typ{INT}: the integer $N$, \item \typ{MAT}: the factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: this is the preferred format and provides both the integer $N$ and its factorization in a two-component vector \kbd{[$N$, fa]}. When the group is fixed and many orders or discrete logarithms will be computed, it is much more efficient to initialize this data once and for all and pass it to the relevant functions, as in \bprog ? p = nextprime(10^40); ? v = [p-1, factor(p-1)]; \\ data for discrete log & order computations ? znorder(Mod(2,p), v) %3 = 500000000000000000000000000028 ? g = znprimroot(p); ? znlog(2, g, v) %5 = 543038070904014908801878611374 @eprog \bigskip \subsec{addprimes$(\{x=[\,]\})$}\kbdsidx{addprimes}\label{se:addprimes} Adds the integers contained in the vector $x$ (or the single integer $x$) to a special table of ``user-defined primes'', and returns that table. Whenever \kbd{factor} is subsequently called, it will trial divide by the elements in this table. If $x$ is empty or omitted, just returns the current list of extra primes. The entries in $x$ must be primes: there is no internal check, even if the \tet{factor_proven} default is set. To remove primes from the list use \kbd{removeprimes}. The library syntax is \fun{GEN}{addprimes}{GEN x = NULL}. \subsec{bestappr$(x, \{B\})$}\kbdsidx{bestappr}\label{se:bestappr} Using variants of the extended Euclidean algorithm, returns a rational approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, return the best approximation affordable given the input accuracy; if you are looking for true rational numbers, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a positive real scalar (impose $0 < b \leq B$). \item If $x$ is a \typ{REAL} or a \typ{FRAC}, this function uses continued fractions. \bprog ? bestappr(Pi, 100) %1 = 22/7 ? bestappr(0.1428571428571428571428571429) %2 = 1/7 ? bestappr([Pi, sqrt(2) + 'x], 10^3) %3 = [355/113, x + 1393/985] @eprog By definition, $a/b$ is the best rational approximation to $x$ if $|b x - a| < |v x - u|$ for all integers $(u,v)$ with $0 < v \leq B$. (Which implies that $n/d$ is a convergent of the continued fraction of $x$.) \item If $x$ is a \typ{INTMOD} modulo $N$ or a \typ{PADIC} of precision $N = p^k$, this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational number $a/b$ in coprime integers $|a| < N/2B$ and $b\leq B$ which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it of the order of $\sqrt{N/2}$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? bestappr(Mod(18526731858, 11^10)) %1 = 1/7 ? bestappr(Mod(18526731858, 11^20)) %2 = [] ? bestappr(3 + 5 + 3*5^2 + 5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7)) %2 = -1/3 @eprog\noindent In most concrete uses, $B$ is a prime power and we performed Hensel lifting to obtain $x$. The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, return $[]$. The library syntax is \fun{GEN}{bestappr}{GEN x, GEN B = NULL}. \subsec{bestapprPade$(x, \{B\})$}\kbdsidx{bestapprPade}\label{se:bestapprPade} Using variants of the extended Euclidean algorithm, returns a rational function approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, return the best approximation affordable given the input accuracy; if you are looking for true rational functions, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a non-negative real (impose $0 \leq \text{degree}(b) \leq B$). \item If $x$ is a \typ{RFRAC} or \typ{SER}, this function uses continued fractions. \bprog ? bestapprPade((1-x^11)/(1-x)+O(x^11)) %1 = 1/(-x + 1) ? bestapprPade([1/(1+x+O(x^10)), (x^3-2)/(x^3+1)], 1) %2 = [1/(x + 1), -2] @eprog \item If $x$ is a \typ{POLMOD} modulo $N$ or a \typ{SER} of precision $N = t^k$, this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational function $a/b$ in coprime polynomials, with $\text{degree}(b)\leq B$ which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it of the order of $N/2$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? bestapprPade(Mod(1+x+x^2+x^3+x^4, x^4-2)) %1 = (2*x - 1)/(x - 1) ? % * Mod(1,x^4-2) %2 = Mod(x^3 + x^2 + x + 3, x^4 - 2) ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^9)) %2 = [] ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^10)) %3 = (2*x^4 + x^3 - x - 1)/(-x^5 + x^3 + x^2 - 1) @eprog\noindent The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, return $[]$. The library syntax is \fun{GEN}{bestapprPade}{GEN x, long B}. \subsec{bezout$(x,y)$}\kbdsidx{bezout}\label{se:bezout} Deprecated alias for \kbd{gcdext} The library syntax is \fun{GEN}{gcdext0}{GEN x, GEN y}. \subsec{bigomega$(x)$}\kbdsidx{bigomega}\label{se:bigomega} Number of prime divisors of the integer $|x|$ counted with multiplicity: \bprog ? factor(392) %1 = [2 3] [7 2] ? bigomega(392) %2 = 5; \\ = 3+2 ? omega(392) %3 = 2; \\ without multiplicity @eprog The library syntax is \fun{long}{bigomega}{GEN x}. \subsec{binomial$(x,y)$}\kbdsidx{binomial}\label{se:binomial} \idx{binomial coefficient} $\binom{x}{y}$. Here $y$ must be an integer, but $x$ can be any PARI object. The library syntax is \fun{GEN}{binomial}{GEN x, long y}. The function \fun{GEN}{binomialuu}{ulong n, ulong k} is also available, and so is \fun{GEN}{vecbinome}{long n}, which returns a vector $v$ with $n+1$ components such that $v[k+1] = \kbd{binomial}(n,k)$ for $k$ from $0$ up to $n$. \subsec{chinese$(x,\{y\})$}\kbdsidx{chinese}\label{se:chinese} If $x$ and $y$ are both intmods or both polmods, creates (with the same type) a $z$ in the same residue class as $x$ and in the same residue class as $y$, if it is possible. \bprog ? chinese(Mod(1,2), Mod(2,3)) %1 = Mod(5, 6) ? chinese(Mod(x,x^2-1), Mod(x+1,x^2+1)) %2 = Mod(-1/2*x^2 + x + 1/2, x^4 - 1) @eprog\noindent This function also allows vector and matrix arguments, in which case the operation is recursively applied to each component of the vector or matrix. \bprog ? chinese([Mod(1,2),Mod(1,3)], [Mod(1,5),Mod(2,7)]) %3 = [Mod(1, 10), Mod(16, 21)] @eprog\noindent For polynomial arguments in the same variable, the function is applied to each coefficient; if the polynomials have different degrees, the high degree terms are copied verbatim in the result, as if the missing high degree terms in the polynomial of lowest degree had been \kbd{Mod(0,1)}. Since the latter behavior is usually \emph{not} the desired one, we propose to convert the polynomials to vectors of the same length first: \bprog ? P = x+1; Q = x^2+2*x+1; ? chinese(P*Mod(1,2), Q*Mod(1,3)) %4 = Mod(1, 3)*x^2 + Mod(5, 6)*x + Mod(3, 6) ? chinese(Vec(P,3)*Mod(1,2), Vec(Q,3)*Mod(1,3)) %5 = [Mod(1, 6), Mod(5, 6), Mod(4, 6)] ? Pol(%) %6 = Mod(1, 6)*x^2 + Mod(5, 6)*x + Mod(4, 6) @eprog If $y$ is omitted, and $x$ is a vector, \kbd{chinese} is applied recursively to the components of $x$, yielding a residue belonging to the same class as all components of $x$. Finally $\kbd{chinese}(x,x) = x$ regardless of the type of $x$; this allows vector arguments to contain other data, so long as they are identical in both vectors. The library syntax is \fun{GEN}{chinese}{GEN x, GEN y = NULL}. \fun{GEN}{chinese1}{GEN x} is also available. \subsec{content$(x)$}\kbdsidx{content}\label{se:content} Computes the gcd of all the coefficients of $x$, when this gcd makes sense. This is the natural definition if $x$ is a polynomial (and by extension a power series) or a vector/matrix. This is in general a weaker notion than the \emph{ideal} generated by the coefficients: \bprog ? content(2*x+y) %1 = 1 \\ = gcd(2,y) over Q[y] @eprog If $x$ is a scalar, this simply returns the absolute value of $x$ if $x$ is rational (\typ{INT} or \typ{FRAC}), and either $1$ (inexact input) or $x$ (exact input) otherwise; the result should be identical to \kbd{gcd(x, 0)}. The content of a rational function is the ratio of the contents of the numerator and the denominator. In recursive structures, if a matrix or vector \emph{coefficient} $x$ appears, the gcd is taken not with $x$, but with its content: \bprog ? content([ [2], 4*matid(3) ]) %1 = 2 @eprog The library syntax is \fun{GEN}{content}{GEN x}. \subsec{contfrac$(x,\{b\},\{\var{nmax}\})$}\kbdsidx{contfrac}\label{se:contfrac} Returns the row vector whose components are the partial quotients of the \idx{continued fraction} expansion of $x$. In other words, a result $[a_0,\dots,a_n]$ means that $x \approx a_0+1/(a_1+\dots+1/a_n)$. The output is normalized so that $a_n \neq 1$ (unless we also have $n = 0$). The number of partial quotients $n+1$ is limited by \kbd{nmax}. If \kbd{nmax} is omitted, the expansion stops at the last significant partial quotient. \bprog ? \p19 realprecision = 19 significant digits ? contfrac(Pi) %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2] ? contfrac(Pi,, 3) \\ n = 2 %2 = [3, 7, 15] @eprog\noindent $x$ can also be a rational function or a power series. If a vector $b$ is supplied, the numerators are equal to the coefficients of $b$, instead of all equal to $1$ as above; more precisely, $x \approx (1/b_0)(a_0+b_1/(a_1+\dots+b_n/a_n))$; for a numerical continued fraction ($x$ real), the $a_i$ are integers, as large as possible; if $x$ is a rational function, they are polynomials with $\deg a_i = \deg b_i + 1$. The length of the result is then equal to the length of $b$, unless the next partial quotient cannot be reliably computed, in which case the expansion stops. This happens when a partial remainder is equal to zero (or too small compared to the available significant digits for $x$ a \typ{REAL}). A direct implementation of the numerical continued fraction \kbd{contfrac(x,b)} described above would be \bprog \\ "greedy" generalized continued fraction cf(x, b) = { my( a= vector(#b), t ); x *= b[1]; for (i = 1, #b, a[i] = floor(x); t = x - a[i]; if (!t || i == #b, break); x = b[i+1] / t; ); a; } @eprog\noindent There is some degree of freedom when choosing the $a_i$; the program above can easily be modified to derive variants of the standard algorithm. In the same vein, although no builtin function implements the related \idx{Engel expansion} (a special kind of \idx{Egyptian fraction} decomposition: $x = 1/a_1 + 1/(a_1a_2) + \dots$ ), it can be obtained as follows: \bprog \\ n terms of the Engel expansion of x engel(x, n = 10) = { my( u = x, a = vector(n) ); for (k = 1, n, a[k] = ceil(1/u); u = u*a[k] - 1; if (!u, break); ); a } @eprog \misctitle{Obsolete hack} (don't use this): If $b$ is an integer, \var{nmax} is ignored and the command is understood as \kbd{contfrac($x,, b$)}. The library syntax is \fun{GEN}{contfrac0}{GEN x, GEN b = NULL, long nmax}. Also available are \fun{GEN}{gboundcf}{GEN x, long nmax}, \fun{GEN}{gcf}{GEN x} and \fun{GEN}{gcf2}{GEN b, GEN x}. \subsec{contfracpnqn$(x, \{n=-1\})$}\kbdsidx{contfracpnqn}\label{se:contfracpnqn} When $x$ is a vector or a one-row matrix, $x$ is considered as the list of partial quotients $[a_0,a_1,\dots,a_n]$ of a rational number, and the result is the 2 by 2 matrix $[p_n,p_{n-1};q_n,q_{n-1}]$ in the standard notation of continued fractions, so $p_n/q_n=a_0+1/(a_1+\dots+1/a_n)$. If $x$ is a matrix with two rows $[b_0,b_1,\dots,b_n]$ and $[a_0,a_1,\dots,a_n]$, this is then considered as a generalized continued fraction and we have similarly $p_n/q_n=(1/b_0)(a_0+b_1/(a_1+\dots+b_n/a_n))$. Note that in this case one usually has $b_0=1$. If $n \geq 0$ is present, returns all convergents from $p_0/q_0$ up to $p_n/q_n$. (All convergents if $x$ is too small to compute the $n+1$ requested convergents.) \bprog ? a=contfrac(Pi,20) %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2] ? contfracpnqn(a,3) %2 = [3 22 333 355] [1 7 106 113] ? contfracpnqn(a,7) %3 = [3 22 333 355 103993 104348 208341 312689] [1 7 106 113 33102 33215 66317 99532] @eprog The library syntax is \fun{GEN}{contfracpnqn}{GEN x, long n}. also available is \fun{GEN}{pnqn}{GEN x} for $n = -1$. \subsec{core$(n,\{\fl=0\})$}\kbdsidx{core}\label{se:core} If $n$ is an integer written as $n=df^2$ with $d$ squarefree, returns $d$. If $\fl$ is non-zero, returns the two-element row vector $[d,f]$. By convention, we write $0 = 0 \times 1^2$, so \kbd{core(0, 1)} returns $[0,1]$. The library syntax is \fun{GEN}{core0}{GEN n, long flag}. Also available are \fun{GEN}{core}{GEN n} ($\fl = 0$) and \fun{GEN}{core2}{GEN n} ($\fl = 1$) \subsec{coredisc$(n,\{\fl=0\})$}\kbdsidx{coredisc}\label{se:coredisc} A \emph{fundamental discriminant} is an integer of the form $t\equiv 1 \mod 4$ or $4t \equiv 8,12 \mod 16$, with $t$ squarefree (i.e.~$1$ or the discriminant of a quadratic number field). Given a non-zero integer $n$, this routine returns the (unique) fundamental discriminant $d$ such that $n=df^2$, $f$ a positive rational number. If $\fl$ is non-zero, returns the two-element row vector $[d,f]$. If $n$ is congruent to 0 or 1 modulo 4, $f$ is an integer, and a half-integer otherwise. By convention, \kbd{coredisc(0, 1))} returns $[0,1]$. Note that \tet{quaddisc}$(n)$ returns the same value as \kbd{coredisc}$(n)$, and also works with rational inputs $n\in\Q^*$. The library syntax is \fun{GEN}{coredisc0}{GEN n, long flag}. Also available are \fun{GEN}{coredisc}{GEN n} ($\fl = 0$) and \fun{GEN}{coredisc2}{GEN n} ($\fl = 1$) \subsec{dirdiv$(x,y)$}\kbdsidx{dirdiv}\label{se:dirdiv} $x$ and $y$ being vectors of perhaps different lengths but with $y[1]\neq 0$ considered as \idx{Dirichlet series}, computes the quotient of $x$ by $y$, again as a vector. The library syntax is \fun{GEN}{dirdiv}{GEN x, GEN y}. \subsec{direuler$(p=a,b,\var{expr},\{c\})$}\kbdsidx{direuler}\label{se:direuler} Computes the \idx{Dirichlet series} associated to the \idx{Euler product} of expression \var{expr} as $p$ ranges through the primes from $a$ to $b$. \var{expr} must be a polynomial or rational function in another variable than $p$ (say $X$) and $\var{expr}(X)$ is understood as the local factor $\var{expr}(p^{-s})$. The series is output as a vector of coefficients. If $c$ is present, output only the first $c$ coefficients in the series. The following command computes the \teb{sigma} function, associated to $\zeta(s)\zeta(s-1)$: \bprog ? direuler(p=2, 10, 1/((1-X)*(1-p*X))) %1 = [1, 3, 4, 7, 6, 12, 8, 15, 13, 18] @eprog \synt{direuler}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b} \subsec{dirmul$(x,y)$}\kbdsidx{dirmul}\label{se:dirmul} $x$ and $y$ being vectors of perhaps different lengths representing the \idx{Dirichlet series} $\sum_n x_n n^{-s}$ and $\sum_n y_n n^{-s}$, computes the product of $x$ by $y$, again as a vector. \bprog ? dirmul(vector(10,n,1), vector(10,n,moebius(n))) %1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] @eprog\noindent The product length is the minimum of $\kbd{\#}x\kbd{*}v(y)$ and $\kbd{\#}y\kbd{*}v(x)$, where $v(x)$ is the index of the first non-zero coefficient. \bprog ? dirmul([0,1], [0,1]); %2 = [0, 0, 0, 1] @eprog The library syntax is \fun{GEN}{dirmul}{GEN x, GEN y}. \subsec{divisors$(x)$}\kbdsidx{divisors}\label{se:divisors} Creates a row vector whose components are the divisors of $x$. The factorization of $x$ (as output by \tet{factor}) can be used instead. By definition, these divisors are the products of the irreducible factors of $n$, as produced by \kbd{factor(n)}, raised to appropriate powers (no negative exponent may occur in the factorization). If $n$ is an integer, they are the positive divisors, in increasing order. The library syntax is \fun{GEN}{divisors}{GEN x}. \subsec{eulerphi$(x)$}\kbdsidx{eulerphi}\label{se:eulerphi} Euler's $\phi$ (totient)\sidx{Euler totient function} function of the integer $|x|$, in other words $|(\Z/x\Z)^*|$. \bprog ? eulerphi(40) %1 = 16 @eprog\noindent According to this definition we let $\phi(0) := 2$, since $\Z^* = \{-1,1\}$; this is consistent with \kbd{znstar(0)}: we have \kbd{znstar$(n)$.no = eulerphi(n)} for all $n\in\Z$. The library syntax is \fun{GEN}{eulerphi}{GEN x}. \subsec{factor$(x,\{\var{lim}\})$}\kbdsidx{factor}\label{se:factor} General factorization function, where $x$ is a rational (including integers), a complex number with rational real and imaginary parts, or a rational function (including polynomials). The result is a two-column matrix: the first contains the irreducibles dividing $x$ (rational or Gaussian primes, irreducible polynomials), and the second the exponents. By convention, $0$ is factored as $0^1$. \misctitle{$\Q$ and $\Q(i)$} See \tet{factorint} for more information about the algorithms used. The rational or Gaussian primes are in fact \var{pseudoprimes} (see \kbd{ispseudoprime}), a priori not rigorously proven primes. In fact, any factor which is $\leq 2^{64}$ (whose norm is $\leq 2^{64}$ for an irrational Gaussian prime) is a genuine prime. Use \kbd{isprime} to prove primality of other factors, as in \bprog ? fa = factor(2^2^7 + 1) %1 = [59649589127497217 1] [5704689200685129054721 1] ? isprime( fa[,1] ) %2 = [1, 1]~ \\ both entries are proven primes @eprog\noindent Another possibility is to set the global default \tet{factor_proven}, which will perform a rigorous primality proof for each pseudoprime factor. A \typ{INT} argument \var{lim} can be added, meaning that we look only for prime factors $p < \var{lim}$. The limit \var{lim} must be non-negative. In this case, all but the last factor are proven primes, but the remaining factor may actually be a proven composite! If the remaining factor is less than $\var{lim}^2$, then it is prime. \bprog ? factor(2^2^7 +1, 10^5) %3 = [340282366920938463463374607431768211457 1] @eprog\noindent \misctitle{Deprecated feature} Setting $\var{lim}=0$ is the same as setting it to $\kbd{primelimit} + 1$. Don't use this: it is unwise to rely on global variables when you can specify an explicit argument. \smallskip This routine uses trial division and perfect power tests, and should not be used for huge values of \var{lim} (at most $10^9$, say): \kbd{factorint(, 1 + 8)} will in general be faster. The latter does not guarantee that all small prime factors are found, but it also finds larger factors, and in a much more efficient way. \bprog ? F = (2^2^7 + 1) * 1009 * 100003; factor(F, 10^5) \\ fast, incomplete time = 0 ms. %4 = [1009 1] [34029257539194609161727850866999116450334371 1] ? factor(F, 10^9) \\ very slow time = 6,892 ms. %6 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F, 1+8) \\ much faster, all small primes were found time = 12 ms. %7 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factor(F) \\ complete factorisation time = 112 ms. %8 = [1009 1] [100003 1] [59649589127497217 1] [5704689200685129054721 1] @eprog\noindent Over $\Q$, the prime factors are sorted in increasing order. \misctitle{Rational functions} The polynomials or rational functions to be factored must have scalar coefficients. In particular PARI does not know how to factor \emph{multivariate} polynomials. The following domains are currently supported: $\Q$, $\R$, $\C$, $\Q_p$, finite fields and number fields. See \tet{factormod} and \tet{factorff} for the algorithms used over finite fields, \tet{factornf} for the algorithms over number fields. Over $\Q$, \idx{van Hoeij}'s method is used, which is able to cope with hundreds of modular factors. The routine guesses a sensible ring over which to factor: the smallest ring containing all coefficients, taking into account quotient structures induced by \typ{INTMOD}s and \typ{POLMOD}s (e.g.~if a coefficient in $\Z/n\Z$ is known, all rational numbers encountered are first mapped to $\Z/n\Z$; different moduli will produce an error). Factoring modulo a non-prime number is not supported; to factor in $\Q_p$, use \typ{PADIC} coefficients not \typ{INTMOD} modulo $p^n$. \bprog ? T = x^2+1; ? factor(T); \\ over Q ? factor(T*Mod(1,3)) \\ over F_3 ? factor(T*ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2} ? factor(T*Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again ? factor(T*(1 + O(3^6)) \\ over Q_3, precision 6 ? factor(T*1.) \\ over R, current precision ? factor(T*(1.+0.*I)) \\ over C ? factor(T*Mod(1, y^3-2)) \\ over Q(2^{1/3}) @eprog\noindent In most cases, it is clearer and simpler to call an explicit variant than to rely on the generic \kbd{factor} function and the above detection mechanism: \bprog ? factormod(T, 3) \\ over F_3 ? factorff(T, 3, t^2+t+2)) \\ over F_{3^2} ? factorpadic(T, 3,6) \\ over Q_3, precision 6 ? nffactor(y^3-2, T) \\ over Q(2^{1/3}) ? polroots(T) \\ over C @eprog Note that factorization of polynomials is done up to multiplication by a constant. In particular, the factors of rational polynomials will have integer coefficients, and the content of a polynomial or rational function is discarded and not included in the factorization. If needed, you can always ask for the content explicitly: \bprog ? factor(t^2 + 5/2*t + 1) %1 = [2*t + 1 1] [t + 2 1] ? content(t^2 + 5/2*t + 1) %2 = 1/2 @eprog\noindent The irreducible factors are sorted by increasing degree. See also \tet{nffactor}. The library syntax is \fun{GEN}{gp_factor0}{GEN x, GEN lim = NULL}. This function should only be used by the \kbd{gp} interface. Use directly \fun{GEN}{factor}{GEN x} or \fun{GEN}{boundfact}{GEN x, ulong lim}. The obsolete function \fun{GEN}{factor0}{GEN x, long lim} is kept for backward compatibility. \subsec{factorback$(f,\{e\})$}\kbdsidx{factorback}\label{se:factorback} Gives back the factored object corresponding to a factorization. The integer $1$ corresponds to the empty factorization. If $e$ is present, $e$ and $f$ must be vectors of the same length ($e$ being integral), and the corresponding factorization is the product of the $f[i]^{e[i]}$. If not, and $f$ is vector, it is understood as in the preceding case with $e$ a vector of 1s: we return the product of the $f[i]$. Finally, $f$ can be a regular factorization, as produced with any \kbd{factor} command. A few examples: \bprog ? factor(12) %1 = [2 2] [3 1] ? factorback(%) %2 = 12 ? factorback([2,3], [2,1]) \\ 2^3 * 3^1 %3 = 12 ? factorback([5,2,3]) %4 = 30 @eprog The library syntax is \fun{GEN}{factorback2}{GEN f, GEN e = NULL}. Also available is \fun{GEN}{factorback}{GEN f} (case $e = \kbd{NULL}$). \subsec{factorcantor$(x,p)$}\kbdsidx{factorcantor}\label{se:factorcantor} Factors the polynomial $x$ modulo the prime $p$, using distinct degree plus \idx{Cantor-Zassenhaus}\sidx{Zassenhaus}. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix, the first column being the irreducible polynomials dividing $x$, and the second the exponents. If you want only the \emph{degrees} of the irreducible polynomials (for example for computing an $L$-function), use $\kbd{factormod}(x,p,1)$. Note that the \kbd{factormod} algorithm is usually faster than \kbd{factorcantor}. The library syntax is \fun{GEN}{factcantor}{GEN x, GEN p}. \subsec{factorff$(x,\{p\},\{a\})$}\kbdsidx{factorff}\label{se:factorff} Factors the polynomial $x$ in the field $\F_q$ defined by the irreducible polynomial $a$ over $\F_p$. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix: the first column contains the irreducible factors of $x$, and the second their exponents. If all the coefficients of $x$ are in $\F_p$, a much faster algorithm is applied, using the computation of isomorphisms between finite fields. Either $a$ or $p$ can omitted (in which case both are ignored) if x has \typ{FFELT} coefficients; the function then becomes identical to \kbd{factor}: \bprog ? factorff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25 %1 = [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x + Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1] [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x + Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1] ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT ? factorff(x^2 + 1) \\ not enough information to determine the base field *** at top-level: factorff(x^2+1) *** ^--------------- *** factorff: incorrect type in factorff. ? factorff(x^2 + t^0) \\ make sure a coeff. is a t_FFELT %3 = [x + 2 1] [x + 3 1] ? factorff(x^2 + t + 1) %11 = [x + (2*t + 1) 1] [x + (3*t + 4) 1] @eprog\noindent Notice that the second syntax is easier to use and much more readable. The library syntax is \fun{GEN}{factorff}{GEN x, GEN p = NULL, GEN a = NULL}. \subsec{factorial$(x)$}\kbdsidx{factorial}\label{se:factorial} Factorial of $x$. The expression $x!$ gives a result which is an integer, while $\kbd{factorial}(x)$ gives a real number. The library syntax is \fun{GEN}{mpfactr}{long x, long prec}. \fun{GEN}{mpfact}{long x} returns $x!$ as a \typ{INT}. \subsec{factorint$(x,\{\fl=0\})$}\kbdsidx{factorint}\label{se:factorint} Factors the integer $n$ into a product of pseudoprimes (see \kbd{ispseudoprime}), using a combination of the \idx{Shanks SQUFOF} and \idx{Pollard Rho} method (with modifications due to Brent), \idx{Lenstra}'s \idx{ECM} (with modifications by Montgomery), and \idx{MPQS} (the latter adapted from the \idx{LiDIA} code with the kind permission of the LiDIA maintainers), as well as a search for pure powers. The output is a two-column matrix as for \kbd{factor}: the first column contains the ``prime'' divisors of $n$, the second one contains the (positive) exponents. By convention $0$ is factored as $0^1$, and $1$ as the empty factorization; also the divisors are by default not proven primes is they are larger than $2^{64}$, they only failed the BPSW compositeness test (see \tet{ispseudoprime}). Use \kbd{isprime} on the result if you want to guarantee primality or set the \tet{factor_proven} default to $1$. Entries of the private prime tables (see \tet{addprimes}) are also included as is. This gives direct access to the integer factoring engine called by most arithmetical functions. \fl\ is optional; its binary digits mean 1: avoid MPQS, 2: skip first stage ECM (we may still fall back to it later), 4: avoid Rho and SQUFOF, 8: don't run final ECM (as a result, a huge composite may be declared to be prime). Note that a (strong) probabilistic primality test is used; thus composites might not be detected, although no example is known. You are invited to play with the flag settings and watch the internals at work by using \kbd{gp}'s \tet{debug} default parameter (level 3 shows just the outline, 4 turns on time keeping, 5 and above show an increasing amount of internal details). The library syntax is \fun{GEN}{factorint}{GEN x, long flag}. \subsec{factormod$(x,p,\{\fl=0\})$}\kbdsidx{factormod}\label{se:factormod} Factors the polynomial $x$ modulo the prime integer $p$, using \idx{Berlekamp}. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix, the first column being the irreducible polynomials dividing $x$, and the second the exponents. If $\fl$ is non-zero, outputs only the \emph{degrees} of the irreducible polynomials (for example, for computing an $L$-function). A different algorithm for computing the mod $p$ factorization is \kbd{factorcantor} which is sometimes faster. The library syntax is \fun{GEN}{factormod0}{GEN x, GEN p, long flag}. \subsec{ffgen$(q,\{v\})$}\kbdsidx{ffgen}\label{se:ffgen} Return a \typ{FFELT} generator for the finite field with $q$ elements; $q = p^f$ must be a prime power. This functions computes an irreducible monic polynomial $P\in\F_p[X]$ of degree~$f$ (via \tet{ffinit}) and returns $g = X \pmod{P(X)}$. If \kbd{v} is given, the variable name is used to display $g$, else the variable $x$ is used. \bprog ? g = ffgen(8, 't); ? g.mod %2 = t^3 + t^2 + 1 ? g.p %3 = 2 ? g.f %4 = 3 ? ffgen(6) *** 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} 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 $P$ is used. If $P$ is not irreducible, we create an invalid object and behaviour of functions dealing with the resulting \typ{FFELT} is undefined; in fact, it is much more costly to test $P$ for irreducibility than it would be to produce it via \kbd{ffinit}. The library syntax is \fun{GEN}{ffgen}{GEN q, long v = -1}, where \kbd{v} is a variable number. To create a generator for a prime finite field, the function \fun{GEN}{p_to_GEN}{GEN p, long v} returns \kbd{1+ffgen(x*Mod(1,p),v)}. \subsec{ffinit$(p,n,\{v='x\})$}\kbdsidx{ffinit}\label{se:ffinit} Computes a monic polynomial of degree $n$ which is irreducible over $\F_p$, where $p$ is assumed to be prime. This function uses a fast variant of Adleman and Lenstra's algorithm. It is useful in conjunction with \tet{ffgen}; for instance if \kbd{P = ffinit(3,2)}, you can represent elements in $\F_{3^2}$ in term of \kbd{g = ffgen(P,'t)}. This can be abbreviated as \kbd{g = ffgen(3\pow2, 't)}, where the defining polynomial $P$ can be later recovered as \kbd{g.mod}. The library syntax is \fun{GEN}{ffinit}{GEN p, long n, long v = -1}, where \kbd{v} is a variable number. \subsec{fflog$(x,g,\{o\})$}\kbdsidx{fflog}\label{se:fflog} Discrete logarithm of the finite field element $x$ in base $g$, i.e.~ an $e$ in $\Z$ such that $g^e = o$. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. It may be set as a side effect of calling \tet{ffprimroot}. If no $o$ is given, assume that $g$ is a primitive root. The result is undefined if $e$ does not exist. This function uses \item a combination of generic discrete log algorithms (see \tet{znlog}) \item a cubic sieve index calculus algorithm for large fields of degree at least $5$. \item Coppersmith's algorithm for fields of characteristic at most $5$. \bprog ? t = ffgen(ffinit(7,5)); ? o = fforder(t) %2 = 5602 \\@com \emph{not} a primitive root. ? fflog(t^10,t) %3 = 10 ? fflog(t^10,t, o) %4 = 10 ? g = ffprimroot(t, &o); ? o \\ order is 16806, bundled with its factorization matrix %6 = [16806, [2, 1; 3, 1; 2801, 1]] ? fforder(g, o) %7 = 16806 ? fflog(g^10000, g, o) %8 = 10000 @eprog The library syntax is \fun{GEN}{fflog}{GEN x, GEN g, GEN o = NULL}. \subsec{ffnbirred$(q,n\{,\var{fl}=0\})$}\kbdsidx{ffnbirred}\label{se:ffnbirred} Computes the number of monic irreducible polynomials over $\F_q$ of degree exactly $n$, ($\fl=0$ or omitted) or at most $n$ ($\fl=1$). The library syntax is \fun{GEN}{ffnbirred0}{GEN q, long n, long fl}. Also available are \fun{GEN}{ffnbirred}{GEN q, long n} (for $\fl=0$) and \fun{GEN}{ffsumnbirred}{GEN q, long n} (for $\fl=1$). \subsec{fforder$(x,\{o\})$}\kbdsidx{fforder}\label{se:fforder} Multiplicative order of the finite field element $x$. If $o$ is present, it represents a multiple of the order of the element, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where \kbd{N} is the cardinality of the multiplicative group of the underlying finite field. \bprog ? t = ffgen(ffinit(nextprime(10^8), 5)); ? g = ffprimroot(t, &o); \\@com o will be useful! ? fforder(g^1000000, o) time = 0 ms. %5 = 5000001750000245000017150000600250008403 ? fforder(g^1000000) time = 16 ms. \\@com noticeably slower, same result of course %6 = 5000001750000245000017150000600250008403 @eprog The library syntax is \fun{GEN}{fforder}{GEN x, GEN o = NULL}. \subsec{ffprimroot$(x, \{\&o\})$}\kbdsidx{ffprimroot}\label{se:ffprimroot} 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 a vector \kbd{[ord, fa]}, where \kbd{ord} is the order of the group and \kbd{fa} its factorisation \kbd{factor(ord)}. This last parameter is useful in \tet{fflog} and \tet{fforder}, see \secref{se:DLfun}. \bprog ? t = ffgen(ffinit(nextprime(10^7), 5)); ? g = ffprimroot(t, &o); ? o[1] %3 = 100000950003610006859006516052476098 ? o[2] %4 = [2 1] [7 2] [31 1] [41 1] [67 1] [1523 1] [10498781 1] [15992881 1] [46858913131 1] ? fflog(g^1000000, g, o) time = 1,312 ms. %5 = 1000000 @eprog The library syntax is \fun{GEN}{ffprimroot}{GEN x, GEN *o = NULL}. \subsec{fibonacci$(x)$}\kbdsidx{fibonacci}\label{se:fibonacci} $x^{\text{th}}$ Fibonacci number. The library syntax is \fun{GEN}{fibo}{long x}. \subsec{gcd$(x,\{y\})$}\kbdsidx{gcd}\label{se:gcd} Creates the greatest common divisor of $x$ and $y$. If you also need the $u$ and $v$ such that $x*u + y*v = \gcd(x,y)$, use the \tet{bezout} function. $x$ and $y$ can have rather quite general types, for instance both rational numbers. If $y$ is omitted and $x$ is a vector, returns the $\text{gcd}$ of all components of $x$, i.e.~this is equivalent to \kbd{content(x)}. When $x$ and $y$ are both given and one of them is a vector/matrix type, the GCD is again taken recursively on each component, but in a different way. If $y$ is a vector, resp.~matrix, then the result has the same type as $y$, and components equal to \kbd{gcd(x, y[i])}, resp.~\kbd{gcd(x, y[,i])}. Else if $x$ is a vector/matrix the result has the same type as $x$ and an analogous definition. Note that for these types, \kbd{gcd} is not commutative. The algorithm used is a naive \idx{Euclid} except for the following inputs: \item integers: use modified right-shift binary (``plus-minus'' variant). \item univariate polynomials with coefficients in the same number field (in particular rational): use modular gcd algorithm. \item general polynomials: use the \idx{subresultant algorithm} if coefficient explosion is likely (non modular coefficients). If $u$ and $v$ are polynomials in the same variable with \emph{inexact} coefficients, their gcd is defined to be scalar, so that \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? b = y*x + O(y); gcd(b,b) %2 = y ? c = 4*x + O(2^3); gcd(c,c) %3 = 4 @eprog\noindent A good quantitative check to decide whether such a gcd ``should be'' non-trivial, is to use \tet{polresultant}: a value close to $0$ means that a small deformation of the inputs has non-trivial gcd. You may also use \tet{gcdext}, which does try to compute an approximate gcd $d$ and provides $u$, $v$ to check whether $u x + v y$ is close to $d$. The library syntax is \fun{GEN}{ggcd0}{GEN x, GEN y = NULL}. Also available are \fun{GEN}{ggcd}{GEN x, GEN y}, if \kbd{y} is not \kbd{NULL}, and \fun{GEN}{content}{GEN x}, if $\kbd{y} = \kbd{NULL}$. \subsec{gcdext$(x,y)$}\kbdsidx{gcdext}\label{se:gcdext} Returns $[u,v,d]$ such that $d$ is the gcd of $x,y$, $x*u+y*v=\gcd(x,y)$, and $u$ and $v$ minimal in a natural sense. The arguments must be integers or polynomials. \sidx{extended gcd} \sidx{Bezout relation} \bprog ? [u, v, d] = gcdext(32,102) %1 = [16, -5, 2] ? d %2 = 2 ? gcdext(x^2-x, x^2+x-2) %3 = [-1/2, 1/2, x - 1] @eprog If $x,y$ are polynomials in the same variable and \emph{inexact} coefficients, then compute $u,v,d$ such that $x*u+y*v = d$, where $d$ approximately divides both and $x$ and $y$; in particular, we do not obtain \kbd{gcd(x,y)} which is \emph{defined} to be a scalar in this case: \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? gcdext(a,a) %2 = [0, 1, x + 0.E-28] ? gcdext(x-Pi, 6*x^2-zeta(2)) %3 = [-6*x - 18.8495559, 1, 57.5726923] @eprog\noindent For inexact inputs, the output is thus not well defined mathematically, but you obtain explicit polynomials to check whether the approximation is close enough for your needs. The library syntax is \fun{GEN}{gcdext0}{GEN x, GEN y}. \subsec{hilbert$(x,y,\{p\})$}\kbdsidx{hilbert}\label{se:hilbert} \idx{Hilbert symbol} of $x$ and $y$ modulo the prime $p$, $p=0$ meaning the place at infinity (the result is undefined if $p\neq 0$ is not prime). It is possible to omit $p$, in which case we take $p = 0$ if both $x$ and $y$ are rational, or one of them is a real number. And take $p = q$ if one of $x$, $y$ is a \typ{INTMOD} modulo $q$ or a $q$-adic. (Incompatible types will raise an error.) The library syntax is \fun{long}{hilbert}{GEN x, GEN y, GEN p = NULL}. \subsec{isfundamental$(x)$}\kbdsidx{isfundamental}\label{se:isfundamental} True (1) if $x$ is equal to 1 or to the discriminant of a quadratic field, false (0) otherwise. The library syntax is \fun{long}{isfundamental}{GEN x}. \subsec{ispolygonal$(x,s,\{\&N\})$}\kbdsidx{ispolygonal}\label{se:ispolygonal} True (1) if the integer $x$ is an s-gonal number, false (0) if not. The parameter $s > 2$ must be a \typ{INT}. If $N$ is given, set it to $n$ if $x$ is the $n$-th $s$-gonal number. \bprog ? ispolygonal(36, 3, &N) %1 = 1 ? N @eprog The library syntax is \fun{long}{ispolygonal}{GEN x, GEN s, GEN *N = NULL}. \subsec{ispower$(x,\{k\},\{\&n\})$}\kbdsidx{ispower}\label{se:ispower} If $k$ is given, returns true (1) if $x$ is a $k$-th power, false (0) if not. If $k$ is omitted, only integers and fractions are allowed for $x$ and the function returns the maximal $k \geq 2$ such that $x = n^k$ is a perfect power, or 0 if no such $k$ exist; in particular \kbd{ispower(-1)}, \kbd{ispower(0)}, and \kbd{ispower(1)} all return $0$. If a third argument $\&n$ is given and $x$ is indeed a $k$-th power, sets $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) @eprog The library syntax is \fun{long}{ispower}{GEN x, GEN k = NULL, GEN *n = NULL}. Also available is \fun{long}{gisanypower}{GEN x, GEN *pty} ($k$ omitted). \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. \bprog ? ispowerful(50) %1 = 0 ? ispowerful(100) %2 = 1 ? ispowerful(5^3*(10^1000+1)^2) %3 = 1 @eprog The library syntax is \fun{long}{ispowerful}{GEN x}. \subsec{isprime$(x,\{\fl=0\})$}\kbdsidx{isprime}\label{se:isprime} True (1) if $x$ is a prime number, false (0) otherwise. A prime number is a positive integer having exactly two distinct divisors among the natural numbers, namely 1 and itself. This routine proves or disproves rigorously that a number is prime, which can be very slow when $x$ is indeed prime and has more than $1000$ digits, say. Use \tet{ispseudoprime} to quickly check for compositeness. See also \kbd{factor}. It accepts vector/matrices arguments, and is then applied componentwise. If $\fl=0$, use a combination of Baillie-PSW pseudo primality test (see \tet{ispseudoprime}), Selfridge ``$p-1$'' test if $x-1$ is smooth enough, and Adleman-Pomerance-Rumely-Cohen-Lenstra (APRCL) for general $x$. If $\fl=1$, use Selfridge-Pocklington-Lehmer ``$p-1$'' test and output a primality certificate as follows: return \item 0 if $x$ is composite, \item 1 if $x$ is small enough that passing Baillie-PSW test guarantees its primality (currently $x < 2^{64}$, as checked by Jan Feitsma), \item $2$ if $x$ is a large prime whose primality could only sensibly be proven (given the algorithms implemented in PARI) using the APRCL test. \item Otherwise ($x$ is large and $x-1$ is smooth) output a three column matrix as a primality certificate. The first column contains prime divisors $p$ of $x-1$ (such that $\prod p^{v_p(x-1)} > x^{1/3}$), the second the corresponding elements $a_p$ as in Proposition~8.3.1 in GTM~138 , and the third the output of isprime(p,1). The algorithm fails if one of the pseudo-prime factors is not prime, which is exceedingly unlikely and well worth a bug report. Note that if you monitor \kbd{isprime} at a high enough debug level, you may see warnings about untested integers being declared primes. This is normal: we ask for partial factorisations (sufficient to prove primality if the unfactored part is not too large), and \kbd{factor} warns us that the cofactor hasn't been tested. It may or may not be tested later, and may or may not be prime. This does not affect the validity of the whole \kbd{isprime} procedure. If $\fl=2$, use APRCL. The library syntax is \fun{GEN}{gisprime}{GEN x, long flag}. \subsec{isprimepower$(x,\{\&n\})$}\kbdsidx{isprimepower}\label{se:isprimepower} If $x = p^k$ is a prime power ($p$ prime, $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$. The library syntax is \fun{long}{isprimepower}{GEN x, GEN *n = NULL}. \subsec{ispseudoprime$(x,\{\fl\})$}\kbdsidx{ispseudoprime}\label{se:ispseudoprime} 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 that $x$ is a prime number. Use \tet{isprime} (which is of course much slower) to prove that $x$ is indeed prime. The function accepts vector/matrices arguments, and is then applied componentwise. If $\fl = 0$, checks whether $x$ is a Baillie-Pomerance-Selfridge-Wagstaff pseudo prime (strong Rabin-Miller pseudo prime for base $2$, followed by strong Lucas test for the sequence $(P,-1)$, $P$ smallest positive integer 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}). 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{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 \typ{COMPLEX} are squares, as well as all non-negative \typ{REAL}; for exact types such as \typ{INT}, \typ{FRAC} and \typ{INTMOD}, squares are numbers of the form $s^2$ with $s$ in $\Z$, $\Q$ and $\Z/N\Z$ respectively. \bprog ? issquare(3) \\ as an integer %1 = 0 ? issquare(3.) \\ as a real number %2 = 1 ? issquare(Mod(7, 8)) \\ in Z/8Z %3 = 0 ? issquare( 5 + O(13^4) ) \\ in Q_13 %4 = 0 @eprog If $n$ is given, a square root of $x$ is put into $n$. \bprog ? issquare(4, &n) %1 = 1 ? n %2 = 2 @eprog For polynomials, either we detect that the characteristic is 2 (and check directly odd and even-power monomials) or we assume that $2$ is invertible and check whether squaring the truncated power series for the square root yields the original input. The library syntax is \fun{long}{issquareall}{GEN x, GEN *n = NULL}. Also available is \fun{long}{issquare}{GEN x}. Deprecated GP-specific functions \fun{GEN}{gissquare}{GEN x} and \fun{GEN}{gissquareall}{GEN x, GEN *pt} return \kbd{gen\_0} and \kbd{gen\_1} instead of a boolean value. \subsec{issquarefree$(x)$}\kbdsidx{issquarefree}\label{se:issquarefree} True (1) if $x$ is squarefree, false (0) if not. Here $x$ can be an integer or a polynomial. The library syntax is \fun{long}{issquarefree}{GEN x}. \subsec{istotient$(x,\{\&N\})$}\kbdsidx{istotient}\label{se:istotient} True (1) if $x = \phi(n)$ for some integer $n$, false (0) if not. \bprog ? istotient(14) %1 = 0 ? istotient(100) %2 = 0 @eprog If $N$ is given, set $N = n$ as well. \bprog ? istotient(4, &n) %1 = 1 ? n %2 = 10 @eprog The library syntax is \fun{long}{istotient}{GEN x, GEN *N = NULL}. \subsec{kronecker$(x,y)$}\kbdsidx{kronecker}\label{se:kronecker} \idx{Kronecker symbol} $(x|y)$, where $x$ and $y$ must be of type integer. By definition, this is the extension of \idx{Legendre symbol} to $\Z \times \Z$ by total multiplicativity in both arguments with the following special rules for $y = 0, -1$ or $2$: \item $(x|0) = 1$ if $|x| = 1$ and $0$ otherwise. \item $(x|-1) = 1$ if $x \geq 0$ and $-1$ otherwise. \item $(x|2) = 0$ if $x$ is even and $1$ if $x = 1,-1 \mod 8$ and $-1$ if $x=3,-3 \mod 8$. 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$ is a vector, returns the $\text{lcm}$ of all components of $x$. 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. If $y$ is a vector, resp.~matrix, then the result has the same type as $y$, and components equal to \kbd{lcm(x, y[i])}, resp.~\kbd{lcm(x, y[,i])}. Else if $x$ is a vector/matrix the result has the same type as $x$ and an analogous definition. Note that for these types, \kbd{lcm} is not commutative. Note that \kbd{lcm(v)} is quite different from \bprog l = v[1]; for (i = 1, #v, l = lcm(l, v[i])) @eprog\noindent Indeed, \kbd{lcm(v)} is a scalar, but \kbd{l} may not be (if one of 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); ? lcm(v); time = 323 ms. ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i])) time = 833 ms. @eprog The library syntax is \fun{GEN}{glcm0}{GEN x, GEN y = NULL}. \subsec{logint$(x,b,\&z)$}\kbdsidx{logint}\label{se:logint} Return the largest integer $e$ so that $b^e \leq x$, where the parameters $b > 1$ and $x > 0$ are both integers. If the parameter $z$ is present, set it to $b^e$. \bprog ? logint(1000, 2) %1 = 9 ? 2^9 %2 = 512 ? logint(1000, 2, &z) %3 = 9 ? z %4 = 512 @eprog\noindent The number of digits used to write $b$ in base $x$ is \kbd{1 + logint(x,b)}: \bprog ? #digits(1000!, 10) %5 = 2568 ? logint(1000!, 10) %6 = 2567 @eprog\noindent This function may conveniently replace \bprog floor( log(x) / log(b) ) @eprog\noindent which may not give the correct answer since PARI does not guarantee exact rounding. The library syntax is \fun{long}{logint0}{GEN x, GEN b, GEN *z = NULL}. \subsec{moebius$(x)$}\kbdsidx{moebius}\label{se:moebius} \idx{Moebius} $\mu$-function of $|x|$. $x$ must be of type integer. The library syntax is \fun{long}{moebius}{GEN x}. \subsec{nextprime$(x)$}\kbdsidx{nextprime}\label{se:nextprime} Finds the smallest pseudoprime (see \tet{ispseudoprime}) greater than or equal to $x$. $x$ can be of any real type. Note that if $x$ is a pseudoprime, this function returns $x$ and not the smallest pseudoprime strictly larger than $x$. To rigorously prove that the result is prime, use \kbd{isprime}. The library syntax is \fun{GEN}{nextprime}{GEN x}. \subsec{numbpart$(n)$}\kbdsidx{numbpart}\label{se:numbpart} Gives the number of unrestricted partitions of $n$, usually called $p(n)$ in the literature; in other words the number of nonnegative integer solutions to $a+2b+3c+\cdots=n$. $n$ must be of type integer and $n<10^{15}$ (with trivial values $p(n) = 0$ for $n < 0$ and $p(0) = 1$). The algorithm uses the Hardy-Ramanujan-Rademacher formula. To explicitly enumerate them, see \tet{partitions}. The library syntax is \fun{GEN}{numbpart}{GEN n}. \subsec{numdiv$(x)$}\kbdsidx{numdiv}\label{se:numdiv} Number of divisors of $|x|$. $x$ must be of type integer. The library syntax is \fun{GEN}{numdiv}{GEN x}. \subsec{omega$(x)$}\kbdsidx{omega}\label{se:omega} Number of distinct prime divisors of $|x|$. $x$ must be of type integer. \bprog ? factor(392) %1 = [2 3] [7 2] ? omega(392) %2 = 2; \\ without multiplicity ? bigomega(392) %3 = 5; \\ = 3+2, with multiplicity @eprog The library syntax is \fun{long}{omega}{GEN x}. \subsec{partitions$(k,\{a=k\},\{n=k\}))$}\kbdsidx{partitions}\label{se:partitions} Returns the vector of partitions of the integer $k$ as a sum of positive integers (parts); for $k < 0$, it returns the empty set \kbd{[]}, and for $k = 0$ the trivial partition (no parts). A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order: \bprog ? partitions(3) %1 = [Vecsmall([3]), Vecsmall([1, 2]), Vecsmall([1, 1, 1])] @eprog\noindent correspond to $3$, $1+2$ and $1+1+1$. The number of (unrestricted) partitions of $k$ is given by \tet{numbpart}: \bprog ? #partitions(50) %1 = 204226 ? numbpart(50) %2 = 204226 @eprog \noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). \bprog ? partitions(4, 2) \\ parts bounded by 2 %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])] ? partitions(4,, 2) \\ at most 2 parts %2 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])] ? partitions(4,[0,3], 2) \\ at most 2 parts %3 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])] @eprog\noindent By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case $nmin$ is ignored and $X$ is of constant length $\var{nmax}$: \bprog ? partitions(4, [0,3]) \\ parts between 0 and 3 %1 = [Vecsmall([0, 0, 1, 3]), Vecsmall([0, 0, 2, 2]),\ Vecsmall([0, 1, 1, 2]), Vecsmall([1, 1, 1, 1])] @eprog The library syntax is \fun{GEN}{partitions}{long k, GEN a = NULL, GEN n) = NULL}. \subsec{polrootsff$(x,\{p\},\{a\})$}\kbdsidx{polrootsff}\label{se:polrootsff} Returns the vector of distinct roots of the polynomial $x$ in the field $\F_q$ defined by the irreducible polynomial $a$ over $\F_p$. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. Either $a$ or $p$ can omitted (in which case both are ignored) if x has \typ{FFELT} coefficients: \bprog ? polrootsff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25 %1 = [Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)), Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5))] ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT ? polrootsff(x^2 + 1) \\ not enough information to determine the base field *** at top-level: polrootsff(x^2+1) *** ^----------------- *** polrootsff: incorrect type in factorff. ? polrootsff(x^2 + t^0) \\ make sure one coeff. is a t_FFELT %3 = [3, 2] ? polrootsff(x^2 + t + 1) %4 = [2*t + 1, 3*t + 4] @eprog\noindent Notice that the second syntax is easier to use and much more readable. The library syntax is \fun{GEN}{polrootsff}{GEN x, GEN p = NULL, GEN a = NULL}. \subsec{precprime$(x)$}\kbdsidx{precprime}\label{se:precprime} Finds the largest pseudoprime (see \tet{ispseudoprime}) less than or equal to $x$. $x$ can be of any real type. Returns 0 if $x\le1$. Note that if $x$ is a prime, this function returns $x$ and not the largest prime strictly smaller than $x$. To rigorously prove that the result is prime, use \kbd{isprime}. The library syntax is \fun{GEN}{precprime}{GEN x}. \subsec{prime$(n)$}\kbdsidx{prime}\label{se:prime} The $n^{\text{th}}$ prime number \bprog ? prime(10^9) %1 = 22801763489 @eprog\noindent Uses checkpointing and a naive $O(n)$ algorithm. The library syntax is \fun{GEN}{prime}{long n}. \subsec{primepi$(x)$}\kbdsidx{primepi}\label{se:primepi} The prime counting function. Returns the number of primes $p$, $p \leq x$. \bprog ? primepi(10) %1 = 4; ? primes(5) %2 = [2, 3, 5, 7, 11] ? primepi(10^11) %3 = 4118054813 @eprog\noindent Uses checkpointing and a naive $O(x)$ algorithm. The library syntax is \fun{GEN}{primepi}{GEN x}. \subsec{primes$(n)$}\kbdsidx{primes}\label{se:primes} Creates a row vector whose components are the first $n$ prime numbers. (Returns the empty vector for $n \leq 0$.) A \typ{VEC} $n = [a,b]$ is also allowed, in which case the primes in $[a,b]$ are returned \bprog ? primes(10) \\ the first 10 primes %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([0,29]) \\ the primes up to 29 %2 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([15,30]) %3 = [17, 19, 23, 29] @eprog 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}. \misctitle{Warning} Contrary to what its name implies, this routine does not compute the number of classes of binary primitive forms of discriminant $D$, which is equal to the \emph{narrow} class number. The two notions are the same when $D < 0$ or the fundamental unit $\varepsilon$ has negative norm; when $D > 0$ and $N\varepsilon > 0$, the number of classes of forms is twice the ordinary class number. This is a problem which we cannot fix for backward compatibility reasons. Use the following routine if you are only interested in the number of classes of forms: \bprog QFBclassno(D) = qfbclassno(D) * if (D < 0 || norm(quadunit(D)) < 0, 1, 2) @eprog\noindent Here are a few examples: \bprog ? qfbclassno(400000028) time = 3,140 ms. %1 = 1 ? quadclassunit(400000028).no time = 20 ms. \\@com{ much faster} %2 = 1 ? qfbclassno(-400000028) time = 0 ms. %3 = 7253 \\@com{ correct, and fast enough} ? quadclassunit(-400000028).no time = 0 ms. %4 = 7253 @eprog\noindent See also \kbd{qfbhclassno}. The library syntax is \fun{GEN}{qfbclassno0}{GEN D, long flag}. The following functions are also available: \fun{GEN}{classno}{GEN D} ($\fl = 0$) \fun{GEN}{classno2}{GEN D} ($\fl = 1$). \noindent Finally \fun{GEN}{hclassno}{GEN D} computes the class number of an imaginary quadratic field by counting reduced forms, an $O(|D|)$ algorithm. \subsec{qfbcompraw$(x,y)$}\kbdsidx{qfbcompraw}\label{se:qfbcompraw} \idx{composition} of the binary quadratic forms $x$ and $y$, without \idx{reduction} of the result. This is useful e.g.~to compute a generating element of an ideal. The result is undefined if $x$ and $y$ do not have the same discriminant. The library syntax is \fun{GEN}{qfbcompraw}{GEN x, GEN y}. \subsec{qfbhclassno$(x)$}\kbdsidx{qfbhclassno}\label{se:qfbhclassno} \idx{Hurwitz class number} of $x$, where $x$ is non-negative and congruent to 0 or 3 modulo 4. For $x > 5\cdot 10^5$, we assume the GRH, and use \kbd{quadclassunit} with default parameters. The library syntax is \fun{GEN}{hclassno}{GEN x}. \subsec{qfbnucomp$(x,y,L)$}\kbdsidx{qfbnucomp}\label{se:qfbnucomp} \idx{composition} of the primitive positive definite binary quadratic forms $x$ and $y$ (type \typ{QFI}) using the NUCOMP and NUDUPL algorithms of \idx{Shanks}, \`a la Atkin. $L$ is any positive constant, but for optimal speed, one should take $L=|D|^{1/4}$, where $D$ is the common discriminant of $x$ and $y$. When $x$ and $y$ do not have the same discriminant, the result is undefined. The current implementation is straightforward and in general \emph{slower} than the generic routine (since the latter takes advantage of asymptotically fast operations and careful optimizations). The library syntax is \fun{GEN}{nucomp}{GEN x, GEN y, GEN L}. Also available is \fun{GEN}{nudupl}{GEN x, GEN L} when $x=y$. \subsec{qfbnupow$(x,n)$}\kbdsidx{qfbnupow}\label{se:qfbnupow} $n$-th power of the primitive positive definite binary quadratic form $x$ using \idx{Shanks}'s NUCOMP and NUDUPL algorithms (see \kbd{qfbnucomp}, in particular the final warning). The library syntax is \fun{GEN}{nupow}{GEN x, GEN n}. \subsec{qfbpowraw$(x,n)$}\kbdsidx{qfbpowraw}\label{se:qfbpowraw} $n$-th power of the binary quadratic form $x$, computed without doing any \idx{reduction} (i.e.~using \kbd{qfbcompraw}). Here $n$ must be non-negative and $n<2^{31}$. The library syntax is \fun{GEN}{qfbpowraw}{GEN x, long n}. \subsec{qfbprimeform$(x,p)$}\kbdsidx{qfbprimeform}\label{se:qfbprimeform} Prime binary quadratic form of discriminant $x$ whose first coefficient is $p$, where $|p|$ is a prime number. By abuse of notation, $p = \pm 1$ is also valid and returns the unit form. Returns an error if $x$ is not a quadratic residue mod $p$, or if $x < 0$ and $p < 0$. (Negative definite \typ{QFI} are not implemented.) In the case where $x>0$, the ``distance'' component of the form is set equal to zero according to the current precision. The library syntax is \fun{GEN}{primeform}{GEN x, GEN p, long prec}. \subsec{qfbred$(x,\{\fl=0\},\{d\},\{\var{isd}\},\{\var{sd}\})$}\kbdsidx{qfbred}\label{se:qfbred} Reduces the binary quadratic form $x$ (updating Shanks's distance function if $x$ is indefinite). The binary digits of $\fl$ are toggles meaning \quad 1: perform a single \idx{reduction} step \quad 2: don't update \idx{Shanks}'s distance The arguments $d$, \var{isd}, \var{sd}, if present, supply the values of the discriminant, $\floor{\sqrt{d}}$, and $\sqrt{d}$ respectively (no checking is done of these facts). If $d<0$ these values are useless, and all references to Shanks's distance are irrelevant. The library syntax is \fun{GEN}{qfbred0}{GEN x, long flag, GEN d = NULL, GEN isd = NULL, GEN sd = NULL}. Also available are \fun{GEN}{redimag}{GEN x} (for definite $x$), \noindent and for indefinite forms: \fun{GEN}{redreal}{GEN x} \fun{GEN}{rhoreal}{GEN x} (= \kbd{qfbred(x,1)}), \fun{GEN}{redrealnod}{GEN x, GEN isd} (= \kbd{qfbred(x,2,,isd)}), \fun{GEN}{rhorealnod}{GEN x, GEN isd} (= \kbd{qfbred(x,3,,isd)}). \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. Return $[x,y]$ as a two-components vector, or zero if there is no solution. Note that this function returns only one solution and not all the solutions. Let $D = \disc Q$. The algorithm used runs in probabilistic polynomial time in $p$ (through the computation of a square root of $D$ modulo $p$); it is polynomial time in $D$ if $Q$ is imaginary, but exponential time if $Q$ is real (through the computation of a full cycle of reduced forms). In the latter case, note that \tet{bnfisprincipal} provides a solution in heuristic subexponential time in $D$ assuming the GRH. The library syntax is \fun{GEN}{qfbsolve}{GEN Q, GEN p}. \subsec{quadclassunit$(D,\{\fl=0\},\{\var{tech}=[\,]\})$}\kbdsidx{quadclassunit}\label{se:quadclassunit} \idx{Buchmann-McCurley}'s sub-exponential algorithm for computing the class group of a quadratic order of discriminant $D$. This function should be used instead of \tet{qfbclassno} or \tet{quadregula} when $D<-10^{25}$, $D>10^{10}$, or when the \emph{structure} is wanted. It is a special case of \tet{bnfinit}, which is slower, but more robust. The result is a vector $v$ whose components should be accessed using member functions: \item \kbd{$v$.no}: the class number \item \kbd{$v$.cyc}: a vector giving the structure of the class group as a product of cyclic groups; \item \kbd{$v$.gen}: a vector giving generators of those cyclic groups (as binary quadratic forms). \item \kbd{$v$.reg}: the regulator, computed to an accuracy which is the maximum of an internal accuracy determined by the program and the current default (note that once the regulator is known to a small accuracy it is trivial to compute it to very high accuracy, see the tutorial). The $\fl$ is obsolete and should be left alone. In older versions, it supposedly computed the narrow class group when $D>0$, but this did not work at all; use the general function \tet{bnfnarrow}. Optional parameter \var{tech} is a row vector of the form $[c_1, c_2]$, where $c_1 \leq c_2$ are non-negative real numbers which control the execution time and the stack size, see \ref{se:GRHbnf}. The parameter is used as a threshold to balance the relation finding phase against the final linear algebra. Increasing the default $c_1$ means that relations are easier to find, but more relations are needed and the linear algebra will be harder. The default value for $c_1$ is $0$ and means that it is taken equal to $c_2$. The parameter $c_2$ is mostly obsolete and should not be changed, but we still document it for completeness: we compute a tentative class group by generators and relations using a factorbase of prime ideals $\leq c_1 (\log |D|)^2$, then prove that ideals of norm $\leq c_2 (\log |D|)^2$ do not generate a larger group. By default an optimal $c_2$ is chosen, so that the result is provably correct under the GRH --- a famous result of Bach states that $c_2 = 6$ is fine, but it is possible to improve on this algorithmically. You may provide a smaller $c_2$, it will be ignored (we use the provably correct one); you may provide a larger $c_2$ than the default value, which results in longer computing times for equally correct outputs (under GRH). The library syntax is \fun{GEN}{quadclassunit0}{GEN D, long flag, GEN tech = NULL, long prec}. If you really need to experiment with the \var{tech} parameter, it is usually more convenient to use \fun{GEN}{Buchquad}{GEN D, double c1, double c2, long prec} \subsec{quaddisc$(x)$}\kbdsidx{quaddisc}\label{se:quaddisc} Discriminant of the quadratic field $\Q(\sqrt{x})$, where $x\in\Q$. The library syntax is \fun{GEN}{quaddisc}{GEN x}. \subsec{quadgen$(D)$}\kbdsidx{quadgen}\label{se:quadgen} Creates the quadratic number\sidx{omega} $\omega=(a+\sqrt{D})/2$ where $a=0$ if $D\equiv0\mod4$, $a=1$ if $D\equiv1\mod4$, so that $(1,\omega)$ is an integral basis for the quadratic order of discriminant $D$. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square. The library syntax is \fun{GEN}{quadgen}{GEN D}. \subsec{quadhilbert$(D)$}\kbdsidx{quadhilbert}\label{se:quadhilbert} Relative equation defining the \idx{Hilbert class field} of the quadratic field of discriminant $D$. If $D < 0$, uses complex multiplication (\idx{Schertz}'s variant). If $D > 0$ \idx{Stark units} are used and (in rare cases) a vector of extensions may be returned whose compositum is the requested class field. See \kbd{bnrstark} for details. The library syntax is \fun{GEN}{quadhilbert}{GEN D, long prec}. \subsec{quadpoly$(D,\{v='x\})$}\kbdsidx{quadpoly}\label{se:quadpoly} Creates the ``canonical'' quadratic polynomial (in the variable $v$) corresponding to the discriminant $D$, i.e.~the minimal polynomial of $\kbd{quadgen}(D)$. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square. The library syntax is \fun{GEN}{quadpoly0}{GEN D, long v = -1}, where \kbd{v} is a variable number. \subsec{quadray$(D,f)$}\kbdsidx{quadray}\label{se:quadray} Relative equation for the ray class field of conductor $f$ for the quadratic field of discriminant $D$ using analytic methods. A \kbd{bnf} for $x^2 - D$ is also accepted in place of $D$. For $D < 0$, uses the $\sigma$ function and Schertz's method. For $D>0$, uses Stark's conjecture, and a vector of relative equations may be returned. See \tet{bnrstark} for more details. The library syntax is \fun{GEN}{quadray}{GEN D, GEN f, long prec}. \subsec{quadregulator$(x)$}\kbdsidx{quadregulator}\label{se:quadregulator} Regulator of the quadratic field of positive discriminant $x$. Returns an error if $x$ is not a discriminant (fundamental or not) or if $x$ is a square. See also \kbd{quadclassunit} if $x$ is large. The library syntax is \fun{GEN}{quadregulator}{GEN x, long prec}. \subsec{quadunit$(D)$}\kbdsidx{quadunit}\label{se:quadunit} Fundamental unit\sidx{fundamental units} of the real quadratic field $\Q(\sqrt D)$ where $D$ is the positive discriminant of the field. If $D$ is not a fundamental discriminant, this probably gives the fundamental unit of the corresponding order. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square; the result is a quadratic number (see \secref{se:quadgen}). The library syntax is \fun{GEN}{quadunit}{GEN D}. \subsec{randomprime$(\{N = 2^{{31}}\})$}\kbdsidx{randomprime}\label{se:randomprime} Returns a strong pseudo prime (see \tet{ispseudoprime}) in $[2,N-1]$. A \typ{VEC} $N = [a,b]$ is also allowed, with $a \leq b$ in which case a pseudo prime $a \leq p \leq b$ is returned; if no prime exists in the interval, the function will run into an infinite loop. If the upper bound is less than $2^{64}$ the pseudo prime returned is a proven prime. The library syntax is \fun{GEN}{randomprime}{GEN N = NULL}. \subsec{removeprimes$(\{x=[\,]\})$}\kbdsidx{removeprimes}\label{se:removeprimes} Removes the primes listed in $x$ from the prime number table. In particular \kbd{removeprimes(addprimes())} empties the extra prime table. $x$ can also be a single integer. List the current extra primes if $x$ is omitted. The library syntax is \fun{GEN}{removeprimes}{GEN x = NULL}. \subsec{sigma$(x,\{k=1\})$}\kbdsidx{sigma}\label{se:sigma} Sum of the $k^{\text{th}}$ powers of the positive divisors of $|x|$. $x$ and $k$ must be of type integer. The library syntax is \fun{GEN}{sumdivk}{GEN x, long k}. Also available is \fun{GEN}{sumdiv}{GEN n}, for $k = 1$. \subsec{sqrtint$(x)$}\kbdsidx{sqrtint}\label{se:sqrtint} Returns the integer square root of $x$, i.e. the largest integer $y$ such that $y^2 \leq x$, where $x$ a non-negative integer. \bprog ? N = 120938191237; sqrtint(N) %1 = 347761 ? sqrt(N) %2 = 347761.68741970412747602130964414095216 @eprog The library syntax is \fun{GEN}{sqrtint}{GEN x}. \subsec{sqrtnint$(x,n)$}\kbdsidx{sqrtnint}\label{se:sqrtnint} Returns the integer $n$-th root of $x$, i.e. the largest integer $y$ such that $y^n \leq x$, where $x$ is a non-negative integer. \bprog ? N = 120938191237; sqrtnint(N, 5) %1 = 164 ? N^(1/5) %2 = 164.63140849829660842958614676939677391 @eprog\noindent The special case $n = 2$ is \tet{sqrtint} The library syntax is \fun{GEN}{sqrtnint}{GEN x, long n}. \subsec{stirling$(n,k,\{\fl=1\})$}\kbdsidx{stirling}\label{se:stirling} \idx{Stirling number} of the first kind $s(n,k)$ ($\fl=1$, default) or of the second kind $S(n,k)$ (\fl=2), where $n$, $k$ are non-negative integers. The former is $(-1)^{n-k}$ times the number of permutations of $n$ symbols with exactly $k$ cycles; the latter is the number of ways of partitioning a set of $n$ elements into $k$ non-empty subsets. Note that if all $s(n,k)$ are needed, it is much faster to compute $$\sum_k s(n,k) x^k = x(x-1)\dots(x-n+1).$$ Similarly, if a large number of $S(n,k)$ are needed for the same $k$, one should use $$\sum_n S(n,k) x^n = \dfrac{x^k}{(1-x)\dots(1-kx)}.$$ (Should be implemented using a divide and conquer product.) Here are simple variants for $n$ fixed: \bprog /* list of s(n,k), k = 1..n */ 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]; simplify(t[2])); } @eprog The library syntax is \fun{GEN}{stirling}{long n, long k, long flag}. Also available are \fun{GEN}{stirling1}{ulong n, ulong k} ($\fl=1$) and \fun{GEN}{stirling2}{ulong n, ulong k} ($\fl=2$). \subsec{sumdedekind$(h,k)$}\kbdsidx{sumdedekind}\label{se:sumdedekind} Returns the \idx{Dedekind sum} associated to the integers $h$ and $k$, corresponding to a fast implementation of \bprog s(h,k) = sum(n = 1, k-1, (n/k)*(frac(h*n/k) - 1/2)) @eprog 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$. \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}. The library syntax is \fun{GEN}{sumdigits}{GEN n}. \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 $|x| \leq X$ such that $$\gcd(N, P(x)) \geq B,$$ using \idx{Coppersmith}'s algorithm (a famous application of the \idx{LLL} algorithm). $X$ must be smaller than $\exp(\log^2 B / (\deg(P) \log N))$: for $B = N$, this means $X < N^{1/\deg(P)}$. Some $x$ larger than $X$ may be returned if you are very lucky. The smaller $B$ (or the larger $X$), the slower the routine will be. The strength of Coppersmith method is the ability to find roots modulo a general \emph{composite} $N$: if $N$ is a prime or a prime power, \tet{polrootsmod} or \tet{polrootspadic} will be much faster. We shall now present two simple applications. The first one is finding non-trivial factors of $N$, given some partial information on the factors; in that case $B$ must obviously be smaller than the largest non-trivial divisor of $N$. \bprog setrand(1); \\ to make the example reproducible 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 L = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) \\ result in 10ms. %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}$. The second application is an attack on RSA with low exponent, when the message $x$ is short and the padding $P$ is known to the attacker. We use the same RSA modulus $N$ as in the first example: \bprog setrand(1); P = random(N); \\ known padding e = 3; \\ small public encryption exponent X = floor(N^0.3); \\ N^(1/e - epsilon) x0 = random(X); \\ unknown short message C = lift( (Mod(x0,N) + P)^e ); \\ known ciphertext, with padding P zncoppersmith((P + x)^3 - C, N, X) \\ result in 244ms. %14 = [2679982004001230401] ? %[1] == x0 %4 = 1 @eprog\noindent We guessed an integer of the order of $10^{18}$, almost instantly. The library syntax is \fun{GEN}{zncoppersmith}{GEN P, GEN N, GEN X, GEN B = NULL}. \subsec{znlog$(x,g,\{o\})$}\kbdsidx{znlog}\label{se:znlog} Discrete logarithm of $x$ in $(\Z/N\Z)^*$ in base $g$. The result is $[]$ when $x$ is not a power of $g$. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. This provides a definite speedup when the discrete log problem is simple: \bprog ? p = nextprime(10^4); g = znprimroot(p); o = [p-1, factor(p-1)]; ? for(i=1,10^4, znlog(i, g, o)) time = 205 ms. ? for(i=1,10^4, znlog(i, g)) time = 244 ms. \\ a little slower @eprog The result is undefined if $g$ is not invertible mod $N$ or if the supplied order is incorrect. This function uses \item a combination of generic discrete log algorithms (see below). \item in $(\Z/N\Z)^*$ when $N$ is prime: a linear sieve index calculus method, suitable for $N < 10^{50}$, say, is used for large prime divisors of the order. The generic discrete log algorithms are: \item Pohlig-Hellman algorithm, to reduce to groups of prime order $q$, where $q | p-1$ and $p$ is an odd prime divisor of $N$, \item Shanks baby-step/giant-step ($q < 2^{32}$ is small), \item Pollard rho method ($q > 2^{32}$). The latter two algorithms require $O(\sqrt{q})$ operations in the group on average, hence will not be able to treat cases where $q > 10^{30}$, say. In addition, Pollard rho is not able to handle the case where there are no solutions: it will enter an infinite loop. \bprog ? g = znprimroot(101) %1 = Mod(2,101) ? znlog(5, g) %2 = 24 ? g^24 %3 = Mod(5, 101) ? G = znprimroot(2 * 101^10) %4 = Mod(110462212541120451003, 220924425082240902002) ? znlog(5, G) %5 = 76210072736547066624 ? G^% == 5 %6 = 1 ? N = 2^4*3^2*5^3*7^4*11; g = Mod(13, N); znlog(g^110, g) %7 = 110 ? znlog(6, Mod(2,3)) \\ no solution %8 = [] @eprog\noindent For convenience, $g$ is also allowed to be a $p$-adic number: \bprog ? g = 3+O(5^10); znlog(2, g) %1 = 1015243 ? g^% %2 = 2 + O(5^10) @eprog The library syntax is \fun{GEN}{znlog}{GEN x, GEN g, GEN o = NULL}. \subsec{znorder$(x,\{o\})$}\kbdsidx{znorder}\label{se:znorder} $x$ must be an integer mod $n$, and the result is the order of $x$ in the multiplicative group $(\Z/n\Z)^*$. Returns an error if $x$ is not invertible. The parameter o, if present, represents a non-zero multiple of the order of $x$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord = eulerphi(n)} is the cardinality of the group. The library syntax is \fun{GEN}{znorder}{GEN x, GEN o = NULL}. Also available is \fun{GEN}{order}{GEN x}. \subsec{znprimroot$(n)$}\kbdsidx{znprimroot}\label{se:znprimroot} Returns a primitive root (generator) of $(\Z/n\Z)^*$, whenever this latter group is cyclic ($n = 4$ or $n = 2p^k$ or $n = p^k$, where $p$ is an odd prime and $k \geq 0$). If the group is not cyclic, the result is undefined. If $n$ is a prime power, then the smallest positive primitive root is returned. This may not be true for $n = 2p^k$, $p$ odd. Note that this function requires factoring $p-1$ for $p$ as above, in order to determine the exact order of elements in $(\Z/n\Z)^*$: this is likely to be costly if $p$ is large. The library syntax is \fun{GEN}{znprimroot}{GEN n}. \subsec{znstar$(n)$}\kbdsidx{znstar}\label{se:znstar} Gives the structure of the multiplicative group $(\Z/n\Z)^*$ as a 3-component row vector $v$, where $v[1]=\phi(n)$ is the order of that group, $v[2]$ is a $k$-component row-vector $d$ of integers $d[i]$ such that $d[i]>1$ and $d[i]\mid d[i-1]$ for $i \ge 2$ and $(\Z/n\Z)^* \simeq \prod_{i=1}^k(\Z/d[i]\Z)$, and $v[3]$ is a $k$-component row vector giving generators of the image of the cyclic groups $\Z/d[i]\Z$. \bprog ? G = znstar(40) %1 = [16, [4, 2, 2], [Mod(17, 40), Mod(21, 40), Mod(11, 40)]] ? G.no \\ eulerphi(40) %2 = 16 ? G.cyc \\ cycle structure %3 = [4, 2, 2] ? G.gen \\ generators for the cyclic components %4 = [Mod(17, 40), Mod(21, 40), Mod(11, 40)] ? apply(znorder, G.gen) %5 = [4, 2, 2] @eprog\noindent According to the above definitions, \kbd{znstar(0)} is \kbd{[2, [2], [-1]]}, corresponding to $\Z^*$. The library syntax is \fun{GEN}{znstar}{GEN n}. %SECTION: number_theoretical \section{Functions related to elliptic curves} \subsec{Elliptic curve structures} An elliptic curve is given by a Weierstrass model\sidx{Weierstrass equation} $$ y^2+a_1xy+a_3y=x^3+a_2x^2+a_4x+a_6, $$ whose discriminant is non-zero. Affine points on \kbd{E} are represented as two-component vectors \kbd{[x,y]}; the point at infinity, i.e.~the identity element of the group law, is represented by the one-component vector \kbd{[0]}. Given a vector of coefficients $[a_1,a_2,a_3,a_4,a_6]$, the function \tet{ellinit} initializes and returns an \tev{ell} structure. (An additional optional argument allows to specify the base field in case it cannot be inferred from the curve coefficients.) This structure contains data needed by elliptic curve related functions, and is generally passed as a first argument. Expensive data are skipped on initialization: they will be dynamically computed when (and if) needed, and then inserted in the structure. The precise layout of the \tev{ell} structure is left undefined and should never be used directly. The following \idx{member functions} are available, depending on the underlying domain. \subsubsec{All domains} \item \tet{a1}, \tet{a2}, \tet{a3}, \tet{a4}, \tet{a6}: coefficients of the elliptic curve. \item \tet{b2}, \tet{b4}, \tet{b6}, \tet{b8}: $b$-invariants of the curve; in characteristic $\neq 2$, for $Y = 2y + a_1x+a3$, the curve equation becomes $$ Y^2 = 4 x^3 + b_2 x^2 + 2b_4 x + b_6 =: g(x). $$ \item \tet{c4}, \tet{c6}: $c$-invariants of the curve; in characteristic $\neq 2,3$, for $X = x + b_2/12$ and $Y = 2y + a_1x+a3$, the curve equation becomes $$ Y^2 = 4 X^3 - (c_4/12) X - (c_6/216). $$ \item \tet{disc}: discriminant of the curve. This is only required to be non-zero, not necessarily a unit. \item \tet{j}: $j$-invariant of the curve. \noindent These are used as follows: \bprog ? E = ellinit([0,0,0, a4,a6]); ? E.b4 %2 = 2*a4 ? E.disc %3 = -64*a4^3 - 432*a6^2 @eprog \subsubsec{Curves over $\R$} This in particular includes curves defined over $\Q$. All member functions in this section return data, as it is currently stored in the structure, if present; and otherwise compute it to the default accuracy, that was fixed \emph{at the time of ellinit} (via a \typ{REAL} $D$ domain argument, or \kbd{realprecision} by default). The function \tet{ellperiods} allows to recompute (and cache) the following data to \emph{current} \kbd{realprecision}. \item \tet{area}: volume of the complex lattice defining $E$. \item \tet{roots} is a vector whose three components contain the complex roots of the right hand side $g(x)$ of the associated $b$-model $Y^2 = g(x)$. If the roots are all real, they are ordered by decreasing value. If only one is real, it is the first component. \item \tet{omega}: $[\omega_1,\omega_2]$, periods forming a basis of the complex lattice defining $E$. The first component $\omega_1$ is the (positive) real period, in other words the integral of $dx/(2y+a_1x+a_3)$ over the connected component of the identity component of $E(\R)$. The second component $\omega_2$ is a complex period, such that $\tau=\dfrac{\omega_1}{\omega_2}$ belongs to Poincar\'e's half-plane (positive imaginary part); not necessarily to the standard fundamental domain. \item \tet{eta} is a row vector containing the quasi-periods $\eta_1$ and $\eta_2$ such that $\eta_i = 2\zeta(\omega_i/2)$, where $\zeta$ is the Weierstrass zeta function associated to the period lattice; see \tet{ellzeta}. In particular, the Legendre relation holds: $\eta_2\omega_1 - \eta_1\omega_2 = 2i\pi$. \misctitle{Warning} As for the orientation of the basis of the period lattice, beware that many sources use the inverse convention where $\omega_2/\omega_1$ has positive imaginary part and our $\omega_2$ is the negative of theirs. Our convention $\tau = \omega_1/\omega_2$ ensures that the action of $\text{PSL}_2$ is the natural one: $$[a,b;c,d]\cdot\tau = (a\tau+b)/(c\tau+d) = (a \omega_1 + b\omega_2)/(c\omega_1 + d\omega_2),$$ instead of a twisted one. (Our $tau$ is $-1/\tau$ in the above inverse convention.) \subsubsec{Curves over $\Q_p$} We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model. For the time being only curves with multiplicative reduction (split or non-split), i.e. $v_p(j) < 0$, are supported by non-trivial functions. In this case the curve is analytically isomorphic to $\bar{\Q}_p^*/q^\Z := E_q(\bar{\Q}_p)$, for some $p$-adic integer $q$ (the Tate period). In particular, we have $j(q) = j(E)$. \item \tet{p} is the residual characteristic \item \tet{roots} is a vector with a single component, equal to the $p$-adic root $e_1$ of the right hand side $g(x)$ of the associated $b$-model $Y^2 = g(x)$. The point $(e_1,0)$ corresponds to $-1 \in \bar{\Q}_p^*/q^\Z$ under the Tate parametrization. \item \tet{tate} returns $[u^2,u,q,[a,b]]$ in the notation of Henniart-Mestre (CRAS t. 308, p.~391--395, 1989): $q$ is as above, $u\in \Q_p(\sqrt{-c_6})$ is such that $\phi^* dx/(2y + a_1x+a3) = u dt/t$, where $\phi: E_q\to E$ is an isomorphism (well defined up to sign) and $dt/t$ is the canonical invariant differential on the Tate curve; $u^2\in\Q_p$ does not depend on $\phi$. (Technicality: if $u\not\in\Q_p$, it is stored as a quadratic \typ{POLMOD}.) Finally, $[a,b]$ satisfy $4u^2 b \cdot \text{agm}(\sqrt{a/b},1)^2 = 1$ as in Theorem~2 (\emph{loc.~cit.}). \subsubsec{Curves over $\F_q$} \item \tet{p} is the characteristic of $\F_q$. \item \tet{no} is $\#E(\F_q)$. \item \tet{cyc} gives the cycle structure of $E(\F_q)$. \item \tet{gen} returns the generators of $E(\F_q)$. \item \tet{group} returns $[\kbd{no},\kbd{cyc},\kbd{gen}]$, i.e. $E(\F_q)$ as an abelian group structure. \subsubsec{Curves over $\Q$} All functions should return a correct result, whether the model is minimal or not, but it is a good idea to stick to minimal models whenever $\gcd(c_4,c_6)$ is easy to factor (minor speed-up). The construction \bprog E = ellminimalmodel(E0, &v) @eprog\noindent replaces the original model $E_0$ by a minimal model $E$, and the variable change $v$ allows to go between the two models: \bprog ellchangepoint(P0, v) ellchangepointinv(P, v) @eprog\noindent respectively map the point $P_0$ on $E_0$ to its image on $E$, and the point $P$ on $E$ to its pre-image on $E_0$. A few routines --- namely \tet{ellgenerators}, \tet{ellidentify}, \tet{ellsearch}, \tet{forell} --- require the optional package \tet{elldata} (John Cremona's database) to be installed. In that case, the function \tet{ellinit} will allow alternative inputs, e.g.~\kbd{ellinit("11a1")}. Functions using this package need to load chunks of a large database in 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) \subsec{ellL1$(e, r)$}\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.) \bprog ? e = ellinit("11a1"); \\ order of vanishing is 0 ? ellL1(e, 0) %2 = 0.2538418608559106843377589233 ? e = ellinit("389a1"); \\ order of vanishing is 2 ? ellL1(e, 0) %4 = -5.384067311837218089235032414 E-29 ? ellL1(e, 1) %5 = 0 ? ellL1(e, 2) %6 = 1.518633000576853540460385214 @eprog\noindent The main use of this function, after computing at \emph{low} accuracy the order of vanishing using \tet{ellanalyticrank}, is to compute the leading term at \emph{high} accuracy to check (or use) the Birch and Swinnerton-Dyer conjecture: \bprog ? \p18 realprecision = 18 significant digits ? ellanalyticrank(ellinit([0, 0, 1, -7, 6])) time = 32 ms. %1 = [3, 10.3910994007158041] ? \p200 realprecision = 202 significant digits (200 digits displayed) ? ellL1(e, 3) time = 23,113 ms. %3 = 10.3910994007158041387518505103609170697263563756570092797@com$[\dots]$ @eprog 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 elliptic curve corresponding to $E$. The library syntax is \fun{GEN}{elladd}{GEN E, GEN z1, GEN z2}. \subsec{ellak$(E,n)$}\kbdsidx{ellak}\label{se:ellak} Computes the coefficient $a_n$ of the $L$-function of the elliptic curve $E/\Q$, i.e.~coefficients of a newform of weight 2 by the modularity theorem (\idx{Taniyama-Shimura-Weil conjecture}). $E$ must be an \var{ell} structure over $\Q$ as output by \kbd{ellinit}. $E$ must be given by an integral model, not necessarily minimal, although a minimal model will make the function faster. \bprog ? E = ellinit([0,1]); ? ellak(E, 10) %2 = 0 ? e = ellinit([5^4,5^6]); \\ not minimal at 5 ? ellak(e, 5) \\ wasteful but works %3 = -3 ? E = ellminimalmodel(e); \\ now minimal ? ellak(E, 5) %5 = -3 @eprog\noindent If the model is not minimal at a number of bad primes, then the function will be slower on those $n$ divisible by the bad primes. The speed should be comparable for other $n$: \bprog ? for(i=1,10^6, ellak(E,5)) time = 820 ms. ? for(i=1,10^6, ellak(e,5)) \\ 5 is bad, markedly slower time = 1,249 ms. ? for(i=1,10^5,ellak(E,5*i)) time = 977 ms. ? for(i=1,10^5,ellak(e,5*i)) \\ still slower but not so much on average time = 1,008 ms. @eprog The library syntax is \fun{GEN}{akell}{GEN E, GEN n}. \subsec{ellan$(E,n)$}\kbdsidx{ellan}\label{se:ellan} Computes the vector of the first $n$ Fourier coefficients $a_k$ corresponding to the elliptic curve $E$. The curve must be given by an integral model, not necessarily minimal, although a minimal model will make the function faster. The library syntax is \fun{GEN}{anell}{GEN E, long n}. Also available is \fun{GEN}{anellsmall}{GEN e, long n}, which returns a \typ{VECSMALL} instead of a \typ{VEC}, saving on memory. \subsec{ellanalyticrank$(e, \{\var{eps}\})$}\kbdsidx{ellanalyticrank}\label{se:ellanalyticrank} 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 \kbd{eps} is zero. If no value of \kbd{eps} is given, a value of half the current precision is used. \bprog ? e = ellinit("11a1"); \\ rank 0 ? ellanalyticrank(e) %2 = [0, 0.2538418608559106843377589233] ? e = ellinit("37a1"); \\ rank 1 ? ellanalyticrank(e) %4 = [1, 0.3059997738340523018204836835] ? e = ellinit("389a1"); \\ rank 2 ? ellanalyticrank(e) %6 = [2, 1.518633000576853540460385214] ? e = ellinit("5077a1"); \\ rank 3 ? ellanalyticrank(e) %8 = [3, 10.39109940071580413875185035] @eprog The library syntax is \fun{GEN}{ellanalyticrank}{GEN e, GEN eps = NULL, long prec}. \subsec{ellap$(E,\{p\})$}\kbdsidx{ellap}\label{se:ellap} Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. This function computes the trace of Frobenius $t$ for the elliptic curve $E$, defined by the equation $\#E(\F_q) = q+1 - t$. If the curve is defined over $\Q$, $p$ must be explicitly given and the function computes the trace of the reduction over $\F_p$. The trace of Frobenius is also the $a_p$ coefficient in the curve $L$-series $L(E,s) = \sum_n a_n n^{-s}$, whence the function name. The equation must be integral at $p$ but need not be minimal at $p$; of course, a minimal model will be more efficient. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellap(E, 7) \\ 7 necessary here %2 = -4 \\ #E(F_7) = 7+1-(-4) = 12 ? ellcard(E, 7) %3 = 12 \\ OK ? E = ellinit([0,1], 11); \\ defined over F_11 ? ellap(E) \\ no need to repeat 11 %4 = 0 ? ellap(E, 11) \\ ... but it also works %5 = 0 ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellap(E,13) *** ^----------- *** ellap: inconsistent moduli in Rg_to_Fp: 11 13 ? Fq = ffgen(ffinit(11,3), 'a); \\ defines F_q := F_{11^3} ? E = ellinit([a+1,a], Fq); \\ y^2 = x^3 + (a+1)x + a, defined over F_q ? ellap(E) %8 = -3 @eprog \misctitle{Algorithms used} If $E/\F_q$ has CM by a principal imaginary 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. 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. The library syntax is \fun{GEN}{bilhell}{GEN E, GEN z1, GEN z2, long prec}. \subsec{ellcard$(E,\{p\})$}\kbdsidx{ellcard}\label{se:ellcard} Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. 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 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. The library syntax is \fun{GEN}{ellcard}{GEN E, GEN p = NULL}. Also available is \fun{GEN}{ellcard}{GEN E, GEN p} where $p$ is not \kbd{NULL}. \subsec{ellchangecurve$(E,v)$}\kbdsidx{ellchangecurve}\label{se:ellchangecurve} Changes the data for the elliptic curve $E$ by changing the coordinates using the vector \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the new coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$. $E$ must be an \var{ell} structure as output by \kbd{ellinit}. The special case $v = 1$ is also used instead of $[1,0,0,0]$ to denote the trivial coordinate change. The library syntax is \fun{GEN}{ellchangecurve}{GEN E, GEN v}. \subsec{ellchangepoint$(x,v)$}\kbdsidx{ellchangepoint}\label{se:ellchangepoint} Changes the coordinates of the point or vector of points $x$ using the vector \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the new coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$ (see also \kbd{ellchangecurve}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] @eprog The library syntax is \fun{GEN}{ellchangepoint}{GEN x, GEN v}. The reciprocal function \fun{GEN}{ellchangepointinv}{GEN x, GEN ch} inverts the coordinate change. \subsec{ellchangepointinv$(x,v)$}\kbdsidx{ellchangepointinv}\label{se:ellchangepointinv} Changes the coordinates of the point or vector of points $x$ using the inverse of the isomorphism associated to \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the old coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$ (inverse of \kbd{ellchangepoint}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] \\ we get back P0 @eprog The library syntax is \fun{GEN}{ellchangepointinv}{GEN x, GEN v}. \subsec{ellconvertname$(\var{name})$}\kbdsidx{ellconvertname}\label{se:ellconvertname} Converts an elliptic curve name, as found in the \tet{elldata} database, from a string to a triplet $[\var{conductor}, \var{isogeny class}, \var{index}]$. It will also convert a triplet back to a curve name. Examples: \bprog ? ellconvertname("123b1") %1 = [123, 1, 1] ? ellconvertname(%) %2 = "123b1" @eprog The library syntax is \fun{GEN}{ellconvertname}{GEN name}. \subsec{elldivpol$(E,n,\{v='x\})$}\kbdsidx{elldivpol}\label{se:elldivpol} $n$-division polynomial $f_n$ for the curve $E$ in the variable $v$. In standard notation, for any affine point $P = (X,Y)$ on the curve, 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][X,Y]$. We have $f_n(X) = \psi_n(X)$ for $n$ odd, and $f_n(X) = \psi_n(X,Y) (2Y + a_1X+a_3)$ for $n$ even. We have $$ f_1 = 1,\quad f_2 = 4X^3 + b_2X^2 + 2b_4 X + b_6, \quad f_3 = 3 X^4 + b_2 X^3 + 3b_4 X^2 + 3 b_6 X + b8, $$ $$ f_4 = f_2(2X^6 + b_2 X^5 + 5b_4 X^4 + 10 b_6 X^3 + 10 b_8 X^2 + (b_2b_8-b_4b_6)X + (b_8b_4 - b_6^2)), \dots $$ For $n \geq 2$, the roots of $f_n$ are the $X$-coordinates of points in $E[n]$. The library syntax is \fun{GEN}{elldivpol}{GEN E, long n, long v = -1}, where \kbd{v} is a variable number. \subsec{elleisnum$(w,k,\{\fl=0\})$}\kbdsidx{elleisnum}\label{se:elleisnum} $k$ being an even positive integer, computes the numerical value of the Eisenstein series of weight $k$ at the lattice $w$, as given by \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), $$ 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 = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit}. \bprog ? w = ellperiods([1,I]); ? elleisnum(w, 4) %2 = 2268.8726415508062275167367584190557607 ? elleisnum(w, 6) %3 = -3.977978632282564763 E-33 ? E = ellinit([1, 0]); ? elleisnum(E, 4, 1) %5 = -47.999999999999999999999999999999999998 @eprog When \fl\ is non-zero and $k=4$ or 6, returns the elliptic invariants $g_2$ or $g_3$, such that $$y^2 = 4x^3 - g_2 x - g_3$$ is a Weierstrass equation for $E$. The library syntax is \fun{GEN}{elleisnum}{GEN w, long k, long flag, long prec}. \subsec{elleta$(w)$}\kbdsidx{elleta}\label{se:elleta} Returns the quasi-periods $[\eta_1,\eta_2]$ associated to the lattice basis $\var{w} = [\omega_1, \omega_2]$. Alternatively, \var{w} can be an elliptic curve $E$ as output by \kbd{ellinit}, in which case, the quasi periods associated to the period lattice basis \kbd{$E$.omega} (namely, \kbd{$E$.eta}) are returned. \bprog ? elleta([1, I]) %1 = [3.141592653589793238462643383, 9.424777960769379715387930149*I] @eprog The library syntax is \fun{GEN}{elleta}{GEN w, long prec}. \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$. The library syntax is \fun{GEN}{ellfromj}{GEN j}. \subsec{ellgenerators$(E)$}\kbdsidx{ellgenerators}\label{se:ellgenerators} If $E$ is an elliptic curve over the rationals, return a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to $E$. This relies on the \tet{elldata} database being installed and referencing the curve, and so is only available for curves over $\Z$ of small conductors. If $E$ is an elliptic curve over a finite field $\F_q$ as output by \tet{ellinit}, return a minimal set of generators for the group $E(\F_q)$. The library syntax is \fun{GEN}{ellgenerators}{GEN E}. \subsec{ellglobalred$(E)$}\kbdsidx{ellglobalred}\label{se:ellglobalred} Calculates the arithmetic conductor, the global minimal model of $E$ and the global \idx{Tamagawa number} $c$. $E$ must be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$. The result is a vector $[N,v,c,F,L]$, where \item $N$ is the arithmetic conductor of the curve, \item $v$ gives the coordinate change for $E$ over $\Q$ to the minimal integral model (see \tet{ellminimalmodel}), \item $c$ is the product of the local Tamagawa numbers $c_p$, a quantity which enters in the \idx{Birch and Swinnerton-Dyer conjecture},\sidx{minimal model} \item $F$ is the factorization of $N$ over $\Z$. \item $L$ is a vector, whose $i$-th entry contains the local data at the $i$-th prime divisor of $N$, i.e. \kbd{L[i] = elllocalred(E,F[i,1])}, where the local coordinate change has been deleted, and replaced by a $0$. The library syntax is \fun{GEN}{ellglobalred}{GEN E}. \subsec{ellgroup$(E,\{p\},\{\fl\})$}\kbdsidx{ellgroup}\label{se:ellgroup} Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. This function computes the structure of the group $E(\F_q) \sim \Z/d_1\Z \times \Z/d_2\Z$, with $d_2\mid d_1$. If the curve is defined over $\Q$, $p$ must be explicitly given and the function computes the structure 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 structure of the (cyclic) group of non-singular points in this case. If the flag is $0$ (default), return $[d_1]$ or $[d_1, d_2]$, if $d_2>1$. If the flag is $1$, return a triple $[h,\var{cyc},\var{gen}]$, where $h$ is the curve cardinality, \var{cyc} gives the group structure as a product of cyclic groups (as per $\fl = 0$). More precisely, if $d_2 > 1$, the output is $[d_1d_2, [d_1,d_2],[P,Q]]$ where $P$ is of order $d_1$ and $[P,Q]$ generates the curve. \misctitle{Caution} It is not guaranteed that $Q$ has order $d_2$, which in the worst case requires an expensive discrete log computation. Only that \kbd{ellweilpairing(E, P, Q, d1)} has order $d_2$. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellgroup(E, 7) %2 = [6, 2] \\ Z/6 x Z/2, non-cyclic ? E = ellinit([0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %4 = [12] ? ellgroup(E, 11) \\ ... but it also works %5 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11 13 ? ellgroup(E, 7, 1) %6 = [12, [6, 2], [[Mod(2, 7), Mod(4, 7)], [Mod(4, 7), Mod(4, 7)]]] @eprog\noindent If $E$ is defined over $\Q$, we allow singular reduction and in this case we return the structure of the group of non-singular points, satisfying $\#E_{ns}(\F_p) = p - a_p$. \bprog ? E = ellinit([0,5]); ? ellgroup(E, 5, 1) %2 = [5, [5], [[Mod(4, 5), Mod(2, 5)]]] ? ellap(E, 5) %3 = 0 \\ additive reduction at 5 ? E = ellinit([0,-1,0,35,0]); ? ellgroup(E, 5, 1) %5 = [4, [4], [[Mod(2, 5), Mod(2, 5)]]] ? ellap(E, 5) %6 = 1 \\ split multiplicative reduction at 5 ? ellgroup(E, 7, 1) %7 = [8, [8], [[Mod(3, 7), Mod(5, 7)]]] ? ellap(E, 7) %8 = -1 \\ non-split multiplicative reduction at 7 @eprog The library syntax is \fun{GEN}{ellgroup0}{GEN E, GEN p = NULL, long flag}. Also available is \fun{GEN}{ellgroup}{GEN E, GEN p}, corresponding to \fl = 0. \subsec{ellheegner$(E)$}\kbdsidx{ellheegner}\label{se:ellheegner} Let $E$ be an elliptic curve over the rationals, assumed to be of (analytic) rank $1$. This returns a non-torsion rational point on the curve, whose canonical height is equal to the product of the elliptic regulator by the analytic Sha. This uses the Heegner point method, described in Cohen GTM 239; the complexity is proportional to the product of the square root of the conductor and the height of the point (thus, it is preferable to apply it to strong Weil curves). \bprog ? E = ellinit([-157^2,0]); ? u = ellheegner(E); print(u[1], "\n", u[2]) 69648970982596494254458225/166136231668185267540804 538962435089604615078004307258785218335/67716816556077455999228495435742408 ? ellheegner(ellinit([0,1])) \\ E has rank 0 ! *** at top-level: ellheegner(E=ellinit *** ^-------------------- *** ellheegner: The curve has even analytic rank. @eprog 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{ellheightmatrix$(E,x)$}\kbdsidx{ellheightmatrix}\label{se:ellheightmatrix} $x$ being a vector of points, this function outputs the Gram matrix of $x$ with respect to the N\'eron-Tate height, in other words, the $(i,j)$ component of the matrix is equal to \kbd{ellbil($E$,x[$i$],x[$j$])}. The rank of this matrix, at least in some approximate sense, gives the rank of the set of points, and if $x$ is a basis of the \idx{Mordell-Weil group} of $E$, its determinant is equal to 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}. \subsec{ellidentify$(E)$}\kbdsidx{ellidentify}\label{se:ellidentify} Look up the elliptic curve $E$, defined by an arbitrary model over $\Q$, in the \tet{elldata} database. Return \kbd{[[N, M, G], C]} where $N$ is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} $E(\Q)$ and $C$ is the change of coordinates change, suitable for \kbd{ellchangecurve}. The library syntax is \fun{GEN}{ellidentify}{GEN E}. \subsec{ellinit$(x,\{D=1\})$}\kbdsidx{ellinit}\label{se:ellinit} Initialize an \tet{ell} structure, associated to the elliptic curve $E$. $E$ is either \item a $5$-component vector $[a_1,a_2,a_3,a_4,a_6]$ defining the elliptic curve with Weierstrass equation $$ Y^2 + a_1 XY + a_3 Y = X^3 + a_2 X^2 + a_4 X + a_6, $$ \item a $2$-component vector $[a_4,a_6]$ defining the elliptic curve with short Weierstrass equation $$ Y^2 = X^3 + a_4 X + a_6, $$ \item a character string in Cremona's notation, e.g. \kbd{"11a1"}, in which case the curve is retrieved from the \tet{elldata} database if available. The optional argument $D$ describes the domain over which the curve is defined: \item the \typ{INT} $1$ (default): the field of rational numbers $\Q$. \item a \typ{INT} $p$, where $p$ is a prime number: the prime finite field $\F_p$. \item an \typ{INTMOD} \kbd{Mod(a, p)}, where $p$ is a prime number: the prime finite field $\F_p$. \item a \typ{FFELT}, as returned by \tet{ffgen}: the corresponding finite field $\F_q$. \item a \typ{PADIC}, $O(p^n)$: the field $\Q_p$, where $p$-adic quantities will be computed to a relative accuracy of $n$ digits. We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model, at the given accuracy. \item a \typ{REAL} $x$: the field $\C$ of complex numbers, where floating 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. 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 raised: \bprog ? ellinit([1 + O(5), 1], O(7)); *** at top-level: ellinit([1+O(5),1],O *** ^-------------------- *** ellinit: inconsistent moduli in ellinit: 7 != 5 @eprog\noindent If the curve coefficients are too general to fit any of the above domain categories, only basic operations, such as point addition, will be supported later. If the curve (seen over the domain $D$) is singular, fail and return an empty vector $[]$. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1, over Q ? E = ellinit([0,1]); \\ the same curve, short form ? E = ellinit("36a1"); \\ sill the same curve, Cremona's notations ? E = ellinit([0,1], 2) \\ over F2: singular curve %4 = [] ? E = ellinit(['a4,'a6] * Mod(1,5)); \\ over F_5[a4,a6], basic support ! @eprog\noindent The result of \tet{ellinit} is an \tev{ell} structure. It contains at least the following information in its components: % $$ a_1,a_2,a_3,a_4,a_6,b_2,b_4,b_6,b_8,c_4,c_6,\Delta,j.$$ % All are accessible via member functions. In particular, the discriminant is \kbd{$E$.disc}, and the $j$-invariant is \kbd{$E$.j}. \bprog ? E = ellinit([a4, a6]); ? E.disc %2 = -64*a4^3 - 432*a6^2 ? E.j %3 = -6912*a4^3/(-4*a4^3 - 27*a6^2) @eprog Further components contain domain-specific data, which are in general dynamic: only computed when needed, and then cached in the structure. \bprog ? E = ellinit([2,3], 10^60+7); \\ E over F_p, p large ? ellap(E) time = 4,440 ms. %2 = -1376268269510579884904540406082 ? ellcard(E); \\ now instantaneous ! time = 0 ms. ? ellgenerators(E); time = 5,965 ms. ? ellgenerators(E); \\ second time instantaneous time = 0 ms. @eprog See the description of member functions related to elliptic curves at the beginning of this section. The library syntax is \fun{GEN}{ellinit}{GEN x, GEN D = NULL, long prec}. \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 take this into account, i.e.~an imprecise equality is checked, not a precise one. It is allowed for $z$ to be a vector of points in which case a vector (of the same type) is returned. 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{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 $p$-adic number with positive valuation. 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$. 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: 1 means good reduction (type I$_0$), 2, 3 and 4 mean types II, III and IV respectively, $4+\nu$ with $\nu>0$ means type I$_\nu$; finally the opposite values $-1$, $-2$, etc.~refer to the starred types I$_0^*$, II$^*$, etc. The third component $v$ is itself a vector $[u,r,s,t]$ 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$. The library syntax is \fun{GEN}{elllocalred}{GEN E, GEN p}. \subsec{elllog$(E,P,G,\{o\})$}\kbdsidx{elllog}\label{se:elllog} Given two points $P$ and $G$ on the elliptic curve $E/\F_q$, returns the discrete logarithm of $P$ in base $G$, i.e. the smallest non-negative integer $n$ such that $P = [n]G$. See \tet{znlog} for the limitations of the underlying discrete log algorithms. If present, $o$ represents the order of $G$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where $N$ is the order of $G$. If no $o$ is given, assume that $G$ generates the curve. The function also assumes that $P$ is a multiple of $G$. \bprog ? a = ffgen(ffinit(2,8),'a); ? E = ellinit([a,1,0,0,1]); \\ over F_{2^8} ? x = a^3; y = ellordinate(E,x)[1]; ? P = [x,y]; G = ellmul(E, P, 113); ? ord = [242, factor(242)]; \\ P generates a group of order 242. Initialize. ? ellorder(E, G, ord) %4 = 242 ? e = elllog(E, P, G, ord) %5 = 15 ? ellmul(E,G,e) == P %6 = 1 @eprog The library syntax is \fun{GEN}{elllog}{GEN E, GEN P, GEN G, GEN o = NULL}. \subsec{elllseries$(E,s,\{A=1\})$}\kbdsidx{elllseries}\label{se:elllseries} $E$ being an elliptic curve, given by an arbitrary model over $\Q$ as output by \kbd{ellinit}, this function computes the value of the $L$-series of $E$ at the (complex) point $s$. This function uses an $O(N^{1/2})$ algorithm, where $N$ is the conductor. The optional parameter $A$ fixes a cutoff point for the integral and is best left omitted; the result must be independent of $A$, up to \kbd{realprecision}, so this allows to check the function's accuracy. The library syntax is \fun{GEN}{elllseries}{GEN E, GEN s, GEN A = NULL, long prec}. \subsec{ellminimalmodel$(E,\{\&v\})$}\kbdsidx{ellminimalmodel}\label{se:ellminimalmodel} Return the standard minimal integral model of the rational elliptic curve $E$. If present, sets $v$ to the corresponding change of variables, which is a vector $[u,r,s,t]$ with rational components. The return value is identical to that of \kbd{ellchangecurve(E, v)}. The resulting model has integral coefficients, is everywhere minimal, $a_1$ is 0 or 1, $a_2$ is 0, 1 or $-1$ and $a_3$ is 0 or 1. Such a model is unique, and the vector $v$ is unique if we specify that $u$ is positive, which we do. \sidx{minimal model} The library syntax is \fun{GEN}{ellminimalmodel}{GEN E, GEN *v = NULL}. \subsec{ellmodulareqn$(N,\{x\},\{y\})$}\kbdsidx{ellmodulareqn}\label{se:ellmodulareqn} Return a vector [\kbd{eqn},$t$] where \kbd{eqn} is a modular equation of level $N$, i.e.~a bivariate polynomial with integer coefficients; $t$ indicates the type of this equation: either \emph{canonical} ($t = 0$) or \emph{Atkin} ($t = 1$). This function currently requires the package \kbd{seadata} to be installed and is limited to $N<500$, $N$ prime. Let $j$ be the $j$-invariant function. The polynomial \kbd{eqn} satisfies the following functional equation, which allows to compute the values of the classical modular polynomial $\Phi_N$ of prime level $N$, such that $\Phi_N(j(\tau), j(N\tau)) = 0$, while being much smaller than the latter: \item for canonical type: $P(f(\tau),j(\tau)) = P(N^s/f(\tau),j(N\*\tau)) = 0$, where $s = 12/\gcd(12,N-1)$; \item for Atkin type: $P(f(\tau),j(\tau)) = P(f(\tau),j(N\*\tau)) = 0$. \noindent In both cases, $f$ is a suitable modular function (see below). The following GP function returns values of the classical modular polynomial by eliminating $f(\tau)$ in the above two equations, for $N\leq 31$ or $N\in\{41,47,59,71\}$. \bprog classicaleqn(N, X='X, Y='Y)= { my(E=ellmodulareqn(N), P=E[1], t=E[2], Q, d); if(poldegree(P,'y)>2,error("level unavailable in classicaleqn")); if (t == 0, my(s = 12/gcd(12,N-1)); Q = 'x^(N+1) * substvec(P,['x,'y],[N^s/'x,Y]); d = N^(s*(2*N+1)) * (-1)^(N+1); , Q = subst(P,'y,Y); d = (X-Y)^(N+1)); polresultant(subst(P,'y,X), Q) / d; } @eprog More precisely, let $W_N(\tau)={{-1}\over{N\*\tau}}$ be the Atkin-Lehner involution; we have $j(W_N(\tau)) = j(N\*\tau)$ and the function $f$ also satisfies: \item for canonical type: $f(W_N(\tau)) = N^s/f(\tau)$; \item for Atkin type: $f(W_N(\tau)) = f(\tau)$. \noindent Furthermore, for an equation of canonical type, $f$ is the standard $\eta$-quotient $$f(\tau) = N^s \* \big(\eta(N\*\tau) / \eta(\tau) \big)^{2\*s},$$ where $\eta$ is Dedekind's eta function, which is invariant under $\Gamma_0(N)$. The library syntax is \fun{GEN}{ellmodulareqn}{long N, long x = -1, long y = -1}, where \kbd{x}, \kbd{y} are variable numbers. \subsec{ellmul$(E,z,n)$}\kbdsidx{ellmul}\label{se:ellmul} Computes $[n]z$, where $z$ is a point on the elliptic curve $E$. The exponent $n$ is in $\Z$, or may be a complex quadratic integer if the curve $E$ has complex multiplication by $n$ (if not, an error message is issued). \bprog ? Ei = ellinit([1,0]); z = [0,0]; ? ellmul(Ei, z, 10) %2 = [0] \\ unsurprising: z has order 2 ? ellmul(Ei, z, I) %3 = [0, 0] \\ Ei has complex multiplication by Z[i] ? ellmul(Ei, z, quadgen(-4)) %4 = [0, 0] \\ an alternative syntax for the same query ? Ej = ellinit([0,1]); z = [-1,0]; ? ellmul(Ej, z, I) *** at top-level: ellmul(Ej,z,I) *** ^-------------- *** ellmul: not a complex multiplication in ellmul. ? ellmul(Ej, z, 1+quadgen(-3)) %6 = [1 - w, 0] @eprog The simple-minded algorithm for the CM case assumes that we are in characteristic $0$, and that the quadratic order to which $n$ belongs has small discriminant. The library syntax is \fun{GEN}{ellmul}{GEN E, GEN z, GEN n}. \subsec{ellneg$(E,z)$}\kbdsidx{ellneg}\label{se:ellneg} Opposite of the point $z$ on elliptic curve $E$. The library syntax is \fun{GEN}{ellneg}{GEN E, GEN z}. \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. \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 ? E = ellinit(ellfromj(ffgen(5^10))); ? ellcard(E) %5 = 9762580 ? P = random(E); ellorder(E, P) %6 = 4881290 ? p = 2^160+7; E = ellinit([1,2], p); ? N = ellcard(E) %8 = 1461501637330902918203686560289225285992592471152 ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E))) time = 260 ms. @eprog The parameter $o$, is now mostly useless, and kept for backward compatibility. If present, it represents a non-zero multiple of the order of $z$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the cardinality of the curve. It is no longer needed since PARI is now able to compute it over large finite fields (was restricted to small prime fields at the time this feature was introduced), \emph{and} caches the result in $E$ so that it is computed and factored only once. Modifying the last example, we see that including this extra parameter provides no improvement: \bprog ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E),o)) time = 260 ms. @eprog The library syntax is \fun{GEN}{ellorder}{GEN E, GEN z, GEN o = NULL}. The obsolete form \fun{GEN}{orderell}{GEN e, GEN z} should no longer be used. \subsec{ellordinate$(E,x)$}\kbdsidx{ellordinate}\label{se:ellordinate} Gives a 0, 1 or 2-component vector containing the $y$-coordinates of the points of the curve $E$ having $x$ as $x$-coordinate. The library syntax is \fun{GEN}{ellordinate}{GEN E, GEN x, long prec}. \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 the same lattice such that $\tau := W_1/W_2$ has positive imaginary part and lies in the standard fundamental domain for $\text{SL}_2(\Z)$. If $\fl = 1$, the function returns $[[W_1,W_2], [\eta_1,\eta_2]]$, where $\eta_1$ and $\eta_2$ are the quasi-periods associated to $[W_1,W_2]$, satisfying $\eta_1 W_2 - \eta_2 W_1 = 2 i \pi$. The output of this function is meant to be used as the first argument given to ellwp, ellzeta, ellsigma or elleisnum. Quasi-periods are needed by ellzeta and ellsigma only. The library syntax is \fun{GEN}{ellperiods}{GEN w, long flag , long prec}. \subsec{ellpointtoz$(E,P)$}\kbdsidx{ellpointtoz}\label{se:ellpointtoz} If $E/\C \simeq \C/\Lambda$ is a complex elliptic curve ($\Lambda = \kbd{E.omega}$), computes a complex number $z$, well-defined modulo the lattice $\Lambda$, corresponding to the point $P$; i.e.~such that $P = [\wp_\Lambda(z),\wp'_\Lambda(z)]$ satisfies the equation $$y^2 = 4x^3 - g_2 x - g_3,$$ where $g_2$, $g_3$ are the elliptic invariants. If $E$ is defined over $\R$ and $P\in E(\R)$, we have more precisely, $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$, where $(w1,w2)$ are the real and complex periods of $E$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [6.372367644529809109 E-58, 7.646841173435770930 E-57] ? ellpointtoz(E, [0]) \\ the point at infinity %5 = 0 @eprog If $E/\Q_p$ has multiplicative reduction, then $E/\bar{\Q_p}$ is analytically isomorphic to $\bar{\Q}_p^*/q^\Z$ (Tate curve) for some $p$-adic integer $q$. The behaviour is then as follows: \item If the reduction is split ($E.\kbd{tate[2]}$ is a \typ{PADIC}), we have an isomorphism $\phi: E(\Q_p) \simeq \Q_p^*/q^\Z$ and the function returns $\phi(P)\in \Q_p$. \item If the reduction is \emph{not} split ($E.\kbd{tate[2]}$ is a \typ{POLMOD}), we only have an isomorphism $\phi: E(K) \simeq K^*/q^\Z$ over the unramified quadratic extension $K/\Q_p$. In this case, the output $\phi(P)\in K$ is a \typ{POLMOD}. \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); P = [0,0]; ? [u2,u,q] = E.tate; type(u) \\ split multiplicative reduction %2 = "t_PADIC" ? ellmul(E, P, 5) \\ P has order 5 %3 = [0] ? z = ellpointtoz(E, [0,0]) %4 = 3 + 11^2 + 2*11^3 + 3*11^4 + O(11^5) ? z^5 %5 = 1 + O(11^5) ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ t_POLMOD of t_POL with t_PADIC coeffs ? liftint(z) \\ lift all p-adics %8 = Mod(8*u + 7, u^2 + 437) @eprog The library syntax is \fun{GEN}{zell}{GEN E, GEN P, long prec}. \subsec{ellpow$(E,z,n)$}\kbdsidx{ellpow}\label{se:ellpow} Deprecated alias for \kbd{ellmul}. The library syntax is \fun{GEN}{ellmul}{GEN E, GEN z, GEN n}. \subsec{ellrootno$(E,\{p\})$}\kbdsidx{ellrootno}\label{se:ellrootno} $E$ being an \var{ell} structure over $\Q$ as output by \kbd{ellinit}, this function computes the local root number of its $L$-series at the place $p$ (at the infinite place if $p = 0$). If $p$ is omitted, return the global root number. Note that the global root number is the sign of the functional equation and conjecturally is the parity of the rank of the \idx{Mordell-Weil group}. The equation for $E$ needs not be minimal at $p$, but if the model is already minimal the function will run faster. The library syntax is \fun{long}{ellrootno}{GEN E, GEN p = NULL}. \subsec{ellsearch$(N)$}\kbdsidx{ellsearch}\label{se:ellsearch} This function finds all curves in the \tet{elldata} database satisfying the constraint defined by the argument $N$: \item if $N$ is a character string, it selects a given curve, e.g. \kbd{"11a1"}, or curves in the given isogeny class, e.g. \kbd{"11a"}, or curves with given conductor, e.g. \kbd{"11"}; \item if $N$ is a vector of integers, it encodes the same constraints as the character string above, according to the \tet{ellconvertname} correspondance, e.g. \kbd{[11,0,1]} for \kbd{"11a1"}, \kbd{[11,0]} for \kbd{"11a"} and \kbd{[11]} for \kbd{"11"}; \item if $N$ is an integer, curves with conductor $N$ are selected. If $N$ is a full curve name, e.g. \kbd{"11a1"} or \kbd{[11,0,1]}, the output format is $[N, [a_1,a_2,a_3,a_4,a_6], G]$ where $[a_1,a_2,a_3,a_4,a_6]$ are the coefficients of the Weierstrass equation of the curve and $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to the curve. \bprog ? ellsearch("11a3") %1 = ["11a3", [0, -1, 1, 0, 0], []] ? ellsearch([11,0,3]) %2 = ["11a3", [0, -1, 1, 0, 0], []] @eprog\noindent If $N$ is not a full curve name, then the output is a vector of all matching curves in the above format: \bprog ? ellsearch("11a") %1 = [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], []], ["11a3", [0, -1, 1, 0, 0], []]] ? ellsearch("11b") %2 = [] @eprog The library syntax is \fun{GEN}{ellsearch}{GEN N}. Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only accepts complete curve names (as \typ{STR}). \subsec{ellsigma$(L,\{z='x\},\{\fl=0\})$}\kbdsidx{ellsigma}\label{se:ellsigma} Computes the value at $z$ of the Weierstrass $\sigma$ function attached to the lattice $L$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \sigma(z, L) = z \prod_{\omega\in L^*} \left(1 - \dfrac{z}{\omega}\right)e^{\dfrac{z}{\omega} + \dfrac{z^2}{2\omega^2}}.$$ It is also possible to directly input $L = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($L = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I], 1); ? ellsigma(w, 1/2) %2 = 0.47494937998792065033250463632798296855 ? E = ellinit([1,0]); ? ellsigma(E) \\ at 'x, implicitly at default seriesprecision %4 = x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17) @eprog If $\fl=1$, computes an arbitrary determination of $\log(\sigma(z))$. The library syntax is \fun{GEN}{ellsigma}{GEN L, GEN z = NULL, long flag, long prec}. \subsec{ellsub$(E,\var{z1},\var{z2})$}\kbdsidx{ellsub}\label{se:ellsub} Difference of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. The library syntax is \fun{GEN}{ellsub}{GEN E, GEN z1, GEN z2}. \subsec{elltaniyama$(E, \{d = \var{seriesprecision}\})$}\kbdsidx{elltaniyama}\label{se:elltaniyama} Computes the modular parametrization of the elliptic curve $E/\Q$, where $E$ is an \var{ell} structure as output by \kbd{ellinit}. This returns a two-component vector $[u,v]$ of power series, given to $d$ significant terms (\tet{seriesprecision} by default), characterized by the following two properties. First the point $(u,v)$ satisfies the equation of the elliptic curve. Second, let $N$ be the conductor of $E$ and $\Phi: X_0(N)\to E$ be a modular parametrization; the pullback by $\Phi$ of the N\'eron differential $du/(2v+a_1u+a_3)$ is equal to $2i\pi f(z)dz$, a holomorphic differential form. The variable used in the power series for $u$ and $v$ is $x$, which is implicitly understood to be equal to $\exp(2i\pi z)$. The algorithm assumes that $E$ is a \emph{strong} \idx{Weil curve} and that the Manin constant is equal to 1: in fact, $f(x) = \sum_{n > 0} \kbd{ellan}(E, n) x^n$. The library syntax is \fun{GEN}{elltaniyama}{GEN E, long precdl}. \subsec{elltatepairing$(E, P, Q, m)$}\kbdsidx{elltatepairing}\label{se:elltatepairing} Computes the Tate pairing of the two points $P$ and $Q$ on the elliptic 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$. \bprog ? E = ellinit([-1,0]); ? elltors(E) %1 = [4, [2, 2], [[0, 0], [1, 0]]] @eprog 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)}. \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$ on the elliptic curve $E$. The library syntax is \fun{GEN}{ellweilpairing}{GEN E, GEN P, GEN Q, GEN m}. \subsec{ellwp$(w,\{z='x\},\{\fl=0\})$}\kbdsidx{ellwp}\label{se:ellwp} Computes the value at $z$ of the Weierstrass $\wp$ function attached to the lattice $w$ as given by \tet{ellperiods}. It is also possible to directly input $w = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I]); ? ellwp(w, 1/2) %2 = 6.8751858180203728274900957798105571978 ? E = ellinit([1,1]); ? ellwp(E, 1/2) %4 = 3.9413112427016474646048282462709151389 @eprog\noindent One can also compute the series expansion around $z = 0$: \bprog ? E = ellinit([1,0]); ? ellwp(E) \\ 'x implicitly at default seriesprecision %5 = x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14) ? ellwp(E, x + O(x^12)) \\ explicit precision %6 = x^-2 - 1/5*x^2 + 1/75*x^6 + O(x^9) @eprog Optional \fl\ means 0 (default): compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. The library syntax is \fun{GEN}{ellwp0}{GEN w, GEN z = NULL, long flag, long prec}. For $\fl = 0$, we also have \fun{GEN}{ellwp}{GEN w, GEN z, long prec}, and \fun{GEN}{ellwpseries}{GEN E, long v, long precdl} for the power series in variable $v$. \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 is useful, otherwise there are recomputed from scratch for each new $z$. $$ \zeta(z, L) = \dfrac{1}{z} + z^2\sum_{\omega\in L^*} \dfrac{1}{\omega^2(z-\omega)}.$$ It is also possible to directly input $w = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). The quasi-periods of $\zeta$, such that $$\zeta(z + a\omega_1 + b\omega_2) = \zeta(z) + a\eta_1 + b\eta_2 $$ for integers $a$ and $b$ are obtained as $\eta_i = 2\zeta(\omega_i/2)$. Or using directly \tet{elleta}. \bprog ? w = ellperiods([1,I],1); ? ellzeta(w, 1/2) %2 = 1.5707963267948966192313216916397514421 ? E = ellinit([1,0]); ? ellzeta(E, E.omega[1]/2) %4 = 0.84721308479397908660649912348219163647 @eprog\noindent One can also compute the series expansion around $z = 0$ (the quasi-periods are useless in this case): \bprog ? E = ellinit([0,1]); ? ellzeta(E) \\ at 'x, implicitly at default seriesprecision %4 = x^-1 + 1/35*x^5 - 1/7007*x^11 + O(x^15) ? ellzeta(E, x + O(x^20)) \\ explicit precision %5 = x^-1 + 1/35*x^5 - 1/7007*x^11 + 1/1440257*x^17 + O(x^18) @eprog\noindent The library syntax is \fun{GEN}{ellzeta}{GEN w, GEN z = NULL, long prec}. \subsec{ellztopoint$(E,z)$}\kbdsidx{ellztopoint}\label{se:ellztopoint} $E$ being an \var{ell} as output by \kbd{ellinit}, computes the coordinates $[x,y]$ on the curve $E$ corresponding to the complex number $z$. Hence this is the inverse function of \kbd{ellpointtoz}. In other words, if the curve is put in Weierstrass form $y^2 = 4x^3 - g_2x - g_3$, $[x,y]$ represents the Weierstrass $\wp$-function\sidx{Weierstrass $\wp$-function} and its derivative. More precisely, we have $$x = \wp(z) - b_2/12,\quad y = \wp'(z) - (a_1 x + a_3)/2.$$ If $z$ is in the lattice defining $E$ over $\C$, the result is the point at infinity $[0]$. The library syntax is \fun{GEN}{pointell}{GEN E, GEN z, long prec}. \subsec{genus2red$(Q,P,\{p\})$}\kbdsidx{genus2red}\label{se:genus2red} Let $Q,P$ be polynomials 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 special fiber $X_p$ of the minimal regular model $X$ of $C$ over $\Z$.) 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/}. \misctitle{CAVEAT} The function interface may change: for the time being, it returns $[N,\var{FaN}, T, V]$ where $N$ is either the local conductor at $p$ or the global conductor, \var{FaN} is its factorization, $y^2 = T$ defines a minimal model over $\Z[1/2]$ and $V$ describes the reduction type at the various considered~$p$. Unfortunately, the program is not complete for $p = 2$, and we may return the odd part of the conductor only: this is the case if the factorization includes the (impossible) term $2^{-1}$; if the factorization contains another power of $2$, then this is the exact local conductor at $2$ and $N$ is the global conductor. \bprog ? default(debuglevel, 1); ? genus2red(0,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, []], ["[III{9}] page 184", [3, 3]]]] ? [N, FaN, T, V] = genus2red(x^3-x^2-1, x^2-x); \\ X_1(13), global reduction p = 13 (potential) stable reduction: [5, [Mod(0, 13), Mod(0, 13)]] reduction at p: [I{0}-II-0] page 159, [], f = 2 ? N %3 = 169 ? FaN %4 = Mat([13, 2]) \\ in particular, good reduction at 2 ! ? T %5 = x^6 + 58*x^5 + 1401*x^4 + 18038*x^3 + 130546*x^2 + 503516*x + 808561 ? V %6 = [[13, [5, [Mod(0, 13), Mod(0, 13)]], ["[I{0}-II-0] page 159", []]]] @eprog\noindent We now first describe the format of the vector $V = V_p$ in the case where $p$ was specified (local reduction at~$p$): it is a triple $[p, \var{stable}, \var{red}]$. The component $\var{stable} = [\var{type}, \var{vecj}]$ contains information about the stable reduction after a field extension; depending on \var{type}s, the stable reduction is \item 1: smooth (i.e. the curve has potentially good reduction). The Jacobian $J(C)$ has potentially good reduction. \item 2: an elliptic curve $E$ with an ordinary double point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 3: a projective line with two ordinary double points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 4: the union of two projective lines crossing transversally at three points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 5: the union of two elliptic curves $E_1$ and $E_2$ intersecting transversally at one point; \var{vecj} contains their modular invariants $j_1$ and $j_2$, which may live in a quadratic extension of $\F_p$ are need not be distinct. The Jacobian $J(C)$ has potentially good reduction, isomorphic to the product of the reductions of $E_1$ and $E_2$. \item 6: the union of an elliptic curve $E$ and a projective line which has an ordinary double point, and these two components intersect transversally at one point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 7: as in type 6, but the two components are both singular. The Jacobian $J(C)$ has potentially multiplicative reduction. The component $\var{red} = [\var{NUtype}, \var{neron}]$ contains two data concerning the reduction at $p$ without any ramified field extension. The \var{NUtype} is a \typ{STR} describing the reduction at $p$ of $C$, following Namikawa-Ueno, \emph{The complete classification of fibers in pencils of curves of genus two}, Manuscripta Math., vol. 9, (1973), pages 143-186. The reduction symbol is followed by the corresponding page number in this article. The second datum \var{neron} is the group of connected components (over an algebraic closure of $\F_p$) of the N\'eron model of $J(C)$, given as a finite abelian group (vector of elementary divisors). \smallskip If $p = 2$, the \var{red} component may be omitted altogether (and replaced by \kbd{[]}, in the case where the program could not compute it. When $p$ was not specified, $V$ is the vector of all $V_p$, for all considered $p$. \misctitle{Notes about Namikawa-Ueno types} \item A lower index is denoted between braces: for instance, \kbd{[I\obr 2\cbr-II-5]} means \kbd{[I\_2-II-5]}. \item If $K$ and $K'$ are Kodaira symbols for singular fibers of elliptic curves, \kbd{[$K$-$K'$-m]} and \kbd{[$K'$-$K$-m]} are the same. \item \kbd{[$K$-$K'$-$-1$]} is \kbd{[$K'$-$K$-$\alpha$]} in the notation of Namikawa-Ueno. \item The figure \kbd{[2I\_0-m]} in Namikawa-Ueno, page 159, must be denoted by \kbd{[2I\_0-(m+1)]}. The library syntax is \fun{GEN}{genus2red}{GEN Q, GEN P, GEN p = NULL}. %SECTION: elliptic_curves \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). \subsec{Number field structures} Let $K = \Q[X] / (T)$ a number field, $\Z_K$ its ring of integers, $T\in\Z[X]$ is monic. Three basic number field structures can be associated to $K$ in GP: \item $\tev{nf}$ denotes a number field, i.e.~a data structure output by \tet{nfinit}. This contains the basic arithmetic data associated to the number field: signature, maximal order (given by a basis \kbd{nf.zk}), discriminant, defining polynomial $T$, etc. \item $\tev{bnf}$ denotes a ``Buchmann's number field'', i.e.~a data structure output by \tet{bnfinit}. This contains $\var{nf}$ and the deeper invariants of the field: units $U(K)$, class group $\Cl(K)$, as well as technical data required to solve the two associated discrete logarithm problems. \item $\tev{bnr}$ denotes a ``ray number field'', i.e.~a data structure output by \kbd{bnrinit}, corresponding to the ray class group structure of the field, for some modulus $f$. It contains a \var{bnf}, the modulus $f$, the ray class group $\Cl_f(K)$ and data associated to the discrete logarithm problem therein. \subsec{Algebraic numbers and ideals} \noindent An \tev{algebraic number} belonging to $K = \Q[X]/(T)$ is given as \item a \typ{INT}, \typ{FRAC} or \typ{POL} (implicitly modulo $T$), or \item a \typ{POLMOD} (modulo $T$), or \item a \typ{COL}~\kbd{v} of dimension $N = [K:\Q]$, representing the element in terms of the computed integral basis, as \kbd{sum(i = 1, N,~v[i] * nf.zk[i])}. Note that a \typ{VEC} will not be recognized. \medskip \noindent An \tev{ideal} is given in any of the following ways: \item an algebraic number in one of the above forms, defining a principal ideal. \item a prime ideal, i.e.~a 5-component vector in the format output by \kbd{idealprimedec} or \kbd{idealfactor}. \item a \typ{MAT}, square and in Hermite Normal Form (or at least upper triangular with non-negative coefficients), whose columns represent a $\Z$-basis of the ideal. One may use \kbd{idealhnf} to convert any ideal to the last (preferred) format. \item an \emph{extended ideal} \sidx{ideal (extended)} is a 2-component vector $[I, t]$, where $I$ is an ideal as above and $t$ is an algebraic number, representing the ideal $(t)I$. This is useful whenever \tet{idealred} is involved, implicitly working in the ideal class group, while keeping track of principal ideals. Ideal operations suitably update the principal part when it makes sense (in a multiplicative context), e.g.~using \kbd{idealmul} on $[I,t]$, $[J,u]$, we obtain $[IJ, tu]$. When it does not make sense, the extended part is silently discarded, e.g.~using \kbd{idealadd} with the above input produces $I+J$. The ``principal part'' $t$ in an extended ideal may be represented in any of the above forms, and \emph{also} as a factorization matrix (in terms of number field elements, not ideals!), possibly the empty matrix \kbd{[;]} representing $1$. In the latter case, elements stay in factored form, or \tev{famat} for \emph{fa}ctorization \emph{mat}rix, which is a convenient way to avoid coefficient explosion. To recover the conventional expanded form, try \tet{nffactorback}; but many functions already accept \var{famat}s as input, for instance \tet{ideallog}, so expanding huge elements should never be necessary. \subsec{Finite abelian groups} A finite abelian group $G$ in user-readable format is given by its Smith Normal Form as a pair $[h,d]$ or triple $[h,d,g]$. Here $h$ is the cardinality of $G$, $(d_i)$ is the vector of elementary divisors, and $(g_i)$ is a vector of generators. In short, $G = \oplus_{i\leq n} (\Z/d_i\Z) g_i$, with $d_n \mid \dots \mid d_2 \mid d_1$ and $\prod d_i = h$. This information can also be retrieved as $G.\kbd{no}$, $G.\kbd{cyc}$ and $G.\kbd{gen}$. \item a \tev{character} on the abelian group $\oplus (\Z/d_i\Z) g_i$ is given by a row vector $\chi = [a_1,\ldots,a_n]$ such that $\chi(\prod g_i^{n_i}) = \exp(2i\pi\sum a_i n_i / d_i)$. \item given such a structure, a \tev{subgroup} $H$ is input as a square matrix in HNF, whose columns express generators of $H$ on the given generators $g_i$. Note that the determinant of that matrix is equal to the index $(G:H)$. \subsec{Relative extensions} We now have a look at data structures associated to relative extensions of number fields $L/K$, and to projective $\Z_K$-modules. When defining a relative extension $L/K$, the $\var{nf}$ associated to the base field $K$ must be defined by a variable having a lower priority (see \secref{se:priority}) than the variable defining the extension. For example, you may use the variable name $y$ to define the base field $K$, and $x$ to define the relative extension $L/K$. \subsubsec{Basic definitions}\label{se:ZKmodules} \item $\tev{rnf}$ denotes a relative number field, i.e.~a data structure output by \kbd{rnfinit}, associated to the extension $L/K$. The \var{nf} associated to be base field $K$ is \kbd{rnf.nf}. \item A \emph{relative matrix} is an $m\times n$ matrix whose entries are elements of $K$, in any form. Its $m$ columns $A_j$ represent elements in $K^n$. \item An \tev{ideal list} is a row vector of fractional ideals of the number field $\var{nf}$. \item A \tev{pseudo-matrix} is a 2-component row vector $(A,I)$ where $A$ is a relative $m\times n$ matrix and $I$ an ideal list of length $n$. If $I = \{{\Bbb a}_1,\dots, {\Bbb a}_n\}$ and the columns of $A$ are $(A_1,\dots, A_n)$, this data defines the torsion-free (projective) $\Z_K$-module ${\Bbb a}_1 A_1\oplus {\Bbb a}_n A_n$. \item An \tev{integral pseudo-matrix} is a 3-component row vector w$(A,I,J)$ where $A = (a_{i,j})$ is an $m\times n$ relative matrix and $I = ({\Bbb b}_1,\dots, {\Bbb b}_m)$, $J = ({\Bbb a}_1,\dots, {\Bbb a}_n)$ are ideal lists, such that $a_{i,j} \in {\Bbb b}_i {\Bbb a}_j^{-1}$ for all $i,j$. This data defines two abstract projective $\Z_K$-modules $N = {\Bbb a_1}\omega_1\oplus \cdots\oplus {\Bbb a_n}\omega_n $ in $K^n$, $P = {\Bbb b_1}\eta_1\oplus \cdots\oplus {\Bbb b_m}\eta_m$ in $K^m$, and a $\Z_K$-linear map $f:N\to P$ given by $$ f(\sum \alpha_j\omega_j) = \sum_i \Big(a_{i,j}\alpha_j\Big) \eta_i.$$ This data defines the $\Z_K$-module $M = P/f(N)$. \item Any \emph{projective} $\Z_K$-module\varsidx{projective module} $M$ of finite type in $K^m$ can be given by a pseudo matrix $(A,I)$. \item An arbitrary $\Z_K$ modules of finite type in $K^m$, with non-trivial torsion, is given by an integral pseudo-matrix $(A,I,J)$ \subsubsec{Pseudo-bases, determinant} \item The pair $(A,I)$ is a \tev{pseudo-basis} of the module it generates if the ${\Bbb a_j}$ are non-zero, and the $A_j$ are $K$-linearly independent. We call $n$ the \emph{size} of the pseudo-basis. If $A$ is a relative matrix, the latter condition means it is square with non-zero determinant; we say that it is in Hermite Normal Form\sidx{Hermite normal form} (HNF) if it is upper triangular and all the elements of the diagonal are equal to 1. \item For instance, the relative integer basis \kbd{rnf.zk} is a pseudo-basis $(A,I)$ of $\Z_L$, where $A = \kbd{rnf.zk[1]}$ is a vector of elements of $L$, which are $K$-linearly independent. Most \var{rnf} routines return and handle $\Z_K$-modules contained in $L$ (e.g.~$\Z_L$-ideals) via a pseudo-basis $(A',I')$, where $A'$ is a relative matrix representing a vector of elements of $L$ in terms of the fixed basis \kbd{rnf.zk[1]} \item The \emph{determinant} of a pseudo-basis $(A,I)$ is the ideal equal to the product of the determinant of $A$ by all the ideals of $I$. The determinant of a pseudo-matrix is the determinant of any pseudo-basis of the module it generates. \subsec{Class field theory}\label{se:CFT} A $\tev{modulus}$, in the sense of class field theory, is a divisor supported on the non-complex places of $K$. In PARI terms, this means either an ordinary ideal $I$ as above (no Archimedean component), or a pair $[I,a]$, where $a$ is a vector with $r_1$ $\{0,1\}$-components, corresponding to the infinite part of the divisor. More precisely, the $i$-th component of $a$ corresponds to the real embedding associated to the $i$-th real root of \kbd{K.roots}. (That ordering is not canonical, but well defined once a defining polynomial for $K$ is chosen.) For instance, \kbd{[1, [1,1]]} is a modulus for a real quadratic field, allowing ramification at any of the two places at infinity, and nowhere else. A \tev{bid} or ``big ideal'' is a structure output by \kbd{idealstar} needed to compute in $(\Z_K/I)^*$, where $I$ is a modulus in the above sense. It is a finite abelian group as described above, supplemented by technical data needed to solve discrete log problems. Finally we explain how to input ray number fields (or \var{bnr}), using class field theory. These are defined by a triple $A$, $B$, $C$, where the defining set $[A,B,C]$ can have any of the following forms: $[\var{bnr}]$, $[\var{bnr},\var{subgroup}]$, $[\var{bnf},\var{mod}]$, $[\var{bnf},\var{mod},\var{subgroup}]$. The last two forms are kept for backward compatibility, but no longer serve any real purpose (see example below); no newly written function will accept them. \item $\var{bnf}$ is as output by \kbd{bnfinit}, where units are mandatory unless the modulus is trivial; \var{bnr} is as output by \kbd{bnrinit}. This is the ground field $K$. \item \emph{mod} is a modulus $\goth{f}$, as described above. \item \emph{subgroup} a subgroup of the ray class group modulo $\goth{f}$ of $K$. As described above, this is input as a square matrix expressing generators of a subgroup of the ray class group \kbd{\var{bnr}.clgp} on the given generators. The corresponding \var{bnr} is the subfield of the ray class field of $K$ modulo $\goth{f}$, fixed by the given subgroup. \bprog ? K = bnfinit(y^2+1); ? bnr = bnrinit(K, 13) ? %.clgp %3 = [36, [12, 3]] ? bnrdisc(bnr); \\ discriminant of the full ray class field ? bnrdisc(bnr, [3,1;0,1]); \\ discriminant of cyclic cubic extension of K @eprog\noindent We could have written directly \bprog ? bnrdisc(K, 13); ? bnrdisc(K, 13, [3,1;0,1]); @eprog\noindent avoiding one \tet{bnrinit}, but this would actually be slower since the \kbd{bnrinit} is called internally anyway. And now twice! \subsec{General use} All the functions which are specific to relative extensions, number fields, Buchmann's number fields, Buchmann's number rays, share the prefix \kbd{rnf}, \kbd{nf}, \kbd{bnf}, \kbd{bnr} respectively. They take as first argument a number field of that precise type, respectively output by \kbd{rnfinit}, \kbd{nfinit}, \kbd{bnfinit}, and \kbd{bnrinit}. However, and even though it may not be specified in the descriptions of the functions below, it is permissible, if the function expects a $\var{nf}$, to use a $\var{bnf}$ instead, which contains much more information. On the other hand, if the function requires a \kbd{bnf}, it will \emph{not} launch \kbd{bnfinit} for you, which is a costly operation. Instead, it will give you a specific error message. In short, the types $$ \kbd{nf} \leq \kbd{bnf} \leq \kbd{bnr}$$ are ordered, each function requires a minimal type to work properly, but you may always substitute a larger type. The data types corresponding to the structures described above are rather complicated. Thus, as we already have seen it with elliptic curves, GP provides ``member functions'' to retrieve data from these structures (once they have been initialized of course). The relevant types of number fields are indicated between parentheses: \smallskip \sidx{member functions} \settabs\+xxxxxxx&(\var{bnr},x&\var{bnf},x&nf\hskip2pt&)x&: &\cr \+\tet{bid} &(\var{bnr}&&&)&: & bid ideal structure.\cr \+\tet{bnf} &(\var{bnr},& \var{bnf}&&)&: & Buchmann's number field.\cr \+\tet{clgp} &(\var{bnr},& \var{bnf}&&)&: & classgroup. This one admits the following three subclasses:\cr \+ \quad \tet{cyc} &&&&&: & \quad cyclic decomposition (SNF)\sidx{Smith normal form}.\cr \+ \quad \kbd{gen}\sidx{gen (member function)} &&&&&: & \quad generators.\cr \+ \quad \tet{no} &&&&&: & \quad number of elements.\cr \+\tet{diff} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the different ideal.\cr \+\tet{codiff}&(\var{bnr},& \var{bnf},& \var{nf}&)&: & the codifferent (inverse of the different in the ideal group).\cr \+\tet{disc} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & discriminant.\cr \+\tet{fu} &(\var{bnr},& \var{bnf}&&)&: & \idx{fundamental units}.\cr \+\tet{index} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & \idx{index} of the power order in the ring of integers.\cr \+\tet{mod} &(\var{bnr}&&&)&: & modulus.\cr \+\tet{nf} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & number field.\cr \+\tet{pol} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & defining polynomial.\cr \+\tet{r1} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the number of real embeddings.\cr \+\tet{r2} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the number of pairs of complex embeddings.\cr \+\tet{reg} &(\var{bnr},& \var{bnf}&&)&: & regulator.\cr \+\tet{roots}&(\var{bnr},& \var{bnf},& \var{nf}&)&: & roots of the polynomial generating the field.\cr \+\tet{sign} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & signature $[r1,r2]$.\cr \+\tet{t2} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & the $T_2$ matrix (see \kbd{nfinit}).\cr \+\tet{tu} &(\var{bnr},& \var{bnf}&&)&: & a generator for the torsion units.\cr \+\tet{zk} &(\var{bnr},& \var{bnf},& \var{nf}&)&: & integral basis, i.e.~a $\Z$-basis of the maximal order.\cr \+\tet{zkst} &(\var{bnr}&&&)&: & structure of $(\Z_K/m)^*$.\cr \misctitle{Deprecated} The following member functions are still available, but deprecated and should not be used in new scripts : \+\tet{futu} &(\var{bnr},& \var{bnf},&&)&: & $[u_1,...,u_r,w]$, $(u_i)$ is a vector of fundamental units,\cr \+&&&&&& $w$ generates the torsion units.\cr \+\tet{tufu} &(\var{bnr},& \var{bnf},&&)&: & $[w,u_1,...,u_r]$, $(u_i)$ is a vector of fundamental units,\cr \+&&&&&& $w$ generates the torsion units.\cr For instance, assume that $\var{bnf} = \kbd{bnfinit}(\var{pol})$, for some polynomial. Then \kbd{\var{bnf}.clgp} retrieves the class group, and \kbd{\var{bnf}.clgp.no} the class number. If we had set $\var{bnf} = \kbd{nfinit}(\var{pol})$, both would have output an error message. All these functions are completely recursive, thus for instance \kbd{\var{bnr}.bnf.nf.zk} will yield the maximal order of \var{bnr}, which you could get directly with a simple \kbd{\var{bnr}.zk}. \subsec{Class group, units, and the GRH}\label{se:GRHbnf} Some of the functions starting with \kbd{bnf} are implementations of the sub-exponential algorithms for finding class and unit groups under \idx{GRH}, due to Hafner-McCurley, \idx{Buchmann} and Cohen-Diaz-Olivier. The general call to the functions concerning class groups of general number fields (i.e.~excluding \kbd{quadclassunit}) involves a polynomial $P$ and a technical vector $$\var{tech} = [c_1, c_2, \var{nrpid} ],$$ where the parameters are to be understood as follows: $P$ is the defining polynomial for the number field, which must be in $\Z[X]$, irreducible and monic. In fact, if you supply a non-monic polynomial at this point, \kbd{gp} issues a warning, then \emph{transforms your polynomial} so that it becomes monic. The \kbd{nfinit} routine will return a different result in this case: instead of \kbd{res}, you get a vector \kbd{[res,Mod(a,Q)]}, where \kbd{Mod(a,Q) = Mod(X,P)} gives the change of variables. In all other routines, the variable change is simply lost. The \var{tech} interface is obsolete and you should not tamper with these parameters. Indeed, from version 2.4.0 on, \item the results are always rigorous under \idx{GRH} (before that version, they relied on a heuristic strengthening, hence the need for overrides). \item the influence of these parameters on execution time and stack size is marginal. They \emph{can} be useful to fine-tune and experiment with the \kbd{bnfinit} code, but you will be better off modifying all tuning parameters in the C code (there are many more than just those three). We nevertheless describe it for completeness. The numbers $c_1 \leq c_2$ are non-negative real numbers. By default they are chosen so that the result is correct under GRH. For $i = 1,2$, let $B_i = c_i(\log |d_K|)^2$, and denote by $S(B)$ the set of maximal ideals of $K$ whose norm is less than $B$. We want $S(B_1)$ to generate $\Cl(K)$ and hope that $S(B_2)$ can be \emph{proven} to generate $\Cl(K)$. More precisely, $S(B_1)$ is a factorbase used to compute a tentative $\Cl(K)$ by generators and relations. We then check explicitly, using essentially \kbd{bnfisprincipal}, that the elements of $S(B_2)$ belong to the span of $S(B_1)$. Under the assumption that $S(B_2)$ generates $\Cl(K)$, we are done. User-supplied $c_i$ are only used to compute initial guesses for the bounds $B_i$, and the algorithm increases them until one can \emph{prove} under GRH that $S(B_2)$ generates $\Cl(K)$. A uniform result of Bach says that $c_2 = 12$ is always suitable, but this bound is very pessimistic and a direct algorithm due to Belabas-Diaz-Friedman is used to check the condition, assuming GRH. The default values are $c_1 = c_2 = 0$. When $c_1$ is equal to $0$ the algorithm takes it equal to $c_2$. $\var{nrpid}$ is the maximal number of small norm relations associated to each ideal in the factor base. Set it to $0$ to disable the search for small norm relations. Otherwise, reasonable values are between 4 and 20. The default is 4. \misctitle{Warning} Make sure you understand the above! By default, most of the \kbd{bnf} routines depend on the correctness of the GRH. In particular, any of the class number, class group structure, class group generators, regulator and fundamental units may be wrong, independently of each other. Any result computed from such a \kbd{bnf} may be wrong. The only guarantee is that the units given generate a subgroup of finite index in the full unit group. You must use \kbd{bnfcertify} to certify the computations unconditionally. \misctitle{Remarks} You do not need to supply the technical parameters (under the library you still need to send at least an empty vector, coded as \kbd{NULL}). However, should you choose to set some of them, they \emph{must} be given in the requested order. For example, if you want to specify a given value of \var{nrpid}, you must give some values as well for $c_1$ and $c_2$, and provide a vector $[c_1,c_2,\var{nrpid}]$. Note also that you can use an $\var{nf}$ instead of $P$, which avoids recomputing the integral basis and analogous quantities. \smallskip \subsec{bnfcertify$(\var{bnf},\{\fl = 0\})$}\kbdsidx{bnfcertify}\label{se:bnfcertify} $\var{bnf}$ being as output by \kbd{bnfinit}, checks whether the result is correct, i.e.~whether it is possible to remove the assumption of the Generalized Riemann Hypothesis\sidx{GRH}. It is correct if and only if the answer is 1. If it is incorrect, the program may output some error message, or loop indefinitely. You can check its progress by increasing the debug level. The \var{bnf} structure must contain the fundamental units: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K) *** at top-level: K=bnfinit(x^3+2^2^3+1);bnfcertify(K) *** ^------------- *** bnfcertify: missing units in bnf. ? K = bnfinit(x^3+2^2^3+1, 1); \\ include units ? bnfcertify(K) %3 = 1 @eprog If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general); likewise, the computed units may form a subgroup of the full unit group. In this variant, the units are no longer needed: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K, 1) %4 = 1 @eprog The library syntax is \fun{long}{bnfcertify0}{GEN bnf, long flag }. Also available is \fun{GEN}{bnfcertify}{GEN bnf} ($\fl=0$). \subsec{bnfcompress$(\var{bnf})$}\kbdsidx{bnfcompress}\label{se:bnfcompress} Computes a compressed version of \var{bnf} (from \tet{bnfinit}), a ``small Buchmann's number field'' (or \var{sbnf} for short) which contains enough information to recover a full $\var{bnf}$ vector very rapidly, but which is much smaller and hence easy to store and print. Calling \kbd{bnfinit} on the result recovers a true \kbd{bnf}, in general different from the original. Note that an \tev{snbf} is useless for almost all purposes besides storage, and must be converted back to \tev{bnf} form before use; for instance, no \kbd{nf*}, \kbd{bnf*} or member function accepts them. An \var{sbnf} is a 12 component vector $v$, as follows. Let \kbd{bnf} be the result of a full \kbd{bnfinit}, complete with units. Then $v[1]$ is \kbd{bnf.pol}, $v[2]$ is the number of real embeddings \kbd{bnf.sign[1]}, $v[3]$ is \kbd{bnf.disc}, $v[4]$ is \kbd{bnf.zk}, $v[5]$ is the list of roots \kbd{bnf.roots}, $v[7]$ is the matrix $\kbd{W} = \kbd{bnf[1]}$, $v[8]$ is the matrix $\kbd{matalpha}=\kbd{bnf[2]}$, $v[9]$ is the prime ideal factor base \kbd{bnf[5]} coded in a compact way, and ordered according to the permutation \kbd{bnf[6]}, $v[10]$ is the 2-component vector giving the number of roots of unity and a generator, expressed on the integral basis, $v[11]$ is the list of fundamental units, expressed on the integral basis, $v[12]$ is a vector containing the algebraic numbers alpha corresponding to the columns of the matrix \kbd{matalpha}, expressed on the integral basis. All the components are exact (integral or rational), except for the roots in $v[5]$. The library syntax is \fun{GEN}{bnfcompress}{GEN bnf}. \subsec{bnfdecodemodule$(\var{nf},m)$}\kbdsidx{bnfdecodemodule}\label{se:bnfdecodemodule} If $m$ is a module as output in the first component of an extension given by \kbd{bnrdisclist}, outputs the true module. \bprog ? K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[1][2] %1 = [[Mat([8, 1]), [[0, 0, 0]]], [Mat([9, 1]), [[0, 0, 0]]]] ? bnfdecodemodule(K, s[1][1]) %2 = [2 0] [0 1] @eprog The library syntax is \fun{GEN}{decodemodule}{GEN nf, GEN m}. \subsec{bnfinit$(P,\{\fl=0\},\{\var{tech}=[\,]\})$}\kbdsidx{bnfinit}\label{se:bnfinit} Initializes a \var{bnf} structure. Used in programs such as \kbd{bnfisprincipal}, \kbd{bnfisunit} or \kbd{bnfnarrow}. By default, the results are conditional on the GRH, see \ref{se:GRHbnf}. The result is a 10-component vector \var{bnf}. This implements \idx{Buchmann}'s sub-exponential algorithm for computing the class group, the regulator and a system of \idx{fundamental units} of the general algebraic number field $K$ defined by the irreducible polynomial $P$ with integer coefficients. If the precision becomes insufficient, \kbd{gp} does not strive to compute the units by default ($\fl=0$). When $\fl=1$, we insist on finding the fundamental units exactly. Be warned that this can take a very long time when the coefficients of the fundamental units on the integral basis are very large. If the fundamental units are simply too large to be represented in this form, an error message is issued. They could be obtained using the so-called compact representation of algebraic numbers as a formal product of algebraic integers. The latter is implemented internally but not publicly accessible yet. $\var{tech}$ is a technical vector (empty by default, see \ref{se:GRHbnf}). Careful use of this parameter may speed up your computations, but it is mostly obsolete and you should leave it alone. \smallskip The components of a \var{bnf} or \var{sbnf} are technical and never used by the casual user. In fact: \emph{never access a component directly, always use a proper member function.} However, for the sake of completeness and internal documentation, their description is as follows. We use the notations explained in the book by H. Cohen, \emph{A Course in Computational Algebraic Number Theory}, Graduate Texts in Maths \key{138}, Springer-Verlag, 1993, Section 6.5, and subsection 6.5.5 in particular. $\var{bnf}[1]$ contains the matrix $W$, i.e.~the matrix in Hermite normal form giving relations for the class group on prime ideal generators $(\goth{p}_i)_{1\le i\le r}$. $\var{bnf}[2]$ contains the matrix $B$, i.e.~the matrix containing the expressions of the prime ideal factorbase in terms of the $\goth{p}_i$. It is an $r\times c$ matrix. $\var{bnf}[3]$ contains the complex logarithmic embeddings of the system of fundamental units which has been found. It is an $(r_1+r_2)\times(r_1+r_2-1)$ matrix. $\var{bnf}[4]$ contains the matrix $M''_C$ of Archimedean components of the relations of the matrix $(W|B)$. $\var{bnf}[5]$ contains the prime factor base, i.e.~the list of prime ideals used in finding the relations. $\var{bnf}[6]$ used to contain a permutation of the prime factor base, but has been obsoleted. It contains a dummy $0$. $\var{bnf}[7]$ or \kbd{\var{bnf}.nf} is equal to the number field data $\var{nf}$ as would be given by \kbd{nfinit}. $\var{bnf}[8]$ is a vector containing the classgroup \kbd{\var{bnf}.clgp} as a finite abelian group, the regulator \kbd{\var{bnf}.reg}, a $1$ (used to contain an obsolete ``check number''), the number of roots of unity and a generator \kbd{\var{bnf}.tu}, the fundamental units \kbd{\var{bnf}.fu}. $\var{bnf}[9]$ is a 3-element row vector used in \tet{bnfisprincipal} only and obtained as follows. Let $D = U W V$ obtained by applying the \idx{Smith normal form} algorithm to the matrix $W$ (= $\var{bnf}[1]$) and let $U_r$ be the reduction of $U$ modulo $D$. The first elements of the factorbase are given (in terms of \kbd{bnf.gen}) by the columns of $U_r$, with Archimedean component $g_a$; let also $GD_a$ be the Archimedean components of the generators of the (principal) ideals defined by the \kbd{bnf.gen[i]\pow bnf.cyc[i]}. Then $\var{bnf}[9]=[U_r, g_a, GD_a]$. $\var{bnf}[10]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available, which is rarely needed, hence would be too expensive to compute during the initial \kbd{bnfinit} call. For instance, the generators of the principal ideals \kbd{bnf.gen[i]\pow bnf.cyc[i]} (during a call to \tet{bnrisprincipal}), or those corresponding to the relations in $W$ and $B$ (when the \kbd{bnf} internal precision needs to be increased). The library syntax is \fun{GEN}{bnfinit0}{GEN P, long flag, GEN tech = NULL, long prec}. Also available is \fun{GEN}{Buchall}{GEN P, long flag, long prec}, corresponding to \kbd{tech = NULL}, where \kbd{flag} is either $0$ (default) or \tet{nf_FORCE} (insist on finding fundamental units). The function \fun{GEN}{Buchall_param}{GEN P, double c1, double c2, long nrpid, long flag, long prec} gives direct access to the technical parameters. \subsec{bnfisintnorm$(\var{bnf},x)$}\kbdsidx{bnfisintnorm}\label{se:bnfisintnorm} Computes a complete system of solutions (modulo units of positive norm) of the absolute norm equation $\Norm(a)=x$, where $a$ is an integer in $\var{bnf}$. If $\var{bnf}$ has not been certified, the correctness of the result depends on the validity of \idx{GRH}. See also \tet{bnfisnorm}. The library syntax is \fun{GEN}{bnfisintnorm}{GEN bnf, GEN x}. The function \fun{GEN}{bnfisintnormabs}{GEN bnf, GEN a} returns a complete system of solutions modulo units of the absolute norm equation $|\Norm(x)| = |a|$. As fast as \kbd{bnfisintnorm}, but solves the two equations $\Norm(x) = \pm a$ simultaneously. \subsec{bnfisnorm$(\var{bnf},x,\{\fl=1\})$}\kbdsidx{bnfisnorm}\label{se:bnfisnorm} Tries to tell whether the rational number $x$ is the norm of some element y in $\var{bnf}$. Returns a vector $[a,b]$ where $x=Norm(a)*b$. Looks for a solution which is an $S$-unit, with $S$ a certain set of prime ideals containing (among others) all primes dividing $x$. If $\var{bnf}$ is known to be \idx{Galois}, set $\fl=0$ (in this case, $x$ is a norm iff $b=1$). If $\fl$ is non zero the program adds to $S$ the following prime ideals, depending on the sign of $\fl$. If $\fl>0$, the ideals of norm less than $\fl$. And if $\fl<0$ the ideals dividing $\fl$. Assuming \idx{GRH}, the answer is guaranteed (i.e.~$x$ is a norm iff $b=1$), if $S$ contains all primes less than $12\log(\disc(\var{Bnf}))^2$, where $\var{Bnf}$ is the Galois closure of $\var{bnf}$. See also \tet{bnfisintnorm}. The library syntax is \fun{GEN}{bnfisnorm}{GEN bnf, GEN x, long flag}. \subsec{bnfisprincipal$(\var{bnf},x,\{\fl=1\})$}\kbdsidx{bnfisprincipal}\label{se:bnfisprincipal} $\var{bnf}$ being the \sidx{principal ideal} number field data output by \kbd{bnfinit}, and $x$ being an ideal, this function tests whether the ideal is principal or not. The result is more complete than a simple true/false answer and solves general discrete logarithm problem. Assume the class group is $\oplus (\Z/d_i\Z)g_i$ (where the generators $g_i$ and their orders $d_i$ are respectively given by \kbd{bnf.gen} and \kbd{bnf.cyc}). The routine returns a row vector $[e,t]$, where $e$ is a vector of exponents $0 \leq e_i < d_i$, and $t$ is a number field element such that $$ x = (t) \prod_i g_i^{e_i}.$$ For \emph{given} $g_i$ (i.e. for a given \kbd{bnf}), the $e_i$ are unique, and $t$ is unique modulo units. In particular, $x$ is principal if and only if $e$ is the zero vector. Note that the empty vector, which is returned when the class number is $1$, is considered to be a zero vector (of dimension $0$). \bprog ? K = bnfinit(y^2+23); ? K.cyc %2 = [3] ? K.gen %3 = [[2, 0; 0, 1]] \\ a prime ideal above 2 ? P = idealprimedec(K,3)[1]; \\ a prime ideal above 3 ? v = bnfisprincipal(K, P) %5 = [[2]~, [3/4, 1/4]~] ? idealmul(K, v[2], idealfactorback(K, K.gen, v[1])) %6 = [3 0] [0 1] ? % == idealhnf(K, P) %7 = 1 @eprog \noindent The binary digits of \fl mean: \item $1$: If set, outputs $[e,t]$ as explained above, otherwise returns only $e$, which is much easier to compute. The following idiom only tests whether an ideal is principal: \bprog is_principal(bnf, x) = !bnfisprincipal(bnf,x,0); @eprog \item $2$: It may not be possible to recover $t$, given the initial accuracy to which \kbd{bnf} was computed. In that case, a warning is printed and $t$ is set equal to the empty vector \kbd{[]\til}. If this bit is set, increase the precision and recompute needed quantities until $t$ can be computed. Warning: setting this may induce \emph{very} lengthy computations. The library syntax is \fun{GEN}{bnfisprincipal0}{GEN bnf, GEN x, long flag}. Instead of the above hardcoded numerical flags, one should rather use an or-ed combination of the symbolic flags \tet{nf_GEN} (include generators, possibly a place holder if too difficult) and \tet{nf_FORCE} (insist on finding the generators). \subsec{bnfissunit$(\var{bnf},\var{sfu},x)$}\kbdsidx{bnfissunit}\label{se:bnfissunit} $\var{bnf}$ being output by \kbd{bnfinit}, \var{sfu} by \kbd{bnfsunit}, gives the column vector of exponents of $x$ on the fundamental $S$-units and the roots of unity. If $x$ is not a unit, outputs an empty vector. The library syntax is \fun{GEN}{bnfissunit}{GEN bnf, GEN sfu, GEN x}. \subsec{bnfisunit$(\var{bnf},x)$}\kbdsidx{bnfisunit}\label{se:bnfisunit} \var{bnf} being the number field data output by \kbd{bnfinit} and $x$ being an algebraic number (type integer, rational or polmod), this outputs the decomposition of $x$ on the fundamental units and the roots of unity if $x$ is a unit, the empty vector otherwise. More precisely, if $u_1$,\dots,$u_r$ are the fundamental units, and $\zeta$ is the generator of the group of roots of unity (\kbd{bnf.tu}), the output is a vector $[x_1,\dots,x_r,x_{r+1}]$ such that $x=u_1^{x_1}\cdots u_r^{x_r}\cdot\zeta^{x_{r+1}}$. The $x_i$ are integers for $i\le r$ and is an integer modulo the order of $\zeta$ for $i=r+1$. Note that \var{bnf} need not contain the fundamental unit explicitly: \bprog ? setrand(1); bnf = bnfinit(x^2-x-100000); ? bnf.fu *** at top-level: bnf.fu *** ^-- *** _.fu: missing units in .fu. ? u = [119836165644250789990462835950022871665178127611316131167, \ 379554884019013781006303254896369154068336082609238336]~; ? bnfisunit(bnf, u) %3 = [-1, Mod(0, 2)]~ @eprog\noindent The given $u$ is the inverse of the fundamental unit implicitly stored in \var{bnf}. In this case, the fundamental unit was not computed and stored in algebraic form since the default accuracy was too low. (Re-run the command at \bs g1 or higher to see such diagnostics.) The library syntax is \fun{GEN}{bnfisunit}{GEN bnf, GEN x}. \subsec{bnfnarrow$(\var{bnf})$}\kbdsidx{bnfnarrow}\label{se:bnfnarrow} $\var{bnf}$ being as output by \kbd{bnfinit}, computes the narrow class group of $\var{bnf}$. The output is a 3-component row vector $v$ analogous to the corresponding class group component \kbd{\var{bnf}.clgp} (\kbd{\var{bnf}[8][1]}): the first component is the narrow class number \kbd{$v$.no}, the second component is a vector containing the SNF\sidx{Smith normal form} cyclic components \kbd{$v$.cyc} of the narrow class group, and the third is a vector giving the generators of the corresponding \kbd{$v$.gen} cyclic groups. Note that this function is a special case of \kbd{bnrinit}. The library syntax is \fun{GEN}{buchnarrow}{GEN bnf}. \subsec{bnfsignunit$(\var{bnf})$}\kbdsidx{bnfsignunit}\label{se:bnfsignunit} $\var{bnf}$ being as output by \kbd{bnfinit}, this computes an $r_1\times(r_1+r_2-1)$ matrix having $\pm1$ components, giving the signs of the real embeddings of the fundamental units. The following functions compute generators for the totally positive units: \bprog /* exponents of totally positive units generators on bnf.tufu */ tpuexpo(bnf)= { my(S,d,K); S = bnfsignunit(bnf); d = matsize(S); S = matrix(d[1],d[2], i,j, if (S[i,j] < 0, 1,0)); S = concat(vectorv(d[1],i,1), S); \\ add sign(-1) K = lift(matker(S * Mod(1,2))); if (K, mathnfmodid(K, 2), 2*matid(d[1])) } /* totally positive units */ tpu(bnf)= { my(vu = bnf.tufu, ex = tpuexpo(bnf)); vector(#ex-1, i, factorback(vu, ex[,i+1])) \\ ex[,1] is 1 } @eprog The library syntax is \fun{GEN}{signunits}{GEN bnf}. \subsec{bnfsunit$(\var{bnf},S)$}\kbdsidx{bnfsunit}\label{se:bnfsunit} Computes the fundamental $S$-units of the number field $\var{bnf}$ (output by \kbd{bnfinit}), where $S$ is a list of prime ideals (output by \kbd{idealprimedec}). The output is a vector $v$ with 6 components. $v[1]$ gives a minimal system of (integral) generators of the $S$-unit group modulo the unit group. $v[2]$ contains technical data needed by \kbd{bnfissunit}. $v[3]$ is an empty vector (used to give the logarithmic embeddings of the generators in $v[1]$ in version 2.0.16). $v[4]$ is the $S$-regulator (this is the product of the regulator, the determinant of $v[2]$ and the natural logarithms of the norms of the ideals in $S$). $v[5]$ gives the $S$-class group structure, in the usual format (a row vector whose three components give in order the $S$-class number, the cyclic components and the generators). $v[6]$ is a copy of $S$. The library syntax is \fun{GEN}{bnfsunit}{GEN bnf, GEN S, long prec}. \subsec{bnrL1$(\var{bnr}, \{H\}, \{\fl=0\})$}\kbdsidx{bnrL1}\label{se:bnrL1} Let \var{bnr} be the number field data output by \kbd{bnrinit(,,1)} and \var{H} be a square matrix defining a congruence subgroup of the ray class group corresponding to \var{bnr} (the trivial congruence subgroup if omitted). This function returns, for each \idx{character} $\chi$ of the ray class group which is trivial on $H$, the value at $s = 1$ (or $s = 0$) of the abelian $L$-function associated to $\chi$. For the value at $s = 0$, the function returns in fact for each $\chi$ a vector $[r_\chi, c_\chi]$ where $$L(s, \chi) = c \cdot s^r + O(s^{r + 1})$$ \noindent near $0$. The argument \fl\ is optional, its binary digits mean 1: compute at $s = 0$ if unset or $s = 1$ if set, 2: compute the primitive $L$-function associated to $\chi$ if unset or the $L$-function with Euler factors at prime ideals dividing the modulus of \var{bnr} removed if set (that is $L_S(s, \chi)$, where $S$ is the set of infinite places of the number field together with the finite prime ideals dividing the modulus of \var{bnr}), 3: return also the character if set. \bprog K = bnfinit(x^2-229); bnr = bnrinit(K,1,1); bnrL1(bnr) @eprog\noindent returns the order and the first non-zero term of $L(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K = \Q(\sqrt{229})$. Then \bprog bnr2 = bnrinit(K,2,1); bnrL1(bnr2,,2) @eprog\noindent returns the order and the first non-zero terms of $L_S(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K$ and $S$ is the set of infinite places of $K$ together with the finite prime $2$. Note that the ray class group modulo $2$ is in fact the class group, so \kbd{bnrL1(bnr2,0)} returns the same answer as \kbd{bnrL1(bnr,0)}. This function will fail with the message \bprog *** bnrL1: overflow in zeta_get_N0 [need too many primes]. @eprog\noindent if the approximate functional equation requires us to sum too many terms (if the discriminant of $K$ is too large). The library syntax is \fun{GEN}{bnrL1}{GEN bnr, GEN H = NULL, long flag, long prec}. \subsec{bnrclassno$(A,\{B\},\{C\})$}\kbdsidx{bnrclassno}\label{se:bnrclassno} Let $A$, $B$, $C$ define a class field $L$ over a ground field $K$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, or \kbd{[\var{bnf}, \var{modulus}]}, or \kbd{[\var{bnf}, \var{modulus},\var{subgroup}]}, \secref{se:CFT}); this function returns the relative degree $[L:K]$. In particular if $A$ is a \var{bnf} (with units), and $B$ a modulus, this function returns the corresponding ray class number modulo $B$. One can input the associated \var{bid} (with generators if the subgroup $C$ is non trivial) for $B$ instead of the module itself, saving some time. This function is faster than \kbd{bnrinit} and should be used if only the ray class number is desired. See \tet{bnrclassnolist} if you need ray class numbers for all moduli less than some bound. The library syntax is \fun{GEN}{bnrclassno0}{GEN A, GEN B = NULL, GEN C = NULL}. Also available is \fun{GEN}{bnrclassno}{GEN bnf,GEN f} to compute the ray class number modulo~$f$. \subsec{bnrclassnolist$(\var{bnf},\var{list})$}\kbdsidx{bnrclassnolist}\label{se:bnrclassnolist} $\var{bnf}$ being as output by \kbd{bnfinit}, and \var{list} being a list of moduli (with units) as output by \kbd{ideallist} or \kbd{ideallistarch}, outputs the list of the class numbers of the corresponding ray class groups. To compute a single class number, \tet{bnrclassno} is more efficient. \bprog ? bnf = bnfinit(x^2 - 2); ? L = ideallist(bnf, 100, 2); ? H = bnrclassnolist(bnf, L); ? H[98] %4 = [1, 3, 1] ? l = L[1][98]; ids = vector(#l, i, l[i].mod[1]) %5 = [[98, 88; 0, 1], [14, 0; 0, 7], [98, 10; 0, 1]] @eprog The weird \kbd{l[i].mod[1]}, is the first component of \kbd{l[i].mod}, i.e. the finite part of the conductor. (This is cosmetic: since by construction the Archimedean part is trivial, I do not want to see it). This tells us that the ray class groups modulo the ideals of norm 98 (printed as \kbd{\%5}) have respectively order $1$, $3$ and $1$. Indeed, we may check directly: \bprog ? bnrclassno(bnf, ids[2]) %6 = 3 @eprog The library syntax is \fun{GEN}{bnrclassnolist}{GEN bnf, GEN list}. \subsec{bnrconductor$(A,\{B\},\{C\},\{\fl=0\})$}\kbdsidx{bnrconductor}\label{se:bnrconductor} Conductor $f$ of the subfield of a ray class field as defined by $[A,B,C]$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, \kbd{[\var{bnf}, \var{modulus}]} or \kbd{[\var{bnf}, \var{modulus}, \var{subgroup}]}, \secref{se:CFT}) If $\fl = 0$, returns $f$. If $\fl = 1$, returns $[f, Cl_f, H]$, where $Cl_f$ is the ray class group modulo $f$, as a finite abelian group; finally $H$ is the subgroup of $Cl_f$ defining the extension. If $\fl = 2$, returns $[f, \var{bnr}(f), H]$, as above except $Cl_f$ is replaced by a \kbd{bnr} structure, as output by $\tet{bnrinit}(,f,1)$. The library syntax is \fun{GEN}{bnrconductor0}{GEN A, GEN B = NULL, GEN C = NULL, long flag}. Also available is \fun{GEN}{bnrconductor}{GEN bnr, GEN H, long flag} \subsec{bnrconductorofchar$(\var{bnr},\var{chi})$}\kbdsidx{bnrconductorofchar}\label{se:bnrconductorofchar} \var{bnr} being a big ray number field as output by \kbd{bnrinit}, and \var{chi} being a row vector representing a \idx{character} as expressed on the generators of the ray class group, gives the conductor of this character as a modulus. The library syntax is \fun{GEN}{bnrconductorofchar}{GEN bnr, GEN chi}. \subsec{bnrdisc$(A,\{B\},\{C\},\{\fl=0\})$}\kbdsidx{bnrdisc}\label{se:bnrdisc} $A$, $B$, $C$ defining a class field $L$ over a ground field $K$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, \kbd{[\var{bnf}, \var{modulus}]} or \kbd{[\var{bnf}, \var{modulus}, \var{subgroup}]}, \secref{se:CFT}), outputs data $[N,r_1,D]$ giving the discriminant and signature of $L$, depending on the binary digits of \fl: \item 1: if this bit is unset, output absolute data related to $L/\Q$: $N$ is the absolute degree $[L:\Q]$, $r_1$ the number of real places of $L$, and $D$ the discriminant of $L/\Q$. Otherwise, output relative data for $L/K$: $N$ is the relative degree $[L:K]$, $r_1$ is the number of real places of $K$ unramified in $L$ (so that the number of real places of $L$ is equal to $r_1$ times $N$), and $D$ is the relative discriminant ideal of $L/K$. \item 2: if this bit is set and if the modulus is not the conductor of $L$, only return 0. The library syntax is \fun{GEN}{bnrdisc0}{GEN A, GEN B = NULL, GEN C = NULL, long flag}. \subsec{bnrdisclist$(\var{bnf},\var{bound},\{\var{arch}\})$}\kbdsidx{bnrdisclist}\label{se:bnrdisclist} $\var{bnf}$ being as output by \kbd{bnfinit} (with units), computes a list of discriminants of Abelian extensions of the number field by increasing modulus norm up to bound \var{bound}. The ramified Archimedean places are given by \var{arch}; all possible values are taken if \var{arch} is omitted. The alternative syntax $\kbd{bnrdisclist}(\var{bnf},\var{list})$ is supported, where \var{list} is as output by \kbd{ideallist} or \kbd{ideallistarch} (with units), in which case \var{arch} is disregarded. The output $v$ is a vector of vectors, where $v[i][j]$ is understood to be in fact $V[2^{15}(i-1)+j]$ of a unique big vector $V$. (This awkward scheme allows for larger vectors than could be otherwise represented.) $V[k]$ is itself a vector $W$, whose length is the number of ideals of norm $k$. We consider first the case where \var{arch} was specified. Each component of $W$ corresponds to an ideal $m$ of norm $k$, and gives invariants associated to the ray class field $L$ of $\var{bnf}$ of conductor $[m, \var{arch}]$. Namely, each contains a vector $[m,d,r,D]$ with the following meaning: $m$ is the prime ideal factorization of the modulus, $d = [L:\Q]$ is the absolute degree of $L$, $r$ is the number of real places of $L$, and $D$ is the factorization of its absolute discriminant. We set $d = r = D = 0$ if $m$ is not the finite part of a conductor. If \var{arch} was omitted, all $t = 2^{r_1}$ possible values are taken and a component of $W$ has the form $[m, [[d_1,r_1,D_1], \dots, [d_t,r_t,D_t]]]$, where $m$ is the finite part of the conductor as above, and $[d_i,r_i,D_i]$ are the invariants of the ray class field of conductor $[m,v_i]$, where $v_i$ is the $i$-th Archimedean component, ordered by inverse lexicographic order; so $v_1 = [0,\dots,0]$, $v_2 = [1,0\dots,0]$, etc. Again, we set $d_i = r_i = D_i = 0$ if $[m,v_i]$ is not a conductor. Finally, each prime ideal $pr = [p,\alpha,e,f,\beta]$ in the prime factorization $m$ is coded as the integer $p\cdot n^2+(f-1)\cdot n+(j-1)$, where $n$ is the degree of the base field and $j$ is such that \kbd{pr = idealprimedec(\var{nf},p)[j]}. \noindent $m$ can be decoded using \tet{bnfdecodemodule}. Note that to compute such data for a single field, either \tet{bnrclassno} or \tet{bnrdisc} is more efficient. The library syntax is \fun{GEN}{bnrdisclist0}{GEN bnf, GEN bound, GEN arch = NULL}. \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 the ray class group structure corresponding to this module, a so-called \var{bnr} structure. One can input the associated \var{bid} with generators for $f$ instead of the module itself, saving some time. (As in \tet{idealstar}, the finite part of the conductor may be given by a factorization into prime ideals, as produced by \tet{idealfactor}.) The following member functions are available on the result: \kbd{.bnf} is the underlying \var{bnf}, \kbd{.mod} the modulus, \kbd{.bid} the \var{bid} structure associated to the modulus; finally, \kbd{.clgp}, \kbd{.no}, \kbd{.cyc}, \kbd{.gen} refer to the ray class group (as a finite abelian group), its cardinality, its elementary divisors, its generators (only computed if $\fl = 1$). The last group of functions are different from the members of the underlying \var{bnf}, which refer to the class group; use \kbd{\var{bnr}.bnf.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bnf.cyc} to get the cyclic decomposition of the class group. They are also different from the members of the underlying \var{bid}, which refer to $(\Z_K/f)^*$; use \kbd{\var{bnr}.bid.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bid.no} to get $\phi(f)$. If $\fl=0$ (default), the generators of the ray class group are not computed, which saves time. Hence \kbd{\var{bnr}.gen} would produce an error. If $\fl=1$, as the default, except that generators are computed. 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. \subsec{bnrisconductor$(A,\{B\},\{C\})$}\kbdsidx{bnrisconductor}\label{se:bnrisconductor} $A$, $B$, $C$ represent an extension of the base field, given by class field theory (see~\secref{se:CFT}). Outputs 1 if this modulus is the conductor, and 0 otherwise. This is slightly faster than \kbd{bnrconductor}. The library syntax is \fun{long}{bnrisconductor0}{GEN A, GEN B = NULL, GEN C = NULL}. \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 ideal in any form, outputs the components of $x$ on the ray class group generators in a way similar to \kbd{bnfisprincipal}. That is a 2-component vector $v$ where $v[1]$ is the vector of components of $x$ on the ray class group generators, $v[2]$ gives on the integral basis an element $\alpha$ such that $x=\alpha\prod_ig_i^{x_i}$. If $\fl=0$, outputs only $v_1$. In that case, \var{bnr} need not contain the ray class group generators, i.e.~it may be created with \kbd{bnrinit}$(,,0)$ If $x$ is not coprime to the modulus of \var{bnr} the result is undefined. The library syntax is \fun{GEN}{bnrisprincipal}{GEN bnr, GEN x, long flag}. Instead of hardcoded numerical flags, one should rather use \fun{GEN}{isprincipalray}{GEN bnr, GEN x} for $\kbd{flag} = 0$, and if you want generators: \bprog bnrisprincipal(bnr, x, nf_GEN) @eprog \subsec{bnrrootnumber$(\var{bnr},\var{chi},\{\fl=0\})$}\kbdsidx{bnrrootnumber}\label{se:bnrrootnumber} If $\chi=\var{chi}$ is a \idx{character} over \var{bnr}, not necessarily primitive, let $L(s,\chi) = \sum_{id} \chi(id) N(id)^{-s}$ be the associated \idx{Artin L-function}. Returns the so-called \idx{Artin root number}, i.e.~the complex number $W(\chi)$ of modulus 1 such that % $$\Lambda(1-s,\chi) = W(\chi) \Lambda(s,\overline{\chi})$$ % \noindent where $\Lambda(s,\chi) = A(\chi)^{s/2}\gamma_\chi(s) L(s,\chi)$ is the enlarged L-function associated to $L$. The generators of the ray class group are needed, and you can set $\fl=1$ if the character is known to be primitive. Example: \bprog bnf = bnfinit(x^2 - x - 57); bnr = bnrinit(bnf, [7,[1,1]], 1); bnrrootnumber(bnr, [2,1]) @eprog\noindent returns the root number of the character $\chi$ of $\Cl_{7\infty_1\infty_2}(\Q(\sqrt{229}))$ defined by $\chi(g_1^ag_2^b) = \zeta_1^{2a}\zeta_2^b$. Here $g_1, g_2$ are the generators of the ray-class group given by \kbd{bnr.gen} and $\zeta_1 = e^{2i\pi/N_1}, \zeta_2 = e^{2i\pi/N_2}$ where $N_1, N_2$ are the orders of $g_1$ and $g_2$ respectively ($N_1=6$ and $N_2=3$ as \kbd{bnr.cyc} readily tells us). The library syntax is \fun{GEN}{bnrrootnumber}{GEN bnr, GEN chi, long flag, long prec}. \subsec{bnrstark$(\var{bnr},\{\var{subgroup}\})$}\kbdsidx{bnrstark}\label{se:bnrstark} \var{bnr} being as output by \kbd{bnrinit(,,1)}, finds a relative equation for the class field corresponding to the modulus in \var{bnr} and the given congruence subgroup (as usual, omit $\var{subgroup}$ if you want the whole ray class group). The main variable of \var{bnr} must not be $x$, and the ground field and the class field must be totally real. When the base field is $\Q$, the vastly simpler \tet{galoissubcyclo} is used instead. Here is an example: \bprog bnf = bnfinit(y^2 - 3); bnr = bnrinit(bnf, 5, 1); bnrstark(bnr) @eprog\noindent returns the ray class field of $\Q(\sqrt{3})$ modulo $5$. Usually, one wants to apply to the result one of \bprog rnfpolredabs(bnf, pol, 16) \\@com compute a reduced relative polynomial rnfpolredabs(bnf, pol, 16 + 2) \\@com compute a reduced absolute polynomial @eprog The routine uses \idx{Stark units} and needs to find a suitable auxiliary conductor, which may not exist when the class field is not cyclic over the base. In this case \kbd{bnrstark} is allowed to return a vector of polynomials defining \emph{independent} relative extensions, whose compositum is the requested class field. It was decided that it was more useful to keep the extra information thus made available, hence the user has to take the compositum herself. Even if it exists, the auxiliary conductor may be so large that later computations become unfeasible. (And of course, Stark's conjecture may simply be wrong.) In case of difficulties, try \tet{rnfkummer}: \bprog ? bnr = bnrinit(bnfinit(y^8-12*y^6+36*y^4-36*y^2+9,1), 2, 1); ? bnrstark(bnr) *** at top-level: bnrstark(bnr) *** ^------------- *** bnrstark: need 3919350809720744 coefficients in initzeta. *** Computation impossible. ? lift( rnfkummer(bnr) ) time = 24 ms. %2 = x^2 + (1/3*y^6 - 11/3*y^4 + 8*y^2 - 5) @eprog The library syntax is \fun{GEN}{bnrstark}{GEN bnr, GEN subgroup = NULL, long prec}. \subsec{dirzetak$(\var{nf},b)$}\kbdsidx{dirzetak}\label{se:dirzetak} Gives as a vector the first $b$ coefficients of the \idx{Dedekind} zeta function of the number field $\var{nf}$ considered as a \idx{Dirichlet series}. The library syntax is \fun{GEN}{dirzetak}{GEN nf, GEN b}. \subsec{factornf$(x,t)$}\kbdsidx{factornf}\label{se:factornf} Factorization of the univariate polynomial $x$ over the number field defined by the (univariate) polynomial $t$. $x$ may have coefficients in $\Q$ or in the number field. The algorithm reduces to factorization over $\Q$ (\idx{Trager}'s trick). The direct approach of \tet{nffactor}, which uses \idx{van Hoeij}'s method in a relative setting, is in general faster. The main variable of $t$ must be of \emph{lower} priority than that of $x$ (see \secref{se:priority}). However if non-rational number field elements occur (as polmods or polynomials) as coefficients of $x$, the variable of these polmods \emph{must} be the same as the main variable of $t$. For example \bprog ? factornf(x^2 + Mod(y, y^2+1), y^2+1); ? factornf(x^2 + y, y^2+1); \\@com these two are OK ? factornf(x^2 + Mod(z,z^2+1), y^2+1) *** at top-level: factornf(x^2+Mod(z,z *** ^-------------------- *** factornf: inconsistent data in rnf function. ? factornf(x^2 + z, y^2+1) *** at top-level: factornf(x^2+z,y^2+1 *** ^-------------------- *** factornf: incorrect variable in rnf function. @eprog The library syntax is \fun{GEN}{polfnf}{GEN x, GEN t}. \subsec{galoisexport$(\var{gal},\{\fl\})$}\kbdsidx{galoisexport}\label{se:galoisexport} \var{gal} being be a Galois group as output by \tet{galoisinit}, export the underlying permutation group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example compute the index of the underlying abstract group in the GAP library: \bprog ? G = galoisinit(x^6+108); ? s = galoisexport(G) %2 = "Group((1, 2, 3)(4, 5, 6), (1, 4)(2, 6)(3, 5))" ? extern("echo \"IdGroup("s");\" | gap -q") %3 = [6, 1] ? galoisidentify(G) %4 = [6, 1] @eprog\noindent This command also accepts subgroups returned by \kbd{galoissubgroups}. To \emph{import} a GAP permutation into gp (for \tet{galoissubfields} for instance), the following GAP function may be useful: \bprog PermToGP := function(p, n) return Permuted([1..n],p); end; gap> p:= (1,26)(2,5)(3,17)(4,32)(6,9)(7,11)(8,24)(10,13)(12,15)(14,27) (16,22)(18,28)(19,20)(21,29)(23,31)(25,30) gap> PermToGP(p,32); [ 26, 5, 17, 32, 2, 9, 11, 24, 6, 13, 7, 15, 10, 27, 12, 22, 3, 28, 20, 19, 29, 16, 31, 8, 30, 1, 14, 18, 21, 25, 23, 4 ] @eprog The library syntax is \fun{GEN}{galoisexport}{GEN gal, long flag}. \subsec{galoisfixedfield$(\var{gal},\var{perm},\{\fl\},\{v=y\})$}\kbdsidx{galoisfixedfield}\label{se:galoisfixedfield} \var{gal} being be a Galois group as output by \tet{galoisinit} and \var{perm} an element of $\var{gal}.group$, a vector of such elements or a subgroup of \var{gal} as returned by galoissubgroups, computes the fixed field of \var{gal} by the automorphism defined by the permutations \var{perm} of the roots $\var{gal}.roots$. $P$ is guaranteed to be squarefree modulo $\var{gal}.p$. If no flags or $\fl=0$, output format is the same as for \tet{nfsubfield}, returning $[P,x]$ such that $P$ is a polynomial defining the fixed field, and $x$ is a root of $P$ expressed as a polmod in $\var{gal}.pol$. If $\fl=1$ return only the polynomial $P$. If $\fl=2$ return $[P,x,F]$ where $P$ and $x$ are as above and $F$ is the factorization of $\var{gal}.pol$ over the field defined by $P$, where variable $v$ ($y$ by default) stands for a root of $P$. The priority of $v$ must be less than the priority of the variable of $\var{gal}.pol$ (see \secref{se:priority}). Example: \bprog ? G = galoisinit(x^4+1); ? galoisfixedfield(G,G.group[2],2) %2 = [x^2 + 2, Mod(x^3 + x, x^4 + 1), [x^2 - y*x - 1, x^2 + y*x - 1]] @eprog\noindent computes the factorization $x^4+1=(x^2-\sqrt{-2}x-1)(x^2+\sqrt{-2}x-1)$ The library syntax is \fun{GEN}{galoisfixedfield}{GEN gal, GEN perm, long flag, long v = -1}, where \kbd{v} is a variable number. \subsec{galoisgetpol$(a,\{b\},\{s\})$}\kbdsidx{galoisgetpol}\label{se:galoisgetpol} 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 [\kbd{pol}, \kbd{den}] where \item \kbd{pol} is the polynomial of degree $a$ \item \kbd{den} is the denominator of \kbd{nfgaloisconj(pol)}. Pass it as an optional argument to \tet{galoisinit} or \tet{nfgaloisconj} to speed them up: \bprog ? [pol,den] = galoisgetpol(64,4,1); ? G = galoisinit(pol); time = 352ms ? galoisinit(pol, den); \\ passing 'den' speeds up the computation time = 264ms ? % == %` %4 = 1 \\ same answer @eprog If $b$ and $s$ are omitted, return the number of isomorphism classes of groups of order $a$. The library syntax is \fun{GEN}{galoisgetpol}{long a, long b, long s}. Also available is \fun{GEN}{galoisnbpol}{long a} when $b$ and $s$ are omitted. \subsec{galoisidentify$(\var{gal})$}\kbdsidx{galoisidentify}\label{se:galoisidentify} \var{gal} being be a Galois group as output by \tet{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, by Hans Ulrich Besche, Bettina Eick and Eamonn O'Brien. This command also accepts subgroups returned by \kbd{galoissubgroups}. The current implementation is limited to degree less or equal to $127$. Some larger ``easy'' orders are also supported. The output is similar to the output of the function \kbd{IdGroup} in GAP4. Note that GAP4 \kbd{IdGroup} handles all groups of order less than $2000$ except $1024$, so you can use \tet{galoisexport} and GAP4 to identify large Galois groups. The library syntax is \fun{GEN}{galoisidentify}{GEN gal}. \subsec{galoisinit$(\var{pol},\{\var{den}\})$}\kbdsidx{galoisinit}\label{se:galoisinit} Computes the Galois group and all necessary information for computing the fixed fields of the Galois extension $K/\Q$ where $K$ is the number field defined by $\var{pol}$ (monic irreducible polynomial in $\Z[X]$ or a number field as output by \tet{nfinit}). The extension $K/\Q$ must be Galois with Galois group ``weakly'' super-solvable, see below; returns 0 otherwise. Hence this permits to quickly check whether a polynomial of order strictly less than $36$ is Galois or not. The algorithm used is an improved version of the paper ``An efficient algorithm for the computation of Galois automorphisms'', Bill Allombert, Math.~Comp, vol.~73, 245, 2001, pp.~359--375. A group $G$ is said to be ``weakly'' super-solvable if there exists a normal series $\{1\} = H_0 \triangleleft H_1 \triangleleft \cdots \triangleleft H_{n-1} \triangleleft H_n$ such that each $H_i$ is normal in $G$ and for $i1$). 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)) %3 = 2 ? p1 = L[1]; p2 = L[2]; ? [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 %5 = [1, 2] ? p1.gen %6 = [5, [2, 1, 0]~] ? nfbasistoalg(K, %[2]) \\ a uniformizer for p1 %7 = Mod(x + 2, x^3 - 2) @eprog The library syntax is \fun{GEN}{idealprimedec}{GEN nf, GEN p}. \subsec{idealprincipalunits$(\var{nf},\var{pr},k)$}\kbdsidx{idealprincipalunits}\label{se:idealprincipalunits} Given a prime ideal in \tet{idealprimedec} format, returns the multiplicative group $(1 + \var{pr}) / (1 + \var{pr}^k)$ as an abelian group. This function is much faster than \tet{idealstar} when the norm of \var{pr} is large, since it avoids (useless) work in the multiplicative group of the residue field. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K,2)[1]; ? G = idealprincipalunits(K, P, 20); ? G.cyc [512, 256, 4] \\ Z/512 x Z/256 x Z/4 ? G.gen %5 = [[-1, -2]~, 1021, [0, -1]~] \\ minimal generators of given order @eprog The library syntax is \fun{GEN}{idealprincipalunits}{GEN nf, GEN pr, long k}. \subsec{idealramgroups$(\var{nf},\var{gal},\var{pr})$}\kbdsidx{idealramgroups}\label{se:idealramgroups} Let $K$ be the number field defined by \var{nf} and assume that $K/\Q$ is Galois with Galois group $G$ given by \kbd{gal=galoisinit(nf)}. Let \var{pr} be the prime ideal $\goth{P}$ in prid format. This function returns a vector $g$ of subgroups of \kbd{gal} as follow: \item \kbd{g[1]} is the decomposition group of $\goth{P}$, \item \kbd{g[2]} is $G_0(\goth{P})$, the inertia group of $\goth{P}$, and for $i\geq 2$, \item \kbd{g[i]} is $G_{i-2}(\goth{P})$, the $i-2$-th \idx{ramification group} of $\goth{P}$. \noindent The length of $g$ is the number of non-trivial groups in the sequence, thus is $0$ if $e=1$ and $f=1$, and $1$ if $f>1$ and $e=1$. The following function computes the cardinality of a subgroup of $G$, as given by the components of $g$: \bprog card(H) =my(o=H[2]); prod(i=1,#o,o[i]); @eprog \bprog ? nf=nfinit(x^6+3); gal=galoisinit(nf); pr=idealprimedec(nf,3)[1]; ? g = idealramgroups(nf, gal, pr); ? apply(card,g) %4 = [6, 6, 3, 3, 3] \\ cardinalities of the G_i @eprog \bprog ? nf=nfinit(x^6+108); gal=galoisinit(nf); pr=idealprimedec(nf,2)[1]; ? iso=idealramgroups(nf,gal,pr)[2] %4 = [[Vecsmall([2, 3, 1, 5, 6, 4])], Vecsmall([3])] ? nfdisc(galoisfixedfield(gal,iso,1)) %5 = -3 @eprog\noindent The field fixed by the inertia group of $2$ is not ramified at $2$. The library syntax is \fun{GEN}{idealramgroups}{GEN nf, GEN gal, GEN pr}. \subsec{idealred$(\var{nf},I,\{v=0\})$}\kbdsidx{idealred}\label{se:idealred} \idx{LLL} reduction of the ideal $I$ in the number field \var{nf}, along the direction $v$. The $v$ parameter is best left omitted, but if it is present, it must be an $\kbd{nf.r1} + \kbd{nf.r2}$-component vector of \emph{non-negative} integers. (What counts is the relative magnitude of the entries: if all entries are equal, the effect is the same as if the vector had been omitted.) This function finds a ``small'' $a$ in $I$ (see the end for technical details). The result is the Hermite normal form of the ``reduced'' ideal $J = r I/a$, where $r$ is the unique rational number such that $J$ is integral and primitive. (This is usually not a reduced ideal in the sense of \idx{Buchmann}.) \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K,5)[1]; ? idealred(K, P) %3 = [1 0] [0 1] @eprog\noindent More often than not, a \idx{principal ideal} yields the unit ideal as above. This is a quick and dirty way to check if ideals are principal, but it is not a necessary condition: a non-trivial result does not prove that the ideal is non-principal. For guaranteed results, see \kbd{bnfisprincipal}, which requires the computation of a full \kbd{bnf} structure. If the input is an extended ideal $[I,s]$, the output is $[J,sa/r]$; this way, one can keep track of the principal ideal part: \bprog ? idealred(K, [P, 1]) %5 = [[1, 0; 0, 1], [-2, 1]~] @eprog\noindent meaning that $P$ is generated by $[-2, 1]~$. The number field element in the extended part is an algebraic number in any form \emph{or} a factorization matrix (in terms of number field elements, not ideals!). In the latter case, elements stay in factored form, which is a convenient way to avoid coefficient explosion; see also \tet{idealpow}. \misctitle{Technical note} The routine computes an LLL-reduced basis for the lattice $I$ equipped with the quadratic form $$|| x ||_v^2 = \sum_{i=1}^{r_1+r_2} 2^{v_i}\varepsilon_i|\sigma_i(x)|^2,$$ where as usual the $\sigma_i$ are the (real and) complex embeddings and $\varepsilon_i = 1$, resp.~$2$, for a real, resp.~complex place. The element $a$ is simply the first vector in the LLL basis. The only reason you may want to try to change some directions and set some $v_i\neq 0$ is to randomize the elements found for a fixed ideal, which is heuristically useful in index calculus algorithms like \tet{bnfinit} and \tet{bnfisprincipal}. \misctitle{Even more technical note} In fact, the above is a white lie. We do not use $||\cdot||_v$ exactly but a rescaled rounded variant which gets us faster and simpler LLLs. There's no harm since we are not using any theoretical property of $a$ after all, except that it belongs to $I$ and is ``expected to be small''. The library syntax is \fun{GEN}{idealred0}{GEN nf, GEN I, GEN v = NULL}. \subsec{idealstar$(\var{nf},I,\{\fl=1\})$}\kbdsidx{idealstar}\label{se:idealstar} Outputs a \var{bid} structure, necessary for computing in the finite abelian group $G = (\Z_K/I)^*$. Here, \var{nf} is a number field and $I$ is a \var{modulus}: either an ideal in any form, or a row vector whose first component is an ideal and whose second component is a row vector of $r_1$ 0 or 1. Ideals can also be given by a factorization into prime ideals, as produced by \tet{idealfactor}. This \var{bid} is used in \tet{ideallog} to compute discrete logarithms. It also contains useful information which can be conveniently retrieved as \kbd{\var{bid}.mod} (the modulus), \kbd{\var{bid}.clgp} ($G$ as a finite abelian group), \kbd{\var{bid}.no} (the cardinality of $G$), \kbd{\var{bid}.cyc} (elementary divisors) and \kbd{\var{bid}.gen} (generators). If $\fl=1$ (default), the result is a \var{bid} structure without generators. If $\fl=2$, as $\fl=1$, but including generators, which wastes some time. If $\fl=0$, only outputs $(\Z_K/I)^*$ as an abelian group, i.e as a 3-component vector $[h,d,g]$: $h$ is the order, $d$ is the vector of SNF\sidx{Smith normal form} cyclic components and $g$ the corresponding generators. The library syntax is \fun{GEN}{idealstar0}{GEN nf, GEN I, long flag}. Instead the above hardcoded numerical flags, one should rather use \fun{GEN}{Idealstar}{GEN nf, GEN ideal, long flag}, where \kbd{flag} is an or-ed combination of \tet{nf_GEN} (include generators) and \tet{nf_INIT} (return a full \kbd{bid}, not a group), possibly $0$. This offers one more combination: gen, but no init. \subsec{idealtwoelt$(\var{nf},x,\{a\})$}\kbdsidx{idealtwoelt}\label{se:idealtwoelt} Computes a two-element representation of the ideal $x$ in the number field $\var{nf}$, combining a random search and an approximation theorem; $x$ is an ideal in any form (possibly an extended ideal, whose principal part is ignored) \item When called as \kbd{idealtwoelt(nf,x)}, the result is a row vector $[a,\alpha]$ with two components such that $x=a\Z_K+\alpha\Z_K$ and $a$ is chosen to be the positive generator of $x\cap\Z$, unless $x$ was given as a principal ideal (in which case we may choose $a = 0$). The algorithm uses a fast lazy factorization of $x\cap \Z$ and runs in randomized polynomial time. \item When called as \kbd{idealtwoelt(nf,x,a)} with an explicit non-zero $a$ supplied as third argument, the function assumes that $a \in x$ and returns $\alpha\in x$ such that $x = a\Z_K + \alpha\Z_K$. Note that we must factor $a$ in this case, and the algorithm is generally much slower than the default variant. The library syntax is \fun{GEN}{idealtwoelt0}{GEN nf, GEN x, GEN a = NULL}. Also available are \fun{GEN}{idealtwoelt}{GEN nf, GEN x} and \fun{GEN}{idealtwoelt2}{GEN nf, GEN x, GEN a}. \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 library syntax is \fun{long}{idealval}{GEN nf, GEN x, GEN pr}. \subsec{matalgtobasis$(\var{nf},x)$}\kbdsidx{matalgtobasis}\label{se:matalgtobasis} $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a (row or column) vector or matrix, apply \tet{nfalgtobasis} to each entry of $x$. The library syntax is \fun{GEN}{matalgtobasis}{GEN nf, GEN x}. \subsec{matbasistoalg$(\var{nf},x)$}\kbdsidx{matbasistoalg}\label{se:matbasistoalg} $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a (row or column) vector or matrix, apply \tet{nfbasistoalg} to each entry of $x$. The library syntax is \fun{GEN}{matbasistoalg}{GEN nf, GEN x}. \subsec{modreverse$(z)$}\kbdsidx{modreverse}\label{se:modreverse} Let $z = \kbd{Mod(A, T)}$ be a polmod, and $Q$ be its minimal polynomial, which must satisfy $\text{deg}(Q) = \text{deg}(T)$. Returns a ``reverse polmod'' \kbd{Mod(B, Q)}, which is a root of $T$. This is quite useful when one changes the generating element in algebraic extensions: \bprog ? u = Mod(x, x^3 - x -1); v = u^5; ? w = modreverse(v) %2 = Mod(x^2 - 4*x + 1, x^3 - 5*x^2 + 4*x - 1) @eprog\noindent which means that $x^3 - 5x^2 + 4x -1$ is another defining polynomial for the cubic field $$\Q(u) = \Q[x]/(x^3 - x - 1) = \Q[x]/(x^3 - 5x^2 + 4x - 1) = \Q(v),$$ and that $u \to v^2 - 4v + 1$ gives an explicit isomorphism. From this, it is easy to convert elements between the $A(u)\in \Q(u)$ and $B(v)\in \Q(v)$ representations: \bprog ? A = u^2 + 2*u + 3; subst(lift(A), 'x, w) %3 = Mod(x^2 - 3*x + 3, x^3 - 5*x^2 + 4*x - 1) ? B = v^2 + v + 1; subst(lift(B), 'x, v) %4 = Mod(26*x^2 + 31*x + 26, x^3 - x - 1) @eprog If the minimal polynomial of $z$ has lower degree than expected, the routine fails \bprog ? u = Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1) ? modreverse(u) *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4 *** Break loop: type 'break' to go back to GP prompt break> Vec( dbg_err() ) \\ ask for more info ["e_DOMAIN", "modreverse", "deg(minpoly(z))", "<", 4, Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1)] break> minpoly(u) x^2 - 8 @eprog The library syntax is \fun{GEN}{modreverse}{GEN z}. \subsec{newtonpoly$(x,p)$}\kbdsidx{newtonpoly}\label{se:newtonpoly} Gives the vector of the slopes of the Newton polygon of the polynomial $x$ with respect to the prime number $p$. The $n$ components of the vector are in decreasing order, where $n$ is equal to the degree of $x$. Vertical slopes occur iff the constant coefficient of $x$ is zero and are denoted by \tet{LONG_MAX}, the biggest single precision integer representable on the machine ($2^{31}-1$ (resp.~$2^{63}-1$) on 32-bit (resp.~64-bit) machines), see \secref{se:valuation}. The library syntax is \fun{GEN}{newtonpoly}{GEN x, GEN p}. \subsec{nfalgtobasis$(\var{nf},x)$}\kbdsidx{nfalgtobasis}\label{se:nfalgtobasis} Given an algebraic number $x$ in the number field $\var{nf}$, transforms it to a column vector on the integral basis \kbd{\var{nf}.zk}. \bprog ? nf = nfinit(y^2 + 4); ? nf.zk %2 = [1, 1/2*y] ? nfalgtobasis(nf, [1,1]~) %3 = [1, 1]~ ? nfalgtobasis(nf, y) %4 = [0, 2]~ ? nfalgtobasis(nf, Mod(y, y^2+4)) %4 = [0, 2]~ @eprog This is the inverse function of \kbd{nfbasistoalg}. The library syntax is \fun{GEN}{algtobasis}{GEN nf, GEN x}. \subsec{nfbasis$(T)$}\kbdsidx{nfbasis}\label{se:nfbasis} Let $T(X)$ be an irreducible polynomial with integral coefficients. This function returns an \idx{integral basis} of the number field defined by $T$, that is a $\Z$-basis of its maximal order. The basis elements are given as elements in $\Q[X]/(T)$: \bprog ? nfbasis(x^2 + 1) %1 = [1, x] @eprog This function uses a modified version of the \idx{round 4} algorithm, due to David \idx{Ford}, Sebastian \idx{Pauli} and Xavier \idx{Roblot}. \misctitle{Local basis, orders maximal at certain primes} Obtaining the maximal order is hard: it requires factoring the discriminant $D$ of $T$. Obtaining an order which is maximal at a finite explicit set of primes is easy, but if may then be a strict suborder of the maximal order. To specify that we are interested in a given set of places only, we can replace the argument $T$ by an argument $[T,\var{listP}]$, where \var{listP} encodes the primes we are interested in: it must be a factorization matrix, a vector of integers or a single integer. \item Vector: we assume that it contains distinct \emph{prime} numbers. \item Matrix: we assume that it is a two-column matrix of a (partial) factorization of $D$; namely the first column contains \emph{primes} and the second one the valuation of $D$ at each of these primes. \item Integer $B$: this is replaced by the vector of primes up to $B$. Note that the function will use at least $O(B)$ time: a small value, about $10^5$, should be enough for most applications. Values larger than $2^{32}$ are not supported. In all these cases, the primes may or may not divide the discriminant $D$ of $T$. The function then returns a $\Z$-basis of an order whose index is not divisible by any of these prime numbers. The result is actually a global integral basis if all prime divisors of the \emph{field} discriminant are included! Note that \kbd{nfinit} has built-in support for such a check: \bprog ? K = nfinit([T, listP]); ? nfcertify(K) \\ we computed an actual maximal order %2 = []; @eprog\noindent The first line initializes a number field structure incorporating \kbd{nfbasis([T, listP]} in place of a proven integral basis. The second line certifies that the resulting structure is correct. This allows to create an \kbd{nf} structure associated to the number field $K = \Q[X]/(T)$, when the discriminant of $T$ cannot be factored completely, whereas the prime divisors of $\disc K$ are known. Of course, if \var{listP} contains a single prime number $p$, the function returns a local integral basis for $\Z_p[X]/(T)$: \bprog ? nfbasis(x^2+x-1001) %1 = [1, 1/3*x - 1/3] ? nfbasis( [x^2+x-1001, [2]] ) %2 = [1, x] @eprog \misctitle{The Buchmann-Lenstra algorithm} We now complicate the picture: it is in fact allowed to include \emph{composite} numbers instead of primes in \kbd{listP} (Vector or Matrix case), provided they are pairwise coprime. The result will still be a correct integral basis \emph{if} the field discriminant factors completely over the actual primes in the list. Adding a composite $C$ such that $C^2$ \emph{divides} $D$ may help because when we consider $C$ as a prime and run the algorithm, two good things can happen: either we succeed in proving that no prime dividing $C$ can divide the index (without actually needing to find those primes), or the computation exhibits a non-trivial zero divisor, thereby factoring $C$ and we go on with the refined factorization. (Note that including a $C$ such that $C^2$ does not divide $D$ is useless.) If neither happen, then the computed basis need not generate the maximal order. Here is an example: \bprog ? B = 10^5; ? P = factor(poldisc(T), B)[,1]; \\ primes <= B dividing D + cofactor ? basis = nfbasis([T, listP]) ? disc = nfdisc([T, listP]) @eprog\noindent We obtain the maximal order and its discriminant if the field discriminant factors completely over the primes less than $B$ (together with the primes contained in the \tet{addprimes} table). This can be tested as follows: \bprog check = factor(disc, B); lastp = check[-1..-1,1]; if (lastp > B && !setsearch(addprimes(), lastp), warning("nf may be incorrect!")) @eprog\noindent This is a sufficient but not a necessary condition, hence the warning, instead of an error. N.B. \kbd{lastp} is the last entry in the first column of the \kbd{check} matrix, i.e. the largest prime dividing \kbd{nf.disc} if $\leq B$ or if it belongs to the prime table. The function \tet{nfcertify} speeds up and automates the above process: \bprog ? B = 10^5; ? nf = nfinit([T, B]); ? nfcertify(nf) %3 = [] \\ nf is unconditionally correct ? basis = nf.zk; ? disc = nf.disc; @eprog \synt{nfbasis}{GEN T, GEN *d, GEN listP = NULL}, which returns the order basis, and where \kbd{*d} receives the order discriminant. \subsec{nfbasistoalg$(\var{nf},x)$}\kbdsidx{nfbasistoalg}\label{se:nfbasistoalg} Given an algebraic number $x$ in the number field \kbd{nf}, transforms it into \typ{POLMOD} form. \bprog ? nf = nfinit(y^2 + 4); ? nf.zk %2 = [1, 1/2*y] ? nfbasistoalg(nf, [1,1]~) %3 = Mod(1/2*y + 1, y^2 + 4) ? nfbasistoalg(nf, y) %4 = Mod(y, y^2 + 4) ? nfbasistoalg(nf, Mod(y, y^2+4)) %4 = Mod(y, y^2 + 4) @eprog This is the inverse function of \kbd{nfalgtobasis}. The library syntax is \fun{GEN}{basistoalg}{GEN nf, GEN x}. \subsec{nfcertify$(\var{nf})$}\kbdsidx{nfcertify}\label{se:nfcertify} $\var{nf}$ being as output by \kbd{nfinit}, checks whether the integer basis is known unconditionally. This is in particular useful when the argument to \kbd{nfinit} was of the form $[T, \kbd{listP}]$, specifying a finite list of primes when $p$-maximality had to be proven. The function returns a vector of composite integers. If this vector is empty, then \kbd{nf.zk} and \kbd{nf.disc} are correct. Otherwise, the result is dubious. In order to obtain a certified result, one must completely factor each of the given integers, then \kbd{addprime} each of them, then check whether \kbd{nfdisc(nf.pol)} is equal to \kbd{nf.disc}. The library syntax is \fun{GEN}{nfcertify}{GEN nf}. \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 is particularly useful in conjunction with \kbd{nfhnfmod}. The library syntax is \fun{GEN}{nfdetint}{GEN nf, GEN x}. \subsec{nfdisc$(T)$}\kbdsidx{nfdisc}\label{se:nfdisc} \idx{field discriminant} of the number field defined by the integral, preferably monic, irreducible polynomial $T(X)$. Returns the discriminant of the number field $\Q[X]/(T)$, using the Round $4$ algorithm. \misctitle{Local discriminants, valuations at certain primes} As in \kbd{nfbasis}, the argument $T$ can be replaced by $[T,\var{listP}]$, where \kbd{listP} is as in \kbd{nfbasis}: a vector of pairwise coprime integers (usually distinct primes), a factorization matrix, or a single integer. In that case, the function returns the discriminant of an order whose basis is given by \kbd{nfbasis(T,listP)}, which need not be the maximal order, and whose valuation at a prime entry in \kbd{listP} is the same as the valuation of the field discriminant. In particular, if \kbd{listP} is $[p]$ for a prime $p$, we can return the $p$-adic discriminant of the maximal order of $\Z_p[X]/(T)$, as a power of $p$, as follows: \bprog ? padicdisc(T,p) = p^valuation(nfdisc(T,[p]), p); ? nfdisc(x^2 + 6) %1 = -24 ? padicdisc(x^2 + 6, 2) %2 = 8 ? padicdisc(x^2 + 6, 3) %3 = 3 @eprog \synt{nfdisc}{GEN T} (\kbd{listP = NULL}). Also available is \fun{GEN}{nfbasis}{GEN T, GEN *d, GEN listP = NULL}, which returns the order basis, and where \kbd{*d} receives the order discriminant. \subsec{nfeltadd$(\var{nf},x,y)$}\kbdsidx{nfeltadd}\label{se:nfeltadd} Given two elements $x$ and $y$ in \var{nf}, computes their sum $x+y$ in the number field $\var{nf}$. The library syntax is \fun{GEN}{nfadd}{GEN nf, GEN x, GEN y}. \subsec{nfeltdiv$(\var{nf},x,y)$}\kbdsidx{nfeltdiv}\label{se:nfeltdiv} Given two elements $x$ and $y$ in \var{nf}, computes their quotient $x/y$ in the number field $\var{nf}$. The library syntax is \fun{GEN}{nfdiv}{GEN nf, GEN x, GEN y}. \subsec{nfeltdiveuc$(\var{nf},x,y)$}\kbdsidx{nfeltdiveuc}\label{se:nfeltdiveuc} Given two elements $x$ and $y$ in \var{nf}, computes an algebraic integer $q$ in the number field $\var{nf}$ such that the components of $x-qy$ are reasonably small. In fact, this is functionally identical to \kbd{round(nfdiv(\var{nf},x,y))}. The library syntax is \fun{GEN}{nfdiveuc}{GEN nf, GEN x, GEN y}. \subsec{nfeltdivmodpr$(\var{nf},x,y,\var{pr})$}\kbdsidx{nfeltdivmodpr}\label{se:nfeltdivmodpr} Given two elements $x$ and $y$ in \var{nf} and \var{pr} a prime ideal in \kbd{modpr} format (see \tet{nfmodprinit}), computes their quotient $x / y$ modulo the prime ideal \var{pr}. The library syntax is \fun{GEN}{nfdivmodpr}{GEN nf, GEN x, GEN y, GEN pr}. This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. \subsec{nfeltdivrem$(\var{nf},x,y)$}\kbdsidx{nfeltdivrem}\label{se:nfeltdivrem} Given two elements $x$ and $y$ in \var{nf}, gives a two-element row vector $[q,r]$ such that $x=qy+r$, $q$ is an algebraic integer in $\var{nf}$, and the components of $r$ are reasonably small. The library syntax is \fun{GEN}{nfdivrem}{GEN nf, GEN x, GEN y}. \subsec{nfeltmod$(\var{nf},x,y)$}\kbdsidx{nfeltmod}\label{se:nfeltmod} Given two elements $x$ and $y$ in \var{nf}, computes an element $r$ of $\var{nf}$ of the form $r=x-qy$ with $q$ and algebraic integer, and such that $r$ is small. This is functionally identical to $$\kbd{x - nfmul(\var{nf},round(nfdiv(\var{nf},x,y)),y)}.$$ The library syntax is \fun{GEN}{nfmod}{GEN nf, GEN x, GEN y}. \subsec{nfeltmul$(\var{nf},x,y)$}\kbdsidx{nfeltmul}\label{se:nfeltmul} Given two elements $x$ and $y$ in \var{nf}, computes their product $x*y$ in the number field $\var{nf}$. The library syntax is \fun{GEN}{nfmul}{GEN nf, GEN x, GEN y}. \subsec{nfeltmulmodpr$(\var{nf},x,y,\var{pr})$}\kbdsidx{nfeltmulmodpr}\label{se:nfeltmulmodpr} Given two elements $x$ and $y$ in \var{nf} and \var{pr} a prime ideal in \kbd{modpr} format (see \tet{nfmodprinit}), computes their product $x*y$ modulo the prime ideal \var{pr}. The library syntax is \fun{GEN}{nfmulmodpr}{GEN nf, GEN x, GEN y, GEN pr}. This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. \subsec{nfeltnorm$(\var{nf},x)$}\kbdsidx{nfeltnorm}\label{se:nfeltnorm} Returns the absolute norm of $x$. The library syntax is \fun{GEN}{nfnorm}{GEN nf, GEN x}. \subsec{nfeltpow$(\var{nf},x,k)$}\kbdsidx{nfeltpow}\label{se:nfeltpow} Given an element $x$ in \var{nf}, and a positive or negative integer $k$, computes $x^k$ in the number field $\var{nf}$. The library syntax is \fun{GEN}{nfpow}{GEN nf, GEN x, GEN k}. \fun{GEN}{nfinv}{GEN nf, GEN x} correspond to $k = -1$, and \fun{GEN}{nfsqr}{GEN nf,GEN x} to $k = 2$. \subsec{nfeltpowmodpr$(\var{nf},x,k,\var{pr})$}\kbdsidx{nfeltpowmodpr}\label{se:nfeltpowmodpr} Given an element $x$ in \var{nf}, an integer $k$ and a prime ideal \var{pr} in \kbd{modpr} format (see \tet{nfmodprinit}), computes $x^k$ modulo the prime ideal \var{pr}. The library syntax is \fun{GEN}{nfpowmodpr}{GEN nf, GEN x, GEN k, GEN pr}. This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. \subsec{nfeltreduce$(\var{nf},a,\var{id})$}\kbdsidx{nfeltreduce}\label{se:nfeltreduce} Given an ideal \var{id} in Hermite normal form and an element $a$ of the number field $\var{nf}$, finds an element $r$ in $\var{nf}$ such that $a-r$ belongs to the ideal and $r$ is small. The library syntax is \fun{GEN}{nfreduce}{GEN nf, GEN a, GEN id}. \subsec{nfeltreducemodpr$(\var{nf},x,\var{pr})$}\kbdsidx{nfeltreducemodpr}\label{se:nfeltreducemodpr} Given an element $x$ of the number field $\var{nf}$ and a prime ideal \var{pr} in \kbd{modpr} format compute a canonical representative for the class of $x$ modulo \var{pr}. The library syntax is \fun{GEN}{nfreducemodpr}{GEN nf, GEN x, GEN pr}. This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. \subsec{nfelttrace$(\var{nf},x)$}\kbdsidx{nfelttrace}\label{se:nfelttrace} 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} 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{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}. \subsec{nffactor$(\var{nf},T)$}\kbdsidx{nffactor}\label{se:nffactor} Factorization of the univariate polynomial $T$ over the number field $\var{nf}$ given by \kbd{nfinit}; $T$ has coefficients in $\var{nf}$ (i.e.~either scalar, polmod, polynomial or column vector). The factors are sorted by increasing degree. The main variable of $\var{nf}$ must be of \emph{lower} priority than that of $T$, see \secref{se:priority}. However if the polynomial defining the number field occurs explicitly in the coefficients of $T$ as modulus of a \typ{POLMOD} or as a \typ{POL} coefficient, its main variable must be \emph{the same} as the main variable of $T$. For example, \bprog ? nf = nfinit(y^2 + 1); ? nffactor(nf, x^2 + y); \\@com OK ? nffactor(nf, x^2 + Mod(y, y^2+1)); \\ @com OK ? nffactor(nf, x^2 + Mod(z, z^2+1)); \\ @com WRONG @eprog It is possible to input a defining polynomial for \var{nf} instead, but this is in general less efficient since parts of an \kbd{nf} structure will then be computed internally. This is useful in two situations: when you do not need the \kbd{nf} elsewhere, or when you cannot compute the field discriminant due to integer factorization difficulties. In the latter case, if you must use a partial discriminant factorization (as allowed by both \tet{nfdisc} or \tet{nfbasis}) to build a partially correct \var{nf} structure, always input \kbd{nf.pol} to \kbd{nffactor}, and not your makeshift \var{nf}: otherwise factors could be missed. The library syntax is \fun{GEN}{nffactor}{GEN nf, GEN T}. \subsec{nffactorback$(\var{nf},f,\{e\})$}\kbdsidx{nffactorback}\label{se:nffactorback} Gives back the \kbd{nf} element corresponding to a factorization. The integer $1$ corresponds to the empty factorization. If $e$ is present, $e$ and $f$ must be vectors of the same length ($e$ being integral), and the corresponding factorization is the product of the $f[i]^{e[i]}$. If not, and $f$ is vector, it is understood as in the preceding case with $e$ a vector of 1s: we return the product of the $f[i]$. Finally, $f$ can be a regular factorization matrix. \bprog ? nf = nfinit(y^2+1); ? nffactorback(nf, [3, y+1, [1,2]~], [1, 2, 3]) %2 = [12, -66]~ ? 3 * (I+1)^2 * (1+2*I)^3 %3 = 12 - 66*I @eprog The library syntax is \fun{GEN}{nffactorback}{GEN nf, GEN f, GEN e = NULL}. \subsec{nffactormod$(\var{nf},Q,\var{pr})$}\kbdsidx{nffactormod}\label{se:nffactormod} Factors the univariate polynomial $Q$ modulo the prime ideal \var{pr} in the number field $\var{nf}$. The coefficients of $Q$ belong to the number field (scalar, polmod, polynomial, even column vector) and the main variable of $\var{nf}$ must be of lower priority than that of $Q$ (see \secref{se:priority}). The prime ideal \var{pr} is either in \tet{idealprimedec} or (preferred) \tet{modprinit} format. The coefficients of the polynomial factors are lifted to elements of \var{nf}: \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? nffactormod(K, x^2 + y*x + 18*y+1, P) %3 = [x + (2*y + 1) 1] [x + (2*y + 2) 1] ? P = nfmodprinit(K, P); \\ convert to nfmodprinit format ? nffactormod(K, x^2 + y*x + 18*y+1) [x + (2*y + 1) 1] [x + (2*y + 2) 1] @eprog\noindent Same result, of course, here about 10\% faster due to the precomputation. The library syntax is \fun{GEN}{nffactormod}{GEN nf, GEN Q, GEN pr}. \subsec{nfgaloisapply$(\var{nf},\var{aut},x)$}\kbdsidx{nfgaloisapply}\label{se:nfgaloisapply} Let $\var{nf}$ be a number field as output by \kbd{nfinit}, and let \var{aut} be a \idx{Galois} automorphism of $\var{nf}$ expressed by its image on the field generator (such automorphisms can be found using \kbd{nfgaloisconj}). The function computes the action of the automorphism \var{aut} on the object $x$ in the number field; $x$ can be a number field element, or an ideal (possibly extended). Because of possible confusion with elements and ideals, other vector or matrix arguments are forbidden. \bprog ? nf = nfinit(x^2+1); ? L = nfgaloisconj(nf) %2 = [-x, x]~ ? aut = L[1]; /* the non-trivial automorphism */ ? nfgaloisapply(nf, aut, x) %4 = Mod(-x, x^2 + 1) ? P = idealprimedec(nf,5); /* prime ideals above 5 */ ? nfgaloisapply(nf, aut, P[2]) == P[1] %7 = 0 \\ !!!! ? idealval(nf, nfgaloisapply(nf, aut, P[2]), P[1]) %8 = 1 @eprog\noindent The surprising failure of the equality test (\kbd{\%7}) is due to the fact that although the corresponding prime ideals are equal, their representations are not. (A prime ideal is specified by a uniformizer, and there is no guarantee that applying automorphisms yields the same elements as a direct \kbd{idealprimedec} call.) The automorphism can also be given as a column vector, representing the image of \kbd{Mod(x, nf.pol)} as an algebraic number. This last representation is more efficient and should be preferred if a given automorphism must be used in many such calls. \bprog ? nf = nfinit(x^3 - 37*x^2 + 74*x - 37); ? l = nfgaloisconj(nf); aut = l[2] \\ @com automorphisms in basistoalg form %2 = -31/11*x^2 + 1109/11*x - 925/11 ? L = matalgtobasis(nf, l); AUT = L[2] \\ @com same in algtobasis form %3 = [16, -6, 5]~ ? v = [1, 2, 3]~; nfgaloisapply(nf, aut, v) == nfgaloisapply(nf, AUT, v) %4 = 1 \\ @com same result... ? for (i=1,10^5, nfgaloisapply(nf, aut, v)) time = 1,451 ms. ? for (i=1,10^5, nfgaloisapply(nf, AUT, v)) time = 1,045 ms. \\ @com but the latter is faster @eprog The library syntax is \fun{GEN}{galoisapply}{GEN nf, GEN aut, GEN x}. \subsec{nfgaloisconj$(\var{nf},\{\fl=0\},\{d\})$}\kbdsidx{nfgaloisconj}\label{se:nfgaloisconj} $\var{nf}$ being a number field as output by \kbd{nfinit}, computes the conjugates of a root $r$ of the non-constant polynomial $x=\var{nf}[1]$ expressed as polynomials in $r$. This also makes sense when the number field is not \idx{Galois} since some conjugates may lie in the field. $\var{nf}$ can simply be a polynomial. If no flags or $\fl=0$, use a combination of flag $4$ and $1$ and the result is always complete. There is no point whatsoever in using the other flags. If $\fl=1$, use \kbd{nfroots}: a little slow, but guaranteed to work in polynomial time. If $\fl=2$ (OBSOLETE), use complex approximations to the roots and an integral \idx{LLL}. The result is not guaranteed to be complete: some conjugates may be missing (a warning is issued if the result is not proved complete), especially so if the corresponding polynomial has a huge index, and increasing the default precision may help. This variant is slow and unreliable: don't use it. If $\fl=4$, use \kbd{galoisinit}: very fast, but only applies to (most) Galois fields. If the field is Galois with weakly super-solvable Galois group (see \tet{galoisinit}), return the complete list of automorphisms, else only the identity element. If present, $d$ is assumed to be a multiple of the least common denominator of the conjugates expressed as polynomial in a root of \var{pol}. This routine can only compute $\Q$-automorphisms, but it may be used to get $K$-automorphism for any base field $K$ as follows: \bprog rnfgaloisconj(nfK, R) = \\ K-automorphisms of L = K[X] / (R) { my(polabs, N); R *= Mod(1, nfK.pol); \\ convert coeffs to polmod elts of K polabs = rnfequation(nfK, R); N = nfgaloisconj(polabs) % R; \\ Q-automorphisms of L \\ select the ones that fix K select(s->subst(R, variable(R), Mod(s,R)) == 0, N); } K = nfinit(y^2 + 7); rnfgaloisconj(K, x^4 - y*x^3 - 3*x^2 + y*x + 1) \\ K-automorphisms of L @eprog The library syntax is \fun{GEN}{galoisconj0}{GEN nf, long flag, GEN d = NULL, long prec}. Use directly \fun{GEN}{galoisconj}{GEN nf, GEN d}, corresponding to $\fl = 0$, the others only have historical interest. \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 is $1$ if $x^2 - a y^2 - b z^2$ has a non trivial solution $(x,y,z)$ in $\var{nf}$, and $-1$ otherwise. Otherwise compute the local symbol modulo the prime ideal \var{pr}, as output by \kbd{idealprimedec}. 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} Given a pseudo-matrix $(A,I)$, finds a pseudo-basis in \idx{Hermite normal form} of the module it generates. The library syntax is \fun{GEN}{nfhnf}{GEN nf, GEN x}. Also available: \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. \subsec{nfhnfmod$(\var{nf},x,\var{detx})$}\kbdsidx{nfhnfmod}\label{se:nfhnfmod} Given a pseudo-matrix $(A,I)$ and an ideal \var{detx} which is contained in (read integral multiple of) the determinant of $(A,I)$, finds a pseudo-basis in \idx{Hermite normal form} of the module generated by $(A,I)$. This avoids coefficient explosion. \var{detx} can be computed using the function \kbd{nfdetint}. The library syntax is \fun{GEN}{nfhnfmod}{GEN nf, GEN x, GEN detx}. \subsec{nfinit$(\var{pol},\{\fl=0\})$}\kbdsidx{nfinit}\label{se:nfinit} \var{pol} being a non-constant, preferably monic, irreducible polynomial in $\Z[X]$, initializes a \emph{number field} structure (\kbd{nf}) associated to the field $K$ defined by \var{pol}. As such, it's a technical object passed as the first argument to most \kbd{nf}\var{xxx} functions, but it contains some information which may be directly useful. Access to this information via \emph{member functions} is preferred since the specific data organization specified below may change in the future. Currently, \kbd{nf} is a row vector with 9 components: $\var{nf}[1]$ contains the polynomial \var{pol} (\kbd{\var{nf}.pol}). $\var{nf}[2]$ contains $[r1,r2]$ (\kbd{\var{nf}.sign}, \kbd{\var{nf}.r1}, \kbd{\var{nf}.r2}), the number of real and complex places of $K$. $\var{nf}[3]$ contains the discriminant $d(K)$ (\kbd{\var{nf}.disc}) of $K$. $\var{nf}[4]$ contains the index of $\var{nf}[1]$ (\kbd{\var{nf}.index}), i.e.~$[\Z_K : \Z[\theta]]$, where $\theta$ is any root of $\var{nf}[1]$. $\var{nf}[5]$ is a vector containing 7 matrices $M$, $G$, \var{roundG}, $T$, $MD$, $TI$, $MDI$ useful for certain computations in the number field $K$. \quad\item $M$ is the $(r1+r2)\times n$ matrix whose columns represent the numerical values of the conjugates of the elements of the integral basis. \quad\item $G$ is an $n\times n$ matrix such that $T2 = {}^t G G$, where $T2$ is the quadratic form $T_2(x) = \sum |\sigma(x)|^2$, $\sigma$ running over the embeddings of $K$ into $\C$. \quad\item \var{roundG} is a rescaled copy of $G$, rounded to nearest integers. \quad\item $T$ is the $n\times n$ matrix whose coefficients are $\text{Tr}(\omega_i\omega_j)$ where the $\omega_i$ are the elements of the integral basis. Note also that $\det(T)$ is equal to the discriminant of the field $K$. Also, when understood as an ideal, the matrix $T^{-1}$ generates the codifferent ideal. \quad\item The columns of $MD$ (\kbd{\var{nf}.diff}) express a $\Z$-basis of the different of $K$ on the integral basis. \quad\item $TI$ is equal to the primitive part of $T^{-1}$, which has integral coefficients. \quad\item Finally, $MDI$ is a two-element representation (for faster ideal product) of $d(K)$ times the codifferent ideal (\kbd{\var{nf}.disc$*$\var{nf}.codiff}, which is an integral ideal). $MDI$ is only used in \tet{idealinv}. $\var{nf}[6]$ is the vector containing the $r1+r2$ roots (\kbd{\var{nf}.roots}) of $\var{nf}[1]$ corresponding to the $r1+r2$ embeddings of the number field into $\C$ (the first $r1$ components are real, the next $r2$ have positive imaginary part). $\var{nf}[7]$ is an integral basis for $\Z_K$ (\kbd{\var{nf}.zk}) expressed on the powers of~$\theta$. Its first element is guaranteed to be $1$. This basis is LLL-reduced with respect to $T_2$ (strictly speaking, it is a permutation of such a basis, due to the condition that the first element be $1$). $\var{nf}[8]$ is the $n\times n$ integral matrix expressing the power basis in terms of the integral basis, and finally $\var{nf}[9]$ is the $n\times n^2$ matrix giving the multiplication table 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. \bprog ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12) ? nf.pol \\ defining polynomial %2 = x^3 - 12 ? nf.disc \\ field discriminant %3 = -972 ? nf.index \\ index of power basis order in maximal order %4 = 2 ? nf.zk \\ integer basis, lifted to Q[X] %5 = [1, x, 1/2*x^2] ? nf.sign \\ signature %6 = [1, 1] ? factor(abs(nf.disc )) \\ determines ramified primes %7 = [2 2] [3 5] ? idealfactor(nf, 2) %8 = [[2, [0, 0, -1]~, 3, 1, [0, 1, 0]~] 3] \\ @com $\goth{p}_2^3$ @eprog \misctitle{Huge discriminants, helping nfdisc} In case \var{pol} has a huge discriminant which is difficult to factor, it is hard to compute from scratch the maximal order. The special input format $[\var{pol}, B]$ is also accepted where \var{pol} is a polynomial as above and $B$ has one of the following forms \item an integer basis, as would be computed by \tet{nfbasis}: a vector of polynomials with first element $1$. This is useful if the maximal order is known in advance. \item an argument \kbd{listP} which specifies a list of primes (see \tet{nfbasis}). Instead of the maximal order, \kbd{nfinit} then computes an order which is maximal at these particular primes as well as the primes contained in the private prime table (see \tet{addprimes}). The result is unconditionaly correct when the discriminant \kbd{nf.disc} factors completely over this set of primes. The function \tet{nfcertify} automates this: \bprog ? pol = polcompositum(x^5 - 101, polcyclo(7))[1]; ? nf = nfinit( [pol, 10^3] ); ? nfcertify(nf) %3 = [] @eprog\noindent A priori, \kbd{nf.zk} defines an order which is only known to be maximal at all primes $\leq 10^3$ (no prime $\leq 10^3$ divides \kbd{nf.index}). The certification step proves the correctness of the computation. \medskip If $\fl=2$: \var{pol} is changed into another polynomial $P$ defining the same number field, which is as simple as can easily be found using the \tet{polredbest} algorithm, and all the subsequent computations are done using this new polynomial. In particular, the first component of the result is the modified polynomial. If $\fl=3$, apply \kbd{polredbest} as in case 2, but outputs $[\var{nf},\kbd{Mod}(a,P)]$, where $\var{nf}$ is as before and $\kbd{Mod}(a,P)=\kbd{Mod}(x,\var{pol})$ gives the change of variables. This is implicit when \var{pol} is not monic: first a linear change of variables is performed, to get a monic polynomial, then \kbd{polredbest}. The library syntax is \fun{GEN}{nfinit0}{GEN pol, long flag, long prec}. Also available are \fun{GEN}{nfinit}{GEN x, long prec} ($\fl = 0$), \fun{GEN}{nfinitred}{GEN x, long prec} ($\fl = 2$), \fun{GEN}{nfinitred2}{GEN x, long prec} ($\fl = 3$). Instead of the above hardcoded numerical flags in \kbd{nfinit0}, one should rather use \fun{GEN}{nfinitall}{GEN x, long flag, long prec}, where \fl\ is an or-ed combination of \item \tet{nf_RED}: find a simpler defining polynomial, \item \tet{nf_ORIG}: if \tet{nf_RED} set, also return the change of variable, \item \tet{nf_ROUND2}: \emph{Deprecated}. Slow down the routine by using an obsolete normalization algorithm (do not use this one!), \item \tet{nf_PARTIALFACT}: \emph{Deprecated}. Lazy factorization of the polynomial discriminant. Result is conditional unless \kbd{nfcertify} can certify it. \subsec{nfisideal$(\var{nf},x)$}\kbdsidx{nfisideal}\label{se:nfisideal} Returns 1 if $x$ is an ideal in the number field $\var{nf}$, 0 otherwise. The library syntax is \fun{long}{isideal}{GEN nf, GEN x}. \subsec{nfisincl$(x,y)$}\kbdsidx{nfisincl}\label{se:nfisincl} Tests whether the number field $K$ defined by the polynomial $x$ is conjugate to a subfield of the field $L$ defined by $y$ (where $x$ and $y$ must be in $\Q[X]$). If they are not, the output is the number 0. If they are, the output is a vector of polynomials, each polynomial $a$ representing an embedding of $K$ into $L$, i.e.~being such that $y\mid x\circ a$. If $y$ is a number field (\var{nf}), a much faster algorithm is used (factoring $x$ over $y$ using \tet{nffactor}). Before version 2.0.14, this wasn't guaranteed to return all the embeddings, hence was triggered by a special flag. This is no more the case. The library syntax is \fun{GEN}{nfisincl}{GEN x, GEN y}. \subsec{nfisisom$(x,y)$}\kbdsidx{nfisisom}\label{se:nfisisom} As \tet{nfisincl}, but tests for isomorphism. If either $x$ or $y$ is a number field, a much faster algorithm will be used. The library syntax is \fun{GEN}{nfisisom}{GEN x, GEN y}. \subsec{nfkermodpr$(\var{nf},x,\var{pr})$}\kbdsidx{nfkermodpr}\label{se:nfkermodpr} Kernel of the matrix $a$ in $\Z_K/\var{pr}$, where \var{pr} is in \key{modpr} format (see \kbd{nfmodprinit}). The library syntax is \fun{GEN}{nfkermodpr}{GEN nf, GEN x, GEN pr}. This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nfM\_to\_FqM}, then work there. \subsec{nfmodprinit$(\var{nf},\var{pr})$}\kbdsidx{nfmodprinit}\label{se:nfmodprinit} Transforms the prime ideal \var{pr} into \tet{modpr} format necessary for all operations modulo \var{pr} in the number field \var{nf}. The library syntax is \fun{GEN}{nfmodprinit}{GEN nf, GEN pr}. \subsec{nfnewprec$(\var{nf})$}\kbdsidx{nfnewprec}\label{se:nfnewprec} Transforms the number field $\var{nf}$ into the corresponding data using current (usually larger) precision. This function works as expected if $\var{nf}$ is in fact a $\var{bnf}$ (update $\var{bnf}$ to current precision) but may be quite slow (many generators of principal ideals have to be computed). The library syntax is \fun{GEN}{nfnewprec}{GEN nf, long prec}. See also \fun{GEN}{bnfnewprec}{GEN bnf, long prec} and \fun{GEN}{bnrnewprec}{GEN bnr, long prec}. \subsec{nfroots$(\{\var{nf}\},x)$}\kbdsidx{nfroots}\label{se:nfroots} Roots of the polynomial $x$ in the number field $\var{nf}$ given by \kbd{nfinit} without multiplicity (in $\Q$ if $\var{nf}$ is omitted). $x$ has coefficients in the number field (scalar, polmod, polynomial, column vector). The main variable of $\var{nf}$ must be of lower priority than that of $x$ (see \secref{se:priority}). However if the coefficients of the number field occur explicitly (as polmods) as coefficients of $x$, the variable of these polmods \emph{must} be the same as the main variable of $t$ (see \kbd{nffactor}). It is possible to input a defining polynomial for \var{nf} instead, but this is in general less efficient since parts of an \kbd{nf} structure will be computed internally. This is useful in two situations: when you don't need the \kbd{nf}, or when you can't compute its discriminant due to integer factorization difficulties. In the latter case, \tet{addprimes} is a possibility but a dangerous one: roots will probably be missed if the (true) field discriminant and an \kbd{addprimes} entry are strictly divisible by some prime. If you have such an unsafe \var{nf}, it is safer to input \kbd{nf.pol}. The library syntax is \fun{GEN}{nfroots}{GEN nf = NULL, GEN x}. See also \fun{GEN}{nfrootsQ}{GEN x}, corresponding to $\kbd{nf} = \kbd{NULL}$. \subsec{nfrootsof1$(\var{nf})$}\kbdsidx{nfrootsof1}\label{se:nfrootsof1} Returns a two-component vector $[w,z]$ where $w$ is the number of roots of unity in the number field \var{nf}, and $z$ is a primitive $w$-th root of unity. \bprog ? K = nfinit(polcyclo(11)); ? nfrootsof1(K) %2 = [22, [0, 0, 0, 0, 0, -1, 0, 0, 0, 0]~] ? z = nfbasistoalg(K, %[2]) \\ in algebraic form %3 = Mod(-x^5, x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) ? [lift(z^11), lift(z^2)] \\ proves that the order of z is 22 %4 = [-1, -x^9 - x^8 - x^7 - x^6 - x^5 - x^4 - x^3 - x^2 - x - 1] @eprog This function guesses the number $w$ as the gcd of the $\#k(v)^*$ for unramified $v$ above odd primes, then computes the roots in \var{nf} of the $w$-th cyclotomic polynomial: the algorithm is polynomial time with respect to the field degree and the bitsize of the multiplication table in \var{nf} (both of them polynomially bounded in terms of the size of the discriminant). Fields of degree up to $100$ or so should require less than one minute. The library syntax is \fun{GEN}{rootsof1}{GEN nf}. Also available is \fun{GEN}{rootsof1_kannan}{GEN nf}, that computes all algebraic integers of $T_2$ norm equal to the field degree (all roots of $1$, by Kronecker's theorem). This is in general a little 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$. 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 $I = [b_1,\dots,b_n]$ and $J = [a_1,\dots,a_n]$ are two ideal lists, and $A$ is a square $n\times n$ matrix with columns $(A_1,\dots,A_n)$, seen as elements in $K^n$ (with canonical basis $(e_1,\dots,e_n)$). This data defines the $\Z_K$ module $x$ given by $$ (b_1e_1\oplus\cdots\oplus b_ne_n) / (a_1A_1\oplus\cdots\oplus a_nA_n) \enspace, $$ The integrality condition is $a_{i,j} \in b_i a_j^{-1}$ for all $i,j$. If it 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}. \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}), let $a$ be a matrix, invertible over the residue field, and let $b$ be a column vector or matrix. This function returns a solution of $a\cdot x = b$; the coefficients of $x$ are lifted to \var{nf} elements. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? P = nfmodprinit(K, P); ? a = [y+1, y; y, 0]; b = [1, y]~ ? nfsolvemodpr(K, a,b, P) %5 = [1, 2]~ @eprog 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{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 \var{pol} (all subfields if $d$ is null or omitted). The 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 $\var{nf}$. This routine uses J.~Kl\"uners's algorithm in the general case, and B.~Allombert's \tet{galoissubfields} when \var{nf} is Galois (with weakly supersolvable Galois group).\sidx{Galois}\sidx{subfield} The library syntax is \fun{GEN}{nfsubfields}{GEN pol, long d}. \subsec{polcompositum$(P,Q,\{\fl=0\})$}\kbdsidx{polcompositum}\label{se:polcompositum} \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))$. The factors are given by a list of polynomials $R$ in $\Z[X]$, associated to the number field $\Q(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 disjoint. Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it is in general much faster to proceed as follows \bprog nf = nfinit(P); L = nffactor(nf, Q)[,1]; vector(#L, i, rnfequation(nf, L[i])) @eprog\noindent 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$ 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$. 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})$: \bprog ? L = polcompositum(x^5 - 5, 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$) ? R \\@com defines the compositum %3 = x^20 + 5*x^19 + 15*x^18 + 35*x^17 + 70*x^16 + 141*x^15 + 260*x^14\ + 355*x^13 + 95*x^12 - 1460*x^11 - 3279*x^10 - 3660*x^9 - 2005*x^8 \ + 705*x^7 + 9210*x^6 + 13506*x^5 + 7145*x^4 - 2740*x^3 + 1040*x^2 \ - 320*x + 256 ? a^5 - 5 \\@com a fifth root of $5$ %4 = 0 ? [T, X] = polredbest(R, 1); ? T \\@com simpler defining polynomial for $\Q[x]/(R)$ %6 = x^20 + 25*x^10 + 5 ? X \\ @com root of $R$ in $\Q[y]/(T(y))$ %7 = Mod(-1/11*x^15 - 1/11*x^14 + 1/22*x^10 - 47/22*x^5 - 29/11*x^4 + 7/22,\ x^20 + 25*x^10 + 5) ? a = subst(a.pol, 'x, X) \\@com \kbd{a} in the new coordinates %8 = Mod(1/11*x^14 + 29/11*x^4, x^20 + 25*x^10 + 5) ? a^5 - 5 %9 = 0 @eprog The library syntax is \fun{GEN}{polcompositum0}{GEN P, GEN Q, long flag}. Also available are \fun{GEN}{compositum}{GEN P, GEN Q} ($\fl = 0$) and \fun{GEN}{compositum2}{GEN P, GEN Q} ($\fl = 1$). \subsec{polgalois$(T)$}\kbdsidx{polgalois}\label{se:polgalois} \idx{Galois} group of the non-constant polynomial $T\in\Q[X]$. In the present version \vers, $T$ must be irreducible and the degree $d$ of $T$ must be less than or equal to 7. If the \tet{galdata} package has been installed, degrees 8, 9, 10 and 11 are also implemented. By definition, if $K = \Q[x]/(T)$, this computes the action of the Galois group of the Galois closure of $K$ on the $d$ distinct roots of $T$, up to conjugacy (corresponding to different root orderings). The output is a 4-component vector $[n,s,k,name]$ with the following meaning: $n$ is the cardinality of the group, $s$ is its signature ($s=1$ if the group is a subgroup of the alternating group $A_d$, $s=-1$ otherwise) and name is a character string containing name of the transitive group according to the GAP 4 transitive groups library by Alexander Hulpke. $k$ is more arbitrary and the choice made up to version~2.2.3 of PARI is rather unfortunate: for $d > 7$, $k$ is the numbering of the group among all transitive subgroups of $S_d$, as given in ``The transitive groups of degree up to eleven'', G.~Butler and J.~McKay, \emph{Communications in Algebra}, vol.~11, 1983, pp.~863--911 (group $k$ is denoted $T_k$ there). And for $d \leq 7$, it was ad hoc, so as to ensure that a given triple would denote a unique group. Specifically, for polynomials of degree $d\leq 7$, the groups are coded as follows, using standard notations \smallskip In degree 1: $S_1=[1,1,1]$. \smallskip In degree 2: $S_2=[2,-1,1]$. \smallskip In degree 3: $A_3=C_3=[3,1,1]$, $S_3=[6,-1,1]$. \smallskip In degree 4: $C_4=[4,-1,1]$, $V_4=[4,1,1]$, $D_4=[8,-1,1]$, $A_4=[12,1,1]$, $S_4=[24,-1,1]$. \smallskip In degree 5: $C_5=[5,1,1]$, $D_5=[10,1,1]$, $M_{20}=[20,-1,1]$, $A_5=[60,1,1]$, $S_5=[120,-1,1]$. \smallskip In degree 6: $C_6=[6,-1,1]$, $S_3=[6,-1,2]$, $D_6=[12,-1,1]$, $A_4=[12,1,1]$, $G_{18}=[18,-1,1]$, $S_4^-=[24,-1,1]$, $A_4\times C_2=[24,-1,2]$, $S_4^+=[24,1,1]$, $G_{36}^-=[36,-1,1]$, $G_{36}^+=[36,1,1]$, $S_4\times C_2=[48,-1,1]$, $A_5=PSL_2(5)=[60,1,1]$, $G_{72}=[72,-1,1]$, $S_5=PGL_2(5)=[120,-1,1]$, $A_6=[360,1,1]$, $S_6=[720,-1,1]$. \smallskip In degree 7: $C_7=[7,1,1]$, $D_7=[14,-1,1]$, $M_{21}=[21,1,1]$, $M_{42}=[42,-1,1]$, $PSL_2(7)=PSL_3(2)=[168,1,1]$, $A_7=[2520,1,1]$, $S_7=[5040,-1,1]$. \smallskip This is deprecated and obsolete, but for reasons of backward compatibility, we cannot change this behavior yet. So you can use the default \tet{new_galois_format} to switch to a consistent naming scheme, namely $k$ is always the standard numbering of the group among all transitive subgroups of $S_n$. If this default is in effect, the above groups will be coded as: \smallskip In degree 1: $S_1=[1,1,1]$. \smallskip In degree 2: $S_2=[2,-1,1]$. \smallskip In degree 3: $A_3=C_3=[3,1,1]$, $S_3=[6,-1,2]$. \smallskip In degree 4: $C_4=[4,-1,1]$, $V_4=[4,1,2]$, $D_4=[8,-1,3]$, $A_4=[12,1,4]$, $S_4=[24,-1,5]$. \smallskip In degree 5: $C_5=[5,1,1]$, $D_5=[10,1,2]$, $M_{20}=[20,-1,3]$, $A_5=[60,1,4]$, $S_5=[120,-1,5]$. \smallskip In degree 6: $C_6=[6,-1,1]$, $S_3=[6,-1,2]$, $D_6=[12,-1,3]$, $A_4=[12,1,4]$, $G_{18}=[18,-1,5]$, $A_4\times C_2=[24,-1,6]$, $S_4^+=[24,1,7]$, $S_4^-=[24,-1,8]$, $G_{36}^-=[36,-1,9]$, $G_{36}^+=[36,1,10]$, $S_4\times C_2=[48,-1,11]$, $A_5=PSL_2(5)=[60,1,12]$, $G_{72}=[72,-1,13]$, $S_5=PGL_2(5)=[120,-1,14]$, $A_6=[360,1,15]$, $S_6=[720,-1,16]$. \smallskip In degree 7: $C_7=[7,1,1]$, $D_7=[14,-1,2]$, $M_{21}=[21,1,3]$, $M_{42}=[42,-1,4]$, $PSL_2(7)=PSL_3(2)=[168,1,5]$, $A_7=[2520,1,6]$, $S_7=[5040,-1,7]$. \smallskip \misctitle{Warning} The method used is that of resolvent polynomials and is sensitive to the current precision. The precision is updated internally but, in very rare cases, a wrong result may be returned if the initial precision was not sufficient. The library syntax is \fun{GEN}{polgalois}{GEN T, long prec}. To enable the new format in library mode, set the global variable \tet{new_galois_format} to $1$. \subsec{polred$(T,\{\fl=0\})$}\kbdsidx{polred}\label{se:polred} This function is \emph{deprecated}, use \tet{polredbest} instead. Finds polynomials with reasonably small coefficients defining subfields of the number field defined by $T$. One of the polynomials always defines $\Q$ (hence is equal to $x-1$), and another always defines the same number field as $T$ if $T$ is irreducible. All $T$ accepted by \tet{nfinit} are also allowed here; in particular, the format \kbd{[T, listP]} is recommended, e.g. with $\kbd{listP} = 10^5$ or a vector containing all ramified primes. Otherwise, the maximal order of $\Q[x]/(T)$ must be computed. The following binary digits of $\fl$ are significant: 1: Possibly use a suborder of the maximal order. The primes dividing the index of the order chosen are larger than \tet{primelimit} or divide integers stored in the \tet{addprimes} table. This flag is \emph{deprecated}, the \kbd{[T, listP]} format is more flexible. 2: gives also elements. The result is a two-column matrix, the first column giving primitive elements defining these subfields, the second giving the corresponding minimal polynomials. \bprog ? M = polred(x^4 + 8, 2) %1 = [1 x - 1] [1/2*x^2 x^2 + 2] [1/4*x^3 x^4 + 2] [x x^4 + 8] ? minpoly(Mod(M[2,1], x^4+8)) %2 = x^2 + 2 @eprog \synt{polred}{GEN T} ($\fl = 0$). Also available is \fun{GEN}{polred2}{GEN T} ($\fl = 2$). The function \kbd{polred0} is deprecated, provided for backward compatibility. \subsec{polredabs$(T,\{\fl=0\})$}\kbdsidx{polredabs}\label{se:polredabs} Returns a canonical defining polynomial $P$ for the number field $\Q[X]/(T)$ defined by $T$, such that the sum of the squares of the modulus of the roots (i.e.~the $T_2$-norm) is minimal. Different $T$ defining isomorphic number fields will yield the same $P$. All $T$ accepted by \tet{nfinit} are also allowed here, e.g. non-monic polynomials, or pairs \kbd{[T, listP]} specifying that a non-maximal order may be used. \misctitle{Warning 1} Using a \typ{POL} $T$ requires fully factoring the discriminant of $T$, which may be very hard. The format \kbd{[T, listP]} computes only a suborder of the maximal order and replaces this part of the algorithm by a polynomial time computation. In that case the polynomial $P$ is a priori no longer canonical, and it may happen that it does not have minimal $T_2$ norm. The routine attempts to certify the result independently of this order computation (as per \tet{nfcertify}: we try to prove that the order is maximal); if it fails, the routine returns $0$ instead of $P$. In order to force an output in that case as well, you may either use \tet{polredbest}, or \kbd{polredabs(,16)}, or \bprog polredabs([T, nfbasis([T, listP])]) @eprog\noindent (In all three cases, the result is no longer canonical.) \misctitle{Warning 2} Apart from the factorization of the discriminant of $T$, this routine runs in polynomial time for a \emph{fixed} degree. But the complexity is exponential in the degree: this routine may be exceedingly slow when the number field has many subfields, hence a lot of elements of small $T_2$-norm. If you do not need a canonical polynomial, the function \tet{polredbest} is in general much faster (it runs in polynomial time), and tends to return polynomials with smaller discriminants. The binary digits of $\fl$ mean 1: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{Mod(a, P)} is a root of the original $T$. 4: gives \emph{all} polynomials of minimal $T_2$ norm; of the two polynomials $P(x)$ and $\pm P(-x)$, only one is given. 16: Possibly use a suborder of the maximal order, \emph{without} attempting to certify the result as in Warning 1: we always return a polynomial and never $0$. The result is a priori not canonical. \bprog ? T = x^16 - 136*x^14 + 6476*x^12 - 141912*x^10 + 1513334*x^8 \ - 7453176*x^6 + 13950764*x^4 - 5596840*x^2 + 46225 ? T1 = polredabs(T); T2 = polredbest(T); ? [ norml2(polroots(T1)), norml2(polroots(T2)) ] %3 = [88.0000000, 120.000000] ? [ sizedigit(poldisc(T1)), sizedigit(poldisc(T2)) ] %4 = [75, 67] @eprog The library syntax is \fun{GEN}{polredabs0}{GEN T, long flag}. Instead of the above hardcoded numerical flags, one should use an or-ed combination of \item \tet{nf_PARTIALFACT}: possibly use a suborder of the maximal order, \emph{without} attempting to certify the result. \item \tet{nf_ORIG}: return $[P, a]$, where \kbd{Mod(a, P)} is a root of $T$. \item \tet{nf_RAW}: return $[P, b]$, where \kbd{Mod(b, T)} is a root of $P$. The algebraic integer $b$ is the raw result produced by the small vectors enumeration in the maximal order; $P$ was computed as the characteristic polynomial of \kbd{Mod(b, T)}. \kbd{Mod(a, P)} as in \tet{nf_ORIG} is obtained with \tet{modreverse}. \item \tet{nf_ADDZK}: if $r$ is the result produced with some of the above flags (of the form $P$ or $[P,c]$), return \kbd{[r,zk]}, where \kbd{zk} is a $\Z$-basis for the maximal order of $\Q[X]/(P)$. \item \tet{nf_ALL}: return a vector of results of the above form, for all polynomials of minimal $T_2$-norm. \subsec{polredbest$(T,\{\fl=0\})$}\kbdsidx{polredbest}\label{se:polredbest} Finds a polynomial with reasonably small coefficients defining the same number field as $T$. All $T$ accepted by \tet{nfinit} are also allowed here (e.g. non-monic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[T,Z\_K\_basis]}). Contrary to \tet{polredabs}, this routine runs in polynomial time, but it offers no guarantee as to the minimality of its result. This routine computes an LLL-reduced basis for the ring of integers of $\Q[X]/(T)$, then examines small linear combinations of the basis vectors, computing their characteristic polynomials. It returns the \emph{separable} $P$ polynomial of smallest discriminant (the one with lexicographically smallest \kbd{abs(Vec(P))} in case of ties). This is a good candidate for subsequent number field computations, since it guarantees that the denominators of algebraic integers, when expressed in the power basis, are reasonably small. With no claim of minimality, though. It can happen that iterating this functions yields better and better polynomials, until it stabilizes: \bprog ? \p5 ? P = X^12+8*X^8-50*X^6+16*X^4-3069*X^2+625; ? poldisc(P)*1. %2 = 1.2622 E55 ? P = polredbest(P); ? poldisc(P)*1. %4 = 2.9012 E51 ? P = polredbest(P); ? poldisc(P)*1. %6 = 8.8704 E44 @eprog\noindent In this example, the initial polynomial $P$ is the one returned by \tet{polredabs}, and the last one is stable. If $\fl = 1$: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{Mod(a, P)} is a root of the original $T$. \bprog ? [P,a] = polredbest(x^4 + 8, 1) %1 = [x^4 + 2, Mod(x^3, x^4 + 2)] ? charpoly(a) %2 = x^4 + 8 @eprog\noindent In particular, the map $\Q[x]/(T) \to \Q[x]/(P)$, $x\mapsto \kbd{Mod(a,P)}$ defines an isomorphism of number fields, which can be computed as \bprog subst(lift(Q), 'x, a) @eprog\noindent if $Q$ is a \typ{POLMOD} modulo $T$; \kbd{b = modreverse(a)} returns a \typ{POLMOD} giving the inverse of the above map (which should be useless since $\Q[x]/(P)$ is a priori a better representation for the number field and its elements). The library syntax is \fun{GEN}{polredbest}{GEN T, long flag}. \subsec{polredord$(x)$}\kbdsidx{polredord}\label{se:polredord} Finds polynomials with reasonably small coefficients and of the same degree as that of $x$ defining suborders of the order defined by $x$. One of the polynomials always defines $\Q$ (hence is equal to $(x-1)^n$, where $n$ is the degree), and another always defines the same order as $x$ if $x$ is irreducible. Useless function: try \kbd{polredbest}. The library syntax is \fun{GEN}{polredord}{GEN x}. \subsec{poltschirnhaus$(x)$}\kbdsidx{poltschirnhaus}\label{se:poltschirnhaus} Applies a random Tschirnhausen transformation to the polynomial $x$, which is assumed to be non-constant and separable, so as to obtain a new equation for the \'etale algebra defined by $x$. This is for instance useful when computing resolvents, hence is used by the \kbd{polgalois} function. The library syntax is \fun{GEN}{tschirnhaus}{GEN x}. \subsec{rnfalgtobasis$(\var{rnf},x)$}\kbdsidx{rnfalgtobasis}\label{se:rnfalgtobasis} Expresses $x$ on the relative integral basis. Here, $\var{rnf}$ is a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an element of $L$ in absolute form, i.e. expressed as a polynomial or polmod with polmod coefficients, \emph{not} on the relative integral basis. The library syntax is \fun{GEN}{rnfalgtobasis}{GEN rnf, GEN x}. \subsec{rnfbasis$(\var{bnf},M)$}\kbdsidx{rnfbasis}\label{se:rnfbasis} Let $K$ the field represented by \var{bnf}, as output by \kbd{bnfinit}. $M$ is a projective $\Z_K$-module of rank $n$ ($M\otimes K$ is an $n$-dimensional $K$-vector space), given by a pseudo-basis of size $n$. The routine returns either a true $\Z_K$-basis of $M$ (of size $n$) if it exists, or an $n+1$-element generating set of $M$ if not. It is allowed to use an irreducible polynomial $P$ in $K[X]$ instead of $M$, in which case, $M$ is defined as the ring of integers of $K[X]/(P)$, viewed as a $\Z_K$-module. The library syntax is \fun{GEN}{rnfbasis}{GEN bnf, GEN M}. \subsec{rnfbasistoalg$(\var{rnf},x)$}\kbdsidx{rnfbasistoalg}\label{se:rnfbasistoalg} Computes the representation of $x$ as a polmod with polmods coefficients. Here, $\var{rnf}$ is a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an element of $L$ expressed on the relative integral basis. The library syntax is \fun{GEN}{rnfbasistoalg}{GEN rnf, GEN x}. \subsec{rnfcharpoly$(\var{nf},T,a,\{\var{var}='x\})$}\kbdsidx{rnfcharpoly}\label{se:rnfcharpoly} Characteristic polynomial of $a$ over $\var{nf}$, where $a$ belongs to the algebra defined by $T$ over $\var{nf}$, i.e.~$\var{nf}[X]/(T)$. Returns a polynomial in variable $v$ ($x$ by default). \bprog ? nf = nfinit(y^2+1); ? rnfcharpoly(nf, x^2+y*x+1, x+y) %2 = x^2 + Mod(-y, y^2 + 1)*x + 1 @eprog The library syntax is \fun{GEN}{rnfcharpoly}{GEN nf, GEN T, GEN a, long var = -1}, where \kbd{var} is a variable number. \subsec{rnfconductor$(\var{bnf},\var{pol})$}\kbdsidx{rnfconductor}\label{se:rnfconductor} Given $\var{bnf}$ as output by \kbd{bnfinit}, and \var{pol} a relative polynomial defining an \idx{Abelian extension}, computes the class field theory conductor of this Abelian extension. The result is a 3-component vector $[\var{conductor},\var{rayclgp},\var{subgroup}]$, where \var{conductor} is the conductor of the extension given as a 2-component row vector $[f_0,f_\infty]$, \var{rayclgp} is the full ray class group corresponding to the conductor given as a 3-component vector [h,cyc,gen] as usual for a group, and \var{subgroup} is a matrix in HNF defining the subgroup of the ray class group on the given generators gen. The library syntax is \fun{GEN}{rnfconductor}{GEN bnf, GEN pol}. \subsec{rnfdedekind$(\var{nf},\var{pol},\{\var{pr}\},\{\fl=0\})$}\kbdsidx{rnfdedekind}\label{se:rnfdedekind} Given a number field $K$ coded by $\var{nf}$ and a monic polynomial $P\in \Z_K[X]$, irreducible over $K$ and thus defining a relative extension $L$ of $K$, applies \idx{Dedekind}'s criterion to the order $\Z_K[X]/(P)$, at the prime ideal \var{pr}. It is possible to set \var{pr} to a vector of prime ideals (test maximality at all primes in the vector), or to omit altogether, in which case maximality at \emph{all} primes is tested; in this situation \fl\ is automatically set to $1$. The default historic behavior (\fl\ is 0 or omitted and \var{pr} is a single prime ideal) is not so useful since \kbd{rnfpseudobasis} gives more information and is generally not that much slower. It returns a 3-component vector $[\var{max}, \var{basis}, v]$: \item \var{basis} is a pseudo-basis of an enlarged order $O$ produced by Dedekind's criterion, containing the original order $\Z_K[X]/(P)$ with index a power of \var{pr}. Possibly equal to the original order. \item \var{max} is a flag equal to 1 if the enlarged order $O$ could be proven to be \var{pr}-maximal and to 0 otherwise; it may still be maximal in the latter case if \var{pr} is ramified in $L$, \item $v$ is the valuation at \var{pr} of the order discriminant. If \fl\ is non-zero, on the other hand, we just return $1$ if the order $\Z_K[X]/(P)$ is \var{pr}-maximal (resp.~maximal at all relevant primes, as described above), and $0$ if not. This is much faster than the default, since the enlarged order is not computed. \bprog ? nf = nfinit(y^2-3); P = x^3 - 2*y; ? pr3 = idealprimedec(nf,3)[1]; ? rnfdedekind(nf, P, pr3) %2 = [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8] ? rnfdedekind(nf, P, pr3, 1) %3 = 1 @eprog\noindent In this example, \kbd{pr3} is the ramified ideal above $3$, and the order generated by the cube roots of $y$ is already \kbd{pr3}-maximal. The order-discriminant has valuation $8$. On the other hand, the order is not maximal at the prime above 2: \bprog ? pr2 = idealprimedec(nf,2)[1]; ? rnfdedekind(nf, P, pr2, 1) %5 = 0 ? rnfdedekind(nf, P, pr2) %6 = [0, [[2, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0; 0, 1], [1, 0; 0, 1], [1, 1/2; 0, 1/2]]], 2] @eprog The enlarged order is not proven to be \kbd{pr2}-maximal yet. In fact, it is; it is in fact the maximal order: \bprog ? B = rnfpseudobasis(nf, P) %7 = [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, [1, 1/2; 0, 1/2]], [162, 0; 0, 162], -1] ? idealval(nf,B[3], pr2) %4 = 2 @eprog\noindent It is possible to use this routine with non-monic $P = \sum_{i\leq n} a_i X^i \in \Z_K[X]$ if $\fl = 1$; in this case, we test maximality of Dedekind's order generated by $$1, a_n \alpha, a_n\alpha^2 + a_{n-1}\alpha, \dots, a_n\alpha^{n-1} + a_{n-1}\alpha^{n-2} + \cdots + a_1\alpha.$$ The routine will fail if $P$ is $0$ on the projective line over the residue field $\Z_K/\kbd{pr}$ (FIXME). The library syntax is \fun{GEN}{rnfdedekind}{GEN nf, GEN pol, GEN pr = NULL, long flag}. \subsec{rnfdet$(\var{nf},M)$}\kbdsidx{rnfdet}\label{se:rnfdet} Given a pseudo-matrix $M$ over the maximal order of $\var{nf}$, computes its determinant. The library syntax is \fun{GEN}{rnfdet}{GEN nf, GEN M}. \subsec{rnfdisc$(\var{nf},\var{pol})$}\kbdsidx{rnfdisc}\label{se:rnfdisc} Given a number field $\var{nf}$ as output by \kbd{nfinit} and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes the relative discriminant of $L$. This is a two-element row vector $[D,d]$, where $D$ is the relative ideal discriminant and $d$ is the relative discriminant considered as an element of $\var{nf}^*/{\var{nf}^*}^2$. The main variable of $\var{nf}$ \emph{must} be of lower priority than that of \var{pol}, see \secref{se:priority}. The library syntax is \fun{GEN}{rnfdiscf}{GEN nf, GEN pol}. \subsec{rnfeltabstorel$(\var{rnf},x)$}\kbdsidx{rnfeltabstorel}\label{se:rnfeltabstorel} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}, computes $x$ as an element of the relative extension $L/K$ as a polmod with polmod coefficients. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltabstorel(L, Mod(x, L.pol)) %3 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltabstorel(L, Mod(2, L.pol)) %4 = 2 ? rnfeltabstorel(L, Mod(x, x^2-y)) *** at top-level: rnfeltabstorel(L,Mod *** ^-------------------- *** rnfeltabstorel: inconsistent moduli in rnfeltabstorel: x^2-y != x^4+1 @eprog The library syntax is \fun{GEN}{rnfeltabstorel}{GEN rnf, GEN x}. \subsec{rnfeltdown$(\var{rnf},x)$}\kbdsidx{rnfeltdown}\label{se:rnfeltdown} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial or polmod with polmod coefficients, computes $x$ as an element of $K$ as a polmod, assuming $x$ is in $K$ (otherwise a domain error occurs). \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltdown(L, Mod(x^2, L.pol)) %3 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(y, x^2-y)) %4 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(y,K.pol)) %5 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(x, L.pol)) *** at top-level: rnfeltdown(L,Mod(x,x *** ^-------------------- *** rnfeltdown: domain error in rnfeltdown: element not in the base field @eprog The library syntax is \fun{GEN}{rnfeltdown}{GEN rnf, GEN x}. \subsec{rnfeltnorm$(\var{rnf},x)$}\kbdsidx{rnfeltnorm}\label{se:rnfeltnorm} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative norm $N_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfeltnorm(L, Mod(x, L.pol)) %2 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltnorm(L, 2) %3 = 4 ? rnfeltnorm(L, Mod(x, x^2-y)) @eprog The library syntax is \fun{GEN}{rnfeltnorm}{GEN rnf, GEN x}. \subsec{rnfeltreltoabs$(\var{rnf},x)$}\kbdsidx{rnfeltreltoabs}\label{se:rnfeltreltoabs} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial or polmod with polmod coefficients, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltreltoabs(L, Mod(x, L.pol)) %3 = Mod(x, x^4 + 1) ? rnfeltreltoabs(L, Mod(y, x^2-y)) %4 = Mod(x^2, x^4 + 1) ? rnfeltreltoabs(L, Mod(y,K.pol)) %5 = Mod(x^2, x^4 + 1) @eprog The library syntax is \fun{GEN}{rnfeltreltoabs}{GEN rnf, GEN x}. \subsec{rnfelttrace$(\var{rnf},x)$}\kbdsidx{rnfelttrace}\label{se:rnfelttrace} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative trace $N_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfelttrace(L, Mod(x, L.pol)) %2 = 0 ? rnfelttrace(L, 2) %3 = 4 ? rnfelttrace(L, Mod(x, x^2-y)) @eprog The library syntax is \fun{GEN}{rnfelttrace}{GEN rnf, GEN x}. \subsec{rnfeltup$(\var{rnf},x)$}\kbdsidx{rnfeltup}\label{se:rnfeltup} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $K$, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltup(L, Mod(y, K.pol)) %4 = Mod(x^2, x^4 + 1) ? rnfeltup(L, y) %5 = Mod(x^2, x^4 + 1) ? rnfeltup(L, [1,2]~) \\ in terms of K.zk %6 = Mod(2*x^2 + 1, x^4 + 1) @eprog The library syntax is \fun{GEN}{rnfeltup}{GEN rnf, GEN x}. \subsec{rnfequation$(\var{nf},\var{pol},\{\fl=0\})$}\kbdsidx{rnfequation}\label{se:rnfequation} Given a number field $\var{nf}$ as output by \kbd{nfinit} (or simply a polynomial) and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes an absolute equation of $L$ over $\Q$. The main variable of $\var{nf}$ \emph{must} be of lower priority than that of \var{pol} (see \secref{se:priority}). Note that for efficiency, this does not check whether the relative equation is irreducible over $\var{nf}$, but only if it is squarefree. If it is reducible but squarefree, the result will be the absolute equation of the \'etale algebra defined by \var{pol}. If \var{pol} is not squarefree, raise an \kbd{e\_DOMAIN} exception. \bprog ? rnfequation(y^2+1, x^2 - y) %1 = x^4 + 1 ? T = y^3-2; rnfequation(nfinit(T), (x^3-2)/(x-Mod(y,T))) %2 = x^6 + 108 \\ Galois closure of Q(2^(1/3)) @eprog If $\fl$ is non-zero, outputs a 3-component row vector $[z,a,k]$, where \item $z$ is the absolute equation of $L$ over $\Q$, as in the default behavior, \item $a$ expresses as a \typ{POLMOD} modulo $z$ a root $\alpha$ of the polynomial defining the base field $\var{nf}$, \item $k$ is a small integer such that $\theta = \beta+k\alpha$ is a root of $z$, where $\beta$ is a root of $\var{pol}$. \bprog ? T = y^3-2; pol = x^2 +x*y + y^2; ? [z,a,k] = rnfequation(T, pol, 1); ? z %4 = x^6 + 108 ? subst(T, y, a) %5 = 0 ? alpha= Mod(y, T); ? beta = Mod(x*Mod(1,T), pol); ? subst(z, x, beta + k*alpha) %8 = 0 @eprog The library syntax is \fun{GEN}{rnfequation0}{GEN nf, GEN pol, long flag}. Also available are \fun{GEN}{rnfequation}{GEN nf, GEN pol} ($\fl = 0$) and \fun{GEN}{rnfequation2}{GEN nf, GEN pol} ($\fl = 1$). \subsec{rnfhnfbasis$(\var{bnf},x)$}\kbdsidx{rnfhnfbasis}\label{se:rnfhnfbasis} Given $\var{bnf}$ as output by \kbd{bnfinit}, and either a polynomial $x$ with coefficients in $\var{bnf}$ defining a relative extension $L$ of $\var{bnf}$, or a pseudo-basis $x$ of such an extension, gives either a true $\var{bnf}$-basis of $L$ in upper triangular Hermite normal form, if it exists, and returns $0$ otherwise. The library syntax is \fun{GEN}{rnfhnfbasis}{GEN bnf, GEN x}. \subsec{rnfidealabstorel$(\var{rnf},x)$}\kbdsidx{rnfidealabstorel}\label{se:rnfidealabstorel} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ be an ideal of the absolute extension $L/\Q$ given by a $\Z$-basis of elements of $L$. Returns the relative pseudo-matrix in HNF giving the ideal $x$ considered as an ideal of the relative extension $L/K$, i.e.~as a $\Z_K$-module. The reason why the input does not use the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, and $m$ is in HNF, defining an (absolute) ideal with respect to the $\Z$-basis \kbd{Labs.zk}, then \kbd{Labs.zk * m} is a suitable $\Z$-basis for the ideal, and \bprog 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); ? 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 ? A = rnfidealreltoabs(L, B) %4 = [17, x^2 + 4, x + 8, x^3 + 8*x^2] \\ Z-basis for m in Q[x]/(L.pol) ? mathnf(matalgtobasis(Labs, A)) %5 = [17 8 4 2] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] ? % == m %6 = 1 @eprog The library syntax is \fun{GEN}{rnfidealabstorel}{GEN rnf, GEN x}. \subsec{rnfidealdown$(\var{rnf},x)$}\kbdsidx{rnfidealdown}\label{se:rnfidealdown} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an ideal of $L$, given either in relative form or by a $\Z$-basis of elements of $L$ (see \secref{se:rnfidealabstorel}). This function returns the ideal of $K$ below $x$, i.e.~the intersection of $x$ with $K$. The library syntax is \fun{GEN}{rnfidealdown}{GEN rnf, GEN x}. \subsec{rnfidealhnf$(\var{rnf},x)$}\kbdsidx{rnfidealhnf}\label{se:rnfidealhnf} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being a relative ideal (which can be, as in the absolute case, of many different types, including of course elements), computes the HNF pseudo-matrix associated to $x$, viewed as a $\Z_K$-module. The library syntax is \fun{GEN}{rnfidealhnf}{GEN rnf, GEN x}. \subsec{rnfidealmul$(\var{rnf},x,y)$}\kbdsidx{rnfidealmul}\label{se:rnfidealmul} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ and $y$ being ideals of the relative extension $L/K$ given by pseudo-matrices, outputs the ideal product, again as a relative ideal. The library syntax is \fun{GEN}{rnfidealmul}{GEN rnf, GEN x, GEN y}. \subsec{rnfidealnormabs$(\var{rnf},x)$}\kbdsidx{rnfidealnormabs}\label{se:rnfidealnormabs} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the norm of the $x$ considered as an ideal of the absolute extension $L/\Q$. This is identical to \bprog idealnorm(rnf, rnfidealnormrel(rnf,x)) @eprog\noindent but faster. The library syntax is \fun{GEN}{rnfidealnormabs}{GEN rnf, GEN x}. \subsec{rnfidealnormrel$(\var{rnf},x)$}\kbdsidx{rnfidealnormrel}\label{se:rnfidealnormrel} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the relative norm of $x$ as an ideal of $K$ in HNF. The library syntax is \fun{GEN}{rnfidealnormrel}{GEN rnf, GEN x}. \subsec{rnfidealreltoabs$(\var{rnf},x)$}\kbdsidx{rnfidealreltoabs}\label{se:rnfidealreltoabs} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal, given as a $\Z_K$-module by a pseudo matrix $[A,I]$. This function returns the ideal $x$ as an absolute ideal of $L/\Q$ in the form of a $\Z$-basis, given by a vector of polynomials (modulo \kbd{rnf.pol}). The reason why we do not return the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, then \bprog xabs = rnfidealreltoabs(L, x); xLabs = mathnf(matalgtobasis(Labs, xabs)); @eprog\noindent computes a traditional HNF \kbd{xLabs} for $x$ in terms of the fixed $\Z$-basis \kbd{Labs.zk}. The library syntax is \fun{GEN}{rnfidealreltoabs}{GEN rnf, GEN x}. \subsec{rnfidealtwoelt$(\var{rnf},x)$}\kbdsidx{rnfidealtwoelt}\label{se:rnfidealtwoelt} $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an ideal of the relative extension $L/K$ given by a pseudo-matrix, gives a vector of two generators of $x$ over $\Z_L$ expressed as polmods with polmod coefficients. The library syntax is \fun{GEN}{rnfidealtwoelement}{GEN rnf, GEN x}. \subsec{rnfidealup$(\var{rnf},x)$}\kbdsidx{rnfidealup}\label{se:rnfidealup} Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be an ideal of $K$. This function returns the ideal $x\Z_L$ as an absolute ideal of $L/\Q$, in the form of a $\Z$-basis, given by a vector of polynomials (modulo \kbd{rnf.pol}). The reason why we do not return the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, then \bprog xabs = rnfidealup(L, x); xLabs = mathnf(matalgtobasis(Labs, xabs)); @eprog\noindent computes a traditional HNF \kbd{xLabs} for $x$ in terms of the fixed $\Z$-basis \kbd{Labs.zk}. The library syntax is \fun{GEN}{rnfidealup}{GEN rnf, GEN x}. \subsec{rnfinit$(\var{nf},\var{pol})$}\kbdsidx{rnfinit}\label{se:rnfinit} $\var{nf}$ being a number field in \kbd{nfinit} format considered as base field, and \var{pol} a polynomial defining a relative extension over $\var{nf}$, this computes data to work in the relative extension. The main variable of \var{pol} must be of higher priority (see \secref{se:priority}) than that of $\var{nf}$, and the coefficients of \var{pol} must be in $\var{nf}$. The result is a row vector, whose components are technical. In the following description, we let $K$ be the base field defined by $\var{nf}$ and $L/K$ the large field associated to the \var{rnf}. Furthermore, we let $m = [K:\Q]$ the degree of the base field, $n = [L:K]$ the relative degree, $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. $\var{rnf}[1]$(\kbd{rnf.pol}) contains the relative polynomial \var{pol}. $\var{rnf}[2]$ contains the integer basis $[A,d]$ of $K$, as (integral) elements of $L/\Q$. More precisely, $A$ is a vector of polynomial with integer coefficients, $d$ is a denominator, and the integer basis is given by $A/d$. $\var{rnf}[3]$ (\kbd{rnf.disc}) is a two-component row vector $[\goth{d}(L/K),s]$ where $\goth{d}(L/K)$ is the relative ideal discriminant of $L/K$ and $s$ is the discriminant of $L/K$ viewed as an element of $K^*/(K^*)^2$, in other words it is the output of \kbd{rnfdisc}. $\var{rnf}[4]$(\kbd{rnf.index}) is the ideal index $\goth{f}$, i.e.~such that $d(pol)\Z_K=\goth{f}^2\goth{d}(L/K)$. $\var{rnf}[5]$ is currently unused. $\var{rnf}[6]$ is currently unused. $\var{rnf}[7]$ (\kbd{rnf.zk}) is the pseudo-basis $(A,I)$ for the maximal order $\Z_L$ as a $\Z_K$-module: $A$ is the relative integral pseudo basis expressed as polynomials (in the variable of $pol$) with polmod coefficients in $\var{nf}$, and the second component $I$ is the ideal list of the pseudobasis in HNF. $\var{rnf}[8]$ is the inverse matrix of the integral basis matrix, with coefficients polmods in $\var{nf}$. $\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 $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 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 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 working, but we advise to change the relative polynomial so that its root becomes $\beta + k \alpha$. Typical GP instructions would be \bprog [P,a,k] = rnfequation(K, pol, 1); if (k, pol = subst(pol, x, x - k*Mod(y, K.pol))); L = rnfinit(K, pol); @eprog $\var{rnf}[12]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available (which is rarely needed, hence would be too expensive to compute during the initial \kbd{rnfinit} call). The library syntax is \fun{GEN}{rnfinit}{GEN nf, GEN pol}. \subsec{rnfisabelian$(\var{nf},T)$}\kbdsidx{rnfisabelian}\label{se:rnfisabelian} $T$ being a relative polynomial with coefficients in \var{nf}, return 1 if it defines an abelian extension, and 0 otherwise. \bprog ? K = nfinit(y^2 + 23); ? rnfisabelian(K, x^3 - 3*x - y) %2 = 1 @eprog The library syntax is \fun{long}{rnfisabelian}{GEN nf, GEN T}. \subsec{rnfisfree$(\var{bnf},x)$}\kbdsidx{rnfisfree}\label{se:rnfisfree} Given $\var{bnf}$ as output by \kbd{bnfinit}, and either a polynomial $x$ with coefficients in $\var{bnf}$ defining a relative extension $L$ of $\var{bnf}$, or a pseudo-basis $x$ of such an extension, returns true (1) if $L/\var{bnf}$ is free, false (0) if not. The library syntax is \fun{long}{rnfisfree}{GEN bnf, GEN x}. \subsec{rnfisnorm$(T,a,\{\fl=0\})$}\kbdsidx{rnfisnorm}\label{se:rnfisnorm} Similar to \kbd{bnfisnorm} but in the relative case. $T$ is as output by \tet{rnfisnorminit} applied to the extension $L/K$. This tries to decide whether the element $a$ in $K$ is the norm of some $x$ in the extension $L/K$. The output is a vector $[x,q]$, where $a = \Norm(x)*q$. The algorithm looks for a solution $x$ which is an $S$-integer, with $S$ a list of places of $K$ containing at least the ramified primes, the generators of the class group of $L$, as well as those primes dividing $a$. If $L/K$ is Galois, then this is enough; otherwise, $\fl$ is used to add more primes to $S$: all the places above the primes $p \leq \fl$ (resp.~$p|\fl$) if $\fl>0$ (resp.~$\fl<0$). The answer is guaranteed (i.e.~$a$ is a norm iff $q = 1$) if the field is Galois, or, under \idx{GRH}, if $S$ contains all primes less than $12\log^2\left|\disc(M)\right|$, where $M$ is the normal closure of $L/K$. If \tet{rnfisnorminit} has determined (or was told) that $L/K$ is \idx{Galois}, and $\fl \neq 0$, a Warning is issued (so that you can set $\fl = 1$ to check whether $L/K$ is known to be Galois, according to $T$). Example: \bprog bnf = bnfinit(y^3 + y^2 - 2*y - 1); p = x^2 + Mod(y^2 + 2*y + 1, bnf.pol); T = rnfisnorminit(bnf, p); rnfisnorm(T, 17) @eprog\noindent checks whether $17$ is a norm in the Galois extension $\Q(\beta) / \Q(\alpha)$, where $\alpha^3 + \alpha^2 - 2\alpha - 1 = 0$ and $\beta^2 + \alpha^2 + 2\alpha + 1 = 0$ (it is). The library syntax is \fun{GEN}{rnfisnorm}{GEN T, GEN a, long flag}. \subsec{rnfisnorminit$(\var{pol},\var{polrel},\{\fl=2\})$}\kbdsidx{rnfisnorminit}\label{se:rnfisnorminit} Let $K$ be defined by a root of \var{pol}, and $L/K$ the extension defined by the polynomial \var{polrel}. As usual, \var{pol} can in fact be an \var{nf}, or \var{bnf}, etc; if \var{pol} has degree $1$ (the base field is $\Q$), polrel is also allowed to be an \var{nf}, etc. Computes technical data needed by \tet{rnfisnorm} to solve norm equations $Nx = a$, for $x$ in $L$, and $a$ in $K$. If $\fl = 0$, do not care whether $L/K$ is Galois or not. If $\fl = 1$, $L/K$ is assumed to be Galois (unchecked), which speeds up \tet{rnfisnorm}. If $\fl = 2$, let the routine determine whether $L/K$ is Galois. The library syntax is \fun{GEN}{rnfisnorminit}{GEN pol, GEN polrel, long flag}. \subsec{rnfkummer$(\var{bnr},\{\var{subgp}\},\{d=0\})$}\kbdsidx{rnfkummer}\label{se:rnfkummer} \var{bnr} being as output by \kbd{bnrinit}, finds a relative equation for the class field corresponding to the module in \var{bnr} and the given congruence subgroup (the full ray class field if \var{subgp} is omitted). If $d$ is positive, outputs the list of all relative equations of degree $d$ contained in the ray class field defined by \var{bnr}, with the \emph{same} conductor as $(\var{bnr}, \var{subgp})$. \misctitle{Warning} This routine only works for subgroups of prime index. It uses Kummer theory, adjoining necessary roots of unity (it needs to compute a tough \kbd{bnfinit} here), and finds a generator via Hecke's characterization of ramification in Kummer extensions of prime degree. If your extension does not have prime degree, for the time being, you have to split it by hand as a tower / compositum of such extensions. The library syntax is \fun{GEN}{rnfkummer}{GEN bnr, GEN subgp = NULL, long d, long prec}. \subsec{rnflllgram$(\var{nf},\var{pol},\var{order})$}\kbdsidx{rnflllgram}\label{se:rnflllgram} Given a polynomial \var{pol} with coefficients in \var{nf} defining a relative extension $L$ and a suborder \var{order} of $L$ (of maximal rank), as output by \kbd{rnfpseudobasis}$(\var{nf},\var{pol})$ or similar, gives $[[\var{neworder}],U]$, where \var{neworder} is a reduced order and $U$ is the unimodular transformation matrix. The library syntax is \fun{GEN}{rnflllgram}{GEN nf, GEN pol, GEN order, long prec}. \subsec{rnfnormgroup$(\var{bnr},\var{pol})$}\kbdsidx{rnfnormgroup}\label{se:rnfnormgroup} \var{bnr} being a big ray class field as output by \kbd{bnrinit} and \var{pol} a relative polynomial defining an \idx{Abelian extension}, computes the norm group (alias Artin or Takagi group) corresponding to the Abelian extension of $\var{bnf}=$\kbd{bnr.bnf} defined by \var{pol}, where the module corresponding to \var{bnr} is assumed 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. The library syntax is \fun{GEN}{rnfnormgroup}{GEN bnr, GEN pol}. \subsec{rnfpolred$(\var{nf},\var{pol})$}\kbdsidx{rnfpolred}\label{se:rnfpolred} THIS FUNCTION IS OBSOLETE: use \tet{rnfpolredbest} instead. Relative version of \kbd{polred}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a list of relative polynomials defining some subfields, hopefully simpler and containing the original field. In the present version \vers, this is slower and less efficient than \kbd{rnfpolredbest}. \misctitle{Remark} this function is based on an incomplete reduction theory of lattices over number fields, implemented by \kbd{rnflllgram}, which deserves to be improved. The library syntax is \fun{GEN}{rnfpolred}{GEN nf, GEN pol, long prec}. \subsec{rnfpolredabs$(\var{nf},\var{pol},\{\fl=0\})$}\kbdsidx{rnfpolredabs}\label{se:rnfpolredabs} THIS FUNCTION IS OBSOLETE: use \tet{rnfpolredbest} instead. Relative version of \kbd{polredabs}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a simpler relative polynomial defining the same field. The binary digits of $\fl$ mean The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative, $16$: possibly use a suborder of the maximal order. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. Same as but faster than \bprog rnfequation(nf, rnfpolredabs(nf,pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. 16: possibly use a suborder of the maximal order. This is slower than the default when the relative discriminant is smooth, and much faster otherwise. See \secref{se:polredabs}. \misctitle{Warning} In the present implementation, \kbd{rnfpolredabs} produces smaller polynomials than \kbd{rnfpolred} and is usually faster, but its complexity is still exponential in the absolute degree. The function \tet{rnfpolredbest} runs in polynomial time, and tends to return polynomials with smaller discriminants. The library syntax is \fun{GEN}{rnfpolredabs}{GEN nf, GEN pol, long flag}. \subsec{rnfpolredbest$(\var{nf},\var{pol},\{\fl=0\})$}\kbdsidx{rnfpolredbest}\label{se:rnfpolredbest} Relative version of \kbd{polredbest}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a simpler relative polynomial $P$ defining the same field. As opposed to \tet{rnfpolredabs} this function does not return a \emph{smallest} (canonical) polynomial with respect to some measure, but it does run in polynomial time. The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. Same as but faster than \bprog rnfequation(nf, rnfpolredbest(nf,pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. \bprog ? K = nfinit(y^3-2); pol = x^2 +x*y + y^2; ? [P, a] = rnfpolredbest(K,pol,1); ? P %3 = x^2 - x + Mod(y - 1, y^3 - 2) ? a %4 = Mod(Mod(2*y^2+3*y+4,y^3-2)*x + Mod(-y^2-2*y-2,y^3-2), x^2 - x + Mod(y-1,y^3-2)) ? subst(K.pol,y,a) %5 = 0 ? [Pabs, a, b] = rnfpolredbest(K,pol,3); ? Pabs %7 = x^6 - 3*x^5 + 5*x^3 - 3*x + 1 ? a %8 = Mod(-x^2+x+1, x^6-3*x^5+5*x^3-3*x+1) ? b %9 = Mod(2*x^5-5*x^4-3*x^3+10*x^2+5*x-5, x^6-3*x^5+5*x^3-3*x+1) ? subst(K.pol,y,a) %10 = 0 ? substvec(pol,[x,y],[a,b]) %11 = 0 @eprog The library syntax is \fun{GEN}{rnfpolredbest}{GEN nf, GEN pol, long flag}. \subsec{rnfpseudobasis$(\var{nf},\var{pol})$}\kbdsidx{rnfpseudobasis}\label{se:rnfpseudobasis} Given a number field $\var{nf}$ as output by \kbd{nfinit} and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes a pseudo-basis $(A,I)$ for the maximal order $\Z_L$ viewed as a $\Z_K$-module, and the relative discriminant of $L$. This is output as a four-element row vector $[A,I,D,d]$, where $D$ is the relative ideal discriminant and $d$ is the relative discriminant considered as an element of $\var{nf}^*/{\var{nf}^*}^2$. The library syntax is \fun{GEN}{rnfpseudobasis}{GEN nf, GEN pol}. \subsec{rnfsteinitz$(\var{nf},x)$}\kbdsidx{rnfsteinitz}\label{se:rnfsteinitz} Given a number field $\var{nf}$ as output by \kbd{nfinit} and either a polynomial $x$ with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, or a pseudo-basis $x$ of such an extension as output for example by \kbd{rnfpseudobasis}, computes another pseudo-basis $(A,I)$ (not in HNF in general) such that all the ideals of $I$ except perhaps the last one are equal to the ring of integers of $\var{nf}$, and outputs the four-component row vector $[A,I,D,d]$ as in \kbd{rnfpseudobasis}. The name of this function comes from the fact that the ideal class of the last ideal of $I$, which is well defined, is the \idx{Steinitz class} of the $\Z_K$-module $\Z_L$ (its image in $SK_0(\Z_K)$). The library syntax is \fun{GEN}{rnfsteinitz}{GEN nf, GEN x}. \subsec{subgrouplist$(\var{bnr},\{\var{bound}\},\{\fl=0\})$}\kbdsidx{subgrouplist}\label{se:subgrouplist} \var{bnr} being as output by \kbd{bnrinit} or a list of cyclic components of a finite Abelian group $G$, outputs the list of subgroups of $G$. Subgroups are given as HNF left divisors of the SNF matrix corresponding to $G$. If $\fl=0$ (default) and \var{bnr} is as output by \kbd{bnrinit}, gives only the subgroups whose modulus is the conductor. Otherwise, the modulus is not taken into account. If \var{bound} is present, and is a positive integer, restrict the output to subgroups of index less than \var{bound}. If \var{bound} is a vector containing a single positive integer $B$, then only subgroups of index exactly equal to $B$ are computed. For instance \bprog ? subgrouplist([6,2]) %1 = [[6, 0; 0, 2], [2, 0; 0, 2], [6, 3; 0, 1], [2, 1; 0, 1], [3, 0; 0, 2], [1, 0; 0, 2], [6, 0; 0, 1], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]] ? subgrouplist([6,2],3) \\@com index less than 3 %2 = [[2, 1; 0, 1], [1, 0; 0, 2], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]] ? subgrouplist([6,2],[3]) \\@com index 3 %3 = [[3, 0; 0, 1]] ? bnr = bnrinit(bnfinit(x), [120,[1]], 1); ? L = subgrouplist(bnr, [8]); @eprog\noindent In the last example, $L$ corresponds to the 24 subfields of $\Q(\zeta_{120})$, of degree $8$ and conductor $120\infty$ (by setting \fl, we see there are a total of $43$ subgroups of degree $8$). \bprog ? vector(#L, i, galoissubcyclo(bnr, L[i])) @eprog\noindent will produce their equations. (For a general base field, you would have to rely on \tet{bnrstark}, or \tet{rnfkummer}.) The library syntax is \fun{GEN}{subgrouplist0}{GEN bnr, GEN bound = NULL, long flag}. \subsec{zetak$(\var{nfz},x,\{\fl=0\})$}\kbdsidx{zetak}\label{se:zetak} \var{znf} being a number field initialized by \kbd{zetakinit} (\emph{not} by \kbd{nfinit}), computes the value of the \idx{Dedekind} zeta function of the number field at the complex number $x$. If $\fl=1$ computes Dedekind $\Lambda$ function instead (i.e.~the product of the Dedekind zeta function by its gamma and exponential factors). \misctitle{CAVEAT} This implementation is not satisfactory and must be rewritten. In particular \item The accuracy of the result depends in an essential way on the accuracy of both the \kbd{zetakinit} program and the current accuracy. Be wary in particular that $x$ of large imaginary part or, on the contrary, very close to an ordinary integer will suffer from precision loss, yielding fewer significant digits than expected. Computing with 28 digits of relative accuracy, we have \bprog ? zeta(3) %1 = 1.202056903159594285399738161 ? zeta(3-1e-20) %2 = 1.202056903159594285401719424 ? zetak(zetakinit(x), 3-1e-20) %3 = 1.2020569031595952919 \\ 5 digits are wrong ? zetak(zetakinit(x), 3-1e-28) %4 = -25.33411749 \\ junk @eprog \item As the precision increases, results become unexpectedly completely wrong: \bprog ? \p100 ? zetak(zetakinit(x^2-5), -1) - 1/30 %1 = 7.26691813 E-108 \\ perfect ? \p150 ? zetak(zetakinit(x^2-5), -1) - 1/30 %2 = -2.486113578 E-156 \\ perfect ? \p200 ? zetak(zetakinit(x^2-5), -1) - 1/30 %3 = 4.47... E-75 \\ more than half of the digits are wrong ? \p250 ? zetak(zetakinit(x^2-5), -1) - 1/30 %4 = 1.6 E43 \\ junk @eprog The library syntax is \fun{GEN}{gzetakall}{GEN nfz, GEN x, long flag, long prec}. See also \fun{GEN}{glambdak}{GEN znf, GEN x, long prec} or \fun{GEN}{gzetak}{GEN znf, GEN x, long prec}. \subsec{zetakinit$(\var{bnf})$}\kbdsidx{zetakinit}\label{se:zetakinit} Computes a number of initialization data concerning the number field associated to \kbd{bnf} so as to be able to compute the \idx{Dedekind} zeta and lambda functions, respectively $\kbd{zetak}(x)$ and $\kbd{zetak}(x,1)$, at the current real precision. If you do not need the \kbd{bnfinit} data somewhere else, you may call it with an irreducible polynomial instead of a \var{bnf}: it will call \kbd{bnfinit} itself. The result is a 9-component vector $v$ whose components are very technical and cannot really be used except through the \kbd{zetak} function. This function is very inefficient and should be rewritten. It needs to computes millions of coefficients of the corresponding Dirichlet series if the precision is big. Unless the discriminant is small it will not be able to handle more than 9 digits of relative precision. For instance, \kbd{zetakinit(x\pow 8 - 2)} needs 440MB of memory at default precision. This function will fail with the message \bprog *** bnrL1: overflow in zeta_get_N0 [need too many primes]. @eprog\noindent if the approximate functional equation requires us to sum 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{Polynomials and power series} We group here all functions which are specific to polynomials or power series. Many other functions which can be applied on these objects are described in the other sections. Also, some of the functions described here can be applied to other types. \subsec{O$(p\hbox{\kbd{\pow}}e)$}\kbdsidx{O}\label{se:O} If $p$ is an integer greater than $2$, returns a $p$-adic $0$ of precision $e$. In all other cases, returns a power series zero with precision given by $e v$, where $v$ is the $X$-adic valuation of $p$ with respect to its main variable. The library syntax is \fun{GEN}{ggrando}{}. \fun{GEN}{zeropadic}{GEN p, long e} for a $p$-adic and \fun{GEN}{zeroser}{long v, long e} for a power series zero in variable $v$. \subsec{bezoutres$(A,B,\{v\})$}\kbdsidx{bezoutres}\label{se:bezoutres} Deprecated alias for \kbd{polresultantext} The library syntax is \fun{GEN}{polresultantext0}{GEN A, GEN B, long v = -1}, where \kbd{v} is a variable number. \subsec{deriv$(x,\{v\})$}\kbdsidx{deriv}\label{se:deriv} Derivative of $x$ with respect to the main variable if $v$ is omitted, and with respect to $v$ otherwise. The derivative of a scalar type is zero, and the derivative of a vector or matrix is done componentwise. One can use $x'$ as a shortcut if the derivative is with respect to the main variable of $x$. By definition, the main variable of a \typ{POLMOD} is the main variable among the coefficients from its two polynomial components (representative and modulus); in other words, assuming a polmod represents an element of $R[X]/(T(X))$, the variable $X$ is a mute variable and the derivative is taken with respect to the main variable used in the base ring $R$. The library syntax is \fun{GEN}{deriv}{GEN x, long v = -1}, where \kbd{v} is a variable number. \subsec{diffop$(x,v,d,\{n=1\})$}\kbdsidx{diffop}\label{se:diffop} Let $v$ be a vector of variables, and $d$ a vector of the same length, return the image of $x$ by the $n$-power ($1$ if n is not given) of the differential operator $D$ that assumes the value \kbd{d[i]} on the variable \kbd{v[i]}. The value of $D$ on a scalar type is zero, and $D$ applies componentwise to a vector or matrix. When applied to a \typ{POLMOD}, if no value is provided for the variable of the modulus, such value is derived using the implicit function theorem. Some examples: This function can be used to differentiate formal expressions: If $E=\exp(X^2)$ then we have $E'=2*X*E$. We can derivate $X*exp(X^2)$ as follow: \bprog ? diffop(E*X,[X,E],[1,2*X*E]) %1 = (2*X^2 + 1)*E @eprog Let \kbd{Sin} and \kbd{Cos} be two function such that $\kbd{Sin}^2+\kbd{Cos}^2=1$ and $\kbd{Cos}'=-\kbd{Sin}$. We can differentiate $\kbd{Sin}/\kbd{Cos}$ as follow, PARI inferring the value of $\kbd{Sin}'$ from the equation: \bprog ? diffop(Mod('Sin/'Cos,'Sin^2+'Cos^2-1),['Cos],[-'Sin]) %1 = Mod(1/Cos^2, Sin^2 + (Cos^2 - 1)) @eprog Compute the Bell polynomials (both complete and partial) via the Faa di Bruno formula: \bprog Bell(k,n=-1)= { my(var(i)=eval(Str("X",i))); my(x,v,dv); v=vector(k,i,if(i==1,'E,var(i-1))); dv=vector(k,i,if(i==1,'X*var(1)*'E,var(i))); x=diffop('E,v,dv,k)/'E; if(n<0,subst(x,'X,1),polcoeff(x,n,'X)) } @eprog The library syntax is \fun{GEN}{diffop0}{GEN x, GEN v, GEN d, long n}. For $n=1$, the function \fun{GEN}{diffop}{GEN x, GEN v, GEN d} is also available. \subsec{eval$(x)$}\kbdsidx{eval}\label{se:eval} Replaces in $x$ the formal variables by the values that have been assigned to them after the creation of $x$. This is mainly useful in GP, and not in library mode. Do not confuse this with substitution (see \kbd{subst}). If $x$ is a character string, \kbd{eval($x$)} executes $x$ as a GP command, as if directly input from the keyboard, and returns its output. \bprog ? x1 = "one"; x2 = "two"; ? n = 1; eval(Str("x", n)) %2 = "one" ? f = "exp"; v = 1; ? eval(Str(f, "(", v, ")")) %4 = 2.7182818284590452353602874713526624978 @eprog\noindent Note that the first construct could be implemented in a simpler way by using a vector \kbd{x = ["one","two"]; x[n]}, and the second by using a closure \kbd{f = exp; f(v)}. The final example is more interesting: \bprog ? genmat(u,v) = matrix(u,v,i,j, eval( Str("x",i,j) )); ? genmat(2,3) \\ generic 2 x 3 matrix %2 = [x11 x12 x13] [x21 x22 x23] @eprog A syntax error in the evaluation expression raises an \kbd{e\_SYNTAX} exception, which can be trapped as usual: \bprog ? 1a *** unused characters: 1a *** ^- ? E(expr) = { iferr(eval(expr), e, print("syntax error"), errname(e) == "e_SYNTAX"); } ? E("1+1") %1 = 2 ? E("1a") syntax error @eprog \synt{geval}{GEN x}. \subsec{factorpadic$(\var{pol},p,r)$}\kbdsidx{factorpadic}\label{se:factorpadic} $p$-adic factorization of the polynomial \var{pol} to precision $r$, the result being a two-column matrix as in \kbd{factor}. Note that this is not the same as a factorization over $\Z/p^r\Z$ (polynomials over that ring do not form a unique factorization domain, anyway), but approximations in $\Q/p^r\Z$ of the true factorization in $\Q_p[X]$. \bprog ? factorpadic(x^2 + 9, 3,5) %1 = [(1 + O(3^5))*x^2 + O(3^5)*x + (3^2 + O(3^5)) 1] ? factorpadic(x^2 + 1, 5,3) %2 = [ (1 + O(5^3))*x + (2 + 5 + 2*5^2 + O(5^3)) 1] [(1 + O(5^3))*x + (3 + 3*5 + 2*5^2 + O(5^3)) 1] @eprog\noindent The factors are normalized so that their leading coefficient is a power of $p$. The method used is a modified version of the \idx{round 4} algorithm of \idx{Zassenhaus}. If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence we actually factor exactly a polynomial which is only $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials with exact rational coefficients. \synt{factorpadic}{GEN f,GEN p, long r} . The function \kbd{factorpadic0} is deprecated, provided for backward compatibility. \subsec{intformal$(x,\{v\})$}\kbdsidx{intformal}\label{se:intformal} \idx{formal integration} of $x$ with respect to the variable $v$ (wrt. the main variable if $v$ is omitted). Since PARI cannot represent logarithmic or arctangent terms, any such term in the result will yield an error: \bprog ? intformal(x^2) %1 = 1/3*x^3 ? intformal(x^2, y) %2 = y*x^2 ? intformal(1/x) *** at top-level: intformal(1/x) *** ^-------------- *** intformal: domain error in intformal: residue(series, pole) != 0 @eprog The argument $x$ can be of any type. When $x$ is a rational function, we assume that the base ring is an integral domain of characteristic zero. By definition, the main variable of a \typ{POLMOD} is the main variable among the coefficients from its two polynomial components (representative and modulus); in other words, assuming a polmod represents an element of $R[X]/(T(X))$, the variable $X$ is a mute variable and the integral is taken with respect to the main variable used in the base ring $R$. In particular, it is meaningless to integrate with respect to the main variable of \kbd{x.mod}: \bprog ? intformal(Mod(1,x^2+1), 'x) *** intformal: incorrect priority in intformal: variable x = x @eprog The library syntax is \fun{GEN}{integ}{GEN x, long v = -1}, where \kbd{v} is a variable number. \subsec{padicappr$(\var{pol},a)$}\kbdsidx{padicappr}\label{se:padicappr} Vector of $p$-adic roots of the polynomial $pol$ congruent to the $p$-adic number $a$ modulo $p$, and with the same $p$-adic precision as $a$. The number $a$ can be an ordinary $p$-adic number (type \typ{PADIC}, i.e.~an element of $\Z_p$) or can be an integral element of a finite extension of $\Q_p$, given as a \typ{POLMOD} at least one of whose coefficients is a \typ{PADIC}. In this case, the result is the vector of roots belonging to the same extension of $\Q_p$ as $a$. The library syntax is \fun{GEN}{padicappr}{GEN pol, GEN a}. Also available is \fun{GEN}{Zp_appr}{GEN f, GEN a} when $a$ is a \typ{PADIC}. \subsec{padicfields$(p, N, \{\fl=0\})$}\kbdsidx{padicfields}\label{se:padicfields} Returns a vector of polynomials generating all the extensions of degree $N$ of the field $\Q_p$ of $p$-adic rational numbers; $N$ is allowed to be a 2-component vector $[n,d]$, in which case we return the extensions of degree $n$ and discriminant $p^d$. The list is minimal in the sense that two different polynomials generate non-isomorphic extensions; in particular, the number of polynomials is the number of classes of non-isomorphic extensions. If $P$ is a polynomial in this list, $\alpha$ is any root of $P$ and $K = \Q_p(\alpha)$, then $\alpha$ is the sum of a uniformizer and a (lift of a) generator of the residue field of $K$; in particular, the powers of $\alpha$ generate the ring of $p$-adic integers of $K$. If $\fl = 1$, replace each polynomial $P$ by a vector $[P, e, f, d, c]$ where $e$ is the ramification index, $f$ the residual degree, $d$ the valuation of the discriminant, and $c$ the number of conjugate fields. If $\fl = 2$, only return the \emph{number} of extensions in a fixed algebraic closure (Krasner's formula), which is much faster. The library syntax is \fun{GEN}{padicfields0}{GEN p, GEN N, long flag}. Also available is \fun{GEN}{padicfields}{GEN p, long n, long d, long flag}, which computes extensions of $\Q_p$ of degree $n$ and discriminant $p^d$. \subsec{polchebyshev$(n,\{\fl=1\},\{a='x\})$}\kbdsidx{polchebyshev}\label{se:polchebyshev} Returns the $n^{\text{th}}$ \idx{Chebyshev} polynomial of the first kind $T_n$ ($\fl=1$) or the second kind $U_n$ ($\fl=2$), evaluated at $a$ (\kbd{'x} by default). Both series of polynomials satisfy the 3-term relation $$ P_{n+1} = 2xP_n - P_{n-1}, $$ and are determined by the initial conditions $U_0 = T_0 = 1$, $T_1 = x$, $U_1 = 2x$. In fact $T_n' = n U_{n-1}$ and, for all complex numbers $z$, we have $T_n(\cos z) = \cos (nz)$ and $U_{n-1}(\cos z) = \sin(nz)/\sin z$. If $n \geq 0$, then these polynomials have degree $n$. For $n < 0$, $T_n$ is equal to $T_{-n}$ and $U_n$ is equal to $-U_{-2-n}$. In particular, $U_{-1} = 0$. The library syntax is \fun{GEN}{polchebyshev_eval}{long n, long flag, GEN a = NULL}. Also available are \fun{GEN}{polchebyshev}{long n, long \fl, long v}, \fun{GEN}{polchebyshev1}{long n, long v} and \fun{GEN}{polchebyshev2}{long n, long v} for $T_n$ and $U_n$ respectively. \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$ is greater than the degree, the result is zero. Naturally applies to scalars (polynomial of degree $0$), as well as to rational functions whose denominator is a monomial. It also applies to power series: if $n$ is less than the valuation, the result is zero. If it is greater than the largest significant degree, then an error message is issued. For greater flexibility, $x$ can be a vector or matrix type and the function then returns \kbd{component(x,n)}. The library syntax is \fun{GEN}{polcoeff0}{GEN x, long n, long v = -1}, where \kbd{v} is a variable number. \subsec{polcyclo$(n,\{a = 'x\})$}\kbdsidx{polcyclo}\label{se:polcyclo} $n$-th cyclotomic polynomial, evaluated at $a$ (\kbd{'x} by default). The integer $n$ must be positive. Algorithm used: reduce to the case where $n$ is squarefree; to compute the cyclotomic polynomial, use $\Phi_{np}(x)=\Phi_n(x^p)/\Phi(x)$; to compute it evaluated, use $\Phi_n(x) = \prod_{d\mid n} (x^d-1)^{\mu(n/d)}$. In the evaluated case, the algorithm assumes that $a^d - 1$ is either $0$ or invertible, for all $d\mid n$. If this is not the case (the base ring has zero divisors), use \kbd{subst(polcyclo(n),x,a)}. The library syntax is \fun{GEN}{polcyclo_eval}{long n, GEN a = NULL}. The variant \fun{GEN}{polcyclo}{long n, long v} returns the $n$-th cyclotomic polynomial in variable $v$. \subsec{polcyclofactors$(f)$}\kbdsidx{polcyclofactors}\label{se:polcyclofactors} Returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing $f$. \bprog ? f = x^10+5*x^8-x^7+8*x^6-4*x^5+8*x^4-3*x^3+7*x^2+3; ? v = polcyclofactors(f) %2 = [x^2 + 1, x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] ? apply(poliscycloprod, v) %3 = [1, 1, 1] ? apply(poliscyclo, v) %4 = [4, 3, 10] @eprog\noindent In general, the polynomials are products of cyclotomic polynomials and not themselves irreducible: \bprog ? g = x^8+2*x^7+6*x^6+9*x^5+12*x^4+11*x^3+10*x^2+6*x+3; ? polcyclofactors(g) %2 = [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] ? factor(%[1]) %3 = [ x^2 + x + 1 1] [x^4 + x^3 + x^2 + x + 1 1] @eprog The library syntax is \fun{GEN}{polcyclofactors}{GEN f}. \subsec{poldegree$(x,\{v\})$}\kbdsidx{poldegree}\label{se:poldegree} 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 library syntax is \fun{long}{poldegree}{GEN x, long v = -1}, where \kbd{v} is a variable number. \subsec{poldisc$(\var{pol},\{v\})$}\kbdsidx{poldisc}\label{se:poldisc} Discriminant of the polynomial \var{pol} in the main variable if $v$ is omitted, in $v$ otherwise. Uses a modular algorithm over $\Z$ or $\Q$, and the \idx{subresultant algorithm} otherwise. \bprog ? T = x^4 + 2*x+1; ? poldisc(T) %2 = -176 ? poldisc(T^2) %3 = 0 @eprog For convenience, the function also applies to types \typ{QUAD} and \typ{QFI}/\typ{QFR}: \bprog ? z = 3*quadgen(8) + 4; ? poldisc(z) %2 = 8 ? q = Qfb(1,2,3); ? poldisc(q) %4 = -8 @eprog The library syntax is \fun{GEN}{poldisc0}{GEN pol, long v = -1}, where \kbd{v} is a variable number. \subsec{poldiscreduced$(f)$}\kbdsidx{poldiscreduced}\label{se:poldiscreduced} Reduced discriminant vector of the (integral, monic) polynomial $f$. This is the vector of elementary divisors of $\Z[\alpha]/f'(\alpha)\Z[\alpha]$, where $\alpha$ is a root of the polynomial $f$. The components of the result are all positive, and their product is equal to the absolute value of the discriminant of~$f$. The library syntax is \fun{GEN}{reduceddiscsmith}{GEN f}. \subsec{polgraeffe$(f)$}\kbdsidx{polgraeffe}\label{se:polgraeffe} Returns the \idx{Graeffe} transform $g$ of $f$, such that $g(x^2) = f(x) f(-x)$. The library syntax is \fun{GEN}{polgraeffe}{GEN f}. \subsec{polhensellift$(A, B, p, e)$}\kbdsidx{polhensellift}\label{se:polhensellift} Given a prime $p$, an integral polynomial $A$ whose leading coefficient is a $p$-unit, a vector $B$ of integral polynomials that are monic and pairwise relatively prime modulo $p$, and whose product is congruent to $A/\text{lc}(A)$ modulo $p$, lift the elements of $B$ to polynomials whose product is congruent to $A$ modulo $p^e$. More generally, if $T$ is an integral polynomial irreducible mod $p$, and $B$ is a factorization of $A$ over the finite field $\F_p[t]/(T)$, you can lift it to $\Z_p[t]/(T, p^e)$ by replacing the $p$ argument with $[p,T]$: \bprog ? { T = t^3 - 2; p = 7; A = x^2 + t + 1; B = [x + (3*t^2 + t + 1), x + (4*t^2 + 6*t + 6)]; r = polhensellift(A, B, [p, T], 6) } %1 = [x + (20191*t^2 + 50604*t + 75783), x + (97458*t^2 + 67045*t + 41866)] ? liftall( r[1] * r[2] * Mod(Mod(1,p^6),T) ) %2 = x^2 + (t + 1) @eprog The library syntax is \fun{GEN}{polhensellift}{GEN A, GEN B, GEN p, long e}. \subsec{polhermite$(n,\{a='x\})$}\kbdsidx{polhermite}\label{se:polhermite} $n^{\text{th}}$ \idx{Hermite} polynomial $H_n$ evaluated at $a$ (\kbd{'x} by default), i.e. $$ H_n(x) = (-1)^n\*e^{x^2} \dfrac{d^n}{dx^n}e^{-x^2}.$$ The library syntax is \fun{GEN}{polhermite_eval}{long n, GEN a = NULL}. The variant \fun{GEN}{polhermite}{long n, long v} returns the $n$-th Hermite polynomial in variable $v$. \subsec{polinterpolate$(X,\{Y\},\{x\},\{\&e\})$}\kbdsidx{polinterpolate}\label{se:polinterpolate} Given the data vectors $X$ and $Y$ of the same length $n$ ($X$ containing the $x$-coordinates, and $Y$ the corresponding $y$-coordinates), this function finds the \idx{interpolating polynomial} passing through these points and evaluates it at~$x$. If $Y$ is omitted, return the polynomial interpolating the $(i,X[i])$. If present, $e$ will contain an error estimate on the returned value. The library syntax is \fun{GEN}{polint}{GEN X, GEN Y = NULL, GEN x = NULL, GEN *e = NULL}. \subsec{poliscyclo$(f)$}\kbdsidx{poliscyclo}\label{se:poliscyclo} Returns 0 if $f$ is not a cyclotomic polynomial, and $n > 0$ if $f = \Phi_n$, the $n$-th cyclotomic polynomial. \bprog ? poliscyclo(x^4-x^2+1) %1 = 12 ? polcyclo(12) %2 = x^4 - x^2 + 1 ? poliscyclo(x^4-x^2-1) %3 = 0 @eprog The library syntax is \fun{long}{poliscyclo}{GEN f}. \subsec{poliscycloprod$(f)$}\kbdsidx{poliscycloprod}\label{se:poliscycloprod} Returns 1 if $f$ is a product of cyclotomic polynomial, and $0$ otherwise. \bprog ? f = x^6+x^5-x^3+x+1; ? poliscycloprod(f) %2 = 1 ? factor(f) %3 = [ x^2 + x + 1 1] [x^4 - x^2 + 1 1] ? [ poliscyclo(T) | T <- %[,1] ] %4 = [3, 12] ? polcyclo(3) * polcyclo(12) %5 = x^6 + x^5 - x^3 + x + 1 @eprog The library syntax is \fun{long}{poliscycloprod}{GEN f}. \subsec{polisirreducible$(\var{pol})$}\kbdsidx{polisirreducible}\label{se:polisirreducible} \var{pol} being a polynomial (univariate in the present version \vers), returns 1 if \var{pol} is non-constant and irreducible, 0 otherwise. Irreducibility is checked over the smallest base field over which \var{pol} seems to be defined. The library syntax is \fun{long}{isirreducible}{GEN pol}. \subsec{pollead$(x,\{v\})$}\kbdsidx{pollead}\label{se:pollead} Leading coefficient of the polynomial or power series $x$. This is computed with respect to the main variable of $x$ if $v$ is omitted, with respect to the variable $v$ otherwise. The library syntax is \fun{GEN}{pollead}{GEN x, long v = -1}, where \kbd{v} is a variable number. \subsec{pollegendre$(n,\{a='x\})$}\kbdsidx{pollegendre}\label{se:pollegendre} $n^{\text{th}}$ \idx{Legendre polynomial} evaluated at $a$ (\kbd{'x} by default). 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{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. The library syntax is \fun{GEN}{polrecip}{GEN pol}. \subsec{polresultant$(x,y,\{v\},\{\fl=0\})$}\kbdsidx{polresultant}\label{se:polresultant} Resultant of the two polynomials $x$ and $y$ with exact entries, with respect to the main variables of $x$ and $y$ if $v$ is omitted, with respect to the variable $v$ otherwise. The algorithm assumes the base ring is a domain. If you also need the $u$ and $v$ such that $x*u + y*v = \text{Res}(x,y)$, use the \tet{polresultantext} function. If $\fl=0$ (default), uses the the algorithm best suited to the inputs, either the \idx{subresultant algorithm} (Lazard/Ducos variant, generic case), a modular algorithm (inputs in $\Q[X]$) or Sylvester's matrix (inexact inputs). If $\fl=1$, uses the determinant of Sylvester's matrix instead; this should always be slower than the default. The library syntax is \fun{GEN}{polresultant0}{GEN x, GEN y, long v = -1, long flag}, where \kbd{v} is a variable number. \subsec{polresultantext$(A,B,\{v\})$}\kbdsidx{polresultantext}\label{se:polresultantext} Finds polynomials $U$ and $V$ such that $A*U + B*V = R$, where $R$ is the resultant of $U$ and $V$ with respect to the main variables of $A$ and $B$ if $v$ is omitted, and with respect to $v$ otherwise. Returns the row vector $[U,V,R]$. The algorithm used (subresultant) assumes that the base ring is a domain. \bprog ? A = x*y; B = (x+y)^2; ? [U,V,R] = polresultantext(A, B) %2 = [-y*x - 2*y^2, y^2, y^4] ? A*U + B*V %3 = y^4 ? [U,V,R] = polresultantext(A, B, y) %4 = [-2*x^2 - y*x, x^2, x^4] ? A*U+B*V %5 = x^4 @eprog The library syntax is \fun{GEN}{polresultantext0}{GEN A, GEN B, long v = -1}, where \kbd{v} is a variable number. Also available is \fun{GEN}{polresultantext}{GEN x, GEN y}. \subsec{polroots$(x)$}\kbdsidx{polroots}\label{se:polroots} Complex roots of the polynomial \var{x}, given as a column vector where each root is repeated according to its multiplicity. The precision is given as for transcendental functions: in GP it is kept in the variable \kbd{realprecision} and is transparent to the user, but it must be explicitly given as a second argument in library mode. The algorithm used is a modification of A.~Sch\"onhage\sidx{Sch\"onage}'s root-finding algorithm, due to and originally implemented by X.~Gourdon. Barring bugs, it is guaranteed to converge and to give the roots to the required accuracy. The library syntax is \fun{GEN}{roots}{GEN x, long prec}. \subsec{polrootsmod$(\var{pol},p,\{\fl=0\})$}\kbdsidx{polrootsmod}\label{se:polrootsmod} Row vector of roots modulo $p$ of the polynomial \var{pol}. Multiple roots are \emph{not} repeated. \bprog ? polrootsmod(x^2-1,2) %1 = [Mod(1, 2)]~ @eprog\noindent If $p$ is very small, you may set $\fl=1$, which uses a naive search. The library syntax is \fun{GEN}{rootmod0}{GEN pol, GEN p, long flag}. \subsec{polrootspadic$(x,p,r)$}\kbdsidx{polrootspadic}\label{se:polrootspadic} Vector of $p$-adic roots of the polynomial \var{pol}, given to $p$-adic precision $r$ $p$ is assumed to be a prime. Multiple roots are \emph{not} repeated. Note that this is not the same as the roots in $\Z/p^r\Z$, rather it gives approximations in $\Z/p^r\Z$ of the true roots living in $\Q_p$. \bprog ? polrootspadic(x^3 - x^2 + 64, 2, 5) %1 = [2^3 + O(2^5), 2^3 + 2^4 + O(2^5), 1 + O(2^5)]~ @eprog If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence the roots given are approximations of the roots of an exact polynomial which is $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials 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. 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). \subsec{polsubcyclo$(n,d,\{v='x\})$}\kbdsidx{polsubcyclo}\label{se:polsubcyclo} Gives polynomials (in variable $v$) defining the sub-Abelian extensions of degree $d$ of the cyclotomic field $\Q(\zeta_n)$, where $d\mid \phi(n)$. If there is exactly one such extension the output is a polynomial, else it is a vector of polynomials, possibly empty. To get a vector in all cases, use \kbd{concat([], polsubcyclo(n,d))}. The function \tet{galoissubcyclo} allows to specify exactly which sub-Abelian extension should be computed. The library syntax is \fun{GEN}{polsubcyclo}{long n, long d, long v = -1}, where \kbd{v} is a variable number. \subsec{polsylvestermatrix$(x,y)$}\kbdsidx{polsylvestermatrix}\label{se:polsylvestermatrix} Forms the Sylvester matrix corresponding to the two polynomials $x$ and $y$, where the coefficients of the polynomials are put in the columns of the matrix (which is the natural direction for solving equations afterwards). The use of this matrix can be essential when dealing with polynomials with inexact entries, since polynomial Euclidean division doesn't make much sense in this case. The library syntax is \fun{GEN}{sylvestermatrix}{GEN x, GEN y}. \subsec{polsym$(x,n)$}\kbdsidx{polsym}\label{se:polsym} Creates the column vector of the \idx{symmetric powers} of the roots of the polynomial $x$ up to power $n$, using Newton's formula. The library syntax is \fun{GEN}{polsym}{GEN x, long n}. \subsec{poltchebi$(n,\{v='x\})$}\kbdsidx{poltchebi}\label{se:poltchebi} Deprecated alias for \kbd{polchebyshev} The library syntax is \fun{GEN}{polchebyshev1}{long n, long v = -1}, where \kbd{v} is a variable number. \subsec{polzagier$(n,m)$}\kbdsidx{polzagier}\label{se:polzagier} 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. %@article {MR2001m:11222, % AUTHOR = {Cohen, Henri and Rodriguez Villegas, Fernando and Zagier, Don}, % TITLE = {Convergence acceleration of alternating series}, % JOURNAL = {Experiment. Math.}, % VOLUME = {9}, % YEAR = {2000}, % NUMBER = {1}, % PAGES = {3--12}, %} The library syntax is \fun{GEN}{polzag}{long n, long m}. \subsec{serconvol$(x,y)$}\kbdsidx{serconvol}\label{se:serconvol} Convolution (or \idx{Hadamard product}) of the two power series $x$ and $y$; in other words if $x=\sum a_k*X^k$ and $y=\sum b_k*X^k$ then $\kbd{serconvol}(x,y)=\sum a_k*b_k*X^k$. 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$. The library syntax is \fun{GEN}{laplace}{GEN x}. \subsec{serreverse$(s)$}\kbdsidx{serreverse}\label{se:serreverse} Reverse power series of $s$, i.e. the series $t$ such that $t(s) = x$; $s$ must be a power series whose valuation is exactly equal to one. \bprog ? \ps 8 ? t = serreverse(tan(x)) %2 = x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + O(x^8) ? tan(t) %3 = x + O(x^8) @eprog The library syntax is \fun{GEN}{serreverse}{GEN s}. \subsec{subst$(x,y,z)$}\kbdsidx{subst}\label{se:subst} Replace the simple variable $y$ by the argument $z$ in the ``polynomial'' expression $x$. Every type is allowed for $x$, but if it is not a genuine polynomial (or power series, or rational function), the substitution will be done as if the scalar components were polynomials of degree zero. In particular, beware that: \bprog ? subst(1, x, [1,2; 3,4]) %1 = [1 0] [0 1] ? subst(1, x, Mat([0,1])) *** at top-level: subst(1,x,Mat([0,1]) *** ^-------------------- *** subst: forbidden substitution by a non square matrix. @eprog\noindent If $x$ is a power series, $z$ must be either a polynomial, a power series, or a rational function. Finally, if $x$ is a vector, matrix or list, the substitution is applied to each individual entry. Use the function \kbd{substvec} to replace several variables at once, or the function \kbd{substpol} to replace a polynomial expression. The library syntax is \fun{GEN}{gsubst}{GEN x, long y, GEN z}, where \kbd{y} is a variable number. \subsec{substpol$(x,y,z)$}\kbdsidx{substpol}\label{se:substpol} Replace the ``variable'' $y$ by the argument $z$ in the ``polynomial'' expression $x$. Every type is allowed for $x$, but the same behavior as \kbd{subst} above apply. The difference with \kbd{subst} is that $y$ is allowed to be any polynomial here. The substitution is done moding out all components of $x$ (recursively) by $y - t$, where $t$ is a new free variable of lowest priority. Then substituting $t$ by $z$ in the resulting expression. For instance \bprog ? substpol(x^4 + x^2 + 1, x^2, y) %1 = y^2 + y + 1 ? substpol(x^4 + x^2 + 1, x^3, y) %2 = x^2 + y*x + 1 ? substpol(x^4 + x^2 + 1, (x+1)^2, y) %3 = (-4*y - 6)*x + (y^2 + 3*y - 3) @eprog The library syntax is \fun{GEN}{gsubstpol}{GEN x, GEN y, GEN z}. Further, \fun{GEN}{gdeflate}{GEN T, long v, long d} attempts to write $T(x)$ in the form $t(x^d)$, where $x=$\kbd{pol\_x}$(v)$, and returns \kbd{NULL} if the substitution fails (for instance in the example \kbd{\%2} above). \subsec{substvec$(x,v,w)$}\kbdsidx{substvec}\label{se:substvec} $v$ being a vector of monomials of degree 1 (variables), $w$ a vector of expressions of the same length, replace in the expression $x$ all occurrences of $v_i$ by $w_i$. The substitutions are done simultaneously; more precisely, the $v_i$ are first replaced by new variables in $x$, then these are replaced by the $w_i$: \bprog ? substvec([x,y], [x,y], [y,x]) %1 = [y, x] ? substvec([x,y], [x,y], [y,x+y]) %2 = [y, x + y] \\ not [y, 2*y] @eprog The library syntax is \fun{GEN}{gsubstvec}{GEN x, GEN v, GEN w}. \subsec{sumformal$(f,\{v\})$}\kbdsidx{sumformal}\label{se:sumformal} \idx{formal sum} of the polynomial expression $f$ with respect to the main variable if $v$ is omitted, with respect to the variable $v$ otherwise; it is assumed that the base ring has characteristic zero. In other words, considering $f$ as a polynomial function in the variable $v$, returns $F$, a polynomial in $v$ vanishing at $0$, such that $F(b) - F(a) = sum_{v = a+1}^b f(v)$: \bprog ? sumformal(n) \\ 1 + ... + n %1 = 1/2*n^2 + 1/2*n ? f(n) = n^3+n^2+1; ? F = sumformal(f(n)) \\ f(1) + ... + f(n) %3 = 1/4*n^4 + 5/6*n^3 + 3/4*n^2 + 7/6*n ? sum(n = 1, 2000, f(n)) == subst(F, n, 2000) %4 = 1 ? sum(n = 1001, 2000, f(n)) == subst(F, n, 2000) - subst(F, n, 1000) %5 = 1 ? sumformal(x^2 + x*y + y^2, y) %6 = y*x^2 + (1/2*y^2 + 1/2*y)*x + (1/3*y^3 + 1/2*y^2 + 1/6*y) ? x^2 * y + x * sumformal(y) + sumformal(y^2) == % %7 = 1 @eprog The library syntax is \fun{GEN}{sumformal}{GEN f, long v = -1}, where \kbd{v} is a variable number. \subsec{taylor$(x,t,\{d=\var{seriesprecision}\})$}\kbdsidx{taylor}\label{se:taylor} Taylor expansion around $0$ of $x$ with respect to the simple variable $t$. $x$ can be of any reasonable type, for example a rational function. Contrary to \tet{Ser}, which takes the valuation into account, this function adds $O(t^d)$ to all components of $x$. \bprog ? taylor(x/(1+y), y, 5) %1 = (y^4 - y^3 + y^2 - y + 1)*x + O(y^5) ? Ser(x/(1+y), y, 5) *** at top-level: Ser(x/(1+y),y,5) *** ^---------------- *** Ser: main variable must have higher priority in gtoser. @eprog The library syntax is \fun{GEN}{tayl}{GEN x, long t, long precdl}, where \kbd{t} is a variable number. \subsec{thue$(\var{tnf},a,\{\var{sol}\})$}\kbdsidx{thue}\label{se:thue} Returns all solutions of the equation $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. 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 very wasteful if more than one value of $a$ is required. If \var{tnf} was computed without assuming GRH (flag $1$ in \tet{thueinit}), then the result is unconditional. Otherwise, it depends in principle of the truth of the GRH, but may still be unconditionally correct in some favorable cases. The result is conditional on the GRH if $a\neq \pm 1$ and, $P$ has a single irreducible rational factor, whose associated tentative class number $h$ and regulator $R$ (as computed assuming the GRH) satisfy \item $h > 1$, \item $R/0.2 > 1.5$. Here's how to solve the Thue equation $x^{13} - 5y^{13} = - 4$: \bprog ? tnf = thueinit(x^13 - 5); ? thue(tnf, -4) %1 = [[1, 1]] @eprog\noindent In this case, one checks that \kbd{bnfinit(x\pow13 -5).no} is $1$. Hence, the only solution is $(x,y) = (1,1)$, and the result is unconditional. On the other hand: \bprog ? P = x^3-2*x^2+3*x-17; tnf = thueinit(P); ? thue(tnf, -15) %2 = [[1, 1]] \\ a priori conditional on the GRH. ? K = bnfinit(P); K.no %3 = 3 ? K.reg %4 = 2.8682185139262873674706034475498755834 @eprog This time the result is conditional. All results computed using this particular \var{tnf} are likewise conditional, \emph{except} for a right-hand side of $\pm 1$. The above result is in fact correct, so we did not just disprove the GRH: \bprog ? tnf = thueinit(x^3-2*x^2+3*x-17, 1 /*unconditional*/); ? thue(tnf, -15) %4 = [[1, 1]] @eprog Note that reducible or non-monic polynomials are allowed: \bprog ? tnf = thueinit((2*x+1)^5 * (4*x^3-2*x^2+3*x-17), 1); ? thue(tnf, 128) %2 = [[-1, 0], [1, 0]] @eprog\noindent Reducible polynomials are in fact much easier to handle. 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. 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. The library syntax is \fun{GEN}{thueinit}{GEN P, long flag, long prec}. %SECTION: polynomials \section{Vectors, matrices, linear algebra and sets} \label{se:linear_algebra} Note that most linear algebra functions operating on subspaces defined by generating sets (such as \tet{mathnf}, \tet{qflll}, etc.) take matrices as arguments. As usual, the generating vectors are taken to be the \emph{columns} of the given matrix. Since PARI does not have a strong typing system, scalars live in unspecified commutative base rings. It is very difficult to write robust linear algebra routines in such a general setting. We thus assume that the base ring is a domain and work over its field of fractions. If the base ring is \emph{not} a domain, one gets an error as soon as a non-zero pivot turns out to be non-invertible. Some functions, e.g.~\kbd{mathnf} or \kbd{mathnfmod}, specifically assume that the base ring is $\Z$. \subsec{algdep$(x,k,\{\fl=0\})$}\kbdsidx{algdep}\label{se:algdep} \sidx{algebraic dependence} $x$ being real/complex, or $p$-adic, finds a polynomial of degree at most $k$ with integer coefficients having $x$ as approximate root. Note that the polynomial which is obtained is not necessarily the ``correct'' one. In fact it is not even guaranteed to be irreducible. One can check the closeness either by a polynomial evaluation (use \tet{subst}), or by computing the roots of the polynomial given by \kbd{algdep} (use \tet{polroots}). Internally, \tet{lindep}$([1,x,\ldots,x^k], \fl)$ is used. A non-zero value of $\fl$ may improve on the default behavior if the input number is known to a \emph{huge} accuracy, and you suspect the last bits are incorrect (this truncates the number, throwing away the least significant bits), but default values are usually sufficient: \bprog ? \p200 ? algdep(2^(1/6)+3^(1/5), 30); \\ wrong in 0.8s ? algdep(2^(1/6)+3^(1/5), 30, 100); \\ wrong in 0.4s ? algdep(2^(1/6)+3^(1/5), 30, 170); \\ right in 0.8s ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ wrong in 1.0s ? \p250 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 1.0s ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ right in 1.0s ? \p500 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 2.9s ? \p1000 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 10.6s @eprog\noindent The changes in \kbd{defaultprecision} only affect the quality of the initial approximation to $2^{1/6} + 3^{1/5}$, \kbd{algdep} itself uses exact operations (the size of its operands depend on the accuracy of the input of course: more accurate input means slower operations). Proceeding by increments of 5 digits of accuracy, \kbd{algdep} with default flag produces its first correct result at 205 digits, and from then on a steady stream of correct results. The above example is the test case studied in a 2000 paper by Borwein and Lisonek: Applications of integer relation algorithms, \emph{Discrete Math.}, {\bf 217}, p.~65--82. The version of PARI tested there was 1.39, which succeeded reliably from precision 265 on, in about 200 as much time as the current version. The library syntax is \fun{GEN}{algdep0}{GEN x, long k, long flag}. Also available is \fun{GEN}{algdep}{GEN x, long k} ($\fl=0$). \subsec{charpoly$(A,\{v='x\},\{\fl=5\})$}\kbdsidx{charpoly}\label{se:charpoly} \idx{characteristic polynomial} of $A$ with respect to the variable $v$, i.e.~determinant of $v*I-A$ if $A$ is a square matrix. \bprog ? charpoly([1,2;3,4]); %1 = x^2 - 5*x - 2 ? charpoly([1,2;3,4],, 't) %2 = t^2 - 5*t - 2 @eprog\noindent If $A$ is not a square matrix, the function returns the characteristic polynomial of the map ``multiplication by $A$'' if $A$ is a scalar: \bprog ? charpoly(Mod(x+2, x^3-2)) %1 = x^3 - 6*x^2 + 12*x - 10 ? charpoly(I) %2 = x^2 + 1 ? charpoly(quadgen(5)) %3 = x^2 - x - 1 ? charpoly(ffgen(ffinit(2,4))) %4 = Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) @eprog The value of $\fl$ is only significant for matrices, and we advise to stick to the default value. Let $n$ be the dimension of $A$. If $\fl=0$, same method (Le Verrier's) as for computing the adjoint matrix, i.e.~using the traces of the powers of $A$. Assumes that $n!$ is invertible; uses $O(n^4)$ scalar operations. If $\fl=1$, uses Lagrange interpolation which is usually the slowest method. Assumes that $n!$ is invertible; uses $O(n^4)$ scalar operations. If $\fl=2$, uses the Hessenberg form. Assumes that the base ring is a field. Uses $O(n^3)$ scalar operations, but suffers from coefficient explosion unless the base field is finite or $\R$. If $\fl=3$, uses Berkowitz's division free algorithm, valid over any ring (commutative, with unit). Uses $O(n^4)$ scalar operations. If $\fl=4$, $x$ must be integral. Uses a modular algorithm: Hessenberg form for various small primes, then Chinese remainders. If $\fl=5$ (default), uses the ``best'' method given $x$. This means we use Berkowitz unless the base ring is $\Z$ (use $\fl=4$) or a field where coefficient explosion does not occur, e.g.~a finite field or the reals (use $\fl=2$). The library syntax is \fun{GEN}{charpoly0}{GEN A, long v = -1, long flag}, where \kbd{v} is a variable number. Also available are \fun{GEN}{charpoly}{GEN x, long v} ($\fl=5$), \fun{GEN}{caract}{GEN A, long v} ($\fl=1$), \fun{GEN}{carhess}{GEN A, long v} ($\fl=2$), \fun{GEN}{carberkowitz}{GEN A, long v} ($\fl=3$) and \fun{GEN}{caradj}{GEN A, long v, GEN *pt}. In this last case, if \var{pt} is not \kbd{NULL}, \kbd{*pt} receives the address of the adjoint matrix of $A$ (see \tet{matadjoint}), so both can be obtained at once. \subsec{concat$(x,\{y\})$}\kbdsidx{concat}\label{se:concat} Concatenation of $x$ and $y$. If $x$ or $y$ is not a vector or matrix, it is considered as a one-dimensional vector. All types are allowed for $x$ and $y$, but the sizes must be compatible. Note that matrices are concatenated horizontally, i.e.~the number of rows stays the same. Using transpositions, one can concatenate them vertically, but it is often simpler to use \tet{matconcat}. \bprog ? x = matid(2); y = 2*matid(2); ? concat(x,y) %2 = [1 0 2 0] [0 1 0 2] ? concat(x~,y~)~ %3 = [1 0] [0 1] [2 0] [0 2] ? matconcat([x;y]) %4 = [1 0] [0 1] [2 0] [0 2] @eprog\noindent To concatenate vectors sideways (i.e.~to obtain a two-row or two-column matrix), use \tet{Mat} instead, or \tet{matconcat}: \bprog ? x = [1,2]; ? y = [3,4]; ? concat(x,y) %3 = [1, 2, 3, 4] ? Mat([x,y]~) %4 = [1 2] [3 4] ? matconcat([x;y]) %5 = [1 2] [3 4] @eprog Concatenating a row vector to a matrix having the same number of columns will add the row to the matrix (top row if the vector is $x$, i.e.~comes first, and bottom row otherwise). The empty matrix \kbd{[;]} is considered to have a number of rows compatible with any operation, in particular concatenation. (Note that this is \emph{not} the case for empty vectors \kbd{[~]} or \kbd{[~]\til}.) If $y$ is omitted, $x$ has to be a row vector or a list, in which case its elements are concatenated, from left to right, using the above rules. \bprog ? concat([1,2], [3,4]) %1 = [1, 2, 3, 4] ? a = [[1,2]~, [3,4]~]; concat(a) %2 = [1 3] [2 4] ? concat([1,2; 3,4], [5,6]~) %3 = [1 2 5] [3 4 6] ? concat([%, [7,8]~, [1,2,3,4]]) %5 = [1 2 5 7] [3 4 6 8] [1 2 3 4] @eprog The library syntax is \fun{GEN}{concat}{GEN x, GEN y = NULL}. \fun{GEN}{concat1}{GEN x} is a shortcut for \kbd{concat(x,NULL)}. \subsec{forqfvec$(v,q,b,\var{expr})$}\kbdsidx{forqfvec}\label{se:forqfvec} $q$ being a square and symmetric matrix representing a positive definite quadratic form, evaluate \kbd{expr} for all vector $v$ such that $q(v)\leq b$. The formal variable $v$ runs through all such vectors in turn. \bprog ? forqfvec(v, [3,2;2,3], 3, print(v)) [0, 1]~ [1, 0]~ [-1, 1]~ @eprog The library syntax is \fun{void}{forqfvec0}{GEN v, GEN q = NULL, GEN b}. The following function is also available: \fun{void}{forqfvec}{void *E, long (*fun)(void *, GEN, double), GEN q, GEN b}: Evaluate \kbd{fun(E,v,m)} on all $v$ such that $q(v) 0$ the computation is done with an accuracy of $\fl$ decimal digits. To get meaningful results in the latter case, the parameter $\fl$ should be smaller than the number of correct decimal digits in the input. \bprog ? lindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)]) %1 = [-1, -1, 1]~ @eprog If $v$ is $p$-adic, $\fl$ is ignored and the algorithm LLL-reduces a suitable (dual) lattice. \bprog ? lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)]) %2 = [1, -2]~ @eprog If $v$ is a matrix, $\fl$ is ignored and the function returns a non trivial kernel vector (combination of the columns). \bprog ? lindep([1,2,3;4,5,6;7,8,9]) %3 = [1, -2, 1]~ @eprog If $v$ contains polynomials or power series over some base field, finds a linear relation with coefficients in the field. \bprog ? lindep([x*y, x^2 + y, x^2*y + x*y^2, 1]) %4 = [y, y, -1, -y^2]~ @eprog\noindent For better control, it is preferable to use \typ{POL} rather than \typ{SER} in the input, otherwise one gets a linear combination which is $t$-adically small, but not necessarily $0$. Indeed, power series are first converted to the minimal absolute accuracy occurring among the entries of $v$ (which can cause some coefficients to be ignored), then truncated to polynomials: \bprog ? v = [t^2+O(t^4), 1+O(t^2)]; L=lindep(v) %1 = [1, 0]~ ? v*L %2 = t^2+O(t^4) \\ small but not 0 @eprog The library syntax is \fun{GEN}{lindep0}{GEN v, long flag}. Also available are \fun{GEN}{lindep}{GEN v} (real/complex entries, $\fl=0$), \fun{GEN}{lindep2}{GEN v, long flag} (real/complex entries) \fun{GEN}{padic_lindep}{GEN v} ($p$-adic entries) and \fun{GEN}{Xadic_lindep}{GEN v} (polynomial entries). Finally \fun{GEN}{deplin}{GEN v} returns a non-zero kernel vector for a \typ{MAT} input. \subsec{listcreate$()$}\kbdsidx{listcreate}\label{se:listcreate} Creates an empty list. This routine used to have a mandatory argument, which is now ignored (for backward compatibility). In fact, this function has become redundant and obsolete; it will disappear in future versions of PARI: just use \kbd{List()} % \syn{NO} \subsec{listinsert$(L,x,n)$}\kbdsidx{listinsert}\label{se:listinsert} Inserts the object $x$ at position $n$ in $L$ (which must be of type \typ{LIST}). This has complexity $O(\#L - n + 1)$: all the remaining elements of \var{list} (from position $n+1$ onwards) are shifted to the right. The library syntax is \fun{GEN}{listinsert}{GEN L, GEN x, long n}. \subsec{listkill$(L)$}\kbdsidx{listkill}\label{se:listkill} Obsolete, retained for backward compatibility. Just use \kbd{L = List()} instead of \kbd{listkill(L)}. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns. The library syntax is \fun{void}{listkill}{GEN L}. \subsec{listpop$(\var{list},\{n\})$}\kbdsidx{listpop}\label{se:listpop} Removes the $n$-th element of the list \var{list} (which must be of type \typ{LIST}). If $n$ is omitted, or greater than the list current length, removes the last element. If the list is already empty, do nothing. This runs in time $O(\#L - n + 1)$. The library syntax is \fun{void}{listpop}{GEN list, long n}. \subsec{listput$(\var{list},x,\{n\})$}\kbdsidx{listput}\label{se:listput} Sets the $n$-th element of the list \var{list} (which must be of type \typ{LIST}) equal to $x$. If $n$ is omitted, or greater than the list length, appends $x$. You may put an element into an occupied cell (not changing the list length), but it is easier to use the standard \kbd{list[n] = x} construct. This runs in time $O(\#L)$ in the worst case (when the list must be reallocated), but in time $O(1)$ on average: any number of successive \kbd{listput}s run in time $O(\#L)$, where $\#L$ denotes the list \emph{final} length. The library syntax is \fun{GEN}{listput}{GEN list, GEN x, long n}. \subsec{listsort$(L,\{\fl=0\})$}\kbdsidx{listsort}\label{se:listsort} Sorts the \typ{LIST} \var{list} in place, with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. In particular, the ordering is the same as for sets and \tet{setsearch} can be used on a sorted list. \bprog ? L = List([1,2,4,1,3,-1]); listsort(L); L %1 = List([-1, 1, 1, 2, 3, 4]) ? setsearch(L, 4) %2 = 6 ? setsearch(L, -2) %3 = 0 @eprog\noindent This is faster than the \kbd{vecsort} command since the list is sorted in place: no copy is made. No value returned. If $\fl$ is non-zero, suppresses all repeated coefficients. The library syntax is \fun{void}{listsort}{GEN L, long flag}. \subsec{matadjoint$(M,\{\fl=0\})$}\kbdsidx{matadjoint}\label{se:matadjoint} \idx{adjoint matrix} of $M$, i.e.~a matrix $N$ of cofactors of $M$, satisfying $M*N=\det(M)*\Id$. $M$ must be a (non-necessarily invertible) square matrix of dimension $n$. If $\fl$ is 0 or omitted, we try to use Leverrier-Faddeev's algorithm, which assumes that $n!$ invertible. If it fails or $\fl = 1$, compute $T = \kbd{charpoly}(M)$ independently first and return $(-1)^{n-1} (T(x)-T(0))/x$ evaluated at $M$. \bprog ? a = [1,2,3;3,4,5;6,7,8] * Mod(1,4); %2 = [Mod(1, 4) Mod(2, 4) Mod(3, 4)] [Mod(3, 4) Mod(0, 4) Mod(1, 4)] [Mod(2, 4) Mod(3, 4) Mod(0, 4)] @eprog\noindent Both algorithms use $O(n^4)$ operations in the base ring, and are usually slower than computing the characteristic polynomial or the inverse of $M$ directly. The library syntax is \fun{GEN}{matadjoint0}{GEN M, long flag}. Also available are \fun{GEN}{adj}{GEN x} (\fl=0) and \fun{GEN}{adjsafe}{GEN x} (\fl=1). \subsec{matcompanion$(x)$}\kbdsidx{matcompanion}\label{se:matcompanion} The left companion matrix to the non-zero polynomial $x$. The library syntax is \fun{GEN}{matcompanion}{GEN x}. \subsec{matconcat$(v)$}\kbdsidx{matconcat}\label{se:matconcat} Returns a \typ{MAT} built from the entries of $v$, which may be a \typ{VEC} (concatenate horizontally), a \typ{COL} (concatenate vertically), or a \typ{MAT} (concatenate vertically each column, and concatenate vertically the resulting matrices). The entries of $v$ are always considered as matrices: they can themselves be \typ{VEC} (seen as a row matrix), a \typ{COL} seen as a column matrix), a \typ{MAT}, or a scalar (seen as an $1 \times 1$ matrix). \bprog ? A=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9; ? matconcat([A, B]) \\ horizontal %1 = [1 2 5] [3 4 6] ? matconcat([A, C]~) \\ vertical %2 = [1 2] [3 4] [7 8] ? matconcat([A, B; C, D]) \\ block matrix %3 = [1 2 5] [3 4 6] [7 8 9] @eprog\noindent If the dimensions of the entries to concatenate do not match up, the above rules are extended as follows: \item each entry $v_{i,j}$ of $v$ has a natural length and height: $1 \times 1$ for a scalar, $1 \times n$ for a \typ{VEC} of length $n$, $n \times 1$ for a \typ{COL}, $m \times n$ for an $m\times n$ \typ{MAT} \item let $H_i$ be the maximum over $j$ of the lengths of the $v_{i,j}$, let $L_j$ be the maximum over $i$ of the heights of the $v_{i,j}$. The dimensions of the $(i,j)$-th block in the concatenated matrix are $H_i \times L_j$. \item a scalar $s = v_{i,j}$ is considered as $s$ times an identity matrix of the block dimension $\min (H_i,L_j)$ \item blocks are extended by 0 columns on the right and 0 rows at the bottom, as needed. \bprog ? matconcat([1, [2,3]~, [4,5,6]~]) \\ horizontal %4 = [1 2 4] [0 3 5] [0 0 6] ? matconcat([1, [2,3], [4,5,6]]~) \\ vertical %5 = [1 0 0] [2 3 0] [4 5 6] ? matconcat([B, C; A, D]) \\ block matrix %6 = [5 0 7 8] [6 0 0 0] [1 2 9 0] [3 4 0 9] ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9]; ? matconcat(matdiagonal([U, V])) \\ block diagonal %7 = [1 2 0 0 0] [3 4 0 0 0] [0 0 1 2 3] [0 0 4 5 6] [0 0 7 8 9] @eprog The library syntax is \fun{GEN}{matconcat}{GEN v}. \subsec{matdet$(x,\{\fl=0\})$}\kbdsidx{matdet}\label{se:matdet} Determinant of the square matrix $x$. If $\fl=0$, uses an appropriate algorithm depending on the coefficients: \item integer entries: modular method due to Dixon, Pernet and Stein. \item real or $p$-adic entries: classical Gaussian elimination using maximal pivot. \item intmod entries: classical Gaussian elimination using first non-zero pivot. \item other cases: Gauss-Bareiss. If $\fl=1$, uses classical Gaussian elimination with appropriate pivoting strategy (maximal pivot for real or $p$-adic coefficients). This is usually worse than the default. The library syntax is \fun{GEN}{det0}{GEN x, long flag}. Also available are \fun{GEN}{det}{GEN x} ($\fl=0$), \fun{GEN}{det2}{GEN x} ($\fl=1$) and \fun{GEN}{ZM_det}{GEN x} for integer entries. \subsec{matdetint$(B)$}\kbdsidx{matdetint}\label{se:matdetint} Let $B$ be an $m\times n$ matrix with integer coefficients. The \emph{determinant} $D$ of the lattice generated by the columns of $B$ is the square root of $\det(B^T B)$ if $B$ has maximal rank $m$, and $0$ otherwise. This function uses the Gauss-Bareiss algorithm to compute a positive \emph{multiple} of $D$. When $B$ is square, the function actually returns $D = |\det B|$. This function is useful in conjunction with \kbd{mathnfmod}, which needs to know such a multiple. If the rank is maximal and the matrix non-square, you can obtain $D$ exactly using \bprog matdet( mathnfmod(B, matdetint(B)) ) @eprog\noindent Note that as soon as one of the dimensions gets large ($m$ or $n$ is larger than 20, say), it will often be much faster to use \kbd{mathnf(B, 1)} or \kbd{mathnf(B, 4)} directly. The library syntax is \fun{GEN}{detint}{GEN B}. \subsec{matdiagonal$(x)$}\kbdsidx{matdiagonal}\label{se:matdiagonal} $x$ being a vector, creates the diagonal matrix whose diagonal entries are those of $x$. \bprog ? matdiagonal([1,2,3]); %1 = [1 0 0] [0 2 0] [0 0 3] @eprog\noindent Block diagonal matrices are easily created using \tet{matconcat}: \bprog ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9]; ? matconcat(matdiagonal([U, V])) %1 = [1 2 0 0 0] [3 4 0 0 0] [0 0 1 2 3] [0 0 4 5 6] [0 0 7 8 9] @eprog The library syntax is \fun{GEN}{diagonal}{GEN x}. \subsec{mateigen$(x,\{\fl=0\})$}\kbdsidx{mateigen}\label{se:mateigen} Returns the (complex) eigenvectors of $x$ as columns of a matrix. If $\fl=1$, return $[L,H]$, where $L$ contains the eigenvalues and $H$ the corresponding eigenvectors; multiple eigenvalues are repeated according to the eigenspace dimension (which may be less than the eigenvalue multiplicity in the characteristic polynomial). This function first computes the characteristic polynomial of $x$ and approximates its complex roots $(\lambda_i)$, then tries to compute the eigenspaces as kernels of the $x - \lambda_i$. This algorithm is ill-conditioned and is likely to miss kernel vectors if some roots of the characteristic polynomial are close, in particular if it has multiple roots. \bprog ? A = [13,2; 10,14]; mateigen(A) %1 = [-1/2 2/5] [ 1 1] ? [L,H] = mateigen(A, 1); ? L %3 = [9, 18] ? H %4 = [-1/2 2/5] [ 1 1] @eprog\noindent For symmetric matrices, use \tet{qfjacobi} instead; for Hermitian matrices, compute \bprog A = real(x); B = imag(x); y = matconcat([A, -B; B, A]); @eprog\noindent and apply \kbd{qfjacobi} to $y$. The library syntax is \fun{GEN}{mateigen}{GEN x, long flag, long prec}. Also available is \fun{GEN}{eigen}{GEN x, long prec} ($\fl = 0$) \subsec{matfrobenius$(M,\{\fl\},\{v='x\})$}\kbdsidx{matfrobenius}\label{se:matfrobenius} Returns the Frobenius form of the square matrix \kbd{M}. If $\fl=1$, returns only the elementary divisors as a vector of polynomials in the variable \kbd{v}. If $\fl=2$, returns a two-components vector [F,B] where \kbd{F} is the Frobenius form and \kbd{B} is the basis change so that $M=B^{-1}FB$. The library syntax is \fun{GEN}{matfrobenius}{GEN M, long flag, long v = -1}, where \kbd{v} is a variable number. \subsec{mathess$(x)$}\kbdsidx{mathess}\label{se:mathess} Returns a matrix similar to the square matrix $x$, which is in upper Hessenberg form (zero entries below the first subdiagonal). The library syntax is \fun{GEN}{hess}{GEN x}. \subsec{mathilbert$(n)$}\kbdsidx{mathilbert}\label{se:mathilbert} $x$ being a \kbd{long}, creates the \idx{Hilbert matrix}of order $x$, i.e.~the matrix whose coefficient ($i$,$j$) is $1/ (i+j-1)$. The library syntax is \fun{GEN}{mathilbert}{long n}. \subsec{mathnf$(M,\{\fl=0\})$}\kbdsidx{mathnf}\label{se:mathnf} Let $R$ be a Euclidean ring, equal to $\Z$ or to $K[X]$ for some field $K$. If $M$ is a (not necessarily square) matrix with entries in $R$, this routine finds the \emph{upper triangular} \idx{Hermite normal form} of $M$. If the rank of $M$ is equal to its number of rows, this is a square matrix. In general, the columns of the result form a basis of the $R$-module spanned by the columns of $M$. The values $0,1,2,3$ of $\fl$ have a binary meaning, analogous to the one in \tet{matsnf}; in this case, binary digits of $\fl$ mean: \item 1 (complete output): if set, outputs $[H,U]$, where $H$ is the Hermite normal form of $M$, and $U$ is a transformation matrix such that $MU=[0|H]$. The matrix $U$ belongs to $\text{GL}(R)$. When $M$ has a large kernel, the entries of $U$ are in general huge. \item 2 (generic input): \emph{Deprecated}. If set, assume that $R = K[X]$ is a polynomial ring; otherwise, assume that $R = \Z$. This flag is now useless since the routine always checks whether the matrix has integral entries. \noindent For these 4 values, we use a naive algorithm, which behaves well in small dimension only. Larger values correspond to different algorithms, are restricted to \emph{integer} matrices, and all output the unimodular matrix $U$. From now on all matrices have integral entries. \item $\fl=4$, returns $[H,U]$ as in ``complete output'' above, using a variant of \idx{LLL} reduction along the way. The matrix $U$ is provably small in the $L_2$ sense, and in general close to optimal; but the reduction is in general slow, although provably polynomial-time. If $\fl=5$, uses Batut's algorithm and output $[H,U,P]$, such that $H$ and $U$ are as before and $P$ is a permutation of the rows such that $P$ applied to $MU$ gives $H$. This is in general faster than $\fl=4$ but the matrix $U$ is usually worse; it is heuristically smaller than with the default algorithm. When the matrix is dense and the dimension is large (bigger than 100, say), $\fl = 4$ will be fastest. When $M$ has maximal rank, then \bprog H = mathnfmod(M, matdetint(M)) @eprog\noindent will be even faster. You can then recover $U$ as $M^{-1}H$. \bprog ? M = matrix(3,4,i,j,random([-5,5])) %1 = [ 0 2 3 0] [-5 3 -5 -5] [ 4 3 -5 4] ? [H,U] = mathnf(M, 1); ? U %3 = [-1 0 -1 0] [ 0 5 3 2] [ 0 3 1 1] [ 1 0 0 0] ? H %5 = [19 9 7] [ 0 9 1] [ 0 0 1] ? M*U %6 = [0 19 9 7] [0 0 9 1] [0 0 0 1] @eprog For convenience, $M$ is allowed to be a \typ{VEC}, which is then automatically converted to a \typ{MAT}, as per the \tet{Mat} function. For instance to solve the generalized extended gcd problem, one may use \bprog ? v = [116085838, 181081878, 314252913,10346840]; ? [H,U] = mathnf(v, 1); ? U %2 = [ 103 -603 15 -88] [-146 13 -1208 352] [ 58 220 678 -167] [-362 -144 381 -101] ? v*U %3 = [0, 0, 0, 1] @eprog\noindent This also allows to input a matrix as a \typ{VEC} of \typ{COL}s of the same length (which \kbd{Mat} would concatenate to the \typ{MAT} having those columns): \bprog ? v = [[1,0,4]~, [3,3,4]~, [0,-4,-5]~]; mathnf(v) %1 = [47 32 12] [ 0 1 0] [ 0 0 1] @eprog The library syntax is \fun{GEN}{mathnf0}{GEN M, long flag}. Also available are \fun{GEN}{hnf}{GEN M} ($\fl=0$) and \fun{GEN}{hnfall}{GEN M} ($\fl=1$). To reduce \emph{huge} relation matrices (sparse with small entries, say dimension $400$ or more), you can use the pair \kbd{hnfspec} / \kbd{hnfadd}. Since this is quite technical and the calling interface may change, they are not documented yet. Look at the code in \kbd{basemath/hnf\_snf.c}. \subsec{mathnfmod$(x,d)$}\kbdsidx{mathnfmod}\label{se:mathnfmod} If $x$ is a (not necessarily square) matrix of maximal rank with integer entries, and $d$ is a multiple of the (non-zero) determinant of the lattice spanned by the columns of $x$, finds the \emph{upper triangular} \idx{Hermite normal form} of $x$. If the rank of $x$ is equal to its number of rows, the result is a square matrix. In general, the columns of the result form a basis of the lattice spanned by the columns of $x$. Even when $d$ is known, this is in general slower than \kbd{mathnf} but uses much less memory. The library syntax is \fun{GEN}{hnfmod}{GEN x, GEN d}. \subsec{mathnfmodid$(x,d)$}\kbdsidx{mathnfmodid}\label{se:mathnfmodid} Outputs the (upper triangular) \idx{Hermite normal form} of $x$ concatenated with the diagonal matrix with diagonal $d$. Assumes that $x$ has integer entries. Variant: if $d$ is an integer instead of a vector, concatenate $d$ times the identity matrix. \bprog ? m=[0,7;-1,0;-1,-1] %1 = [ 0 7] [-1 0] [-1 -1] ? mathnfmodid(m, [6,2,2]) %2 = [2 1 1] [0 1 0] [0 0 1] ? mathnfmodid(m, 10) %3 = [10 7 3] [ 0 1 0] [ 0 0 1] @eprog The library syntax is \fun{GEN}{hnfmodid}{GEN x, GEN d}. \subsec{mathouseholder$(Q,v)$}\kbdsidx{mathouseholder}\label{se:mathouseholder} \sidx{Householder transform}applies a sequence $Q$ of Householder transforms, as returned by \kbd{matqr}$(M,1)$ to the vector or matrix $v$. The library syntax is \fun{GEN}{mathouseholder}{GEN Q, GEN v}. \subsec{matid$(n)$}\kbdsidx{matid}\label{se:matid} Creates the $n\times n$ identity matrix. The library syntax is \fun{GEN}{matid}{long n}. \subsec{matimage$(x,\{\fl=0\})$}\kbdsidx{matimage}\label{se:matimage} Gives a basis for the image of the matrix $x$ as columns of a matrix. A priori the matrix can have entries of any type. If $\fl=0$, use standard Gauss pivot. If $\fl=1$, use \kbd{matsupplement} (much slower: keep the default flag!). The library syntax is \fun{GEN}{matimage0}{GEN x, long flag}. Also available is \fun{GEN}{image}{GEN x} ($\fl=0$). \subsec{matimagecompl$(x)$}\kbdsidx{matimagecompl}\label{se:matimagecompl} Gives the vector of the column indices which are not extracted by the function \kbd{matimage}, as a permutation (\typ{VECSMALL}). Hence the number of components of \kbd{matimagecompl(x)} plus the number of columns of \kbd{matimage(x)} is equal to the number of columns of the matrix $x$. The library syntax is \fun{GEN}{imagecompl}{GEN x}. \subsec{matindexrank$(x)$}\kbdsidx{matindexrank}\label{se:matindexrank} $x$ being a matrix of rank $r$, returns a vector with two \typ{VECSMALL} components $y$ and $z$ of length $r$ giving a list of rows and columns respectively (starting from 1) such that the extracted matrix obtained from these two vectors using $\tet{vecextract}(x,y,z)$ is invertible. The library syntax is \fun{GEN}{indexrank}{GEN x}. \subsec{matintersect$(x,y)$}\kbdsidx{matintersect}\label{se:matintersect} $x$ and $y$ being two matrices with the same number of rows each of whose columns are independent, finds a basis of the $\Q$-vector space equal to the intersection of the spaces spanned by the columns of $x$ and $y$ respectively. The faster function \tet{idealintersect} can be used to intersect fractional ideals (projective $\Z_K$ modules of rank $1$); the slower but much more general function \tet{nfhnf} can be used to intersect general $\Z_K$-modules. The library syntax is \fun{GEN}{intersect}{GEN x, GEN y}. \subsec{matinverseimage$(x,y)$}\kbdsidx{matinverseimage}\label{se:matinverseimage} Given a matrix $x$ and a column vector or matrix $y$, returns a preimage $z$ of $y$ by $x$ if one exists (i.e such that $x z = y$), an empty vector or matrix otherwise. The complete inverse image is $z + \text{Ker} x$, where a basis of the kernel of $x$ may be obtained by \kbd{matker}. \bprog ? M = [1,2;2,4]; ? matinverseimage(M, [1,2]~) %2 = [1, 0]~ ? matinverseimage(M, [3,4]~) %3 = []~ \\@com no solution ? matinverseimage(M, [1,3,6;2,6,12]) %4 = [1 3 6] [0 0 0] ? matinverseimage(M, [1,2;3,4]) %5 = [;] \\@com no solution ? K = matker(M) %6 = [-2] [1] @eprog The library syntax is \fun{GEN}{inverseimage}{GEN x, GEN y}. \subsec{matisdiagonal$(x)$}\kbdsidx{matisdiagonal}\label{se:matisdiagonal} Returns true (1) if $x$ is a diagonal matrix, false (0) if not. The library syntax is \fun{GEN}{isdiagonal}{GEN x}. \subsec{matker$(x,\{\fl=0\})$}\kbdsidx{matker}\label{se:matker} Gives a basis for the kernel of the matrix $x$ as columns of a matrix. The matrix can have entries of any type, provided they are compatible with the generic arithmetic operations ($+$, $\times$ and $/$). If $x$ is known to have integral entries, set $\fl=1$. The library syntax is \fun{GEN}{matker0}{GEN x, long flag}. Also available are \fun{GEN}{ker}{GEN x} ($\fl=0$), \fun{GEN}{keri}{GEN x} ($\fl=1$). \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. If $\fl=1$, uses $\kbd{matrixqz}(x,-2)$. Many orders of magnitude slower than the default: never use this. 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); @eprog\noindent Remove the outermost \kbd{ZM\_lll} if LLL-reduction is not desired (saves time). \subsec{matmuldiagonal$(x,d)$}\kbdsidx{matmuldiagonal}\label{se:matmuldiagonal} Product of the matrix $x$ by the diagonal matrix whose diagonal entries are those of the vector $d$. Equivalent to, but much faster than $x*\kbd{matdiagonal}(d)$. The library syntax is \fun{GEN}{matmuldiagonal}{GEN x, GEN d}. \subsec{matmultodiagonal$(x,y)$}\kbdsidx{matmultodiagonal}\label{se:matmultodiagonal} Product of the matrices $x$ and $y$ assuming that the result is a diagonal matrix. Much faster than $x*y$ in that case. The result is undefined if $x*y$ is not diagonal. The library syntax is \fun{GEN}{matmultodiagonal}{GEN x, GEN y}. \subsec{matpascal$(n,\{q\})$}\kbdsidx{matpascal}\label{se:matpascal} Creates as a matrix the lower triangular \idx{Pascal triangle} of order $x+1$ (i.e.~with binomial coefficients up to $x$). If $q$ is given, compute the $q$-Pascal triangle (i.e.~using $q$-binomial coefficients). The library syntax is \fun{GEN}{matqpascal}{long n, GEN q = NULL}. Also available is \fun{GEN}{matpascal}{GEN x}. \subsec{matqr$(M,\{\fl=0\})$}\kbdsidx{matqr}\label{se:matqr} Returns $[Q,R]$, the \idx{QR-decomposition} of the square invertible matrix $M$ with real entries: $Q$ is orthogonal and $R$ upper triangular. If $\fl=1$, the orthogonal matrix is returned as a sequence of Householder transforms: applying such a sequence is stabler and faster than multiplication by the corresponding $Q$ matrix.\sidx{Householder transform} More precisely, if \bprog [Q,R] = matqr(M); [q,r] = matqr(M, 1); @eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is $R$; furthermore \bprog mathouseholder(q, matid(#M)) == Q~ @eprog\noindent the inverse of $Q$. This function raises an error if the precision is too low or $x$ is singular. The library syntax is \fun{GEN}{matqr}{GEN M, long flag, long prec}. \subsec{matrank$(x)$}\kbdsidx{matrank}\label{se:matrank} Rank of the matrix $x$. The library syntax is \fun{long}{rank}{GEN x}. \subsec{matrix$(m,n,\{X\},\{Y\},\{\var{expr}=0\})$}\kbdsidx{matrix}\label{se:matrix} Creation of the $m\times n$ matrix whose coefficients are given by the expression \var{expr}. There are two formal parameters in \var{expr}, the first one ($X$) corresponding to the rows, the second ($Y$) to the columns, and $X$ goes from 1 to $m$, $Y$ goes from 1 to $n$. If one of the last 3 parameters is omitted, fill the matrix with zeroes. %\syn{NO} \subsec{matrixqz$(A,\{p=0\})$}\kbdsidx{matrixqz}\label{se:matrixqz} $A$ being an $m\times n$ matrix in $M_{m,n}(\Q)$, let $\text{Im}_\Q A$ (resp.~$\text{Im}_\Z A$) the $\Q$-vector space (resp.~the $\Z$-module) spanned by the columns of $A$. This function has varying behavior depending on the sign of $p$: If $p \geq 0$, $A$ is assumed to have maximal rank $n\leq m$. The function returns a matrix $B\in M_{m,n}(\Z)$, with $\text{Im}_\Q B = \text{Im}_\Q A$, such that the GCD of all its $n\times n$ minors is coprime to $p$; in particular, if $p = 0$ (default), this GCD is $1$. \bprog ? minors(x) = vector(#x[,1], i, matdet(x[^i,])); ? A = [3,1/7; 5,3/7; 7,5/7]; minors(A) %1 = [4/7, 8/7, 4/7] \\ determinants of all 2x2 minors ? B = matrixqz(A) %2 = [3 1] [5 2] [7 3] ? minors(%) %3 = [1, 2, 1] \\ B integral with coprime minors @eprog If $p=-1$, returns the HNF basis of the lattice $\Z^n \cap \text{Im}_\Z A$. If $p=-2$, returns the HNF basis of the lattice $\Z^n \cap \text{Im}_\Q A$. \bprog ? matrixqz(A,-1) %4 = [8 5] [4 3] [0 1] ? matrixqz(A,-2) %5 = [2 -1] [1 0] [0 1] @eprog The library syntax is \fun{GEN}{matrixqz0}{GEN A, GEN p = NULL}. \subsec{matsize$(x)$}\kbdsidx{matsize}\label{se:matsize} $x$ being a vector or matrix, returns a row vector with two components, the first being the number of rows (1 for a row vector), the second the number of columns (1 for a column vector). The library syntax is \fun{GEN}{matsize}{GEN x}. \subsec{matsnf$(X,\{\fl=0\})$}\kbdsidx{matsnf}\label{se:matsnf} If $X$ is a (singular or non-singular) matrix outputs the vector of \idx{elementary divisors} of $X$, i.e.~the diagonal of the \idx{Smith normal form} of $X$, normalized so that $d_n \mid d_{n-1} \mid \ldots \mid d_1$. The binary digits of \fl\ mean: 1 (complete output): if set, outputs $[U,V,D]$, where $U$ and $V$ are two unimodular matrices such that $UXV$ is the diagonal matrix $D$. Otherwise output only the diagonal of $D$. If $X$ is not a square matrix, then $D$ will be a square diagonal matrix padded with zeros on the left or the top. 2 (generic input): if set, allows polynomial entries, in which case the input matrix must be square. Otherwise, assume that $X$ has integer coefficients with arbitrary shape. 4 (cleanup): if set, cleans up the output. This means that elementary divisors equal to $1$ will be deleted, i.e.~outputs a shortened vector $D'$ instead of $D$. If complete output was required, returns $[U',V',D']$ so that $U'XV' = D'$ holds. If this flag is set, $X$ is allowed to be of the form `vector of elementary divisors' or $[U,V,D]$ as would normally be output with the cleanup flag unset. The library syntax is \fun{GEN}{matsnf0}{GEN X, long flag}. \subsec{matsolve$(M,B)$}\kbdsidx{matsolve}\label{se:matsolve} $M$ being an invertible matrix and $B$ a column vector, finds the solution $X$ of $MX=B$, using Dixon $p$-adic lifting method if $M$ and $B$ are integral and Gaussian elimination otherwise. This has the same effect as, but is faster, than $M^{-1}*B$. The library syntax is \fun{GEN}{gauss}{GEN M, GEN B}. For integral input, the function \fun{GEN}{ZM_gauss}{GEN M,GEN B} is also available. \subsec{matsolvemod$(M,D,B,\{\fl=0\})$}\kbdsidx{matsolvemod}\label{se:matsolvemod} $M$ being any integral matrix, $D$ a column vector of non-negative integer moduli, and $B$ an integral column vector, gives a small integer solution to the system of congruences $\sum_i m_{i,j}x_j\equiv b_i\pmod{d_i}$ if one exists, otherwise returns zero. Shorthand notation: $B$ (resp.~$D$) can be given as a single integer, in which case all the $b_i$ (resp.~$d_i$) above are taken to be equal to $B$ (resp.~$D$). \bprog ? M = [1,2;3,4]; ? matsolvemod(M, [3,4]~, [1,2]~) %2 = [-2, 0]~ ? matsolvemod(M, 3, 1) \\ M X = [1,1]~ over F_3 %3 = [-1, 1]~ ? matsolvemod(M, [3,0]~, [1,2]~) \\ x + 2y = 1 (mod 3), 3x + 4y = 2 (in Z) %4 = [6, -4]~ @eprog If $\fl=1$, all solutions are returned in the form of a two-component row vector $[x,u]$, where $x$ is a small integer solution to the system of congruences and $u$ is a matrix whose columns give a basis of the homogeneous system (so that all solutions can be obtained by adding $x$ to any linear combination of columns of $u$). If no solution exists, returns zero. The library syntax is \fun{GEN}{matsolvemod0}{GEN M, GEN D, GEN B, long flag}. Also available are \fun{GEN}{gaussmodulo}{GEN M, GEN D, GEN B} ($\fl=0$) and \fun{GEN}{gaussmodulo2}{GEN M, GEN D, GEN B} ($\fl=1$). \subsec{matsupplement$(x)$}\kbdsidx{matsupplement}\label{se:matsupplement} Assuming that the columns of the matrix $x$ are linearly independent (if they are not, an error message is issued), finds a square invertible matrix whose first columns are the columns of $x$, i.e.~supplement the columns of $x$ to a basis of the whole space. \bprog ? matsupplement([1;2]) %1 = [1 0] [2 1] @eprog Raises an error if $x$ has 0 columns, since (due to a long standing design bug), the dimension of the ambient space (the number of rows) is unknown in this case: \bprog ? matsupplement(matrix(2,0)) *** at top-level: matsupplement(matrix *** ^-------------------- *** matsupplement: sorry, suppl [empty matrix] is not yet implemented. @eprog The library syntax is \fun{GEN}{suppl}{GEN x}. \subsec{mattranspose$(x)$}\kbdsidx{mattranspose}\label{se:mattranspose} Transpose of $x$ (also $x\til$). This has an effect only on vectors and matrices. The library syntax is \fun{GEN}{gtrans}{GEN x}. \subsec{minpoly$(A,\{v='x\})$}\kbdsidx{minpoly}\label{se:minpoly} \idx{minimal polynomial} of $A$ with respect to the variable $v$., i.e. the monic polynomial $P$ of minimal degree (in the variable $v$) such that $P(A) = 0$. The library syntax is \fun{GEN}{minpoly}{GEN A, long v = -1}, where \kbd{v} is a variable number. \subsec{norml2$(x)$}\kbdsidx{norml2}\label{se:norml2} Square of the $L^2$-norm of $x$. More precisely, if $x$ is a scalar, $\kbd{norml2}(x)$ is defined to be the square of the complex modulus of $x$ (real \typ{QUAD}s are not supported). If $x$ is a polynomial, a (row or column) vector or a matrix, \kbd{norml2($x$)} is defined recursively as $\sum_i \kbd{norml2}(x_i)$, where $(x_i)$ run through the components of $x$. In particular, this yields the usual $\sum |x_i|^2$ (resp.~$\sum |x_{i,j}|^2$) if $x$ is a polynomial or vector (resp.~matrix) with complex components. \bprog ? norml2( [ 1, 2, 3 ] ) \\ vector %1 = 14 ? norml2( [ 1, 2; 3, 4] ) \\ matrix %2 = 30 ? norml2( 2*I + x ) %3 = 5 ? norml2( [ [1,2], [3,4], 5, 6 ] ) \\ recursively defined %4 = 91 @eprog The library syntax is \fun{GEN}{gnorml2}{GEN x}. \subsec{normlp$(x,\{p\})$}\kbdsidx{normlp}\label{se:normlp} $L^p$-norm of $x$; sup norm if $p$ is omitted. More precisely, if $x$ is a scalar, \kbd{normlp}$(x, p)$ is defined to be \kbd{abs}$(x)$. If $x$ is a polynomial, a (row or column) vector or a matrix: \item if $p$ is omitted, \kbd{normlp($x$)} is defined recursively as $\max_i \kbd{normlp}(x_i))$, where $(x_i)$ run through the components of~$x$. In particular, this yields the usual sup norm if $x$ is a polynomial or vector with complex components. \item otherwise, \kbd{normlp($x$, $p$)} is defined recursively as $(\sum_i \kbd{normlp}^p(x_i,p))^{1/p}$. In particular, this yields the usual $(\sum |x_i|^p)^{1/p}$ if $x$ is a polynomial or vector with complex components. \bprog ? v = [1,-2,3]; normlp(v) \\ vector %1 = 3 ? M = [1,-2;-3,4]; normlp(M) \\ matrix %2 = 4 ? T = (1+I) + I*x^2; normlp(T) %3 = 1.4142135623730950488016887242096980786 ? normlp([[1,2], [3,4], 5, 6]) \\ recursively defined %4 = 6 ? normlp(v, 1) %5 = 6 ? normlp(M, 1) %6 = 10 ? normlp(T, 1) %7 = 2.4142135623730950488016887242096980786 @eprog The library syntax is \fun{GEN}{gnormlp}{GEN x, GEN p = NULL, long prec}. \subsec{qfauto$(G,\{\var{fl}\})$}\kbdsidx{qfauto}\label{se:qfauto} $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the automorphism group of the associate lattice. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. $G$ can also be given by an \kbd{qfisominit} structure. See \kbd{qfisominit} for the meaning of \var{fl}. The output is a two-components vector $[o,g]$ where $o$ is the group order and $g$ is the list of generators (as a vector). For each generator $H$, the equality $G={^t}H\*G\*H$ holds. The interface of this function is experimental and will likely change in the future. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. The library syntax is \fun{GEN}{qfauto0}{GEN G, GEN fl = NULL}. Also available is \fun{GEN}{qfauto}{GEN G, GEN fl} where $G$ is a vector of \kbd{zm}. \subsec{qfautoexport$(\var{qfa},\{\fl\})$}\kbdsidx{qfautoexport}\label{se:qfautoexport} \var{qfa} being an automorphism group as output by \tet{qfauto}, export the underlying matrix group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example computes the size of the matrix group using GAP: \bprog ? G = qfauto([2,1;1,2]) %1 = [12, [[-1, 0; 0, -1], [0, -1; 1, 1], [1, 1; 0, -1]]] ? s = qfautoexport(G) %2 = "Group([[-1, 0], [0, -1]], [[0, -1], [1, 1]], [[1, 1], [0, -1]])" ? extern("echo \"Order("s");\" | gap -q") %3 = 12 @eprog The library syntax is \fun{GEN}{qfautoexport}{GEN qfa, long flag}. \subsec{qfbil$(x,y,\{q\})$}\kbdsidx{qfbil}\label{se:qfbil} Evaluate the bilinear form $q$ (symmetric matrix) at the vectors $(x,y)$; if $q$ omitted, use the standard Euclidean scalar product, corresponding to the identity matrix. Roughly equivalent to \kbd{x\til * q * y}, but a little faster and more convenient (does not distinguish between column and row vectors): \bprog ? x = [1,2,3]~; y = [-1,0,1]~; qfbil(x,y) %1 = 2 ? q = [1,2,3;2,2,-1;3,-1,0]; qfbil(x,y, q) %2 = -13 ? for(i=1,10^6, qfbil(x,y,q)) %3 = 568ms ? for(i=1,10^6, x~*q*y) %4 = 717ms @eprog\noindent The associated quadratic form is also available, as \tet{qfnorm}, slightly faster: \bprog ? for(i=1,10^6, qfnorm(x,q)) time = 444ms ? for(i=1,10^6, qfnorm(x)) time = 176 ms. ? for(i=1,10^6, qfbil(x,y)) time = 208 ms. @eprog The library syntax is \fun{GEN}{qfbil}{GEN x, GEN y, GEN q = NULL}. \subsec{qfgaussred$(q)$}\kbdsidx{qfgaussred}\label{se:qfgaussred} \idx{decomposition into squares} of the quadratic form represented by the symmetric matrix $q$. The result is a matrix whose diagonal entries are the coefficients of the squares, and the off-diagonal entries on each line represent the bilinear forms. More precisely, if $(a_{ij})$ denotes the output, one has $$ q(x) = \sum_i a_{ii} (x_i + \sum_{j \neq i} a_{ij} x_j)^2 $$ \bprog ? qfgaussred([0,1;1,0]) %1 = [1/2 1] [-1 -1/2] @eprog\noindent This means that $2xy = (1/2)(x+y)^2 - (1/2)(x-y)^2$. The library syntax is \fun{GEN}{qfgaussred}{GEN q}. \fun{GEN}{qfgaussred_positive}{GEN q} assumes that $q$ is positive definite and is a little faster; returns \kbd{NULL} if a vector with negative norm occurs (non positive matrix or too many rounding errors). \subsec{qfisom$(G,H,\{\var{fl}\})$}\kbdsidx{qfisom}\label{se:qfisom} $G$, $H$ being square and symmetric matrices with integer entries representing positive definite quadratic forms, return an invertible matrix $S$ such that $G={^t}S\*H\*S$. This defines a isomorphism between the corresponding lattices. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. See \kbd{qfisominit} for the meaning of \var{fl}. $G$ can also be given by an \kbd{qfisominit} structure which is preferable if several forms $H$ need to be compared to $G$. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. The library syntax is \fun{GEN}{qfisom0}{GEN G, GEN H, GEN fl = NULL}. Also available is \fun{GEN}{qfisom}{GEN G, GEN H, GEN fl} where $G$ is a vector of \kbd{zm}, and $H$ is a \kbd{zm}. \subsec{qfisominit$(G,\{\var{fl}\})$}\kbdsidx{qfisominit}\label{se:qfisominit} $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, return an \kbd{isom} structure allowing to compute isomorphisms between $G$ and other quadratic forms faster. The interface of this function is experimental and will likely change in future release. If present, the optional parameter \var{fl} must be a \typ{VEC} with two components. It allows to specify the invariants used, which can make the computation faster or slower. The components are \item \kbd{fl[1]} Depth of scalar product combination to use. \item \kbd{fl[2]} Maximum level of Bacher polynomials to use. Since this function computes the minimal vectors, it can become very lengthy as the dimension of $G$ grows. The library syntax is \fun{GEN}{qfisominit0}{GEN G, GEN fl = NULL}. Also available is \fun{GEN}{qfisominit}{GEN F, GEN fl} where $F$ is a vector of \kbd{zm}. \subsec{qfjacobi$(A)$}\kbdsidx{qfjacobi}\label{se:qfjacobi} Apply Jacobi's eigenvalue algorithm to the real symmetric matrix $A$. This returns $[L, V]$, where \item $L$ is the vector of (real) eigenvalues of $A$, sorted in increasing order, \item $V$ is the corresponding orthogonal matrix of eigenvectors of $A$. \bprog ? \p19 ? A = [1,2;2,1]; mateigen(A) %1 = [-1 1] [ 1 1] ? [L, H] = qfjacobi(A); ? L %3 = [-1.000000000000000000, 3.000000000000000000]~ ? H %4 = [ 0.7071067811865475245 0.7071067811865475244] [-0.7071067811865475244 0.7071067811865475245] ? norml2( (A-L[1])*H[,1] ) \\ approximate eigenvector %5 = 9.403954806578300064 E-38 ? norml2(H*H~ - 1) %6 = 2.350988701644575016 E-38 \\ close to orthogonal @eprog The library syntax is \fun{GEN}{jacobi}{GEN A, long prec}. \subsec{qflll$(x,\{\fl=0\})$}\kbdsidx{qflll}\label{se:qflll} \idx{LLL} algorithm applied to the \emph{columns} of the matrix $x$. The columns of $x$ may be linearly dependent. The result is a unimodular transformation matrix $T$ such that $x \cdot T$ is an LLL-reduced basis of the lattice generated by the column vectors of $x$. Note that if $x$ is not of maximal rank $T$ will not be square. The LLL parameters are $(0.51,0.99)$, meaning that the Gram-Schmidt coefficients for the final basis satisfy $\mu_{i,j} \leq |0.51|$, and the Lov\'{a}sz's constant is $0.99$. If $\fl=0$ (default), assume that $x$ has either exact (integral or rational) or real floating point entries. The matrix is rescaled, converted to integers and the behavior is then as in $\fl = 1$. If $\fl=1$, assume that $x$ is integral. Computations involving Gram-Schmidt vectors are approximate, with precision varying as needed (Lehmer's trick, as generalized by Schnorr). Adapted from Nguyen and Stehl\'e's algorithm and Stehl\'e's code (\kbd{fplll-1.3}). If $\fl=2$, $x$ should be an integer matrix whose columns are linearly independent. Returns a partially reduced basis for $x$, using an unpublished algorithm by Peter Montgomery: a basis is said to be \emph{partially reduced} if $|v_i \pm v_j| \geq |v_i|$ for any two distinct basis vectors $v_i, \, v_j$. This is faster than $\fl=1$, esp. when one row is huge compared to the other rows (knapsack-style), and should quickly produce relatively short vectors. The resulting basis is \emph{not} LLL-reduced in general. If LLL reduction is eventually desired, avoid this partial reduction: applying LLL to the partially reduced matrix is significantly \emph{slower} than starting from a knapsack-type lattice. If $\fl=4$, as $\fl=1$, returning a vector $[K, T]$ of matrices: the columns of $K$ represent a basis of the integer kernel of $x$ (not LLL-reduced in general) and $T$ is the transformation matrix such that $x\cdot T$ is an LLL-reduced $\Z$-basis of the image of the matrix $x$. If $\fl=5$, case as case $4$, but $x$ may have polynomial coefficients. If $\fl=8$, same as case $0$, but $x$ may have polynomial coefficients. The library syntax is \fun{GEN}{qflll0}{GEN x, long flag}. Also available are \fun{GEN}{lll}{GEN x} ($\fl=0$), \fun{GEN}{lllint}{GEN x} ($\fl=1$), and \fun{GEN}{lllkerim}{GEN x} ($\fl=4$). \subsec{qflllgram$(G,\{\fl=0\})$}\kbdsidx{qflllgram}\label{se:qflllgram} Same as \kbd{qflll}, except that the matrix $G = \kbd{x\til * x}$ is the Gram matrix of some lattice vectors $x$, and not the coordinates of the vectors themselves. In particular, $G$ must now be a square symmetric real matrix, corresponding to a positive quadratic form (not necessarily definite: $x$ needs not have maximal rank). The result is a unimodular transformation matrix $T$ such that $x \cdot T$ is an LLL-reduced basis of the lattice generated by the column vectors of $x$. See \tet{qflll} for further details about the LLL implementation. If $\fl=0$ (default), assume that $G$ has either exact (integral or rational) or real floating point entries. The matrix is rescaled, converted to integers and the behavior is then as in $\fl = 1$. If $\fl=1$, assume that $G$ is integral. Computations involving Gram-Schmidt vectors are approximate, with precision varying as needed (Lehmer's trick, as generalized by Schnorr). Adapted from Nguyen and Stehl\'e's algorithm and Stehl\'e's code (\kbd{fplll-1.3}). $\fl=4$: $G$ has integer entries, gives the kernel and reduced image of $x$. $\fl=5$: same as $4$, but $G$ may have polynomial coefficients. The library syntax is \fun{GEN}{qflllgram0}{GEN G, long flag}. Also available are \fun{GEN}{lllgram}{GEN G} ($\fl=0$), \fun{GEN}{lllgramint}{GEN G} ($\fl=1$), and \fun{GEN}{lllgramkerim}{GEN G} ($\fl=4$). \subsec{qfminim$(x,\{b\},\{m\},\{\fl=0\})$}\kbdsidx{qfminim}\label{se:qfminim} $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 behavior is undefined if $x$ is not positive definite (a ``precision too low'' error is most likely, although more precise error messages are possible). The precise behavior depends on $\fl$. If $\fl=0$ (default), seeks at most $2m$ vectors. The result is a three-component vector, the first component being the number of vectors found, the second being the maximum norm found, and the last vector is a matrix whose columns are the vectors found, only one being given for each pair $\pm v$ (at most $m$ such pairs, unless $m$ was omitted). The vectors are returned in no particular order. If $\fl=1$, ignores $m$ and returns $[N,v]$, where $v$ is a non-zero vector of length $N \leq b$, or $[]$ if no non-zero vector has length $\leq b$. If no explicit $b$ is provided, return a vector of smallish norm (smallest vector in an LLL-reduced basis). In these two cases, $x$ must have \emph{integral} entries. The implementation uses low precision floating point computations for maximal speed, which gives incorrect result when $x$ has large entries. (The condition is checked in the code and the routine raises an error if large rounding errors occur.) A more robust, but much slower, implementation is chosen if the following flag is used: If $\fl=2$, $x$ can have non integral real entries. In this case, if $b$ is omitted, the ``minimal'' vectors only have approximately the same norm. If $b$ is omitted, $m$ is an upper bound for the number of vectors that will be stored and returned, but all minimal vectors are nevertheless enumerated. If $m$ is omitted, all vectors found are stored and returned; note that this may be a huge vector! \bprog ? x = matid(2); ? qfminim(x) \\@com 4 minimal vectors of norm 1: $\pm[0,1]$, $\pm[1,0]$ %2 = [4, 1, [0, 1; 1, 0]] ? { x = [4, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1, 0,-1, 0, 0, 0,-2; 2, 4,-2,-2, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1, 0, 1,-1,-1; 0,-2, 4, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 0, 1,-1,-1, 0, 0; 0,-2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1,-1, 0, 1,-1, 1, 0; 0, 0,-2, 0, 4, 0, 0, 0, 1,-1, 0, 0, 1, 0, 0, 0,-2, 0, 0,-1, 1, 1, 0, 0; -2, -2,0, 0, 0, 4,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,-1, 1, 1; 0, 0, 0, 0, 0,-2, 4,-2, 0, 0, 0, 0, 0, 1, 0, 0, 0,-1, 0, 0, 0, 1,-1, 0; 0, 0, 0, 0, 0, 0,-2, 4, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1,-1,-1, 0, 1, 0; 0, 0, 0, 0, 1,-1, 0, 0, 4, 0,-2, 0, 1, 1, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 0, 0, 1, 1,-1, 1, 0, 0, 0, 1, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 4,-2, 0,-1, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 4,-1, 1, 0, 0,-1, 1, 0, 1, 1, 1,-1, 0; 1, 0,-1, 1, 1, 0, 0,-1, 1, 1, 0,-1, 4, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,-1; -1,-1, 1,-1, 0, 0, 1, 0, 1, 1,-1, 1, 0, 4, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 1, 1, 0, 0; 0, 0, 1, 0,-2, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 1, 1, 1, 0, 0, 1, 1; 1, 0, 0, 1, 0, 0,-1, 0, 1, 0,-1, 1, 1, 0, 0, 0, 1, 4, 0, 1, 1, 0, 1, 0; 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 4, 0, 1, 1, 0, 1; -1, -1,1, 0,-1, 1, 0,-1, 0, 1,-1, 1, 0, 1, 0, 0, 1, 1, 0, 4, 0, 0, 1, 1; 0, 0,-1, 1, 1, 0, 0,-1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 4, 1, 0, 1; 0, 1,-1,-1, 1,-1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 4, 0, 1; 0,-1, 0, 1, 0, 1,-1, 1, 0, 1, 0,-1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 4, 1; -2,-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 4]; } ? qfminim(x,,0) \\ the Leech lattice has 196560 minimal vectors of norm 4 time = 648 ms. %4 = [196560, 4, [;]] ? qfminim(x,,0,2); \\ safe algorithm. Slower and unnecessary here. time = 18,161 ms. %5 = [196560, 4.000061035156250000, [;]] @eprog\noindent\sidx{Leech lattice}\sidx{minimal vector} In the last example, we store 0 vectors to limit memory use. All minimal vectors are nevertheless enumerated. Provided \kbd{parisize} is about 50MB, \kbd{qfminim(x)} succeeds in 2.5 seconds. The library syntax is \fun{GEN}{qfminim0}{GEN x, GEN b = NULL, GEN m = NULL, long flag, long prec}. Also available are \fun{GEN}{minim}{GEN x, GEN b = NULL, GEN m = NULL} ($\fl=0$), \fun{GEN}{minim2}{GEN x, GEN b = NULL, GEN m = NULL} ($\fl=1$). \fun{GEN}{minim_raw}{GEN x, GEN b = NULL, GEN m = NULL} (do not perform LLL reduction on x). \subsec{qfnorm$(x,\{q\})$}\kbdsidx{qfnorm}\label{se:qfnorm} Evaluate the binary quadratic form $q$ (symmetric matrix) at the vector $x$. If $q$ omitted, use the standard Euclidean form, corresponding to the identity matrix. Equivalent to \kbd{x\til * q * x}, but about twice faster and more convenient (does not distinguish between column and row vectors): \bprog ? x = [1,2,3]~; qfnorm(x) %1 = 14 ? q = [1,2,3;2,2,-1;3,-1,0]; qfnorm(x, q) %2 = 23 ? for(i=1,10^6, qfnorm(x,q)) time = 384ms. ? for(i=1,10^6, x~*q*x) time = 729ms. @eprog\noindent We also allow \typ{MAT}s of compatible dimensions for $x$, and return \kbd{x\til * q * x} in this case as well: \bprog ? M = [1,2,3;4,5,6;7,8,9]; qfnorm(M) \\ Gram matrix %5 = [66 78 90] [78 93 108] [90 108 126] ? for(i=1,10^6, qfnorm(M,q)) time = 2,144 ms. ? for(i=1,10^6, M~*q*M) time = 2,793 ms. @eprog \noindent The polar form is also available, as \tet{qfbil}. The library syntax is \fun{GEN}{qfnorm}{GEN x, GEN q = NULL}. \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 perfection rank of the form. That is, gives the rank of the family of the $s$ symmetric matrices $v_iv_i^t$, where $s$ is half the number of minimal vectors and the $v_i$ ($1\le i\le s$) are the minimal vectors. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension of $x$ grows. The library syntax is \fun{GEN}{perf}{GEN G}. \subsec{qfrep$(q,B,\{\fl=0\})$}\kbdsidx{qfrep}\label{se:qfrep} $q$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, count the vectors representing successive integers. \item If $\fl = 0$, count all vectors. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors $v$ such that $q(v)=i$. \item If $\fl = 1$, count vectors of even norm. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors such that $q(v) = 2i$. \bprog ? q = [2, 1; 1, 3]; ? qfrep(q, 5) %2 = Vecsmall([0, 1, 2, 0, 0]) \\ 1 vector of norm 2, 2 of norm 3, etc. ? qfrep(q, 5, 1) %3 = Vecsmall([1, 0, 0, 1, 0]) \\ 1 vector of norm 2, 0 of norm 4, etc. @eprog\noindent This routine uses a naive algorithm based on \tet{qfminim}, and will fail if any entry becomes larger than $2^{31}$ (or $2^{63}$). The library syntax is \fun{GEN}{qfrep0}{GEN q, GEN B, long flag}. \subsec{qfsign$(x)$}\kbdsidx{qfsign}\label{se:qfsign} Returns $[p,m]$ the signature of the quadratic form represented by the symmetric matrix $x$. Namely, $p$ (resp.~$m$) is the number of positive (resp.~negative) eigenvalues of $x$.The result is computed using Gaussian reduction. The library syntax is \fun{GEN}{qfsign}{GEN x}. \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 $\leq r$. In case no relation is found, return $0$. \bprog ? s = 1 + 10*y - 46*y^2 + 460*y^3 - 5658*y^4 + 77740*y^5 + O(y^6); ? seralgdep(s, 2, 2) %2 = -x^2 + (8*y^2 + 20*y + 1) ? subst(%, x, s) %3 = O(y^6) ? seralgdep(s, 1, 3) %4 = (-77*y^2 - 20*y - 1)*x + (310*y^3 + 231*y^2 + 30*y + 1) ? seralgdep(s, 1, 2) %5 = 0 @eprog\noindent The series main variable must not be $x$, so as to be able to express the result as a polynomial in $x$. The library syntax is \fun{GEN}{seralgdep}{GEN s, long p, long r}. \subsec{setbinop$(f,X,\{Y\})$}\kbdsidx{setbinop}\label{se:setbinop} The set whose elements are the f(x,y), where x,y run through X,Y. respectively. If $Y$ is omitted, assume that $X = Y$ and that $f$ is symmetric: $f(x,y) = f(y,x)$ for all $x,y$ in $X$. \bprog ? X = [1,2,3]; Y = [2,3,4]; ? setbinop((x,y)->x+y, X,Y) \\ set X + Y %2 = [3, 4, 5, 6, 7] ? setbinop((x,y)->x-y, X,Y) \\ set X - Y %3 = [-3, -2, -1, 0, 1] ? setbinop((x,y)->x+y, X) \\ set 2X = X + X %2 = [2, 3, 4, 5, 6] @eprog The library syntax is \fun{GEN}{setbinop}{GEN f, GEN X, GEN Y = NULL}. \subsec{setintersect$(x,y)$}\kbdsidx{setintersect}\label{se:setintersect} Intersection of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. The library syntax is \fun{GEN}{setintersect}{GEN x, GEN y}. \subsec{setisset$(x)$}\kbdsidx{setisset}\label{se:setisset} Returns true (1) if $x$ is a set, false (0) if not. In PARI, a set is a row vector whose entries are strictly increasing with respect to a (somewhat arbitrary) universal comparison function. To convert any object into a set (this is most useful for vectors, of course), use the function \kbd{Set}. \bprog ? a = [3, 1, 1, 2]; ? setisset(a) %2 = 0 ? Set(a) %3 = [1, 2, 3] @eprog The library syntax is \fun{long}{setisset}{GEN x}. \subsec{setminus$(x,y)$}\kbdsidx{setminus}\label{se:setminus} Difference of the two sets $x$ and $y$ (see \kbd{setisset}), i.e.~set of elements of $x$ which do not belong to $y$. If $x$ or $y$ is not a set, the result is undefined. The library syntax is \fun{GEN}{setminus}{GEN x, GEN y}. \subsec{setsearch$(S,x,\{\fl=0\})$}\kbdsidx{setsearch}\label{se:setsearch} Determines whether $x$ belongs to the set $S$ (see \kbd{setisset}). We first describe the default behaviour, when $\fl$ is zero or omitted. If $x$ belongs to the set $S$, returns the index $j$ such that $S[j]=x$, otherwise returns 0. \bprog ? T = [7,2,3,5]; S = Set(T); ? setsearch(S, 2) %2 = 1 ? setsearch(S, 4) \\ not found %3 = 0 ? setsearch(T, 7) \\ search in a randomly sorted vector %4 = 0 \\ WRONG ! @eprog\noindent If $S$ is not a set, we also allow sorted lists with respect to the \tet{cmp} sorting function, without repeated entries, as per \tet{listsort}$(L,1)$; otherwise the result is undefined. \bprog ? L = List([1,4,2,3,2]); setsearch(L, 4) %1 = 0 \\ WRONG ! ? listsort(L, 1); L \\ sort L first %2 = List([1, 2, 3, 4]) ? setsearch(L, 4) %3 = 4 \\ now correct @eprog\noindent If $\fl$ is non-zero, this function returns the index $j$ where $x$ should be inserted, and $0$ if it already belongs to $S$. This is meant to be used for dynamically growing (sorted) lists, in conjunction with \kbd{listinsert}. \bprog ? L = List([1,5,2,3,2]); listsort(L,1); L %1 = List([1,2,3,5]) ? j = setsearch(L, 4, 1) \\ 4 should have been inserted at index j %2 = 4 ? listinsert(L, 4, j); L %3 = List([1, 2, 3, 4, 5]) @eprog The library syntax is \fun{long}{setsearch}{GEN S, GEN x, long flag}. \subsec{setunion$(x,y)$}\kbdsidx{setunion}\label{se:setunion} Union of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. The library syntax is \fun{GEN}{setunion}{GEN x, GEN y}. \subsec{trace$(x)$}\kbdsidx{trace}\label{se:trace} This applies to quite general $x$. If $x$ is not a matrix, it is equal to the sum of $x$ and its conjugate, except for polmods where it is the trace as an algebraic number. For $x$ a square matrix, it is the ordinary trace. If $x$ is a non-square matrix (but not a vector), an error occurs. The library syntax is \fun{GEN}{gtrace}{GEN x}. \subsec{vecextract$(x,y,\{z\})$}\kbdsidx{vecextract}\label{se:vecextract} Extraction of components of the vector or matrix $x$ according to $y$. In case $x$ is a matrix, its components are the \emph{columns} of $x$. The parameter $y$ is a component specifier, which is either an integer, a string describing a range, or a vector. If $y$ is an integer, it is considered as a mask: the binary bits of $y$ are read from right to left, but correspond to taking the components from left to right. For example, if $y=13=(1101)_2$ then the components 1,3 and 4 are extracted. If $y$ is a vector (\typ{VEC}, \typ{COL} or \typ{VECSMALL}), which must have integer entries, these entries correspond to the component numbers to be extracted, in the order specified. If $y$ is a string, it can be \item a single (non-zero) index giving a component number (a negative index means we start counting from the end). \item a range of the form \kbd{"$a$..$b$"}, where $a$ and $b$ are indexes as above. Any of $a$ and $b$ can be omitted; in this case, we take as default values $a = 1$ and $b = -1$, i.e.~ the first and last components respectively. We then extract all components in the interval $[a,b]$, in reverse order if $b < a$. In addition, if the first character in the string is \kbd{\pow}, the complement of the given set of indices is taken. If $z$ is not omitted, $x$ must be a matrix. $y$ is then the \emph{row} specifier, and $z$ the \emph{column} specifier, where the component specifier is as explained above. \bprog ? v = [a, b, c, d, e]; ? vecextract(v, 5) \\@com mask %1 = [a, c] ? vecextract(v, [4, 2, 1]) \\@com component list %2 = [d, b, a] ? vecextract(v, "2..4") \\@com interval %3 = [b, c, d] ? vecextract(v, "-1..-3") \\@com interval + reverse order %4 = [e, d, c] ? vecextract(v, "^2") \\@com complement %5 = [a, c, d, e] ? vecextract(matid(3), "2..", "..") %6 = [0 1 0] [0 0 1] @eprog The range notations \kbd{v[i..j]} and \kbd{v[\pow i]} (for \typ{VEC} or \typ{COL}) and \kbd{M[i..j, k..l]} and friends (for \typ{MAT}) implement a subset of the above, in a simpler and \emph{faster} way, hence should be preferred in most common situations. The following features are not implemented in the range notation: \item reverse order, \item omitting either $a$ or $b$ in \kbd{$a$..$b$}. The library syntax is \fun{GEN}{extract0}{GEN x, GEN y, GEN z = NULL}. \subsec{vecsearch$(v,x,\{\var{cmpf}\})$}\kbdsidx{vecsearch}\label{se:vecsearch} Determines whether $x$ belongs to the sorted vector or list $v$: return 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). 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 encode comparison functions. \bprog ? v = [1,3,4,5,7]; ? vecsearch(v, 3) %2 = 2 ? vecsearch(v, 6) %3 = 0 \\ not in the list ? vecsearch([7,6,5], 5) \\ unsorted vector: result undefined %4 = 0 @eprog By abuse of notation, $x$ is also allowed to be a matrix, seen as a vector of its columns; again by abuse of notation, a \typ{VEC} is considered as part of the matrix, if its transpose is one of the matrix columns. \bprog ? v = vecsort([3,0,2; 1,0,2]) \\ sort matrix columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsearch(v, [3,1]~) %2 = 3 ? vecsearch(v, [3,1]) \\ can search for x or x~ %3 = 3 ? vecsearch(v, [1,2]) %4 = 0 \\ not in the list @eprog\noindent The library syntax is \fun{long}{vecsearch}{GEN v, GEN x, GEN cmpf = NULL}. \subsec{vecsort$(x,\{\var{cmpf}\},\{\fl=0\})$}\kbdsidx{vecsort}\label{se:vecsort} Sorts the vector $x$ in ascending order, using a mergesort method. $x$ must be a list, vector or matrix (seen as a vector of its columns). Note that mergesort is stable, hence the initial ordering of ``equal'' entries (with respect to the sorting criterion) is not changed. If \kbd{cmpf} is omitted, we use the standard comparison function \kbd{lex}, thereby restricting the possible types for the elements of $x$ (integers, fractions or reals and vectors of those). If \kbd{cmpf} is present, it is understood as a comparison function and we sort according to it. The following possibilities exist: \item an integer $k$: sort according to the value of the $k$-th subcomponents of the components of~$x$. \item a vector: sort lexicographically according to the components listed in the vector. For example, if $\kbd{cmpf}=\kbd{[2,1,3]}$, sort with respect to the second component, and when these are equal, with respect to the first, and when these are equal, with respect to the third. \item a comparison function (\typ{CLOSURE}), with two arguments $x$ and $y$, and returning an integer which is $<0$, $>0$ or $=0$ if $xy$ or $x=y$ respectively. The \tet{sign} function is very useful in this context: \bprog ? vecsort([3,0,2; 1,0,2]) \\ sort columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsort(v, (x,y)->sign(y-x)) \\@com reverse sort ? vecsort(v, (x,y)->sign(abs(x)-abs(y))) \\@com sort by increasing absolute value ? cmpf(x,y) = my(dx = poldisc(x), dy = poldisc(y)); sign(abs(dx) - abs(dy)) ? vecsort([x^2+1, x^3-2, x^4+5*x+1], cmpf) @eprog\noindent The last example used the named \kbd{cmpf} instead of an anonymous function, and sorts polynomials with respect to the absolute value of their discriminant. A more efficient approach would use precomputations to ensure a given discriminant is computed only once: \bprog ? DISC = vector(#v, i, abs(poldisc(v[i]))); ? perm = vecsort(vector(#v,i,i), (x,y)->sign(DISC[x]-DISC[y])) ? vecextract(v, perm) @eprog\noindent Similar ideas apply whenever we sort according to the values of a function which is expensive to compute. \noindent The binary digits of \fl\ mean: \item 1: indirect sorting of the vector $x$, i.e.~if $x$ is an $n$-component vector, returns a permutation of $[1,2,\dots,n]$ which applied to the components of $x$ sorts $x$ in increasing order. For example, \kbd{vecextract(x, vecsort(x,,1))} is equivalent to \kbd{vecsort(x)}. \item 4: use descending instead of ascending order. \item 8: remove ``duplicate'' entries with respect to the sorting function (keep the first occurring entry). For example: \bprog ? vecsort([Pi,Mod(1,2),z], (x,y)->0, 8) \\@com make everything compare equal %1 = [3.141592653589793238462643383] ? vecsort([[2,3],[0,1],[0,3]], 2, 8) %2 = [[0, 1], [2, 3]] @eprog 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$ The library syntax is \fun{GEN}{vecsum}{GEN v}. \subsec{vector$(n,\{X\},\{\var{expr}=0\})$}\kbdsidx{vector}\label{se:vector} Creates a row vector (type \typ{VEC}) with $n$ components whose components are the expression \var{expr} evaluated at the integer points between 1 and $n$. If one of the last two arguments is omitted, fill the vector with zeroes. \bprog ? vector(3,i, 5*i) %1 = [5, 10, 15] ? vector(3) %2 = [0, 0, 0] @eprog The variable $X$ is lexically scoped to each evaluation of \var{expr}. Any change to $X$ within \var{expr} does not affect subsequent evaluations, it still runs 1 to $n$. A local change allows for example different indexing: \bprog vector(10, i, i=i-1; f(i)) \\ i = 0, ..., 9 vector(10, i, i=2*i; f(i)) \\ i = 2, 4, ..., 20 @eprog\noindent This per-element scope for $X$ differs from \kbd{for} loop evaluations, as the following example shows: \bprog n = 3 v = vector(n); vector(n, i, i++) ----> [2, 3, 4] v = vector(n); for (i = 1, n, v[i] = i++) ----> [2, 0, 4] @eprog\noindent %\syn{NO} \subsec{vectorsmall$(n,\{X\},\{\var{expr}=0\})$}\kbdsidx{vectorsmall}\label{se:vectorsmall} Creates a row vector of small integers (type \typ{VECSMALL}) with $n$ components whose components are the expression \var{expr} evaluated at the integer points between 1 and $n$. If one of the last two arguments is omitted, fill the vector with zeroes. %\syn{NO} \subsec{vectorv$(n,\{X\},\{\var{expr}=0\})$}\kbdsidx{vectorv}\label{se:vectorv} As \tet{vector}, but returns a column vector (type \typ{COL}). %\syn{NO} %SECTION: linear_algebra \section{Sums, products, integrals and similar functions} \label{se:sums} Although the \kbd{gp} calculator is programmable, it is useful to have a number of preprogrammed loops, including sums, products, and a certain number of recursions. Also, a number of functions from numerical analysis like numerical integration and summation of series will be described here. One of the parameters in these loops must be the control variable, hence a simple variable name. In the descriptions, the letter $X$ will always denote any simple variable name, and represents the formal parameter used in the function. The expression to be summed, integrated, etc. is any legal PARI expression, including of course expressions using loops. \misctitle{Library mode} Since it is easier to program directly the loops in library mode, these functions are mainly useful for GP programming. On the other hand, numerical routines code a function (to be integrated, summed, etc.) with two parameters named \bprog GEN (*eval)(void*,GEN) void *E; \\ context: eval(E, x) must evaluate your function at x. @eprog\noindent see the Libpari manual for details. \misctitle{Numerical integration}\sidx{numerical integration} Starting with version 2.2.9 the ``double exponential'' univariate integration method is implemented in \tet{intnum} and its variants. Romberg integration is still available under the name \kbd{intnumromb}, but superseded. It is possible to compute numerically integrals to thousands of decimal places in reasonable time, as long as the integrand is regular. It is also reasonable to compute numerically integrals in several variables, although more than two becomes lengthy. The integration domain may be non-compact, and the integrand may have reasonable singularities at endpoints. To use \kbd{intnum}, you must split the integral into a sum of subintegrals where the function has no singularities except at the endpoints. Polynomials in logarithms are not considered singular, and neglecting these logs, singularities are assumed to be algebraic (asymptotic to $C(x-a)^{-\alpha}$ for some $\alpha > -1$ when $x$ is close to $a$), or to correspond to simple discontinuities of some (higher) derivative of the function. For instance, the point $0$ is a singularity of $\text{abs}(x)$. See also the discrete summation methods below, sharing the prefix \kbd{sum}. \subsec{derivnum$(X=a,\var{expr})$}\kbdsidx{derivnum}\label{se:derivnum} Numerical derivation of \var{expr} with respect to $X$ at $X=a$. \bprog ? derivnum(x=0,sin(exp(x))) - cos(1) %1 = -1.262177448 E-29 @eprog A clumsier approach, which would not work in library mode, is \bprog ? f(x) = sin(exp(x)) ? f'(0) - cos(1) %1 = -1.262177448 E-29 @eprog When $a$ is a power series, compute \kbd{derivnum(t=a,f)} as $f'(a) = (f(a))'/a'$. \synt{derivnum}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec}. Also available is \fun{GEN}{derivfun}{void *E, GEN (*eval)(void *, GEN), GEN a, long prec}, which also allows power series for $a$. \subsec{intcirc$(X=a,R,\var{expr},\{\var{tab}\})$}\kbdsidx{intcirc}\label{se:intcirc} Numerical integration of $(2i\pi)^{-1}\var{expr}$ with respect to $X$ on the circle $|X-a| = R$. In other words, when \var{expr} is a meromorphic function, sum of the residues in the corresponding disk. \var{tab} is as in \kbd{intnum}, except that if computed with \kbd{intnuminit} it should be with the endpoints \kbd{[-1, 1]}. \bprog ? \p105 ? intcirc(s=1, 0.5, zeta(s)) - 1 %1 = -2.398082982 E-104 - 7.94487211 E-107*I @eprog \synt{intcirc}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN R,GEN tab, long prec}. \subsec{intfouriercos$(X=a,b,z,\var{expr},\{\var{tab}\})$}\kbdsidx{intfouriercos}\label{se:intfouriercos} Numerical integration of $\var{expr}(X)\cos(2\pi zX)$ from $a$ to $b$, in other words Fourier cosine transform (from $a$ to $b$) of the function represented by \var{expr}. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity, but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfouriercos}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. \subsec{intfourierexp$(X=a,b,z,\var{expr},\{\var{tab}\})$}\kbdsidx{intfourierexp}\label{se:intfourierexp} Numerical integration of $\var{expr}(X)\exp(-2i\pi zX)$ from $a$ to $b$, in other words Fourier transform (from $a$ to $b$) of the function represented by \var{expr}. Note the minus sign. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfourierexp}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. \subsec{intfouriersin$(X=a,b,z,\var{expr},\{\var{tab}\})$}\kbdsidx{intfouriersin}\label{se:intfouriersin} Numerical integration of $\var{expr}(X)\sin(2\pi zX)$ from $a$ to $b$, in other words Fourier sine transform (from $a$ to $b$) of the function represented by \var{expr}. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfouriersin}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. \subsec{intfuncinit$(X=a,b,\var{expr},\{\fl=0\},\{m=0\})$}\kbdsidx{intfuncinit}\label{se:intfuncinit} Initialize tables for use with integral transforms such as \kbd{intmellininv}, etc., where $a$ and $b$ are coded as in \kbd{intnum}, $\var{expr}$ is the function $s(X)$ to which the integral transform is to be applied (which will multiply the weights of integration) and $m$ is as in \kbd{intnuminit}. If $\fl$ is nonzero, assumes that $s(-X)=\overline{s(X)}$, which makes the computation twice as fast. See \kbd{intmellininvshort} for examples of the use of this function, which is particularly useful when the function $s(X)$ is lengthy to compute, such as a gamma product. \synt{intfuncinit}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,long m, long flag, long prec}. Note that the order of $m$ and $\fl$ are reversed compared to the \kbd{GP} syntax. \subsec{intlaplaceinv$(X=\var{sig},z,\var{expr},\{\var{tab}\})$}\kbdsidx{intlaplaceinv}\label{se:intlaplaceinv} Numerical integration of $(2i\pi)^{-1}\var{expr}(X)e^{Xz}$ with respect to $X$ on the line $\Re(X)=sig$. In other words, inverse Laplace transform of the function corresponding to \var{expr} at the value $z$. $sig$ is coded as follows. Either it is a real number $\sigma$, equal to the abscissa of integration, and then the integrand is assumed to be slowly decreasing when the imaginary part of the variable tends to $\pm\infty$. Or it is a two component vector $[\sigma,\alpha]$, where $\sigma$ is as before, and either $\alpha=0$ for slowly decreasing functions, or $\alpha>0$ for functions decreasing like $\exp(-\alpha t)$. Note that it is not necessary to choose the exact value of $\alpha$. \var{tab} is as in \kbd{intnum}. It is often a good idea to use this function with a value of $m$ one or two higher than the one chosen by default (which can be viewed thanks to the function \kbd{intnumstep}), or to increase the abscissa of integration $\sigma$. For example: \bprog ? \p 105 ? intlaplaceinv(x=2, 1, 1/x) - 1 time = 350 ms. %1 = 7.37... E-55 + 1.72... E-54*I \\@com not so good ? m = intnumstep() %2 = 7 ? intlaplaceinv(x=2, 1, 1/x, m+1) - 1 time = 700 ms. %3 = 3.95... E-97 + 4.76... E-98*I \\@com better ? intlaplaceinv(x=2, 1, 1/x, m+2) - 1 time = 1400 ms. %4 = 0.E-105 + 0.E-106*I \\@com perfect but slow. ? intlaplaceinv(x=5, 1, 1/x) - 1 time = 340 ms. %5 = -5.98... E-85 + 8.08... E-85*I \\@com better than \%1 ? intlaplaceinv(x=5, 1, 1/x, m+1) - 1 time = 680 ms. %6 = -1.09... E-106 + 0.E-104*I \\@com perfect, fast. ? intlaplaceinv(x=10, 1, 1/x) - 1 time = 340 ms. %7 = -4.36... E-106 + 0.E-102*I \\@com perfect, fastest, but why $sig=10$? ? intlaplaceinv(x=100, 1, 1/x) - 1 time = 330 ms. %7 = 1.07... E-72 + 3.2... E-72*I \\@com too far now... @eprog \synt{intlaplaceinv}{void *E, GEN (*eval)(void*,GEN), GEN sig,GEN z, GEN tab, long prec}. \subsec{intmellininv$(X=\var{sig},z,\var{expr},\{\var{tab}\})$}\kbdsidx{intmellininv}\label{se:intmellininv} Numerical integration of $(2i\pi)^{-1}\var{expr}(X)z^{-X}$ with respect to $X$ on the line $\Re(X)=sig$, in other words, inverse Mellin transform of the function corresponding to \var{expr} at the value $z$. $sig$ is coded as follows. Either it is a real number $\sigma$, equal to the abscissa of integration, and then the integrated is assumed to decrease exponentially fast, of the order of $\exp(-t)$ when the imaginary part of the variable tends to $\pm\infty$. Or it is a two component vector $[\sigma,\alpha]$, where $\sigma$ is as before, and either $\alpha=0$ for slowly decreasing functions, or $\alpha>0$ for functions decreasing like $\exp(-\alpha t)$, such as gamma products. Note that it is not necessary to choose the exact value of $\alpha$, and that $\alpha=1$ (equivalent to $sig$ alone) is usually sufficient. \var{tab} is as in \kbd{intnum}. As all similar functions, this function is provided for the convenience of the user, who could use \kbd{intnum} directly. However it is in general better to use \kbd{intmellininvshort}. \bprog ? \p 105 ? intmellininv(s=2,4, gamma(s)^3); time = 1,190 ms. \\@com reasonable. ? \p 308 ? intmellininv(s=2,4, gamma(s)^3); time = 51,300 ms. \\@com slow because of $\Gamma(s)^3$. @eprog\noindent \synt{intmellininv}{void *E, GEN (*eval)(void*,GEN), GEN sig, GEN z, GEN tab, long prec}. \subsec{intmellininvshort$(\var{sig},z,\var{tab})$}\kbdsidx{intmellininvshort}\label{se:intmellininvshort} Numerical integration of $(2i\pi)^{-1}s(X)z^{-X}$ with respect to $X$ on the line $\Re(X)=sig$. In other words, inverse Mellin transform of $s(X)$ at the value $z$. Here $s(X)$ is implicitly contained in \var{tab} in \kbd{intfuncinit} format, typically \bprog tab = intfuncinit(T = [-1], [1], 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|)$ ? tab = intfuncinit(t=[-oo, 3*Pi/2],[oo, 3*Pi/2], gamma(2+I*t)^3, 1); time = 1,370 ms. ? intmellininvshort(2,4, tab) - A time = 50 ms. %4 = -1.26... - 3.25...E-109*I \\@com 50 times faster than \kbd{A} and perfect. ? tab2 = intfuncinit(t=-oo, oo, gamma(2+I*t)^3, 1); ? intmellininvshort(2,4, tab2) %6 = -1.2...E-42 - 3.2...E-109*I \\@com 63 digits lost @eprog\noindent In the computation of \var{tab}, it was not essential to include the \emph{exact} exponential decrease of $\Gamma(2+it)^3$. But as the last example shows, a rough indication \emph{must} be given, otherwise slow decrease is assumed, resulting in catastrophic loss of accuracy. The library syntax is \fun{GEN}{intmellininvshort}{GEN sig, GEN z, GEN tab, long prec}. \subsec{intnum$(X=a,b,\var{expr},\{\var{tab}\})$}\kbdsidx{intnum}\label{se:intnum} Numerical integration of \var{expr} on $]a,b[$ with respect to $X$. The integrand may have values belonging to a vector space over the real numbers; in particular, it can be complex-valued or vector-valued. But it is assumed that the function is regular on $]a,b[$. If the endpoints $a$ and $b$ are finite and the function is regular there, the situation is simple: \bprog ? intnum(x = 0,1, x^2) %1 = 0.3333333333333333333333333333 ? 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. \bprog ? oo = [1]; \\@com for clarity ? intnum(x = 1,+oo, 1/x^2) %2 = 1.000000000000000000000000000 @eprog\noindent In basic usage, it is assumed that the function does not decrease exponentially fast at infinity: \bprog ? intnum(x=0,+oo, exp(-x)) *** at top-level: intnum(x=0,+oo,exp(- *** ^-------------------- *** exp: exponent (expo) overflow @eprog\noindent We shall see in a moment how to avoid the last problem, after describing the last argument \var{tab}, which is both optional and technical. The routine uses weights, which are mostly independent of the function being integrated, evaluated at many sampling points. If \var{tab} is \item a positive integer $m$, we use $2^m$ sampling points, hopefully increasing accuracy. But note that the running time is roughly proportional to $2^m$. One may try consecutive values of $m$ until they give the same value up to an accepted error. If \var{tab} is omitted, the algorithm guesses a reasonable value for $m$ depending on the current precision only, which should be sufficient for regular functions. That value may be obtained from \tet{intnumstep}, and increased in case of difficulties. \item a set of integration tables as output by \tet{intnuminit}, they are used directly. This is useful if several integrations of the same type are performed (on the same kind of interval and functions, for a given accuracy), in particular for multivariate integrals, since we then skip 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$. 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 0$, we only assume the function is regular, which is the default assumption.) If a wrong singularity exponent is used, the result will lose a catastrophic number of decimals: \bprog ? intnum(x=0, 1, x^(-1/2)) \\@com assume $x^{-1/2}$ is regular at 0 %1 = 1.999999999999999999990291881 ? intnum(x=[0,-1/2], 1, x^(-1/2)) \\@com no, it's not %2 = 2.000000000000000000000000000 ? intnum(x=[0,-1/10], 1, x^(-1/2)) %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: \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$ 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(- *** ^-------------------- *** exp: exponent (expo) overflow ? intnum(x=0, [+oo, 2], exp(-2*x)) %1 = 0.5000000000000000000000000000 \\@com OK! ? intnum(x=0, [+oo, 4], exp(-2*x)) %2 = 0.4999999999999999999961990984 \\@com wrong exponent $\Rightarrow$ imprecise result ? intnum(x=0, [+oo, 20], exp(-2*x)) %2 = 0.4999524997739071283804510227 \\@com disaster @eprog \item $\alpha<-1$ assumes that the function tends to $0$ slowly, like $x^{\alpha}$. Here it is essential to give the correct $\alpha$, if possible, but on the other hand $\alpha\le -2$ is equivalent to $\alpha=0$, in other words to no $\alpha$ at all. \smallskip The last two codes are reserved for oscillating functions. Let $k > 0$ real, and $g(x)$ a non-oscillating function tending slowly to $0$ (e.g. like a negative power of $x$), then \item $\alpha=k * I$ assumes that the function behaves like $\cos(kx)g(x)$. \item $\alpha=-k* I$ assumes that the function behaves like $\sin(kx)g(x)$. \noindent Here it is critical to give the exact value of $k$. If the oscillating part is not a pure sine or cosine, one must expand it into a Fourier series, use the above codings, and sum the resulting contributions. Otherwise you will get nonsense. Note that $\cos(kx)$, and similarly $\sin(kx)$, means that very function, and not a translated version such as $\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 if the oscillations are much weaker than the exponential decrease, choose $[[\pm1],\alpha]$, otherwise choose $[[\pm1],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 choose the oscillating type of integral we perhaps obtain the best results, at the expense of having to recompute our functions for a different value of the variable $z$ giving the transform, preventing us to use a function such as \kbd{intmellininvshort}. On the other hand using the exponential type of integral, we obtain less accurate results, but we skip expensive recomputations. See \kbd{intmellininvshort} and \kbd{intfuncinit} for more explanations. \smallskip We shall now see many examples to get a feeling for what the various 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 by \var{expr} has no singularities, it may be important to define the function differently near special points. For instance, if $f(x) = 1 /(\exp(x)-1) - \exp(-x)/x$, then $\int_0^\infty f(x)\,dx=\gamma$, Euler's constant \kbd{Euler}. But \bprog ? f(x) = 1/(exp(x)-1) - exp(-x)/x ? intnum(x = 0, [oo,1], f(x)) - Euler %1 = 6.00... E-67 @eprog\noindent thus only correct to $67$ decimal digits. This is because close to $0$ the function $f$ is computed with an enormous loss of accuracy. A better solution is \bprog ? f(x) = 1/(exp(x)-1)-exp(-x)/x ? F = truncate( f(t + O(t^7)) ); \\@com expansion around t = 0 ? g(x) = if (x > 1e-18, f(x), subst(F,t,x)) \\@com note that $6 \cdot 18 > 105$ ? intnum(x = 0, [oo,1], g(x)) - Euler %2 = 0.E-106 \\@com perfect @eprog\noindent It is up to the user to determine constants such as the $10^{-18}$ and $7$ used above. \misctitle{True singularities} With true singularities the result is worse. For instance \bprog ? intnum(x = 0, 1, 1/sqrt(x)) - 2 %1 = -1.92... E-59 \\@com only $59$ correct decimals ? intnum(x = [0,-1/2], 1, 1/sqrt(x)) - 2 %2 = 0.E-105 \\@com better @eprog \misctitle{Oscillating functions} \bprog ? intnum(x = 0, oo, sin(x) / x) - Pi/2 %1 = 20.78.. \\@com nonsense ? intnum(x = 0, [oo,1], sin(x)/x) - Pi/2 %2 = 0.004.. \\@com bad ? intnum(x = 0, [oo,-I], sin(x)/x) - Pi/2 %3 = 0.E-105 \\@com perfect ? intnum(x = 0, [oo,-I], sin(2*x)/x) - Pi/2 \\@com oops, wrong $k$ %4 = 0.07... ? intnum(x = 0, [oo,-2*I], sin(2*x)/x) - Pi/2 %5 = 0.E-105 \\@com perfect ? intnum(x = 0, [oo,-I], sin(x)^3/x) - Pi/4 %6 = 0.0092... \\@com bad ? sin(x)^3 - (3*sin(x)-sin(3*x))/4 %7 = O(x^17) @eprog\noindent We may use the above linearization and compute two oscillating integrals with ``infinite endpoints'' \kbd{[oo, -I]} and \kbd{[oo, -3*I]} respectively, or notice the obvious change of variable, and reduce to the single integral ${1\over 2}\int_0^\infty \sin(x)/x\,dx$. We finish with some more complicated examples: \bprog ? intnum(x = 0, [oo,-I], (1-cos(x))/x^2) - Pi/2 %1 = -0.0004... \\@com bad ? 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) - Pi/2 %2 = -2.18... E-106 \\@com OK ? intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)) - 0.3 %3 = 5.45... E-107 \\@com OK ? intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)) - 0.3 %4 = -1.33... E-89 \\@com lost 16 decimals. Try higher $m$: ? m = intnumstep() %5 = 7 \\@com the value of $m$ actually used above. ? tab = intnuminit(0,[oo,-I], m+1); \\@com try $m$ one higher. ? intnum(x = 0, oo, sin(x)^3*exp(-x), tab) - 0.3 %6 = 5.45... E-107 \\@com OK this time. @eprog \misctitle{Warning} Like \tet{sumalt}, \kbd{intnum} often assigns a reasonable value to diverging integrals. Use these values at your own risk! For example: \bprog ? intnum(x = 0, [oo, -I], x^2*sin(x)) %1 = -2.0000000000... @eprog\noindent Note the formula $$ \int_0^\infty \sin(x)/x^s\,dx = \cos(\pi s/2) \Gamma(1-s)\;, $$ a priori valid only for $0 < \Re(s) < 2$, but the right hand side provides an analytic continuation which may be evaluated at $s = -2$\dots \misctitle{Multivariate integration} Using successive univariate integration with respect to different formal parameters, it is immediate to do naive multivariate integration. But it is important to use a suitable \kbd{intnuminit} to precompute data for the \emph{internal} integrations at least! For example, to compute the double integral on the unit disc $x^2+y^2\le1$ of the function $x^2+y^2$, we can write \bprog ? tab = intnuminit(-1,1); ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab) @eprog\noindent The first \var{tab} is essential, the second optional. Compare: \bprog ? tab = intnuminit(-1,1); time = 30 ms. ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2)); time = 54,410 ms. \\@com slow ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab); time = 7,210 ms. \\@com faster @eprog\noindent However, the \kbd{intnuminit} program is usually pessimistic when it comes to choosing the integration step $2^{-m}$. It is often possible to improve the speed by trial and error. Continuing the above example: \bprog ? test(M) = { tab = intnuminit(-1,1, M); intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2,tab), tab) - Pi/2 } ? m = intnumstep() \\@com what value of $m$ did it take? %1 = 7 ? test(m - 1) time = 1,790 ms. %2 = -2.05... E-104 \\@com $4 = 2^2$ times faster and still OK. ? test(m - 2) time = 430 ms. %3 = -1.11... E-104 \\@com $16 = 2^4$ times faster and still OK. ? test(m - 3) time = 120 ms. %3 = -7.23... E-60 \\@com $64 = 2^6$ times faster, lost $45$ decimals. @eprog \synt{intnum}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,GEN tab, long prec}, where an omitted \var{tab} is coded as \kbd{NULL}. \subsec{intnuminit$(a,b,\{m=0\})$}\kbdsidx{intnuminit}\label{se:intnuminit} Initialize tables for integration from $a$ to $b$, where $a$ and $b$ are coded as in \kbd{intnum}. Only the 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 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. The result is technical, but in some cases it is useful to know the output. Let $x=\phi(t)$ be the change of variable which is used. \var{tab}[1] contains the integer $m$ as above, either given by the user or computed from the default precision, and can be recomputed directly using the function \kbd{intnumstep}. \var{tab}[2] and \var{tab}[3] contain respectively the abscissa and weight corresponding to $t=0$ ($\phi(0)$ and $\phi'(0)$). \var{tab}[4] and \var{tab}[5] contain the abscissas and weights corresponding to positive $t=nh$ for $1\le n\le N$ and $h=1/2^m$ ($\phi(nh)$ and $\phi'(nh)$). Finally \var{tab}[6] and \var{tab}[7] contain either the abscissas and weights corresponding to negative $t=nh$ for $-N\le n\le -1$, or may be empty (but not always) if $\phi(t)$ is an odd function (implicitly we would have $\var{tab}[6]=-\var{tab}[4]$ and $\var{tab}[7]=\var{tab}[5]$). The library syntax is \fun{GEN}{intnuminit}{GEN a, GEN b, long m, long prec}. \subsec{intnuminitgen$(t,a,b,\var{ph},\{m=0\},\{\fl=0\})$}\kbdsidx{intnuminitgen}\label{se:intnuminitgen} 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 \fl = 1 or 2, multiply the reserved table length by $4^{\fl}$, to avoid corresponding error. \synt{intnuminitgen}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, long m, long flag, long prec} \subsec{intnumromb$(X=a,b,\var{expr},\{\fl=0\})$}\kbdsidx{intnumromb}\label{se:intnumromb} Numerical integration of \var{expr} (smooth in $]a,b[$), with respect to $X$. Suitable for low accuracy; if \var{expr} is very regular (e.g. analytic in a large region) and high accuracy is desired, try \tet{intnum} first. Set $\fl=0$ (or omit it altogether) when $a$ and $b$ are not too large, the function is smooth, and can be evaluated exactly everywhere on the interval $[a,b]$. If $\fl=1$, uses a general driver routine for doing numerical integration, making no particular assumption (slow). $\fl=2$ is tailored for being used when $a$ or $b$ are infinite. One \emph{must} have $ab>0$, and in fact if for example $b=+\infty$, then it is preferable to have $a$ as large as possible, at least $a\ge1$. If $\fl=3$, the function is allowed to be undefined (but continuous) at $a$ or $b$, for example the function $\sin(x)/x$ at $x=0$. The user should not require too much accuracy: 18 or 28 decimal digits is OK, but not much more. In addition, analytical cleanup of the integral must have been done: there must be no singularities in the interval or at the boundaries. In practice this can be accomplished with a simple change of variable. Furthermore, for improper integrals, where one or both of the limits of integration are plus or minus infinity, the function must decrease sufficiently rapidly at infinity. This can often be accomplished through integration by parts. Finally, the function to be integrated should not be very small (compared to the current precision) on the entire interval. This can of course be accomplished by just multiplying by an appropriate constant. Note that \idx{infinity} can be represented with essentially no loss of accuracy by an appropriate huge number. However beware of real underflow when dealing with rapidly decreasing functions. For example, in order to compute the $\int_0^\infty e^{-x^2}\,dx$ to 28 decimal digits, then one can set infinity equal to 10 for example, and certainly not to \kbd{1e1000}. \synt{intnumromb}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, long flag, long prec}, where $\kbd{eval}(x, E)$ returns the value of the function at $x$. You may store any additional information required by \kbd{eval} in $E$, or set it to \kbd{NULL}. \subsec{intnumstep$()$}\kbdsidx{intnumstep}\label{se:intnumstep} Give the value of $m$ used in all the \kbd{intnum} and \kbd{sumnum} programs, hence such that the integration step is equal to $1/2^m$. The library syntax is \fun{long}{intnumstep}{long prec}. \subsec{prod$(X=a,b,\var{expr},\{x=1\})$}\kbdsidx{prod}\label{se:prod} Product of expression \var{expr}, initialized at $x$, the formal parameter $X$ going from $a$ to $b$. As for \kbd{sum}, the main purpose of the initialization parameter $x$ is to force the type of the operations being performed. For example if it is set equal to the integer 1, operations will start being done exactly. If it is set equal to the real $1.$, they will be done using real numbers having the default precision. If it is set equal to the power series $1+O(X^k)$ for a certain $k$, they will be done using power series of precision at most $k$. These are the three most common initializations. \noindent As an extreme example, compare \bprog ? prod(i=1, 100, 1 - X^i); \\@com this has degree $5050$ !! time = 128 ms. ? prod(i=1, 100, 1 - X^i, 1 + O(X^101)) time = 8 ms. %2 = 1 - X - X^2 + X^5 + X^7 - X^12 - X^15 + X^22 + X^26 - X^35 - X^40 + \ X^51 + X^57 - X^70 - X^77 + X^92 + X^100 + O(X^101) @eprog\noindent Of course, in this specific case, it is faster to use \tet{eta}, which is computed using Euler's formula. \bprog ? prod(i=1, 1000, 1 - X^i, 1 + O(X^1001)); time = 589 ms. ? \ps1000 seriesprecision = 1000 significant terms ? eta(X) - % time = 8ms. %4 = O(X^1001) @eprog \synt{produit}{GEN a, GEN b, char *expr, GEN x}. \subsec{prodeuler$(X=a,b,\var{expr})$}\kbdsidx{prodeuler}\label{se:prodeuler} Product of expression \var{expr}, initialized at 1. (i.e.~to a \emph{real} number equal to 1 to the current \kbd{realprecision}), the formal parameter $X$ ranging over the prime numbers between $a$ and $b$.\sidx{Euler product} \synt{prodeuler}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b, long prec}. \subsec{prodinf$(X=a,\var{expr},\{\fl=0\})$}\kbdsidx{prodinf}\label{se:prodinf} \idx{infinite product} of expression \var{expr}, the formal parameter $X$ starting at $a$. The evaluation stops when the relative error of the expression minus 1 is less than the default precision. In particular, non-convergent products result in infinite loops. The expressions must always evaluate to an element of $\C$. If $\fl=1$, do the product of the ($1+\var{expr}$) instead. \synt{prodinf}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec} ($\fl=0$), or \tet{prodinf1} with the same arguments ($\fl=1$). \subsec{solve$(X=a,b,\var{expr})$}\kbdsidx{solve}\label{se:solve} Find a real root of expression \var{expr} between $a$ and $b$, under the condition $\var{expr}(X=a) * \var{expr}(X=b) \le 0$. (You will get an error message \kbd{roots must be bracketed in solve} if this does not hold.) This routine uses Brent's method and can fail miserably if \var{expr} is not defined in the whole of $[a,b]$ (try \kbd{solve(x=1, 2, tan(x))}). \synt{zbrent}{void *E,GEN (*eval)(void*,GEN),GEN a,GEN b,long prec}. \subsec{sum$(X=a,b,\var{expr},\{x=0\})$}\kbdsidx{sum}\label{se:sum} Sum of expression \var{expr}, initialized at $x$, the formal parameter going from $a$ to $b$. As for \kbd{prod}, the initialization parameter $x$ may be given to force the type of the operations being performed. \noindent As an extreme example, compare \bprog ? sum(i=1, 10^4, 1/i); \\@com rational number: denominator has $4345$ digits. time = 236 ms. ? sum(i=1, 5000, 1/i, 0.) time = 8 ms. %2 = 9.787606036044382264178477904 @eprog \synt{somme}{GEN a, GEN b, char *expr, GEN x}. \subsec{sumalt$(X=a,\var{expr},\{\fl=0\})$}\kbdsidx{sumalt}\label{se:sumalt} 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). If $\fl=1$, use a variant with slightly different polynomials. Sometimes faster. 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 \secref{se:userfundef}.) If the series already converges geometrically, \tet{suminf} is often a better choice: \bprog ? \p28 ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 0 ms. %1 = -2.524354897 E-29 ? suminf(i = 1, -(-1)^i / i) \\@com Had to hit *** at top-level: suminf(i=1,-(-1)^i/i) *** ^------ *** suminf: user interrupt after 10min, 20,100 ms. ? \p1000 ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 90 ms. %2 = 4.459597722 E-1002 ? sumalt(i = 0, (-1)^i / i!) - exp(-1) time = 670 ms. %3 = -4.03698781490633483156497361352190615794353338591897830587 E-944 ? suminf(i = 0, (-1)^i / i!) - exp(-1) time = 110 ms. %4 = -8.39147638 E-1000 \\ @com faster and more accurate @eprog \synt{sumalt}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also available is \tet{sumalt2} with the same arguments ($\fl = 1$). \subsec{sumdiv$(n,X,\var{expr})$}\kbdsidx{sumdiv}\label{se:sumdiv} Sum of expression \var{expr} over the positive divisors of $n$. This function is a trivial wrapper essentially equivalent to \bprog D = divisors(n); for (i = 1, #D, X = D[i]; eval(expr)) @eprog\noindent (except that \kbd{X} is lexically scoped to the \kbd{sumdiv} loop). If \var{expr} is a multiplicative function, use \tet{sumdivmult}. %\syn{NO} \subsec{sumdivmult$(n,d,\var{expr})$}\kbdsidx{sumdivmult}\label{se:sumdivmult} Sum of \emph{multiplicative} expression \var{expr} over the positive divisors $d$ of $n$. Assume that \var{expr} evaluates to $f(d)$ where $f$ is multiplicative: $f(1) = 1$ and $f(ab) = f(a)f(b)$ for coprime $a$ and $b$. %\syn{NO} \subsec{suminf$(X=a,\var{expr})$}\kbdsidx{suminf}\label{se:suminf} \idx{infinite sum} of expression \var{expr}, the formal parameter $X$ starting at $a$. The evaluation stops when the relative error of the expression is less than the default precision for 3 consecutive evaluations. The expressions must always evaluate to a complex number. If the series converges slowly, make sure \kbd{realprecision} is low (even 28 digits may be too much). In this case, if the series is alternating or the terms have a constant sign, \tet{sumalt} and \tet{sumpos} should be used instead. \bprog ? \p28 ? suminf(i = 1, -(-1)^i / i) \\@com Had to hit *** at top-level: suminf(i=1,-(-1)^i/i) *** ^------ *** suminf: user interrupt after 10min, 20,100 ms. ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 0 ms. %1 = -2.524354897 E-29 @eprog \synt{suminf}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec}. \subsec{sumnum$(X=a,\var{sig},\var{expr},\{\var{tab}\},\{\fl=0\})$}\kbdsidx{sumnum}\label{se:sumnum} Numerical summation of \var{expr}, the variable $X$ taking integer values from ceiling of $a$ to $+\infty$, where \var{expr} is assumed to be a holomorphic function $f(X)$ for $\Re(X)\ge \sigma$. The parameter $\sigma\in\R$ is coded in the argument \kbd{sig} as follows: it is either \item a real number $\sigma$. Then the function $f$ is assumed to decrease at least as $1/X^2$ at infinity, but not exponentially; \item a two-component vector $[\sigma,\alpha]$, where $\sigma$ is as before, $\alpha < -1$. The function $f$ is assumed to decrease like $X^{\alpha}$. In particular, $\alpha\le-2$ is equivalent to no $\alpha$ at all. \item a two-component vector $[\sigma,\alpha]$, where $\sigma$ is as before, $\alpha > 0$. The function $f$ is assumed to decrease like $\exp(-\alpha X)$. In this case it is essential that $\alpha$ be exactly the rate of exponential decrease, and it is usually a good idea to increase the default value of $m$ used for the integration step. In practice, if the function is exponentially decreasing \kbd{sumnum} is slower and less accurate than \kbd{sumpos} or \kbd{suminf}, so should not be used. The function uses the \tet{intnum} routines and integration on the line $\Re(s) = \sigma$. The optional argument \var{tab} is as in intnum, except it must be initialized with \kbd{sumnuminit} instead of \kbd{intnuminit}. When \var{tab} is not precomputed, \kbd{sumnum} can be slower than \kbd{sumpos}, when the latter is applicable. It is in general faster for slowly decreasing functions. Finally, if $\fl$ is nonzero, we assume that the function $f$ to be summed is of real type, i.e. satisfies $\overline{f(z)}=f(\overline{z})$, which speeds up the computation. \bprog ? \p 308 ? a = sumpos(n=1, 1/(n^3+n+1)); time = 1,410 ms. ? tab = sumnuminit(2); time = 1,620 ms. \\@com slower but done once and for all. ? b = sumnum(n=1, 2, 1/(n^3+n+1), tab); time = 460 ms. \\@com 3 times as fast as \kbd{sumpos} ? a - b %4 = -1.0... E-306 + 0.E-320*I \\@com perfect. ? sumnum(n=1, 2, 1/(n^3+n+1), tab, 1) - a; \\@com function of real type time = 240 ms. %2 = -1.0... E-306 \\@com twice as fast, no imaginary part. ? c = sumnum(n=1, 2, 1/(n^2+1), tab, 1); time = 170 ms. \\@com fast ? d = sumpos(n=1, 1 / (n^2+1)); time = 2,700 ms. \\@com slow. ? d - c time = 0 ms. %5 = 1.97... E-306 \\@com perfect. @eprog For slowly decreasing function, we must indicate singularities: \bprog ? \p 308 ? a = sumnum(n=1, 2, n^(-4/3)); time = 9,930 ms. \\@com slow because of the computation of $n^{-4/3}$. ? a - zeta(4/3) time = 110 ms. %1 = -2.42... E-107 \\@com lost 200 decimals because of singularity at $\infty$ ? b = sumnum(n=1, [2,-4/3], n^(-4/3), /*omitted*/, 1); \\@com of real type time = 12,210 ms. ? b - zeta(4/3) %3 = 1.05... E-300 \\@com better @eprog Since the \emph{complex} values of the function are used, beware of determination problems. For instance: \bprog ? \p 308 ? tab = sumnuminit([2,-3/2]); time = 1,870 ms. ? sumnum(n=1,[2,-3/2], 1/(n*sqrt(n)), tab,1) - zeta(3/2) time = 690 ms. %1 = -1.19... E-305 \\@com fast and correct ? sumnum(n=1,[2,-3/2], 1/sqrt(n^3), tab,1) - zeta(3/2) time = 730 ms. %2 = -1.55... \\@com nonsense. However ? sumnum(n=1,[2,-3/2], 1/n^(3/2), tab,1) - zeta(3/2) time = 8,990 ms. %3 = -1.19... E-305 \\@com perfect, as $1/(n*\sqrt{n})$ above but much slower @eprog For exponentially decreasing functions, \kbd{sumnum} is given for completeness, but one of \tet{suminf} or \tet{sumpos} should always be preferred. If you experiment with such functions and \kbd{sumnum} anyway, indicate the exact rate of decrease and increase $m$ by $1$ or $2$: \bprog ? suminf(n=1, 2^(-n)) - 1 time = 10 ms. %1 = -1.11... E-308 \\@com fast and perfect ? sumpos(n=1, 2^(-n)) - 1 time = 10 ms. %2 = -2.78... E-308 \\@com also fast and perfect ? sumnum(n=1,2, 2^(-n)) - 1 %3 = -1.321115060 E320 + 0.E311*I \\@com nonsense ? sumnum(n=1, [2,log(2)], 2^(-n), /*omitted*/, 1) - 1 \\@com of real type time = 5,860 ms. %4 = -1.5... E-236 \\@com slow and lost $70$ decimals ? m = intnumstep() %5 = 9 ? sumnum(n=1,[2,log(2)], 2^(-n), m+1, 1) - 1 time = 11,770 ms. %6 = -1.9... E-305 \\@com now perfect, but slow. @eprog \synt{sumnum}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN sig,GEN tab,long flag, long prec}. \subsec{sumnumalt$(X=a,\var{sig},\var{expr},\{\var{tab}\},\{\fl=0\})$}\kbdsidx{sumnumalt}\label{se:sumnumalt} Numerical summation of $(-1)^X\var{expr}(X)$, the variable $X$ taking integer values from ceiling of $a$ to $+\infty$, where \var{expr} is assumed to be a holomorphic function for $\Re(X)\ge sig$ (or $sig[1]$). \misctitle{Warning} This function uses the \kbd{intnum} routines and is orders of magnitude slower than \kbd{sumalt}. It is only given for completeness and should not be used in practice. \misctitle{Warning 2} The expression \var{expr} must \emph{not} include the $(-1)^X$ coefficient. Thus $\kbd{sumalt}(n=a,(-1)^nf(n))$ is (approximately) equal to $\kbd{sumnumalt}(n=a,sig,f(n))$. $sig$ is coded as in \kbd{sumnum}. However for slowly decreasing functions (where $sig$ is coded as $[\sigma,\alpha]$ with $\alpha<-1$), it is not really important to indicate $\alpha$. In fact, as for \kbd{sumalt}, the program will often give meaningful results (usually analytic continuations) even for divergent series. On the other hand the exponential decrease must be indicated. \var{tab} is as in \kbd{intnum}, but if used must be initialized with \kbd{sumnuminit}. If $\fl$ is nonzero, assumes that the function $f$ to be summed is of real type, i.e. satisfies $\overline{f(z)}=f(\overline{z})$, and then twice faster when \var{tab} is precomputed. \bprog ? \p 308 ? tab = sumnuminit(2, /*omitted*/, -1); \\@com abscissa $\sigma=2$, alternating sums. time = 1,620 ms. \\@com slow, but done once and for all. ? a = sumnumalt(n=1, 2, 1/(n^3+n+1), tab, 1); time = 230 ms. \\@com similar speed to \kbd{sumnum} ? b = sumalt(n=1, (-1)^n/(n^3+n+1)); time = 0 ms. \\@com infinitely faster! ? a - b time = 0 ms. %1 = -1.66... E-308 \\@com perfect @eprog \synt{sumnumalt}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN sig, GEN tab, long flag, long prec}. \subsec{sumnuminit$(\var{sig}, \{m=0\}, \{\var{sgn}=1\})$}\kbdsidx{sumnuminit}\label{se:sumnuminit} Initialize tables for numerical summation using \kbd{sumnum} (with $\var{sgn}=1$) or \kbd{sumnumalt} (with $\var{sgn}=-1$), $sig$ is the abscissa of integration coded as in \kbd{sumnum}, and $m$ is as in \kbd{intnuminit}. The library syntax is \fun{GEN}{sumnuminit}{GEN sig, long m, long sgn, long prec}. \subsec{sumpos$(X=a,\var{expr},\{\fl=0\})$}\kbdsidx{sumpos}\label{se:sumpos} Numerical summation of the series \var{expr}, which must be a series of terms having the same sign, the formal variable $X$ starting at $a$. The algorithm used is Van Wijngaarden's trick for converting such a series into an alternating one, then we use \tet{sumalt}. For regular functions, the function \kbd{sumnum} is in general much faster once the initializations have been made using \kbd{sumnuminit}. The routine is heuristic and assumes that \var{expr} is more or less a decreasing function of $X$. In particular, the result will be completely wrong if \var{expr} is 0 too often. We do not check either that all terms 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. \synt{sumpos}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also available is \tet{sumpos2} with the same arguments ($\fl = 1$). %SECTION: sums \section{Plotting functions} Although plotting is not even a side purpose of PARI, a number of plotting functions are provided. Moreover, a lot of people \footnote{*}{Among these, special thanks go to Klaus-Peter Nischke who suggested the recursive plotting and forking/resizing stuff the graphical window, and Ilya Zakharevich who rewrote the graphic code from scratch implementing many new primitives (splines, clipping). Nils Skoruppa and Bill Allombert wrote the \tet{Qt} and \tet{fltk} graphic drivers respectively.} suggested ideas or submitted patches for this section of the code. There are three types of graphic functions. \subsec{High-level plotting functions} (all the functions starting with \kbd{ploth}) in which the user has little to do but explain what type of plot he wants, and whose syntax is similar to the one used in the preceding section. \subsec{Low-level plotting functions} (called \var{rectplot} functions, sharing the prefix \kbd{plot}), where every drawing primitive (point, line, box, etc.) is specified by the user. These low-level functions work as follows. You have at your disposal 16 virtual windows which are filled independently, and can then be physically ORed on a single window at user-defined positions. These windows are numbered from 0 to 15, and must be initialized before being used by the function \kbd{plotinit}, which specifies the height and width of the virtual window (called a \var{rectwindow} in the sequel). At all times, a virtual cursor (initialized at $[0,0]$) is associated to the window, and its current value can be obtained using the function \kbd{plotcursor}. A number of primitive graphic objects (called \var{rect} objects) can then be drawn in these windows, using a default color associated to that window (which can be changed using the \kbd{plotcolor} function) and only the part of the object which is inside the window will be drawn, with the exception of polygons and strings which are drawn entirely. The ones sharing the prefix \kbd{plotr} draw relatively to the current position of the virtual cursor, the others use absolute coordinates. Those having the prefix \kbd{plotrecth} put in the rectwindow a large batch of rect objects corresponding to the output of the related \kbd{ploth} function. Finally, the actual physical drawing is done using \kbd{plotdraw}. The rectwindows are preserved so that further drawings using the same windows at different positions or different windows can be done without extra work. To erase a window, use \kbd{plotkill}. It is not possible to partially erase a window: erase it completely, initialize it again, then fill it with the graphic objects that you want to keep. In addition to initializing the window, you may use a scaled window to avoid unnecessary conversions. For this, use \kbd{plotscale}. As long as this function is not called, the scaling is simply the number of pixels, the origin being at the upper left and the $y$-coordinates going downwards. Plotting functions are platform independent, but a number of graphical drivers are available for screen output: X11-windows (hence also for GUI's based on X11 such as Openwindows and Motif), and the Qt and FLTK graphical libraries. The physical window opened by \kbd{plotdraw} or any of the \kbd{ploth*} functions is completely separated from \kbd{gp} (technically, a \kbd{fork} is done, and the non-graphical memory is immediately freed in the child process), which means you can go on working in the current \kbd{gp} session, without having to kill the window first. This window can be closed, enlarged or reduced using the standard window manager functions. No zooming procedure is implemented though (yet). \subsec{Functions for PostScript output} in the same way that \kbd{printtex} allows you to have a \TeX\ output corresponding to printed results, the functions starting with \kbd{ps} allow you to have \tet{PostScript} output of the plots. This will not be identical with the screen output, but sufficiently close. Note that you can use PostScript output even if you do not have the plotting routines enabled. The PostScript output is written in a file whose name is derived from the \tet{psfile} default (\kbd{./pari.ps} if you did not tamper with it). Each time a new PostScript output is asked for, the PostScript output is appended to that file. Hence you probably want to remove this file, or change the value of \kbd{psfile}, in between plots. On the other hand, in this manner, as many plots as desired can be kept in a single file. \smallskip \subsec{Library mode} \emph{None of the graphic functions are available within the PARI library, you must be under \kbd{gp} to use them}. The reason for that is that you really should not use PARI for heavy-duty graphical work, there are better specialized alternatives around. This whole set of routines was only meant as a convenient, but simple-minded, visual aid. If you really insist on using these in your program (we warned you), the source (\kbd{plot*.c}) should be readable enough for you to achieve something. \subsec{plot$(X=a,b,\var{expr},\{\var{Ymin}\},\{\var{Ymax}\})$}\kbdsidx{plot}\label{se:plot} Crude ASCII plot of the function represented by expression \var{expr} from $a$ to $b$, with \var{Y} ranging from \var{Ymin} to \var{Ymax}. If \var{Ymin} (resp. \var{Ymax}) is not given, the minimum (resp. the maximum) of the computed values of the expression is used instead. \subsec{plotbox$(w,\var{x2},\var{y2})$}\kbdsidx{plotbox}\label{se:plotbox} Let $(x1,y1)$ be the current position of the virtual cursor. Draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x2,y2)$ are opposite corners. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. \subsec{plotclip$(w)$}\kbdsidx{plotclip}\label{se:plotclip} `clips' the content of rectwindow $w$, i.e remove all parts of the drawing that would not be visible on the screen. Together with \tet{plotcopy} this function enables you to draw on a scratchpad before committing the part you're interested in to the final picture. \subsec{plotcolor$(w,c)$}\kbdsidx{plotcolor}\label{se:plotcolor} Set default color to $c$ in rectwindow $w$. This is only implemented for the X-windows, fltk and Qt graphing engines. Possible values for $c$ are given by the \tet{graphcolormap} default, factory setting are 1=black, 2=blue, 3=violetred, 4=red, 5=green, 6=grey, 7=gainsborough. but this can be considerably extended. \subsec{plotcopy$(\var{sourcew},\var{destw},\var{dx},\var{dy},\{\fl=0\})$}\kbdsidx{plotcopy}\label{se:plotcopy} Copy the contents of rectwindow \var{sourcew} to rectwindow \var{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 \subsec{plotcursor$(w)$}\kbdsidx{plotcursor}\label{se:plotcursor} Give as a 2-component vector the current (scaled) position of the virtual cursor corresponding to the rectwindow $w$. \subsec{plotdraw$(\var{list}, \{\fl=0\})$}\kbdsidx{plotdraw}\label{se:plotdraw} Physically draw the rectwindows given in $list$ which must be a vector whose number of components is divisible by 3. If $list=[w1,x1,y1,w2,x2,y2,\dots]$, the windows $w1$, $w2$, etc.~are physically placed with their upper left corner at physical position $(x1,y1)$, $(x2,y2)$,\dots\ respectively, and are then drawn together. Overlapping regions will thus be drawn twice, and the windows are considered transparent. Then display the whole drawing in a special window on your screen. If $\fl \neq 0$, x1, y1 etc. express fractions of the size of the current output device \subsec{ploth$(X=a,b,\var{expr},\{\var{flags}=0\},\{n=0\})$}\kbdsidx{ploth}\label{se:ploth} High precision plot of the function $y=f(x)$ represented by the expression \var{expr}, $x$ going from $a$ to $b$. This opens a specific window (which is killed whenever you click on it), and returns a four-component vector giving the coordinates of the bounding box in the form $[\var{xmin},\var{xmax},\var{ymin},\var{ymax}]$. \misctitle{Important note} \kbd{ploth} may evaluate \kbd{expr} thousands of times; given the relatively low resolution of plotting devices, few significant digits of the result will be meaningful. Hence you should keep the current precision to a minimum (e.g.~9) before calling this function. $n$ specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values (1000 for general plot, 1500 for parametric plot, and 8 for recursive plot). If no $\fl$ is given, \var{expr} is either a scalar expression $f(X)$, in which case the plane curve $y=f(X)$ will be drawn, or a vector $[f_1(X),\dots,f_k(X)]$, and then all the curves $y=f_i(X)$ will be drawn in the same window. \noindent The binary digits of $\fl$ mean: \item $1 = \kbd{Parametric}$: \tev{parametric plot}. Here \var{expr} must be a vector with an even number of components. Successive pairs are then understood as the parametric coordinates of a plane curve. Each of these are then drawn. For instance: \bprog ploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") ploth(X=0,2*Pi,[sin(X),cos(X)]) ploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric") @eprog\noindent draw successively a circle, two entwined sinusoidal curves and a circle cut by the line $y=x$. \item $2 = \kbd{Recursive}$: \tev{recursive plot}. If this flag is set, only \emph{one} curve can be drawn at a time, i.e.~\var{expr} must be either a two-component vector (for a single parametric curve, and the parametric flag \emph{has} to be set), or a scalar function. The idea is to choose pairs of successive reference points, and if their middle point is not too far away from the segment joining them, draw this as a local approximation to the curve. Otherwise, add the middle point to the reference points. This is fast, and usually more precise than usual plot. Compare the results of \bprog ploth(X=-1,1, sin(1/X), "Recursive") ploth(X=-1,1, sin(1/X)) @eprog\noindent for instance. But beware that if you are extremely unlucky, or choose too few reference points, you may draw some nice polygon bearing little resemblance to the original curve. For instance you should \emph{never} plot recursively an odd function in a symmetric interval around 0. Try \bprog ploth(x = -20, 20, sin(x), "Recursive") @eprog\noindent to see why. Hence, it's usually a good idea to try and plot the same curve with slightly different parameters. The other values toggle various display options: \item $4 = \kbd{no\_Rescale}$: do not rescale plot according to the computed extrema. This is used in conjunction with \tet{plotscale} when graphing multiple functions on a rectwindow (as a \tet{plotrecth} call): \bprog s = plothsizes(); plotinit(0, s[2]-1, s[2]-1); plotscale(0, -1,1, -1,1); plotrecth(0, t=0,2*Pi, [cos(t),sin(t)], "Parametric|no_Rescale") plotdraw([0, -1,1]); @eprog\noindent This way we get a proper circle instead of the distorted ellipse produced by \bprog ploth(t=0,2*Pi, [cos(t),sin(t)], "Parametric") @eprog \item $8 = \kbd{no\_X\_axis}$: do not print the $x$-axis. \item $16 = \kbd{no\_Y\_axis}$: do not print the $y$-axis. \item $32 = \kbd{no\_Frame}$: do not print frame. \item $64 = \kbd{no\_Lines}$: only plot reference points, do not join them. \item $128 = \kbd{Points\_too}$: plot both lines and points. \item $256 = \kbd{Splines}$: use splines to interpolate the points. \item $512 = \kbd{no\_X\_ticks}$: plot no $x$-ticks. \item $1024 = \kbd{no\_Y\_ticks}$: plot no $y$-ticks. \item $2048 = \kbd{Same\_ticks}$: plot all ticks with the same length. \item $4096 = \kbd{Complex}$: is a parametric plot but where each member of \kbd{expr} is considered a complex number encoding the two coordinates of a point. For instance: \bprog ploth(X=0,2*Pi,exp(I*X), "Complex") ploth(X=0,2*Pi,[(1+I)*X,exp(I*X)], "Complex") @eprog\noindent will draw respectively a circle and a circle cut by the line $y=x$. \subsec{plothraw$(\var{listx},\var{listy},\{\fl=0\})$}\kbdsidx{plothraw}\label{se:plothraw} Given \var{listx} and \var{listy} two vectors of equal length, plots (in high precision) the points whose $(x,y)$-coordinates are given in \var{listx} and \var{listy}. Automatic positioning and scaling is done, but with the same scaling factor on $x$ and $y$. If $\fl$ is 1, join points, other non-0 flags toggle display options and should be combinations of bits $2^k$, $k \geq 3$ as in \kbd{ploth}. \subsec{plothsizes$(\{\fl=0\})$}\kbdsidx{plothsizes}\label{se:plothsizes} Return data corresponding to the output window in the form of a 6-component vector: window width and height, sizes for ticks in horizontal and vertical directions (this is intended for the \kbd{gnuplot} interface and is currently not significant), width and height of characters. If $\fl = 0$, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size \subsec{plotinit$(w,\{x\},\{y\},\{\fl=0\})$}\kbdsidx{plotinit}\label{se:plotinit} Initialize the rectwindow $w$, destroying any rect objects you may have already drawn in $w$. The virtual cursor is set to $(0,0)$. The rectwindow size is set to width $x$ and height $y$; omitting either $x$ or $y$ means we use the full size of the device in that direction. If $\fl=0$, $x$ and $y$ represent pixel units. Otherwise, $x$ and $y$ are understood as fractions of the size of the current output device (hence must be between $0$ and $1$) and internally converted to pixels. The plotting device imposes an upper bound for $x$ and $y$, for instance the number of pixels for screen output. These bounds are available through the \tet{plothsizes} function. The following sequence initializes in a portable way (i.e independent of the output device) a window of maximal size, accessed through coordinates in the $[0,1000] \times [0,1000]$ range: \bprog s = plothsizes(); plotinit(0, s[1]-1, s[2]-1); plotscale(0, 0,1000, 0,1000); @eprog \subsec{plotkill$(w)$}\kbdsidx{plotkill}\label{se:plotkill} Erase rectwindow $w$ and free the corresponding memory. Note that if you want to use the rectwindow $w$ again, you have to use \kbd{plotinit} first to specify the new size. So it's better in this case to use \kbd{plotinit} directly as this throws away any previous work in the given rectwindow. \subsec{plotlines$(w,X,Y,\{\fl=0\})$}\kbdsidx{plotlines}\label{se:plotlines} Draw on the rectwindow $w$ the polygon such that the (x,y)-coordinates of the vertices are in the vectors of equal length $X$ and $Y$. For simplicity, the whole polygon is drawn, not only the part of the polygon which is inside the rectwindow. If $\fl$ is non-zero, close the polygon. In any case, the virtual cursor does not move. $X$ and $Y$ are allowed to be scalars (in this case, both have to). There, a single segment will be drawn, between the virtual cursor current position and the point $(X,Y)$. And only the part thereof which actually lies within the boundary of $w$. Then \emph{move} the virtual cursor to $(X,Y)$, even if it is outside the window. If you want to draw a line from $(x1,y1)$ to $(x2,y2)$ where $(x1,y1)$ is not necessarily the position of the virtual cursor, use \kbd{plotmove(w,x1,y1)} before using this function. \subsec{plotlinetype$(w,\var{type})$}\kbdsidx{plotlinetype}\label{se:plotlinetype} Change the type of lines subsequently plotted in rectwindow $w$. \var{type} $-2$ corresponds to frames, $-1$ to axes, larger values may correspond to something else. $w = -1$ changes highlevel plotting. This is only taken into account by the \kbd{gnuplot} interface. \subsec{plotmove$(w,x,y)$}\kbdsidx{plotmove}\label{se:plotmove} Move the virtual cursor of the rectwindow $w$ to position $(x,y)$. \subsec{plotpoints$(w,X,Y)$}\kbdsidx{plotpoints}\label{se:plotpoints} Draw on the rectwindow $w$ the points whose $(x,y)$-coordinates are in the vectors of equal length $X$ and $Y$ and which are inside $w$. The virtual cursor does \emph{not} move. This is basically the same function as \kbd{plothraw}, but either with no scaling factor or with a scale chosen using the function \kbd{plotscale}. As was the case with the \kbd{plotlines} function, $X$ and $Y$ are allowed to be (simultaneously) scalar. In this case, draw the single point $(X,Y)$ on the rectwindow $w$ (if it is actually inside $w$), and in any case \emph{move} the virtual cursor to position $(x,y)$. \subsec{plotpointsize$(w,\var{size})$}\kbdsidx{plotpointsize}\label{se:plotpointsize} Changes the ``size'' of following points in rectwindow $w$. If $w = -1$, change it in all rectwindows. This only works in the \kbd{gnuplot} interface. \subsec{plotpointtype$(w,\var{type})$}\kbdsidx{plotpointtype}\label{se:plotpointtype} Change the type of points subsequently plotted in rectwindow $w$. $\var{type} = -1$ corresponds to a dot, larger values may correspond to something else. $w = -1$ changes highlevel plotting. This is only taken into account by the \kbd{gnuplot} interface. \subsec{plotrbox$(w,\var{dx},\var{dy})$}\kbdsidx{plotrbox}\label{se:plotrbox} Draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x1+dx,y1+dy)$ are opposite corners, where $(x1,y1)$ is the current position of the cursor. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. \subsec{plotrecth$(w,X=a,b,\var{expr},\{\fl=0\},\{n=0\})$}\kbdsidx{plotrecth}\label{se:plotrecth} Writes to rectwindow $w$ the curve output of \kbd{ploth}$(w,X=a,b,\var{expr},\fl,n)$. Returns a vector for the bounding box. \subsec{plotrecthraw$(w,\var{data},\{\var{flags}=0\})$}\kbdsidx{plotrecthraw}\label{se:plotrecthraw} Plot graph(s) for \var{data} in rectwindow $w$. $\fl$ has the same significance here as in \kbd{ploth}, though recursive plot is no more significant. \var{data} is a vector of vectors, each corresponding to a list a coordinates. If parametric plot is set, there must be an even number of vectors, each successive pair corresponding to a curve. Otherwise, the first one contains the $x$ coordinates, and the other ones contain the $y$-coordinates of curves to plot. \subsec{plotrline$(w,\var{dx},\var{dy})$}\kbdsidx{plotrline}\label{se:plotrline} Draw in the rectwindow $w$ the part of the segment $(x1,y1)-(x1+dx,y1+dy)$ which is inside $w$, where $(x1,y1)$ is the current position of the virtual cursor, and move the virtual cursor to $(x1+dx,y1+dy)$ (even if it is outside the window). \subsec{plotrmove$(w,\var{dx},\var{dy})$}\kbdsidx{plotrmove}\label{se:plotrmove} Move the virtual cursor of the rectwindow $w$ to position $(x1+dx,y1+dy)$, where $(x1,y1)$ is the initial position of the cursor (i.e.~to position $(dx,dy)$ relative to the initial cursor). \subsec{plotrpoint$(w,\var{dx},\var{dy})$}\kbdsidx{plotrpoint}\label{se:plotrpoint} Draw the point $(x1+dx,y1+dy)$ on the rectwindow $w$ (if it is inside $w$), where $(x1,y1)$ is the current position of the cursor, and in any case move the virtual cursor to position $(x1+dx,y1+dy)$. \subsec{plotscale$(w,\var{x1},\var{x2},\var{y1},\var{y2})$}\kbdsidx{plotscale}\label{se:plotscale} Scale the local coordinates of the rectwindow $w$ so that $x$ goes from $x1$ to $x2$ and $y$ goes from $y1$ to $y2$ ($x2 to continue; 'break' to go back to GP break> z 10 break> %2 = 13 @eprog \subsec{dbg\_down$(\{n=1\})$}\kbdsidx{dbg_down}\label{se:dbg_down} (In the break loop) go down n frames. This allows to cancel a previous call to \kbd{dbg\_up}. \subsec{dbg\_err$()$}\kbdsidx{dbg_err}\label{se:dbg_err} In the break loop, return the error data of the current error, if any. See \tet{iferr} for details about error data. Compare: \bprog ? iferr(1/(Mod(2,12019)^(6!)-1),E,Vec(E)) %1 = ["e_INV", "Fp_inv", Mod(119, 12019)] ? 1/(Mod(2,12019)^(6!)-1) *** at top-level: 1/(Mod(2,12019)^(6!)- *** ^-------------------- *** _/_: impossible inverse in Fp_inv: Mod(119, 12019). *** Break loop: type 'break' to go back to GP prompt break> Vec(dbg_err()) ["e_INV", "Fp_inv", Mod(119, 12019)] @eprog \subsec{dbg\_up$(\{n=1\})$}\kbdsidx{dbg_up}\label{se:dbg_up} (In the break loop) go up n frames. This allows to inspect data of the parent function. To cancel a \tet{dbg_up} call, use \tet{dbg_down} \subsec{dbg\_x$(A\{,n\})$}\kbdsidx{dbg_x}\label{se:dbg_x} Print the inner structure of \kbd{A}, complete if \kbd{n} is omitted, up to level \kbd{n} otherwise. This is useful for debugging. This is similar to \b{x} but does not require \kbd{A} to be an history entry. In particular, it can be used in the break loop. \subsec{for$(X=a,b,\var{seq})$}\kbdsidx{for}\label{se:for} Evaluates \var{seq}, where the formal variable $X$ goes from $a$ to $b$. Nothing is done if $a>b$. $a$ and $b$ must be in $\R$. \subsec{forcomposite$(n=a,\{b\},\var{seq})$}\kbdsidx{forcomposite}\label{se:forcomposite} Evaluates \var{seq}, where the formal variable $n$ ranges over the composite numbers between the non-negative real numbers $a$ to $b$, including $a$ and $b$ if they are composite. Nothing is done if $a>b$. \bprog ? forcomposite(n = 0, 10, print(n)) 4 6 8 9 10 @eprog\noindent Omitting $b$ means we will run through all composites $\geq a$, starting an infinite loop; it is expected that the user will break out of the loop himself at some point, using \kbd{break} or \kbd{return}. Note that the value of $n$ cannot be modified within \var{seq}: \bprog ? forcomposite(n = 2, 10, n = []) *** at top-level: forcomposite(n=2,10,n=[]) *** ^--- *** index read-only: was changed to []. @eprog \subsec{fordiv$(n,X,\var{seq})$}\kbdsidx{fordiv}\label{se:fordiv} Evaluates \var{seq}, where the formal variable $X$ ranges through the divisors of $n$ (see \tet{divisors}, which is used as a subroutine). It is assumed that \kbd{factor} can handle $n$, without negative exponents. Instead of $n$, it is possible to input a factorization matrix, i.e. the output of \kbd{factor(n)}. This routine uses \kbd{divisors} as a subroutine, then loops over the divisors. In particular, if $n$ is an integer, divisors are sorted by increasing size. To avoid storing all divisors, possibly using a lot of memory, the following (much slower) routine loops over the divisors using essentially constant space: \bprog FORDIV(N)= { my(P, E); P = factor(N); E = P[,2]; P = P[,1]; forvec( v = vector(#E, i, [0,E[i]]), X = factorback(P, v) \\ ... ); } ? for(i=1,10^5, FORDIV(i)) time = 3,445 ms. ? for(i=1,10^5, fordiv(i, d, )) time = 490 ms. @eprog \subsec{forell$(E,a,b,\var{seq})$}\kbdsidx{forell}\label{se:forell} Evaluates \var{seq}, where the formal variable $E = [\var{name}, M, G]$ ranges through all elliptic curves of conductors from $a$ to $b$. In this notation \var{name} is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the Mordell-Weil group $E(\Q)$. \bprog ? forell(E, 1, 500, my([name,M,G] = E); \ if (#G > 1, print(name))) 389a1 433a1 446d1 @eprog\noindent The \tet{elldata} database must be installed and contain data for the specified conductors. \synt{forell}{void *data, long (*call)(void*,GEN), long a, long b}. \subsec{forpart$(X=k,\var{seq},\{a=k\},\{n=k\})$}\kbdsidx{forpart}\label{se:forpart} Evaluate \var{seq} over the partitions $X=[x_1,\dots x_n]$ of the integer $k$, i.e.~increasing sequences $x_1\leq x_2\dots \leq x_n$ of sum $x_1+\dots + x_n=k$. By convention, $0$ admits only the empty partition and negative numbers have no partitions. A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order: \bprog ? forpart(X=3, print(X)) Vecsmall([3]) Vecsmall([1, 2]) Vecsmall([1, 1, 1]) @eprog\noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case $X$ is of constant length $\var{nmax}$. \bprog \\ at most 3 non-zero parts, all <= 4 ? forpart(v=5,print(Vec(v)),4,3) [1, 4] [2, 3] [1, 1, 3] [1, 2, 2] \\ between 2 and 4 parts less than 5, fill with zeros ? forpart(v=5,print(Vec(v)),[0,5],[2,4]) [0, 0, 1, 4] [0, 0, 2, 3] [0, 1, 1, 3] [0, 1, 2, 2] [1, 1, 1, 2] @eprog\noindent The behavior is unspecified if $X$ is modified inside the loop. \synt{forpart}{void *data, long (*call)(void*,GEN), long k, GEN a, GEN n}. \subsec{forprime$(p=a,\{b\},\var{seq})$}\kbdsidx{forprime}\label{se:forprime} Evaluates \var{seq}, where the formal variable $p$ ranges over the prime numbers between the real numbers $a$ to $b$, including $a$ and $b$ if they are prime. More precisely, the value of $p$ is incremented to \kbd{nextprime($p$ + 1)}, the smallest prime strictly larger than $p$, at the end of each iteration. Nothing is done if $a>b$. \bprog ? forprime(p = 4, 10, print(p)) 5 7 @eprog\noindent Omitting $b$ means we will run through all primes $\geq a$, starting an infinite loop; it is expected that the user will break out of the loop himself at some point, using \kbd{break} or \kbd{return}. Note that the value of $p$ cannot be modified within \var{seq}: \bprog ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. @eprog \subsec{forstep$(X=a,b,s,\var{seq})$}\kbdsidx{forstep}\label{se:forstep} Evaluates \var{seq}, where the formal variable $X$ goes from $a$ to $b$, in increments of $s$. Nothing is done if $s>0$ and $a>b$ or if $s<0$ and $a$), 2 (\typ{GEN}): a numerical limit $l$ bounding the allowed range, 3 (\kbd{GEN}): the index $x$. It satisfies $x$ \var{op} $l$. \item \kbd{"e\_DOMAIN"}. An argument is not in the function's domain. \var{E} has five components, 1 (\typ{STR}): the function name, 2 (\typ{STR}): the mathematical name of the out-of-domain argument 3 (\typ{STR}): an operator $\var{op}$ describing the domain error, 4 (\typ{GEN}): the numerical limit $l$ describing the domain error, 5 (\kbd{GEN}): the out-of-domain argument $x$. The argument satisfies $x$ \var{op} $l$, which prevents it from belonging to the function's domain. \item \kbd{"e\_MAXPRIME"}. A function using the precomputed list of prime numbers ran out of primes. \var{E} has one component, 1 (\typ{INT}): the requested prime bound, which overflowed \kbd{primelimit} or $0$ (bound is unknown). \item \kbd{"e\_MEM"}. A call to \tet{pari_malloc} or \tet{pari_realloc} failed. \var{E} has no component. \item \kbd{"e\_OVERFLOW"}. An object in function $s$ becomes too large to be represented within PARI's hardcoded limits. (As in \kbd{2\pow2\pow2\pow10} or \kbd{exp(1e100)}, which overflow in \kbd{lg} and \kbd{expo}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_PREC"}. Function $s$ fails because input accuracy is too low. (As in \kbd{floor(1e100)} at default accuracy.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_STACK"}. The PARI stack overflows. \var{E} has no component. \misctitle{Errors triggered intentionally} \item \kbd{"e\_ALARM"}. A timeout, generated by the \tet{alarm} function. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_USER"}. A user error, as triggered by \tet{error}($g_1,\dots,g_n)$. \var{E} has one component, 1 (\typ{VEC}): the vector of $n$ arguments given to \kbd{error}. \misctitle{Mathematical errors} \item \kbd{"e\_CONSTPOL"}. An argument of function $s$ is a constant polynomial, which does not make sense. (As in \kbd{galoisinit(Pol(1))}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_COPRIME"}. Function $s$ expected coprime arguments, and did receive $x,y$, which were not. \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_INV"}. Tried to invert a non-invertible object $x$ in function $s$. \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the non-invertible $x$. If $x = \kbd{Mod}(a,b)$ is a \typ{INTMOD} and $a$ is not $0$ mod $b$, this allows to factor the modulus, as \kbd{gcd}$(a,b)$ is a non-trivial divisor of $b$. \item \kbd{"e\_IRREDPOL"}. Function $s$ expected an irreducible polynomial, and did receive $T$, which was not. (As in \kbd{nfinit(x\pow2-1)}.) \var{E} has two component, 1 (\typ{STR}): the function name $s$, 2 (\typ{POL}): the polynomial $x$. \item \kbd{"e\_MISC"}. Generic uncategorized error. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_MODULUS"}. moduli $x$ and $y$ submitted to function $s$ are inconsistent. As in \bprog nfalgtobasis(nfinit(t^3-2), Mod(t,t^2+1) @eprog\noindent \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$, 2: the argument $p$. \item \kbd{"e\_ROOTS0"}. An argument of function $s$ is a zero polynomial, and we need to consider its roots. (As in \kbd{polroots(0)}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_SQRTN"}. Trying to compute an $n$-th root of $x$, which does not exist, in function $s$. (As in \kbd{sqrt(Mod(-1,3))}.) \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the argument $x$. \subsec{next$(\{n=1\})$}\kbdsidx{next}\label{se:next} Interrupts execution of current $seq$, resume the next iteration of the innermost enclosing loop, within the current function call (or top level loop). If $n$ is specified, resume at the $n$-th enclosing loop. If $n$ is bigger than the number of enclosing loops, all enclosing loops are exited. \subsec{return$(\{x=0\})$}\kbdsidx{return}\label{se:return} Returns from current subroutine, with result $x$. If $x$ is omitted, return the \kbd{(void)} value (return no result, like \kbd{print}). \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, \var{seq} is evaluated once (more generally, the condition on $a$ is tested \emph{after} execution of the \var{seq}, not before as in \kbd{while}). \subsec{while$(a,\var{seq})$}\kbdsidx{while}\label{se:while} While $a$ is non-zero, evaluates the expression sequence \var{seq}. The test is made \emph{before} evaluating the $seq$, hence in particular if $a$ is initially equal to zero the \var{seq} will not be evaluated at all. %SECTION: programming/control \section{Programming in GP: other specific functions} \label{se:gp_program} In addition to the general PARI functions, it is necessary to have some functions which will be of use specifically for \kbd{gp}, though a few of these can be accessed under library mode. Before we start describing these, we recall the difference between \emph{strings} and \emph{keywords} (see \secref{se:strings}): the latter don't get expanded at all, and you can type them without any enclosing quotes. The former are dynamic objects, where everything outside quotes gets immediately expanded. \subsec{Strprintf$(\var{fmt},\{x\}*)$}\kbdsidx{Strprintf}\label{se:Strprintf} Returns a string built from the remaining arguments according to the format fmt. The format consists of ordinary characters (not \%), printed unchanged, and conversions specifications. See \kbd{printf}. %\syn{NO} \subsec{addhelp$(\var{sym},\var{str})$}\kbdsidx{addhelp}\label{se:addhelp} Changes the help message for the symbol \kbd{sym}. The string \var{str} is expanded on the spot and stored as the online help for \kbd{sym}. It is recommended to document global variables and user functions in this way, although \kbd{gp} will not protest if you don't. You can attach a help text to an alias, but it will never be shown: aliases are expanded by the \kbd{?} help operator and we get the help of the symbol the alias points to. Nothing prevents you from modifying the help of built-in PARI functions. But if you do, we would like to hear why you needed it! Without \tet{addhelp}, the standard help for user functions consists of its name and definition. \bprog gp> f(x) = x^2; gp> ?f f = (x)->x^2 @eprog\noindent Once addhelp is applied to $f$, the function code is no longer included. It can still be consulted by typing the function name: \bprog gp> addhelp(f, "Square") gp> ?f Square gp> f %2 = (x)->x^2 @eprog The library syntax is \fun{void}{addhelp}{const char *sym, const char *str}. \subsec{alarm$(\{s = 0\},\{\var{code}\})$}\kbdsidx{alarm}\label{se:alarm} If \var{code} is omitted, trigger an \var{e\_ALARM} exception after $s$ seconds, cancelling any previously set alarm; stop a pending alarm if $s = 0$ or is omitted. Otherwise, if $s$ is positive, the function evaluates \var{code}, aborting after $s$ seconds. The return value is the value of \var{code} if it ran to completion before the alarm timeout, and a \typ{ERROR} object otherwise. \bprog ? p = nextprime(10^25); q = nextprime(10^26); N = p*q; ? E = alarm(1, factor(N)); ? type(E) %3 = "t_ERROR" ? print(E) %4 = error("alarm interrupt after 964 ms.") ? alarm(10, factor(N)); \\ enough time %5 = [ 10000000000000000000000013 1] [100000000000000000000000067 1] @eprog\noindent Here is a more involved example: the function \kbd{timefact(N,sec)} below tries to factor $N$ and gives up after \var{sec} seconds, returning a partial factorisation. \bprog \\ Time-bounded partial factorization default(factor_add_primes,1); timefact(N,sec)= { F = alarm(sec, factor(N)); if (type(F) == "t_ERROR", factor(N, 2^24), F); } @eprog\noindent We either return the factorization directly, or replace the \typ{ERROR} result by a simple bounded factorization \kbd{factor(N, 2\pow 24)}. Note the \tet{factor_add_primes} trick: any prime larger than $2^{24}$ discovered while attempting the initial factorization is stored and remembered. When the alarm rings, the subsequent bounded factorization finds 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. \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 ? alias("det", "matdet"); ? det([1,2;3,4]) %1 = -2 @eprog\noindent You are not restricted to ordinary functions, as in the above example: to alias (from/to) member functions, prefix them with `\kbd{\_.}'; to alias operators, use their internal name, obtained by writing \kbd{\_} in lieu of the operators argument: for instance, \kbd{\_!} and \kbd{!\_} are the internal names of the factorial and the logical negation, respectively. \bprog ? alias("mod", "_.mod"); ? alias("add", "_+_"); ? alias("_.sin", "sin"); ? mod(Mod(x,x^4+1)) %2 = x^4 + 1 ? add(4,6) %3 = 10 ? Pi.sin %4 = 0.E-37 @eprog Alias expansion is performed directly by the internal GP compiler. Note that since alias is performed at compilation-time, it does not require any run-time processing, however it only affects GP code compiled \emph{after} the alias command is evaluated. A slower but more flexible alternative is to use variables. Compare \bprog ? fun = sin; ? g(a,b) = intnum(t=a,b,fun(t)); ? g(0, Pi) %3 = 2.0000000000000000000000000000000000000 ? fun = cos; ? g(0, Pi) %5 = 1.8830410776607851098 E-39 @eprog\noindent with \bprog ? alias(fun, sin); ? g(a,b) = intnum(t=a,b,fun(t)); ? g(0,Pi) %2 = 2.0000000000000000000000000000000000000 ? alias(fun, cos); \\ Oops. Does not affect *previous* definition! ? g(0,Pi) %3 = 2.0000000000000000000000000000000000000 ? g(a,b) = intnum(t=a,b,fun(t)); \\ Redefine, taking new alias into account ? g(0,Pi) %5 = 1.8830410776607851098 E-39 @eprog A sample alias file \kbd{misc/gpalias} is provided with the standard distribution. The library syntax is \fun{void}{alias0}{const char *newsym, const char *sym}. \subsec{allocatemem$(\{s=0\})$}\kbdsidx{allocatemem}\label{se:allocatemem} This special operation changes the stack size \emph{after} initialization. $x$ must be a non-negative integer. If $x > 0$, a new stack 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 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 larger expression sequence, e.g \bprog allocatemem(); x = 1; \\@com This will not set \kbd{x}! @eprog\noindent 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 user). In particular, we have the following possibly unexpected behavior: in \bprog read("file.gp"); x = 1 @eprog\noindent were \kbd{file.gp} contains an \kbd{allocatemem} statement, 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 \subsec{apply$(f, A)$}\kbdsidx{apply}\label{se:apply} Apply the \typ{CLOSURE} \kbd{f} to the entries of \kbd{A}. If \kbd{A} is a scalar, return \kbd{f(A)}. If \kbd{A} is a polynomial or power series, apply \kbd{f} on all coefficients. If \kbd{A} is a vector or list, return the elements $f(x)$ where $x$ runs through \kbd{A}. If \kbd{A} is a matrix, return the matrix whose entries are the $f(\kbd{A[i,j]})$. \bprog ? apply(x->x^2, [1,2,3,4]) %1 = [1, 4, 9, 16] ? apply(x->x^2, [1,2;3,4]) %2 = [1 4] [9 16] ? apply(x->x^2, 4*x^2 + 3*x+ 2) %3 = 16*x^2 + 9*x + 4 @eprog\noindent Note that many functions already act componentwise on vectors or matrices, but they almost never act on lists; in this case, \kbd{apply} is a good solution: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? lift(L) *** at top-level: lift(L) *** ^------- *** lift: incorrect type in lift. ? apply(lift, L); %2 = List([1, 2]) @eprog \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? [ lift(x) | x<-L ] %2 = [1, 2] @eprog \synt{genapply}{void *E, GEN (*fun)(void*,GEN), GEN a}. \subsec{default$(\{\var{key}\},\{\var{val}\})$}\kbdsidx{default}\label{se:default} Returns the default corresponding to keyword \var{key}. If \var{val} is present, sets the default to \var{val} first (which is subject to string expansion first). Typing \kbd{default()} (or \b{d}) yields the complete default list as well as their current values. See \secref{se:defaults} for an introduction to GP defaults, \secref{se:gp_defaults} for a list of available defaults, and \secref{se:meta} for some shortcut alternatives. Note that the shortcuts are meant for interactive use and usually display more information than \kbd{default}. The library syntax is \fun{GEN}{default0}{const char *key = NULL, const char *val = NULL}. \subsec{errname$(E)$}\kbdsidx{errname}\label{se:errname} Returns the type of the error message \kbd{E} as a string. The library syntax is \fun{GEN}{errname}{GEN E}. \subsec{error$(\{\var{str}\}*)$}\kbdsidx{error}\label{se:error} Outputs its argument list (each of them interpreted as a string), then interrupts the running \kbd{gp} program, returning to the input prompt. For instance \bprog error("n = ", n, " is not squarefree!") @eprog\noindent % \syn{NO} \subsec{extern$(\var{str})$}\kbdsidx{extern}\label{se:extern} 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. \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. \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}: \bprog my (t = getabstime()); ... print("Time: ", getabstime() - t); @eprog The library syntax is \fun{long}{getabstime}{}. \subsec{getenv$(s)$}\kbdsidx{getenv}\label{se:getenv} Return the value of the environment variable \kbd{s} if it is defined, otherwise return 0. The library syntax is \fun{GEN}{gp_getenv}{const char *s}. \subsec{getheap$()$}\kbdsidx{getheap}\label{se:getheap} 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. The library syntax is \fun{GEN}{getheap}{}. \subsec{getrand$()$}\kbdsidx{getrand}\label{se:getrand} Returns the current value of the seed used by the pseudo-random number generator \tet{random}. Useful mainly for debugging purposes, to reproduce a specific chain of computations. The returned value is technical (reproduces an internal state array), and can only be used as an argument to \tet{setrand}. The library syntax is \fun{GEN}{getrand}{}. \subsec{getstack$()$}\kbdsidx{getstack}\label{se:getstack} Returns the current value of $\kbd{top}-\kbd{avma}$, i.e.~the number of 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 \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}. The library syntax is \fun{long}{gettime}{}. \subsec{global$(\var{list} \var{of} \var{variables})$}\kbdsidx{global}\label{se:global} Obsolete. Scheduled for deletion. % \syn{NO} \subsec{inline$(x,...,z)$}\kbdsidx{inline}\label{se:inline} (Experimental) declare $x,\ldots, z$ as inline variables. Such variables behave like lexically scoped variable (see my()) but with unlimited scope. It is however possible to exit the scope by using \kbd{uninline()}. When used in a GP script, it is recommended to call \kbd{uninline()} before the script's end to avoid inline variables leaking outside the script. \subsec{input$()$}\kbdsidx{input}\label{se:input} Reads a string, interpreted as a GP expression, from the input file, usually standard input (i.e.~the keyboard). If a sequence of expressions is given, the result is the result of the last expression of the sequence. When using this instruction, it is useful to prompt for the string by using the \kbd{print1} function. Note that in the present version 2.19 of \kbd{pari.el}, when using \kbd{gp} under GNU Emacs (see \secref{se:emacs}) one \emph{must} prompt for the string, with a string which ends with the same prompt as any of the previous ones (a \kbd{"? "} will do for instance). \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} \var{code} (see below). If \var{gpname} is omitted, uses \var{name}. If \var{lib} is omitted, all symbols known to \kbd{gp} are available: this includes the whole of \kbd{libpari.so} and possibly others (such as \kbd{libc.so}). Most importantly, \kbd{install} gives you access to all non-static functions defined in the PARI library. For instance, the function \kbd{GEN addii(GEN x, GEN y)} adds two PARI integers, and is not directly accessible under \kbd{gp} (it is eventually called by the \kbd{+} operator of course): \bprog ? install("addii", "GG") ? addii(1, 2) %1 = 3 @eprog\noindent It also allows to add external functions to the \kbd{gp} interpreter. For instance, it makes the function \tet{system} obsolete: \bprog ? install(system, vs, sys,/*omitted*/) ? sys("ls gp*") gp.c gp.h gp_rl.c @eprog\noindent This works because \kbd{system} is part of \kbd{libc.so}, which is linked to \kbd{gp}. It is also possible to compile a shared library yourself and provide it to gp in this way: use \kbd{gp2c}, or do it manually (see the \kbd{modules\_build} variable in \kbd{pari.cfg} for hints). Re-installing a function will print a warning and update the prototype code if needed. However, it will not reload a symbol from the library, even if the latter has been recompiled. \misctitle{Prototype} We only give a simplified description here, covering most functions, but there are many more possibilities. The full documentation is available in \kbd{libpari.dvi}, see \bprog ??prototype @eprog \item First character \kbd{i}, \kbd{l}, \kbd{v} : return type int / long / void. (Default: \kbd{GEN}) \item One letter for each mandatory argument, in the same order as they appear in the argument list: \kbd{G} (\kbd{GEN}), \kbd{\&} (\kbd{GEN*}), \kbd{L} (\kbd{long}), \kbd{s} (\kbd{char *}), \kbd{n} (variable). \item \kbd{p} to supply \kbd{realprecision} (usually \kbd{long prec} in the argument list), \kbd{P} to supply \kbd{seriesprecision} (usually \kbd{long precdl}). \noindent We also have special constructs for optional arguments and default values: \item \kbd{DG} (optional \kbd{GEN}, \kbd{NULL} if omitted), \item \kbd{D\&} (optional \kbd{GEN*}, \kbd{NULL} if omitted), \item \kbd{Dn} (optional variable, $-1$ if omitted), For instance the prototype corresponding to \bprog long issquareall(GEN x, GEN *n = NULL) @eprog\noindent is \kbd{lGD\&}. \misctitle{Caution} This function may not work on all systems, especially when \kbd{gp} has been compiled statically. In that case, the first use of an installed function will provoke a Segmentation Fault (this should never happen with a dynamically linked executable). If you intend to use this function, please check first on some harmless example such as the one above that it works properly on your machine. The library syntax is \fun{void}{gpinstall}{const char *name, const char *code, const char *gpname, const char *lib}. \subsec{kill$(\var{sym})$}\kbdsidx{kill}\label{se:kill} Restores the symbol \kbd{sym} to its ``undefined'' status, and deletes any help messages associated to \kbd{sym} using \kbd{addhelp}. Variable names remain known to the interpreter and keep their former priority: you cannot make a variable ``less important" by killing it! \bprog ? z = y = 1; y %1 = 1 ? kill(y) ? y \\ restored to ``undefined'' status %2 = y ? variable() %3 = [x, y, z] \\ but the variable name y is still known, with y > z ! @eprog\noindent For the same reason, killing a user function (which is an ordinary variable holding a \typ{CLOSURE}) does not remove its name from the list of variable names. If the symbol is associated to a variable --- user functions being an important special case ---, one may use the \idx{quote} operator \kbd{a = 'a} to reset variables to their starting values. However, this will not delete a help message associated to \kbd{a}, and is also slightly slower than \kbd{kill(a)}. \bprog ? x = 1; addhelp(x, "foo"); x %1 = 1 ? x = 'x; x \\ same as 'kill', except we don't delete help. %2 = x ? ?x foo @eprog\noindent On the other hand, \kbd{kill} is the only way to remove aliases and installed functions. \bprog ? alias(fun, sin); ? kill(fun); ? install(addii, GG); ? kill(addii); @eprog The library syntax is \fun{void}{kill0}{const char *sym}. \subsec{print$(\{\var{str}\}*)$}\kbdsidx{print}\label{se:print} Outputs its (string) arguments in raw format, ending with a newline. %\syn{NO} \subsec{print1$(\{\var{str}\}*)$}\kbdsidx{print1}\label{se:print1} Outputs its (string) arguments in raw format, without ending with a newline. Note that you can still embed newlines within your strings, using the \b{n} notation~! %\syn{NO} \subsec{printf$(\var{fmt},\{x\}*)$}\kbdsidx{printf}\label{se:printf} This function is based on the C library command of the same name. It prints its arguments according to the format \var{fmt}, which specifies how subsequent arguments are converted for output. The format is a character string composed of zero or more directives: \item ordinary characters (not \kbd{\%}), printed unchanged, \item conversions specifications (\kbd{\%} followed by some characters) which fetch one argument from the list and prints it according to the specification. More precisely, a conversion specification consists in a \kbd{\%}, one or more optional flags (among \kbd{\#}, \kbd{0}, \kbd{-}, \kbd{+}, ` '), an optional decimal digit string specifying a minimal field width, an optional precision in the form of a period (`\kbd{.}') followed by a decimal digit string, and the conversion specifier (among \kbd{d},\kbd{i}, \kbd{o}, \kbd{u}, \kbd{x},\kbd{X}, \kbd{p}, \kbd{e},\kbd{E}, \kbd{f}, \kbd{g},\kbd{G}, \kbd{s}). \misctitle{The flag characters} The character \kbd{\%} is followed by zero or more of the following flags: \item \kbd{\#}: The value is converted to an ``alternate form''. For \kbd{o} conversion (octal), a \kbd{0} is prefixed to the string. For \kbd{x} and \kbd{X} conversions (hexa), respectively \kbd{0x} and \kbd{0X} are prepended. For other conversions, the flag is ignored. \item \kbd{0}: The value should be zero padded. For \kbd{d}, \kbd{i}, \kbd{o}, \kbd{u}, \kbd{x}, \kbd{X} \kbd{e}, \kbd{E}, \kbd{f}, \kbd{F}, \kbd{g}, and \kbd{G} conversions, the value is padded on the left with zeros rather than blanks. (If the \kbd{0} and \kbd{-} flags both appear, the \kbd{0} flag is ignored.) \item \kbd{-}: The value is left adjusted on the field boundary. (The default is right justification.) The value is padded on the right with blanks, rather than on the left with blanks or zeros. A \kbd{-} overrides a \kbd{0} if both are given. \item \kbd{` '} (a space): A blank is left before a positive number produced by a signed conversion. \item \kbd{+}: A sign (+ or -) is placed before a number produced by a signed conversion. A \kbd{+} overrides a space if both are used. \misctitle{The field width} An optional decimal digit string (whose first digit is non-zero) specifying a \emph{minimum} field width. If the value has fewer characters than the field width, it is padded with spaces on the left (or right, if the left-adjustment flag has been given). In no case does a small field width cause truncation of a field; if the value is wider than the field width, the field is expanded to contain the conversion result. Instead of a decimal digit string, one may write \kbd{*} to specify that the field width is given in the next argument. \misctitle{The precision} An optional precision in the form of a period (`\kbd{.}') followed by a decimal digit string. This gives the number of digits to appear after the radix character for \kbd{e}, \kbd{E}, \kbd{f}, and \kbd{F} conversions, the maximum number of significant digits for \kbd{g} and \kbd{G} conversions, and the maximum number of characters to be printed from an \kbd{s} conversion. Instead of a decimal digit string, one may write \kbd{*} to specify that the field width is given in the next argument. \misctitle{The length modifier} This is ignored under \kbd{gp}, but necessary for \kbd{libpari} programming. Description given here for completeness: \item \kbd{l}: argument is a \kbd{long} integer. \item \kbd{P}: argument is a \kbd{GEN}. \misctitle{The conversion specifier} A character that specifies the type of conversion to be applied. \item \kbd{d}, \kbd{i}: A signed integer. \item \kbd{o}, \kbd{u}, \kbd{x}, \kbd{X}: An unsigned integer, converted to unsigned octal (\kbd{o}), decimal (\kbd{u}) or hexadecimal (\kbd{x} or \kbd{X}) notation. The letters \kbd{abcdef} are used for \kbd{x} conversions; the letters \kbd{ABCDEF} are used for \kbd{X} conversions. \item \kbd{e}, \kbd{E}: The (real) argument is converted in the style \kbd{[ -]d.ddd e[ -]dd}, where there is one digit before the decimal point, and the number of digits after it is equal to the precision; if the precision is missing, use the current \kbd{realprecision} for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. An \kbd{E} conversion uses the letter \kbd{E} rather than \kbd{e} to introduce the exponent. \item \kbd{f}, \kbd{F}: The (real) argument is converted in the style \kbd{[ -]ddd.ddd}, where the number of digits after the decimal point is equal to the precision; if the precision is missing, use the current \kbd{realprecision} for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. If a decimal point appears, at least one digit appears before it. \item \kbd{g}, \kbd{G}: The (real) argument is converted in style \kbd{e} or \kbd{f} (or \kbd{E} or \kbd{F} for \kbd{G} conversions) \kbd{[ -]ddd.ddd}, where the total number of digits printed is equal to the precision; if the precision is missing, use the current \kbd{realprecision}. If the precision is explicitly 0, it is treated as 1. Style \kbd{e} is used when the decimal exponent is $< -4$, to print \kbd{0.}, or when the integer part cannot be decided given the known significant digits, and the \kbd{f} format otherwise. \item \kbd{c}: The integer argument is converted to an unsigned char, and the resulting character is written. \item \kbd{s}: Convert to a character string. If a precision is given, no more than the specified number of characters are written. \item \kbd{p}: Print the address of the argument in hexadecimal (as if by \kbd{\%\#x}). \item \kbd{\%}: A \kbd{\%} is written. No argument is converted. The complete conversion specification is \kbd{\%\%}. \noindent Examples: \bprog ? printf("floor: %d, field width 3: %3d, with sign: %+3d\n", Pi, 1, 2); floor: 3, field width 3: 1, with sign: +2 ? printf("%.5g %.5g %.5g\n",123,123/456,123456789); 123.00 0.26974 1.2346 e8 ? printf("%-2.5s:%2.5s:%2.5s\n", "P", "PARI", "PARIGP"); P :PARI:PARIG \\ min field width and precision given by arguments ? x = 23; y=-1/x; printf("x=%+06.2f y=%+0*.*f\n", x, 6, 2, y); x=+23.00 y=-00.04 \\ minimum fields width 5, pad left with zeroes ? for (i = 2, 5, printf("%05d\n", 10^i)) 00100 01000 10000 100000 \\@com don't truncate fields whose length is larger than the minimum width ? printf("%.2f |%06.2f|", Pi,Pi) 3.14 | 3.14| @eprog\noindent All numerical conversions apply recursively to the entries of vectors and matrices: \bprog ? printf("%4d", [1,2,3]); [ 1, 2, 3] ? printf("%5.2f", mathilbert(3)); [ 1.00 0.50 0.33] [ 0.50 0.33 0.25] [ 0.33 0.25 0.20] @eprog \misctitle{Technical note} Our implementation of \tet{printf} deviates from the C89 and C99 standards in a few places: \item whenever a precision is missing, the current \kbd{realprecision} is used to determine the number of printed digits (C89: use 6 decimals after the radix character). \item in conversion style \kbd{e}, we do not impose that the exponent has at least two digits; we never write a \kbd{+} sign in the exponent; 0 is printed in a special way, always as \kbd{0.E\var{exp}}. \item in conversion style \kbd{f}, we switch to style \kbd{e} if the exponent is greater or equal to the precision. \item in conversion \kbd{g} and \kbd{G}, we do not remove trailing zeros from the fractional part of the result; nor a trailing decimal point; 0 is printed in a special way, always as \kbd{0.E\var{exp}}. %\syn{NO} \subsec{printsep$(\var{sep},\{\var{str}\}*)$}\kbdsidx{printsep}\label{se:printsep} Outputs its (string) arguments in raw format, ending with a newline. Successive entries are separated by \var{sep}: \bprog ? printsep(":", 1,2,3,4) 1:2:3:4 @eprog %\syn{NO} \subsec{printsep1$(\var{sep},\{\var{str}\}*)$}\kbdsidx{printsep1}\label{se:printsep1} Outputs its (string) arguments in raw format, without ending with a newline. Successive entries are separated by \var{sep}: \bprog ? printsep1(":", 1,2,3,4);print("|") 1:2:3:4 @eprog %\syn{NO} \subsec{printtex$(\{\var{str}\}*)$}\kbdsidx{printtex}\label{se:printtex} Outputs its (string) arguments in \TeX\ format. This output can then be used in a \TeX\ manuscript. The printing is done on the standard output. If you want to print it to a file you should use \kbd{writetex} (see there). Another possibility is to enable the \tet{log} default (see~\secref{se:defaults}). You could for instance do:\sidx{logfile} % \bprog default(logfile, "new.tex"); default(log, 1); printtex(result); @eprog %\syn{NO} \subsec{quit$(\{\var{status} = 0\})$}\kbdsidx{quit}\label{se:quit} Exits \kbd{gp} and return to the system with exit status \kbd{status}, a small integer. A non-zero exit status normally indicates abnormal termination. (Note: the system actually sees only \kbd{status} mod $256$, see your man pages for \kbd{exit(3)} or \kbd{wait(2)}). \subsec{read$(\{\var{filename}\})$}\kbdsidx{read}\label{se:read} Reads in the file \var{filename} (subject to string expansion). If \var{filename} is omitted, re-reads the last file that was fed into \kbd{gp}. The return value is the result of the last expression evaluated. If a GP \tet{binary file} is read using this command (see \secref{se:writebin}), the file is loaded and the last object in the file is returned. 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. \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}. \subsec{readvec$(\{\var{filename}\})$}\kbdsidx{readvec}\label{se:readvec} Reads in the file \var{filename} (subject to string expansion). If \var{filename} is omitted, re-reads the last file that was fed into \kbd{gp}. The return value is a vector whose components are the evaluation of all sequences of instructions contained in the file. For instance, if \var{file} contains \bprog 1 2 3 @eprog\noindent then we will get: \bprog ? \r a %1 = 1 %2 = 2 %3 = 3 ? read(a) %4 = 3 ? readvec(a) %5 = [1, 2, 3] @eprog In general a sequence is just a single line, but as usual braces and \kbd{\bs} may be used to enter multiline sequences. The library syntax is \fun{GEN}{gp_readvec_file}{const char *filename}. The underlying library function \fun{GEN}{gp_readvec_stream}{FILE *f} is usually more flexible. \subsec{select$(f, A, \{\fl = 0\})$}\kbdsidx{select}\label{se:select} We first describe the default behavior, when $\fl$ is 0 or omitted. Given a vector or list \kbd{A} and a \typ{CLOSURE} \kbd{f}, \kbd{select} returns the elements $x$ of \kbd{A} such that $f(x)$ is non-zero. In other words, \kbd{f} is seen as a selection function returning a boolean value. \bprog ? select(x->isprime(x), vector(50,i,i^2+1)) %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] ? select(x->(x<100), %) %2 = [2, 5, 17, 37] @eprog\noindent returns the primes of the form $i^2+1$ for some $i\leq 50$, then the elements less than 100 in the preceding result. The \kbd{select} function also applies to a matrix \kbd{A}, seen as a vector of columns, i.e. it selects columns instead of entries, and returns the matrix whose columns are the selected ones. \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? [ x | x <- vector(50,i,i^2+1), isprime(x) ] %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog \noindent If $\fl = 1$, this function returns instead the \emph{indices} of the selected elements, and not the elements themselves (indirect selection): \bprog ? V = vector(50,i,i^2+1); ? select(x->isprime(x), V, 1) %2 = Vecsmall([1, 2, 4, 6, 10, 14, 16, 20, 24, 26, 36, 40]) ? vecextract(V, %) %3 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog\noindent The following function lists the elements in $(\Z/N\Z)^*$: \bprog ? invertibles(N) = select(x->gcd(x,N) == 1, [1..N]) @eprog \noindent Finally \bprog ? select(x->x, M) @eprog\noindent selects the non-0 entries in \kbd{M}. If the latter is a \typ{MAT}, we extract the matrix of non-0 columns. Note that \emph{removing} entries instead of selecting them just involves replacing the selection function \kbd{f} with its negation: \bprog ? select(x->!isprime(x), vector(50,i,i^2+1)) @eprog \synt{genselect}{void *E, long (*fun)(void*,GEN), GEN a}. Also available is \fun{GEN}{genindexselect}{void *E, long (*fun)(void*, GEN), GEN a}, corresponding to $\fl = 1$. \subsec{setrand$(n)$}\kbdsidx{setrand}\label{se:setrand} Reseeds the random number generator using the seed $n$. No value is returned. The seed is either a technical array output by \kbd{getrand}, or a small positive integer, used to generate deterministically a suitable state array. For instance, running a randomized computation starting by \kbd{setrand(1)} twice will generate the exact same output. The library syntax is \fun{void}{setrand}{GEN n}. \subsec{system$(\var{str})$}\kbdsidx{system}\label{se:system} \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 logfile), and control returns to the PARI system. This simply calls the C \kbd{system} command. \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 \emph{obsolete} function \tet{trap}. This function tries to evaluate \var{seq}, trapping runtime error $e$, that is effectively preventing it from aborting computations in the usual way; the recovery sequence \var{rec} is executed if the error occurs and the evaluation of \var{rec} becomes the result of the command. If $e$ is omitted, all exceptions are trapped. See \secref{se:errorrec} for an introduction to error recovery under \kbd{gp}. \bprog ? \\@com trap division by 0 ? inv(x) = trap (e_INV, INFINITY, 1/x) ? inv(2) %1 = 1/2 ? inv(0) %2 = INFINITY @eprog\noindent Note that \var{seq} is effectively evaluated up to the point that produced the error, and the recovery sequence is evaluated starting from that same context, it does not "undo" whatever happened in the other branch (restore the evaluation context): \bprog ? x = 1; trap (, /* recover: */ x, /* try: */ x = 0; 1/x) %1 = 0 @eprog \misctitle{Note} The interface is currently not adequate for trapping individual exceptions. In the current version \vers, the following keywords are recognized, but the name list will be expanded and changed in the future (all library mode errors can be trapped: it's a matter of defining the keywords to \kbd{gp}): \kbd{e\_ALARM}: alarm time-out \kbd{e\_ARCH}: not available on this architecture or operating system \kbd{e\_STACK}: the PARI stack overflows \kbd{e\_INV}: impossible inverse \kbd{e\_IMPL}: not yet implemented \kbd{e\_OVERFLOW}: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle). \kbd{e\_SYNTAX}: syntax error \kbd{e\_MISC}: miscellaneous error \kbd{e\_TYPE}: wrong type \kbd{e\_USER}: user error (from the \kbd{error} function) The library syntax is \fun{GEN}{trap0}{const char *e = NULL, GEN rec = NULL, GEN seq = NULL}. \subsec{type$(x)$}\kbdsidx{type}\label{se:type} This is useful only under \kbd{gp}. Returns the internal type name of the PARI object $x$ as a string. Check out existing type names with the metacommand \b{t}. For example \kbd{type(1)} will return "\typ{INT}". The library syntax is \fun{GEN}{type0}{GEN x}. The macro \kbd{typ} is usually simpler to use since it returns a \kbd{long} that can easily be matched with the symbols \typ{*}. The name \kbd{type} was avoided since it is a reserved identifier for some compilers. \subsec{uninline$()$}\kbdsidx{uninline}\label{se:uninline} (Experimental) Exit the scope of all current \kbd{inline} variables. \subsec{version$()$}\kbdsidx{version}\label{se:version} Returns the current version number as a \typ{VEC} with three integer components (major version number, minor version number and patchlevel); if your sources were obtained through our version control system, this will be followed by further more precise arguments, including e.g.~a~\kbd{git} \emph{commit hash}. This function is present in all versions of PARI following releases 2.3.4 (stable) and 2.4.3 (testing). Unless you are working with multiple development versions, you probably only care about the 3 first numeric components. In any case, the \kbd{lex} function offers a clever way to check against a particular version number, since it will compare each successive vector entry, numerically or as strings, and will not mind if the vectors it compares have different lengths: \bprog if (lex(version(), [2,3,5]) >= 0, \\ code to be executed if we are running 2.3.5 or more recent. , \\ compatibility code ); @eprog\noindent On a number of different machines, \kbd{version()} could return either of \bprog %1 = [2, 3, 4] \\ released version, stable branch %1 = [2, 4, 3] \\ released version, testing branch %1 = [2, 6, 1, 15174, ""505ab9b"] \\ development @eprog In particular, if you are only working with released versions, the first line of the gp introductory message can be emulated by \bprog [M,m,p] = version(); printf("GP/PARI CALCULATOR Version %s.%s.%s", M,m,p); @eprog\noindent If you \emph{are} working with many development versions of PARI/GP, the 4th and/or 5th components can be profitably included in the name of your logfiles, for instance. \misctitle{Technical note} For development versions obtained via \kbd{git}, the 4th and 5th components are liable to change eventually, but we document their current meaning for completeness. The 4th component counts the number of reachable commits in the branch (analogous to \kbd{svn}'s revision number), and the 5th is the \kbd{git} commit hash. In particular, \kbd{lex} comparison still orders correctly development versions with respect to each others or to released versions (provided we stay within a given branch, e.g. \kbd{master})! The library syntax is \fun{GEN}{pari_version}{}. \subsec{warning$(\{\var{str}\}*)$}\kbdsidx{warning}\label{se:warning} Outputs the message ``user warning'' and the argument list (each of them interpreted as a string). If colors are enabled, this warning will be in a different color, making it easy to distinguish. \bprog warning(n, " is very large, this might take a while.") @eprog % \syn{NO} \subsec{whatnow$(\var{key})$}\kbdsidx{whatnow}\label{se:whatnow} If keyword \var{key} is the name of a function that was present in GP version 1.39.15 or lower, outputs the new function name and syntax, if it changed at all ($387$ out of $560$ did). \subsec{write$(\var{filename},\{\var{str}\}*)$}\kbdsidx{write}\label{se:write} Writes (appends) to \var{filename} the remaining arguments, and appends a newline (same output as \kbd{print}). %\syn{NO} \subsec{write1$(\var{filename},\{\var{str}\}*)$}\kbdsidx{write1}\label{se:write1} Writes (appends) to \var{filename} the remaining arguments without a trailing newline (same output as \kbd{print1}). %\syn{NO} \subsec{writebin$(\var{filename},\{x\})$}\kbdsidx{writebin}\label{se:writebin} Writes (appends) to \var{filename} the object $x$ in binary format. This format is not human readable, but contains the exact internal structure of $x$, and is much faster to save/load than a string expression, as would be produced by \tet{write}. The binary file format includes a magic number, so that such a file can be recognized and correctly input by the regular \tet{read} or \b{r} function. If saved objects refer to (polynomial) variables that are not defined in the new session, they will be displayed in a funny way (see \secref{se:kill}). Installed functions and history objects can not be saved via this function. If $x$ is omitted, saves all user variables from the session, together with their names. Reading such a ``named object'' back in a \kbd{gp} session will set the corresponding user variable to the saved value. E.g after \bprog x = 1; writebin("log") @eprog\noindent reading \kbd{log} into a clean session will set \kbd{x} to $1$. The relative variables priorities (see \secref{se:priority}) of new variables set in this way remain the same (preset variables retain their former priority, but are set to the new value). In particular, reading such a session log into a clean session will restore all variables exactly as they were in the original one. Just as a regular input file, a binary file can be compressed using \tet{gzip}, provided the file name has the standard \kbd{.gz} extension.\sidx{binary file} In the present implementation, the binary files are architecture dependent and compatibility with future versions of \kbd{gp} is not guaranteed. Hence binary files should not be used for long term storage (also, they are larger and harder to compress than text files). The library syntax is \fun{void}{gpwritebin}{const char *filename, GEN x = NULL}. \subsec{writetex$(\var{filename},\{\var{str}\}*)$}\kbdsidx{writetex}\label{se:writetex} As \kbd{write}, in \TeX\ format. %\syn{NO} %SECTION: programming/specific \section{Parallel programming} These function are only available if PARI was configured using \kbd{Configure --mt=\dots}. Two multithread interfaces are supported: \item POSIX threads \item Message passing interface (MPI) As a rule, POSIX threads are well-suited for single systems, while MPI is used by most clusters. However the parallel GP interface does not depend on the chosen multithread interface: a properly written GP program will work identically with both. \subsec{parapply$(f, x)$}\kbdsidx{parapply}\label{se:parapply} Parallel evaluation of \kbd{f} on the elements of \kbd{x}. The function \kbd{f} must not access global variables or variables declared with local(), and must be free of side effects. \bprog parapply(factor,[2^256 + 1, 2^193 - 1]) @eprog factors $2^{256} + 1$ and $2^{193} - 1$ in parallel. \bprog { my(E = ellinit([1,3]), V = vector(12,i,randomprime(2^200))); parapply(p->ellcard(E,p), V) } @eprog computes the order of $E(\F_p)$ for $12$ random primes of $200$ bits. The library syntax is \fun{GEN}{parapply}{GEN f, GEN x}. \subsec{pareval$(x)$}\kbdsidx{pareval}\label{se:pareval} Parallel evaluation of the elements of \kbd{x}, where \kbd{x} is a vector of closures. The closures must be of arity $0$, must not access global variables or variables declared with \kbd{local} and must be free of side effects. The library syntax is \fun{GEN}{pareval}{GEN x}. \subsec{parfor$(i=a,\{b\},\var{expr1},\{j\},\{\var{expr2}\})$}\kbdsidx{parfor}\label{se:parfor} Evaluates the sequence \kbd{expr2} (dependent on $i$ and $j$) for $i$ between $a$ and $b$, in random order, computed in parallel; in this sequence \kbd{expr2}, substitute the variable $j$ by the value of \kbd{expr1} (dependent on $i$). If $b$ is omitted, the loop will not stop. It is allowed for \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}; however in that case, \kbd{expr2} will still be evaluated for all remaining value of $i$ less than the current one, unless a subsequent \kbd{break}/\kbd{next}/\kbd{return} happens. %\syn{NO} \subsec{parforprime$(p=a,\{b\},\var{expr1},\{j\},\{\var{expr2}\})$}\kbdsidx{parforprime}\label{se:parforprime} Evaluates the sequence \kbd{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 \kbd{expr1} (dependent on $p$). If $b$ is omitted, the loop will not stop. It is allowed fo \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}, however in that case, \kbd{expr2} will still be evaluated for all remaining value of $p$ less than the current one, unless a subsequent \kbd{break}/\kbd{next}/\kbd{return} happens. %\syn{NO} \subsec{parselect$(f, A, \{\fl = 0\})$}\kbdsidx{parselect}\label{se:parselect} Selects elements of $A$ according to the selection function $f$, done in parallel. If \fl is $1$, return the indices of those elements (indirect selection) The function \kbd{f} must not access global variables or variables declared with local(), and must be free of side effects. The library syntax is \fun{GEN}{parselect}{GEN f, GEN A, long flag }. \subsec{parsum$(i=a,b,\var{expr},\{x\})$}\kbdsidx{parsum}\label{se:parsum} Sum of expression \var{expr}, initialized at $x$, the formal parameter going from $a$ to $b$, evaluated in parallel in random order. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog parsum(i=1,1000,ispseudoprime(2^prime(i)-1)) @eprog returns the numbers of prime numbers among the first $1000$ Mersenne numbers. %\syn{NO} \subsec{parvector$(N,i,\var{expr})$}\kbdsidx{parvector}\label{se:parvector} As \kbd{vector(N,i,expr)} but the evaluations of \kbd{expr} are done in parallel. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog parvector(10,i,quadclassunit(2^(100+i)+1).no) @eprog\noindent computes the class numbers in parallel. %\syn{NO} %SECTION: programming/parallel \section{GP defaults} \label{se:gp_defaults} This section documents the GP defaults \subsec{TeXstyle}\kbdsidx{TeXstyle}\label{se:def,TeXstyle} The bits of this default allow \kbd{gp} to use less rigid TeX formatting commands in the logfile. This default is only taken into account when $\kbd{log} = 3$. The bits of \kbd{TeXstyle} have the following meaning 2: insert \kbd{\bs right} / \kbd{\bs left} pairs where appropriate. 4: insert discretionary breaks in polynomials, to enhance the probability of a good line break. The default value is \kbd{0}. \subsec{breakloop}\kbdsidx{breakloop}\label{se:def,breakloop} If true, enables the ``break loop'' debugging mode, see \secref{se:break_loop}. The default value is \kbd{1} if we are running an interactive \kbd{gp} session, and \kbd{0} otherwise. \subsec{colors}\kbdsidx{colors}\label{se:def,colors} This default is only usable if \kbd{gp} is running within certain color-capable terminals. For instance \kbd{rxvt}, \kbd{color\_xterm} and modern versions of \kbd{xterm} under X Windows, or standard Linux/DOS text consoles. It causes \kbd{gp} to use a small palette of colors for its output. With xterms, the colormap used corresponds to the resources \kbd{Xterm*color$n$} where $n$ ranges from $0$ to $15$ (see the file \kbd{misc/color.dft} for an example). Accepted values for this default are strings \kbd{"$a_1$,\dots,$a_k$"} where $k\le7$ and each $a_i$ is either \noindent\item the keyword \kbd{no} (use the default color, usually black on transparent background) \noindent\item an integer between 0 and 15 corresponding to the aforementioned colormap \noindent\item a triple $[c_0,c_1,c_2]$ where $c_0$ stands for foreground color, $c_1$ for background color, and $c_2$ for attributes (0 is default, 1 is bold, 4 is underline). The output objects thus affected are respectively error messages, history numbers, prompt, input line, output, help messages, timer (that's seven of them). If $k < 7$, the remaining $a_i$ are assumed to be $no$. For instance % \bprog default(colors, "9, 5, no, no, 4") @eprog \noindent typesets error messages in color $9$, history numbers in color $5$, output in color $4$, and does not affect the rest. A set of default colors for dark (reverse video or PC console) and light backgrounds respectively is activated when \kbd{colors} is set to \kbd{darkbg}, resp.~\kbd{lightbg} (or any proper prefix: \kbd{d} is recognized as an abbreviation for \kbd{darkbg}). A bold variant of \kbd{darkbg}, called \kbd{boldfg}, is provided if you find the former too pale. \emacs In the present version, this default is incompatible with PariEmacs. Changing it will just fail silently (the alternative would be to display escape sequences as is, since Emacs will refuse to interpret them). You must customize color highlighting from the PariEmacs side, see its 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}. \subsec{datadir}\kbdsidx{datadir}\label{se:def,datadir} The name of directory containing the optional data files. For now, this includes the \kbd{elldata}, \kbd{galdata}, \kbd{galpol}, \kbd{seadata} packages. The default value is \datadir (the location of installed precomputed data, can be specified via \kbd{Configure --datadir=}). \subsec{debug}\kbdsidx{debug}\label{se:def,debug} Debugging level. If it is non-zero, some extra messages may be printed, according to what is going on (see~\b{g}). The default value is \kbd{0} (no debugging messages). \subsec{debugfiles}\kbdsidx{debugfiles}\label{se:def,debugfiles} File usage debugging level. If it is non-zero, \kbd{gp} will print information on file descriptors in use, from PARI's point of view (see~\b{gf}). The default value is \kbd{0} (no debugging messages). \subsec{debugmem}\kbdsidx{debugmem}\label{se:def,debugmem} Memory debugging level. If it is non-zero, \kbd{gp} will regularly print information on memory usage. If it's greater than 2, it will indicate any important garbage collecting and the function it is taking place in (see~\b{gm}). \noindent {\bf Important Note:} As it noticeably slows down the performance, the first functionality (memory usage) is disabled if you're not running a version compiled for debugging (see Appendix~A). The default value is \kbd{0} (no debugging messages). \subsec{echo}\kbdsidx{echo}\label{se:def,echo} This toggle is either 1 (on) or 0 (off). When \kbd{echo} mode is on, each command is reprinted before being executed. This can be useful when reading a file with the \b{r} or \kbd{read} commands. For example, it is turned on at the beginning of the test files used to check whether \kbd{gp} has been built correctly (see \b{e}). The default value is \kbd{0} (no echo). \subsec{factor\_add\_primes}\kbdsidx{def,factor_add_primes}\label{se:def,factor_add_primes} This toggle is either 1 (on) or 0 (off). If on, the integer factorization machinery calls \tet{addprimes} on primes factor that were difficult to find (larger than $2^24$), so they are automatically tried first in other factorizations. If a routine is performing (or has performed) a factorization and is interrupted by an error or via Control-C, this lets you recover the prime factors already found. The downside is that a huge \kbd{addprimes} table unrelated to the current computations will slow down arithmetic functions relying on integer factorization; one should then empty the table using \tet{removeprimes}. The default value is \kbd{0}. \subsec{factor\_proven}\kbdsidx{def,factor_proven}\label{se:def,factor_proven} This toggle is either 1 (on) or 0 (off). By default, the factors output by the integer factorization machinery are only pseudo-primes, not proven primes. If this toggle is set, a primality proof is done for each factor and all results depending on integer factorization are fully proven. This flag does not affect partial factorization when it is explicitly requested. It also does not affect the private table managed by \tet{addprimes}: its entries are included as is in factorizations, without being tested for primality. The default value is \kbd{0}. \subsec{format}\kbdsidx{format}\label{se:def,format} Of the form x$.n$, where x (conversion style) is a letter in $\{\kbd{e},\kbd{f},\kbd{g}\}$, and $n$ (precision) is an integer; this affects the way real numbers are printed: \item If the conversion style is \kbd{e}, real numbers are printed in \idx{scientific format}, always with an explicit exponent, e.g.~\kbd{3.3 E-5}. \item In style \kbd{f}, real numbers are generally printed in \idx{fixed floating point format} without exponent, e.g.~\kbd{0.000033}. A large real number, whose integer part is not well defined (not enough significant digits), is printed in style~\kbd{e}. For instance \kbd{10.\pow 100} known to ten significant digits is always printed in style \kbd{e}. \item In style \kbd{g}, non-zero real numbers are printed in \kbd{f} format, except when their decimal exponent is $< -4$, in which case they are printed in \kbd{e} format. Real zeroes (of arbitrary exponent) are printed in \kbd{e} format. The precision $n$ is the number of significant digits printed for real numbers, except if $n<0$ where all the significant digits will be printed (initial default 28, or 38 for 64-bit machines). For more powerful formatting possibilities, see \tet{printf} and \tet{Strprintf}. The default value is \kbd{"g.28"} and \kbd{"g.38"} on 32-bit and 64-bit machines, respectively. \subsec{graphcolormap}\kbdsidx{graphcolormap}\label{se:def,graphcolormap} A vector of colors, to be used by hi-res graphing routines. Its length is arbitrary, but it must contain at least 3 entries: the first 3 colors are used for background, frame/ticks and axes respectively. All colors in the colormap may be freely used in \tet{plotcolor} calls. A color is either given as in the default by character strings or by an RGB code. For valid character strings, see the standard \kbd{rgb.txt} file in X11 distributions, where we restrict to lowercase letters and remove all whitespace from color names. An RGB code is a vector with 3 integer entries between 0 and 255. For instance \kbd{[250, 235, 215]} and \kbd{"antiquewhite"} represent the same color. RGB codes are cryptic but often easier to generate. The default value is [\kbd{"white"}, \kbd{"black"}, \kbd{"blue"}, \kbd{"violetred"}, \kbd{"red"}, \kbd{"green"}, \kbd{"grey"}, \kbd{"gainsboro"}]. \subsec{graphcolors}\kbdsidx{graphcolors}\label{se:def,graphcolors} Entries in the \tet{graphcolormap} that will be used to plot multi-curves. The successive curves are drawn in colors \kbd{graphcolormap[graphcolors[1]]}, \kbd{graphcolormap[graphcolors[2]]}, \dots cycling when the \kbd{graphcolors} list is exhausted. The default value is \kbd{[4,5]}. \subsec{help}\kbdsidx{help}\label{se:def,help} Name of the external help program to use from within \kbd{gp} when extended help is invoked, usually through a \kbd{??} or \kbd{???} request (see \secref{se:exthelp}), or \kbd{M-H} under readline (see \secref{se:readline}). The default value is the path to the \kbd{gphelp} script we install. \subsec{histfile}\kbdsidx{histfile}\label{se:def,histfile} Name of a file where \kbd{gp} will keep a history of all \emph{input} commands (results are omitted). If this file exists when the value of \kbd{histfile} changes, it is read in and becomes part of the session history. Thus, setting this default in your gprc saves your readline history between sessions. Setting this default to the empty string \kbd{""} changes it to \kbd{$<$undefined$>$} The default value is \kbd{$<$undefined$>$} (no history file). \subsec{histsize}\kbdsidx{histsize}\label{se:def,histsize} \kbd{gp} keeps a history of the last \kbd{histsize} results computed so far, which you can recover using the \kbd{\%} notation (see \secref{se:history}). When this number is exceeded, the oldest values are erased. Tampering with this default is the only way to get rid of the ones you do not need anymore. The default value is \kbd{5000}. \subsec{lines}\kbdsidx{lines}\label{se:def,lines} If set to a positive value, \kbd{gp} prints at most that many lines from each result, terminating the last line shown with \kbd{[+++]} if further material has been suppressed. The various \kbd{print} commands (see \secref{se:gp_program}) are unaffected, so you can always type \kbd{print(\%)} or \b{a} to view the full result. If the actual screen width cannot be determined, a ``line'' is assumed to be 80 characters long. The default value is \kbd{0}. \subsec{linewrap}\kbdsidx{linewrap}\label{se:def,linewrap} If set to a positive value, \kbd{gp} wraps every single line after printing that many characters. The default value is \kbd{0} (unset). \subsec{log}\kbdsidx{log}\label{se:def,log} This can be either 0 (off) or 1, 2, 3 (on, see below for the various modes). When logging mode is turned on, \kbd{gp} opens a log file, whose exact name is determined by the \kbd{logfile} default. Subsequently, all the commands and results will be written to that file (see \b{l}). In case a file with this precise name already existed, it will not be erased: your data will be \emph{appended} at the end. The specific positive values of \kbd{log} have the following meaning 1: plain logfile 2: emit color codes to the logfile (if \kbd{colors} is set). 3: write LaTeX output to the logfile (can be further customized using \tet{TeXstyle}). The default value is \kbd{0}. \subsec{logfile}\kbdsidx{logfile}\label{se:def,logfile} Name of the log file to be used when the \kbd{log} toggle is on. Environment and time expansion are performed. The default value is \kbd{"pari.log"}. \subsec{nbthreads}\kbdsidx{nbthreads}\label{se:def,nbthreads} Number of threads to use for parallel computing. The exact meaning an default depend on the \kbd{mt} engine used: \item \kbd{single}: not used (always one thread). \item \kbd{pthread}: number of threads (unlimited, default: number of core) \item \kbd{mpi}: number of MPI process to use (limited to the number allocated by \kbd{mpirun}, default: use all allocated process). \subsec{new\_galois\_format}\kbdsidx{def,new_galois_format}\label{se:def,new_galois_format} This toggle is either 1 (on) or 0 (off). If on, the \tet{polgalois} command will use a different, more consistent, naming scheme for Galois groups. This default is provided to ensure that scripts can control this behavior and do not break unexpectedly. The default value is \kbd{0}. This value will change to $1$ (set) in the next major version. \subsec{output}\kbdsidx{output}\label{se:def,output} There are three possible values: 0 (=~\var{raw}), 1 (=~\var{prettymatrix}), or 3 (=~\var{external} \var{prettyprint}). This means that, independently of the default \kbd{format} for reals which we explained above, you can print results in three ways: \item \tev{raw format}, i.e.~a format which is equivalent to what you input, including explicit multiplication signs, and everything typed on a line instead of two dimensional boxes. This can have several advantages, for instance it allows you to pick the result with a mouse or an editor, and to paste it somewhere else. \item \tev{prettymatrix format}: this is identical to raw format, except that matrices are printed as boxes instead of horizontally. This is prettier, but takes more space and cannot be used for input. Column vectors are still printed horizontally. \item \tev{external prettyprint}: pipes all \kbd{gp} output in TeX format to an external prettyprinter, according to the value of \tet{prettyprinter}. The default script (\tet{tex2mail}) converts its input to readable two-dimensional text. Independently of the setting of this default, an object can be printed in any of the three formats at any time using the commands \b{a} and \b{m} and \b{B} respectively. 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. The default value is 4M, resp.~8M on a 32-bit, resp.~64-bit machine. \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). When asked to read a file whose name is not given by an absolute path (does not start with \kbd{/}, \kbd{./} or \kbd{../}), \kbd{gp} will look for it in these directories, in the order they were written in \kbd{path}. Here, as usual, \kbd{.} means the current directory, and \kbd{..} its immediate parent. Environment expansion is performed. The default value is \kbd{".:\til:\til/gp"} on UNIX systems, \kbd{".;C:\bs;C:\bs GP"} on DOS, OS/2 and Windows, and \kbd{"."} otherwise. \subsec{prettyprinter}\kbdsidx{prettyprinter}\label{se:def,prettyprinter} The name of an external prettyprinter to use when \kbd{output} is~3 (alternate prettyprinter). Note that the default \tet{tex2mail} looks much nicer than the built-in ``beautified format'' ($\kbd{output} = 2$). The default value is \kbd{"tex2mail -TeX -noindent -ragged -by\_par"}. \subsec{primelimit}\kbdsidx{primelimit}\label{se:def,primelimit} \kbd{gp} precomputes a list of all primes less than \kbd{primelimit} at initialization time, and can build fast sieves on demand to quickly iterate over primes up to the \emph{square} of \kbd{primelimit}. These are used by many arithmetic functions, usually for trial division purposes. The maximal value is $2^{32} - 2049$ (resp $2^{64} - 2049$) on a 32-bit (resp.~64-bit) machine, but values beyond $10^8$, allowing to iterate over primes up to $10^{16}$, do not seem useful. Since almost all arithmetic functions eventually require some table of prime numbers, PARI guarantees that the first 6547 primes, up to and including 65557, are precomputed, even if \kbd{primelimit} is $1$. This default is only used on startup: changing it will not recompute a new table. \misctitle{Deprecated feature} \kbd{primelimit} was used in some situations by algebraic number theory functions using the \tet{nf_PARTIALFACT} flag (\tet{nfbasis}, \tet{nfdisc}, \tet{nfinit}, \dots): this assumes that all primes $p > \kbd{primelimit}$ have a certain property (the equation order is $p$-maximal). This is never done by default, and must be explicitly set by the user of such functions. Nevertheless, these functions now provide a more flexible interface, and their use of the global default \kbd{primelimit} is deprecated. \misctitle{Deprecated feature} \kbd{factor(N, 0)} was used to partially factor integers by removing all prime factors $\leq$ \kbd{primelimit}. Don't use this, supply an explicit bound: \kbd{factor(N, bound)}, which avoids relying on an unpredictable global variable. The default value is \kbd{500k}. \subsec{prompt}\kbdsidx{prompt}\label{se:def,prompt} A string that will be printed as prompt. Note that most usual escape sequences are available there: \b{e} for Esc, \b{n} for Newline, \dots, \kbd{\bs\bs} for \kbd{\bs}. Time expansion is performed. This string is sent through the library function \tet{strftime} (on a Unix system, you can try \kbd{man strftime} at your shell prompt). This means that \kbd{\%} constructs have a special meaning, usually related to the time and date. For instance, \kbd{\%H} = hour (24-hour clock) and \kbd{\%M} = minute [00,59] (use \kbd{\%\%} to get a real \kbd{\%}). If you use \kbd{readline}, escape sequences in your prompt will result in display bugs. If you have a relatively recent \kbd{readline} (see the comment at the end of \secref{se:def,colors}), you can brace them with special sequences (\kbd{\bs[} and \kbd{\bs]}), and you will be safe. If these just result in extra spaces in your prompt, then you'll have to get a more recent \kbd{readline}. See the file \kbd{misc/gprc.dft} for an example. \emacs {\bf Caution}: PariEmacs needs to know about the prompt pattern to separate your input from previous \kbd{gp} results, without ambiguity. It is not a trivial problem to adapt automatically this regular expression to an arbitrary prompt (which can be self-modifying!). See PariEmacs's documentation. The default value is \kbd{"? "}. \subsec{prompt\_cont}\kbdsidx{def,prompt_cont}\label{se:def,prompt_cont} A string that will be printed to prompt for continuation lines (e.g. in between braces, or after a line-terminating backslash). Everything that applies to \kbd{prompt} applies to \kbd{prompt\_cont} as well. The default value is \kbd{""}. \subsec{psfile}\kbdsidx{psfile}\label{se:def,psfile} Name of the default file where \kbd{gp} is to dump its PostScript drawings (these are appended, so that no previous data are lost). Environment and time expansion are performed. The default value is \kbd{"pari.ps"}. \subsec{readline}\kbdsidx{readline}\label{se:def,readline} Switches readline line-editing facilities on and off. This may be useful if you are running \kbd{gp} in a Sun \tet{cmdtool}, which interacts badly with readline. Of course, until readline is switched on again, advanced editing features like automatic completion and editing history are not available. The default value is \kbd{1}. \subsec{realprecision}\kbdsidx{realprecision}\label{se:def,realprecision} The number of significant digits used to convert exact inputs given to transcendental functions (see \secref{se:trans}), or to create absolute floating point constants (input as \kbd{1.0} or \kbd{Pi} for instance). Unless you tamper with the \tet{format} default, this is also the number of significant digits used to print a \typ{REAL} number; \kbd{format} will override this latter behaviour, and allow you to have a large internal precision while outputting few digits for instance. Note that PARI's internal precision works on a word basis (by increments of 32 or 64 bits), hence may be a little larger than the number of decimal digits you expected. For instance to get 2 decimal digits you need one word of precision which, on a 64-bit machine, actually gives you 19 digits ($19 < \log_{10}(2^{64}) < 20$). The value returned when typing \kbd{default(realprecision)} is the internal number of significant digits, not the number of printed digits: \bprog ? default(realprecision, 2) realprecision = 19 significant digits (2 digits displayed) ? default(realprecision) %1 = 19 @eprog The default value is \kbd{38}, resp.~\kbd{28}, on a 64-bit, resp~.32-bit, machine. \subsec{recover}\kbdsidx{recover}\label{se:def,recover} This toggle is either 1 (on) or 0 (off). If you change this to $0$, any error becomes fatal and causes the gp interpreter to exit immediately. Can be useful in batch job scripts. The default value is \kbd{1}. \subsec{secure}\kbdsidx{secure}\label{se:def,secure} This toggle is either 1 (on) or 0 (off). If on, the \tet{system} and \tet{extern} command are disabled. These two commands are potentially dangerous when you execute foreign scripts since they let \kbd{gp} execute arbitrary UNIX commands. \kbd{gp} will ask for confirmation before letting you (or a script) unset this toggle. The default value is \kbd{0}. \subsec{seriesprecision}\kbdsidx{seriesprecision}\label{se:def,seriesprecision} Number of significant terms when converting a polynomial or rational function to a power series (see~\b{ps}). The default value is \kbd{16}. \subsec{simplify}\kbdsidx{simplify}\label{se:def,simplify} This toggle is either 1 (on) or 0 (off). When the PARI library computes something, the type of the result is not always the simplest possible. The only type conversions which the PARI library does automatically are rational numbers to integers (when they are of type \typ{FRAC} and equal to integers), and similarly rational functions to polynomials (when they are of type \typ{RFRAC} and equal to polynomials). This feature is useful in many cases, and saves time, but can be annoying at times. Hence you can disable this and, whenever you feel like it, use the function \kbd{simplify} (see Chapter 3) which allows you to simplify objects to the simplest possible types recursively (see~\b{y}). \sidx{automatic simplification} The default value is \kbd{1}. \subsec{sopath}\kbdsidx{sopath}\label{se:def,sopath} This is a list of directories, separated by colons ':' (semicolons ';' in the DOS world, since colons are preempted for drive names). When asked to \tet{install} an external symbol from a shared library whose name is not given by an absolute path (does not start with \kbd{/}, \kbd{./} or \kbd{../}), \kbd{gp} will look for it in these directories, in the order they were written in \kbd{sopath}. Here, as usual, \kbd{.} means the current directory, and \kbd{..} its immediate parent. Environment expansion is performed. The default value is \kbd{""}, corresponding to an empty list of directories: \tet{install} will use the library name as input (and look in the current directory if the name is not an absolute path). \subsec{strictargs}\kbdsidx{strictargs}\label{se:def,strictargs} This toggle is either 1 (on) or 0 (off). If on, all arguments to \emph{new} user functions are mandatory unless the function supplies an explicit default value. Otherwise arguments have the default value $0$. In this example, \bprog fun(a,b=2)=a+b @eprog \kbd{a} is mandatory, while \kbd{b} is optional. If \kbd{strictargs} is on: \bprog ? fun() *** at top-level: fun() *** ^----- *** in function fun: a,b=2 *** ^----- *** missing mandatory argument 'a' in user function. @eprog This applies to functions defined while \kbd{strictargs} is on. Changing \kbd{strictargs} 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}. \subsec{threadsize}\kbdsidx{threadsize}\label{se:def,threadsize} In parallel mode, each thread needs its own private \tev{stack} in which to do its computations, see \kbd{parisize}. This value determines the size in bytes of the stacks of each thread, so the total memory allocated will be $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. If set to $0$, the value used is the same as \kbd{parisize}. 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, to some accuracy depending on the hardware and operating system. When \tet{timer} is on, each such timing is printed immediately before the output as follows: \bprog ? factor(2^2^7+1) time = 108 ms. \\ this line omitted if 'timer' is 0 %1 = [ 59649589127497217 1] [5704689200685129054721 1] @eprog\noindent (See also \kbd{\#} and \kbd{\#\#}.) The time measured is the user \idx{CPU time}, \emph{not} including the time for printing the results. If the time is negligible ($< 1$ ms.), nothing is printed: in particular, no timing should be printed when defining a user function or an alias, or installing a symbol from the library. The default value is \kbd{0} (off). %SECTION: default \vfill\eject pari-2.7.5/doc/users.tex0000644000175000017500000000144312366172547013555 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Compile with plain TeX % \def\TITLE{User's Guide to Pari/GP} \input parimacro.tex % remove TOC for this level \SUBSECTOCfalse % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine User's Guide} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine PARI / GP} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \openin\std=libpari.aux \ifeof\std \else \input libpari.aux \fi \chapno=0 { \input usersch1 } { \input usersch2 } { \input usersch3 } { \input appa } \input index\end pari-2.7.5/doc/usersch4.tex0000644000175000017500000030310612413013142014127 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Programming PARI in Library Mode} \noindent The \emph{User's Guide to Pari/GP} gives in three chapters a general presentation of the system, of the \kbd{gp} calculator, and detailed explanation of high level PARI routines available through the calculator. The present manual assumes general familiarity with the contents of these chapters and the basics of ANSI C programming, and focuses on the usage of the PARI library. In this chapter, we introduce the general concepts of PARI programming and describe useful general purpose functions; the following chapters describes all public low or high-level functions, underlying or extending the GP functions seen in Chapter 3 of the User's guide. \section{Introduction: initializations, universal objects} \label{se:intro4} \noindent To use PARI in \idx{library mode}, you must write a C program and link it to the PARI library. See the installation guide or the Appendix to the \emph{User's Guide to Pari/GP} on how to create and install the library and include files. A sample Makefile is presented in Appendix~A, and a more elaborate one in \kbd{examples/Makefile}. The best way to understand how programming is done is to work through a complete example. We will write such a program in~\secref{se:prog}. Before doing this, a few explanations are in order. First, one must explain to the outside world what kind of objects and routines we are going to use. This is done\footnote{*}{This assumes that PARI headers are installed in a directory which belongs to your compiler's search path for header files. You might need to add flags like \kbd{-I/usr/local/include} or modify \tet{C_INCLUDE_PATH}.} with the directive \bprog #include @eprog \noindent In particular, this defines the fundamental type for all PARI objects: the type \teb{GEN}, which is simply a pointer to \kbd{long}. Before any PARI routine is called, one must initialize the system, and in particular the PARI stack which is both a scratchboard and a repository for computed objects. This is done with a call to the function \fun{void}{pari_init}{size_t size, ulong maxprime} \noindent The first argument is the number of bytes given to PARI to work with, and the second is the upper limit on a precomputed prime number table; \kbd{size} should not reasonably be taken below $500000$ but you may set $\tet{maxprime} = 0$, although the system still needs to precompute all primes up to about $2^{16}$. For lower-level variants allowing finer control, e.g.~preventing PARI from installing its own error or signal handlers, see~\secref{se:pari_init_tech}. \noindent We have now at our disposal: \item a PARI \tev{stack} containing nothing. This is a big connected chunk of \kbd{size} bytes of memory, where all computations take place. In large computations, intermediate results quickly clutter up memory so some kind of garbage collecting is needed. Most systems do garbage collecting when the memory is getting scarce, and this slows down the performance. PARI takes a different approach, admittedly more demanding on the programmer: you must do your own cleaning up when the intermediate results are not needed anymore. We will see later how (and when) this is done. \item the following \emph{universal objects} (by definition, objects which do not belong to the stack): the integers $0$, $1$, $-1$, $2$ and $-2$ (respectively called \tet{gen_0}, \tet{gen_1}, \tet{gen_m1}, \tet{gen_2} and \tet{gen_m2}), the fraction $\dfrac{1}{2}$ (\tet{ghalf}). All of these are of type \kbd{GEN}. \item a \tev{heap} which is just a linked list of permanent universal objects. For now, it contains exactly the ones listed above. You will probably very rarely use the heap yourself; and if so, only as a collection of copies of objects taken from the stack (called \idx{clone}s in the sequel). Thus you need not bother with its internal structure, which may change as PARI evolves. Some complex PARI functions create clones for special garbage collecting purposes, usually destroying them when returning. \item a table of primes (in fact of \emph{differences} between consecutive primes), called \teb{diffptr}, of type \kbd{byteptr} (pointer to \kbd{unsigned char}). Its use is described in \secref{se:primetable} later. Using it directly is deprecated, high-level iterators provide a cleaner and more flexible interface, see \secref{se:primeiter} (such iterators use the private prime table, but extend it dynamically). \item access to all the built-in functions of the PARI library. These are declared to the outside world when you include \kbd{pari.h}, but need the above things to function properly. So if you forget the call to \tet{pari_init}, you will get a fatal error when running your program. \section{Important technical notes} \subsec{Backward compatibility} The PARI function names evolved over time, and deprecated functions are eventually deleted. The file \kbd{pariold.h} contains macros implementing a weak form of backward compatibility. In particular, whenever the name of a documented function changes, a \kbd{\#define} is added to this file so that the old name expands to the new one (provided the prototype didn't change also). This file is included by \kbd{pari.h}, but a large section is commented out by default. Define \tet{PARI_OLD_NAMES} before including \kbd{pari.h} to pollute your namespace with lots of obsolete names like \kbd{un}\footnote{*}{For \kbd{(long)gen\_1}. Since 2004 and version 2.2.9, typecasts are completely unnecessary in PARI programs.}: that might enable you to compile old programs without having to modify them. The preferred way to do that is to add \kbd{-DPARI\_OLD\_NAMES} to your compiler \kbd{CFLAGS}, so that you don't need to modify the program files themselves. Of course, it's better to fix the program if you can! \subsec{Types} \noindent Although PARI objects all have the C type \kbd{GEN}, we will freely use the word \teb{type} to refer to PARI dynamic subtypes: \typ{INT}, \typ{REAL}, etc. The declaration \bprog GEN x; @eprog\noindent declares a C variable of type \kbd{GEN}, but its ``value'' will be said to have type \typ{INT}, \typ{REAL}, etc. The meaning should always be clear from the context. \subsec{Type recursivity} \noindent Conceptually, most PARI types are recursive. But the \kbd{GEN} type is a pointer to \kbd{long}, not to \kbd{GEN}. So special macros must be used to access \kbd{GEN}'s components. The simplest one is \tet{gel}$(V, i)$, where \key{el} stands for \key{el}ement, to access component number $i$ of the \kbd{GEN} $V$. This is a valid \kbd{lvalue} (may be put on the left side of an assignment), and the following two constructions are exceedingly frequent % \bprog gel(V, i) = x; x = gel(V, i); @eprog\noindent where \kbd{x} and \kbd{V} are \kbd{GEN}s. This macro accesses and modifies directly the components of $V$ and do not create a copy of the coefficient, contrary to all the library \emph{functions}. More generally, to retrieve the values of elements of lists of \dots\ of lists of vectors we have the \tet{gmael} macros (for {\bf m}ultidimensional {\bf a}rray {\bf el}ement). The syntax is $\key{gmael}n(V,a_1,\dots,a_n)$, where $V$ is a \kbd{GEN}, the $a_i$ are indexes, and $n$ is an integer between $1$ and $5$. This stands for $x[a_1][a_2]\dots[a_n]$, and returns a \kbd{GEN}. The macros \tet{gel} (resp.~\tet{gmael}) are synonyms for \tet{gmael1} (resp.~\kbd{gmael2}). Finally, the macro $\tet{gcoeff}(M, i, j)$ has exactly the meaning of \kbd{M[i,j]} in GP when \kbd{M} is a matrix. Note that due to the implementation of \typ{MAT}s as horizontal lists of vertical vectors, \kbd{gcoeff(x,y)} is actually equivalent to \kbd{gmael(y,x)}. One should use \kbd{gcoeff} in matrix context, and \kbd{gmael} otherwise. \subsec{Variations on basic functions}\label{se:low_level} In the library syntax descriptions in Chapter~3, we have only given the basic names of the functions. For example \kbd{gadd}$(x,y)$ assumes that $x$ and $y$ are \kbd{GEN}s, and \emph{creates} the result $x+y$ on the PARI stack. For most of the basic operators and functions, many other variants are available. We give some examples for \kbd{gadd}, but the same is true for all the basic operators, as well as for some simple common functions (a complete list is given in Chapter~6): \fun{GEN}{gaddgs}{GEN x, long y} \fun{GEN}{gaddsg}{long x, GEN y} \noindent In the following one, \kbd{z} is a preexisting \kbd{GEN} and the result of the corresponding operation is put into~\kbd{z}. The size of the PARI stack does not change: \fun{void}{gaddz}{GEN x, GEN y, GEN z} \noindent (This last form is inefficient in general and deprecated outside of PARI kernel programming.) Low level kernel functions implement these operators for specialized arguments and are also available: Level 0 deals with operations at the word level (\kbd{long}s and \kbd{ulong}s), Level 1 with \typ{INT} and \typ{REAL} and Level 2 with the rest (modular arithmetic, polynomial arithmetic and linear algebra). Here are some examples of Level $1$ functions: \fun{GEN}{addii}{GEN x, GEN y}: here $x$ and $y$ are \kbd{GEN}s of type \typ{INT} (this is not checked). \fun{GEN}{addrr}{GEN x, GEN y}: here $x$ and $y$ are \kbd{GEN}s of type \typ{REAL} (this is not checked). \noindent There also exist functions \teb{addir}, \teb{addri}, \teb{mpadd} (whose two arguments can be of type \typ{INT} or \typ{REAL}), \teb{addis} (to add a \typ{INT} and a \kbd{long}) and so on. The Level $1$ names are self-explanatory once you know that {\bf i} stands for a \typ{INT}, {\bf r} for a \typ{REAL}, {\bf mp} for i or r, {\bf s} for a signed C long integer, {\bf u} for an unsigned C long integer; finally the suffix {\bf z} means that the result is not created on the PARI stack but assigned to a preexisting GEN object passed as an extra argument. Chapter 6 gives a description of these low-level functions. Level $2$ names are more complicated, see \secref{se:level2names} for all the gory details, and we content ourselves with a simple example used to implement \typ{INTMOD} arithmetic: \fun{GEN}{Fp_add}{GEN x, GEN y, GEN m}: returns the sum of $x$ and $y$ modulo $m$. Here $x, y, m$ are \typ{INT}s (this is not checked). The operation is more efficient if the inputs $x$, $y$ are reduced modulo $m$, but this is not a necessary condition. \misctitle{Important Note} These specialized functions are of course more efficient than the generic ones, but note the hidden danger here: the types of the objects involved (which is not checked) must be severely controlled, e.g.~using \kbd{addii} on a \typ{FRAC} argument will cause disasters. Type mismatches may corrupt the PARI stack, though in most cases they will just immediately overflow the stack. Because of this, the PARI philosophy of giving a result which is as exact as possible, enforced for generic functions like \kbd{gadd} or \kbd{gmul}, is dropped in kernel routines of Level $1$, where it is replaced by the much simpler rule: the result is a \typ{INT} if and only if all arguments are integer types (\typ{INT} but also C \kbd{long} and \kbd{ulong}) and a \typ{REAL} otherwise. For instance, multiplying a \typ{REAL} by a \typ{INT} always yields a \typ{REAL} if you use \kbd{mulir}, where \kbd{gmul} returns the \typ{INT} \kbd{gen\_0} if the integer is $0$. \subsec{Portability: 32-bit / 64-bit architectures} \noindent PARI supports both 32-bit and 64-bit based machines, but not simultaneously! The library is compiled assuming a given architecture, and some of the header files you include (through \kbd{pari.h}) will have been modified to match the library. Portable macros are defined to bypass most machine dependencies. If you want your programs to run identically on 32-bit and 64-bit machines, you have to use these, and not the corresponding numeric values, whenever the precise size of your \kbd{long} integers might matter. Here are the most important ones: \settabs\+ -----------------------------&---------------&------------&\cr \+ & 64-bit & 32-bit \cr\+ \tet{BITS_IN_LONG} & 64 & 32 \cr\+ \tet{LONG_IS_64BIT} & defined & undefined \cr\+ \tet{DEFAULTPREC} & 3 & 4 & ($\approx$ 19 decimal digits, % see formula below) \cr\+ \tet{MEDDEFAULTPREC}& 4 & 6 & ($\approx$ 38 decimal digits) \cr\+ \tet{BIGDEFAULTPREC}& 5 & 8 & ($\approx$ 57 decimal digits) \cr \noindent For instance, suppose you call a transcendental function, such as \kbd{GEN \key{gexp}(GEN x, long prec)}. \noindent The last argument \kbd{prec} is an integer $\geq 3$, corresponding to the default floating point precision required. It is \emph{only} used if \kbd{x} is an exact object, otherwise the relative precision is determined by the precision of~\kbd{x}. Since the parameter \kbd{prec} sets the size of the inexact result counted in (\kbd{long}) \emph{words} (including codewords), the same value of \kbd{prec} will yield different results on 32-bit and 64-bit machines. Real numbers have two codewords (see~\secref{se:impl}), so the formula for computing the bit accuracy is $$ \tet{bit_accuracy}(\kbd{prec}) = (\kbd{prec} - 2) * \tet{BITS_IN_LONG}$$ (this is actually the definition of an inline function). The corresponding accuracy expressed in decimal digits would be % $$ \kbd{bit\_accuracy(prec)} * \log(2) / \log(10).$$ % For example if the value of \kbd{prec} is 5, the corresponding accuracy for 32-bit machines is $(5-2)*\log(2^{32})/\log(10)\approx 28$ decimal digits, while for 64-bit machines it is $(5-2)*\log(2^{64})/\log(10)\approx 57$ decimal digits. Thus, you must take care to change the \kbd{prec} parameter you are supplying according to the bit size, either using the default precisions given by the various \kbd{DEFAULTPREC}s, or by using conditional constructs of the form: % \bprog #ifndef LONG_IS_64BIT prec = 4; #else prec = 6; #endif @eprog \noindent which is in this case equivalent to the statement \kbd{prec = MEDDEFAULTPREC;}. Note that for parity reasons, half the accuracies available on 32-bit architectures (the odd ones) have no precise equivalents on 64-bit machines. \subsec{Using \kbd{malloc} / \kbd{free}} You should make use of the PARI stack as much as possible, and avoid allocating objects using the customary functions. If you do, you should use, or at least have a very close look at, the following wrappers: \fun{void*}{pari_malloc}{size_t size} calls \kbd{malloc} to allocate \kbd{size} bytes and returns a pointer to the allocated memory. If the request fails, an error is raised. The \kbd{SIGINT} signal is blocked until \kbd{malloc} returns, to avoid leaving the system stack in an inconsistent state. \fun{void*}{pari_realloc}{void* ptr, size_t size} as \tet{pari_malloc} but calls \kbd{realloc} instead of \kbd{malloc}. \fun{void*}{pari_calloc}{size_t size} as \tet{pari_malloc}, setting the memory to zero. \fun{void}{pari_free}{void* ptr} calls \kbd{free} to liberate the memory space pointed to by \kbd{ptr}, which must have been allocated by \kbd{malloc} (\tet{pari_malloc}) or \kbd{realloc} (\tet{pari_realloc}). The \kbd{SIGINT} signal is blocked until \kbd{free} returns. If you use the standard \kbd{libc} functions instead of our wrappers, then your functions will be subtly incompatible with the \kbd{gp} calculator: when the user tries to interrupt a computation, the calculator may crash (if a system call is interrupted at the wrong time). \section{Garbage collection}\label{se:garbage}\sidx{garbage collecting} \subsec{Why and how} \noindent As we have seen, \kbd{pari\_init} allocates a big range of addresses, the \tev{stack}, that are going to be used throughout. Recall that all PARI objects are pointers. Except for a few universal objects, they all point at some part of the stack. The stack starts at the address \kbd{bot} and ends just before \kbd{top}. This means that the quantity % $$ (\kbd{top} - \kbd{bot})\,/\,\kbd{sizeof(long)} $$ % is (roughly) equal to the \kbd{size} argument of \kbd{pari\_init}. The PARI stack also has a ``current stack pointer'' called \teb{avma}, which stands for {\bf av}ailable {\bf m}emory {\bf a}ddress. These three variables are global (declared by \kbd{pari.h}). They are of type \tet{pari_sp}, which means \emph{pari stack pointer}. The stack is oriented upside-down: the more recent an object, the closer to \kbd{bot}. Accordingly, initially \kbd{avma} = \kbd{top}, and \kbd{avma} gets \emph{decremented} as new objects are created. As its name indicates, \kbd{avma} always points just \emph{after} the first free address on the stack, and \kbd{(GEN)avma} is always (a pointer to) the latest created object. When \kbd{avma} reaches \kbd{bot}, the stack overflows, aborting all computations, and an error message is issued. To avoid this \emph{you} need to clean up the stack from time to time, when intermediate objects are not needed anymore. This is called ``\emph{garbage collecting}.'' We are now going to describe briefly how this is done. We will see many concrete examples in the next subsection. \noindent\item First, PARI routines do their own garbage collecting, which means that whenever a documented function from the library returns, only its result(s) have been added to the stack, possibly up to a very small overhead (non-documented ones may not do this). In particular, a PARI function that does not return a \kbd{GEN} does not clutter the stack. Thus, if your computation is small enough (e.g.~you call few PARI routines, or most of them return \kbd{long} integers), then you do not need to do any garbage collecting. This is probably the case in many of your subroutines. Of course the objects that were on the stack \emph{before} the function call are left alone. Except for the ones listed below, PARI functions only collect their own garbage. \noindent\item It may happen that all objects that were created after a certain point can be deleted~--- for instance, if the final result you need is not a \kbd{GEN}, or if some search proved futile. Then, it is enough to record the value of \kbd{avma} just \emph{before} the first garbage is created, and restore it upon exit: \bprog pari_sp av = avma; /*@Ccom record initial avma */ garbage ... avma = av; /*@Ccom restore it */ @eprog \noindent All objects created in the \kbd{garbage} zone will eventually be overwritten: they should no longer be accessed after \kbd{avma} has been restored. \noindent\item If you want to destroy (i.e.~give back the memory occupied by) the \emph{latest} PARI object on the stack (e.g.~the latest one obtained from a function call), you can use the function\sidx{destruction}% \vadjust{\penalty500}%discourage page break \fun{void}{cgiv}{GEN z} \noindent where \kbd{z} is the object you want to give back. This is equivalent to the above where the initial \kbd{av} is computed from \kbd{z}. \noindent\item Unfortunately life is not so simple, and sometimes you will want to give back accumulated garbage \emph{during} a computation without losing recent data. We shall start with the lowest level function to get a feel for the underlying mechanisms, we shall describe simpler variants later: \fun{GEN}{gerepile}{pari_sp ltop, pari_sp lbot, GEN q}. This function cleans up the stack between \kbd{ltop} and \kbd{lbot}, where $\kbd{lbot} < \kbd{ltop}$, and returns the updated object \kbd{q}. This means: 1) we translate (copy) all the objects in the interval $[\kbd{avma}, \kbd{lbot}[$, so that its right extremity abuts the address \kbd{ltop}. Graphically \vbox{\bprog bot avma lbot ltop top End of stack |-------------[++++++[-/-/-/-/-/-/-|++++++++| Start free memory garbage @eprog \noindent becomes: \bprog bot avma ltop top End of stack |---------------------------[++++++[++++++++| Start free memory @eprog } \noindent where \kbd{++} denote significant objects, \kbd{--} the unused part of the stack, and \kbd{-/-} the garbage we remove. 2) The function then inspects all the PARI objects between \kbd{avma} and \kbd{lbot} (i.e.~the ones that we want to keep and that have been translated) and looks at every component of such an object which is not a codeword. Each such component is a pointer to an object whose address is either --- between \kbd{avma} and \kbd{lbot}, in which case it is suitably updated, --- larger than or equal to \kbd{ltop}, in which case it does not change, or --- between \kbd{lbot} and \kbd{ltop} in which case \kbd{gerepile} raises an error (``significant pointers lost in gerepile''). 3) \key{avma} is updated (we add $\kbd{ltop} - \kbd{lbot}$ to the old value). 4) We return the (possibly updated) object \kbd{q}: if \kbd{q} initially pointed between \kbd{avma} and \kbd{lbot}, we return the updated address, as in~2). If not, the original address is still valid, and is returned! As stated above, no component of the remaining objects (in particular \kbd{q}) should belong to the erased segment [\kbd{lbot}, \kbd{ltop}[, and this is checked within \kbd{gerepile}. But beware as well that the addresses of the objects in the translated zone change after a call to \kbd{gerepile}, so you must not access any pointer which previously pointed into the zone below \kbd{ltop}. If you need to recover more than one object, use the \kbd{gerepileall} function below. \misctitle{Remark} As a consequence of the preceding explanation, if a PARI object is to be relocated by \hbox{gerepile} then, apart from universal objects, the chunks of memory used by its components should be in consecutive memory locations. All \kbd{GEN}s created by documented PARI functions are guaranteed to satisfy this. This is because the \kbd{gerepile} function knows only about \emph{two connected zones}: the garbage that is erased (between \kbd{lbot} and \kbd{ltop}) and the significant pointers that are copied and updated. If there is garbage interspersed with your objects, disaster occurs when we try to update them and consider the corresponding ``pointers''. In most cases of course the said garbage is in fact a bunch of other \kbd{GEN}s, in which case we simply waste time copying and updating them for nothing. But be wary when you allow objects to become disconnected. \noindent In practice this is achieved by the following programming idiom: \bprog ltop = avma; garbage(); lbot = avma; q = anything(); return gerepile(ltop, lbot, q); /*@Ccom returns the updated q */ @eprog\noindent or directly \bprog ltop = avma; garbage(); lbot = avma; return gerepile(ltop, lbot, anything()); @eprog\noindent Beware that \bprog ltop = avma; garbage(); return gerepile(ltop, avma, anything()) @eprog \noindent might work, but should be frowned upon. We cannot predict whether \kbd{avma} is evaluated after or before the call to \kbd{anything()}: it depends on the compiler. If we are out of luck, it is \emph{after} the call, so the result belongs to the garbage zone and the \kbd{gerepile} statement becomes equivalent to \kbd{avma = ltop}. Thus we return a pointer to random garbage. \subsec{Variants} \fun{GEN}{gerepileupto}{pari_sp ltop, GEN q}. Cleans the stack between \kbd{ltop} and the \emph{connected} object \kbd{q} and returns \kbd{q} updated. For this to work, \kbd{q} must have been created \emph{before} all its components, otherwise they would belong to the garbage zone! Unless mentioned otherwise, documented PARI functions guarantee this. \fun{GEN}{gerepilecopy}{pari_sp ltop, GEN x}. Functionally equivalent to, but more efficient than \bprog gerepileupto(ltop, gcopy(x)) @eprog\noindent In this case, the \kbd{GEN} parameter \kbd{x} need not satisfy any property before the garbage collection: it may be disconnected, components created before the root, and so on. Of course, this is about twice slower than either \tet{gerepileupto} or \tet{gerepile}, because \kbd{x} has to be copied to a clean stack zone first. This function is a special case of \tet{gerepileall} below, where $n=1$. \fun{void}{gerepileall}{pari_sp ltop, int n, ...}. To cope with complicated cases where many objects have to be preserved. The routine expects $n$ further arguments, which are the \emph{addresses} of the \kbd{GEN}s you want to preserve: \bprog pari_sp ltop = avma; ...; y = ...; ... x = ...; ...; gerepileall(ltop, 2, &x, &y); @eprog\noindent It cleans up the most recent part of the stack (between \kbd{ltop} and \kbd{avma}), updating all the \kbd{GEN}s added to the argument list. A copy is done just before the cleaning to preserve them, so they do not need to be connected before the call. With \kbd{gerepilecopy}, this is the most robust of the \kbd{gerepile} functions (the less prone to user error), hence the slowest. \fun{void}{gerepileallsp}{pari_sp ltop, pari_sp lbot, int n, ...}. More efficient, but trickier than \kbd{gerepileall}. Cleans the stack between \kbd{lbot} and \kbd{ltop} and updates the \kbd{GEN}s pointed at by the elements of \kbd{gptr} without any further copying. This is subject to the same restrictions as \kbd{gerepile}, the only difference being that more than one address gets updated. \subsec{Examples} \subsubsec{gerepile} Let \kbd{x} and \kbd{y} be two preexisting PARI objects and suppose that we want to compute $\kbd{x}^2 + \kbd{y}^2$. This is done using the following program: \bprog GEN x2 = gsqr(x); GEN y2 = gsqr(y), z = gadd(x2,y2); @eprog\noindent The \kbd{GEN} \kbd{z} indeed points at the desired quantity. However, consider the stack: it contains as unnecessary garbage \kbd{x2} and \kbd{y2}. More precisely it contains (in this order) \kbd{z}, \kbd{y2}, \kbd{x2}. (Recall that, since the stack grows downward from the top, the most recent object comes first.) It is not possible to get rid of \kbd{x2}, \kbd{y2} before \kbd{z} is computed, since they are used in the final operation. We cannot record \kbd{avma} before \kbd{x2} is computed and restore it later, since this would destroy \kbd{z} as well. It is not possible either to use the function \kbd{cgiv} since \kbd{x2} and \kbd{y2} are not at the bottom of the stack and we do not want to give back~\kbd{z}. But using \kbd{gerepile}, we can give back the memory locations corresponding to \kbd{x2}, \kbd{y2}, and move the object \kbd{z} upwards so that no space is lost. Specifically: \bprog pari_sp ltop = avma; /*@Ccom remember the current top of the stack */ GEN x2 = gsqr(x); GEN y2 = gsqr(y); pari_sp lbot = avma; /*@Ccom the bottom of the garbage pile */ GEN z = gadd(x2, y2); /*@Ccom z is now the last object on the stack */ z = gerepile(ltop, lbot, z); @eprog \noindent Of course, the last two instructions could also have been written more simply: \bprog z = gerepile(ltop, lbot, gadd(x2,y2)); @eprog\noindent In fact \kbd{gerepileupto} is even simpler to use, because the result of \kbd{gadd} is the last object on the stack and \kbd{gadd} is guaranteed to return an object suitable for \kbd{gerepileupto}: \bprog ltop = avma; z = gerepileupto(ltop, gadd(gsqr(x), gsqr(y))); @eprog\noindent Make sure you understand exactly what has happened before you go on! \misctitle{Remark on assignments and gerepile} When the tree structure and the size of the PARI objects which will appear in a computation are under control, one may allocate sufficiently large objects at the beginning, use assignment statements, then simply restore \kbd{avma}. Coming back to the above example, note that \emph{if} we know that x and y are of type real fitting into \kbd{DEFAULTPREC} words, we can program without using \kbd{gerepile} at all: \bprog z = cgetr(DEFAULTPREC); ltop = avma; gaffect(gadd(gsqr(x), gsqr(y)), z); avma = ltop; @eprog\noindent This is often \emph{slower} than a craftily used \kbd{gerepile} though, and certainly more cumbersome to use. As a rule, assignment statements should generally be avoided. \misctitle{Variations on a theme} it is often necessary to do several \kbd{gerepile}s during a computation. However, the fewer the better. The only condition for \kbd{gerepile} to work is that the garbage be connected. If the computation can be arranged so that there is a minimal number of connected pieces of garbage, then it should be done that way. For example suppose we want to write a function of two \kbd{GEN} variables \kbd{x} and \kbd{y} which creates the vector $\kbd{[x}^2+\kbd{y}, \kbd{y}^2+\kbd{x]}$. Without garbage collecting, one would write: % \bprog p1 = gsqr(x); p2 = gadd(p1, y); p3 = gsqr(y); p4 = gadd(p3, x); z = mkvec2(p2, p4); /* not suitable for gerepileupto! */ @eprog\noindent This leaves a dirty stack containing (in this order) \kbd{z}, \kbd{p4}, \kbd{p3}, \kbd{p2}, \kbd{p1}. The garbage here consists of \kbd{p1} and \kbd{p3}, which are separated by \kbd{p2}. But if we compute \kbd{p3} \emph{before} \kbd{p2} then the garbage becomes connected, and we get the following program with garbage collecting: % \bprog ltop = avma; p1 = gsqr(x); p3 = gsqr(y); lbot = avma; z = cgetg(3, t_VEC); gel(z, 1) = gadd(p1,y); gel(z, 2) = gadd(p3,x); z = gerepile(ltop,lbot,z); @eprog\noindent Finishing by \kbd{z = gerepileupto(ltop, z)} would be ok as well. Beware that \bprog ltop = avma; p1 = gadd(gsqr(x), y); p3 = gadd(gsqr(y), x); z = cgetg(3, t_VEC); gel(z, 1) = p1; gel(z, 2) = p3; z = gerepileupto(ltop,z); /*@Ccom WRONG */ @eprog\noindent is a disaster since \kbd{p1} and \kbd{p3} are created before \kbd{z}, so the call to \kbd{gerepileupto} overwrites them, leaving \kbd{gel(z, 1)} and \kbd{gel(z, 2)} pointing at random data! The following does work: \bprog ltop = avma; p1 = gsqr(x); p3 = gsqr(y); lbot = avma; z = mkvec2(gadd(p1,y), gadd(p3,x)); z = gerepile(ltop,lbot,z); @eprog\noindent but is very subtly wrong in the sense that \kbd{z = gerepileupto(ltop, z)} would \emph{not} work. The reason being that \kbd{mkvec2} creates the root \kbd{z} of the vector \emph{after} its arguments have been evaluated, creating the components of \kbd{z} too early; \kbd{gerepile} does not care, but the created \kbd{z} is a time bomb which will explode on any later \kbd{gerepileupto}. On the other hand \bprog ltop = avma; z = cgetg(3, t_VEC); gel(z, 1) = gadd(gsqr(x), y); gel(z, 2) = gadd(gsqr(y), x); z = gerepileupto(ltop,z); /*@Ccom INEFFICIENT */ @eprog\noindent leaves the results of \kbd{gsqr(x)} and \kbd{gsqr(y)} on the stack (and lets \kbd{gerepileupto} update them for naught). Finally, the most elegant and efficient version (with respect to time and memory use) is as follows \bprog z = cgetg(3, t_VEC); ltop = avma; gel(z, 1) = gerepileupto(ltop, gadd(gsqr(x), y)); ltop = avma; gel(z, 2) = gerepileupto(ltop, gadd(gsqr(y), x)); @eprog\noindent which avoids updating the container \kbd{z} and cleans up its components individually, as soon as they are computed. \misctitle{One last example} Let us compute the product of two complex numbers $x$ and $y$, using the $3M$ method which requires 3 multiplications instead of the obvious 4. Let $z = x*y$, and set $x = x_r + i*x_i$ and similarly for $y$ and $z$. We compute $p_1 = x_r*y_r$, $p_2=x_i*y_i$, $p_3=(x_r+x_i)*(y_r+y_i)$, and then we have $z_r=p_1-p_2$, $z_i=p_3-(p_1+p_2)$. The program is as follows: % \bprog ltop = avma; p1 = gmul(gel(x,1), gel(y,1)); p2 = gmul(gel(x,2), gel(y,2)); p3 = gmul(gadd(gel(x,1), gel(x,2)), gadd(gel(y,1), gel(y,2))); p4 = gadd(p1,p2); lbot = avma; z = cgetg(3, t_COMPLEX); gel(z, 1) = gsub(p1,p2); gel(z, 2) = gsub(p3,p4); z = gerepile(ltop,lbot,z); @eprog \misctitle{Exercise} Write a function which multiplies a matrix by a column vector. Hint: start with a \kbd{cgetg} of the result, and use \kbd{gerepile} whenever a coefficient of the result vector is computed. You can look at the answer in \kbd{src/basemath/RgV.c:RgM\_RgC\_mul()}. \subsubsec{gerepileall} Let us now see why we may need the \kbd{gerepileall} variants. Although it is not an infrequent occurrence, we do not give a specific example but a general one: suppose that we want to do a computation (usually inside a larger function) producing more than one PARI object as a result, say two for instance. Then even if we set up the work properly, before cleaning up we have a stack which has the desired results \kbd{z1}, \kbd{z2} (say), and then connected garbage from lbot to ltop. If we write \bprog z1 = gerepile(ltop, lbot, z1); @eprog\noindent then the stack is cleaned, the pointers fixed up, but we have lost the address of \kbd{z2}. This is where we need the \idx{gerepileall} function: \bprog gerepileall(ltop, 2, &z1, &z2) @eprog \noindent copies \kbd{z1} and \kbd{z2} to new locations, cleans the stack from \kbd{ltop} to the old \kbd{avma}, and updates the pointers \kbd{z1} and \kbd{z2}. Here we do not assume anything about the stack: the garbage can be disconnected and \kbd{z1}, \kbd{z2} need not be at the bottom of the stack. If all of these assumptions are in fact satisfied, then we can call \kbd{gerepilemanysp} instead, which is usually faster since we do not need 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); 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); } @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$). \subsec{Comments} First, \kbd{gerepile} has turned out to be a flexible and fast garbage collector for number-theoretic computations, which compares favorably with more sophisticated methods used in other systems. Our benchmarks indicate that the price paid for using \kbd{gerepile} and \kbd{gerepile}-related copies, when properly used, is usually less than 1\% of the total running time, which is quite acceptable! Second, it is of course harder on the programmer, and quite error-prone if you do not stick to a consistent PARI programming style. If all seems lost, just use \tet{gerepilecopy} (or \tet{gerepileall}) to fix up the stack for you. You can always optimize later when you have sorted out exactly which routines are crucial and what objects need to be preserved and their usual sizes. \smallskip If you followed us this far, congratulations, and rejoice: the rest is much easier. \section{Creation of PARI objects, assignments, conversions} \subsec{Creation of PARI objects}\sidx{creation} The basic function which creates a PARI object is \fun{GEN}{cgetg}{long l, long t} $l$ specifies the number of longwords to be allocated to the object, and $t$ is the type of the object, in symbolic form (see \secref{se:impl} for the list of these). The precise effect of this function is as follows: it first creates on the PARI \emph{stack} a chunk of memory of size \kbd{length} longwords, and saves the address of the chunk which it will in the end return. If the stack has been used up, a message to the effect that ``the PARI stack overflows'' is printed, and an error raised. Otherwise, it sets the type and length of the PARI object. In effect, it fills its first codeword (\kbd{z[0]}). Many PARI objects also have a second codeword (types \typ{INT}, \typ{REAL}, \typ{PADIC}, \typ{POL}, and \typ{SER}). In case you want to produce one of those from scratch, which should be exceedingly rare, \emph{it is your responsibility to fill this second codeword}, either explicitly (using the macros described in \secref{se:impl}), or implicitly using an assignment statement (using \kbd{gaffect}). Note that the length argument $l$ is predetermined for a number of types: 3 for types \typ{INTMOD}, \typ{FRAC}, \typ{COMPLEX}, \typ{POLMOD}, \typ{RFRAC}, 4 for type \typ{QUAD} and \typ{QFI}, and 5 for type \typ{PADIC} and \typ{QFR}. However for the sake of efficiency, \kbd{cgetg} does not check this: disasters will occur if you give an incorrect length for those types. \misctitle{Notes} 1) The main use of this function is create efficiently a constant object, or to prepare for later assignments (see \secref{se:assign}). Most of the time you will use \kbd{GEN} objects as they are created and returned by PARI functions. In this case you do not need to use \kbd{cgetg} to create space to hold them. \noindent 2) For the creation of leaves, i.e.~\typ{INT} or \typ{REAL}, \fun{GEN}{cgeti}{long length} \fun{GEN}{cgetr}{long length} \noindent should be used instead of \kbd{cgetg(length, t\_INT)} and \kbd{cgetg(length, t\_REAL)} respectively. Finally \fun{GEN}{cgetc}{long prec} \noindent creates a \typ{COMPLEX} whose real and imaginary part are \typ{REAL}s allocated by \kbd{cgetr(prec)}. \misctitle{Examples} 1) Both \kbd{z = cgeti(DEFAULTPREC)} and \kbd{cgetg(DEFAULTPREC, t\_INT)} create a \typ{INT} whose ``precision'' is \kbd{bit\_accuracy(DEFAULTPREC)} = 64. This means \kbd{z} can hold rational integers of absolute value less than $2^{64}$. Note that in both cases, the second codeword is \emph{not} filled. Of course we could use numerical values, e.g.~\kbd{cgeti(4)}, but this would have different meanings on different machines as \kbd{bit\_accuracy(4)} equals 64 on 32-bit machines, but 128 on 64-bit machines. \noindent 2) The following creates a \emph{complex number} whose real and imaginary parts can hold real numbers of precision $\kbd{bit\_accuracy(MEDDEFAULTPREC)} = 96\hbox{ bits:}$ % \bprog z = cgetg(3, t_COMPLEX); gel(z, 1) = cgetr(MEDDEFAULTPREC); gel(z, 2) = cgetr(MEDDEFAULTPREC); @eprog\noindent or simply \kbd{z = cgetc(MEDDEFAULTPREC)}. \noindent 3) To create a matrix object for $4\times 3$ matrices: % \bprog z = cgetg(4, t_MAT); for(i=1; i<4; i++) gel(z, i) = cgetg(5, t_COL); @eprog\noindent or simply \kbd{z = zeromatcopy(4, 3)}, which further initializes all entries to \kbd{gen\_0}. These last two examples illustrate the fact that since PARI types are recursive, all the branches of the tree must be created. The function \teb{cgetg} creates only the ``root'', and other calls to \kbd{cgetg} must be made to produce the whole tree. For matrices, a common mistake is to think that \kbd{z = cgetg(4, t\_MAT)} (for example) creates the root of the matrix: one needs also to create the column vectors of the matrix (obviously, since we specified only one dimension in the first \kbd{cgetg}!). This is because a matrix is really just a row vector of column vectors (hence a priori not a basic type), but it has been given a special type number so that operations with matrices become possible. Finally, to facilitate input of constant objects when speed is not paramount, 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). \bprog mkintn(3, a2, a1, a0); @eprog \noindent returns $a_2 2^{64} + a_1 2^{32} + a_0$. \fun{GEN}{mkpoln}{long n, ...} Returns the \typ{POL} whose $n$ coefficients (\kbd{GEN}) follow, in order of decreasing degree. \bprog mkpoln(3, gen_1, gen_2, gen_0); @eprog \noindent returns the polynomial $X^2 + 2X$ (in variable $0$, use \tet{setvarn} if you want other variable numbers). Beware that $n$ is the number of coefficients, hence \emph{one more} than the degree. \fun{GEN}{mkvecn}{long n, ...} returns the \typ{VEC} whose $n$ coefficients (\kbd{GEN}) follow. \fun{GEN}{mkcoln}{long n, ...} returns the \typ{COL} whose $n$ coefficients (\kbd{GEN}) follow. \misctitle{Warning} Contrary to the policy of general PARI functions, the latter three functions do \emph{not} copy their arguments, nor do they produce an object a priori suitable for \tet{gerepileupto}. For instance \bprog /*@Ccom gerepile-safe: components are universal objects */ z = mkvecn(3, gen_1, gen_0, gen_2); /*@Ccom not OK for gerepileupto: stoi(3) creates component before root */ z = mkvecn(3, stoi(3), gen_0, gen_2); /*@Ccom NO! First vector component \kbd{x} is destroyed */ x = gclone(gen_1); z = mkvecn(3, x, gen_0, gen_2); gunclone(x); @eprog \noindent The following function is also available as a special case of \tet{mkintn}: \fun{GEN}{uu32toi}{ulong a, ulong b} Returns the \kbd{GEN} equal to $2^{32} a + b$, \emph{assuming} that $a,b < 2^{32}$. This does not depend on \kbd{sizeof(long)}: the behavior is as above on both $32$ and $64$-bit machines. \subsec{Sizes} \fun{long}{gsizeword}{GEN x} returns the total number of \B-bit words occupied by the tree representing~\kbd{x}. \fun{long}{gsizebyte}{GEN x} returns the total number of bytes occupied by the tree representing~\kbd{x}, i.e.~\kbd{gsizeword(x)} multiplied by \kbd{sizeof(long)}. This is normally useless since PARI functions use a number of \emph{words} as input for lengths and precisions. \subsec{Assignments} Firstly, if \kbd{x} and \kbd{y} are both declared as \kbd{GEN} (i.e.~pointers to something), the ordinary C assignment \kbd{y = x} makes perfect sense: we are just moving a pointer around. However, physically modifying either \kbd{x} or \kbd{y} (for instance, \kbd{x[1] = 0}) also changes the other one, which is usually not desirable. \label{se:assign} \misctitle{Very important note} Using the functions described in this paragraph is inefficient and often awkward: one of the \tet{gerepile} functions (see~\secref{se:garbage}) should be preferred. See the paragraph end for one exception to this rule. \noindent The general PARI \idx{assignment} function is the function \teb{gaffect} with the following syntax: \fun{void}{gaffect}{GEN x, GEN y} \noindent Its effect is to assign the PARI object \kbd{x} into the \emph{preexisting} object \kbd{y}. Both \kbd{x} and \kbd{y} must be \emph{scalar} types. For convenience, vector or matrices of scalar types are also allowed. This copies the whole structure of \kbd{x} into \kbd{y} so many conditions must be met for the assignment to be possible. For instance it is allowed to assign a \typ{INT} into a \typ{REAL}, but the converse is forbidden. For that, you must use the truncation or rounding function of your choice, e.g.\kbd{mpfloor}. It can also happen that \kbd{y} is not large enough or does not have the proper tree structure to receive the object \kbd{x}. For instance, let \kbd{y} the zero integer with length equal to 2; then \kbd{y} is too small to accommodate any non-zero \typ{INT}. In general common sense tells you what is possible, keeping in mind the PARI philosophy which says that if it makes sense it is valid. For instance, the assignment of an imprecise object into a precise one does \emph{not} make sense. However, a change in precision of imprecise objects is allowed, even if it \emph{increases} its accuracy: we complement the ``mantissa'' with infinitely many $0$ digits in this case. (Mantissa between quotes, because this is not restricted to \typ{REAL}s, it also applies for $p$-adics for instance.) All functions ending in ``\kbd{z}'' such as \teb{gaddz} (see~\secref{se:low_level}) implicitly use this function. In fact what they exactly do is record {\teb{avma}} (see~\secref{se:garbage}), perform the required operation, \teb{gaffect} the result to the last operand, then restore the initial \kbd{avma}. You can assign ordinary C long integers into a PARI object (not necessarily of type \typ{INT}) using \fun{void}{gaffsg}{long s, GEN y} \misctitle{Note} Due to the requirements mentioned above, it is usually a bad idea to use \tet{gaffect} statements. There is one exception: for simple objects (e.g.~leaves) whose size is controlled, they can be easier to use than \kbd{gerepile}, and about as efficient. \misctitle{Coercion} It is often useful to coerce an inexact object to a given precision. For instance at the beginning of a routine where precision can be kept to a minimum; otherwise the precision of the input is used in all subsequent computations, which is inefficient if the latter is known to thousands of digits. One may use the \kbd{gaffect} function for this, but it is easier and more efficient to call \fun{GEN}{gtofp}{GEN x, long prec} converts the complex number~\kbd{x} (\typ{INT}, \typ{REAL}, \typ{FRAC}, \typ{QUAD} or \typ{COMPLEX}) to either a \typ{REAL} or \typ{COMPLEX} whose components are \typ{REAL} of length \kbd{prec}. \subsec{Copy} It is also very useful to \idx{copy} a PARI object, not just by moving around a pointer as in the \kbd{y = x} example, but by creating a copy of the whole tree structure, without pre-allocating a possibly complicated \kbd{y} to use with \kbd{gaffect}. The function which does this is called \teb{gcopy}. Its syntax is: \fun{GEN}{gcopy}{GEN x} \noindent and the effect is to create a new copy of x on the PARI stack. Sometimes, on the contrary, a quick copy of the skeleton of \kbd{x} is enough, leaving pointers to the original data in \kbd{x} for the sake of speed instead of making a full recursive copy. Use \fun{GEN}{shallowcopy}{GEN x} for this. Note that the result is not suitable for \tet{gerepileupto} ! Make sure at this point that you understand the difference between \kbd{y = x}, \kbd{y = gcopy(x)}, \kbd{y = shallowcopy(x)} and \kbd{gaffect(x,y)}. \subsec{Clones}\sidx{clone}\label{se:clone} Sometimes, it is more efficient to create a \emph{persistent} copy of a PARI object. This is not created on the stack but on the heap, hence unaffected by \tet{gerepile} and friends. The function which does this is called \teb{gclone}. Its syntax is: \fun{GEN}{gclone}{GEN x} A clone can be removed from the heap (thus destroyed) using \fun{void}{gunclone}{GEN x} \noindent No PARI object should keep references to a clone which has been destroyed! \subsec{Conversions}\sidx{conversions} The following functions convert C objects to PARI objects (creating them on the stack as usual): \fun{GEN}{stoi}{long s}: C \kbd{long} integer (``small'') to \typ{INT}. \fun{GEN}{dbltor}{double s}: C \kbd{double} to \typ{REAL}. The accuracy of the result is 19 decimal digits, i.e.~a type \typ{REAL} of length \kbd{DEFAULTPREC}, although on 32-bit machines only 16 of them are significant. \noindent We also have the converse functions: \fun{long}{itos}{GEN x}: \kbd{x} must be of type \typ{INT}, \fun{double}{rtodbl}{GEN x}: \kbd{x} must be of type \typ{REAL}, \noindent as well as the more general ones: \fun{long}{gtolong}{GEN x}, \fun{double}{gtodouble}{GEN x}. \section{Implementation of the PARI types} \label{se:impl} \noindent We now go through each type and explain its implementation. Let \kbd{z} be a \kbd{GEN}, pointing at a PARI object. In the following paragraphs, we will constantly mix two points of view: on the one hand, \kbd{z} is treated as the C pointer it is, on the other, as PARI's handle on some mathematical entity, so we will shamelessly write $\kbd{z} \ne 0$ to indicate that the \emph{value} thus represented is nonzero (in which case the \emph{pointer}~\kbd{z} is certainly non-\kbd{NULL}). We offer no apologies for this style. In fact, you had better feel comfortable juggling both views simultaneously in your mind if you want to write correct PARI programs. Common to all the types is the first codeword \kbd{z[0]}, which we do not have to worry about since this is taken care of by \kbd{cgetg}. Its precise structure depends on the machine you are using, but it always contains the following data: the \emph{internal type number}\sidx{type number} associated to the symbolic type name, the \emph{length} of the root in longwords, and a technical bit which indicates whether the object is a clone or not (see \secref{se:clone}). This last one is used by \kbd{gp} for internal garbage collecting, you will not have to worry about it. Some types have a second codeword, different for each type, which we will soon describe as we will shortly consider each of them in turn. \noindent The first codeword is handled through the following \emph{macros}: \fun{long}{typ}{GEN z} returns the type number of \kbd{z}. \fun{void}{settyp}{GEN z, long n} sets the type number of \kbd{z} to \kbd{n} (you should not have to use this function if you use \kbd{cgetg}). \fun{long}{lg}{GEN z} returns the length (in longwords) of the root of \kbd{z}. \fun{long}{setlg}{GEN z, long l} sets the length of \kbd{z} to \kbd{l} (you should not have to use this function if you use \kbd{cgetg}; however, see an advanced example in \secref{se:prog}). \fun{long}{isclone}{GEN z} is \kbd{z} a clone? \fun{void}{setisclone}{GEN z} sets the \emph{clone} bit. \fun{void}{unsetisclone}{GEN z} clears the \emph{clone} bit. \misctitle{Important remark} For the sake of efficiency, none of the codeword-handling macros check the types of their arguments even when there are stringent restrictions on their use. It is trivial to create invalid objects, or corrupt one of the ``universal constants'' (e.g. setting the sign of \kbd{gen\_0} to $1$), and they usually provide negligible savings. Use higher level functions whenever possible. \misctitle{Remark} The clone bit is there so that \kbd{gunclone} can check it is deleting an object which was allocated by \kbd{gclone}. Miscellaneous vector entries are often cloned by \kbd{gp} so that a GP statement like \kbd{v[1] = x} does not involve copying the whole of \kbd{v}: the component \kbd{v[1]} is deleted if its clone bit is set, and is replaced by a clone of \kbd{x}. Don't set/unset yourself the clone bit unless you know what you are doing: in particular \emph{never} set the clone bit of a vector component when the said vector is scheduled to be uncloned. Hackish code may abuse the clone bit to tag objects for reasons unrelated to the above instead of using proper data structures. Don't do that. \subsec{Type \typ{INT} (integer)} \sidx{integer}\kbdsidx{t_INT}this type has a second codeword \kbd{z[1]} which contains the following information: the sign of \kbd{z}: coded as $1$, $0$ or $-1$ if $\kbd{z} > 0$, $\kbd{z} = 0$, $\kbd{z} < 0$ respectively. the \emph{effective length} of \kbd{z}, i.e.~the total number of significant longwords. This means the following: apart from the integer 0, every integer is ``normalized'', meaning that the most significant mantissa longword is non-zero. However, the integer may have been created with a longer length. Hence the ``length'' which is in \kbd{z[0]} can be larger than the ``effective length'' which is in \kbd{z[1]}. \noindent This information is handled using the following macros: \fun{long}{signe}{GEN z} returns the sign of \kbd{z}. \fun{void}{setsigne}{GEN z, long s} sets the sign of \kbd{z} to \kbd{s}. \fun{long}{lgefint}{GEN z} returns the \idx{effective length} of \kbd{z}. \fun{void}{setlgefint}{GEN z, long l} sets the effective length of \kbd{z} to \kbd{l}. The integer 0 can be recognized either by its sign being~0, or by its effective length being equal to~2. Now assume that $\kbd{z} \ne 0$, and let $$ |z| = \sum_{i = 0}^n z_i B^i, \quad\text{where}~z_n\ne 0~\text{and}~B = 2^{\kbd{BITS\_IN\_LONG}}. $$ With these notations, $n$ is \kbd{lgefint(z) - 3}, and the mantissa of $\kbd{z}$ may be manipulated via the following interface: \fun{GEN}{int_MSW}{GEN z} returns a pointer to the most significant word of \kbd{z}, $z_n$. \fun{GEN}{int_LSW}{GEN z} returns a pointer to the least significant word of \kbd{z}, $z_0$. \fun{GEN}{int_W}{GEN z, long i} returns the $i$-th significant word of \kbd{z}, $z_i$. Accessing the $i$-th significant word for $i > n$ yields unpredictable results. \fun{GEN}{int_W_lg}{GEN z, long i, long lz} returns the $i$-th significant word of \kbd{z}, $z_i$, assuming \kbd{lgefint(z)} is \kbd{lz} ($= n + 3$). Accessing the $i$-th significant word for $i > n$ yields unpredictable results. \fun{GEN}{int_precW}{GEN z} returns the previous (less significant) word of \kbd{z}, $z_{i-1}$ assuming \kbd{z} points to $z_i$. \fun{GEN}{int_nextW}{GEN z} returns the next (more significant) word of \kbd{z}, $z_{i+1}$ assuming \kbd{z} points to $z_i$. Unnormalized integers, such that $z_n$ is possibly $0$, are explicitly forbidden. To enforce this, one may write an arbitrary mantissa then call \fun{void}{int_normalize}{GEN z, long known0} \noindent normalizes in place a non-negative integer (such that $z_n$ is possibly $0$), assuming at least the first \kbd{known0} words are zero. \noindent For instance a binary \kbd{and} could be implemented in the following way: \bprog GEN AND(GEN x, GEN y) { long i, lx, ly, lout; long *xp, *yp, *outp; /* mantissa pointers */ GEN out; if (!signe(x) || !signe(y)) return gen_0; lx = lgefint(x); xp = int_LSW(x); ly = lgefint(y); yp = int_LSW(y); lout = min(lx,ly); /* > 2 */ out = cgeti(lout); out[1] = evalsigne(1) | evallgefint(lout); outp = int_LSW(out); for (i=2; i < lout; i++) { *outp = (*xp) & (*yp); outp = int_nextW(outp); xp = int_nextW(xp); yp = int_nextW(yp); } if ( !*int_MSW(out) ) out = int_normalize(out, 1); return out; } @eprog \noindent This low-level interface is mandatory in order to write portable code since PARI can be compiled using various multiprecision kernels, for instance the native one or GNU MP, with incompatible internal structures (for one thing, the mantissa is oriented in different directions). \noindent The following further functions are available: \fun{int}{mpodd}{GEN x} which is 1 if \kbd{x} is odd, and 0 otherwise. \fun{long}{mod2}{GEN x} \fun{long}{mod4}{GEN x} \fun{long}{mod8}{GEN x} \fun{long}{mod16}{GEN x} \fun{long}{mod32}{GEN x} \fun{long}{mod64}{GEN x} give the residue class of \kbd{x} modulo the corresponding power of 2, for \emph{positive}~\kbd{x}. By definition, $\kbd{mod}n(x) := \kbd{mod}n(|x|)$ for $x < 0$ (the functions disregard the sign), and the result is undefined if $x = 0$. As well, \fun{ulong}{mod2BIL}{GEN x} returns the least significant word of $|x|$, still assuming that $x\neq 0$. These functions directly access the binary data and are thus much faster than the generic modulo functions. Besides, they return long integers instead of \kbd{GEN}s, so they do not clutter up the stack. \subsec{Type \typ{REAL} (real number)} \kbdsidx{t_REAL}\sidx{real number}this type has a second codeword z[1] which also encodes its sign, obtained or set using the same functions as for a \typ{INT}, and a binary exponent. This exponent is handled using the following macros: \fun{long}{expo}{GEN z} returns the exponent of \kbd{z}. This is defined even when \kbd{z} is equal to zero, see \secref{se:whatzero}. \fun{void}{setexpo}{GEN z, long e} sets the exponent of \kbd{z} to \kbd{e}. \noindent Note the functions: \fun{long}{gexpo}{GEN z} which tries to return an exponent for \kbd{z}, even if \kbd{z} is not a real number. \fun{long}{gsigne}{GEN z} which returns a sign for \kbd{z}, even when \kbd{z} is neither real nor integer (a rational number for instance). The real zero is characterized by having its sign equal to 0. If \kbd{z} is not equal to~0, then is is represented as $2^e M$, where $e$ is the exponent, and $M\in [1, 2[$ is the mantissa of $z$, whose digits are stored in $\kbd{z[2]},\dots, \kbd{z[lg(z)-1]}$. More precisely, let $m$ be the integer (\kbd{z[2]},\dots, \kbd{z[lg(z)-1]}) in base \kbd{2\pow BITS\_IN\_LONG}; here, \kbd{z[2]} is the most significant longword and is normalized, i.e.~its most significant bit is~1. Then we have $M := m / 2^{\kbd{bit\_accuracy(lg(z))} - 1 - \kbd{expo}(z)}$. \fun{GEN}{mantissa_real}{GEN z, long *e} returns the mantissa $m$ of $z$, and sets \kbd{*e} to the exponent $\kbd{bit\_accuracy(lg(z))}-1-\kbd{expo}(z)$, so that $z = m / 2^e$. Thus, the real number $3.5$ to accuracy \kbd{bit\_accuracy(lg(z))} is represented as \kbd{z[0]} (encoding $\kbd{type} = \typ{REAL}$, \kbd{lg(z)}), \kbd{z[1]} (encoding $\kbd{sign} = 1$, $\kbd{expo} = 1$), $\kbd{z[2]} = \kbd{0xe0000000}$, $\kbd{z[3]} =\dots = \kbd{z[lg(z)-1]} = \kbd{0x0}$. \subsec{Type \typ{INTMOD}}\kbdsidx{t_INTMOD} \kbd{z[1]} points to the modulus, and \kbd{z[2]} at the number representing the class \kbd{z}. Both are separate \kbd{GEN} objects, and both must be \typ{INT}s, satisfying the inequality $0 \le \kbd{z[2]} < \kbd{z[1]}$. \subsec{Type \typ{FRAC} (rational number)}% \kbdsidx{t_FRAC}\sidx{rational number} \kbd{z[1]} points to the numerator $n$, and \kbd{z[2]} to the denominator $d$. Both must be of type \typ{INT} such that $n\neq 0$, $d > 0$ and $(n,d) = 1$. \subsec{Type \typ{FFELT} (finite field element)}% \kbdsidx{t_FFELT}\sidx{finite field element} (Experimental) Components of this type should normally not be accessed directly. Instead, finite field elements should be created using \kbd{ffgen}. \noindent The second codeword \kbd{z[1]} determines the storage format of the element, among \item \tet{t_FF_FpXQ}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{FpX}, \kbd{p=z[4]} is a \typ{INT}, where $p$ is a prime number, $T$ is irreducible modulo $p$, and $\deg A < \deg T$. This represents the element $A\pmod{T}$ in $\F_p[X]/T$. \item \tet{t_FF_Flxq}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{Flx}, \kbd{l=z[4]} is a \typ{INT}, where $l$ is a prime number, $T$ is irreducible modulo $l$, and $\deg A < \deg T$ This represents the element $A\pmod{T}$ in $\F_l[X]/T$. \item \tet{t_FF_F2xq}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{F2x}, \kbd{l=z[4]} is the \typ{INT} $2$, $T$ is irreducible modulo $2$, and $\deg A < \deg T$. This represents the element $A\pmod{T}$ in $\F_2[X]/T$. \subsec{Type \typ{COMPLEX} (complex number)}% \kbdsidx{t_COMPLEX}\sidx{complex number} \kbd{z[1]} points to the real part, and \kbd{z[2]} to the imaginary part. The components \kbd{z[1]} and \kbd{z[2]} must be of type \typ{INT}, \typ{REAL} or \typ{FRAC}. For historical reasons \typ{INTMOD} and \typ{PADIC} are also allowed (the latter for $p = 2$ or congruent to 3 mod 4 only), but one should rather use the more general \typ{POLMOD} construction. \subsec{Type \typ{PADIC} ($p$-adic numbers)}% \sidx{p-adic number}\kbdsidx{t_PADIC} this type has a second codeword \kbd{z[1]} which contains the following information: the $p$-adic precision (the exponent of $p$ modulo which the $p$-adic unit corresponding to \kbd{z} is defined if \kbd{z} is not~0), i.e.~one less than the number of significant $p$-adic digits, and the exponent of \kbd{z}. This information can be handled using the following functions: \fun{long}{precp}{GEN z} returns the $p$-adic precision of \kbd{z}. This is $0$ if $\kbd{z} = 0$. \fun{void}{setprecp}{GEN z, long l} sets the $p$-adic precision of \kbd{z} to \kbd{l}. \fun{long}{valp}{GEN z} returns the $p$-adic valuation of \kbd{z} (i.e. the exponent). This is defined even if \kbd{z} is equal to~0, see \secref{se:whatzero}. \fun{void}{setvalp}{GEN z, long e} sets the $p$-adic valuation of \kbd{z} to \kbd{e}. In addition to this codeword, \kbd{z[2]} points to the prime $p$, \kbd{z[3]} points to $p^{\text{precp(z)}}$, and \kbd{z[4]} points to a\typ{INT} representing the $p$-adic unit associated to \kbd{z} modulo \kbd{z[3]} (and to zero if \kbd{z} is zero). To summarize, if $z\neq 0$, we have the equality: $$ \kbd{z} = p^{\text{valp(z)}} * (\kbd{z[4]} + O(\kbd{z[3]})),\quad \text{where}\quad \kbd{z[3]} = O(p^{\text{precp(z)}}). $$ \subsec{Type \typ{QUAD} (quadratic number)} \sidx{quadratic number}\kbdsidx{t_QUAD}\kbd{z[1]} points to the canonical polynomial $P$ defining the quadratic field (as output by \tet{quadpoly}), \kbd{z[2]} to the ``real part'' and \kbd{z[3]} to the ``imaginary part''. The latter are of type \typ{INT}, \typ{FRAC}, \typ{INTMOD}, or \typ{PADIC} and are to be taken as the coefficients of \kbd{z} with respect to the canonical basis $(1,X)$ or $\Q[X]/(P(X))$, see~\secref{se:compquad}. Exact complex numbers may be implemented as quadratics, but \typ{COMPLEX} is in general more versatile (\typ{REAL} components are allowed) and more efficient. Operations involving a \typ{QUAD} and \typ{COMPLEX} are implemented by converting the \typ{QUAD} to a \typ{REAL} (or \typ{COMPLEX} with \typ{REAL} components) to the accuracy of the \typ{COMPLEX}. As a consequence, operations between \typ{QUAD} and \emph{exact} \typ{COMPLEX}s are not allowed. \subsec{Type \typ{POLMOD} (polmod)}\kbdsidx{t_POLMOD}\sidx{polmod} as for \typ{INTMOD}s, \kbd{z[1]} points to the modulus, and \kbd{z[2]} to a polynomial representing the class of~\kbd{z}. Both must be of type \typ{POL} in the same variable, satisfying the inequality $\deg \kbd{z[2]} < \deg \kbd{z[1]}$. However, \kbd{z[2]} is allowed to be a simplification of such a polynomial, e.g.~a scalar. This is tricky considering the hierarchical structure of the variables; in particular, a polynomial in variable of \emph{lesser} priority (see \secref{se:priority}) than the modulus variable is valid, since it is considered as the constant term of a polynomial of degree 0 in the correct variable. On the other hand a variable of \emph{greater} priority is not acceptable; see \secref{se:priority} for the problems which may arise. \subsec{Type \typ{POL} (polynomial)}\kbdsidx{t_POL}\sidx{polynomial} this type has a second codeword. It contains a ``\emph{sign}'': 0 if the polynomial is equal to~0, and 1 if not (see however the important remark below) and a \emph{variable number} (e.g.~0 for $x$, 1 for $y$, etc\dots). \noindent These data can be handled with the following macros: \teb{signe} and \teb{setsigne} as for \typ{INT} and \typ{REAL}, \fun{long}{varn}{GEN z} returns the variable number of the object \kbd{z}, \fun{void}{setvarn}{GEN z, long v} sets the variable number of \kbd{z} to \kbd{v}. The variable numbers encode the relative priorities of variables as discussed in \secref{se:priority}. We will give more details in \secref{se:vars}. Note also the function \fun{long}{gvar}{GEN z} which tries to return a \idx{variable number} for \kbd{z}, even if \kbd{z} is not a polynomial or power series. The variable number of a scalar type is set by definition equal to \tet{NO_VARIABLE}, which has lower priority than any other variable number. The components \kbd{z[2]}, \kbd{z[3]},\dots \kbd{z[lg(z)-1]} point to the coefficients of the polynomial \emph{in ascending order}, with \kbd{z[2]} being the constant term and so on. For a \typ{POL} of non-zero sign, \tet{degpol}, \tet{leading_term}, \tet{constant_term}, return its degree, and a pointer to the leading, resp. constant, coefficient with respect to the main variable. Note that no copy is made on the PARI stack so the returned value is not safe for a basic \kbd{gerepile} call. Applied to any other type than \typ{POL}, the result is unspecified. Those three functions are still defined when the sign is $0$, see \secref{se:accessors} and \secref{se:polynomials}. \fun{long}{degree}{GEN x} returns the degree of \kbd{x} with respect to its main variable even when \kbd{x} is not a polynomial (a rational function for instance). By convention, the degree of a zero polynomial is~$-1$. \misctitle{Important remark} The leading coefficient of a \typ{POL} may be equal to zero: \item it is not allowed to be an exact rational $0$, such as \tet{gen_0}; \item an exact non-rational $0$, like \kbd{Mod(0,2)}, is possible for constant polynomials, i.e. of length $3$ and no other coefficient: this carries information about the base ring for the polynomial; \item an inexact $0$, like \kbd{0.E-38} or \kbd{O(3\pow 5)}, is always possible. Inexact zeroes do not correspond to an actual $0$, but to a very small coefficient according to some metric; we keep them to give information on how much cancellation occurred in previous computations. A polynomial disobeying any of these rules is an invalid \emph{unnormalized} object. We advise \emph{not} to use low-level constructions to build a \typ{POL} coefficient by coefficient, such as \bprog GEN T = cgetg(4, t_POL); T[1] = evalvarn(0); gel(T, 2) = x; gel(T, 3) = y; @eprog\noindent But if you do and it is not clear whether the result will be normalized, call \fun{GEN}{normalizepol}{GEN x} applied to an unnormalized \typ{POL}~\kbd{x} (with all coefficients correctly set except that \kbd{leading\_term(x)} might be zero), normalizes \kbd{x} correctly in place and returns~\kbd{x}. This functions sets \kbd{signe} (to $0$ or $1$) properly. \misctitle{Caveat} A consequence of the remark above is that zero polynomials are characterized by the fact that their sign is~0. It is in general incorrect to check whether \kbd{lg(x)} is $2$ or \kbd{degpol(x)} $< 0$, although both tests are valid when the coefficient types are under control: for instance, when they are guaranteed to be \typ{INT}s or \typ{FRAC}s. The same remark applies to \typ{SER}s. \subsec{Type \typ{SER} (power series)} \kbdsidx{t_SER}\sidx{power series}This type also has a second codeword, which encodes a ``\emph{sign}'', i.e.~0 if the power series is 0, and 1 if not, a \emph{variable number} as for polynomials, and an \emph{exponent}. This information can be handled with the following functions: \teb{signe}, \teb{setsigne}, \teb{varn}, \teb{setvarn} as for polynomials, and \teb{valp}, \teb{setvalp} for the exponent as for $p$-adic numbers. Beware: do \emph{not} use \teb{expo} and \teb{setexpo} on power series. 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$.) 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 terms). \subsec{Type \typ{RFRAC} (rational function)}% \kbdsidx{t_RFRAC}\sidx{rational function} \kbd{z[1]} points to the numerator $n$, and \kbd{z[2]} on the denominator $d$. The denominator must be of type \typ{POL}, with variable of higher priority than the numerator. The numerator $n$ is not an exact $0$ and $(n,d) = 1$ (see \tet{gred_rfac2}). \subsec{Type \typ{QFR} (indefinite binary quadratic form)}% \kbdsidx{t_QFR}\sidx{indefinite binary quadratic form} \kbd{z[1]}, \kbd{z[2]}, \kbd{z[3]} point to the three coefficients of the form and are of type \typ{INT}. \kbd{z[4]} is Shanks's distance function, and must be of type \typ{REAL}. \subsec{Type \typ{QFI} (definite binary quadratic form)}% \kbdsidx{t_QFI}\sidx{definite binary quadratic form} \kbd{z[1]}, \kbd{z[2]}, \kbd{z[3]} point to the three coefficients of the form. All three are of type \typ{INT}. \subsec{Type \typ{VEC} and \typ{COL} (vector)}% \kbdsidx{t_VEC}\kbdsidx{t_COL}\sidx{row vector}\sidx{column vector} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} point to the components of the vector. \subsec{Type \typ{MAT} (matrix)}\kbdsidx{t_MAT}\sidx{matrix} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} point to the column vectors of \kbd{z}, i.e.~they must be of type \typ{COL} and of the same length. \subsec{Type \typ{VECSMALL} (vector of small integers)}\kbdsidx{t_VECSMALL} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} are ordinary signed long integers. This type is used instead of a \typ{VEC} of \typ{INT}s for efficiency reasons, for instance to implement efficiently permutations, polynomial arithmetic and linear algebra over small finite fields, etc. \subsec{Type \typ{STR} (character string)}% \kbdsidx{t_STR}\sidx{character string} \fun{char *}{GSTR}{z} (= \kbd{(z+1)}) points to the first character of the (\kbd{NULL}-terminated) string. \subsec{Type \typ{ERROR} (error context)}\kbdsidx{t_ERROR}\sidx{error context} This type holds error messages, as well as details about the error, as returned by the exception handling system. The second codeword \kbd{z[1]} contains the error type (an \kbd{int}, as passed to \tet{pari_err}). The subsequent words \kbd{z[2]},\dots \kbd{z[lg(z)-1]} are \kbd{GEN}s containing additional data, depending on the error type. \subsec{Type \typ{CLOSURE} (closure)}\kbdsidx{t_CLOSURE}\sidx{closure} This type holds GP functions and closures, in compiled form. The internal detail of this type is subject to change each time the GP language evolves. Hence we do not describe it here and refer to the Developer's Guide. However functions to create or to evaluate \typ{CLOSURE}s are documented in \secref{se:closure}. \fun{long}{closure_arity}{GEN C} returns the arity of the \typ{CLOSURE}. \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 memory, as well as many unnecessary copies). Hence we do not describe it here and refer to the Developer's Guide. \misctitle{Implementation note} For the types including an exponent (or a valuation), we actually store a biased non-negative exponent (bit-ORing the biased exponent to the codeword), obtained by adding a constant to the true exponent: either \kbd{HIGHEXPOBIT} (for \typ{REAL}) or \kbd{HIGHVALPBIT} (for \typ{PADIC} and \typ{SER}). Of course, this is encapsulated by the exponent/valuation-handling macros and needs not concern the library user. \section{PARI variables}\label{se:vars} \subsec{Multivariate objects} \sidx{variable (priority)} \noindent We now consider variables and formal computations, and give the technical details corresponding to the general discussion in \secref{se:priority}. As we have seen in \secref{se:impl}, the codewords for types \typ{POL} and \typ{SER} encode a ``variable number''. This is an integer, ranging from $0$ to \kbd{MAXVARN}. Relative priorities may be ascertained using \fun{int}{varncmp}{long v, long w} \noindent which is $>0$, $=0$, $<0$ whenever $v$ has lower, resp.~same, resp.~higher priority than $w$. The way an object is considered in formal computations depends entirely on its ``principal variable number'' which is given by the function \fun{long}{gvar}{GEN z} \noindent which returns a \idx{variable number} for \kbd{z}, even if \kbd{z} is not a polynomial or power series. The variable number of a scalar type is set by definition equal to \tet{NO_VARIABLE} which has lower priority than any valid variable number. The variable number of a recursive type which is not a polynomial or power series is the variable number with highest priority among its components. But for polynomials and power series only the ``outermost'' number counts (we directly access $\tet{varn}(x)$ in the codewords): the representation is not symmetrical at all. Under \kbd{gp}, one needs not worry too much since the interpreter defines the variables as it sees them\footnote{*}{ The first time a given identifier is read by the GP parser a new variable is created, and it is assigned a strictly lower priority than any variable in use at this point. On startup, before any user input has taken place, 'x' is defined in this way and has initially maximal priority (and variable number $0$).} % and do the right thing with the polynomials produced (however, have a look at the remark in \secref{se:rempolmod}). But in library mode, they are tricky objects if you intend to build polynomials yourself (and not just let PARI functions produce them, which is less efficient). For instance, it does not make sense to have a variable number occur in the components of a polynomial whose main variable has a lower priority, even though PARI cannot prevent you from doing it; see \secref{se:priority} for a discussion of possible problems in a similar situation. \subsec{Creating variables} A basic difficulty is to ``create'' a variable. 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)}''. \subsubsec{User variables}\sidx{variable (user)} When the program starts, \kbd{x} is the only user variable (number~$0$). To define new ones, use \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 variable number. \bprog 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. \misctitle{Caveat} You can use \tet{gp_read_str} (see~\secref{se:gp_read_str}) to execute a GP command and create GP variables on the fly as needed: \bprog GEN gy = gp_read_str("'y"); /*@Ccom returns \kbd{pol\_x}($v$), for some $v$ */ long v = varn(gy); @eprog\noindent But please note the quote \kbd{'y} in the above. Using \kbd{gp\_read\_str("y")} might work, but is dangerous, especially when programming functions to be used under \kbd{gp}. The latter reads the value of \kbd{y}, as \emph{currently} known by the \kbd{gp} interpreter, possibly creating it in the process. But if \kbd{y} has been modified by previous \kbd{gp} commands (e.g.~\kbd {y = 1}), then the value of \kbd{gy} is not what you expected it to be and corresponds instead to the current value of the \kbd{gp} variable (e.g.~\kbd{gen\_1}). \fun{GEN}{fetch_var_value}{long v} returns a shallow copy of the current value of the variable numbered $v$. Returns \kbd{NULL} if that variable number is unknown to the interpreter, e.g. it is a user variable. Note 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 \fun{long}{fetch_var}{}\label{se:fetch_var} \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 \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 \fun{void}{name_var}{long n, char *s} \noindent after which the output machinery will use the name \kbd{s} to 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. 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 destroyed by a \kbd{gerepile} or \kbd{avma = ltop} statement). When you do 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 the deleted variable does not appear anywhere in the objects you use later on. Here is an example: \bprog long first = fetch_var(); long n1 = fetch_var(); long n2 = fetch_var(); /*@Ccom prepare three variables for internal use */ ... /*@Ccom delete all variables before leaving */ do { num = delete_var(); } while (num && num <= first); @eprog\noindent The (dangerous) statement \bprog while (delete_var()) /*@Ccom empty */; @eprog\noindent removes all temporary variables in use, except \kbd{MAXVARN} which cannot be deleted. \section{Input and output} \noindent Two important aspects have not yet been explained which are specific to library mode: input and output of PARI objects. \subsec{Input} \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 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. \misctitle{Note} The obsolete form \fun{GEN}{readseq}{char *t} still exists for backward compatibility (assumes filtered input, without spaces or comments). Don't use it. To read a \kbd{GEN} from a file, you can use the simpler interface \fun{GEN}{gp_read_stream}{FILE *file} \noindent which reads a character string of arbitrary length from the stream \kbd{file} (up to the first complete expression sequence), applies \kbd{gp\_read\_str} to it, and returns the resulting \kbd{GEN}. This way, you do not have to worry about allocating buffers to hold the string. To interactively input an expression, use \kbd{gp\_read\_stream(stdin)}. Finally, you can read in a whole file, as in GP's \tet{read} statement \fun{GEN}{gp_read_file}{char *name} \noindent As usual, the return value is that of the last non-empty expression evaluated. There is one technical exception: if \kbd{name} is a \emph{binary} file (from \tet{writebin}) containing more than one object, a \typ{VEC} containing them all is returned. This is because binary objects bypass the parser, hence reading them has no useful side effect. \subsec{Output to screen or file, output to string}\sidx{output} General output functions return nothing but print a character string as a side effect. Low level routines are available to write on PARI output stream \tet{pari_outfile} (\tet{stdout} by default): \fun{void}{pari_putc}{char c}: write character \kbd{c} to the output stream. \fun{void}{pari_puts}{char *s}: write \kbd{s} to the output stream. \fun{void}{pari_flush}{}: flush output stream; most streams are buffered by default, this command makes sure that all characters output so are actually written. \fun{void}{pari_printf}{const char *fmt, ...}: the most versatile such function. \kbd{fmt} is a character string similar to the one \tet{printf} uses. In there, \kbd{\%} characters have a special meaning, and describe how to print the remaining operands. In addition to the standard format types (see the GP function \tet{printf}), you can use the \emph{length modifier}~\kbd{P} (for PARI of course!) to specify that an argument is a \kbd{GEN}. For instance, the following are valid conversions for a \kbd{GEN} argument \bprog %Ps @com convert to \kbd{char*} (will print an arbitrary \kbd{GEN}) %P.10s @com convert to \kbd{char*}, truncated to 10 chars %P.2f @com convert to floating point format with 2 decimals %P4d @com convert to integer, field width at least 4 pari_printf("x[%d] = %Ps is not invertible!\n", i, gel(x,i)); @eprog\noindent Here \kbd{i} is an \kbd{int}, \kbd{x} a \kbd{GEN} which is not a leaf (presumably a vector, or a polynomial) and this would insert the value of its $i$-th \kbd{GEN} component: \kbd{gel(x,i)}. \noindent Simple but useful variants to \kbd{pari\_printf} are \fun{void}{output}{GEN x} prints \kbd{x} in raw format, followed by a newline and a buffer flush. This is more or less equivalent to \bprog pari_printf("%Ps\n", x); pari_flush(); @eprog \fun{void}{outmat}{GEN x} as above except if $x$ is a \typ{MAT}, in which case a multi-line display is used to display the matrix. This is prettier for small dimensions, but quickly becomes unreadable and cannot be pasted and reused for input. If all entries of $x$ are small integers, you may use the recursive features of \kbd{\%Pd} and obtain the same (or better) effect with \bprog pari_printf("%Pd\n", x); pari_flush(); @eprog\noindent A variant like \kbd{"\%5Pd"} would improve alignment by imposing 5 chars for each coefficient. Similarly if all entries are to be converted to floats, a format like \kbd{"\%5.1Pf"} could be useful. These functions write on (PARI's idea of) standard output, and must be used if you want your functions to interact nicely with \kbd{gp}. In most programs, this is not a concern and it is more flexible to write to an explicit \kbd{FILE*}, or to recover a character string: \fun{void}{pari_fprintf}{FILE *file, const char *fmt, ...} writes the remaining arguments to stream \kbd{file} according to the format specification \kbd{fmt}. \fun{char*}{pari_sprintf}{const char *fmt, ...} produces a string from the remaining arguments, according to the PARI format \kbd{fmt} (see \tet{printf}). This is the \kbd{libpari} equivalent of \tet{Strprintf}, and returns a \kbd{malloc}'ed string, which must be freed by the caller. Note that contrary to the analogous \tet{sprintf} in the \kbd{libc} you do not provide a buffer (leading to all kinds of buffer overflow concerns); the function provided is actually closer to the GNU extension \kbd{asprintf}, although the latter has a different interface. Simple variants of \tet{pari_sprintf} convert a \kbd{GEN} to a \kbd{malloc}'ed ASCII string, which you must still \kbd{free} after use: \fun{char*}{GENtostr}{GEN x}, using the current default output format (\kbd{prettymat} by default). \fun{char*}{GENtoTeXstr}{GEN x}, suitable for inclusion in a \TeX\ file. Note that we have \tet{va_list} analogs of the functions of \kbd{printf} type seen so far: \fun{void}{pari_vprintf}{const char *fmt, va_list ap} \fun{void}{pari_vfprintf}{FILE *file, const char *fmt, va_list ap} \fun{char*}{pari_vsprintf}{const char *fmt, va_list ap} \subsec{Errors}\sidx{error}\kbdsidx{e_MISC} \noindent If you want your functions to issue error messages, you can use the general error handling routine \tet{pari_err}. The basic syntax is % \bprog pari_err(e_MISC, "error message"); @eprog\noindent This prints the corresponding error message and exit the program (in library mode; go back to the \kbd{gp} prompt otherwise).\label{se:err} You can also use it in the more versatile guise \bprog pari_err(e_MISC, format, ...); @eprog\noindent where \kbd{format} describes the format to use to write the remaining operands, as in the \tet{pari_printf} function. For instance: \bprog pari_err(e_MISC, "x[%d] = %Ps is not invertible!", i, gel(x,i)); @eprog\noindent The simple syntax seen above is just a special case with a constant format and no remaining arguments. The general syntax is \fun{void}{pari_err}{numerr,...} \noindent where \kbd{numerr} is a codeword which specifies the error class and what to do with the remaining arguments and what message to print. For instance, if $x$ is a \kbd{GEN} with internal type \typ{STR}, say, \kbd{pari\_err(e\_TYPE,"extgcd", $x$)} prints the message: \bprog *** incorrect type in extgcd (t_STR), @eprog\noindent See \secref{se:errors} for details. In the libpari code itself, the general-purpose \kbd{e\_MISC} is used sparingly: it is so flexible that the corresponding error contexts (\typ{ERROR}) become hard to use reliably. Other more rigid error types are generally more useful: for instance the error context associated to the \kbd{e\_TYPE} exception above is precisely documented and contains \kbd{"extgcd"} and $x$ (not only its type) as readily available components. \subsec{Warnings} \noindent To issue a warning, use \fun{void}{pari_warn}{warnerr,...} In that case, of course, we do \emph{not} abort the computation, just print the requested message and go on. The basic example is % \bprog pari_warn(warner, "Strategy 1 failed. Trying strategy 2") @eprog\noindent which is the exact equivalent of \kbd{pari\_err(e\_MISC,...)} except that you certainly do not want to stop the program at this point, just inform the user that something important has occurred; in particular, this output would be suitably highlighted under \kbd{gp}, whereas a simple \kbd{printf} would not. The valid \emph{warning} keywords are \tet{warner} (general), \tet{warnprec} (increasing precision), \tet{warnmem} (garbage collecting) and \tet{warnfile} (error in file operation), used as follows: \bprog pari_warn(warnprec, "bnfinit", newprec); pari_warn(warnmem, "bnfinit"); pari_warn(warnfile, "close", "afile"); /* error when closing "afile" */ @eprog \subsec{Debugging output}\sidx{debugging}\sidx{format}\label{se:dbg_output} For debugging output, you can use the standard output functions, \tet{output} and \tet{pari_printf} mainly. Corresponding to the \kbd{gp} metacommand \kbd{\b x}, you can also output the \idx{hexadecimal tree} associated to an object: \fun{void}{dbgGEN}{GEN x, long nb = -1}, displays the recursive structure of \kbd{x}. If $\kbd{nb} = -1$, the full structure is printed, otherwise the leaves (non-recursive components) are truncated to \kbd{nb} words. \noindent The function \tet{output} is vital under debuggers, since none of them knows how to print PARI objects by default. Seasoned PARI developers add the following \kbd{gdb} macro to their \kbd{.gdbinit}: \bprog define i call output((GEN)$arg0) end @eprog\noindent Typing \kbd{i x} at a breakpoint in \kbd{gdb} then prints the value of the \kbd{GEN} \kbd{x} (provided the optimizer has not put it into a register, but it is rarely a good idea to debug optimized code). \noindent The global variables \teb{DEBUGLEVEL} and \teb{DEBUGMEM} (corresponding to the default \teb{debug} and \teb{debugmem}, see \secref{se:defaults}) are used throughout the PARI code to govern the amount of diagnostic and debugging output, depending on their values. You can use them to debug your own functions, especially if you \tet{install} the latter under \kbd{gp} (see \secref{se:install}). \fun{void}{dbg_pari_heap}{void} print debugging statements about the PARI stack, heap, and number of variables used. Corresponds to \kbd{\bs s} under gp. \subsec{Timers and timing output} \noindent To handle timings in a reentrant way, PARI defines a dedicated data type, \tet{pari_timer}, together with the following methods: \fun{void}{timer_start}{pari_timer *T} start (or reset) a timer. \fun{long}{timer_delay}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last reset. Resets the timer as a side effect. \fun{long}{timer_get}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last reset. Does \emph{not} reset the timer. \fun{long}{timer_printf}{pari_timer *T, char *format,...} This diagnostics function is equivalent to the following code \bprog err_printf("Time ") ... prints remaining arguments according to format ... err_printf(": %ld", timer_delay(T)); @eprog\noindent Resets the timer as a side effect. \noindent They are used as follows: \bprog pari_timer T; timer_start(&T); /* initialize timer */ ... printf("Total time: %ldms\n", timer_delay(&T)); @eprog\noindent or \bprog pari_timer T; timer_start(&T); for (i = 1; i < 10; i++) { ... timer_printf(&T, "for i = %ld (L[i] = %Ps)", i, gel(L,i)); } @eprog The following functions provided the same functionality, in a non-reentrant way, and are now deprecated. \fun{long}{timer}{void} \fun{long}{timer2}{void} \fun{void}{msgtimer}{const char *format, ...} The following function implements \kbd{gp}'s timer and should not be used in libpari programs: \fun{long}{gettime}{void} equivalent to \tet{timer_delay}$(T)$ associated to a private timer $T$. \section{Iterators, Numerical integration, Sums, Products} \subsec{Iterators} Since it is easier to program directly simple loops in library mode, some GP iterators are mainly useful for GP programming. Here are the others: \item \tet{fordiv} is a trivial iteration over a list produced by \tet{divisors}. \item \tet{forell} and \tet{forsubgroup} are currently not implemented as an iterator but as a procedure with callbacks. \fun{void}{forell}{void *E, long fun(void*, GEN), GEN a, GEN b} goes through the same curves as \tet{forell(ell,a,b,)}, calling \tet{fun(E, ell)} for each curve \kbd{ell}, stopping if \kbd{fun} returns a non-zero value. \fun{void}{forsubgroup}{void *E, long fun(void*, GEN), GEN G, GEN B} goes through the same subgroups as \tet{forsubgroup(H = G, B,)}, calling \tet{fun(E, H)} for each subgroup $H$, stopping if \kbd{fun} returns a non-zero value. \item \tet{forprime}, for which we refer you to the next subsection. \item \tet{forcomposite}, we provide an iterator over composite integers: \fun{int}{forcomposite}{forcomposite_t *T, GEN a, GEN b} initialize an iterator $T$ over composite integers in $[a,b]$; over composites $\geq a$ if $b = \kbd{NULL}$. Return $0$ if the range is known to be empty from the start (as if $b < a$ or $b < 0$), and return $1$ otherwise. \fun{GEN}{forcomposite_next}{forcomposite_t *T} returns the next composite in the range, assuming that $T$ was initialized by \tet{forcomposite_init}. \item \tet{forvec}, for which we provide a convenient iterator. To initialize the analog of \kbd{forvec(X = v, ..., flag)}, call \fun{int}{forvec_init}{forvec_t *T, GEN v, long flag} initialize an iterator $T$ over the vectors generated by \kbd{forvec(X = $v$,..., flag)}. This returns $0$ if this vector list is empty, and $1$ otherwise. \fun{GEN}{forvec_next}{forvec_t *T} returns the next element in the \kbd{forvec} sequence, or \kbd{NULL} if we are done. The return value must be used immediately or copied since the next call to the iterator destroys it: the relevant vector is updated in place. The iterator works hard to not use up PARI stack, and is more efficient when all lower bounds in the initialization vector $v$ are integers. In that case, the cost is linear in the number of tuples enumerated, and you can expect to run over more than $10^9$ tuples per minute. If speed is critical and all integers involved would fit in $C$ \kbd{long}s, write a simple direct backtracking algorithm yourself. \item \tet{forpart} is a variant of \kbd{forvec} which iterates over partitions. See the documentation of the \kbd{forpart} GP function for details. This function is available as a loop with callbacks: \fun{void}{forpart}{void *data, long (*call)(void*,GEN), long k, GEN a, GEN n} \noindent It is also available as an iterator: \fun{void}{forpart_init}{forpart_t *T, long k, GEN a, GEN n} initializes an iterator over the partitions of $k$, with length restricted by $n$, and components restricted by $a$, either of which can be set to \kbd{NULL} to run without restriction. \fun{GEN}{forpart_next}{forpart_t *T} returns the next partition, or \kbd{NULL} when all partitions have been exhausted. \fun{GEN}{forpart_prev}{forpart_t *T}returns the previous partition, or \kbd{NULL} when all partitions have been exhausted. You may \emph{not} mix calls to \tet{forpart_next} and \tet{forpart_prev}: the first one called determines the ordering used to iterate over the partitions; you can not go back since the \tet{forpart_t} structure is used in incompatible ways. \subsec{Iterating over primes}\label{se:primeiter} The library provides a high-level iterator, which stores its (private) data in a \kbd{struct} \tet{forprime_t} and runs over arbitrary ranges of primes, without ever overflowing. The iterator has two flavors, one providing the successive primes as \kbd{ulong}s, the other as \kbd{GEN}. They are initialized as follows, where we expect to run over primes $\geq a$ and $\leq b$: \fun{int}{forprime_init}{forprime_t *T, GEN a, GEN b} for the \kbd{GEN} variant, where $b = \kbd{NULL}$ means $+\infty$. \fun{int}{u_forprime_init}{forprime_t *T, ulong a, ulong b} for the \kbd{ulong} variant, where $b = \kbd{ULONG\_MAX}$ means we will run through all primes representable in a \kbd{ulong} type. Both variant return $1$ on success, and $0$ if the iterator would run over an empty interval (if $a > b$, for instance). They allocate the \tet{forprime_t} data structure on the PARI stack. \noindent The successive primes are then obtained using \fun{GEN}{forprime_next}{forprime_t *T}, returns \kbd{NULL} if no more primes are available in the interval. \fun{ulong}{u_forprime_next}{forprime_t *T}, returns $0$ if no more primes are available in the interval. These two functions leave alone the PARI stack, and write their state information in the preallocated \tet{forprime_t} struct. The typical usage is thus: \bprog forprime_t T; GEN p; pari_sp av = avma, av2; forprime_init(&T, gen_2, stoi(1000)); av2 = avma; while ( (p = forprime_next(&T)) ) { ... if ( prime_is_OK(p) ) break; avma = av2; /* delete garbage accumulated in this iteration */ } avma = av; /* delete all */ @eprog\noindent Of course, the final \kbd{avma = av} could be replaced by a \kbd{gerepile} call. Beware that swapping the \kbd{av2 = avma} and \tet{forprime_init} call would be incorrect: the first \kbd{avma = av2} would delete the \tet{forprime_t} structure! \subsec{Numerical analysis} Numerical routines code a function (to be integrated, summed, zeroed, etc.) with two parameters named \bprog void *E; GEN (*eval)(void*, GEN) @eprog\noindent The second is meant to contain all auxiliary data needed by your function. The first is such that \kbd{eval(x, E)} returns your function evaluated at \kbd{x}. For instance, one may code the family of functions $f_t: x \to (x+t)^2$ via \bprog GEN fun(void *t, GEN x) { return gsqr(gadd(x, (GEN)t)); } @eprog\noindent One can then integrate $f_1$ between $a$ and $b$ with the call \bprog intnum((void*)stoi(1), &fun, a, b, NULL, prec); @eprog\noindent Since you can set \kbd{E} to a pointer to any \kbd{struct} (typecast to \kbd{void*}) the above mechanism handles arbitrary functions. For simple functions without extra parameters, you may set \kbd{E = NULL} and ignore that argument in your function definition. \section{Catching exceptions} \subsec{Basic use} PARI provides a mechanism to trap exceptions generated via \kbd{pari\_err} using the \tet{pari_CATCH} construction. The basic usage is as follows \bprog pari_CATCH(err_code) { @com recovery branch } pari_TRY { @com main branch } pari_ENDCATCH @eprog\noindent This fragment executes the main branch, then the recovery branch \emph{if} exception \kbd{err\_code} is thrown, e.g. \kbd{e\_TYPE}. See \secref{se:errors} for the description of all error classes. The special error code \tet{CATCH_ALL} is available to catch all errors. One can replace the \tet{pari_TRY} keyword by \tet{pari_RETRY}, in which case once the recovery branch is run, we run the main branch again, still catching the same exceptions. \misctitle{Restrictions} \item Such constructs can be nested without adverse effect, the innermost handler catching the exception. \item It is \emph{valid} to leave either branch using \tet{pari_err}. \item It is \emph{invalid} to use C flow control instructions (\kbd{break}, \kbd{continue}, \kbd{return}) to directly leave either branch without seeing the \tet{pari_ENDCATCH} keyword. This would leave an invalid structure in the exception handler stack, and the next exception would crash. \item In order to leave using \kbd{break}, \kbd{continue} or \kbd{return}, one must precede the keyword by a call to \fun{void}{pari_CATCH_reset}{} disable the current handler, allowing to leave without adverse effect. \subsec{Advanced use} In the recovery branch, the exception context can be examined via the following helper routines: \fun{GEN}{pari_err_last}{} returns the exception context, as a \typ{ERROR}. The exception $E$ returned by \tet{pari_err_last} can be rethrown, using \bprog pari_err(0, E); @eprog \fun{long}{err_get_num}{GEN E} returns the error symbolic name. E.g \kbd{e\_TYPE}. \fun{GEN}{err_get_compo}{GEN E, long i} error $i$-th component, as documented in \secref{se:errors}. \noindent For instance \bprog pari_CATCH(CATCH_ALL) { /* catch everything */ GEN x, E = pari_err_last(); long code = err_get_num(E); if (code != e_INV) pari_err(0, E); /* unexpected error, rethrow */ x = err_get_compo(E, 2); /* e_INV has two components, 1: function name 2: non-invertible x */ if (typ(x) != t_INTMOD) pari_err(0, E); /* unexpected type, rethrow */ pari_CATCH_reset(); return x; /* leave ! */ @com @dots } pari_TRY { @com main branch } pari_ENDCATCH @eprog \section{A complete program} \label{se:prog} \noindent Now that the preliminaries are out of the way, the best way to learn how to use the library mode is to study a detailed example. We want to write a program which computes the gcd of two integers, together with the Bezout coefficients. We shall use the standard quadratic algorithm which is not optimal but is not too far from the one used in the PARI function \teb{bezout}. Let $x,y$ two integers and initially $ \pmatrix{s_x & s_y \cr t_x & t_y } = \pmatrix{1 & 0 \cr 0 & 1}$, so that $$ \pmatrix{s_x & s_y \cr t_x & t_y } \pmatrix{x \cr y } = \pmatrix{x \cr y }. $$ To apply the ordinary Euclidean algorithm to the right hand side, multiply the system from the left by $ \pmatrix{0 & 1 \cr 1 & -q }$, with $q = \kbd{floor}(x / y)$. Iterate until $y = 0$ in the right hand side, then the first line of the system reads $$ s_x x + s_y y = \gcd(x,y).$$ In practice, there is no need to update $s_y$ and $t_y$ since $\gcd(x,y)$ and $s_x$ are enough to recover $s_y$. The following program is now straightforward. A couple of new functions appear in there, whose description can be found in the technical reference manual in Chapter 5, but whose meaning should be clear from their name and the context. This program can be found in \kbd{examples/extgcd.c} together with a proper \kbd{Makefile}. You may ignore the first comment \bprog /* GP;install("extgcd", "GG&&", "gcdex", "./libextgcd.so"); */ @eprog\noindent which instruments the program so that \kbd{gp2c-run extgcd.c} can import the \kbd{extgcd()} routine into an instance of the \kbd{gp} interpreter (under the name \kbd{gcdex}). See the \kbd{gp2c} manual for details. \newpage \bprogfile{../examples/extgcd.c} \noindent For simplicity, the inner loop does not include any garbage 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); ... while (!gequal0(b)) { GEN r, q = dvmdii(a, b, &r), v = vx; vx = subii(ux, mulii(q, vx)); ux = v; a = b; b = r; if (low_stack(lim, stack_lim(av,1))) gerepileall(av, 4, &a, &b, &ux, &vx); } @eprog \newpage pari-2.7.5/doc/pdfmacs.tex0000644000175000017500000001206012366172547014026 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License %% Modifications to parimacro.tex to be run through pdftex instead of %% tex. Code now includes some pdf-specific code for hyperlinks. %% %% Cliff Bergman (cbergman@iastate.edu) Jan. 2000. %% % %% Set the document info \pdfoutput = 1 \pdfinfo { /Title (\TITLE) /Creator (pdfTeX) /Producer (PARI, pari@math.u-bordeaux.fr) /Author (C. Batut, K. Belabas, D. Bernardi, H. Cohen, M. Olivier) /Subject (Number Theory) } % \pdfcatalog {/PageMode /UseOutlines} % \catcode`\@=11 %% Now we redefine several of the macros so as to provide hyperlinks. % % Colors % %% We use TeX's grouping mechanism to make \currentcolor into a stack. % \def\pushcolor#1{\bgroup\pdfsetcolor{#1}} \def\popcolor{\egroup\pdfsetcolor{\currentcolor}} \def\pdfsetcolor#1{\let\currentcolor=#1\pdfliteral{#1 k}} % % % % Maybe somebody with a better eye would like to pick nicer ones. See % % the file plain/misc/pdfcolor.tex in the pdftex distribution. % % \def\Red{0 1 1 0} \def\Blue{1 1 0 0} \def\Green{1 0 1 0} \def\Black{0 0 0 1} \def\textcolor{\Black} \def\linkcolor{\Red} \def\emacscolor{\Green} \def\unixcolor{\Blue} \let\currentcolor=\textcolor \pdfsetcolor{\textcolor} % %% Bookmarks. These turned out to be a pain. In order to get nested %% bookmarks, Acrobat requires that each entry declare the number of %% subentries in advance. We do this by counting the subentries (the %% main entries are the chapters, subentries are the sections) during %% the first pass and writing them to the aux file as a macro. Then the %% bookmark entry is created on the second pass. % These keep track of the number of sections in each chapter and appendix. \newtoks\numsectok \numsectok={\or} \newtoks\numsecapptok \numsecapptok={\or} % Append #1 to the token list given in #2, separated by \or. #1 is % expanded first (needed by \numsecs) \def\append#1#2{\toks0=\expandafter{#1 \or }% \edef\act{\global\noexpand#2={\the#2 \the\toks0}}\act} \def\writesecnumbers{ % Append the number of sections to the last appendix to the toks reg. \append{\the\secno}\numsecapptok % Write the definitions of (\numsecs and \numsecapp) to the aux file. \write\aux{ \def\string\numsecs\string##1{% \string\ifcase \string##1 \the\numsectok 0 \string\else 0 \string\fi} \def\string\numsecsapp\string##1{% \string\ifcase \string##1 \the\numsecapptok 0 \string\else 0 \string\fi}}} % % Hyperlink destinations will simply be of the form: pdf@nnn, where nnn % is obtained from a new counter. \newcount\pdfdestcntr \pdfdestcntr=0 % \putdest creates a pdf destination. Currently, the destination view % is 'xyz' which means no change from the existing zoom factor. \def\putdest{\global\advance\pdfdestcntr by 1% \pdfdest name {pdf@\number\pdfdestcntr} xyz } %% It turns out that I also need a different counter for these %% destinations since they are only computed on the second pass. \newcount\pdfchapcntr \pdfchapcntr=0 \def\putchapdest{\global\advance\pdfchapcntr by1% \pdfdest name {pdfchap@\number\pdfchapcntr} fitbh } \def\chapter#1#2\par{ \ifnum\chapno=0 \else \append{\the\secno}\numsectok \fi \secno=0\global\advance\chapno by 1 \title{Chapter \number\chapno:}{#1}#2\noindent\ignorespaces \ifsecondpass \pdfoutline goto name {pdfchap@\number\pdfchapcntr} count -\numsecs\chapno {\number\chapno\ #1} \fi } \def\appendix#1{ \ifnum\appno=0 \append{\the\secno}\numsectok \else \append{\the\secno}\numsecapptok \fi \chapno=0 \global\secno=0\global\advance\appno by 1 \def\applet{\ifcase\appno\or A\or B\or C\or D\or E\or F\or G\fi} \title{Appendix \applet:}{#1}\noindent\ignorespaces \ifsecondpass \pdfoutline goto name {pdfchap@\number\pdfchapcntr} count -\numsecsapp\appno {\applet\ #1} \fi} \def\section#1{ \subsecno=0\global\advance\secno by 1 \gdef\currentlabel{\number\secno} \sectitle{\maketitle{#1}} \ifsecondpass \pdfoutline goto name {pdfchap@\number\pdfchapcntr} {\number\chapno.\number\secno\ #1} \fi } % %% FIXME: should use \[push|pop]color and not use explicitly \textcolor %% (cf install() in Chapter 3) \def\@restore{\endgraf \global\let\par\endgraf \pdfsetcolor{\textcolor}} \def\unix{\global\let\par\@restore\pdfsetcolor{\unixcolor}\annotepar{UNIX}} \def\emacs{\global\let\par\@restore\pdfsetcolor{\emacscolor}\annotepar{EMACS}} %% labels and symbolic cross-refs. For this we use the parameter to %% build the symbolic pdf destination. \@ifundef{pdfstartlink}{\global\let\pdfstartlink\pdfannotlink}{} \def\label#1{\immediate\write\aux{\string \newlabel{#1}{{\the\chapno}{\currentlabel}}} \pdfdest name {pdf@lab#1} xyz} \def\ref#1{\@ifundef{r@#1} {{\bf ??}\@errundef{#1}} {\edef\@temp{\csname r@#1\endcsname}% \def\lbl{\@ref}\def\chp{\@cref}% \pdfjumpref{#1}{\ifx\chp{\the\chapno}\lbl\else\chp.\lbl\fi}}} \def\pdfjumpref#1#2{\pdfstartlink attr {/Border [ 0 0 0 ] /H /O} goto name {pdf@lab#1}\pushcolor{\linkcolor}#2\popcolor\pdfendlink} pari-2.7.5/doc/appb.tex0000644000175000017500000000214612366172547013337 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \appendix{A Sample program and Makefile} We assume that you have installed the PARI library and include files as explained in Appendix A or in the installation guide. If you chose differently any of the directory names, change them accordingly in the Makefiles. If the program example that we have given is in the file \kbd{extgcd.c}, then a sample Makefile might look as follows. Note that the actual file {\tt examples/Makefile} is more elaborate and you should have a look at it if you intend to use {\tt install()} on custom made functions, see \secref{se:install}. \bprog CC = cc INCDIR = @includedir LIBDIR = @libdir CFLAGS = -O -I$(INCDIR) -L$(LIBDIR) all: extgcd extgcd: extgcd.c $(CC) $(CFLAGS) -o extgcd extgcd.c -lpari -lm @eprog \noindent We then give the listing of the program \kbd{examples/extgcd.c} seen in detail in \secref{se:prog}. \bprogfile{../examples/extgcd.c} \vfill\eject pari-2.7.5/doc/appa.tex0000644000175000017500000006512012463145120013320 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \appendix{Installation Guide for the UNIX Versions} \def\tocwrite#1{} \section{Required tools} 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 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 20\% speedup on most architectures. \misctitle{Optional libraries and programs} The following programs and libraries are useful 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. \item GNU \kbd{MP} library. This provides an alternative multiprecision kernel, which is faster than PARI's native one, but unfortunately binary incompatible, so the resulting PARI library SONAME is libpari-gmp. \item GNU \kbd{readline} library. This provides line editing under \kbd{gp}, an automatic context-dependent completion, and an editable history of commands. \item GNU \kbd{emacs} and the \tet{PariEmacs} package. The \kbd{gp} calculator can be run in an Emacs buffer, with all the obvious advantages if you are familiar with this editor. Note that \kbd{readline} is still useful in this case since it provides a better automatic completion than is provided by Emacs's GP-mode. \item GNU \kbd{gzip/gunzip/gzcat} package enables \kbd{gp} to read compressed data. \item \kbd{perl} provides extended online help (full text from the manual) about functions and concepts. The script handling this online help can be used under \kbd{gp} or independently. \section{Compiling the library and the \kbd{gp} calculator} \subsec{Basic configuration} Type \kbd{./Configure} \noindent in the toplevel directory. This attempts to configure PARI/GP without outside help. Note that if you want to install the end product in some nonstandard place, you can use the \kbd{--prefix} option, as in \kbd{./Configure --prefix=}\var{/an/exotic/directory} \noindent (the default prefix is \kbd{/usr/local}). For example, to build a package for a Linux distribution, you may want to use \kbd{./Configure --prefix=/usr} This phase extracts some files and creates a \var{build directory}, names \kbd{O}\var{osname}\kbd{-}\var{arch}, where the object files and executables will be built. The \var{osname} and \var{arch} components depends on your architecture and operating system, thus you can build PARI/GP for several different machines from the same source tree (the builds are independent and can be done simultaneously). Decide whether you agree with what \kbd{Configure} printed on your screen, in particular the architecture, compiler and optimization flags. Look for messages prepended by \kbd{\#\#\#}, which report genuine problems. Look especially for the \kbd{gmp}, \kbd{readline} and \kbd{X11} libraries, and the \kbd{perl} and \kbd{gunzip} (or \kbd{zcat}) binaries. If anything should have been found and was not, consider that \kbd{Configure} failed and follow the instructions in section~3. The \kbd{Configure} run creates a file \kbd{config.log} in the build directory, which contains debugging information --- in particular, all messages from compilers --- that may help diagnose problems. This file is erased and recreated from scratch each time \kbd{Configure} is run. \subsec{Advanced configuration} \kbd{Configure} accepts many other flags, and you may use any number of them to build quite a complicated configuration command. See \kbd{Configure --help} for a complete list. In particular, there are sets of flags related to GNU MP (\kbd{--with-gmp*}) and GNU readline library (\kbd{--with-readline*}). Here, we focus on the non-obvious ones: \kbd{--tune}: fine tunes the library for the host used for compilation. This adjusts thresholds by running a large number of comparative tests and creates a file \kbd{tune.h} in the build directory, that will be used from now on, overriding the ones in \kbd{src/kernel/none/} and \kbd{src/kernel/gmp/}. It will take a while: about 30 minutes. Expect a small performance boost, perhaps a 10\% speed increase compared to default settings. If you are using GMP, tune it first, then PARI. Make sure you tune PARI on the machine that will actually run your computations. Do not use a heavily loaded machine for tunings. You may speed up the compilation by using a parallel make: \bprog env MAKE="make -j4" Configure --tune @eprog \kbd{--graphic=}\var{lib}: enables a particular graphic library. The default is \kbd{X11} on most platforms, but PARI can use \kbd{Qt}, \kbd{fltk}, \kbd{ps}, or \kbd{win32} (GDI). \kbd{--time=}\var{function}: chooses a timing function. The default usually works fine, however you can use a different one that better fits your needs. PARI can use \kbd{getrusage}, \kbd{clock\_gettime}, \kbd{times} or \kbd{ftime} as timing functions. (Not all timing functions are available on all platforms.) The three first functions give timings in terms of CPU usage of the current task, approximating the complexity of the algorithm. The last 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}. The remaining options are specific to parallel programming. We provide an \emph{Introduction to parallel GP programming} in the file \kbd{doc/parallel.dvi}, and to multi-threaded \kbd{libpari} programs in Appendix~D. Beware that these options change the library ABI: \kbd{--mt=}\var{engine}: specify the engine used for parallel computations. Supported value are \item single: (default) no parallellism. \item pthread: use POSIX threads. This is well-suited for multi-core systems. Setting this option also set \kbd{--enable-tls}, see below. This option requires the pthread library. For benchmarking, it is often useful to set \kbd{--time=ftime} so that GP report wall-clock instead of the sum of the time spent by each thread. \item mpi: use the MPI interface to parallelism. This allows to take advantage of clusters using MPI. This option requires a MPI library. It is usually necessary to set the environment variable \kbd{CC} to \kbd{mpicc}. \kbd{--enable-tls}: build the thread-safe version of the library. Implied by \kbd{--mt=pthread}. This tends to slow down the \emph{shared} library \kbd{libpari.so} by about $15\%$, so you probably want to use the static library \kbd{libpari.a} instead. \subsec{Compilation} To compile the \kbd{gp} binary and build the documentation, type \kbd{make all} \noindent To only compile the \kbd{gp} binary, type \kbd{make gp} \noindent in the toplevel directory. If your \kbd{make} program supports parallel make, you can speed up the process by going to the build directory that \kbd{Configure} created and doing a parallel make here, for instance \kbd{make -j4} with GNU make. It should even work from the toplevel directory. \subsec{Basic tests} To test the binary, type \kbd{make bench}. This runs a quick series of tests, for a few seconds on modern machines. In many cases, this will also build a different binary (named \kbd{gp-sta} or \kbd{gp-dyn}) linked in a slightly different way and run the tests with both. (In exotic configurations, one may pass all the tests while the other fails and we want to check for this.) To test only the default binary, use \kbd{make dobench} which starts the bench immediately. If a \kbd{[BUG]} message shows up, something went wrong. The testing utility directs you to files containing the differences between the test output and the expected results. Have a look and decide for yourself if something is amiss. If it looks like a bug in the Pari system, we would appreciate a report, see the last section. \subsec{Cross-compiling} When cross-compiling, you can set the environment variable \kbd{RUNTEST} to a program that is able to run the target binaries, e.g. an emulator. It will be used for both the \kbd{Configure} tests and \kbd{make bench}. \section{Troubleshooting and fine tuning} In case the default \kbd{Configure} run fails miserably, try \kbd{./Configure -a} \noindent (interactive mode) and answer all the questions: there are about 30 of them, and default answers are provided. If you accept all default answers, \kbd{Configure} will fail just the same, so be wary. In any case, we would appreciate a bug report (see the last section). \subsec{Installation directories} The precise default destinations are as follows: the \kbd{gp} binary, the scripts \kbd{gphelp} and \kbd{tex2mail} go to \kbd{\$prefix/bin}. The pari library goes to \kbd{\$prefix/lib} and include files to \kbd{\$prefix/include/pari}. Other system-dependent data go to \kbd{\$prefix/lib/pari}. Architecture independent files go to various subdirectories of \kbd{\$share\_prefix}, which defaults to \kbd{\$prefix/share}, and can be specified via the \kbd{--share-prefix} argument. Man pages go into \kbd{\$share\_prefix/man}, and other system-independent data under \kbd{\$share\_prefix/pari}: documentation, sample GP scripts and C code, extra packages like \kbd{elldata} or \kbd{galdata}. \noindent You can also set directly \kbd{--bindir} (executables), \kbd{--libdir} (library), \kbd{--includedir} (include files), \kbd{--mandir} (manual pages), \kbd{--datadir} (other architecture-independent data), and finally \kbd{--sysdatadir} (other architecture-dependent data). \subsec{Environment variables} \kbd{Configure} lets the following environment variable override the defaults if set: \kbd{CC}: C compiler. \kbd{DLLD}: Dynamic library linker. \kbd{LD}: Static linker. \noindent For instance, \kbd{Configure} may avoid \kbd{/bin/cc} on some architectures due to various problems which may have been fixed in your version of the compiler. You can try \kbd{env CC=cc Configure} \noindent and compare the benches. Also, if you insist on using a \kbd{C++} compiler and run into trouble with a fussy \kbd{g++}, try to use \kbd{g++ -fpermissive}. \noindent The contents of the following variables are \emph{appended} to the values computed by \kbd{Configure}: \kbd{CFLAGS}: Flags for \kbd{CC}. \kbd{CPPFLAGS}: Flags for \kbd{CC} (preprocessor). \kbd{LDFLAGS}: Flags for \kbd{LD}. \noindent The contents of the following variables are \emph{prepended} to the values computed by \kbd{Configure}: \kbd{C\_INCLUDE\_PATH} is prepended to the list of directories searched for include files. Note that adding \kbd{-I} flags to \kbd{CFLAGS} is not enough since \kbd{Configure} sometimes relies on finding the include files and parsing them, and it does not parse \kbd{CFLAGS} at this time. \kbd{LIBRARY\_PATH} is prepended to the list of directories searched for libraries. \noindent You may disable inlining by adding \kbd{-DDISABLE\_INLINE} to \kbd{CFLAGS}, and prevent the use of the \kbd{volatile} keyword with \kbd{-DDISABLE\_VOLATILE}. \subsec{Debugging/profiling}: If you also want to debug the PARI library, \kbd{Configure -g} \noindent creates a directory \kbd{O$xxx$.dbg} containing a special \kbd{Makefile} ensuring that the \kbd{gp} and PARI library built there is suitable for debugging. If you want to profile \kbd{gp} or the library, using \kbd{gprof} for instance, \kbd{Configure -pg} \noindent will create an \kbd{O$xxx$.prf} directory where a suitable version of PARI can be built. The \kbd{gp} binary built above with \kbd{make all} or \kbd{make gp} is optimized. If you have run \kbd{Configure -g} or \kbd{-pg} and want to build a special purpose binary, you can \kbd{cd} to the \kbd{.dbg} or \kbd{.prf} directory and type \kbd{make gp} there. You can also invoke \kbd{make gp.dbg} or \kbd{make gp.prf} directly from the toplevel. \subsec{Multiprecision kernel} The kernel can be specified via the \kbd{--kernel=\emph{fully\_qualified\_kernel\_name}} \noindent switch. The PARI kernel consists of two levels: Level 0 (operation on words) and Level 1 (operation on multi-precision integers and reals), which can take the following values. Level 0: \kbd{auto} (as detected), \kbd{none} (portable C) or one of the assembler micro-kernels \bprog alpha hppa hppa64 ia64 ix86 x86_64 m68k ppc ppc64 sparcv7 sparcv8_micro sparcv8_super @eprog Level 1: \kbd{auto} (as detected), \kbd{none} (native code only), or \kbd{gmp} \noindent\item A fully qualified kernel name is of the form \kbd{\var{Level0}-\var{Level1}}, the default value being \kbd{auto-auto}. \noindent\item A \emph{name} not containing a dash '\kbd{-}' is an alias for a fully qualified kernel name. An alias stands for \kbd{\emph{name}-none}, but \kbd{gmp} stands for \kbd{auto-gmp}. \subsec{Problems related to readline} \kbd{Configure} does not try very hard to find the \kbd{readline} library and include files. If they are not in a standard place, it will not find them. You can invoke \kbd{Configure} with one of the following arguments: \kbd{--with-readline[=\emph{prefix to \kbd{lib/libreadline}.xx and \kbd{include/readline.h}}]} \kbd{--with-readline-lib=\emph{path to \kbd{libreadline}.xx}} \kbd{--with-readline-include=\emph{path to \kbd{readline.h}}} \misctitle{Known problems} \item on Linux: Linux distributions have separate \kbd{readline} and \kbd{readline-devel} packages. You need both of them installed to compile gp with readline support. If only \kbd{readline} is installed, \kbd{Configure} will complain. \kbd{Configure} may also complain about a missing libncurses.so, in which case, you have to install the \kbd{ncurses-devel} package (some distributions let you install \kbd{readline-devel} without \kbd{ncurses-devel}, which is a bug in their package dependency handling). \item on OS X.4 or higher: these systems comes equipped with a fake \kbd{readline}, which is not sufficient for our purpose. As a result, gp is 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/ @eprog \subsec{Testing} \subsubsec{Known problems} if \kbd{BUG} shows up in \kbd{make bench} \item \kbd{program}: the GP function \kbd{install} may not be available on your platform, triggering an error message (``not yet available for this architecture''). \item If when running \kbd{gp-dyn}, you get a message of the form \kbd{ld.so: warning: libpari.so.$xxx$ has older revision than expected $xxx$} \noindent (possibly followed by more errors), you already have a dynamic PARI library installed \emph{and} a broken local configuration. Either remove the old library or unset the \kbd{LD\_LIBRARY\_PATH} environment variable. Try to disable this variable in any case if anything \emph{very} wrong occurs with the \kbd{gp-dyn} binary, like an Illegal Instruction on startup. It does not affect \kbd{gp-sta}. \item Some implementations of the \kbd{diff} utility (on HPUX for instance) output \kbd{No differences encountered} or some similar message instead of the expected empty input, thus producing a spurious \kbd{[BUG]} message. \subsubsec{Some more testing} [{\sl Optional\/}] You can test \kbd{gp} in compatibility mode with \kbd{make test-compat}. If you want to test the graphic routines, use \kbd{make test-ploth}. You will have to click on the mouse button after seeing each image. There will be eight of them, probably shown twice (try to resize at least one of them as a further test). The \kbd{make bench}, \kbd{make test-compat} and \kbd{make test-ploth} runs all produce a Postscript file \kbd{pari.ps} in \kbd{O$xxx$} which you can send to a Postscript printer. The output should bear some similarity to the screen images. \subsubsec{Heavy-duty testing} [{\sl Optional\/}] There are a few extra tests which should be useful only for developers. \kbd{make test-kernel} checks whether the low-level kernel seems to work, and provides simple diagnostics if it does not. Only useful if \kbd{make bench} fails horribly, e.g.~things like \kbd{1+1} do not work. \kbd{make test-all} runs all available test suites. Thorough, but slow. Some of the tests require extra packages (\kbd{elldata}, \kbd{galdata}, etc.) to be available. If you want to test such an extra package \emph{before} \kbd{make install} (which would install it to its final location, where \kbd{gp} expects to find it), run \bprog env GP_DATA_DIR=$PWD/data make test-all @eprog\noindent from the PARI toplevel directory, otherwise the test will fail. \kbd{make test-io} tests writing to and reading from files. It requires a working \kbd{system()} command (fails on Windows + MingW). \kbd{make test-time} tests absolute and relative timers. This test has a tendency to fail when the machine is heavily loaded or if the granularity of the chosen system timer is bigger than 2ms. Try it a few times before reporting a problem. \section{Installation} When everything looks fine, type \kbd{make install} \noindent You may have to do this with superuser privileges, depending on the target directories. (Tip for MacOS X beginners: use \kbd{sudo make install}.) In this case, it is advised to type \kbd{make all} first to avoid running unnecessary commands as \kbd{root}. \misctitle{Caveat} Install directories are created honouring your \kbd{umask} settings: if your umask is too restrictive, e.g.~\kbd{077}, the installed files will not be world-readable. (Beware that running \kbd{sudo} may change your user umask.) This installs in the directories chosen at \kbd{Configure} time the default \kbd{gp} executable (probably \kbd{gp-dyn}) under the name \kbd{gp}, the default PARI library (probably \kbd{libpari.so}), the necessary include files, the manual pages, the documentation and help scripts. To save on disk space, you can manually \kbd{gzip} some of the documentation files if you wish: \kbd{usersch*.tex} and all \kbd{dvi} files (assuming your \kbd{xdvi} knows how to deal with compressed files); the online-help system can handle it. \subsec{Static binaries and libraries} By default, if a dynamic library \kbd{libpari.so} can be built, the \kbd{gp} binary we install is \kbd{gp-dyn}, pointing to \kbd{libpari.so}. On the other hand, we can build a \kbd{gp} binary into which the \kbd{libpari} is statically linked (the library code is copied into the binary); that binary is not independent of the machine it was compiled on, and may still refer to other dynamic libraries than \kbd{libpari}. You may want to compile your own programs in the same way, using the static \kbd{libpari.a} instead of \kbd{libpari.so}. By default this static library \kbd{libpari.a} is not created. If you want it as well, use the target \kbd{make install-lib-sta}. You can install a statically linked \kbd{gp} with the target \kbd{make install-bin-sta}. As a rule, programs linked statically (with \kbd{libpari.a}) may be slightly faster (about 5\% gain, possibly up to 20\% when using \kbd{pthreads}), but use more disk space and take more time to compile. They are also harder to upgrade: you will have to recompile them all instead of just installing the new dynamic library. On the other hand, there is no risk of breaking them by installing a new pari library. \subsec{Extra packages} The following optional packages endow PARI with some extra capabilities: \item \kbd{elldata}: This package contains the elliptic curves in John Cremona's database. It is needed by the functions \kbd{ellidentify}, \kbd{ellsearch}, \kbd{forell} and can be used by \kbd{ellinit} to initialize a curve given by its standard code. \item \kbd{galdata}: The default \kbd{polgalois} function can only compute Galois groups of polynomials of degree less or equal to 7. Install this package if you want to handle polynomials of degree bigger than 7 (and less than 11). \item \kbd{seadata}: This package contains the database of modular polynomials extracted from the ECHIDNA databases and computed by David R. Kohel. It is needed by the functions \kbd{ellap} and \kbd{ellgroup} for primes larger than $10^{20}$. \item \kbd{galpol}: This package contains the GALPOL database of polynomials defining Galois extensions of the rationals, accessed by \kbd{galoisgetpol}. \medskip To install package \emph{pack}, you need to fetch the separate archive: \emph{pack}\kbd{.tgz} which you can download from the \kbd{pari} server. Copy the archive in the PARI toplevel directory, then extract its contents; these will go to \kbd{data/\emph{pack}/}. Typing \kbd{make install} installs all such packages. \subsec{The \kbd{GPRC} file} Copy the file \kbd{misc/gprc.dft} (or \kbd{gprc.dos} if you are using \kbd{GP.EXE}) to \kbd{\$HOME/.gprc}. Modify it to your liking. For instance, if you are not using an ANSI terminal, remove control characters from the \kbd{prompt} variable. You can also enable colors. If desired, read \kbd{\$datadir/misc/gpalias} from the \kbd{gprc} file, which provides some common shortcuts to lengthy names; fix the path in gprc first. (Unless you tampered with this via Configure, \kbd{datadir} is \kbd{\$prefix/share/pari}.) If you have superuser privileges and want to provide system-wide defaults, copy your customized \kbd{.gprc} file to \kbd{/etc/gprc}. In older versions, \kbd{gphelp} was hidden in pari lib directory and was not meant to be used from the shell prompt, but not anymore. If gp complains it cannot find \kbd{gphelp}, check whether your \kbd{.gprc} (or the system-wide \kbd{gprc}) does contain explicit paths. If so, correct them according to the current \kbd{misc/gprc.dft}. \section{Getting Started} \subsec{Printable Documentation} Building gp with \kbd{make all} also builds its documentation. You can also type directly \kbd{make doc}. In any case, you need a working (plain) \TeX\ installation. After that, the \kbd{doc} directory contains various \kbd{dvi} files: \kbd{libpari.dvi} (manual for the PARI library), \kbd{users.dvi} (manual for the \kbd{gp} calculator), \kbd{tutorial.dvi} (a tutorial), and \kbd{refcard.dvi} (a reference card for GP). You can send these files to your favorite printer in the usual way, probably via \kbd{dvips}. The reference card is also provided as a \kbd{PostScript} document, which may be easier to print than its \kbd{dvi} equivalent (it is in Landscape orientation and assumes A4 paper size). \noindent If \kbd{pdftex} is part of your \TeX\ setup, you can produce these documents in PDF format, which may be more convenient for online browsing (the manual is complete with hyperlinks); type \kbd{make docpdf} \noindent All these documents are available online from PARI home page (see the last section). \subsec{C programming} Once all libraries and include files are installed, you can link your C programs to the PARI library. A sample makefile \kbd{examples/Makefile} is provided to illustrate the use of the various libraries. Type \kbd{make all} in the \kbd{examples} directory to see how they perform on the \kbd{extgcd.c} program, which is commented in the manual. This should produce a statically linked binary \kbd{extgcd-sta} (standalone), a dynamically linked binary \kbd{extgcd-dyn} (loads libpari at runtime) and a shared library \kbd{libextgcd}, which can be used from \kbd{gp} to \kbd{install} your new \kbd{extgcd} command. The standalone binary should be bulletproof, but the other two may fail for various reasons. If when running \kbd{extgcd-dyn}, you get a message of the form ``DLL not found'', then stick to statically linked binaries or look at your system documentation to see how to indicate at linking time where the required DLLs may be found! (E.g.~on Windows, you will need to move \kbd{libpari.dll} somewhere in your \kbd{PATH}.) \subsec{GP scripts} Several complete sample GP programs are also given in the \kbd{examples} directory, for example Shanks's SQUFOF factoring method, the Pollard rho factoring method, the Lucas-Lehmer primality test for 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/ @eprog\noindent 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/ @eprog\noindent 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}. \smallskip 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 @eprog\noindent 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. \item \kbd{pari-dev}: for everything related to the development of PARI, including suggestions, technical questions or patch submissions. Bug reports can be discussed here, but as a rule it is better to submit them directly to the BTS. \item \kbd{pari-users}: for everything else. \noindent You may send an email to the last two without being subscribed. To subscribe, send an message respectively to \def\@{@} \bprog pari-announce-request@@pari.math.u-bordeaux.fr pari-users-request@@pari.math.u-bordeaux.fr pari-dev-request@@pari.math.u-bordeaux.fr @eprog\noindent with the word \kbd{subscribe} in the \kbd{Subject:}. You can also write to us at the address \bprog pari@@math.u-bordeaux.fr @eprog\noindent but we cannot promise you will get an individual answer. \smallskip If you have used PARI in the preparation of a paper, please cite it in the following form (BibTeX format): \bprog @@preamble{\usepackage{url}} @@manual{PARI2, organization = "{The PARI~Group}", title = "{PARI/GP version @vers}", year = 2015, address = "Bordeaux", note = "available from \url{http://pari.math.u-bordeaux.fr/}" } @eprog \smallskip \noindent In any case, if you like this software, we would be indebted if you could send us an email message giving us some information about yourself and what you use PARI for. \medskip {\bf Good luck and enjoy!} \vfill\eject pari-2.7.5/doc/appd.tex0000644000175000017500000000626512405547147013343 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \appendix{PARI and threads} To use PARI in multi-threaded programs, you must configure it using \kbd{Configure --enable-tls}. Your system must implement the \kbd{\_\_thread} storage class. As a major side effect, this breaks the \kbd{libpari} ABI: the resulting library is not compatible with the old one, and \kbd{-tls} is appended to the PARI library \kbd{soname}. On the other hand, this library is now thread-safe. PARI provides some functions to set up PARI subthreads\sidx{threads}. In our model, each concurrent thread needs its own PARI stack. The following scheme is used: \noindent Child thread: \bprog void *child_thread(void *arg) { GEN data = pari_thread_start((struct pari_thread*)arg); GEN result = ...; /* Compute result from data */ pari_thread_close(); return (void*)result; } @eprog \noindent Parent thread: \bprog pthread_t th; struct pari_thread pth; GEN data, result; pari_thread_alloc(&pth, s, data); pthread_create(&th, NULL, &child_thread, (void*)&pth); /* start child */ ... /* do stuff in parent */ pthread_join(th, (void*)&result); /* wait until child terminates */ result = gcopy(result); /* copy result from thread stack to main stack */ 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 argument \kbd{arg}, with the PARI thread data \kbd{pth}. \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 \tet{pthread_join} in the parent. Any \kbd{GEN} objects returned by the child in the thread stack need to be saved before running this command. \fun{void}{pari_thread_init}{void} Initialize the thread-local PARI data structures. This function is called by \kbd{pari\_thread\_start}. \fun{GEN}{pari_thread_start}{struct pari_thread *t} Initialize the thread-local PARI data structures and set up the thread stack using the PARI thread data \kbd{pth}. This function returns the thread argument \kbd{arg} that was given to \kbd{pari\_thread\_alloc}. \fun{void}{pari_thread_close}{void} Free the thread-local PARI data structures, but keeping the thread stack, so that a \kbd{GEN} returned by the thread remains valid. \noindent Under this model, some PARI states are reset in new threads. In particular \item the random number generator is reset to the starting seed; \item the system stack exhaustion checking code, meant to catch infinite recursions, is disabled (use \kbd{pari\_stackcheck\_init()} to reenable it); \item cached real constants (returned by \kbd{mppi}, \kbd{mpeuler} and \kbd{mplog2}) are not shared between threads and will be recomputed as needed; \noindent The following sample program can be compiled using \bprog cc thread.c -o thread.o -lpari -lpthread @eprog\noindent (Add \kbd{-I/-L} paths as necessary.) \noindent\bprogfile{../examples/thread.c} \vfill\eject pari-2.7.5/doc/paricfg.tex.in0000644000175000017500000000034411636712103014416 0ustar billbill\begingroup \catcode`\&=12 \catcode`\_=12 \catcode`\$=12 \catcode`\#=12 \catcode`\%=12 \catcode`\^=13 \catcode`\~=13 \gdef\vers{@version@} \gdef\includedir{@includedir@} \gdef\libdir{@libdir@} \gdef\datadir{@datadir@} \endgroup pari-2.7.5/doc/usersch6.tex0000644000175000017500000027152512431365114014153 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Technical Reference Guide for Algebraic Number Theory} \section{General Number Fields} \subsec{Number field types} None of the following routines thoroughly check their input: they distinguish between \emph{bona fide} structures as output by PARI routines, but designing perverse data will easily fool them. To give an example, a square matrix will be interpreted as an ideal even though the $\Z$-module generated by its columns may not be an $\Z_K$-module (i.e. the expensive \kbd{nfisideal} routine will \emph{not} be called). \fun{long}{nftyp}{GEN x}. Returns the type of number field structure stored in \kbd{x}, \tet{typ_NF}, \tet{typ_BNF}, or \tet{typ_BNR}. Other answers are possible, meaning \kbd{x} is not a number field structure. \fun{GEN}{get_nf}{GEN x, long *t}. Extract an \var{nf} structure from \kbd{x} if possible and return it, otherwise return \kbd{NULL}. Sets \kbd{t} to the \kbd{nftyp} of \kbd{x} in any case. \fun{GEN}{get_bnf}{GEN x, long *t}. Extract a \kbd{bnf} structure from \kbd{x} if possible and return it, otherwise return \kbd{NULL}. Sets \kbd{t} to the \kbd{nftyp} of \kbd{x} in any case. \fun{GEN}{get_nfpol}{GEN x, GEN *nf} try to extract an \var{nf} structure from \kbd{x}, and sets \kbd{*nf} to \kbd{NULL} (failure) or to the \var{nf}. Returns the (monic, integral) polynomial defining the field. \fun{GEN}{get_bnfpol}{GEN x, GEN *bnf, GEN *nf} try to extract a \var{bnf} and an \var{nf} structure from \kbd{x}, and sets \kbd{*bnf} and \kbd{*nf} to \kbd{NULL} (failure) or to the corresponding structure. Returns the (monic, integral) polynomial defining the field. \fun{GEN}{checknf}{GEN x} if an \var{nf} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. The more general \kbd{get\_nf} is often more flexible. \fun{GEN}{checkbnf}{GEN x} if an \var{bnf} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. The more general \kbd{get\_bnf} is often more flexible. \fun{void}{checkbnr}{GEN bnr} Raise an exception if the argument is not a \var{bnr} structure. \fun{void}{checkbnrgen}{GEN bnr} Raise an exception if the argument is not a \var{bnr} structure, complete with explicit generators for the ray class group. This is normally useless and \tet{checkbnr} should be instead, unless you are absolutely certain that the generators will be needed at a later point, and you are about to embark in a costly intermediate computation. PARI functions do check that generators are present in \var{bnr} before accessing them: they will raise an error themselves; many functions that may require them, e.g. \kbd{bnrconductor}, often do not actually need them. \fun{void}{checkrnf}{GEN rnf} Raise an exception if the argument is not an \var{rnf} structure. \fun{void}{checkbid}{GEN bid} Raise an exception if the argument is not a \var{bid} structure. \fun{GEN}{checkgal}{GEN x} if a \var{galoisinit} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. \fun{void}{checksqmat}{GEN x, long N} check whether \kbd{x} is a square matrix of dimension \kbd{N}. May be used to check for ideals if \kbd{N} is the field degree. \fun{void}{checkprid}{GEN pr} Raise an exception if the argument is not a prime ideal structure. \fun{GEN}{get_prid}{GEN ideal} return the underlying prime ideal structure if one can be extracted from \kbd{ideal} (ideal or extended ideal), and return \kbd{NULL} otherwise. \fun{void}{checkabgrp}{GEN v} Raise an exception if the argument is not an abelian group structure, i.e. a \typ{VEC} with either $2$ or $3$ entries: $[N,\var{cyc}]$ or $[N,\var{cyc}, \var{gen}]$. \fun{GEN}{abgrp_get_no}{GEN x} extract the cardinality $N$ from an abelian group structure. \fun{GEN}{abgrp_get_cyc}{GEN x} extract the elementary divisors \var{cyc} from an abelian group structure. \fun{GEN}{abgrp_get_gen}{GEN x} extract the generators \var{gen} from an abelian group structure. \fun{void}{checkmodpr}{GEN modpr} Raise an exception if the argument is not a prime ideal structure. \fun{GEN}{checknfelt_mod}{GEN nf, GEN x, const char *s} given an \var{nf} structure \kbd{nf} and a \typ{POLMOD} \kbd{x}, return the associated polynomial representative (shallow) if \kbd{x} and \kbd{nf} are compatible. Raise an exception otherwise. Set $s$ to the name of the caller for a meaningful error message. \fun{void}{check_ZKmodule}{GEN x, const char *s} check whether $x$ looks like $\Z_K$-module (a pair $[A,I]$, where $A$ is a matrix and $I$ is a list of ideals; $A$ has as many columns as $I$ has elements. Otherwise raises an exception. Set $s$ to the name of the caller for a meaningful error message. \fun{long}{idealtyp}{GEN *ideal, GEN *fa} The input is \kbd{ideal}, a pointer to an ideal (or extended ideal), which is usually modified, \kbd{fa} being set as a side-effect. Returns the type of the underlying ideal among \tet{id_PRINCIPAL} (a number field element), \tet{id_PRIME} (a prime ideal) \tet{id_MAT} (an ideal in matrix form). If \kbd{ideal} pointed to an ideal, set \kbd{fa} to \kbd{NULL}, and possibly simplify \kbd{ideal} (for instance the zero ideal is replaced by \kbd{gen\_0}). If it pointed to an extended ideal, replace \kbd{ideal} by the underlying ideal and set \kbd{fa} to the factorization matrix component. \subsec{Extracting info from a \kbd{nf} structure} These functions expect a true \var{nf} argument associated to a number field $K = \Q[x]/(T)$, e.g.~a \var{bnf} will not work. Let $n = [K:\Q]$ be the field degree. \fun{GEN}{nf_get_pol}{GEN nf} returns the polynomial $T$ (monic, in $\Z[x]$). \fun{long}{nf_get_varn}{GEN nf} returns the variable number of the number field defining polynomial. \fun{long}{nf_get_r1}{GEN nf} returns the number of real places $r_1$. \fun{long}{nf_get_r2}{GEN nf} returns the number of complex places $r_2$. \fun{void}{nf_get_sign}{GEN nf, long *r1, long *r2} sets $r_1$ and $r_2$ to the number of real and complex places respectively. Note that $r_1+2r_2$ is the field degree. \fun{long}{nf_get_degree}{GEN nf} returns the number field degree, $n = r_1 + 2r_2$. \fun{GEN}{nf_get_disc}{GEN nf} returns the field discriminant. \fun{GEN}{nf_get_index}{GEN nf} returns the index of $T$, i.e. the index of the order generated by the power basis $(1,x,\ldots,x^{n-1})$ in the maximal order of $K$. \fun{GEN}{nf_get_zk}{GEN nf} returns a basis $(w_1,w_2,\ldots,w_n)$ for the maximal order of $K$. Those are polynomials in $\Q[x]$ of degree $ 0$, return $a$ in the image of $A$ such that $1-a$ is in the image of $B$. (By abuse of notation we denote $1$ the column vector $[1,0,\dots,0]$.) If such an $a$ does not exist, return \kbd{NULL}. This is the function underlying \tet{idealaddtoone}. \fun{GEN}{idealaddmultoone}{GEN nf, GEN v} given a list of $n$ (globally) coprime integer ideals $(v[i])$ returns an $n$-dimensional vector $a$ such that $a[i]\in v[i]$ and $\sum a[i] = 1$. If $[K:\Q] = N$, this routine computes the HNF reduction (with $Gl_{nN}(\Z)$ base change) of an $N\times nN$ matrix; so it is well worth pruning "useless" ideals from the list (as long as the ideals remain globally coprime). \fun{GEN}{idealappr}{GEN nf, GEN x} given a fractional ideal $x$, returns an algebraic number $\alpha$ such that $v(x) = v(\alpha)$ for all valuations such that $v(x) > 0$, and $v(\alpha) \geq 0$ at all others. \fun{GEN}{idealapprfact}{GEN nf, GEN fx} same as \tet{idealappr}, $x$ being given in factored form, as after \kbd{fx = idealfactor(nf,x)}, except that we allow $0$ exponents in the factorization. Returns an algebraic number $\alpha$ such that $v(x) = v(\alpha)$ for all valuations associated to the prime ideal decomposition of $x$, and $v(\alpha) \geq 0$ at all others. \fun{GEN}{idealcoprime}{GEN nf, GEN x, GEN y}. Given 2 integral ideals $x$ and $y$, returns an algebraic number $\alpha$ such that $\alpha x$ is an integral ideal coprime to $y$. \fun{GEN}{idealcoprimefact}{GEN nf, GEN x, GEN fy} same as \tet{idealcoprime}, except that $y$ is given in factored form, as from \tet{idealfactor}. \fun{GEN}{idealchinese}{GEN nf, GEN x, GEN y} $x$ being a prime ideal factorization (i.e.~a 2 by 2 matrix whose first column contain prime ideals, and the second column integral exponents), $y$ a vector of elements in $\var{nf}$ indexed by the ideals in $x$, computes an element $b$ such that $v_\wp(b - y_\wp) \geq v_\wp(x)$ for all prime ideals in $x$ and $v_\wp(b)\geq 0$ for all other $\wp$. \subsec{Maximal ideals} The PARI structure associated to maximal ideals is a \tev{prid} (for \emph{pr}ime \emph{id}eal), usually produced by \tet{idealprimedec} and \tet{idealfactor}. In this section, we describe the format; other sections will deal with their daily use. A \var{prid} associated to a maximal ideal $\goth{p}$ stores the following data: the underlying rational prime $p$, the ramification degree $e\geq 1$, the residue field degree $f\geq 1$, a $p$-uniformizer $\pi$ with valuation $1$ at $\goth{p}$ and valuation $0$ at all other primes dividing $p$ and a rescaled ``anti-uniformizer'' $\tau$ used to compute valuations. This $\tau$ is an algebraic integer such that $\tau/p$ has valuation $-1$ at $\goth{p}$ and valuation $0$ at all other primes dividing $p$; in particular, the valuation of $x\in\Z_K$ is positive if and only if the algebraic integer $x\tau$ is divisible by $p$ (easy to check for elements in \typ{COL} form). The following functions are shallow and return directly components of the \var{prid} \kbd{pr}: \fun{GEN}{pr_get_p}{GEN pr} returns $p$. Shallow function. \fun{GEN}{pr_get_gen}{GEN pr} returns $\pi$. Shallow function. \fun{long}{pr_get_e}{GEN pr} returns $e$. \fun{long}{pr_get_f}{GEN pr} returns $f$. \fun{GEN}{pr_get_tau}{GEN pr} returns $\tet{zk_scalar_or_multable}(\var{nf}, \tau)$, which is the \typ{INT}~$1$ iff $p$ is inert, and a \kbd{ZM} otherwise. Shallow function. \fun{int}{pr_is_inert}{GEN pr} returns $1$ if $p$ is inert, $0$ otherwise. \fun{GEN}{pr_norm}{GEN pr} returns the norm $p^f$ of the maximal ideal. \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: \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 return value is a \kbd{modpr} and \kbd{*ppr}, \kbd{*pT} and \kbd{*pp} are set as side effects. The input \kbd{*ppr} is either a maximal ideal or already a \kbd{modpr} (in which case it is replaced by the underlying maximal ideal). The residue field is realized as $\F_p[X]/(T)$ for some monic $T\in\F_p[X]$, and we set \kbd{*pT} to $T$ and \kbd{*pp} to $p$. Set $T = \kbd{NULL}$ if the prime has degree $1$ and the residue field is $\F_p$. In short, this receives (or initializes) a \kbd{modpr} structure, and extracts from it $T$, $p$ and $\goth{p}$. \fun{GEN}{nf_to_Fq}{GEN nf, GEN x, GEN modpr} returns an \kbd{Fq} congruent to $x$ modulo the maximal ideal associated to \kbd{modpr}. The output is canonical: all elements in a given residue class are represented by the same \kbd{Fq}. \fun{GEN}{Fq_to_nf}{GEN x, GEN modpr} returns an \kbd{nf} element lifting the residue field element $x$, either a \typ{INT} or an algebraic integer in \kbd{algtobasis} format. \fun{GEN}{modpr_genFq}{GEN modpr} Returns an \kbd{nf} element whose image by \tet{nf_to_Fq} is $X \pmod T$, if $\deg T>1$, else $1$. \fun{GEN}{zkmodprinit}{GEN nf, GEN pr} as \tet{nfmodprinit}, but we assume we will only reduce algebraic integers, hence do not initialize data allowing to remove denominators. More precisely, we can in fact still handle an $x$ whose rational denominator is not $0$ in the residue field (i.e. if the valuation of $x$ is non-negative at all primes dividing $p$). \fun{GEN}{zk_to_Fq_init}{GEN nf, GEN *pr, GEN *T, GEN *p} as \kbd{nf\_to\_Fq\_init}, able to reduce only $p$-integral elements. \fun{GEN}{zk_to_Fq}{GEN x, GEN modpr} as \kbd{nf\_to\_Fq}, for a $p$-integral $x$. \fun{GEN}{nfM_to_FqM}{GEN M, GEN nf,GEN modpr} reduces a matrix of \kbd{nf} elements to the residue field; returns an \kbd{FqM}. \fun{GEN}{FqM_to_nfM}{GEN M, GEN modpr} lifts an \kbd{FqM} to a matrix of \kbd{nf} elements. \fun{GEN}{nfV_to_FqV}{GEN A, GEN nf,GEN modpr} reduces a vector of \kbd{nf} elements to the residue field; returns an \kbd{FqV} with the same type as \kbd{A} (\typ{VEC} or \typ{COL}). \fun{GEN}{FqV_to_nfV}{GEN A, GEN modpr} lifts an \kbd{FqV} to a vector of \kbd{nf} elements (same type as \kbd{A}). \fun{GEN}{nfX_to_FqX}{GEN Q, GEN nf,GEN modpr} reduces a polynomial with \kbd{nf} coefficients to the residue field; returns an \kbd{FqX}. \fun{GEN}{FqX_to_nfX}{GEN Q, GEN modpr} lifts an \kbd{FqX} to a polynomial with coefficients in \kbd{nf}. \subsec{Valuations} \fun{long}{nfval}{GEN nf, GEN x, GEN P} return $v_P(x)$ \misctitle{Unsafe functions} assume \var{nf} is a genuine \kbd{nf} structure, that $P$, $Q$ are \kbd{prid}. \fun{long}{ZC_nfval}{GEN nf, GEN x, GEN P} returns $v_P(x)$, assuming $x$ is a \kbd{ZC}, representing a non-zero algebraic integer. \fun{long}{ZC_nfvalrem}{GEN nf, GEN x, GEN pr, GEN *newx} returns $v = v_P(x)$, assuming $x$ is a \kbd{ZC}, representing a non-zero algebraic integer, and sets \kbd{*newx} to $x\tau^v$ which is an algebraic integer coprime to $p$. \fun{int}{ZC_prdvd}{GEN nf, GEN x, GEN P} returns $1$ is $P$ divides $x$ and $0$ otherwise. Assumes that $x$ is a \kbd{ZC}, representing an algebraic integer. Faster than computing $v_P(x)$. \fun{int}{pr_equal}{GEN nf, GEN P, GEN Q} returns 1 is $P$ and $Q$ represent the same maximal ideal: they must lie above the same $p$ and share the same $e,f$ invariants, but the $p$-uniformizer and $\tau$ element may differ. Returns $0$ otherwise. \subsec{Signatures} ``Signs'' of the real embeddings of number field element are represented in additive notation, using the standard identification $(\Z/2\Z, +) \to (\{-1,1\},\times)$, $s\mapsto (-1)^s$. With respect to a fixed \kbd{nf} structure, a selection of real places (a divisor at infinity) is normally given as a \typ{VECSMALL} of indices of the roots \kbd{nf.roots} of the defining polynomial for the number field. For compatibility reasons, in particular under GP, the (obsolete) \kbd{vec01} form is also accepted: a \typ{VEC} with \kbd{gen\_0} or \kbd{gen\_1} entries. The following internal functions go back and forth between the two representations for the Archimedean part of divisors (GP: $0/1$ vectors, library: list of indices): \fun{GEN}{vec01_to_indices}{GEN v} given a \typ{VEC} $v$ with \typ{INT} entries 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}{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}{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 $r_1$ real embeddings of $x$, as a \typ{VECSMALL}. Linear algebra functions like \tet{Flv_add_inplace} then allow keeping track of signs in series of multiplications. If $x$ is a \typ{VEC} of number field elements, return the matrix whose columns are the signs of the $x[i]$. \fun{GEN}{nfsign_arch}{GEN nf,GEN x,GEN arch} \kbd{arch} being a list of distinct real places, either in \kbd{vec01} (\typ{VEC} with \kbd{gen\_0} or \kbd{gen\_1} entries) or \kbd{indices} (\typ{VECSMALL}) form (see \tet{vec01_to_indices}), returns the signs of $x$ at the corresponding places. This is the low-level function underlying \kbd{nfsign}. \fun{GEN}{nfsign_units}{GEN bnf, GEN archp, int add_tu} \kbd{archp} being a divisor at infinity in \kbd{indices} form (or \kbd{NULL} for the divisor including all real places), return the signs at \kbd{archp} of a system of fundamental units for the field, in the same order as \kbd{bnf.tufu} if \kbd{add\_tu} is set; and in the same order as \kbd{bnf.fu} otherwise. \fun{GEN}{nfsign_from_logarch}{GEN L, GEN invpi, GEN archp} given $L$ the vector of the $\log \sigma(x)$, where $\sigma$ runs through the (real or complex) embeddings of some number field, \kbd{invpi} being a floating point approximation to $1/\pi$, and \kbd{archp} being a divisor at infinity in \kbd{indices} form, return the signs of $x$ at the corresponding places. This is the low-level function underlying \kbd{nfsign\_units}; the latter is actually a trivial wrapper \kbd{bnf} structures include the $\log \sigma(x)$ for a system of fundamental units of the field. \fun{GEN}{set_sign_mod_divisor}{GEN nf, GEN x, GEN y, GEN module, GEN sarch} let $f = f_0f_\infty$ be the divisor represented by \kbd{module}, $x$, $y$ two number field elements. Returns $yt$ with $t = 1 \text{mod}^* f$ such that $x$ and $ty$ have the same signs at $f_\infty$; if $x = \kbd{NULL}$, make $ty$ totally positive at $f_\infty$. \kbd{sarch} is the output of \kbd{nfarchstar(nf, f0, finf)}. \fun{GEN}{nfarchstar}{GEN nf, GEN f0, GEN finf} for a divisor $f = f_0f_\infty$ represented by the integral ideal \kbd{f0} in HNF and the \kbd{finf} in \kbd{indices} form, returns $(\Z_K/f_\infty)^*$ in a form suitable for computations mod $f$. More precisely, returns $[c, g, M]$, where $c = [2,\ldots, 2]$ gives the cyclic structure of that group ($\#f_\infty$ copies of $\Z/2\Z$), $g$ a minimal system of independent generators, which are furthermore congruent to $1$ mod $f_0$ (no condition if $f_0 = \Z_K$), and $M$ is the matrix of signs of the $g[i]$ at $f_\infty$, which is square and invertible over $\F_2$. \fun{GEN}{idealprincipalunits}{GEN nf, GEN pr, long e} returns the multiplicative group $(1 + \var{pr}) / (1 + \var{pr}^e)$ as an abelian group. Faster than \tet{idealstar} when the norm of \var{pr} is large, since it avoids (useless) work in the multiplicative group of the residue field. \subsec{Maximal order and discriminant} A number field $K = \Q[X]/(T)$ is defined by a monic $T\in\Z[X]$. The low-level function computing a maximal order is \fun{void}{nfmaxord}{nfmaxord_t *S, GEN T0, long flag}, where the polynomial $T_0$ is squarefree with integer coefficients. Let $K$ be the \'etale algebra $\Q[X]/(T_0)$ and let $T = \kbd{ZX\_Q\_normalize}(T_0)$, i.e. $T = C T_0(X/L)$ is monic and integral for some $C,Q\in \Q$. The structure \tet{nfmaxord_t} is initialized by the call; it has the following fields: \bprog GEN T0, T, dT, dK; /* T0, T, discriminants of T and K */ GEN unscale; /* the integer L */ GEN index; /* index of power basis in maximal order */ GEN dTP, dTE; /* factorization of |dT|, primes / exponents */ GEN dKP, dKE; /* factorization of |dK|, primes / exponents */ GEN basis; /* Z-basis for maximal order of Q[X]/(T) */ @eprog\noindent The exponent vectors are \typ{VECSMALL}. The primes in \kbd{dTP} and \kbd{dKP} are pseudoprimes, not proven primes. We recommend restricting to $T = T_0$, i.e. either to pass the input polynomial through \tet{ZX_Q_normalize} \emph{before} the call, or to forget about $T_0$ and go on with the polynomial $T$; otherwise $\kbd{unscale}\neq 1$, all data is expressed in terms of $T\neq T_0$, and needs to be converted to $T_0$. For instance to convert the basis to $\Q[X]/(T_0)$: \bprog RgXV_unscale(S.basis, S.unscale) @eprog Instead of passing $T$, one can use the format $[T,\var{listP}]$ as in \kbd{nfbasis} or \kbd{nfinit}, which computes an order which is maximal at a set of primes, but need not be the maximal order. The \kbd{flag} is an or-ed combination of the binary flags: \tet{nf_PARTIALFACT}: do not try to fully factor \kbd{dT} and only look for primes less than \kbd{primelimit}. In that case, the elements in \kbd{dTP} and \kbd{dKP} need not all be primes. But the resulting \kbd{dK}, \kbd{index} and \kbd{basis} are correct provided there exists no prime $p > \kbd{primelimit}$ such that $p^2$ divides the field discriminant \kbd{dK}. This flag is \emph{deprecated}: the $[T,\var{listP}]$ is safer and more flexible. \tet{nf_ROUND2}: use the ROUND2 algorithm instead of the default ROUND4. This flag is \emph{deprecated}: this algorithm is consistently slower. $T$ is the input polynomial (monic \kbd{ZX}). The format $[T, \kbd{listP}]$ is also recognized, where \kbd{listP} is as in \tet{nfbasis} and is used to compute a local integral basis with respect to a specific set of primes. \fun{GEN}{indexpartial}{GEN T, GEN dT} $T$ a monic separable \kbd{ZX}, \kbd{dT} is either \kbd{NULL} (no information) or a multiple of the discriminant of $T$. Let $K = \Q[X]/(T)$ and $\Z_K$ its maximal order. Returns a multiple of the exponent of the quotient group $\Z_K/(\Z[X]/(T))$. In other word, a \emph{denominator} $d$ such that $d x\in\Z[X]/(T)$ for all $x\in\Z_K$. \subsec{Computing in the class group} We compute with arbitrary ideal representatives (in any of the various formats seen above), and call \fun{GEN}{bnfisprincipal0}{GEN bnf, GEN x, long flag}. The \kbd{bnf} structure already contains information about the class group in the form $\oplus_{i=1}^n (\Z/d_i\Z) g_i$ for canonical integers $d_i$ (with $d_n\mid\dots\mid d_1$ all $> 1$) and essentially random generators $g_i$, which are ideals in HNF. We normally do not need the value of the $g_i$, only that they are fixed once and for all and that any (non-zero) fractional ideal $x$ can be expressed uniquely as $x = (t)\prod_{i=1}^n g_i^{e_i}$, where $0 \leq e_i < d_i$, and $(t)$ is some principal ideal. Computing $e$ is straightforward, but $t$ may be very expensive to obtain explicitly. The routine returns (possibly partial) information about the pair $[e,t]$, depending on \kbd{flag}, which is an or-ed combination of the following symbolic flags: \item \tet{nf_GEN} tries to compute $t$. Returns $[e,t]$, with $t$ an empty vector if the computation failed. This flag is normally useless in non-trivial situations since the next two serve analogous purposes in more efficient ways. \item \tet{nf_GENMAT} tries to compute $t$ in factored form, which is much more efficient than \kbd{nf\_GEN} if the class group is moderately large; imagine a small ideal $x = (t)g^{10000}$: the norm of $t$ has $10000$ as many digits as the norm of $g$; do we want to see it as a vector of huge meaningless integers? The idea is to compute $e$ first, which is easy, then compute $(t)$ as $x \prod g_i^{-e_i}$ using successive \tet{idealmulred}, where the ideal reduction extracts small principal ideals along the way, eventually raised to large powers because of the binary exponentiation technique; the point is to keep this principal part in factored \emph{unexpanded} form. Returns $[e,t]$, with $t$ an empty vector if the computation failed; this should be exceedingly rare, unless the initial accuracy to which \kbd{bnf} was computed was ridiculously low (and then \kbd{bnfinit} should not have succeeded either). Setting/unsetting \kbd{nf\_GEN} has no effect when this flag is set. \item \tet{nf_GEN_IF_PRINCIPAL} tries to compute $t$ \emph{only} if the ideal is principal ($e = 0$). Returns \kbd{gen\_0} if the ideal is not principal. Setting/unsetting \kbd{nf\_GEN} has no effect when this flag is set, but setting/unsetting \kbd{nf\_GENMAT} is possible. \item \tet{nf_FORCE} in the above, insist on computing $t$, even if it requires recomputing a \kbd{bnf} from scratch. This is a last resort, and normally the accuracy of a \kbd{bnf} can be increased without trouble, but it may be that some algebraic information simply cannot be recovered from what we have: see \tet{bnfnewprec}. It should be very rare, though. In simple cases where you do not care about $t$, you may use \fun{GEN}{isprincipal}{GEN bnf, GEN x}, which is a shortcut for \kbd{bnfisprincipal0(bnf, x, 0)}. The following low-level functions are often more useful: \fun{GEN}{isprincipalfact}{GEN bnf, GEN C, GEN L, GEN f, long flag} is about the same as \kbd{bnfisprincipal0} applied to $C \prod L[i]^{f[i]}$, where the $L[i]$ are ideals, the $f[i]$ integers and $C$ is either an ideal or \kbd{NULL} (omitted). Make sure to include \tet{nf_GENMAT} in \kbd{flag}! \fun{GEN}{isprincipalfact_or_fail}{GEN bnf, GEN C, GEN L, GEN f} is for delicate cases, where we must be more clever than \kbd{nf\_FORCE} (it is used when trying to increase the accuracy of a \var{bnf}, for instance). If performs \bprog isprincipalfact(bnf,C, L, f, nf_GENMAT); @eprog\noindent but if it fails to compute $t$, it just returns a \typ{INT}, which is the estimated precision (in words, as usual) that would have been sufficient to complete the computation. The point is that \kbd{nf\_FORCE} does exactly this internally, but goes on increasing the accuracy of the \kbd{bnf}, then discarding it, which is a major inefficiency if you intend to compute lots of discrete logs and have selected a precision which is just too low. (It is sometimes not so bad since most of the really expensive data is cached in \kbd{bnf} anyway, if all goes well.) With this function, the \emph{caller} may decide to increase the accuracy using \tet{bnfnewprec} (and keep the resulting \kbd{bnf}!), or avoid the computation altogether. In any case the decision can be taken at the place where it is most likely to be correct. \subsec{Floating point embeddings, the $T_2$ quadratic form} We assume the \var{nf} is a true \kbd{nf} structure, associated to a number field $K$ of degree $n$ and signature $(r_1,r_2)$. We saw that \fun{GEN}{nf_get_M}{GEN nf} returns the $(r_1+r_2)\times n$ matrix $M$ giving the embeddings of $K$, so that if $v$ is an $n$-th dimensional \typ{COL} representing the element $\sum_{i=1}^n v[i] w_i$ of $K$, then \kbd{RgM\_RgC\_mul(M,v)} represents the embeddings of $v$. Its first $r_1$ components are real numbers (\typ{INT}, \typ{FRAC} or \typ{REAL}, usually the latter), and the last $r_2$ are complex numbers (usually of \typ{COMPLEX}, but not necessarily for embeddings of rational numbers). \fun{GEN}{embed_T2}{GEN x, long r1} assuming $x$ is the vector of floating point embeddings of some algebraic number $v$, i.e. \bprog x = RgM_RgC_mul(nf_get_M(nf), algtobasis(nf,v)); @eprog\noindent returns $T_2(v)$. If the floating point embeddings themselves are not needed, but only the values of $T_2$, it is more efficient to restrict to real arithmetic and use \bprog gnorml2( RgM_RgC_mul(nf_get_G(nf), algtobasis(nf,v))); @eprog \fun{GEN}{embednorm_T2}{GEN x, long r1} analogous to \tet{embed_T2}, applied to the \kbd{gnorm} of the floating point embeddings. Assuming that \bprog x = gnorm( RgM_RgC_mul(nf_get_M(nf), algtobasis(nf,v)) ); @eprog\noindent returns $T_2(v)$. \fun{GEN}{embed_roots}{GEN z, long r1} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return the $r_1+2r_2$ roots of its characteristic polynomial. Shallow function. \fun{GEN}{embed_disc}{GEN z, long r1, long prec} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return a floating point approximation of the discriminant of its characteristic polynomial as a \typ{REAL} of precision \kbd{prec}. \fun{GEN}{embed_norm}{GEN x, long r1} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return (a floating point approximation of) the norm of $v$. \subsec{Ideal reduction, low level} In the following routines \var{nf} is a true \kbd{nf}, associated to a number field $K$ of degree $n$: \fun{GEN}{nf_get_Gtwist}{GEN nf, GEN v} assuming $v$ is a \typ{VECSMALL} with $r_1+r_2$ entries, let $$|| x ||_v^2 = \sum_{i=1}^{r_1+r_2} 2^{v_i}\varepsilon_i|\sigma_i(x)|^2,$$ where as usual the $\sigma_i$ are the (real and) complex embeddings and $\varepsilon_i = 1$, resp.~$2$, for a real, resp.~complex place. This is a twisted variant of the $T_2$ quadratic form, the standard Euclidean form on $K\otimes \R$. In applications, only the relative size of the $v_i$ will matter. Let $G_v\in M_n(\R)$ be a square matrix such that if $x\in K$ is represented by the column vector $X$ in terms of the fixed $\Z$-basis of $\Z_K$ in \var{nf}, then $$||x||_v^2 = {}^t (G_v X) \cdot G_v X.$$ (This is a kind of Cholesky decomposition.) This function returns a rescaled copy of $G_v$, rounded to nearest integers, specifically \tet{RM_round_maxrank}$(G_v)$. Suitable for \kbd{gerepileupto}, but does not collect garbage. \fun{GEN}{nf_get_Gtwist1}{GEN nf, long i}. Simple special case. Returns the twisted $G$ matrix associated to the vector $v$ whose entries are all $0$ except the $i$-th one, which is equal to $10$. \fun{GEN}{idealpseudomin}{GEN x, GEN G}. Let $x$, $G$ be two \kbd{ZM}s, such that the product $Gx$ is well-defined. This returns a ``small'' integral linear combinations of the columns of $x$, given by the LLL-algorithm applied to the lattice $G x$. Suitable for \kbd{gerepileupto}, but does not collect garbage. In applications, $x$ is an integral ideal, $G$ approximates a Cholesky form for the $T_2$ quadratic form as returned by \tet{nf_get_Gtwist}, and we return a small element $a$ in the lattice $(x,T_2)$. This is used to implement \tet{idealred}. \fun{GEN}{idealpseudomin_nonscalar}{GEN x, GEN G}. As \tet{idealpseudomin}, but we insist of returning a non-scalar $a$ (\kbd{ZV\_isscalar} is false), if the dimension of $x$ is $> 1$. In the interpretation where $x$ defines an integral ideal on a fixed $\Z_K$ basis whose first element is $1$, this means that $a$ is not rational. \fun{GEN}{idealred_elt}{GEN nf, GEN x} shortcut for \bprog idealpseudomin(x, nf_get_roundG(nf)) @eprog \subsec{Ideal reduction, high level} \label{se:Ideal_reduction} Given an ideal $x$ this means finding a ``simpler'' ideal in the same ideal class. The public GP function is of course available \fun{GEN}{idealred0}{GEN nf, GEN x, GEN v} finds a small $a\in x$ and returns the primitive part of $x/(a)$, as an ideal in HNF. What ``small'' means depends on the parameter $v$, see the GP description. More precisely, $a$ is returned by \kbd{idealpseudomin}$(x,G)$, where $G$ is \tet{nf_get_Gtwist}$(\var{nf}, v)$ for $v\neq \kbd{NULL}$ and \tet{nf_get_roundG}$(\var{nf})$ otherwise. \noindent Usually one sets $v = \kbd{NULL}$ to obtain an element of small $T_2$ norm in $x$: \fun{GEN}{idealred}{GEN nf, GEN x} is a shortcut for \kbd{idealred0(nf,x,NULL)}. The function \kbd{idealred} remains complicated to use: in order not to lose information $x$ must be an extended ideal, otherwise the value of $a$ is lost. There is a subtlety here: the principal ideal $(a)$ is easy to recover, but $a$ itself is an instance of the principal ideal problem which is very difficult given only an \var{nf} (once a \var{bnf} structure is available, \tet{bnfisprincipal0} will recover it). It is in general simpler to use directly \tet{idealred_elt}. \fun{GEN}{idealmoddivisor}{GEN bnr, GEN x} A proof-of-concept implementation, useless in practice. If \kbd{bnr} is associated to some modulus $f$, returns a ``small'' ideal in the same class as $x$ in the ray class group modulo $f$. The reason why this is useless is that using extended ideals with principal part in a computation, there is a simple way to reduce them: simply reduce the generator of the principal part in $(\Z_K/f)^*$. \fun{GEN}{famat_to_nf_moddivisor}{GEN nf, GEN g, GEN e, GEN bid} given a true \var{nf} associated to a number field $K$, a \var{bid} structure associated to a modulus $f$, and an algebraic number in factored form $\prod g[i]^{e[i]}$, such that $(g[i],f) = 1$ for all $i$, returns a small element in $\Z_K$ congruent to it mod $f$. Note that if $f$ contains places at infinity, this includes sign conditions at the specified places. A simpler case when the conductor has no place at infinity: \fun{GEN}{famat_to_nf_modideal_coprime}{GEN nf, GEN g, GEN e, GEN f, GEN expo} as above except that the ideal $f$ is now integral in HNF (no need for a full \var{bid}), and we pass the exponent of the group $(\Z_K/f)^*$ as \kbd{expo}; any multiple will also do, at the expense of efficiency. Of course if a \var{bid} for $f$ is available, if is easy to extract $f$ and the exact value of \kbd{expo} from it (the latter is the first elementary divisor in the group structure). A useful trick: if you set \kbd{expo} to \emph{any} positive integer, the result is correct up to \kbd{expo}-th powers, hence exact if \kbd{expo} is a multiple of the exponent; this is useful when trying to decide whether an element is a square in a residue field for instance! (take \kbd{expo}$ = 2$). What to do when the $g[i]$ are not coprime to $f$, but only $\prod g[i]^{e[i]}$ is? Then the situation is more complicated, and we advise to solve it one prime divisor of $f$ at a time. Let $v$ the valuation associated to a maximal ideal \kbd{pr} and assume $v(f) = k > 0$: \fun{GEN}{famat_makecoprime}{GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN expo} returns an element in $(\Z_K/\kbd{pr}^k)^*$ congruent to the product $\prod g[i]^{e[i]}$, assumed to be globally coprime to $f$. As above, \kbd{expo} is any positive multiple of the exponent of $(\Z_K/\kbd{pr}^k)^*$, for instance $(Nv-1)p^{k-1}$, if $p$ is the underlying rational prime. You may use other values of \kbd{expo} (see the useful trick in \tet{famat_to_nf_modideal_coprime}). \subsec{Class field theory} Under GP, a class-field theoretic description of a number field is given by a triple $A$, $B$, $C$, where the defining set $[A,B,C]$ can have any of the following forms: $[\var{bnr}]$, $[\var{bnr},\var{subgroup}]$, $[\var{bnf},\var{modulus}]$, $[\var{bnf},\var{modulus},\var{subgroup}]$. You can still use directly all of (\kbd{libpari}'s routines implementing) GP's functions as described in Chapter~3, but they are often awkward in the context of \kbd{libpari} programming. In particular, it does not make much sense to always input a triple $A,B,C$ because of the fringe $[\var{bnf},\var{modulus},\var{subgroup}]$. The first routine to call, is thus \fun{GEN}{Buchray}{GEN bnf, GEN mod, long flag} initializes a \var{bnr} structure from \kbd{bnf} and modulus \kbd{mod}. \kbd{flag} is an or-ed combination of \kbd{nf\_GEN} (include generators) and \kbd{nf\_INIT} (if omitted, do not return a \var{bnr}, only the ray class group as an abelian group). In fact, a single value of \kbd{flag} actually makes sense: \kbd{nf\_GEN | nf\_INIT} to initialize a proper \var{bnr}: removing \kbd{nf\_GEN} saves very little time, but the corresponding crippled \var{bnr} structure will raise errors in most class field theoretic functions. Possibly also 0 to quickly compute the ray class group structure; \tet{bnrclassno} is faster if we only need the \emph{order} of the ray class group. Now we have a proper \var{bnr} encoding a \kbd{bnf} and a modulus, we no longer need the $[\var{bnf},\var{modulus}]$ and $[\var{bnf},\var{modulus},\var{subgroup}]$ forms, which would internally call \tet{Buchray} anyway. Recall that a subgroup $H$ is given by a matrix in HNF, whose column express generators of $H$ on the fixed generators of the ray class group that stored in our \var{bnr}. You may also code the trivial subgroup by \kbd{NULL}. \fun{GEN}{bnrconductor}{GEN bnr, GEN H, long flag} see the documentation of the GP function. \fun{long}{bnrisconductor}{GEN bnr, GEN H} returns 1 is the class field defined by the subgroup $H$ (of the ray class group mod $f$ coded in \kbd{bnr}) has conductor $f$. Returns 0 otherwise. \fun{GEN}{bnrdisc}{GEN bnr, GEN H, long flag} returns the discriminant and signature of the class field defined by \kbd{bnr} and $H$. See the description of the GP function for details. \fl\ is an or-ed combination of the flags \tet{rnf_REL} (output relative data) and \tet{rnf_COND} (return 0 unless the modulus is the conductor). \fun{GEN}{bnrsurjection}{GEN BNR, GEN bnr} \kbd{BNR} and \kbd{bnr} defined over the same field $K$, for moduli $F$ and $f$ with $F\mid f$, returns the matrix of the canonical surjection $\text{Cl}_K(F)\to \text{Cl}_K(f)$ (giving the image of the fixed ray class group generators of \kbd{BNR} in terms of the ones in \kbd{bnr}). \kbd{BNR} must include the ray class group generators. \fun{GEN}{ABC_to_bnr}{GEN A, GEN B, GEN C, GEN *H, int addgen} This is a quick conversion function designed to go from the too general (inefficient) $A$, $B$, $C$ form to the preferred \var{bnr}, $H$ form for class fields. Given $A$, $B$, $C$ as explained above (omitted entries coded by \kbd{NULL}), return the associated \var{bnr}, and set $H$ to the associated subgroup. If \kbd{addgen} is $1$, make sure that if the \var{bnr} needed to be computed, then it contains generators. \subsec{Relative equations, Galois conjugates} \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]$. Returns an absolute equation $C$ (over $\Q$) for the number field $K[X]/(B)$. $C$ is the characteristic polynomial of $b + k a$ for some roots $a$ of $A$ and $b$ of $B$, and $k$ is a small rational integer. Set \kbd{*pk} to $k$. If \kbd{pLPRS} is not \kbd{NULL} set it to $[h_0, h_1]$, $h_i\in \Q[X]$, where $h_0+h_1 Y$ is the last non-constant polynomial in the pseudo-Euclidean remainder sequence associated to $A(Y)$ and $B(X-kY)$, leading to $C = \text{Res}_Y(A(Y), B(Y-kX))$. In particular $a := -h_0/h_1$ is a root of $A$ in $\Q[X]/(C)$, and $X - ka$ is a root of $B$. \fun{GEN}{nf_rnfeq}{GEN A, GEN B} wrapper around \tet{rnfequationall} to allow mapping $K\to L$ (\kbd{eltup}) and converting elements of $L$ between absolute and relative form (\kbd{reltoabs}, \kbd{abstorel}), \emph{without} computing a full \var{rnf} structure, which is useful if the relative integral basis is not required. In fact, since $A$ may be a \typ{POL} or an \var{nf}, the integral basis of the base field is not needed either. The return value is the same as \tet{rnf_get_map}. Shallow function. \fun{GEN}{nf_rnfeqsimple}{GEN nf, GEN relpol} as \tet{nf_rnfeq} except some fields are omitted, so that only the \tet{abstorel} operation is supported. Shallow function. \fun{GEN}{eltabstorel}{GEN rnfeq, GEN x} \kbd{rnfeq} is as given by \tet{rnf_get_map} (but in this case \tet{rnfeltabstorel} is more robust), \tet{nf_rnfeq} or \tet{nf_rnfeqsimple}, return $x$ as an element of $L/K$, i.e. as a \typ{POLMOD} with \typ{POLMOD} coefficients. Shallow function. \fun{GEN}{eltabstorel_lift}{GEN rnfeq, GEN x} same as \tet{eltabstorel}, except that $x$ is returned in partially lifted form, i.e.~ as a \typ{POL} with \typ{POLMOD} coefficients. \fun{GEN}{eltreltoabs}{GEN rnfeq, GEN x} \kbd{rnfeq} is as given by \tet{rnf_get_map} (but in this case \tet{rnfeltreltoabs} is more robust) or \tet{nf_rnfeq}, return $x$ in absolute form. \fun{void}{nf_nfzk}{GEN nf, GEN rnfeq, GEN *zknf, GEN *czknf} \kbd{rnfeq} as given by \tet{nf_rnfeq}, \kbd{nf} a true \var{nf} structure, set \kbd{*zknf} and \kbd{*czknf} to a suitable representation of \kbd{nf.zk} allowing quick computation of the map $K\to L$ by the function \tet{nfeltup}, \emph{without} computing a full \var{rnf} structure, which is useful if the relative integral basis is not required. The computed values are the same as in \tet{rnf_get_nfzk}. Shallow function. \fun{GEN}{nfeltup}{GEN nf, GEN x, GEN zknf, GEN czknf} \kbd{zknf} and \kbd{czknf} are initialized by \tet{nf_nfzk} or \tet{rnf_get_nfzk} (but in this case \tet{rnfeltup} is more robust); \kbd{nf} is a true \var{nf} structure for $K$, returns $x \in K$ as a (lifted) element of $L$, in absolute form. \fun{GEN}{Rg_nffix}{const char *f, GEN T, GEN c, int lift} given a \kbd{ZX} $T$ and a ``coefficient'' $c$ supposedly belonging to $\Q[y]/(T)$, check whether this is a the case and return a cleaned up version of $c$. The string $f$ is the calling function name, used to report errors. This means that $c$ must be one of \typ{INT}, \typ{FRAC}, \typ{POL} in the variable $y$ with rational coefficients, or \typ{POLMOD} modulo $T$ which lift to a rational \typ{POL} as above. The cleanup consists in the following improvements: \item \typ{POL} coefficients are reduced modulo $T$. \item \typ{POL} and \typ{POLMOD} belonging to $\Q$ are converted to rationals, \typ{INT} or \typ{FRAC}. \item if \kbd{lift} is non-zero, convert \typ{POLMOD} to \typ{POL}, and otherwise convert \typ{POL} to \typ{POLMOD}s modulo $T$. \fun{GEN}{RgX_nffix}{const char *f, GEN T, GEN P, int lift} check whether $P$ is a polynomials with coefficients in the number field defined by the absolute equation $T(y) = 0$, where $T$ is a \kbd{ZX} and returns a cleaned up version of $P$. This checks whether $P$ is indeed a \typ{POL} with variable compatible with coefficients in $\Q[y]/(T)$, i.e. \bprog varncmp(varn(P), varn(T)) < 0 @eprog\noindent and applies \tet{Rg_nffix} to each coefficient. \fun{GEN}{RgV_nffix}{const char *f, GEN T, GEN P, int lift} as \tet{RgX_nffix} for a vector of coefficients. \fun{GEN}{polmod_nffix}{const char *f, GEN rnf, GEN x, int lift} given a \typ{POLMOD} $x$ supposedly defining an element of \var{rnf}, check this and perform \tet{Rg_nffix} cleanups. \fun{GEN}{polmod_nffix2}{const char *f, GEN T, GEN P, GEN x, int lift} as \tet{polmod_nffix}, where the relative extension is explicitly defined as $L = (\Q[y]/(T))[x]/(P)$, instead of by an \kbd{rnf} structure. \fun{long}{numberofconjugates}{GEN T, long pinit} returns a quick multiple for the number of $\Q$-automorphism of the (integral, monic) \typ{POL} $T$, from modular factorizations, starting from prime \kbd{pinit} (you can set it to $2$). This upper bounds often coincides with the actual number of conjugates. Of course, you should use \tet{nfgaloisconj} to be sure. \subsec{Obsolete routines} Still provided for backward compatibility, but should not be used in new programs. They will eventually disappear. \fun{GEN}{zidealstar}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_GEN)} \fun{GEN}{zidealstarinit}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_INIT)} \fun{GEN}{zidealstarinitgen}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_GEN|nf\_INIT)} \fun{GEN}{buchimag}{GEN D, GEN c1, GEN c2, GEN gCO} short for \bprog Buchquad(D,gtodouble(c1),gtodouble(c2), /*ignored*/0) @eprog \fun{GEN}{buchreal}{GEN D, GEN gsens, GEN c1, GEN c2, GEN RELSUP, long prec} short for \bprog Buchquad(D,gtodouble(c1),gtodouble(c2), prec) @eprog The following use a naming scheme which is error-prone and not easily extensible; besides, they compute generators as per \kbd{nf\_GEN} and not \kbd{nf\_GENMAT}. Don't use them: \fun{GEN}{isprincipalforce}{GEN bnf,GEN x} \fun{GEN}{isprincipalgen}{GEN bnf, GEN x} \fun{GEN}{isprincipalgenforce}{GEN bnf, GEN x} \fun{GEN}{isprincipalraygen}{GEN bnr, GEN x}, use \tet{bnrisprincipal}. \noindent Variants on \kbd{polred}: use \kbd{polredbest}. \fun{GEN}{factoredpolred}{GEN x, GEN fa} \fun{GEN}{factoredpolred2}{GEN x, GEN fa} \fun{GEN}{smallpolred}{GEN x} \fun{GEN}{smallpolred2}{GEN x}, use \tet{Polred}. \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} \fun{GEN}{discrayabscond}{GEN bnr,GEN subgroup} \fun{GEN}{discrayrel}{GEN bnr,GEN subgroup} \fun{GEN}{discrayrelcond}{GEN bnr,GEN subgroup} \noindent Superseded by \tet{bnrdisclist0}: \fun{GEN}{discrayabslist}{GEN bnf,GEN listes} \fun{GEN}{discrayabslistarch}{GEN bnf, GEN arch, long bound} \fun{GEN}{discrayabslistlong}{GEN bnf, long bound} \section{Galois extensions of $\Q$} This section describes the data structure output by the function \tet{galoisinit}. This will be called a \kbd{gal} structure in the following. \subsec{Extracting info from a \kbd{gal} structure} The functions below expect a \kbd{gal} structure and are shallow. See the documentation of \tet{galoisinit} for the meaning of the member functions. \fun{GEN}{gal_get_pol}{GEN gal} returns \kbd{gal.pol} \fun{GEN}{gal_get_p}{GEN gal} returns \kbd{gal.p} \fun{GEN}{gal_get_e}{GEN gal} returns the integer $e$ such that \kbd{gal.mod==gal.p\pow e}. \fun{GEN}{gal_get_mod}{GEN gal} returns \kbd{gal.mod}. \fun{GEN}{gal_get_roots}{GEN gal} returns \kbd{gal.roots}. \fun{GEN}{gal_get_invvdm}{GEN gal} \kbd{gal[4]}. \fun{GEN}{gal_get_den}{GEN gal} return \kbd{gal[5]}. \fun{GEN}{gal_get_group}{GEN gal} returns \kbd{gal.group}. \fun{GEN}{gal_get_gen}{GEN gal} returns \kbd{gal.gen}. \fun{GEN}{gal_get_orders}{GEN gal} returns \kbd{gal.orders}. \subsec{Miscellaneous functions} \fun{GEN}{nfgaloismatrix}{GEN nf, GEN s} returns the \kbd{ZM} associated to the automorphism $s$, seen as a linear operator expressend on the number field integer basis. This allows to use \bprog M = nfgaloismatrix(nf, s); sx = ZM_ZC_mul(M, x); /* or RgM_RgC_mul(M, x) if x is not integral */ @eprog\noindent instead of \bprog sx = nfgaloisapply(nf, s, x); @eprog\noindent for an algebraic integer $x$. \section{Quadratic number fields and quadratic forms} \subsec{Checks} \fun{void}{check_quaddisc}{GEN x, long *s, long *mod4, const char *f} checks whether the \kbd{GEN} $x$ is a quadratic discriminant (\typ{INT}, not a square, congruent to $0,1$ modulo $4$), and raise an exception otherwise. Set \kbd{*s} to the sign of $x$ and \kbd{*mod4} to $x$ modulo $4$ (0 or 1). \fun{void}{check_quaddisc_real}{GEN x, long *mod4, const char *f} as \tet{check_quaddisc}; check that \kbd{signe(x)} is positive. \fun{void}{check_quaddisc_imag}{GEN x, long *mod4, const char *f} as \tet{check_quaddisc}; check that \kbd{signe(x)} is negative. \subsec{\typ{QFI}, \typ{QFR}} \fun{GEN}{qfi}{GEN x, GEN y, GEN z} creates the \typ{QFI} $(x,y,z)$. \fun{GEN}{qfr}{GEN x, GEN y, GEN z, GEN d} creates the \typ{QFR} $(x,y,z)$ with distance component $d$. \fun{GEN}{qfr_1}{GEN q} given a \typ{QFR} $q$, return the unit form $q^0$. \fun{GEN}{qfi_1}{GEN q} given a \typ{QFI} $q$, return the unit form $q^0$. \subsubsec{Composition} \fun{GEN}{qficomp}{GEN x, GEN y} compose the two \typ{QFI} $x$ and $y$, then reduce the result. This is the same as \kbd{gmul(x,y)}. \fun{GEN}{qfrcomp}{GEN x, GEN y} compose the two \typ{QFR} $x$ and $y$, then reduce the result. This is the same as \kbd{gmul(x,y)}. \fun{GEN}{qfisqr}{GEN x} as \kbd{qficomp(x,y)}. \fun{GEN}{qfrsqr}{GEN x} as \kbd{qfrcomp(x,y)}. \noindent Same as above, \emph{without} reducing the result: \fun{GEN}{qficompraw}{GEN x, GEN y} \fun{GEN}{qfrcompraw}{GEN x, GEN y} \fun{GEN}{qfisqrraw}{GEN x} \fun{GEN}{qfrsqrraw}{GEN x} \fun{GEN}{qfbcompraw}{GEN x, GEN y} compose two \typ{QFI}s or two \typ{QFR}s, without reduce the result. \subsubsec{Powering} \fun{GEN}{powgi}{GEN x, GEN n} computes $x^n$ (will work for many more types than \typ{QFI} and \typ{QFR}, of course). Reduce the result. \fun{GEN}{qfrpow}{GEN x, GEN n} computes $x^n$ for a \typ{QFR} $x$, reducing along the way. If the distance component is initially $0$, leave it alone; otherwise update it. \fun{GEN}{qfbpowraw}{GEN x, long n} compute $x^n$ (pure composition, no reduction), for a \typ{QFI} or \typ{QFR} $x$. \fun{GEN}{qfipowraw}{GEN x, long n} as \tet{qfbpowraw}, for a \typ{QFI} $x$. \fun{GEN}{qfrpowraw}{GEN x, long n} as \tet{qfbpowraw}, for a \typ{QFR} $x$. \subsubsec{Solve, Cornacchia} The following functions underly \tet{qfbsolve}; $p$ denotes a prime number. \fun{GEN}{qfisolvep}{GEN Q, GEN p} solves $Q(x,y) = p$ over the integers, for a \typ{QFI} $Q$. Return \kbd{gen\_0} if there are no solutions. \fun{GEN}{qfrsolvep}{GEN Q, GEN p} solves $Q(x,y) = p$ over the integers, for a \typ{QFR} $Q$. Return \kbd{gen\_0} if there are no solutions. \fun{long}{cornacchia}{GEN d, GEN p, GEN *px, GEN *py} solves $x^2+ dy^2 = p$ over the integers, where $d > 0$. Return $1$ if there is a solution (and store it in \kbd{*x} and \kbd{*y}), $0$ otherwise. \fun{long}{cornacchia2}{GEN d, GEN p, GEN *px, GEN *py} as \kbd{cornacchia}, for the equation $x^2 + dy^2 = 4p$. \subsubsec{Prime forms} \fun{GEN}{primeform_u}{GEN x, ulong p} \typ{QFI} whose first coefficient is the prime $p$. \fun{GEN}{primeform}{GEN x, GEN p, long prec} \subsec{Efficient real quadratic forms} Unfortunately, \typ{QFR}s are very inefficient, and are only provided for backward compatibility. \item they do not contain needed quantities, which are thus constantly recomputed (the discriminant $D$, $\sqrt{D}$ and its integer part), \item the distance component is stored in logarithmic form, which involves computing one extra logarithm per operation. It is much more efficient to store its exponential, computed from ordinary multiplications and divisions (taking exponent overflow into account), and compute its logarithm at the very end. Internally, we have two representations for real quadratic forms: \item \tet{qfr3}, a container $[a,b,c]$ with at least 3 entries: the three coefficients; the idea is to ignore the distance component. \item \tet{qfr5}, a container with at least 5 entries $[a,b,c,e,d]$: the three coefficients a \typ{REAL} $d$ and a \typ{INT} $e$ coding the distance component $2^{Ne} d$, in exponential form, for some large fixed $N$. It is a feature that \kbd{qfr3} and \kbd{qfr5} have no specified length or type. It implies that a \kbd{qfr5} or \typ{QFR} will do whenever a \kbd{qfr3} is expected. Routines using these objects all require a global context, provided by a \kbd{struct qfr\_data *}: \bprog struct qfr_data { GEN D; /* discriminant, t_INT */ GEN sqrtD; /* sqrt(D), t_REAL */ GEN isqrtD; /* floor(sqrt(D)), t_INT */ }; @eprog \fun{void}{qfr_data_init}{GEN D, long prec, struct qfr_data *S} given a discriminant $D > 0$, initialize $S$ for computations at precision \kbd{prec} ($\sqrt{D}$ is computed to that initial accuracy). \noindent All functions below are shallow, and not stack clean. \fun{GEN}{qfr3_comp}{GEN x, GEN y, struct qfr_data *S} compose two \kbd{qfr3}, reducing the result. \fun{GEN}{qfr3_pow}{GEN x, GEN n, struct qfr_data *S} compute $x^n$, reducing along the way. \fun{GEN}{qfr3_red}{GEN x, struct qfr_data *S} reduce $x$. \fun{GEN}{qfr3_rho}{GEN x, struct qfr_data *S} perform one reduction step; \kbd{qfr3\_red} just performs reduction steps until we hit a reduced form. \fun{GEN}{qfr3_to_qfr}{GEN x, GEN d} recover an ordinary \typ{QFR} from the \kbd{qfr3} $x$, adding distance component $d$. Before we explain \kbd{qfr5}, recall that it corresponds to an ideal, that reduction corresponds to multiplying by a principal ideal, and that the distance component is a clever way to keep track of these principal ideals. More precisely, reduction consists in a number of reduction steps, going from the form $(a,b,c)$ to $\rho(a,b,c) = (c, -b \mod 2c, *)$; the distance component is multiplied by (a floating point approximation to) $(b + \sqrt{D}) / (b - \sqrt{D})$. \fun{GEN}{qfr5_comp}{GEN x, GEN y, struct qfr_data *S} compose two \kbd{qfr5}, reducing the result, and updating the distance component. \fun{GEN}{qfr5_pow}{GEN x, GEN n, struct qfr_data *S} compute $x^n$, reducing along the way. \fun{GEN}{qfr5_red}{GEN x, struct qfr_data *S} reduce $x$. \fun{GEN}{qfr5_rho}{GEN x, struct qfr_data *S} perform one reduction step. \fun{GEN}{qfr5_dist}{GEN e, GEN d, long prec} decode the distance component from exponential (\kbd{qfr5}-specific) to logarithmic form (as in a \typ{QFR}). \fun{GEN}{qfr_to_qfr5}{GEN x, long prec} convert a \typ{QFR} to a \kbd{qfr5} with initial trivial distance component ($= 1$). \fun{GEN}{qfr5_to_qfr}{GEN x, GEN d}, assume $x$ is a \kbd{qfr5} and $d$ was the original distance component of some \typ{QFR} that we converted using \tet{qfr_to_qfr5} to perform efficiently a number of operations. Convert $x$ to a \typ{QFR} with the correct (logarithmic) distance component. \section{Linear algebra over $\Z$} \subsec{Hermite and Smith Normal Forms} \fun{GEN}{ZM_hnf}{GEN x} returns the upper triangular Hermite Normal Form of the \kbd{ZM} $x$ (removing $0$ columns), using the \tet{ZM_hnfall} algorithm. If you want the true HNF, use \kbd{ZM\_hnfall(x, NULL, 0)}. \fun{GEN}{ZM_hnfmod}{GEN x, GEN d} returns the HNF of the \kbd{ZM} $x$ (removing $0$ columns), assuming the \typ{INT} $d$ is a multiple of the determinant of $x$. This is usually faster than \tet{ZM_hnf} (and uses less memory) if the dimension is large, $> 50$ say. \fun{GEN}{ZM_hnfmodid}{GEN x, GEN d} returns the HNF of the matrix $(x \mid d \text{Id})$ (removing $0$ columns), for a \kbd{ZM} $x$ and a \typ{INT} $d$. \fun{GEN}{ZM_hnfmodall}{GEN x, GEN d, long flag} low-level function underlying the \kbd{ZM\_hnfmod} variants. If \kbd{flag} is $0$, calls \kbd{ZM\_hnfmod(x,d)}; \kbd{flag} is an or-ed combination of: \item \tet{hnf_MODID} call \kbd{ZM\_hnfmodid} instead of \kbd{ZM\_hnfmod}, \item \tet{hnf_PART} return as soon as we obtain an upper triangular matrix, saving time. The pivots are non-negative and give the diagonal of the true HNF, but the entries to the right of the pivots need not be reduced, i.e.~they may be large or negative. \item \tet{hnf_CENTER} returns the centered HNF, where the entries to the right of a pivot $p$ are centered residues in $[-p/2, p/2[$, hence smallest possible in absolute value, but possibly negative. \fun{GEN}{ZM_hnfall}{GEN x, GEN *U, long remove} returns the upper triangular HNF $H$ of the \kbd{ZM} $x$; if $U$ is not \kbd{NULL}, set if to the matrix $U$ such that $x U = H$. If $\kbd{remove} = 0$, $H$ is the true HNF, including $0$ columns; if $\kbd{remove} = 1$, delete the $0$ columns from $H$ but do not update $U$ accordingly (so that the integer kernel may still be recovered): we no longer have $x U = H$; if $\kbd{remove} = 2$, remove $0$ columns from $H$ and update $U$ so that $x U = H$. The matrix $U$ is square and invertible unless $\kbd{remove} = 2$. This routine uses a naive algorithm which is potentially exponential in the dimension (due to coefficient explosion) but is fast in practice, although it may require lots of memory. The base change matrix $U$ may be very large, when the kernel is large. \fun{GEN}{ZM_hnfperm}{GEN A, GEN *ptU, GEN *ptperm} returns the hnf $H = P A U$ of the matrix $P A$, where $P$ is a suitable permutation matrix, and $U\in \text{Gl}_n(\Z)$. $P$ is chosen so as to (heuristically) minimize the size of $U$; in this respect it is less efficient than \kbd{ZM\_hnflll} but usually faster. Set \kbd{*ptU} to $U$ and \kbd{*pterm} to a \typ{VECSMALL} representing the row permutation associated to $P = (\delta_{i,\kbd{perm}[i]}$. If \kbd{ptU} is set to \kbd{NULL}, $U$ is not computed, saving some time; although useless, setting \kbd{ptperm} to \kbd{NULL} is also allowed. \fun{GEN}{ZM_hnflll}{GEN x, GEN *U, int remove} returns the HNF $H$ of the \kbd{ZM} $x$; if $U$ is not \kbd{NULL}, set if to the matrix $U$ such that $x U = H$. The meaning of \kbd{remove} is the same as in \tet{ZM_hnfall}. This routine uses the \idx{LLL} variant of Havas, Majewski and Mathews, which is polynomial time, but rather slow in practice because it uses an exact LLL over the integers instead of a floating point variant; it uses polynomial space but lots of memory is needed for large dimensions, say larger than 300. On the other hand, the base change matrix $U$ is essentially optimally small with respect to the $L_2$ norm. \fun{GEN}{ZM_hnfcenter}{GEN M}. Given a \kbd{ZM} in HNF $M$, update it in place so that non-diagonal entries belong to a system of \emph{centered} residues. Not suitable for gerepile. Some direct applications: the following routines apply to upper triangular integral matrices; in practice, these come from HNF algorithms. \fun{GEN}{hnf_divscale}{GEN A, GEN B,GEN t} $A$ an upper triangular \kbd{ZM}, $B$ a \kbd{ZM}, $t$ an integer, such that $C := tA^{-1}B$ is integral. Return $C$. \fun{GEN}{hnf_solve}{GEN A, GEN B} $A$ a \kbd{ZM} in upper HNF (not necessarily square), $B$ a \kbd{ZM} or \kbd{ZC}. Return $A^{-1}B$ if it is integral, and \kbd{NULL} if it is not. \fun{GEN}{hnf_invimage}{GEN A, GEN b} $A$ a \kbd{ZM} in upper HNF (not necessarily square), $b$ a \kbd{ZC}. Return $A^{-1}B$ if it is integral, and \kbd{NULL} if it is not. \fun{int}{hnfdivide}{GEN A, GEN B} $A$ and $B$ are two upper triangular \kbd{ZM}. Return $1$ if $A^{-1} B$ is integral, and $0$ otherwise. \misctitle{Smith Normal Form} \fun{GEN}{ZM_snf}{GEN x} returns the Smith Normal Form (vector of elementary divisors) of the \kbd{ZM} $x$. \fun{GEN}{ZM_snfall}{GEN x, GEN *U, GEN *V} returns \kbd{ZM\_smith(x)} and sets $U$ and $V$ to unimodular matrices such that $U\, x\, V = D$ (diagonal matrix of elementary divisors). Either (or both) $U$ or $V$ may be \kbd{NULL} in which case the corresponding matrix is not computed. \fun{GEN}{ZM_snfall_i}{GEN x, GEN *U, GEN *V, int returnvec} same as \kbd{ZM\_snfall}, except that, depending on the value of \kbd{returnvec}, we either return a diagonal matrix (as in \kbd{ZM\_snfall}, \kbd{returnvec} is 0) or a vector of elementary divisors (as in \kbd{ZM\_snf}, \kbd{returnvec} is 1) . \fun{void}{ZM_snfclean}{GEN d, GEN U, GEN V} assuming $d$, $U$, $V$ come from \kbd{d = ZM\_snfall(x, \&U, \&V)}, where $U$ or $V$ may be \kbd{NULL}, cleans up the output in place. This means that elementary divisors equal to 1 are deleted and $U$, $V$ are updated. The output is not suitable for \kbd{gerepileupto}. \fun{GEN}{ZM_snf_group}{GEN H, GEN *U, GEN *Uinv} this function computes data to go back and forth between an abelian group (of finite type) given by generators and relations, and its canonical SNF form. Given an abstract abelian group with generators $g = (g_1,\dots,g_n)$ and a vector $X=(x_i)\in\Z^n$, we write $g X$ for the group element $\sum_i x_i g_i$; analogously if $M$ is an $n\times r$ integer matrix $g M$ is a vector containing $r$ group elements. The group neutral element is $0$; by abuse of notation, we still write $0$ for a vector of group elements all equal to the neutral element. The input is a full relation matrix $H$ among the generators, i.e. a \kbd{ZM} (not necessarily square) such that $gX = 0$ for some $X\in\Z^n$ if and only if $X$ is in the integer image of $H$, so that the abelian group is isomorphic to $\Z^n/\text{Im} H$. \emph{The routine assumes that $H$ is in HNF;} replace it by its HNF if it is not the case. (Of course this defines the same group.) Let $G$ a minimal system of generators in SNF for our abstract group: if the $d_i$ are the elementary divisors ($\dots \mid d_2\mid d_1$), each $G_i$ has either infinite order ($d_i = 0$) or order $d_i > 1$. Let $D$ the matrix with diagonal $(d_i)$, then $$G D = 0,\quad G = g U_{\text{inv}},\quad g = G U,$$ for some integer matrices $U$ and $U_{\text{inv}}$. Note that these are not even square in general; even if square, there is no guarantee that these are unimodular: they are chosen to have minimal entries given the known relations in the group and only satisfy $D \mid (U U_{\text{inv}} - \text{Id})$ and $H \mid (U_{\text{inv}}U - \text{Id})$. The function returns the vector of elementary divisors $(d_i)$; if \kbd{U} is not \kbd{NULL}, it is set to $U$; if \kbd{Uinv} is not \kbd{NULL} it is set to $U_{\text{inv}}$. The function is not memory clean. The following 3 routines underly the various \tet{matrixqz} variants. In all case the $m\times n$ \typ{MAT} $x$ is assumed to have rational (\typ{INT} and \typ{FRAC}) coefficients \fun{GEN}{QM_ImQ_hnf}{GEN x} returns an HNF basis for $\text{Im}_\Q x \cap \Z^n$. \fun{GEN}{QM_ImZ_hnf}{GEN x} returns an HNF basis for $\text{Im}_\Z x \cap \Z^n$. \fun{GEN}{QM_minors_coprime}{GEN x, GEN D}, assumes $m\geq n$, and returns a matrix in $M_{m,n}(\Z)$ with the same $\Q$-image as $x$, such that the GCD of all $n\times n$ minors is coprime to $D$; if $D$ is \kbd{NULL}, we want the GCD to be $1$. \smallskip The following routines are simple wrappers around the above ones and are normally useless in library mode: \fun{GEN}{hnf}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnf}. Normally useless in library mode. \fun{GEN}{hnfmod}{GEN x, GEN d} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnfmod}. Normally useless in library mode. \fun{GEN}{hnfmodid}{GEN x,GEN d} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnfmodid}. Normally useless in library mode. \fun{GEN}{hnfall}{GEN x} calls \kbd{ZM\_hnfall(x, \&U, 1)} and returns $[H, U]$. Normally useless in library mode. \fun{GEN}{hnflll}{GEN x} calls \kbd{ZM\_hnflll(x, \&U, 1)} and returns $[H, U]$. Normally useless in library mode. \fun{GEN}{hnfperm}{GEN x} calls \kbd{ZM\_hnfperm(x, \&U, \&P)} and returns $[H, U, P]$. Normally useless in library mode. \fun{GEN}{smith}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \kbd{ZM\_smith}. Normally useless in library mode. \fun{GEN}{smithall}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \kbd{ZM\_smithall(x, \&U, \&V)} and returns $[U,V,D]$. Normally useless in library mode. \noindent Some related functions over $K[X]$, $K$ a field: \fun{GEN}{gsmith}{GEN A} the input matrix must be square, returns the elementary divisors. \fun{GEN}{gsmithall}{GEN A} the input matrix must be square, returns the $[U,V,D]$, $D$ diagonal, such that $UAV = D$. \fun{GEN}{RgM_hnfall}{GEN A, GEN *pB, long remove} analogous to \tet{ZM_hnfall}. \fun{GEN}{smithclean}{GEN z} cleanup the output of \kbd{smithall} or \kbd{gsmithall} (delete elementary divisors equal to $1$, updating base change matrices). \subsec{The LLL algorithm}\sidx{LLL} The basic GP functions and their immediate variants are normally not very useful in library mode. We briefly list them here for completeness, see the documentation of \kbd{qflll} and \kbd{qflllgram} for details: \item \fun{GEN}{qflll0}{GEN x, long flag} \fun{GEN}{lll}{GEN x} \fl = 0 \fun{GEN}{lllint}{GEN x} \fl = 1 \fun{GEN}{lllkerim}{GEN x} \fl = 4 \fun{GEN}{lllkerimgen}{GEN x} \fl = 5 \fun{GEN}{lllgen}{GEN x} \fl = 8 \item \fun{GEN}{qflllgram0}{GEN x, long flag} \fun{GEN}{lllgram}{GEN x} \fl = 0 \fun{GEN}{lllgramint}{GEN x} \fl = 1 \fun{GEN}{lllgramkerim}{GEN x} \fl = 4 \fun{GEN}{lllgramkerimgen}{GEN x} \fl = 5 \fun{GEN}{lllgramgen}{GEN x} \fl = 8 \smallskip The basic workhorse underlying all integral and floating point LLLs is \fun{GEN}{ZM_lll}{GEN x, double D, long flag}, where $x$ is a \kbd{ZM}; $D \in ]1/4,1[$ is the Lov\'{a}sz constant determining the frequency of swaps during the algorithm: a larger values means better guarantees for the basis (in principle smaller basis vectors) but longer running times (suggested value: $D = 0.99$). \misctitle{Important} This function does not collect garbage and its output is not suitable for either \kbd{gerepile} or \kbd{gerepileupto}. We expect the caller to do something simple with the output (e.g. matrix multiplication), then collect garbage immediately. \noindent\kbd{flag} is an or-ed combination of the following flags: \item \tet{LLL_GRAM}. If set, the input matrix $x$ is the Gram matrix ${}^t v v$ of some lattice vectors $v$. \item \tet{LLL_INPLACE}. If unset, we return the base change matrix $U$, otherwise the transformed matrix $x U$ or ${}^t U x U$ (\kbd{LLL\_GRAM}). Implies \tet{LLL_IM} (see below). \item \tet{LLL_KEEP_FIRST}. The first vector in the output basis is the same one as was originally input. Provided this is a shortest non-zero vector of the lattice, the output basis is still LLL-reduced. This is used to reduce 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). The last three flags are mutually exclusive, either 0 or a single one must be set: \item \tet{LLL_KER} If set, only return a kernel basis $K$ (not LLL-reduced). \item \tet{LLL_IM} If set, only return an LLL-reduced lattice basis $T$. (This is implied by \tet{LLL_INPLACE}). \item \tet{LLL_ALL} If set, returns a 2-component vector $[K, T]$ corresponding to both kernel and image. \fun{GEN}{lllfp}{GEN x, double D, long flag} is a variant for matrices with inexact entries: $x$ is a matrix with real coefficients (types \typ{INT}, \typ{FRAC} and \typ{REAL}), $D$ and $\fl$ are as in \tet{ZM_lll}. The matrix is rescaled, rounded to nearest integers, then fed to \kbd{ZM\_lll}. The flag \kbd{LLL\_INPLACE} is still accepted but less useful (it returns an LLL-reduced basis associated to rounded input, instead of an exact base change matrix). \fun{GEN}{ZM_lll_norms}{GEN x, double D, long flag, GEN *ptB} slightly more general version of \kbd{ZM\_lll}, setting \kbd{*ptB} to a vector containing the squared norms of the Gram-Schmidt vectors $(b_i^*)$ associated to the output basis $(b_i)$, $b_i^* = b_i + \sum_{j < i} \mu_{i,j} b_j^*$. \fun{GEN}{lllintpartial_inplace}{GEN x} given a \kbd{ZM} $x$ of maximal rank, returns a partially reduced basis $(b_i)$ for the space spanned by the columns of $x$: $|b_i \pm b_j| \geq |b_i|$ for any two distinct basis vectors $b_i$, $b_j$. This is faster than the LLL algorithm, but produces much larger bases. \fun{GEN}{lllintpartial}{GEN x} as \kbd{lllintpartial\_inplace}, but returns the base change matrix $U$ from the canonical basis to the $b_i$, i.e. $x U$ is the output of \kbd{lllintpartial\_inplace}. \subsec{Reduction modulo matrices} \fun{GEN}{ZC_hnfremdiv}{GEN x, GEN y, GEN *Q} assuming $y$ is an invertible \kbd{ZM} in HNF and $x$ is a \kbd{ZC}, returns the \kbd{ZC} $R$ equal to $x$ mod $y$ (whose $i$-th entry belongs to $[-y_{i,i}/2, y_{i,i}/2[$). Stack clean \emph{unless} $x$ is already reduced (in which case, returns $x$ itself, not a copy). If $Q$ is not \kbd{NULL}, set it to the \kbd{ZC} such that $x = yQ + R$. \fun{GEN}{ZM_hnfdivrem}{GEN x, GEN y, GEN *Q} reduce each column of the \kbd{ZM} $x$ using \kbd{ZC\_hnfremdiv}. If $Q$ is not \kbd{NULL}, set it to the \kbd{ZM} such that $x = yQ + R$. \fun{GEN}{ZC_hnfrem}{GEN x, GEN y} alias for \kbd{ZC\_hnfremdiv(x,y,NULL)}. \fun{GEN}{ZM_hnfrem}{GEN x, GEN y} alias for \kbd{ZM\_hnfremdiv(x,y,NULL)}. \fun{GEN}{ZC_reducemodmatrix}{GEN v, GEN y} Let $y$ be a ZM, not necessarily square, which is assumed to be LLL-reduced (otherwise, very poor reduction is expected). Size-reduces the ZC $v$ modulo the $\Z$-module $Y$ spanned by $y$ : if the columns of $y$ are denoted by $(y_1,\dots, y_{n-1})$, we return $y_n \equiv v$ modulo $Y$, such that the Gram-Schmidt coefficients $\mu_{n,j}$ are less than $1/2$ in absolute value for all $j < n$. In short, $y_n$ is almost orthogonal to $Y$. \fun{GEN}{ZM_reducemodmatrix}{GEN v, GEN y} Let $y$ be as in \tet{ZC_reducemodmatrix}, and $v$ be a ZM. This returns a matrix $v$ which is congruent to $v$ modulo the $\Z$-module spanned by $y$, whose columns are size-reduced. This is faster than repeatedly calling \tet{ZC_reducemodmatrix} on the columns since most of the Gram-Schmidt coefficients can be reused. \fun{GEN}{ZC_reducemodlll}{GEN v, GEN y} Let $y$ be an arbitrary ZM, LLL-reduce it then call \tet{ZC_reducemodmatrix}. \fun{GEN}{ZM_reducemodlll}{GEN v, GEN y} Let $y$ be an arbitrary ZM, LLL-reduce it then call \tet{ZM_reducemodmatrix}. Besides the above functions, which were specific to integral input, we also have: \fun{GEN}{reducemodinvertible}{GEN x, GEN y} $y$ is an invertible matrix and $x$ a \typ{COL} or \typ{MAT} of compatible dimension. Returns $x - y\lfloor y^{-1}x \rceil$, which has small entries and differs from $x$ by an integral linear combination of the columns of $y$. Suitable for \kbd{gerepileupto}, but does not collect garbage. \fun{GEN}{closemodinvertible}{GEN x, GEN y} returns $x - \kbd{reducemodinvertible}(x,y)$, i.e. an integral linear combination of the columns of $y$, which is close to $x$. \fun{GEN}{reducemodlll}{GEN x,GEN y} LLL-reduce the non-singular \kbd{ZM} $y$ and call \kbd{reducemodinvertible} to find a small representative of $x$ mod $y \Z^n$. Suitable for \kbd{gerepileupto}, but does not collect garbage. \subsec{Miscellaneous} \fun{GEN}{RM_round_maxrank}{GEN G} given a matrix $G$ with real floating point entries and independent columns, let $G_e$ be the rescaled matrix $2^e G$ rounded to nearest integers, for $e \geq 0$. Finds a small $e$ such that the rank of $G_e$ is equal to the rank of $G$ (its number of columns) and return $G_e$. This is useful as a preconditioning step to speed up LLL reductions, see \tet{nf_get_Gtwist}. Suitable for \kbd{gerepileupto}, but does not collect garbage. \newpage pari-2.7.5/doc/develop.tex0000644000175000017500000010323412520212670014033 0ustar billbill\def\TITLE{Developer's Guide to the PARI library} \input parimacro.tex % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine Developer's Guide} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine the PARI library} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \openin\std=develop.aux \ifeof\std \else \input develop.aux \fi \chapno=0 \chapter{Work in progress} This draft documents private internal functions and structures for hard-core PARI developers. Anything in here is liable to change on short notice. Don't use anything in the present document, unless you are implementing new features for the PARI library. Try to fix the interfaces before using them, or document them in a better way. If you find an undocumented hack somewhere, add it here. Hopefully, this will eventually document everything that we buried in \kbd{paripriv.h} or even more private header files like \kbd{anal.h}. Possibly, even implementation choices! Way to go. \section{The type \typ{CLOSURE}}\kbdsidx{t_CLOSURE}\sidx{closure} This type holds closures and functions in compiled form, so is deeply linked to the internals of the GP compiler and evaluator. The length of this type can be $6$, $7$ or $8$ depending whether the object is an ``inline closure'', a ``function'' or a ``true closure''. A function is a regular GP function. The GP input line is treated as a function of arity $0$. A true closure is a GP function defined in a non-empty lexical context. An inline closure is a closure that appears in the code without the preceding \kbd{->} token. They are generally associated to the prototype code 'E' and 'I'. Inline closures can only exist as data of other closures, see below. In the following example, \bprog f(a=Euler)=x->sin(x+a); g=f(Pi/2); plot(x=0,2*Pi,g(x)) @eprog\noindent \kbd{f} is a function, \kbd{g} is a true closure and both \kbd{Euler} and \kbd{g(x)} are inline closures. This type has a second codeword \kbd{z[1]}, which is the arity of the function or closure. This is zero for inline closures. To access it, use \fun{long}{closure_arity}{GEN C} \item \kbd{z[2]} points to a \typ{STR} which holds the opcodes. To access it, use \fun{GEN}{closure_get_code}{GEN C}. \fun{const char *}{closure_codestr}{GEN C} returns as an array of \kbd{char} starting at $1$. \item \kbd{z[3]} points to a \typ{VECSMALL} which holds the operands of the opcodes. To access it, use \fun{GEN}{closure_get_oper}{GEN C} \item \kbd{z[4]} points to a \typ{VEC} which hold the data referenced by the \kbd{pushgen} opcodes, which can be \typ{CLOSURE}, and in particular inline closures. To access it, use \fun{GEN}{closure_get_data}{GEN C} \item \kbd{z[5]} points to a \typ{VEC} which hold extra data needed for error-reporting and debugging. See \secref{se:dbgclosure} for details. To access it, use \fun{GEN}{closure_get_dbg}{GEN C} Additionally, for functions and true closures, \item \kbd{z[6]} usually points to a \typ{VEC} with two components which are \typ{STR}. The first one displays the list of arguments of the closure without the enclosing parentheses, the second one the GP code of the function at the right of the \kbd{->} token. They are used to display the closure, either in implicit or explicit form. However for closures that were not generated from GP code, \kbd{z[6]} can point to a \typ{STR} instead. To access it, use \fun{GEN}{closure_get_text}{GEN C} Additionally, for true closure, \item \kbd{z[7]} points to a \typ{VEC} which holds the values of all lexical variables defined in the scope the closure was defined. To access it, use \fun{GEN}{closure_get_frame}{GEN C} \subsec{Debugging information in closure}\label{se:dbgclosure} Every \typ{CLOSURE} object \kbd{z} has a component \kbd{dbg=z[5]} which which hold extra data needed for error-reporting and debugging. The object \kbd{dbg} is a \typ{VEC} with $3$ components: \kbd{dbg[1]} is a \typ{VECSMALL} of the same length than \kbd{z[3]}. For each opcode, it holds the position of the corresponding GP source code in the strings stored in \kbd{z[6]} for function or true closures, positive indices referring to the second strings, and negative indices referring to the first strings, the last element being indexed as $-1$. For inline closures, the string of the parent function or true closure is used instead. \kbd{dbg[2]} is a \typ{VECSMALL} that lists opcodes index where new lexical local variables are created. The value $0$ denotes the position before the first offset and variables created by the prototype code 'V'. \kbd{dbg[3]} is a \typ{VEC} of \typ{VECSMALL}s that give the list of \kbd{entree*} of the lexical local variables created at a given index in \kbd{dbg[2]}. \section{The type \typ{LIST}}\kbdsidx{t_LIST}\sidx{list} This type needs to go through various hoops to support GP's inconvenient memory model. Don't use \typ{LIST}s in pure library mode, reimplement ordinary lists! This dynamic type is implemented by a \kbd{GEN} of length 3: two codewords and a vector containing the actual entries. In a normal setup (a finished list, ready to be used), \item the vector is malloc'ed, so that it can be realloc'ated without moving the parent \kbd{GEN}. \item all the entries are clones, possibly with cloned subcomponents; they must be deleted with \tet{gunclone_deep}, not \tet{gunclone}. The following macros are proper lvalues and access the components \fun{long}{list_nmax}{GEN L}: current maximal number of elements. This grows as needed. \fun{GEN}{list_data}{GEN L}: the elements. If \kbd{v = list\_data(L)}, then either \kbd{v} is \kbd{NULL} (empty list) or \kbd{l = lg(v)} is defined, and the elements are \kbd{v[1]}, \dots, \kbd{v[l-1]}. In most \kbd{gerepile} scenarios, the list components are not inspected and a shallow copy of the malloc'ed vector is made. The functions \kbd{gclone}, \kbd{copy\_bin\_canon} are exceptions, and make a full copy of the list. The main problem with lists is to avoid memory leaks; in the above setup, a statement like \kbd{a = List(1)} would already leak memory, since \kbd{List(1)} allocates memory, which is cloned (second allocation) when assigned to \kbd{a}; and the original list is lost. The solution we implemented is \item to create anonymous lists (from \kbd{List}, \kbd{gtolist}, \kbd{concat} or \kbd{vecsort}) entirely on the stack, \emph{not} as described above, and to set \kbd{list\_nmax} to $0$. Such a list is not yet proper and trying to append elements to it fails: \bprog ? listput(List(),1) *** variable name expected: listput(List(),1) *** ^---------------- @eprog\noindent If we had been malloc'ing memory for the \kbd{List([1,2,3])}, it would have leaked already. \item as soon as a list is assigned to a variable (or a component thereof) by the GP evaluator, the assigned list is converted to the proper format (with \kbd{list\_nmax} set) previously described. \fun{GEN}{listcopy}{GEN L} return a full copy of the \typ{LIST}~\kbd{L}, allocated on the \emph{stack} (hence \kbd{list\_nmax} is $0$). Shortcut for \kbd{gcopy}. \fun{GEN}{mklistcopy}{GEN x} returns a list with a single element $x$, allocated on the stack. Used to implement most cases of \kbd{gtolist} (except vectors and lists). A typical low-level construct: \bprog long l; /* assume L is a t_LIST */ L = list_data(L); /* discard t_LIST wrapper */ l = L? lg(L): 1; for (i = 1; i < l; i++) output( gel(L, i) ); for (i = 1; i < l; i++) gel(L, i) = gclone( ... ); @eprog\noindent \section{Protection of non-interruptible code} GP allows the user to interrupt a computation by issuing SIGINT (usually by entering control-C) or SIGALRM (usually using alarm()). To avoid such interruption to occurs in section of code which are not reentrant (in particular \kbd{malloc} and \kbd{free}) the following mechanism is provided: \fun{}{BLOCK_SIGINT_START}{} Start a non-interruptible block code. Block both \kbd{SIGINT} and \kbd{SIGARLM}. \fun{}{BLOCK_SIGALRM_START}{} Start a non-interruptible block code. Block only \kbd{SIGARLM}. This is used in the \kbd{SIGINT} handler itself to delay an eventual pending alarm. \fun{}{BLOCK_SIGINT_END}{} End a non-interruptible block code The above macros make use of the following global variables: \tet{PARI_SIGINT_block}: set to $1$ (resp. $2$) by \kbd{BLOCK\_SIGINT\_START} (resp. \kbd{BLOCK\_SIGALRM\_START}). \tet{PARI_SIGINT_pending}: Either $0$ (no signal was blocked), \kbd{SIGINT} (\kbd{SIGINT} was blocked) or \kbd{SIGALRM} (\kbd{SIGALRM} was blocked). This need to be set by the signal handler. Inside a block, a auto variable \kbd{int block} is defined which holds the value of \kbd{PARI\_SIGINT\_block} when entering the block. \subsec{Multithread interruptions} To support multithread, \kbd{BLOCK\_SIGINT\_START} and \kbd{BLOCK\_SIGALRM\_START} calls \kbd{MT\_SIGINT\_BLOCK(block);}, and \kbd{BLOCK\_SIGINT\_END} calls \kbd{MT\_SIGINT\_UNBLOCK(block);}. \tet{MT_SIGINT_BLOCK} and \tet{MT_SIGINT_UNBLOCK} are defined by the multithread engine. They can calls the following public functions defined by the multithread engine. \fun{void}{mt_sigint_block}{void} \fun{void}{mt_sigint_unblock}{void} In practice this mechanism is used by the POSIX thread engine to protect against asychronous cancellation. \section{Black box groups} A black box group is defined by a \tet{bb_group} struct, describing methods available to handle group elements: \bprog struct bb_group { GEN (*mul)(void*, GEN, GEN); GEN (*pow)(void*, GEN, GEN); ulong (*hash)(GEN); GEN (*rand)(void*); int (*equal)(GEN, GEN); int (*equal1)(GEN); GEN (*easylog)(void *E, GEN, GEN, GEN); }; @eprog \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{pow(E,x,n)} returns $x^n$ ($n$ integer, possibly negative or zero). \kbd{hash(x)} returns a hash value for $x$ (\kbd{hash\_GEN} is suitable for this field). \kbd{rand(E)} returns a random element in the group. \kbd{equal(x,y)} returns one if $x=y$ and zero otherwise. \kbd{equal1(x)} returns one if $x$ is the neutral element in the group, and zero otherwise. \kbd{easylog(E,a,g,o)} (optional) returns either NULL or the discrete logarithm $n$ such that $g^n=a$, the element $g$ being of order $o$. This provides a short-cut in situation where a better algorithm than the generic one is known. A group is thus described by a \kbd{struct bb\_group} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box groups: \fun{GEN}{gen_Shanks_log}{GEN x, GEN g, GEN N, void *E, const struct bb_group *grp} \hbadness 10000\break Generic baby-step/giant-step algorithm (Shanks's method). Assuming that $g$ has order $N$, compute an integer $k$ such that $g^k = x$. 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. \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 integer $k$ such that $g^k = x$. This requires $O(\sqrt{N})$ group operations in average and $O(1)$ storage. Will enter an infinite loop if there are no solutions. \fun{GEN}{gen_plog}{GEN x, GEN g, GEN N, void *E, const struct bb_group} Assuming that $g$ has prime order $N$, compute an integer $k$ such that $g^k = x$, using either \kbd{gen\_Shanks\_log} or \kbd{gen\_Pollard\_log}. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. If \kbd{easy} is not \kbd{NULL}, call \kbd{easy(E,a,g,N)} first and if the return value is not \kbd{NULL}, return it. For instance this is used over $\F_q^*$ to compute the discrete log of elements belonging to the prime field. \fun{GEN}{gen_Shanks_sqrtn}{GEN a, GEN n, GEN N, GEN *zetan, void *E, const struct bb_group *grp} \hbadness 10000 returns one solution of $x^n = a$ in a black box cyclic group of order $N$. Return \kbd{NULL} if no solution exists. If \kbd{zetan} is not \kbd{NULL} it is set to an element of exact order $n$. This function uses \kbd{gen\_plog} for all prime divisors of $\gcd(n,N)$. \fun{GEN}{gen_PH_log}{GEN a, GEN g, GEN N, void *E, const struct bb_group *grp} Generic Pohlig-Hellman algorithm. Assuming that $g$ has order $N$, compute an integer $k$ such that $g^k = x$. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. This calls \tet{gen_plog} repeatedly for all prime divisors $p$ of $N$. \kbd{easy} is as in \kbd{gen\_plog}. \fun{GEN}{gen_order}{GEN x, GEN N, void *E, const struct bb_group *grp} computes the order of $x$. If $N$ is not \kbd{NULL} it is a multiple of the order, as a \typ{INT} or a factorization matrix. \fun{GEN}{gen_factored_order}{GEN x, GEN N, void *E, const struct bb_group *grp} returns $[o,F]$, where $o$ is the order of $x$ and $F$ is the factorization of $o$. If $N$ is not \kbd{NULL} it is a multiple of the order, as a \typ{INT} or a factorization matrix. \fun{GEN}{gen_select_order}{GEN v, GEN N, void *E, const struct bb_group *grp} $v$ being a vector of possible order of the group, try to find the true order by checking orders of random points. This will not terminate if there is an ambiguity. \fun{GEN}{gen_gener}{GEN o, void *E, const struct bb_group *grp} returns a random generator of the group, assuming it is of order exactly $o$ (which can be given by a factorization matrix). \subsec{Black box groups with pairing} Theses functions handle groups of rank at most $2$ equipped with a family of bilinear pairings which behave like the Weil pairing on elliptic curves over finite field. The function \kbd{pairorder(E, P, Q, m, F)} must return the order of of the $m$-pairing of $P$ and $Q$, both of order dividing $m$, where $F$ is the factorisation matrix of a multiple of $m$. \fun{GEN}{gen_ellgroup}{GEN o, GEN d, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)} returns the elementary divisors $[d_1, d_2]$ of the group, assuming it is of order exactly $o>1$ (which can be given by a factorization matrix), and that $d_2$ divides $d$. If $d_2=1$ then $[o]$ is returned, otherwise \kbd{m=*pt\_m} is set to the order of the pairing required to verify a generating set which is to be used with \kbd{gen\_ellgens}. \fun{GEN}{gen_ellgens}{GEN d1, GEN d2, GEN m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)} the parameters $d_1$, $d_2$, $m$ being as returned by \kbd{gen\_ellgroup}, returns a pair of generators $[P,Q]$ such that $P$ is of order $d_1$ and the $m$-pairing of $P$ and $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_FpXQ_star}{void **E, GEN T, GEN p} returns a pointer to the black box group $(\F_p[x]/(T))^*$. \fun{const struct bb_group *}{get_FpE_group}{void **pt_E, GEN a4, GEN a6, GEN p} returns a pointer to a black box group and set \kbd{*pt\_E} to the necessary data for computing in the group $E(\F_p)$ where $E$ is the elliptic curve $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p$. \fun{const struct bb_group *}{get_FpXQE_group}{void **pt_E, GEN a4, GEN a6, GEN T, GEN p} returns a pointer to a black box group and set \kbd{*pt\_E} to the necessary data for computing in the group $E(\F_p[X]/(T))$ where $E$ is the elliptic curve $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p[X]/(T)$. \fun{const struct bb_group *}{get_FlxqE_group}{void **pt_E, GEN a4, GEN a6, GEN T, ulong p} idem for small $p$. \fun{const struct bb_group *}{get_F2xqE_group}{void **pt_E, GEN a2, GEN a6, GEN T} idem for $p=2$. \section{Black box finite fields} A black box finite field is defined by a \tet{bb_field} struct, describing methods available to handle field elements: \bprog struct bb_field { GEN (*red)(void *E ,GEN); GEN (*add)(void *E ,GEN, GEN); GEN (*mul)(void *E ,GEN, GEN); GEN (*neg)(void *E ,GEN); GEN (*inv)(void *E ,GEN); int (*equal0)(GEN); GEN (*s)(void *E, long); }; @eprog Note that, in contrast of black box group, elements can have non canonical forms, and only \kbd{red} is required to return a canonical form. \kbd{red(E,x)} returns the canonical form of $x$. \kbd{add(E,x,y)} returns the sum $x+y$. \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{neg(E,x)} returns $-x$. \kbd{inv(E,x)} returns the inverse of $x$. \kbd{equal0(x)} $x$ being in canonical form, returns one if $x=0$ and zero otherwise. \kbd{s(n)} $n$ being a small signed integer, returns $n$ times the unit element. A finite field is thus described by a \kbd{struct bb\_field} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box fields: \fun{GEN}{gen_Gauss}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_Gauss_pivot}{GEN x, long *rr, void *E, const struct bb_field *ff} \fun{GEN}{gen_det}{GEN a, void *E, const struct bb_field *ff} \fun{GEN}{gen_ker}{GEN x, long deplin, void *E, const struct bb_field *ff} \fun{GEN}{gen_matcolmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_matid}{long n, void *E, const struct bb_field *ff} \fun{GEN}{gen_matmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \subsec{Functions returning black box fields} \fun{const struct bb_field *}{get_Fp_field}{void **pt_E, GEN p} \fun{const struct bb_field *}{get_Fq_field}{void **pt_E, GEN T, GEN p} \fun{const struct bb_field *}{get_Flxq_field}{void **pt_E, GEN T, ulong p} \fun{const struct bb_field *}{get_F2xq_field}{void **pt_E, GEN T} \section{Black box algebra} A black box algebra is defined by a \tet{bb_algebra} struct, describing methods available to handle algebra elements: \bprog struct bb_algebra { GEN (*red)(void *E, GEN x); GEN (*add)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); GEN (*one)(void *E); GEN (*zero)(void *E); }; @eprog Note that, in contrast with black box groups, elements can have non canonical forms, but only \kbd{add} is allowed to return a non canonical form. \kbd{red(E,x)} returns the canonical form of $x$. \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$. \kbd{one(E)} returns the unit element. \kbd{zero(E)} returns the zero element. An algebra is thus described by a \kbd{struct bb\_algebra} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box algebra: \fun{GEN}{gen_bkeval}{GEN P, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)} $x$ being an element of the black box algebra, and $P$ some black box polynomial of degree $d$ over the base field, returns $P(x)$. The function \kbd{cmul(E,P,a,y)} must return the coefficient of degree $a$ of $P$ multiplied by $y$. \kbd{cmul} is allowed to return a non canonical form. The flag \kbd{use\_sqr} has the same meaning as for \kbd{gen\_powers}. This implements an algorithm of Brent and Kung (1978). \fun{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)} as \tet{gen_RgX_bkeval} assuming $V$ was output by \tet{gen_powers}$(x, l, E, \var{ff})$ for some $l\geq 1$. For optimal performance, $l$ should be computed by \tet{brent_kung_optpow}. \fun{long}{brent_kung_optpow}{long d, long n, long m} returns the optimal 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 free $\Z_p$-modules} (Very experimental) \fun{GEN}{gen_ZpX_Dixon}{GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN z, GEN q), GEN invl(void *E, GEN z)} Let $F$ be a \kbd{ZpXT} representing the coefficients of some abstract linear mapping $f$ over $\Z_p[X]$ seen as a free $\Z_p$-module, let $V$ be an element of $\Z_p[X]$ and let $q = p^N$. Return $y\in\Z_p[X]$ such that $f(y)=V\pmod{p^N}$ assuming the following holds for $n\leq N$: \item $\kbd{lin}(E, \kbd{FpX\_red}(F, p^n), z, p^n) \equiv f(z) \pmod{p^n}$ \item $f(\kbd{invl}(E, z)) \equiv z \pmod{p}$ The rationale for the argument $F$ being that it allows \kbd{gen\_ZpX\_Dixon} to reduce it to the required $p$-adic precision. \fun{GEN}{gen_ZpX_Newton}{GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN a, GEN q), GEN invd(void *E, GEN b, GEN v, GEN q, long N)} Let $x$ be an element of $\Z_p[X]$ seen as a free $\Z_p$-module, and $f$ some differentiable function over $\Z_p[X]$ such that $f(x) \equiv 0 \pmod{p}$. Return $y$ such that $f(y) \equiv 0\pmod{p^n}$, assuming the following holds for all $a, b\in \Z_p[X]$ and $M\leq N$: \item $v = \kbd{eval}(E,a,p^N)$ is a vector of elements of $\Z_p[X]$, \item $w = \kbd{invd}(E,b,v,p^M,M)$ is an element in $\Z_p[X]$, \item $v[1] \equiv f(a) \pmod{p^N\Z_p[X]}$, \item $df_a(w) \equiv b \pmod{p^M\Z_p[X]}$ \noindent and $df_a$ denotes the differential of $f$ at $a$. Motivation: \kbd{eval} allows to evaluate $f$ and \kbd{invd} allows to invert its differential. Frequently, data useful to compute the differential appear as a 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{Public functions useless outside of GP context} These functions implement GP functionality for which the C language or other libpari routines provide a better equivalent; or which are so tied to the \kbd{gp} interpreter as to be virtually useless in \kbd{libpari}. Some may be generated by \kbd{gp2c}. We document them here for completeness. \subsec{Conversions} \fun{GEN}{toser_i}{GEN x} internal shallow function, used to implement automatic conversions to power series in GP (as in \kbd{cos(x)}). Converts a \typ{POL} or a \typ{RFRAC} to a \typ{SER} in the same variable and precision \kbd{precdl} (the global variable corresponding to \kbd{seriesprecision}). Returns $x$ itself for a \typ{SER}, and \kbd{NULL} for other argument types. The fact that it uses a global variable makes it awkward whenever you're not implementing a new transcendental function in GP. Use \tet{RgX_to_ser} or \tet{rfrac_to_ser} for a fast clean alternative to \kbd{gtoser}. \subsec{Output} \fun{void}{print0}{GEN g, long flag} internal function underlying the \kbd{print} GP function. Prints the entries of the \typ{VEC} $g$, one by one, without any separator; entries of type \typ{STR} are printed without enclosing quotes. \fl is one of \tet{f_RAW}, \tet{f_PRETTYMAT} or \tet{f_TEX}, using the current default output context. \fun{void}{out_print0}{PariOUT *out, const char *sep, GEN g, long flag} as \tet{print0}, using output context \kbd{out} and separator \kbd{sep} between successive entries (no separator if \kbd{NULL}). \fun{void}{printsep}{const char *s, GEN g, long flag} \tet{out_print0} on \tet{pariOut} followed by a newline. \fun{void}{printsep1}{const char *s, GEN g, long flag} \tet{out_print0} on \tet{pariOut}. \fun{char*}{pari_sprint0}{const char *s, GEN g, long flag} displays $s$, then \kbd{print0(g, flag)}. \fun{void}{print}{GEN g} equivalent to \kbd{print0(g, f\_RAW)}, followed by a \kbd{\bs n} then an \kbd{fflush}. \fun{void}{print1}{GEN g} as above, without the \kbd{\bs n}. Use \tet{pari_printf} or \tet{output} instead. \fun{void}{printtex}{GEN g} equivalent to \kbd{print0(g, t\_TEX)}, followed by a \kbd{\bs n} then an \kbd{fflush}. Use \tet{GENtoTeXstr} and \tet{pari_printf} instead. \fun{void}{write0}{const char *s, GEN g} \fun{void}{write1}{const char *s, GEN g} use \kbd{fprintf} \fun{void}{writetex}{const char *s, GEN g} use \tet{GENtoTeXstr} and \kbd{fprintf}. \fun{void}{printf0}{GEN fmt, GEN args} use \tet{pari_printf}. \fun{GEN}{Strprintf}{GEN fmt, GEN args} use \tet{pari_sprintf}. \subsec{Input} \kbd{gp}'s input is read from the stream \tet{pari_infile}, which is changed using \fun{FILE*}{switchin}{const char *name} Note that this function is quite complicated, maintaining stacks of files to allow smooth error recovery and \kbd{gp} interaction. You will be better off using \tet{gp_read_file}. \subsec{Control flow statements} \fun{GEN}{break0}{long n}. Use the C control statement \kbd{break}. Since \kbd{break(2)} is invalid in C, either rework your code or use \kbd{goto}. \fun{GEN}{next0}{long n}. Use the C control statement \kbd{continue}. Since \kbd{continue(2)} is invalid in C, either rework your code or use \kbd{goto}. \fun{GEN}{return0}{GEN x}. Use \kbd{return}! \fun{void}{error0}{GEN g}. Use \kbd{pari\_err(e\_USER,)} \fun{void}{warning0}{GEN g}. Use \kbd{pari\_warn(e\_USER,)} \subsec{Accessors} \fun{GEN}{vecslice0}{GEN A, long y1, long y2} used to implement $A[y_1..y_2]$. \fun{GEN}{matslice0}{GEN A, long x1, long x2, long y1, long y2} used to implement $A[x_1..x_2,y_1..y_2]$. \subsec{Iterators} \fun{GEN}{apply0}{GEN f, GEN A} gp wrapper calling \tet{genapply}, where $f$ is a \typ{CLOSURE}, applied to $A$. Use \kbd{genapply} or a standard C loop. \fun{GEN}{select0}{GEN f, GEN A} gp wrapper calling \tet{genselect}, where $f$ is a \typ{CLOSURE} selecting from $A$. Use \kbd{genselect} or a standard C loop. \fun{GEN}{vecapply}{void *E, GEN (*f)(void* E, GEN x), GEN x} used to implement \kbd{[a(x)|x<-b]}. \fun{GEN}{vecselect}{void *E, long (*f)(void* E, GEN x), GEN A} 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} 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 to implement the behaviour below: \bprog ? my(z=3);eval("z=z^2");z %1 = 9 @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 corresponding value? (returns an offset on the value stack). \subsec{Miscellaneous} \fun{char*}{os_getenv}{const char *s} either calls \kbd{getenv}, or directly return \kbd{NULL} if the \kbd{libc} does not provide it. Use \tet{getenv}. \fun{sighandler_t}{os_signal}{int sig, pari_sighandler_t fun} after a \bprog typedef void (*pari_sighandler_t)(int); @eprog\noindent (private type, not exported). Installs signal handler \kbd{fun} for signal \kbd{sig}, using \tet{sigaction} with flag \tet{SA_NODEFER}. If \kbd{sigaction} is not available use \tet{signal}. If even the latter is not available, just return \tet{SIG_IGN}. Use \tet{sigaction}. \chapter{Regression tests, benches} This chapter documents how to write an automated test module, say \kbd{fun}, so that \kbd{make test-fun} executes the statements in the \kbd{fun} module and times them, compares the output to a template, and prints an error message if they do not match. \item Pick a \emph{new} name for your test, say \kbd{fun}, and write down a GP script named \kbd{fun}. Make sure it produces some useful output and tests adequately a set of routines. \item The script should not be too long: one minute runs should be enough. Try to break your script into independent easily reproducible tests, this way regressions are easier to debug; e.g. include \kbd{setrand(1)} statement before a randomized computation. The expected output may be different on 32-bit and 64-bit machines but should otherwise be platform-independent. If possible, the output shouldn't even depend on \kbd{sizeof(long)}; using a \kbd{realprecision} that exists on both 32-bit and 64-bit architectures, e.g. \kbd{\bs p 38} is a good first step. \item Dump your script into \kbd{src/test/in/} and run \kbd{Configure}. \item \kbd{make test-fun} now runs the new test, producing a \kbd{[BUG]} error message and a \kbd{.dif} file in the relevant object directory \kbd{Oxxx}. In fact, we compared the output to a non-existing template, so this must fail. \item Now \bprog patch -p1 < Oxxx/fun.dif @eprog\noindent generates a template output in the right place \kbd{src/test/32/fun}, for instance on a 32-bit machine. \item If different output is expected on 32-bit and 64-bit machines, run the test on a 64-bit machine and patch again, thereby producing \kbd{src/test/64/fun}. If, on the contrary, the output must be the same, make sure the output template land in the \kbd{src/test/32/} directory (which provides a default template when the 64-bit output file is missing); in particular move the file from \kbd{src/test/64/} to \kbd{src/test/32/} if the test was run on a 64-bit machine. \item You can now re-run the test to check for regressions: no \kbd{[BUG]} is expected this time! Of course you can at any time add some checks, and iterate the test / patch phases. In particular, each time a bug in the \kbd{fun} module is fixed, it is a good idea to add a minimal test case to the test suite. \item By default, your new test is now included in \kbd{make test-all}. If it is particularly annoying, e.g. opens tons of graphical windows as \kbd{make test-ploth} or just much longer than the recommended minute, you may edit \kbd{config/get\_tests} and add the \kbd{fun} test to the list of excluded tests, in the \kbd{test\_extra\_out} variable. \item The \kbd{get\_tests} script also defines the recipe for \kbd{make bench} timings, via the variable \kbd{test\_basic}. A test is included as \kbd{fun} or \kbd{fun\_$n$}, where $n$ is an integer $\leq 1000$; the latter means that the timing is weighted by a factor $n/1000$. (This was introduced a long time ago, when the \kbd{nfields} bench was so much slower than the others that it hid slowdowns elsewhere.) \section{Functions for GP2C} \subsec{Functions for safe access to components} Theses function returns the adress of the requested component after checking it is actually valid. This is used by GP2C -C. \fun{GEN*}{safegel}{GEN x, long l}, safe version of \kbd{gel(x,l)} for \typ{VEC}, \typ{COL} and \typ{MAT}. \fun{long*}{safeel}{GEN x, long l}, safe version of \kbd{x[l]} for \typ{VECSMALL}. \fun{GEN*}{safelistel}{GEN x, long l} safe access to \typ{LIST} component. \fun{GEN*}{safegcoeff}{GEN x, long a, long b} safe version of \kbd{gcoeff(x,a, b)} for \typ{MAT}. \chapter{Parallelism} \section{The PARI MT interface} PARI provides an abstraction for doing parallel computations. \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 \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} 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. 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 \tet{mt_queue_get} before any other call to \tet{mt_queue_submit}, and conversely. The first call to \tet{mt_queue_get} will return \kbd{NULL} until a sufficient number of tasks have been submitted. If no more tasks are left to be submitted, use \bprog mt_queue_submit(handle, id, NULL) @eprog\noindent to allow further calls to \tet{mt_queue_get}. If \tet{mt_queue_get} sets \kbd{pending} to $0$, then no more tasks are pending and it is safe to call \tet{mt_queue_end}. The parameter \kbd{taskid} can be chosen arbitrarily. It is associated to a task but is not available to \kbd{worker}. It provides an efficient way to match a tasks and results. It is ignored when the parameter \kbd{task} is \kbd{NULL}. \subsec{Miscellaneous} \fun{void}{mt_broadcast}{GEN code}: do nothing unless the MPI threading engine is in use. In that case, it evaluates the closure \kbd{code} on all secondary nodes. This can be sued to change the states of the MPI child nodes. This is used by \tet{install}. \section{Initialization} This section is technical. \fun{void}{pari_mt_init}{void} \label{pari_mt_init} When using MPI, it is sometimes necessary to run initialization code on the child nodes after PARI is initialized. This can be done as follow: \item call \tet{pari_init_opts} with the flag \tet{INIT_noIMTm}. This initializes PARI, but not the MT engine. \item call the required initialization code. \item call \tet{pari_mt_init} to initialize the MT engine. Note that under MPI, this function only returns on the master node. On the child nodes, it enters slave mode. Thus it is no longer possible to run initialization code on the child nodes. See the file \kbd{examples/pari-mt.c} for an example. \fun{void}{pari_mt_close}{void} \label{pari_mt_close} When using MPI, calling \tet{pari_close} will terminate the MPI execution environment. If this is undesirable, you should call \tet{pari_close_opts} with the flag \tet{INIT_noIMTm}. This closes PARI without terminating the MPI execution environment It is allowed to call \kbd{pari\_mt\_close} later to terminate it. Note that the once MPI is terminated it cannot be restarted, and that it is considered an error for a program to end without having terminated the MPI execution environment. \vfill\eject \input index\end pari-2.7.5/doc/gphelp.in0000755000175000017500000010543512556155320013501 0ustar billbill#!@perl@ # # $Id$ # # 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. # Output extended help corresponding to a given GP command. By default, # extract relevant information from from the PARI manual, run TeX, then open # an xdvi display. # # The manual can be compressed. # # Usage: gphelp keyword # # Command line options: # -k: apropos (list of relevant GP functions) # -detex (-d): don't use TeX + xdvi (implicit when DISPLAY is not set). # -color_help (-ch) : use color "number" (same scheme as in GP) # -color_bold (-cb) : display bold in color "number" # -color_underline (-cu) : display underlined text in color "number" # # -raw use internal format for output with @x markers, -detex is implicit # (for the TeX-to-pod converter) # # -to_pod file convert file to POD (should be the only args) # # -to_dumbpod file same, but without nested formating # # Granted environment variables (override): # GPTMPDIR: where temporary files will go (/tmp by default). # GPDOCDIR: where is manual (by default, where make install will put it). # GPXDVI: which 'xdvi' program to call (xdvi by default) # $version= "@version@"; $datadir= "@datadir@"; # no expanded material (@key@) below $wwwsite= "http://pari.math.u-bordeaux.fr/"; $xdvi = $ENV{GPXDVI} || "xdvi"; $xdviref = $ENV{GPXDVIREF} || "$xdvi -paper 29.7x21cm"; $gzip = "gzip"; $zcat = "$gzip -dc"; $bzip = "bzip2"; $bzcat = "$bzip -dc"; $docdir = &get_docdir(); $tex = $ENV{GPTEX} || "tex"; $refcard = (@ARGV and $ARGV[-1] =~ /refcard/i); $dumb_pod=1, $ARGV[0] = '-to_pod' if @ARGV && $ARGV[0] eq '-to_dumb_pod'; &to_pod() if @ARGV == 2 && $ARGV[0] eq '-to_pod'; &options(); &init(); if ($#ARGV < 0) { &treat(""); cleanexit(); } &pretex() if (!$detex); for (@ARGV) { &treat($_); } if ($apropos) { &apropos_final_print(); cleanexit(); } &posttex() if (!$detex); print "ugly_kludge_done\n" if (!$detex && $fromgp); cleanexit(); # # Procedures # sub cleanexit { print "\e[0m" unless $to_pod; exit 0; } sub help { print "Usage: $0 [-k] [-detex] [-ch c1] [-cb c2] [-cu c3] keyword\n"; print "where c1,c2,c3 denote background, bold and underline color\n"; exit(1); } sub options { $raw = $detex = $fromgp = $apropos = 0; $ch = $cb = $cu = ''; while ($_ = $ARGV[0]) { last if (! /^-[a-z]/); shift(@ARGV); if ($_ eq "-fromgp") { $fromgp = 1; } elsif ($_ eq "-k") { $apropos = $detex = 1; } elsif ($_ eq "-balloon") { $balloon = 1; } elsif ($_ eq "-detex" || $_ eq "-d") { $detex = 1; } elsif ($_ eq "-raw") { $raw = $detex = 1; } elsif ($_ eq "-color_help" || $_ eq "-ch") { $ch = &color(shift(@ARGV)); } elsif ($_ eq "-color_bold" || $_ eq "-cb") { $cb = &color(shift(@ARGV)); } elsif ($_ eq "-color_underline" || $_ eq "-cu") { $cu = &color(shift(@ARGV)); } else { &help(); } } $ch = "\e[m$ch"; $cu .= $cu ? "\e[1m": "\e[4m"; $cb .= "\e[1m"; $detex = 1 if (!$ENV{DISPLAY}); } sub get_docdir { my $d = $ENV{GPDOCDIR} || $ENV{GPHELP_DOCDIR}; if (!defined $d) { # work from TOPDIR/Oarch or TOPDIR too: may be uninstalled yet; $d = $0; $d =~ s,/gphelp,,; for ("$datadir", '.', '..', $d) { my $t = "$_/doc"; if (-f "$t/translations") { $d = $t; last; } } $d ||= "$datadir/doc"; # Last resort } if ($d =~ /^\./) { eval { require Cwd; $d = Cwd::cwd() . "/$d"; $d =~ s,doc/\.\./doc,doc,; } } return $d; } sub init { &inittr(); $indent = " "; # avoid Glob.pm! (for minimal Windows install) opendir(DIR, $docdir) || die "$docdir not found"; @file_list = grep { /^usersch.*tex/ } readdir(DIR); closedir(DIR); chdir($docdir); $docfile = "usersch3.tex"; open(IN,"translations") || die("Could not find translation file, docdir='$docdir'"); while() { chomp; @_ = split(/ *\@ */); $key = shift(@_); $transl{$key} = join('@',@_); } close(IN); } sub not_found { my($help) = shift; $help =~ s/\\\\/_B#K#S_/g; $help =~ s/\\(.)/$1/g; $help =~ s/_B#K#S_/\\/g; print "'$help' not found !\n"; } sub choose_chap { while (s/\@([0-9])$//) { $docfile = "usersch$1.tex"; } if (-f $docfile) { $pipe = ""; } else { die "Cannot find $docfile" if (! -f "$docfile.z" && ! -f "$docfile.gz" && ! -f "$docfile.Z" && ! -f "$docfile.bz2"); if (-f "$docfile.bz2") { $pipe = $bzcat; $docfile = "$docfile.bz2"; } else { $pipe = $zcat; } } } sub safe_setsid { eval { require POSIX; POSIX::setsid(); # detach from terminal (^C will not kill xdvi) }; } # assume we're in $docdir sub open_viewer_then_quit { my $F = shift; my ($f, $viewer, $redirect); my $cygwin = ($^O =~ /cygwin/); my $win32 = ($^O =~ /ms(win|ys)/); my $osx = ($^O =~ /darwin/); $f = "$F.dvi"; $f = "$F.dvi.gz" if (! -f "$f"); $f = "$F.pdf" if (! -f "$f"); die "could not find \'$F\'" if (! -f "$f"); $F = $f; $redirect = ' 2>/dev/null >/dev/null &'; if ($f =~ /\.dvi/) { # DVI $viewer = ($f =~ /refcard/)? $xdviref: $xdvi; } elsif ($cygwin) { # PDF Win32 @_ = split(/"/, `acro.exe`); ($viewer = $_[1]) =~ s,\\,/,g; $redirect = ""; $F =~ s,/cygdrive/(.),$1:, ; # Reader can't cope with Cygwin paths $F = "\"$F\""; $viewer = "\"$viewer\""; } elsif ($win32) { # PDF Win32 @_ = split(/"/, "$ENV{GP_PDF_VIEWER}"); $viewer = $_[1]; print "using \'$viewer\', "; } elsif ($osx) { $viewer = "open"; } else { # PDF generic $viewer = "acroread"; } print "displaying \'$F\'."; print "\n" if (!$fromgp); safe_setsid(); if ($win32) { system($viewer,$F); } else { system("$viewer $F$redirect"); } cleanexit(); } sub treat { my($help); $_ = $_[0]; s/_QUOTE/'/g; s/_BACKQUOTE/`/g; s/_DOUBQUOTE/"/g; s/^ *"(.*)"([^"]*) *$/$1$2/; if (s/\@$//) { $found = 0; $searchall = 1; $help = $_; for (@file_list) { next if (!/^usersch(.*)\.tex/); &treat("$help\@$1"); if ($apropos && $#list > 0 || $#sentence_list > 0) { print "\nChapter $1:\n"; print "==========\n"; &apropos_final_print(); } } return not_found($help) if (!$found && !$apropos); $searchall = 0; $apropos = 0; return; } &choose_chap; if (!$apropos) { $_ = "users" if (/^$/); open_viewer_then_quit($_) if (/^(users|tutorial|refcard|libpari)$/); if ($transl{$_}) { $_ = $transl{$_}; &choose_chap; } } s/(\W)/\\$1/g; s/_/\\\\_/g; ($pipe && open(DOC,"$pipe $docfile |")) || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!"; return &apropos($_) if ($apropos); if (/^\\[<>=!](\\=)?$/ || /^\\\|\\\||\\&\\&$/ || /\\\||&/ || /===/) { $_ = 'Comparison and Boolean operators'; } $help = $_; my ($first); my ($pat) = $help; if ($pat =~ /[a-zA-Z0-9]$/) { $pat .= '\b'; } else { $pat .= '}'; } while () { if (/\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter|label)\{$pat/) { $first = $_; last; } } if (eof(DOC)) { ¬_found($help) if (!$searchall); return; } $found = 1; if (!$detex) { tex($first); } else { &detex(); print "\n" if (!$fromgp); # Avoid broken pipe from zcat do {local $/; } if $^O eq 'os2' and $pipe; } close(DOC); } # # A propos # sub apropos_print_list { $current = ""; @_ = sort(@_); for (@_) { next if ($_ eq $current); $current = $_; print "$indent$_\n"; } } sub apropos_raw_print { $indent = ""; &apropos_print_list(@sentence_list); &apropos_print_list(@list); } sub apropos_final_print { my($maxlen) = 0; my($i,$nbcol,$current); my($cols) = ($ENV{'COLUMNS'} || 80) - 1; if ($raw) { &apropos_raw_print(); return; } @list = sort(@list); for (@list) { $i= length($_); $maxlen = $i if ($i > $maxlen); } $maxlen++; $nbcol = $cols / $maxlen; $nbcol =~ s/\..*//; $nbcol-- if ($nbcol * $maxlen == $cols); $nbcol = 1 if (!$nbcol); $current = ""; $i = 0; for (@list) { next if ($_ eq $current); $current = $_; print($_); $i++; if ($i >= $nbcol) { $i=0; print "\n"; next; } print " " x ($maxlen - length($_)); } print "\n" if ($i); if ($#sentence_list > 0) { print "\nSee also:\n" if ($#list > 0); $indent = " "; apropos_print_list(@sentence_list); } } sub apropos_check { my($line, $current) = @_; $line =~ s/\n/ /g; return if ($line !~ /$help/i); local($_) = $current; s/\\b\{(.)\}/\\$1/; s/\{\}//g; s/\\pow/^/; s/\\%/%/; s/\\bs/\\/; s/\\\#/\#/g; s,\+\$/\$-,+/-,; s/\$\(.*//; # remove argument lists if (/ /) { push(@sentence_list,$_); } else { push(@list,$_); } } sub apropos { my($line,$current,$new); $help = $_[0]; $help='\\\\pow' if ($help eq '\^'); $help='\\\\til' if ($help eq '\~'); @sentence_list = @list = ""; while () { if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter)\{/) { $new = &get_match($_,'{','}'); &apropos_check($line, $current); $current = $new; $line = ""; } $line .= $_; } &apropos_check($line, $current); } ## ## Tex Part ## # Actual text is in file TEX. Parimacro + Geometry info goes to WRAP sub pretex { my ($basedir) = $ENV{GPHELP_TMPDIR} || $ENV{GPTMPDIR} || $ENV{TMPDIR} || "/tmp"; $tmpdir = "$basedir/gp.help$$"; mkdir $tmpdir, 0755 || die "Cannot create temporary directory"; $texfile = "$tmpdir/gp.help"; open(TEX,">$texfile.tex") || die "Couldn't open $texfile.tex"; } sub tex { my ($first) = @_; print TEX $first; while () { last if /^\\(section|sub[sub]*sec)/i; print TEX; } } sub posttex { my ($wrap) = "$tmpdir/gpwrapper.help"; my (@goners) = ("$texfile.tex", "$wrap.tex", "$wrap.dvi", "$wrap.log", "$wrap.aux"); if (!$found) { unlink @goners; rmdir("$tmpdir"); cleanexit(); } open(WRAP, ">$wrap.tex") || die "Couldn't open $wrap.tex"; if ($balloon) { print WRAP '\nopagenumbers\def\fromgphelp{}' . "\\input $docdir/parimacro.tex" . '\setbox0\vbox{' . "\\input $texfile.tex" . ' } \dimen0=\the\ht0 \advance\dimen0 by \dp0 \advance\dimen0 by 60pt \dimen1=\the\wd0 \advance\dimen1 by 60pt \vsize \dimen0 \hsize \dimen1 \advance\voffset 30pt\advance\hoffset 30pt \advance\hoffset-1in \advance\voffset-1in \special{papersize=\the\dimen1,\the\dimen0} \noindent\box0 \end'; } else { print WRAP '\nopagenumbers\def\fromgphelp{}' . "\\input $docdir/parimacro.tex" . "\\input $texfile.tex" . '\end'; } close(WRAP) || die "Error closing '$wrap.tex': $!"; close(TEX) || die "Error closing '$texfile.tex': $!"; chdir($tmpdir); $out = `$tex $wrap.tex 2>&1 < /dev/null`; -f "$wrap.dvi" || die "could not create '$wrap.dvi': status=$?, $out"; safe_setsid(); my ($goners) = join(" ", @goners); system("($xdvi $wrap.dvi 2>/dev/null >/dev/null; rm -f $goners; rmdir $tmpdir)&"); } # # Detex Part # sub fit_loop { my($i); return if ($miss > 9 || $#_ <= 0); while ($miss > 0) { # print "1:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;])$/$1 /); return if ($miss == 0); } # print "2:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;]) $/$1 /); return if ($miss == 0); } # print "3:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([\),])$/$1 /); return if ($miss == 0); } # print "4:$miss ";print @_;print "\n"; $i = 0; for (@_) { if (!$i) { $i = 1; next; } $miss-- if (s/^\(/ (/); return if ($miss == 0); } # print "5:$miss "; print @_;print "\n"; for (@_) { next if (/^ *$/); $miss--; s/$/ /; return if ($miss == 0); } } } sub fit_line { my($wi, @a); my($l) = -1; my($rem) = $_[0]; for (@l) { my ($l2) = $l; $l += ($_ + 1); if ($l > $rem) { $l = $l2; last; } $wi++; } $miss = $rem - $l; splice(@l, 0, $wi); @a = splice(@w, 0, $wi-1); &fit_loop(@a); push(@a, shift(@w)); return join(' ', @a); } # empty output line sub is_void { my($in) = shift; $in =~ s/\@\[\w+\]//g; $in =~ s/\@[012]//g; ($in =~ /^\s*$/)? 1: 0; } sub nl { push(@f_text, shift); } sub split_words { my ($txt) = @_; $txt =~ s/^ +//; for ( split(/\s+/, $txt) ) { s/\Q$tr{nbrk}/ /g; my ($w) = $_; # these codes will be replaced by 1 character s/\@\[(obr|cbr|ouml|uuml|agrav|eacute|ldollar|lt|gt|\{|\})]/\@/g; s/\@\[pm]/+\/-/g; # the rest will be replaced by zero-width characters s/\@\[\w+\]//g; my ($l) = length($_); # zero-width word if (!$l && $#w >= 0) { $w[$#w] .= $w; next; } push(@l, $l); push(@w, $w); } # first word might still be zero-width if ($#w >= 1 && !$l[0]) { splice(@w, 0,2, "$w[0]$w[1]"); splice(@l, 0,1); } } sub format_text { my($last_void) = 0; my($noindent) = 0; my($init) = 1; my($cols) = ($ENV{'COLUMNS'} || 80) - 1; my($first) = $cols - length($indent); for (@text) { if (s/^\@1//) # start verbatim { nl(&fit_line($first)) if (@w); nl("") if (!$last_void && !is_void($_)); # add empty line nl("$indent$_"); next; } if (s/^\@0//) # verbatim lines { nl("$indent$_"); next; } if (s/^\@2//) # end verbatim, add indent { nl("") if (!$last_void); $last_void = 1; split_words($_); next; } if (s/^\@3//) # end verbatim + no indent { nl("") if (!$last_void); $noindent = 1; $last_void = 1; split_words($_); next; } if (!is_void($_)) { split_words($_); next; } # line is empty, split out previous paragraph next if (!@l || !$l[0]); # nothing if ($init) { nl(&fit_line($first)); } else { nl("") if (!$last_void); nl("\@[endbold]" . ($noindent? "": $indent) . &fit_line($noindent? $cols: $first)); } while (@w) { nl(&fit_line($cols)); } $noindent = $init = $last_void = 0; } } # argument has the form s1${open}s2${close}s3 # Return 's2'. Set $remainder to 's3'. sub get_match { local ($_, $open, $close) = @_; my (@tmp, $arg,$parity,$ok); my ($obr) = 1; $parity = ($open eq $close); /$open/; $_ = $'; # remove everything before (and including) first $open while ($_) { @tmp = split(/($open|$close)/); while ($#tmp >= 0) { $_ = shift(@tmp); $obr++ if (/^$open$/); if ($parity && $obr == 2) { $ok = 1; last } $obr-- if (/^$close$/); if (!$obr) { $ok = 1; last } $arg .= $_; } last if ($ok); $_ = ; } $remainder = join('',@tmp); return $arg; } sub detex { my($fun); # 1: get the function "prototype" $fun = &get_match($_,'{','}'); $fun = &basic_subst($fun); $_ = $remainder; $_ = if (!&basic_subst($_)); push(@text, "\@[startbold]$fun:\@[endbold]"); push(@text, ""); # 2: parse the function description if ($_) { s/^ *://; &presubst(); } while () { last if /^\\(section|sub[sub]*sec)/i; &presubst(); } if ($raw) { print join("\n", @text); return; } # for (@text) { print("AA{$_}BB\n"); } # DEBUG &format_text(); for (@f_text) { &TeXprint($_); } } # We use the special char @ to transmit special sequences sub inittr { @ou = qw( dollar nbrk startbold endbold startcode endcode obr cbr uuml ouml agrave eacute startpodcode endpodcode startlink endlink startbcode endbcode startbi endbi startit endit startword endword startlword endlword pm empty gt lt podleader ); @tr{@ou} = map "\@[$_]", @ou; $tr{dollar} = '$' if $to_pod; %pr = ( dollar => '', ldollar => '$', # literal dollar nbrk => 'S< >', startbold => 'B<', endbold => '>', startcode => 'C<', startlink => 'L<', endlink => '>', endcode => '>', obr => '{', cbr => '}', startpodcode => 'C<', endpodcode => '>', ( $dumb_pod ? (startbcode => 'B<', endbcode => '>', startbi => 'B<', endbi => '>',) : (startbcode => 'B '>>', startbi => 'B '>>')), startit => 'I<', endit => '>', startword => 'F<', endword => '>', startlword => ' F<', endlword => '> ', pm => 'F<+->', "gt" => 'E', "lt" => 'E', ouml => 'E', uuml => 'E', eacute => 'E', agrave => 'E', empty => 'Z<>', podleader => '=', ); } sub indent_equally { my $in = shift; $in =~ s/^[ \t]*/ /mg; $in} sub basic_subst { local($_) = shift; s/(\S)[ \t]*\n[ \t]+/$1\n/gm; s/([^\\])\\\{/$1$tr{obr}/g; s/([^\\])\\\}/$1$tr{cbr}/g; s/([^\\])\\-/$1/g; s/\A\\q?quad(?![a-zA-Z])\s*/$tr{nbrk}$tr{nbrk}/; s|\\wwwsite|$wwwsite|g; s/^\\def\\.*\{\n.*\n\}//gm; s/\\def\\.*//g; s(\\footnote\s*\{?\*+\}?\s*\{\s*((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\}) {$tr{startbold}FOOTNOTE$tr{endbold}$tr{lt}$tr{lt}$tr{lt} $1 $tr{gt}$tr{gt}$tr{gt}}g; s/(\{[\w\s]+)\{\}([\s\w]+\})/$1$2/g; # {nf{}init} s(\\op(?![a-zA-Z])\s*)({\\it op\\/})g; # {nf{}init} s/\\emacs\b//; s/\\unix\b//; s/\\(leavevmode|strut)(?![a-zA-Z])\s*//g; s/ \\funno \s* { \s* ((?:[^{}]|\{[^{}]*\})*) } \s* { \s* ((?:[^{}]|\{[^{}]*\})*) } \s* { \s* ((?:[^{}]|\{[^{}]*\})*) } /\\noindent{\\tt $1 \$\\key{$2}\$($3)}/gx; s/\\fun\s*\{([^{}]*)\}\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*\{((?:[^{}]|\{[^{}]*\})*)\}/\\kbd{$1 \\key{$2}($3)}\\sidx{$2}/g; s/\\\\(?=[a-zA-Z])/\\bs /g; s/\\b\{\}\\b\{\}/\\bs\\bs /g; s/\\\\/\\bs/g; s/(\'\'|\`\`)/"/g unless $to_pod; # (english) double quotes # asymptotic or isomorphic (~) [beware of ties] s/(^|[^\\]) +~/$1~/; s/~ */~/; s/(^|[^\\])~/$1$tr{nbrk}/g; # ties s/\\(simeq|sim|approx)(?![a-zA-Z])/ ~ /g; s/\\til(?![a-zA-Z])/~/g; # ~ (transpose) s/\\(~|tilde)/~/g; s/\\(equiv)(?![a-zA-Z])/ = /g; s/\\`a/$tr{agrave}/; s/\\`\{a\}/$tr{agrave}/; s/\\"o/$tr{ouml}/; s/\\"\{o\}/$tr{ouml}/; s/\\"u/$tr{uuml}/; s/\\"\{u\}/$tr{uuml}/; s/\\'e/$tr{eacute}/; s/\\'\{e\}/$tr{eacute}/; s/(^|[^\\])%.*/$1/g; # comments s/\\vadjust\s*\{\s*\\penalty\s*\d+\s*\}//g; # We do not strip %\n, thus: s/\\kbd\{\n\s*/\\kbd{/g; s/\$\\bf(\b|(?=[\d_]))\s*([^\$]+)\$/\$$tr{startbcode}$1$tr{endbcode}\$/g; s/\$/$tr{dollar}/g; # math mode s/\t/ /g; s/\\,//g; s/\\[ ;]/ /g; # various spaces s/\\\///g; # italic correction s/^&+//g; # tab marks s/([^\\])&+/$1 /g; # tab marks s/\\TeX\{\}/TeX/g; s/\\TeX(\W)/TeX$1/g; s/ *\\circ\b */ o /g; s/\\d?frac\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/($1)\/($2)/g; s(\\d?frac\s*(\d)\s*(\d))(($1/$2))g; s[{\s*(\w)\s*\\over(?![a-zA-Z])\s*(\w)\s*}]{($1/$2)}g; s[{\s*((?:[^{}]|\{[^{}]*\})*)\\over(?![a-zA-Z])\s*((?:[^{}]|\{[^{}]*\})*)}][($1)/($2)]g; # \def\synt#1#2{\syn{#1}{\tt #2}} # \def\syn#1#2{\synx{#1}{#2}{#1}} s/\\synt?\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\synx{$1}{$2}{$1}/g; # \def\synx#1#2#3{\sidx{#3}The library syntax is $\key{#1}({#2})$} # Often used with embedded {}. s/\\synx\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{((?:[^{}]|\{[^{}]*\})*)\}/\\sidx{$3}The library syntax is $tr{startcode}$tr{startbold}$1$tr{endbold}($2)$tr{endcode}/; # May be used with an empty arg s/\\typ\{([^\}]*)\}/$tr{startcode}t_$1$tr{endcode}/g; s/(\\string)?\\_/_/g; s/\\([#\$&%|])/$1/g; s/\\(hat(?![a-zA-Z])|\^)(\{\\?\s*\})?/^/g; s/^(\@\[podleader\]head\d *)\\pow(?![a-zA-z])( *)/$1^$2/gm; s/ *\\pow(?![a-zA-z]) */^/g; s/\\neq?(?![a-zA-Z])/ != /g; s/\\enspace(?![a-zA-Z])/ /g; s/\\\*/ /g; s/\\times(?![a-zA-Z]) */ x /g; s/\\infty(?![a-zA-Z]) */ oo /g; s/ *\\(bmod|mod) */ mod /g; s/ *\\pmod(?![a-zA-Z]) *\{\s*((?:[^{}]|\{[^{}]*\})*)\}/ (mod $1)/g; s/ *\\cdot(?![a-zA-Z]) */./g; # Maybe " . "? s/ *(\\|\@)[lc]?dots(?![a-zA-Z]) */.../g; s/\\(Id|Norm|disc|Cl|log|sin|cos|lim(proj)?|tan|mod|sqrt|exp|ln|det|Re|Im|deg|wp|cap|oplus)(?![a-zA-Z])/$tr{startlword}$1$tr{endlword}/g; s/\\pi(?![a-zA-Z])/$tr{startword}Pi$tr{endword}/g; s/\\(Alpha | Beta | Chi | Delta | Epsilon | Phi | Gamma | Eta | Iota | vartheta | Kappa | Lambda | Mu | Nu | Omicron | Pi | Theta | Rho | Sigma | Tau | Ypsilon | varsigma | Omega | Xi | Psi | Zeta | alpha | beta | chi | delta | epsilon | varepsilon | phi | gamma | eta | iota | varphi | kappa | lambda | mu | nu | omicron | pi | theta | rho | sigma | tau | ypsilon | varpi | omega | xi | psi | zeta | int | expr | seq | args | gcd | lcm | sum | prod | Re | infty ) (?![a-zA-Z])/$tr{startword}$1$tr{endword}/xg; s/ *\\in(?![a-zA-Z]) */ belongs to /g; s/\\pm(?![a-zA-Z])/$tr{pm}/g; s/ *\\mid(?![a-zA-Z]) */ | /g; s/\\idxtyp\{([^{}]*)\}/\\sidx{t_$1}/g; s/\\ref\{([^\}]*)\}/[$tr{startbold}Label: $1$tr{endbold}]/g unless $to_pod; s/\\secref\{([^\}]*)\}/Section [$tr{startbold}Label: $1$tr{endbold}]/g unless $to_pod; s/\\label\{[^\}]*\}//g unless $to_pod; s/ *\\noindent\b */\@3/; s/\\(medskip|bigskip|smallskip|left|right)(?![a-zA-Z])[ \t]*//g; s/\\vfill *(\\eject)?//g; s/\\(q|quad)(?![a-zA-Z])\s*/ /g; s/\\qquad(?![a-zA-Z])\s*/ /g; s/\\centerline\s*\{\s*(?:\\tt\b\s*)?(.*(\n[ \t].*)*)\}(?=\s*$)/indent_equally($1)/ge; s/\\centerline\s*\{\s*(?:\\tt\b\s*)?((?:[^{}]|\{[^{}]*\})*)\}/ indent_equally($1)/ge; s/\\big\b//g; s/\\settabs.*//; s/^\\\+/\n$tr{nbrk}/gm; s/\\\+//g; s/\\cr(?![a-zA-Z])//g; s/\\B(?![a-zA-Z])/\\kbd{BIL}/g; s/ *([=><]) */ $1 /g; s/ *< *([=<]) */ <$1 /g; s/ *> *([=>]) */ >$1 /g; s/ *([*+-\/^&=|:]) += */ $1= /g; s/ *! *= */ != /g; s/ == = / === /g; s/ *\\Rightarrow */ ==$tr{gt} /g; s/\\rangle(?![a-zA-Z])\s*/$tr{startcode}$tr{gt}$tr{endcode}/g; 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/ *\\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; s/ *\\ll?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{lt}$tr{ll}$tr{endcode} $1/g; s/\\(vers|PARIversion)(?![a-zA-Z])/$tr{startbold}$version$tr{endbold}/; s/\\([QRCFZNapdf])(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g; s/\\([QRCFZN])\1(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g; s/\\Bbb\b\s*(\w)/$tr{startbi}$1$tr{endbi}/g; s/\\([oc]br)/$tr{$1}/g; s/\\quo(?![a-zA-Z])/\"/g; s/(^|\s)\{(\w+)\}/$1$2/g; s/\\p(?![a-zA-Z])/$tr{startbold}p$tr{endbold}$1/g; s/^ *\\point\{([^\}]*)\}/\\item $1/g; s/\@\[dollar]\\bullet\@\[dollar]/\\item /g; s/\\bullet/\\item/g; s/^ *\\item/\@3$tr{startbold}*$tr{endbold}/g; 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{gt}/g if $to_pod; s/\\kbd\s*\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startcode}$1$tr{endcode}/g; s/\\key\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g unless $refcard; s/\\goth\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g; if ($refcard) { s/\\(?:key|li)\{((?:[^{}]+(?=[{}])|\{[^{}]*\})*)\}\s*\{\}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/g; s/\\(?:key|li)\{((?:[^{}]+(?=[{}])|\{[^{}]*\})*)\}\s*\{(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/\n=item $tr{startcode}$2$tr{endcode}\n\n$1\n/g; } s/\\(floor|ceil|round|binom)\{/$1\{/g; s/\\(var|emph)\{([^\}]*)\}/$tr{startit}$2$tr{endit}/g; s/\\fl(?![a-zA-Z])/$tr{startit}flag$tr{endit}/g; s/\\b\{([^}]*)\}/$tr{startcode}\\$1$tr{endcode}/g; s/\\kbdsidx/\\sidx/g; s/\\sidx\{[^\}]*\}//g unless $to_pod; s/\\[a-zA-Z]*idx\{([^\}]*)\}/$1/g unless $to_pod; s/\{\\text\{(st|nd|th)\}\}/\\text{$1}/g; s/\^\\text\{th\}/-th/g; s/1\^\\text\{st\}/1st/g; s/2\^\\text\{nd\}/2nd/g; s/\\(text|hbox|Big)//g; s/^([ \t]+)\{ *\\(it|sl|bf|tt)\b/S<$1>{\\$2/gm; s/\{ *\\(it|sl) *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startit}$2$tr{endit}/g; s/\{ *\\bf *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g; s/\{ *\\tt *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startpodcode}$1$tr{endpodcode}/g; $seek=1 if (s/\\emph\{ */$tr{startit}/g); if ($seek) { $seek=0 if (s/\}/$tr{endit}/) } s/\\(backslash|bs)\{(\w)\}/\\$2/g; s/\\(backslash|bs)(?![a-zA-Z]) */\\/g; s/ *\\setminus */ \\ /g; s/\@com(.*)$/$tr{startcode}$1$tr{endcode}/g; # Last resort: s/\\kbd\s*\{(.*?)\}/$tr{startcode}$1$tr{endcode}/g; s/^([ \t]{3,})\Q$tr{startcode}\E(.*)\Q$tr{endcode}\E/$1$2/gmo if $to_pod; # Last resort: s/^([ \t]{3,})\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1$2/gmso if $to_pod; # Remove leading spaces unless have embedded wrapped code: s/^[ \t]+//gm if $to_pod and /^\S/ and not /^[ \t]*\n[ \t]/m; s/\{ *\}//g; # empty args s{\Q$tr{startcode}\E((ftp|http)://.*?)\Q$tr{endcode}\E}{$tr{startlink}$1$tr{endlink}}go if $to_pod; $_; } sub presubst { chomp; if ($in_prog && /\@eprog *(\\noindent)? */) { my ($eprog) = $1? '@3': '@2'; $in_prog = 0; $_ = $eprog . &code_subst($`) . $tr{endcode}; push(@text, $_); $_ = &basic_subst($'); } elsif ($in_prog || s/\\bprog(tabs.*)?//g) { $in_prog++; # = 1 on the \bprog line # code should start on the next line $_ = &code_subst($_); s/^/\@1$tr{startcode}/ if ($in_prog == 2); s/^/\@0/ if ($in_prog > 2); } else { $_ = &basic_subst($_); } if (/^ *$/) { push(@text,"\n"); } else { for (split(/\n/, $_)) { push(@text, $_); } } } sub code_subst { my $in = shift; $in =~ s/\@dots\b/.../g; if ($in =~ /\@com(.*)/) { if ($to_pod) { $in = $` . &basic_subst($1) . code_subst($'); } else { $in = $` . $tr{endcode} . &basic_subst($1) . $tr{startcode} . code_subst($'); } } if ($in =~ /\@Ccom(.*)\*\//) { if ($to_pod) { $in = $` . &basic_subst($1) . "*/" . &code_subst($'); } else { $in = $` . $tr{endcode} . &basic_subst($1) . $tr{startcode} . "*/" . &code_subst($'); } } $in; } sub wrap_code { my $in = shift; $in =~ s/^[ \t]+$//mg; $in = &code_subst($in); $in =~ s/^(.)/ $1/mg; $in =~ s/\s*\Z//; # $in =~ s/\\kbd\{((?:[^{}]|\{[^{}]*\})*)\}/$1/g if $to_pod; $in =~ s/\$([^\$\n]*)\$/$1/g if $to_pod; "\n\n$in\n\n"; } sub indexify { my $in = shift; $in =~ s/(^|and\s+)(\w+)(\$?\()/$1\\idx{$2}$3/g; $in =~ s/^(\\b\{\w+\})(?!\S)/\\idx{$1}/g; $in; } sub for_index { my $in = shift; 1 while $in =~ s/\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1/go; $in; } sub strip_trail { my $in = shift; $in =~ s/\s+\Z//; $in } # This subroutine works in paragraph mode sub TeXprint_topod { s/\A\s+//; s/^\\def\\.*\{\n.*\n\}//gm; s/\\def\\.*//g; # Repeated in basic_subst, as the next one s/(\{[\w\s]+)\{\}([\s\w]+\})/$1$2/g; # {rnf{}llgram} s/\\vbox\s*\{\s*\\bprog/\\bprog/g; s/([\\\@])eprog\s*\}/$1eprog/g; # \n is below to prevent splitting on ' ' # We also remove ':' s/\\sectype\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$2}/g; s/\\sectypeindex\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$3}/g; s/\\sectypes\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} and \\typ{$1} (${3}s)}\n\\sidx{$3}/g; # Try to guard \label/\sidx (removing possible '.') # This somehow breaks index... # s/(\\(?:section|subsec(?:ref|idx|op)?(unix)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/; s/(\\(?:section|subsec(?:ref|idx|op)?)\s*\{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)\})\.?\s*\\(label|sidx)/$1\n\\$2/; # last if /\\subsec[\\{}ref]*[\\\${]$help[}\\\$]/o; s/\\chapter\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/\n\n$tr{podleader}head1 NAME\n\nlibPARI - $1\n\n/; s/\\appendix\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/\n\n$tr{podleader}head1 NAME\n\nAppendix - $1\n\n/; s/\\section\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/"\n\n$tr{podleader}head1 " . indexify($1) . "\n\n"/e; # Try to delimit by : s/\\subsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}([^\n]*):[\n ]/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}([^:]*):\s*/"\n\n$tr{podleader}head3 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(.*)$/"\n\n$tr{podleader}head3 " . indexify("$1") . "$3\n\n"/me; s/\\subseckbd\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; # Try to delimit by ' ' s/\\subsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsec(?:title)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]*})+)\}:?\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e; # This is to skip preface in refcard: /\Q$tr{podleader}\Ehead1|\\title(?![a-zA-Z])\s*\{/o and $seen_start = 1 or $seen_start or return; # Skip now! s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/$tr{podleader}head1 NAME\n\n$1 - $3. $5\n\n/ and $seen_title++ unless $seen_title; s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/\n\n/; s/\\parskip.*/\n/g; # Up to end of the line #s/([A-Z])\ until /(\\|@)eprog\b/ or eof(DOC); $acc .= wrap_code($1) if s/\A(?:tabs[^\n]*)?(?![a-zA-Z])[ \t]*\n?(.*?)(\\|@)eprog\s*//s; } $_ = $acc . basic_subst($_); # s/\\kbd\{/\{\\tt /g; # startcode # s/\\typ\{/\{\\tt t_/g; # startcode s/\$\s*(\@\[startbi\][A-Z]\@\[endbi\])\s*\$/$1/g; # s/\\p(\b|(?=[\d_]))/B

/g; #s/\$\\bf\b\s*([^\$]+)\$/C>/g; @lines = split /^$/m, $_; for (@lines) { s/>/\@[gt]/g unless /^\n*[ \t]/; s/$tr{startcode}$1$tr{endcode}\n\n/gs; s/\$([^\$]+)\$/$tr{startcode}$1$tr{endcode}/g; s/\\s(?:ref|idx)\{\s*([^{}]*)\}/"X<" . for_index($1) . ">"/ge; # s/\\(?:ref|idx)\{\s*([^{}]*)\}/"X<" . for_index($1) . ">$1"/ge; # Conflict between different versions of PARI and refcard: # s/\\(?:key|li)\s*\{(.*)\}\s*\{(.+)\}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/msg; # s/\\(?:key|li)\s*\{(.*)\}\s*\{\}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/mgs; # s/\\(key|var)(?![a-zA-Z])\s*\{(\w+)\}/C<$2>/mg; s/\\var\s*\{X<(\w+)>(\w+)\}/X<$1>$tr{startcode}$2$tr{endcode}/mg; s/\\var\s*\{f\{\}lag\}/$tr{startcode}flag$tr{endcode}/mg; s/\\metax(?![a-zA-Z])\s*\{(.*)\}\s*\{\s*(\w+)(?=C\<)(.*)\}[ \t]*\n/\n\n=item C$3>\n\n$1\n\n/mg; s/\\metax(?![a-zA-Z])\s*\{(.*)\}\s*\{(.*)\}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg; s/C\<\{\}=/C\<=/g; s/\\fl(?![a-zA-Z])/I/g; s/\\file(?![a-zA-Z])/F/g; s/\\(unix|emacs)\b\s*(\{?)(\s*\\(no)?indent)?\s*/X<\U$1>$2/g; s/\A\\label\s*\{([\w:.-]*)\}([ \t]*\n\s*(?=[^\s=]))?/X

] Options: some names can be abbreviated to one character (e.g -h = -help) -a, --ask interactive configuration -h, --help this message -l, --load skip Configure and specify a default config file -s, --static build static GP binary only -v, --verbhelp a longer help message Build Options: --host= target achitecture --kernel= kernel used --graphic= graphic library used (none, X11, Qt, fltk, ps, win32) --time= timing function to use (getrusage, clock_gettime, times, ftime) --builddir= directory where the object files will be created --tune tune the binary for compiling host (slow) Additional developer options: -g creates debugging version (in Oxxx.dbg) -pg creates profiling version (in Oxxx.prf) -gcov creates gcov version (in Oxxx.gcov) --enable-tls (*experimental*) enable thread-local stack --mt=pthread (*experimental*) enable pthread thread engine --mt=mpi (*experimental*) enable MPI thread engine Installation directories: --prefix= install files in (default $prefix) --share-prefix= as 'prefix', for architecture independent files --bindir= for binaries --includedir= for C header files --libdir= for libraries --mandir= for manual pages --sysdatadir= for architecture-dependent data --datadir= for architecture-independent data Optional libraries: --without-readline do not link with GNU readline --with-readline[=DIR] use GNU readline [prefix for readline files] --with-readline-include=DIR specify location of readline headers --with-readline-lib=DIR specify location of readline libs --with-ncurses-lib=DIR specify location of ncurses lib (for readline) --without-gmp use the native kernel instead of GNU MP --with-gmp[=DIR] use the GMP kernel [prefix for gmp files] --with-gmp-include=DIR specify location of gmp headers --with-gmp-lib=DIR specify location of gmp libs --with-qt[=DIR] use the Qt graphical library [prefix for Qt dir.] --with-fltk[=DIR] use the FLTK graphical library [prefix for FLTK dir.] Environment variables affecting the build: CC C compiler CFLAGS additional flags to the C compiler LD linker LDFLAGS additional linker flags DLLDFLAGS additional linker flags for linking the shared lib C_INCLUDE_PATH directories to search for include files (separate by :) LIBRARY_PATH directories to search for libraries (separate by :) EOT exit 1 ;; verb) cat >&2 < $TMPFL if cmp $FL $TMPFL >/dev/null 2>&1; then rm -f $TMPFL else echo "File $FL updated." mv $TMPFL $FL fi pari-2.7.5/config/get_include_path0000644000175000017500000000066312314242551015600 0ustar billbillincpth="`echo $C_INCLUDE_PATH | sed -e \"s%\([^$dir_sep]*\)$dir_sep*%\1 \1/readline %g\"`" case "$osname" in os2);; cygwin*) incpth="$incpth\ $cygtop/usr/local/include\ $cygtop/usr/include\ $cygtop/H-${arch}-cygwin32/${arch}-cygwin32/include\ ";; *) incpth="$incpth\ /usr/local/include\ /usr/include\ /opt/include\ /opt/local/include\ /opt/gnu/include\ ";; esac basic_include_path=$incpth pari-2.7.5/config/has_ftime.c0000644000175000017500000000014412366172547014472 0ustar billbill# include int main() { struct timeb t; ftime(&t); return t.time*1000+t.millitm; } pari-2.7.5/config/has_setsid.c0000644000175000017500000000014411636712103014644 0ustar billbill#include #include pid_t (*f)() = setsid; int main(){ return f != setsid; } pari-2.7.5/config/get_static0000644000175000017500000000173411636712103014431 0ustar billbillif test -z "$DLLD" -o "$optimization" != full; then static=y else static=${static-n} fi if test "$fastread" != yes; then if test -z "$DLLD"; then cat < #include #include int main() { struct rlimit rip; getrlimit(RLIMIT_STACK, &rip); setrlimit(RLIMIT_STACK, &rip); return 0; } pari-2.7.5/config/get_install0000644000175000017500000000400112366172547014613 0ustar billbill# Exported variables _install_list="prefix share_prefix bindir datadir includedir libdir mandir sysdatadir " dflt=$prefix; rep= test "$fastread" = yes || cat </dev/null 2>&1 ; then echo "...using -n."; n=-n; c= else cat <$c"; echo '*' fi pari-2.7.5/config/rl_version.c0000644000175000017500000000015612533333715014710 0ustar billbill#include #include int main(){ printf("%s\n", rl_library_version); return 0; } pari-2.7.5/config/has_times.c0000644000175000017500000000027411636712103014476 0ustar billbill#include #include #include main(){ struct tms t; printf("%d%d", times(&t), #ifdef _SC_CLK_TCK sysconf(_SC_CLK_TCK) #else CLK_TCK #endif ); } pari-2.7.5/config/log_cmd0000644000175000017500000000004112314242551013674 0ustar billbillecho $cmd >&5 eval $cmd >&5 2>&1 pari-2.7.5/config/has_alarm.c0000644000175000017500000000013611636712103014446 0ustar billbill#include unsigned int (*f)(unsigned int) = alarm; int main(){ return f != alarm; } pari-2.7.5/config/get_libpth0000644000175000017500000000241112314242551014414 0ustar billbillcase "$sizeof_long" in 8) addlib64="/usr/local/lib64 /lib64 /usr/lib64" esac libpth="`echo $LIBRARY_PATH | sed -e \"s%\([^$dir_sep]*\)$dir_sep*%\1 %g\"`" case "$osname" in cygwin*) cygtop=/cygdrive/c if test ! -d $cygtop; then ver=`uname -r | cut -d. -f1` cygtop=/Cygnus/cygwin/B$ver if test ! -d $cygtop; then cygtop=/Cygnus/cygwin-B$ver if test ! -d $cygtop; then cygtop=/usr/${arch}-pc-cygwin if test ! -d $cygtop; then echo ..."I could not find Cygwin top directory" >&2 fi fi fi fi if test "$cygtop" = /cygdrive/c; then # cygnus for version 1.* libpth="$libpth\ /usr/local/lib\ /lib\ " cygtop= else # cygnus for version 0.* libpth="$libpth\ $cygtop/H-${arch}-cygwin32/lib\ $cygtop/H-${arch}-cygwin32/${arch}-cygwin32/lib\ " fi;; os2) libpth=`echo $libpth | sed 's,\\\\,/,g'`;; *) libpth="$libpth $addlib64\ /usr/local/lib\ /lib\ /usr/lib\ /opt/lib\ /opt/local/lib\ /opt/gnu/lib\ /lib/pa1.1\ /usr/lib/large\ /lib/large\ /usr/lib/small\ /lib/small\ /usr/ccs/lib\ /usc/ucblib\ /usr/shlib\ .\ ";; esac pari-2.7.5/config/get_cc0000644000175000017500000001113312366172547013536 0ustar billbill# Exported variables _cc_list="__gnuc__ CC CFLAGS optimization DBGFLAGS OPTFLAGS exe_suff suffix ASMINLINE KERNELCFLAGS" # Which optimization ? if test "$fastread" != yes; then cat << EOT ========================================================================== The default is to fully optimize the compilation. You may choose to build an executable for debugging or profiling instead. Choose among : full debugging profiling gcov EOT echo $n ..."Which optimization do you prefer ? $c" dflt=$optimization; rep='full debugging profiling gcov'; . ./myread optimization=$ans fi case "$osname" in os2) exe_suff=.exe; extraflag="-Zexe";; cygwin|mingw) exe_suff=.exe; extraflag="";; # On Darwin, by default, the full library search path is searched for a .dylib # before a .a can be considered, preventing users to install their libraries # in a simple way (e.g. the readline / Editline conflict). Override this. darwin) exe_suff=; extraflag=-Wl,-search_paths_first;; *) exe_suff=; extraflag="";; esac if test -z "$CC"; then echo Choosing C compiler ... if test -n "$gcc"; then CC=$gcc; else CC=$cc; fi fi if test "$fastread" != yes; then cat << EOT ========================================================================== Only ANSI C and C++ compilers are supported. Choosing the GNU compiler gcc/g++ enables the inlining of kernel routines (about 20% speedup; if you use g++, include the -fpermissive flag). We strongly recommand using gcc all the way through. EOT echo $n ..."Which C compiler shall I use ? $c" dflt=$CC; rep=; . ./myread CC=$ans fi if test -z "$CC"; then cat <&1 |\ grep ' version ' | tr '\n' , | sed -e 's/,$//'` echo GNU compatible compiler: $__gnuc__ fi rm -f $exe $exe$exe_suff fi # Which Flags for Compiler ? cflags= ASMINLINE= if test -n "$__gnuc__"; then __GNUC__="-D__GNUC__" warn="-Wall" OPTFLAGS=-O3 ASMINLINE=yes OPTFLAGS="$OPTFLAGS $warn" cmd="$CC $CFLAGS $extraflag -fno-strict-aliasing -o $exe gnu.c" . log_cmd if test -s $exe; then OPTFLAGS="$OPTFLAGS -fno-strict-aliasing" fi rm -f $exe $exe$exe_suff KERNELCFLAGS=-funroll-loops DBGFLAGS=${DBGFLAGS:-"-g $warn"} # Specific optimisations for some architectures case "$arch" in sparcv8*) cflags=-mv8;; i?86|x86_64) case "$__gnuc__" in gcc*4.0.*) cflags=-fno-gcse-after-reload esac esac # problems on some architectures case "$osname" in os2) cflags="$cflags -Zmt -Zsysv-signals";; nextstep) cflags="$cflags -traditional-cpp";; esac # omit-frame-pointer incompatible with -pg PRFFLAGS="-pg $OPTFLAGS" GCOVFLAGS="-fprofile-arcs -ftest-coverage" case "$optimization" in full) case "$osname" in mingw) ;; *) OPTFLAGS="$OPTFLAGS -fomit-frame-pointer";; esac;; esac else DBGFLAGS=${DBGFLAGS:-'-g'} PRFFLAGS='-pg' case "$osname-$arch" in hpux-*) # -Ae is for ANSI C + defines HPUX_SOURCE OPTFLAGS=-O; cflags=-Ae;; aix-*) OPTFLAGS='-O2 -qtune=auto -qmaxmem=8192' cflags='-qlanglvl=ansi';; osf1-*) OPTFLAGS='-O4 -migrate -ifo -Olimit 9999';; sunos-*) OPTFLAGS=-fast; PRFFLAGS='-pg -Bstatic';; solaris-*) OPTFLAGS='-fast -fsimple=1'; PRFFLAGS=-xpg; case "$arch" in sparc*) OPTFLAGS="$OPTFLAGS -xalias_level=any";; esac;; concentrix-*) OPTFLAGS=-Ogi;; *) OPTFLAGS=-O;; esac PRFFLAGS="$PRFFLAGS $OPTFLAGS" fi case "$optimization" in full) suffix=; cflags="$OPTFLAGS $cflags";; profiling) suffix=.prf; cflags="$PRFFLAGS $cflags";; debugging) suffix=.dbg; cflags="-DMEMSTEP=1048576 $DBGFLAGS $cflags";; gcov) suffix=.gcov; cflags="$GCOVFLAGS $cflags";; esac CFLAGS="$cflags $CFLAGS $CPPFLAGS" if test "$fastread" != yes; then echo $n ..."With which flags ? $c" dflt=$CFLAGS; rep=; . ./myread CFLAGS=$ans fi pari-2.7.5/config/paricfg.h.SH0000644000175000017500000000666412405547147014475 0ustar billbillfile="$objdir/paricfg.h" echo Extracting $file rm -f $file case "$optimization" in full) ;; *) debuginfo=" -- $optimization";; esac if test -n "$perl"; then case "$osname" in os2|mingw) gphelp="perl -S gphelp -detex" ;; *) gphelp="\\\"$bindir/gphelp\\\"" ;; esac fi has_stack_check= if test "$osname" = "os2" -o "$has_getrlimit" = "yes"; then has_stack_check=yes; fi cat > $file << EOT /* This file was created by Configure. Any change made to it will be lost * next time Configure is run. */ #ifndef __CONFIG_H__ #define __CONFIG_H__ EOT cat >> $file << EOT #define UNIX #define GPHELP "$gphelp" #define GPDATADIR "$datadir" #define SHELL_Q '\\$shell_q' #define PARIVERSION "GP/PARI CALCULATOR Version ${version}.${patch} (${status})" #define PARIINFO "${pretty}${debuginfo}" #define PARI_VERSION_CODE ${version_code} #define PARI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #define PARI_VERSION_SHIFT 8 #define PARI_VCSVERSION "${vcsversion}" #define PARI_MT_ENGINE "${thread_engine}" #define PARI_DOUBLE_FORMAT ${doubleformat} EOT if test -n "$__gnuc__"; then echo "#define GCC_VERSION \"$__gnuc__\"" >> $file fi case $asmarch in none) echo '#define __HAS_NO_ASM__' >> $file;; hppa) echo '#define __HPPA__' >> $file;; esac if test -n "$ASMINLINE"; then echo '#define ASMINLINE' >> $file fi if test -n "$gzip"; then cat >> $file << EOT /* Location of GNU gzip program (enables reading of .Z and .gz files). */ #define GNUZCAT #define ZCAT "$gzip -dc" EOT else if test -n "$zcat"; then cat >> $file << EOT /* Location of zcat program (enables reading of .Z files). */ #define ZCAT "$zcat" EOT fi fi if test "$osname" = "mingw"; then cat >> $file << EOT #undef UNIX #define GNUZCAT #undef ZCAT #define ZCAT "gzip.exe -dc" EOT fi if test -n "$readline"; then cat >> $file <> $file;; esac case "$has_exp2" in yes) echo '#define HAS_EXP2' >> $file;; esac case "$has_log2" in yes) echo '#define HAS_LOG2' >> $file;; esac case "$has_isatty" in yes) echo '#define HAS_ISATTY' >> $file;; esac case "$has_alarm" in yes) echo '#define HAS_ALARM' >> $file;; esac case "$has_clock_gettime" in yes) echo '#define USE_CLOCK_GETTIME 1' >> $file;; *) case "$has_getrusage" in yes) echo '#define USE_GETRUSAGE 1' >> $file;; *) case "$has_times" in yes) echo '#define USE_TIMES 1' >> $file;; *) case "$has_ftime" in yes) echo '#define USE_FTIME 1' >> $file;; esac;; esac;; esac;; esac case $has_sigaction in yes) echo '#define HAS_SIGACTION' >> $file;; esac case $has_waitpid in yes) echo '#define HAS_WAITPID' >> $file;; esac case $has_getenv in yes) echo '#define HAS_GETENV' >> $file;; esac case $has_setsid in yes) echo '#define HAS_SETSID' >> $file;; esac case $has_dlopen in yes|builtin) cat >> $file << EOT #define HAS_DLOPEN EOT ;; esac case $has_stack_check in yes) echo '#define STACK_CHECK' >> $file;; esac case $has_vsnprintf in yes) echo '#define HAS_VSNPRINTF' >> $file;; esac case $has_TIOCGWINSZ in yes) echo '#define HAS_TIOCGWINSZ' >> $file;; esac case $has_strftime in yes) echo '#define HAS_STRFTIME' >> $file;; esac case $has_opendir in yes) echo '#define HAS_OPENDIR' >> $file;; esac case $has_stat in yes) echo '#define HAS_STAT' >> $file;; esac case $enable_tls in yes) echo '#define ENABLE_TLS' >> $file;; esac echo '#endif' >> $file pari-2.7.5/config/has_sigaction.c0000644000175000017500000000031412314242551015327 0ustar billbill#include int main() { struct sigaction sa, oldsa; sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; (void)(sigaction(SIGINT, &sa, &oldsa)); return 0; } pari-2.7.5/config/has_getrusage.c0000644000175000017500000000033512314242551015340 0ustar billbill#define _INCLUDE_POSIX_SOURCE #include #include #include #include #include int main(){ struct rusage a; printf("%d",getrusage(RUSAGE_SELF,&a)); return 0; } pari-2.7.5/config/ansi.c0000644000175000017500000000005511636712103013451 0ustar billbillint main(int argc, char **argv){ return 0; } pari-2.7.5/config/get_gmp0000644000175000017500000000432212366172547013736 0ustar billbill_gmp_list="gmp GMPLIBS GMPINCLUDE" gmp= 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` case $x in ?:/*|/*) gmp_include=`dirname $x` echo ..."Found gmp header in $gmp_include" GMPINCLUDE="-I$gmp_include" ;; *) echo ..."gmp header file not found by Configure, trying to proceed" gmp=;; esac exe=$osname-$arch-gmpv$$ if test -n "$gmp"; then GMPLIBS="-L$gmp -lgmp" else GMPLIBS="-lgmp" 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 case "$gmp_version" in unsupported) gmp= echo "### Your GMP library ABI is unsupported.";; "") gmp= cmd="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe ansi.c $GMPLIBS" . log_cmd if test -r $exe; then echo "### Your version of GMP is too old for PARI. Please upgrade" else echo "### Your GMP library is incompatible with the compiler settings." fi;; *) if test -z "$gmp"; then gmp=yes; fi;; esac rm -f $exe $exe$exe_suff if test -z "$gmp"; then echo "### Building without GNU MP support" else if test "$fastread" = yes; then echo "Using GNU MP, version $gmp_version" else cat << EOM ========================================================================== GNU MP library can be used as an alternate multiprecision kernel, which is faster than PARI's native one as soon as integers larger than 10^100 are considered. Unfortunately, with GNU MP, libpari is binary incompatible with the native one. Despite this, you should only answer 'no' to the following question if you plan to use libpari (not only the gp shell) and have stringent backward compatibility requirements. EOM echo $n "Do you want to use GNU MP library instead of the native kernel? $c" if test "$with_gmp" = yes; then dflt=y; else dflt=n; fi rep='y n'; . ./myread case $ans in n) gmp=;; esac fi fi if test -n "$gmp"; then kernlvl1=gmp else kernlvl1=none GMPINCLUDE= GMPLIBS= fi . get_pretty pari-2.7.5/config/kernel.c0000644000175000017500000000047412314242551014003 0ustar billbill#define ulong unsigned long #define ASMINLINE #include "asm0.h" #define __asm__ __asm__ volatile void fun(ulong a, ulong b) { LOCAL_HIREMAINDER; LOCAL_OVERFLOW; addll(a,b); addllx(a,b); mulll(a,b); addmul(a,b); #if 0 bfffo(a); #endif } int main(void) { fun(0xb9f3dcdcUL,0xfbdc740b); return 0; } pari-2.7.5/config/cygwin-pari.nsi0000755000175000017500000001514612314242551015330 0ustar billbill#! /bin/sh . config/version release=`echo "$pari_release"|sed 's/\./-/g'` cat << EOT ;--- PARI/GP: NullSoft Installer configuration file !include "MUI.nsh" Name "PARI $pari_release_verbose" !define dll "libpari.dll" !define PARIver "Pari-$release" EOT cat << 'EOT' ;--No need to modify things below -- !define top ".." !define cfgdir "${top}\config" AutoCloseWindow false OutFile "Pari.exe" InstallDir "$PROGRAMFILES\${PARIver}" InstallDirRegKey HKLM "Software\${PARIver}" "" !define MUI_ABORTWARNING !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "${top}\COPYING" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Installer Sections !define uninst "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PARIver}" Section "pari (required)" SecCopy SetOutPath "$INSTDIR" File /oname=gp.exe "gp-dyn.exe" File /oname=.gprc "${cfgdir}\cygwin-gprc" File /oname=postinst "${cfgdir}\cygwin-postinst" File "${top}\misc\tex2mail" File "${dll}" FILE "\cygwin\bin\cygcrypt-0.dll" FILE "\cygwin\bin\cygiconv-2.dll" FILE "\cygwin\bin\cygintl-8.dll" File "\cygwin\bin\cyggmp-3.dll" File "\cygwin\bin\cygncursesw-10.dll" File "\cygwin\bin\cygreadline7.dll" File "\cygwin\bin\cygperl5_10.dll" File "\cygwin\bin\cyggcc_s-1.dll" File "\cygwin\bin\cygssp-0.dll" File "\cygwin\bin\cygwin1.dll" File "\cygwin\bin\perl.exe" File "\cygwin\bin\sh.exe" File "\cygwin\bin\ln.exe" SetOutPath "$INSTDIR\terminfo\c" File /nonfatal "\cygwin\usr\share\terminfo\c\cygwin" SetOutPath "$INSTDIR\terminfo\63" File /nonfatal "\cygwin\usr\share\terminfo\63\cygwin" SetOutPath "$INSTDIR" CreateDirectory "$INSTDIR\..\bin" ExecWait 'sh ./postinst' Delete "ln.exe" Delete "postinst" WriteRegStr HKCU "Software\${PARIver}" "" $INSTDIR WriteRegStr HKLM ${uninst} "DisplayName" "${PARIver} (remove only)" WriteRegStr HKLM ${uninst} "UninstallString" '"$INSTDIR\uninstall.exe"' WriteUninstaller "$INSTDIR\Uninstall.exe" SectionEnd SectionGroup /e "Data files" SecDATA Section "Elliptic curves files" SecELL SetOutPath "$INSTDIR\data\elldata" File "${top}\data\elldata\*" SectionEnd Section "Galois files" SecGAL SetOutPath "$INSTDIR\data\galdata" File "${top}\data\galdata\*" SectionEnd Section "Frobenius of elliptic curves files" SecSEA SetOutPath "$INSTDIR\data\seadata" File "${top}\data\seadata\*" SectionEnd Section "Galois polynomial files" SecGPL SetOutPath "$INSTDIR\data\galpol" File "${top}\data\galpol\*" SectionEnd SectionGroupEnd Section "documentation" SecDOC SetOutPath "$INSTDIR" File "${top}\doc\gphelp" SetOutPath $INSTDIR\doc File "${top}\doc\translations" File "${top}\doc\*.tex" File "${top}\doc\*.pdf" SectionEnd Section "examples" SecEX SetOutPath "$INSTDIR" File "${top}\doc\gphelp" SetOutPath $INSTDIR\examples File "${top}\examples\EXPLAIN" File "${top}\examples\Inputrc" File "${top}\examples\*.gp" File "${top}\examples\*.c" File "${top}\examples\Makefile.cygwin-i686" SectionEnd Function .onInstSuccess MessageBox MB_OK "Thank you for using PARI/GP! Double-click on 'gp' to start the calculator.$\r$\nTweak $INSTDIR\.gprc to customize GP: colors, script search path, etc." ExecShell "open" "$INSTDIR" FunctionEnd !define short "$SMPROGRAMS\${PARIver}" Section "shortcuts" SecSM CreateDirectory "${short}" CreateShortCut "${short}\gp.lnk" "$INSTDIR\gp.exe" "" "$INSTDIR\gp.exe" 0 CreateShortCut "${short}\users.lnk" "$INSTDIR\doc\users.pdf" "" "$INSTDIR\doc\users.pdf" 0 CreateShortCut "${short}\libpari.lnk" "$INSTDIR\doc\libpari.pdf" "" "$INSTDIR\doc\libpari.pdf" 0 CreateShortCut "${short}\tutorial.lnk" "$INSTDIR\doc\tutorial.pdf" "" "$INSTDIR\doc\tutorial.pdf" 0 CreateShortCut "${short}\refcard.lnk" "$INSTDIR\doc\refcard.pdf" "" "$INSTDIR\doc\refcard.pdf" 0 WriteINIStr "${short}\PARI pages.url" "InternetShortcut" "URL" "http://pari.math.u-bordeaux.fr" CreateShortCut "${short}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$DESKTOP\PARI.lnk" "$INSTDIR\gp.exe" SectionEnd ;-------------------------------- ;Descriptions LangString DESC_SecCopy ${LANG_ENGLISH} "Copy pari files to application folder." LangString DESC_DOC ${LANG_ENGLISH} "Install documentation and online help." LangString DESC_EX ${LANG_ENGLISH} "Install sample GP scripts." LangString DESC_DATA ${LANG_ENGLISH} "Data files pertaining to pari" LangString DESC_ELL ${LANG_ENGLISH} "Install elliptic curves data files (for ellsearch and ellidentify)." LangString DESC_GAL ${LANG_ENGLISH} "Install Galois data files (for polgalois in degree > 7)." LangString DESC_SEA ${LANG_ENGLISH} "Install Modular polynomials (for ellap'SEA implementation)." LangString DESC_GPL ${LANG_ENGLISH} "Install Galois polynomials data files (for galoisgetpol)." LangString DESC_SM ${LANG_ENGLISH} "Add PARI shortcuts to Start Menu and desktop." !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecCopy} $(DESC_SecCopy) !insertmacro MUI_DESCRIPTION_TEXT ${SecDATA} $(DESC_DATA) !insertmacro MUI_DESCRIPTION_TEXT ${SecELL} $(DESC_ELL) !insertmacro MUI_DESCRIPTION_TEXT ${SecGAL} $(DESC_GAL) !insertmacro MUI_DESCRIPTION_TEXT ${SecSEA} $(DESC_SEA) !insertmacro MUI_DESCRIPTION_TEXT ${SecGPL} $(DESC_GPL) !insertmacro MUI_DESCRIPTION_TEXT ${SecSM} $(DESC_SM) !insertmacro MUI_DESCRIPTION_TEXT ${SecDOC} $(DESC_DOC) !insertmacro MUI_DESCRIPTION_TEXT ${SecEX} $(DESC_EX) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- Section "Uninstall" Delete "$INSTDIR\gp.exe" Delete "$INSTDIR\.gprc" Delete "$INSTDIR\gphelp" Delete "$INSTDIR\tex2mail" Delete "$INSTDIR\${dll}" Delete "$INSTDIR\cygcrypt-0.dll" Delete "$INSTDIR\cygiconv-2.dll" Delete "$INSTDIR\cygintl-8.dll" Delete "$INSTDIR\cyggmp-3.dll" Delete "$INSTDIR\cygncursesw-10.dll" Delete "$INSTDIR\cygreadline7.dll" Delete "$INSTDIR\cygperl5_10.dll" Delete "$INSTDIR\cyggcc_s-1.dll" Delete "$INSTDIR\cygssp-0.dll" Delete "$INSTDIR\cygwin1.dll" Delete "$INSTDIR\perl.exe" Delete "$INSTDIR\sh.exe" Delete "$INSTDIR\Uninstall.exe" RMDir /r "$INSTDIR\doc" RMDir /r "$INSTDIR\examples" RMDir /r "$INSTDIR\data" RMDir /r "$INSTDIR\terminfo" DeleteRegKey HKLM ${uninst} DeleteRegKey /ifempty HKLM "Software\${PARIver}" RMDir /r "$SMPROGRAMS\${PARIver}" Delete "$DESKTOP\PARI.lnk" Delete "$INSTDIR\..\bin\sh" RMDir "$INSTDIR\..\bin" RMDir "$INSTDIR" SectionEnd EOT pari-2.7.5/config/get_MANIFEST0000755000175000017500000000050112314242551014341 0ustar billbillgit ls-files | grep -v '/$' | grep -v '\.gitignore' | grep -v TODO # generated files echo doc/usersch3.tex 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 echo src/funclist pari-2.7.5/config/has_wait.c0000644000175000017500000000012611636712103014315 0ustar billbill#include #include #include main(){ wait(NULL); } pari-2.7.5/config/display0000755000175000017500000000046511636712103013753 0ustar billbillif test -n "$perl"; then echo $rep | $perl -e " @input=split(/\s/,<>); \$len = \$#input + 3; \$len = ( \$len - \$len % 3) / 3; for(\$i=0;\$i<\$len;\$i++) { printf qq( %-18s%-18s%-18s\n), \$input[\$i], \$input[\$i+\$len], \$input[\$i+2*\$len]; }" else echo $rep fi pari-2.7.5/config/has_getenv.c0000644000175000017500000000007612314242551014644 0ustar billbill#include int main(){ (void)getenv(""); return 0; } pari-2.7.5/config/has_stat.c0000644000175000017500000000034411636712103014326 0ustar billbill#include #if (!defined(_MSC_VER) && !defined(_WIN32)) # include # include #endif int main(void) { struct stat buf; if (stat (".", &buf) || !S_ISDIR(buf.st_mode)) return 1; return 0; } pari-2.7.5/config/kernel-name0000755000175000017500000000113111636712103014473 0ustar billbill#! /bin/sh name=$1 arch=$2 lvl1=$3 case "$name" in *-*) kernlvl0=`echo "$name" | sed -e 's/\(.*\)-.*/\1/'` kernlvl1=`echo "$name" | sed -e 's/.*-\(.*\)/\1/'` ;; gmp) #Alias for auto-gmp kernlvl0="$arch"; kernlvl1=gmp ;; none) #Alias for none-none kernlvl0=none; kernlvl1=none;; *) kernlvl0="$name"; kernlvl1=auto ;; esac if [ "$kernlvl0" = "auto" ]; then kernlvl0="$arch"; fi case "$kernlvl1" in gmp|none) ;; auto) kernlvl1=$lvl1;; *) cat << EOM >& 2 ### ### Level1 kernel = '$kernlvl1' unknown, using 'none' ### EOM kernlvl1=none ;; esac echo "$kernlvl0-$kernlvl1" pari-2.7.5/config/get_ld0000644000175000017500000000337411636712103013543 0ustar billbill# Which Executable Linker ? # _ld_list='LD LDFLAGS LIBS runpathprexix LDneedsWl LDused GNULDused' case "$osname" in darwin) LIBS= ;; osf1) LIBS='-lm -lots';; *) LIBS=-lm;; esac if test -z "$LD"; then LD=$CC; fi if test "$fastread" != yes; then echo $n ..."Which linker for building executables ? $c" dflt=$LD; rep=; . ./myread LD=$ans fi LDused=$LD # Which Flags for Executable Linker? ldflags= GNULDused= if test "$LD" = "$CC"; then ldflags=$CFLAGS if test -n "$__gnuc__"; then LDused=`$CC -print-prog-name=ld` LDneedsWl=yes else if test "$osname" = hpux; then LDneedsWl=yes; fi fi fi if ($LDused -v 2>&1 | grep GNU > /dev/null); then GNULDused=yes; fi tmp= if test "$GNULDused" = "yes"; then case "$osname" in cygwin|mingw) tmp=--enable-auto-import ;; # PE does not support --export-dynamic *) tmp=--export-dynamic ;; esac else case "$osname-$arch" in aix-*) tmp=-brtl ;; # in case we link against a shared library hpux-*) tmp=-E ;; esac fi case "$osname" in darwin) tmp="$tmp -search_paths_first";; esac if test -n "$tmp"; then tmp=`./ldflags "$LDneedsWl" $tmp` ldflags="$ldflags $tmp" fi case "$osname-$arch" in os2-*) ldflags="$ldflags -Zexe" if test "$optimization" = "full"; then ldflags="$ldflags -s"; fi esac LDFLAGS="$ldflags $LDFLAGS" if test "$fastread" != yes; then echo $n ..."With which flags ? $c" dflt=$LDFLAGS; rep=; . ./myread LDFLAGS=$ans fi echo "Executable linker is $LD $LDFLAGS" if test "$GNULDused" = yes; then runpathprefix='-rpath ' else # guess... case "$osname" in gnu|osf1|linux|cygwin*|freebsd|netbsd) runpathprefix='-rpath ' ;; solaris) runpathprefix='-R ' ;; hpux) runpathprefix='+b ' ;; aix) runpathprefix='-blibpath:' ;; esac fi pari-2.7.5/config/get_archos0000644000175000017500000000206311636712103014415 0ustar billbill# Testing Architectures. Try uname to provide a default, then ask user. # if test -z "$target_host"; then target_host=`./arch-osname` fi arch=`echo "$target_host" | sed -e 's/\(.*\)-.*/\1/'` osname=`echo "$target_host" | sed -e 's/.*-\(.*\)/\1/'` if test "$fastread" != yes; then cat << EOM ========================================================================== Currently supported architectures: EOM rep='none sparcv8_super sparcv8_micro sparcv9 ix86 i386 i486 i586 i686 alpha x86_64 arm fx2800 hppa ia64 mips m68k ppc s390' . ./display echo $n ..."Which of these apply, if any ? $c" dflt=$arch; . ./myread; arch=$ans fi # # Test OS, using the info uname provided. # if test "$fastread" != yes; then cat << EOM ========================================================================== I know of the following Operating Systems EOM rep='os2 freebsd netbsd cygwin linux mingw gnu gnukfreebsd hpux aix osf1 solaris sunos nextstep concentrix irix'; . ./display echo $n ..."Any of these apply ? $c" dflt=$osname; . ./myread osname=$ans fi pari-2.7.5/config/get_Qt0000644000175000017500000000202012314242551013512 0ustar billbillif test -z "$with_qt"; then with_qt=yes fi QTDIR= case "$with_qt" in yes) pth="/usr/local/lib /usr/local/share /usr/lib /usr/share" QTDIR=`locatedir qt4/bin $pth` if test -n "$QTDIR"; then QTLIB="-lQtCore -lQtGui" which_graphic_lib=Qt4 else QTDIR=`locatedir qt/bin $pth` if test -n "$QTDIR"; then QTLIB="-lQtCore -lQtGui" which_graphic_lib=Qt4 else QTDIR=`locatedir qt3/bin $pth` if test -n "$QTDIR"; then QTLIB="-lqt-mt" which_graphic_lib=Qt else QTDIR=`locatedir qt2/bin $pth` if test -n "$QTDIR"; then QTLIB="-lqt" which_graphic_lib=Qt fi fi fi fi; if test -n "$QTDIR"; then QTDIR=`dirname $QTDIR` fi;; *) if test ! -d "$with_qt"; then echo "### Qt directory '$with_qt' not found" else QTDIR=$with_qt fi;; esac if test -n "$QTDIR"; then echo "Using Qt library, QTDIR = $QTDIR, QTLIB = $QTLIB" else echo "### Qt not found. Building without Qt support" fi pari-2.7.5/config/get_dlcflags0000644000175000017500000000062611636712103014720 0ustar billbill_dl_list="DLCFLAGS" if test -n "$__gnuc__"; then case $osname in cygwin|mingw) DLCFLAGS=;; darwin) DLCFLAGS=-fPIC case $arch in ppc|ppc64) DLCFLAGS="$DLCFLAGS -fno-common" esac;; *) DLCFLAGS=-fPIC;; esac else #assume native compiler case "$osname" in hpux) DLCFLAGS=+z;; solaris) DLCFLAGS=-KPIC;; esac fi echo "C compiler is $CC $CFLAGS $DLCFLAGS" pari-2.7.5/config/cygwin-postinst0000644000175000017500000000037612314242551015464 0ustar billbillpwd="$(pwd)" echo 'colors = "boldfg"' >> .gprc echo 'help = "'"$pwd"'/perl.exe '"$pwd"'/gphelp -cu 6"' >> .gprc echo 'prettyprinter = "'"$pwd"'/perl.exe tex2mail -TeX -noindent -ragged -by_par"' >> .gprc pwd=${pwd##*/} ./ln -s ../${pwd}/sh.exe ../bin/sh pari-2.7.5/config/has_vsnprintf.c0000644000175000017500000000024212314242551015400 0ustar billbill#include #include int main() { return 0; } int f(int i,...) { char s[1]; va_list ap; va_start(ap,i); vsnprintf(s,1," ",ap); return 0; } pari-2.7.5/config/get_head0000644000175000017500000000013211636712103014032 0ustar billbillif (head -n 1 < /dev/null >/dev/null 2>&1); then head='head -n' else head='head -' fi pari-2.7.5/config/extract_files0000755000175000017500000000110411636712103015131 0ustar billbillflist=`ls $config_dir/*.SH` for file in $flist; do . ./$file done echo "Extracting scripts and macros" for dir in "$doc_dir" "$misc_dir"; do if test -d $dir; then echo "...in $dir" flist=`ls $dir/*.in` for file in $flist; do sed -e "s%@perl@%$perl%g"\ -e "s%@datadir@%$datadir%g"\ -e "s%@bindir@%$bindir%g"\ -e "s%@includedir@%$includedir%g"\ -e "s%@libdir@%$libdir%g"\ -e "s%@version@%$pari_release%g"\ $file > $dir/`basename $file .in` done fi done chmod +x $doc_dir/gphelp $misc_dir/tex2mail pari-2.7.5/config/get_PATH0000644000175000017500000000135711636712103013677 0ustar billbillif test -z "$OS2_SHELL"; then dir_sep=':' ; else dir_sep=';' ; fi # Proper PATH setting pth="\ /bin\ /usr/bin\ /usr/locateal/bin\ /usr/ucb\ /usr/locateal\ /usr/lbin\ /usr/5bin\ /etc\ /usr/etc\ /usr/gnu/bin\ /usr/new\ /usr/new/bin\ /usr/nbin\ /sys5.3/bin\ /sys5.3/usr/bin\ /bsd4.3/bin\ /bsd4.3/usr/ucb\ /bsd4.3/usr/bin\ /usr/bsd\ /bsd43/bin\ /opt/ansic/bin\ /usr/ccs/bin\ /usr/lib\ /usr/ucblib\ /lib\ /usr/ccs/lib\ /sbin\ /usr/sbin\ /usr/libexec\ /usr/openwin/bin\ /usr/local/bin\ " # /usr/openwin/bin added for xmkmf for p in $pth do case "$dir_sep$PATH$dir_sep" in *$dir_sep$p$dir_sep*) ;; *) test -d $p && PATH=$PATH$dir_sep$p ;; esac done PATH=.$dir_sep$PATH; export PATH pari-2.7.5/config/get_mt0000644000175000017500000000133312366172547013572 0ustar billbillfile=$thread_engine.c MT_LIBS= case $thread_engine in single);; pthread) MT_LIBS="-lpthread" cmd="$CC $CFLAGS $extraflag -o $exe $file $MT_LIBS" . log_cmd if test -r $exe; then rm -f $exe $exe$exe_suff enable_tls="yes" else echo "### --mt=pthread requires the library pthread" echo "### Please install it" thread_engine=single; fi;; mpi) cmd="$CC $CFLAGS $extraflag -o $exe $file" . log_cmd if test -r $exe; then rm -f $exe $exe$exe_suff else echo "### --mt=mpi requires to use mpicc" echo "### Please use 'env CC=mpicc ./Configure --mt=mpi'" exit 1; fi;; *) echo "### invalid mt engine $thread_engine" thread_engine=single;; esac echo "Using mt engine $thread_engine" pari-2.7.5/config/myread0000755000175000017500000000075211636712103013566 0ustar billbillif test "$fastread" = yes; then echo "[$dflt]" ans=$dflt else if test -n "$dflt"; then echo $n "[$dflt] $c"; fi while :; do read ans case "$ans" in '') ans="$dflt" break ;; !*) ans=`echo "$ans"|cut -c2-` break ;; *) if test -z "$rep"; then break; fi for i in $rep; do if test "$i" = "$ans"; then break 2; fi done echo $n "*** Please try something else : [$rep] $c" ;; esac done fi pari-2.7.5/config/has_isatty.c0000644000175000017500000000006712314242551014671 0ustar billbill#include int main(){ isatty(0); return 0; } pari-2.7.5/config/pthread.c0000644000175000017500000000055412366172547014167 0ustar billbill#include #include static __thread long counter; void *start_routine(void *pt_val) { long val = *(long *)pt_val; counter = val+1; return NULL; } int main(void) { pthread_t thread; counter = 0; if (pthread_create(&thread, NULL, start_routine, &counter)) exit(1); if (pthread_join(thread, NULL)) exit(1); return 0; } pari-2.7.5/config/setversion0000755000175000017500000000073612314242551014507 0ustar billbill#!/bin/sh # to be run from the Oxxx directory. Called iff $TOP/.git/index exists TOP=.. cfg=$TOP/config f=paricfg.h rm -f $f.old cp $f $f.old . $cfg/get_head . $cfg/version # need $TOP v="GP/PARI CALCULATOR Version ${version}.${patch} (${status})" sed -e "s,define PARIVERSION.*,define PARIVERSION \"$v\",; s,define PARI_VCSVERSION.*,define PARI_VCSVERSION \"${vcsversion}\",; s,define PARI_VERSION_CODE.*,define PARI_VERSION_CODE ${version_code}," $f.old > $f pari-2.7.5/config/get_dlld0000644000175000017500000000746412502252164014066 0ustar billbill# Exported variables _dlld_list='DL_DFLT_NAME DLLD DLLDFLAGS EXTRADLLDFLAGS DLSUFFIX soname sodest DLLTOOL' # Which suffix for Dynamic Lib? # Some linkers (SunOS 4) need minor and major lib version numbers. # Some others (SunOS 5) need a link from a .so # Some others (HPUX 09) do not want version numbers. DLSUFFIX=so soname=.$soname_num do_dll=yes case "$osname" in gnu*|aix|osf1|solaris|linux|freebsd|netbsd) case $pari_release_verbose in *STABLE*) sodest=.$version.$patch;; # released version *DEVELOPMENT*) sodest=.$patch.0.0;; # unstable version esac ;; sunos) sodest=.$VersionMajor$VersionMinor.$patch soname=$sodest;; hpux) soname= ; sodest= ; DLSUFFIX=sl;; irix) soname= ; sodest= ;; os2|cygwin|mingw)soname= ; sodest= ; DLSUFFIX=dll if test "x$DLLTOOL" = x; then DLLTOOL=`locate dlltool`; if test "x$DLLTOOL" = x; then DLLTOOL=`$CC -dumpmachine`-dlltool fi fi;; darwin)soname= ; sodest= ; DLSUFFIX=dylib; compat_ver=$VersionMajor.$VersionMinor.0; num_ver=$VersionMajor.$VersionMinor.$patch;; *) do_dll=no ;; esac # dlopen(NULL) should return a handle to the running process. # On FreeBSD 2.2.5 (Y. Uchikawa) and Cygwin, this does not work. case "$osname" in freebsd|cygwin) DL_DFLT_NAME="\\\"\$(LIBPARI_DYN)\\\"" ;; mingw) DL_DFLT_NAME="\\\"\$(LIBPARI_SO)\\\"" ;; *) DL_DFLT_NAME=NULL ;; esac # if DLLD is defined at this point, respect it, even if do_dll=no if test $do_dll = yes -a -z "$DLLD"; then if test -n "$__gnuc__" -o "$osname" = "solaris"; then DLLD="$CC" else DLLD=$ld # don't take risks fi fi GNUdlld= DLLDisGCC= if test -n "$DLLD"; then # Which Dynamic Lib Linker? if test "$fastread" != yes; then echo $n ..."Which linker for building dynamic libs? $c" dflt="$DLLD"; rep=; . ./myread DLLD=$ans fi if test "$DLLD" = "$CC" -a -n "$__gnuc__"; then DLLDisGCC=yes; GNUdlld=$GNULDused else case "$DLLD" in *ld) if ($DLLD -v 2>&1 | grep GNU > /dev/null); then GNUdlld=yes; fi;; esac fi # Which Flags for Dynamic Lib Linker ? dlldflags="$DLLDFLAGS" DLLDFLAGS= if test -n "$GNUdlld"; then DLLDFLAGS="-shared -soname=\$(LIBPARI_SONAME)" else # DLLD != GNU ld case "$osname" in aix) DLLDFLAGS='-r' ;; darwin) DLLDFLAGS="-compatibility_version $compat_ver -current_version $num_ver" ;; freebsd) DLLDFLAGS='-Bshareable -x' ;; hpux) DLLDFLAGS='-b' ;; irix) DLLDFLAGS='-shared -elf -no_unresolved -all' ;; osf1) DLLDFLAGS='-shared' ;; solaris) DLLDFLAGS="-G -h \$(LIBPARI_SONAME)" ;; sunos) DLLDFLAGS='-assert nodefinitions' ;; os2) ;; # see below linux) ;; # for e.g. the Portland Group cc (pgcc) *) DLLD=;; esac fi if test -n "$DLLDFLAGS"; then DLLDFLAGS=`./ldflags "$DLLDisGCC" $DLLDFLAGS` fi case "$osname" in os2) DLLDFLAGS="$CFLAGS -Zdll" ;; # assume DLLD = gcc cygwin) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A),--export-all-symbols";; mingw) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A)";; esac if test -n "$DLLDisGCC"; then case "$arch-$osname" in sparc-solaris) extra='-mimpure-text';; *) extra=;; esac case "$osname" in darwin) shared=-dynamiclib;; *) shared=-shared;; esac DLLDFLAGS="$shared $extra \$(CFLAGS) \$(DLCFLAGS) $DLLDFLAGS" fi case "$osname" in # Beware: will run through 'eval' [ hence ${...} instead of \$(...) ] gnu*|cygwin|osf1|freebsd|linux|sunos|solaris) EXTRADLLDFLAGS='-lc ${LIBS}';; esac if test "$fastread" != yes; then echo $n ..."Which flags for linker? $c" dflt=$DLLDFLAGS; rep=; . ./myread DLLDFLAGS=$ans fi DLLDFLAGS="$DLLDFLAGS $dlldflags" fi if test -z "$DLLD"; then echo "No Dynamic Lib" else echo "Dynamic Lib linker is $DLLD $DLLDFLAGS" fi pari-2.7.5/config/DOC_Make.SH0000644000175000017500000001077012366172547014173 0ustar billbill# Path to directories cfg=../$config_dir data=../$data_dir doc=../$doc_dir desc=../$desc_dir ex=../$examples_dir misc=../$misc_dir src=../$src_dir cat > doc/Makefile << EOT # This file was created by Configure. Any change made to it will be lost # next time configure is run. # SHELL = $make_sh PERL = $perl TEX = tex PDFTEX= pdftex DESC = pari.desc MACROS= paricfg.tex parimacro.tex USERS_TEX=\$(MACROS) appa.tex users.tex usersch1.tex usersch2.tex usersch3.tex PARI_TEX=\$(MACROS) libpari.tex appb.tex appd.tex usersch4.tex usersch5.tex usersch6.tex usersch7.tex doc all: develop.dvi libpari.dvi parallel.dvi users.dvi refcard.ps tutorial.dvi docps: develop.ps libpari.ps parallel.ps refcard.ps tutorial.ps users.ps INSTALL.ps docpdf: develop.pdf libpari.pdf parallel.pdf users.pdf tutorial.pdf refcard.pdf INSTALL.pdf .SUFFIXES: .tex .ipf .pod .inf .dumbpod .3 .html paricfg.tex: paricfg.tex.in sed -e 's/@version@/$version.$patch/'\\ -e 's!@includedir@!$includedir!'\\ -e 's!@libdir@!$libdir!'\\ -e 's!@datadir@!$datadir!' paricfg.tex.in > \$@ %.pdf: %.tex \$(MACROS) \$(PDFTEX) \$< %.dvi: %.tex \$(MACROS) \$(TEX) \$< libpari.pdf: \$(PARI_TEX) \$(MACROS) -rm -f libpari.std \$(PDFTEX) libpari \$(PDFTEX) libpari make libpari.std; \$(PDFTEX) libpari; rm -f libpari.std libpari.dvi: \$(PARI_TEX) \$(MACROS) -rm -f libpari.std \$(TEX) libpari \$(TEX) libpari make libpari.std; \$(TEX) libpari; rm -f libpari.std develop.pdf: develop.tex \$(MACROS) -rm -f develop.std \$(PDFTEX) develop \$(PDFTEX) develop make develop.std; \$(PDFTEX) develop; rm -f develop.std develop.dvi: develop.tex \$(MACROS) -rm -f develop.std \$(TEX) develop \$(TEX) develop make develop.std; \$(TEX) develop; rm -f develop.std parallel.pdf: parallel.tex \$(MACROS) -rm -f parallel.std \$(PDFTEX) parallel \$(PDFTEX) parallel make parallel.std; \$(PDFTEX) parallel; rm -f parallel.std parallel.dvi: parallel.tex \$(MACROS) -rm -f parallel.std \$(TEX) parallel \$(TEX) parallel make parallel.std; \$(TEX) parallel; rm -f parallel.std tutorial.pdf: tutorial.tex \$(MACROS) -rm -f tutorial.std \$(PDFTEX) tutorial \$(PDFTEX) tutorial tutorial.dvi: tutorial.tex \$(MACROS) -rm -f tutorial.std \$(TEX) tutorial \$(TEX) tutorial %.ps: %.dvi dvips \$< -o \$@ refcard.ps: refcard.dvi dvips refcard.dvi -o \$@ %.std: %.idx sed -e 's/!\([1-9]\)!/!00\1!/'\\ -e 's/!\([1-9][0-9]\)!/!0\1!/'\\ -e 's/\\\\EFF {}/f/g'\\ \$< | env LANG=C sort -f |\\ sed -e 's/!00*\([0-9]*\)!/!\1!/' > \$@; users.dvi: \$(USERS_TEX) -rm -f users.std \$(TEX) users \$(TEX) users make users.std; \$(TEX) users; rm -f users.std users.pdf: \$(USERS_TEX) -rm -f users.std \$(PDFTEX) users \$(PDFTEX) users make users.std; \$(PDFTEX) users; rm -f users.std gpman: gp.1 nroff -man gp.1 | unix2dos -ascii > gp.man clean: rm -f *.log *.dvi *.idx *.ps *.pdf *.aux *.toc *.std *.dumbpod *.3 *.tmp *.html cleandoc: clean veryclean: clean rm -f paricfg.tex gp.man .tex.pod: \$(PERL) gphelp -to_pod \$*.tex > tmp_pod && mv tmp_pod \$*.pod .tex.dumbpod: \$(PERL) gphelp -to_dumb_pod \$*.tex > tmp_pod && mv tmp_pod \$*.dumbpod .ipf.inf: ipfc /INF \$*.ipf # This is for testing: .pod.ipf: pod2ipf \$*.pod > tmp_ipf && mv tmp_ipf \$*.ipf pari.ipf: refcard.pod tutorial.pod usersch1.pod usersch1.pod usersch2.pod usersch3.pod appa.pod pod2ipf --title="PARI/GP Manual" --by-files --section-name="Getting started" --file=refcard.pod --file=tutorial.pod --section-name="User guide" --file=usersch1.pod --file=usersch2.pod --file=usersch3.pod --section-name=Appendices --file=appa.pod > tmp_ipf && mv tmp_ipf pari.ipf dumbpod: appa.dumbpod usersch1.dumbpod usersch2.dumbpod usersch3.dumbpod .dumbpod.html: pod2html --title="PARI/GP Manual, part \$*" --infile=\$*.dumbpod --outfile=tmp_html && mv tmp_html \$*.html manpages: dumbpod appa.3 usersch1.3 usersch2.3 usersch3.3 html: dumbpod appa.html appb.html appd.html usersch1.html usersch2.html usersch3.html usersch4.html usersch5.html usersch6.html usersch7.html .dumbpod.3: pod2man --section=3 --center="PARI/GP Manual, part \$*" --release=$version.$patch --lax \$*.dumbpod > tmp_man && mv tmp_man \$*.3 EOT if test -n "$add_funclist"; then cat >> doc/Makefile << EOT $src/funclist:: @-$cfg/genfunclist $desc $desc/\$(DESC): $src/funclist $desc/merge_822 $desc/PARI/822.pm cd $desc && \$(PERL) merge_822 ../funclist > def\$(TMPSUF) mv $desc/def\$(TMPSUF) \$@ usersch3.tex: $desc/\$(DESC) ../src/desc/doc_make usersFUNCS.tex cd ../src/desc && \$(PERL) doc_make > ../../doc/usersch3.tex EOT fi pari-2.7.5/config/has_strftime.c0000644000175000017500000000012512314242551015204 0ustar billbill#include int main(){ struct tm *x = NULL; strftime("",1," ",x); return 0; } pari-2.7.5/config/gprc.mingw0000644000175000017500000000023712314242551014352 0ustar billbilllines = 25 colors = "brightfg" prompt = "(%H:%M) gp > " histfile = "gp_history.txt" breakloop = 0 help = "@ perl\\perl gphelp.pl -detex -ch 10 -cb 11 -cu 12" pari-2.7.5/config/ldflags0000755000175000017500000000017511636712103013720 0ustar billbill#! /bin/sh t=$1; shift if test -n "$t"; then L=-Wl for c in "$@"; do L=$L,"$c" done; echo $L else echo "$@" fi pari-2.7.5/config/get_pretty0000644000175000017500000000064011636712103014464 0ustar billbillpretty="$prettya running $osname" case "$kernlvl1" in gmp) if test -n "$gmp_version"; then prettyk="$prettyk0/GMP-${gmp_version}" else prettyk="$prettyk0/GMP" fi;; none) prettyk="$prettyk0";; *) prettyk="$prettyk0/$kernlvl1";; esac case "$sizeof_long" in 4) pretty="$pretty ($prettyk kernel) 32-bit version";; 8) pretty="$pretty ($prettyk kernel) 64-bit version";; esac; pari-2.7.5/config/has_dlopen.c0000644000175000017500000000012412314242551014627 0ustar billbill#include #include int main() {dlopen("a",RTLD_LAZY); return 0;} pari-2.7.5/config/get_modld0000644000175000017500000000161412502252164014235 0ustar billbill# Exported variables _modld_list='EXTRAMODLDFLAGS MODLD MODLDFLAGS modules_build' # EXTRADLLDFLAGS might refer to $LIBS __LIBS=$LIBS if test "$static" = n; then LIBS="$LIBS -L$libdir $LDDYN"; fi case $osname in cygwin|mingw) EXTRAMODLDFLAGS="-L$libdir $LDDYN -Wl,--enable-auto-import";; *) EXTRAMODLDFLAGS=`eval echo $EXTRADLLDFLAGS`;; esac; LIBS=$__LIBS case $osname in darwin) MODLD=$CC; MODLDFLAGS="-bundle -undefined dynamic_lookup \ \$(CFLAGS) \$(DLCFLAGS)";; *) MODLD="$DLLD"; MODLDFLAGS=`echo "$DLLDFLAGS" | \ sed -e 's/,*-[^ \t-]*[ \t,=]*\\$(LIBPARI_SONAME)//' \ -e 's/-Wl,--out-implib=\$(LIBPARI_SO)\$(_A)//'`;; esac; modules_build=`echo "$CC -c -o %s.o $CFLAGS $DLCFLAGS -I\"$includedir\" %s.c \ && $MODLD -o %s.so $MODLDFLAGS %s.o $EXTRAMODLDFLAGS" | \ sed -e 's!\$(CFLAGS)'"!$CFLAGS!g" \ -e 's!\$(DLCFLAGS)'"!$DLCFLAGS!g"` pari-2.7.5/config/has_X11.c0000644000175000017500000000016412314242551013723 0ustar billbill#include #include #include int main(){ (void)XOpenDisplay(NULL); return 0; } pari-2.7.5/config/get_graphic_lib0000644000175000017500000000402612314242551015401 0ustar billbillif test "$optimization" = profiling; then which_graphic_lib=none fi _graphic_list="which_graphic_lib X11 X11_INC X11_LIBS \ FLTKDIR FLTK_LIBS QTDIR QTLIB" if test -n "$with_fltk"; then which_graphic_lib=fltk; fi if test -n "$with_qt"; then which_graphic_lib=Qt; fi if test "$fastread" != yes; then cat << EOT ========================================================================== GP contains high resolution plotting functions. Choose among none X11 fltk Qt win32 ps EOT echo $n ..."Use which graphic library (\"none\" means no hi-res plot) ? $c" rep="none X11 fltk Qt win32 ps"; dflt=$which_graphic_lib; . ./myread which_graphic_lib=$ans fi case $osname in mingw|cygwin) case $which_graphic_lib in auto) which_graphic_lib=win32;; esac;; esac case $which_graphic_lib in auto|X11|x11) . ./get_X11 # X11,X11_INC,X11_LIBS. if test -z "$X11_LIBS"; then case $which_graphic_lib in X11|x11) which_graphic_lib=none;; esac else which_graphic_lib=X11 fi;; esac case $which_graphic_lib in auto|fltk) case $osname in darwin) ;; # fltk brings in CoreFoundation, incompatible with pari_daemon *). ./get_fltk # FLTKDIR, FLTK_LIBS ;; if test -z "$FLTKDIR"; then case $which_graphic_lib in fltk) which_graphic_lib=none;; esac else which_graphic_lib=fltk fi;; esac;; esac # TODO: Check whether Qt + pari_daemon() work on darwin [ probably not ] case $which_graphic_lib in auto|Qt|qt) . ./get_Qt # QTDIR, QTLIB if test -z "$QTDIR"; then case $which_graphic_lib in qt|Qt) which_graphic_lib=none;; esac # Never automatically pick Qt fi;; esac case $which_graphic_lib in auto|PS|ps) which_graphic_lib=ps;; esac case $which_graphic_lib in X11|fltk|Qt|Qt4|ps) if test "$has_waitpid" = no -o "$has_setsid" = no; then echo "### Missing waitpid() or setsid(), no Hi-Res graphing window" which_graphic_lib=none fi;; esac echo "Hi-Res Graphics: $which_graphic_lib" pari-2.7.5/config/Imakefile0000644000175000017500000000016311636712103014164 0ustar billbillgp-X11: @echo 'Xincroot="${INCROOT}"; usrlibdir="${USRLIBDIR}"; libdir="${LIBDIR}";extralib="${EXTRA_LIBRARIES}"' pari-2.7.5/config/mpi.c0000644000175000017500000000040012366172547013313 0ustar billbill#include #include int main() { int pari_MPI_size, pari_MPI_rank; int res = MPI_Init(0, NULL); if (res == MPI_SUCCESS) { MPI_Comm_size(MPI_COMM_WORLD, &pari_MPI_size); MPI_Comm_rank(MPI_COMM_WORLD, &pari_MPI_rank); } } pari-2.7.5/config/make_tags0000755000175000017500000000407512314242551014241 0ustar billbilleval 'exec perl "$0" "$1" "$2"' if $running_under_some_shell; use File::Find 'find'; # Build a (sorted) EMACS / VI(M) tags file including GP functions # $emacs_mode = ($ARGV[0] eq "--emacs"); $src = $ARGV[1]; if ($emacs_mode) { $tags = "$src/TAGS"; } else # Case sensitive? { $tags = $^O eq 'os2' ? "$src/ctags" : "$src/tags"; } $tmptags = "$tags.tmp"; my (%gp); getnames("$src/gp/gp_init.h"); getnames("$src/language/init.h"); my (@files) = (); find \&filter_c, $src; @tags = ""; if ($emacs_mode) { system('exuberant-ctags', '-e', '-f', $tmptags, @files) && system('ctags-exuberant', '-e', '-f', $tmptags, @files) && system('etags', '-f', $tmptags, @files) && die("etags failed"); open(T,"$tmptags"); while() { my ($a,$b); $a = $_; if (/^(\w+)\(/ && ($b = $gp{$1}) && $b ne $1) { $a =~ s/\x7F.*\x01/\x7F$b\x01/; push(@tags,$a); } push(@tags,$_); } } else { system('exuberant-ctags', '-f', $tmptags, @files) && system('ctags-exuberant', '-f', $tmptags, @files) && system('ctags', '-dT', '-o', $tmptags, @files) # gctags && system('ctags', '-f', $tmptags, @files) && die("ctags failed"); open(T,"$tmptags"); # Assume ctags outputs sorted tags (e.g Exuberant Ctags) my ($old) = ""; for (sort(keys %gp)) { my ($a) = $_; my ($b) = $gp{$a}; if ($a eq $old) { push(@tags,"$b$rest\n"); next; } $old = $a; while() { push(@tags,$_); if (/^$a(.*)/) { $rest="$1"; push(@tags,"$b$rest\n"); last; } } } while() { push(@tags,$_); } @tags = sort(@tags); } close(T); open(OUT,">$tags"); print OUT @tags; unlink $tmptags; # $gp{GP_function} = C_function sub getnames { open(A,$_[0]); while () { if (/^entree functions_/../^$/) { if (/[^"]*"([^"]*)".*\(void\*\) *([^,]*)/) { my ($gpfun, $cfun) = ($1,$2); $gpfun =~ s/_\.//g; # member functions $gp{$cfun} = $gpfun; } } } close(A); } sub filter_c { return unless /\.[chy]\Z/ && -f; return if (/(dummy|tune|kerntest|parse)\.c/); push @files, "$File::Find::name"; } pari-2.7.5/config/checkspaces0000755000175000017500000000126112314242551014554 0ustar billbill#! /bin/sh srcbase="`echo src/*/*.[chy] | sed -e 's,src/language/parse\.[ch],,g'`" CFILES="$srcbase src/*/*/*.[ch] examples/*.c examples/*.gp" docbase="`echo doc/*.tex | sed -e 's,doc/usersch3.tex,,'`" OFILES="$docbase AUTHORS COMPAT NEW TODO CHANGES MACHINES src/test/in/* src/functions/*/*" SCRIPTS="config/* src/test/dotest" ALLFILES="$CFILES $OFILES $SCRIPTS" err=0; if grep -P '[\x80-\xff]' $ALLFILES; then echo "BUG: high bit found." err=1; fi if grep ' $' $ALLFILES; then echo "BUG: trailing spaces found." err=1; fi if grep ' ' $CFILES $OFILES; then echo "BUG: TAB found." err=1; fi if grep ' $' $SCRIPTS; then echo "BUG: TAB found in scripts." err=1; fi exit $err pari-2.7.5/config/has_exp2.c0000644000175000017500000000011611636712103014226 0ustar billbill#include double (*f)(double) = exp2; int main(){ return f != exp2; } pari-2.7.5/config/genkernel0000755000175000017500000000053312405547147014265 0ustar billbill#! /bin/sh K=../src/kernel knone=$K/none for file in "$@"; do echo "#ifndef ASMINLINE" for i in `grep '^ASM' $file`; do case $i in ASM);; *) cat $knone/$i.h;; esac; done echo "#endif" cat $file for i in `grep '^NOASM' $file`; do case $i in NOASM);; *) cat $knone/$i.h;; esac; done done exit 0 pari-2.7.5/config/TOP_Make.SH0000644000175000017500000001046212366172547014226 0ustar billbillfile=Makefile echo "Extracting $file" rm -f $file dosversion=`echo $version|sed -e 's/\.//g'` dosversion="_$dosversion$patch" __status__=$status case "$status" in development*) __status__='snapshot';; esac cat > $file << EOT # This file was created by Configure. All changes made will be lost # next time Configure is run. # SHELL = $make_sh VERS = pari-$version.$patch $__status__ TAG=release-$VersionMajor-$VersionMinor-$patch dft target:: @echo "Main targets: we suggest 'make all', then 'make install' as root" @echo " all Compilation + Documentation" @echo " gp Compilation" @echo " bench Compilation + Quick test" @echo " dobench Quick test only" @echo " doc Documentation only" @echo " install Installation" @echo " clean, cleantest Clean up" @echo "For pari maintainers:" @echo " dbg Compile gp binary suitable for debugging" @echo " prf Compile gp binary suitable for profiling" @echo " gcov Compile gp binary for test coverage reporting" @echo " alpha, beta, release Tarfile for official source distribution" @echo " snapshot, distrib Tarfile for source snapshot" @echo " nsis Create a NSIS installer for win32" @echo " ctags Generate VI/VIM tags file in ./src" @echo " etags Generate Emacs tags file in ./src" @echo " tune Generate tuning utility" @echo " test-all Thorough regression tests (slow)" all:: @\$(MAKE) gp @-cd doc && \$(MAKE) doc gp bench test-kernel test-all install cleanall cleanobj cleantest nsis install-bin install-doc install-docpdf install-nodata install-data install-lib-sta install-bin-sta dobench dyntest-all statest-all tune $top_test_extra $top_dotest_extra:: @dir=\`config/objdir\`; echo "Making \$@ in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) \$@ dbg gp.dbg:: @dir=\`config/objdir\`.dbg; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -g first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp prf gp.prf:: @dir=\`config/objdir\`.prf; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -pg first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp gcov gp.gcov:: @dir=\`config/objdir\`.gcov; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -gcov first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp doc docps docpdf gpman cleandoc:: cd doc && \$(MAKE) \$@ clean:: cleandoc cleanall clean.dbg:: @dir=\`config/objdir\`.dbg; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean clean.prf:: @dir=\`config/objdir\`.prf; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean clean.gcov:: @dir=\`config/objdir\`.gcov; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean bench.dbg:: @dir=\`config/objdir\`.dbg; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -g first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench bench.prf:: @dir=\`config/objdir\`.prf; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -pg first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench bench.gcov:: @dir=\`config/objdir\`.gcov; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -gcov first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench distrib: $config_dir/settar \$(VERS) $__status__ alpha: $config_dir/settar \$(VERS) alpha beta: $config_dir/settar \$(VERS) beta release: $config_dir/settar \$(VERS) released snapshot: $config_dir/settar \$(VERS) snapshot dosdistrib: gpman -zip -kr GPB${dosversion}.ZIP GP.EXE README README.DOS ../EMX/README.DOC ../RSX/README.TXT -zip -k GPD${dosversion}.ZIP doc/*.tex doc/gphelp doc/gp.man examples misc/gprc* misc/gpalias etags: config/make_tags --emacs "$TOP/src" ctags: config/make_tags --vi "$TOP/src" checkspaces: config/checkspaces EOT pari-2.7.5/config/get_perl0000644000175000017500000000051511636712103014100 0ustar billbill# set variables depending on perl's version _perl_list="add_funclist" add_funclist= if test -n "$perl"; then res=`$perl -e 'print "OK" if ($] >= 5.005);'`; if test $? != 0; then echo "###" echo "### $perl seems to be broken" echo "###" perl= fi if test "$res" = OK; then add_funclist=../src/funclist; fi fi pari-2.7.5/config/locate0000755000175000017500000000032211636712103013545 0ustar billbill#!/bin/sh t=$1; shift; dflt=$1; shift for dir in $*; do file=$dir/$t if test -f $file; then echo $file; exit 0 fi if test -f $file.exe; then echo $file.exe; exit 0 fi done echo $dflt; exit 1 pari-2.7.5/config/get_objdir0000644000175000017500000000163312366172547014426 0ustar billbill# Target directory for object files pre=O objdir=$pre$osname-$arch; if test -n "$dfltobjdir"; then if test "$dfltobjdir" = auto; then case "$kernlvl0" in $asmarch);; sparcv8_micro) if test "$arch" != sparcv9; then objdir=$objdir-$kernlvl0; fi ;; *) objdir=$objdir-$kernlvl0 ;; esac if test -n "$with_gmp"; then objdir=$objdir-gmp; fi dfltobjdir= else objdir="$dfltobjdir" fi fi if test -z "$dfltobjdir"; then case "$optimization" in full) objdir=$objdir;; debugging) objdir=$objdir.dbg ;; profiling) objdir=$objdir.prf ;; gcov) objdir=$objdir.gcov ;; esac fi if test "$fastread" != yes; then cat << EOT ========================================================================== This is the name of the directory where all the object files will be: EOT echo $n ..."Enter dir name : $c" dflt=$objdir; rep=; . ./myread objdir=$ans fi pari-2.7.5/config/convertllp640000755000175000017500000000315312533333715014652 0ustar billbill#!/bin/sh # This script is intended to be run from the pari directory. It will make the following # changes to all source code in preparation for making on mingw64: # 1.) Convert 32 bit constants to 64 bit constants (i.e. L->LL and UL->ULL), # 2.) Convert formatting in printf/sprintf/fprintf (i.e. %ld->%lld, %lu->%llu, etc). test -d config || cd .. test -d config || exit 1 fileList="`find src -name "*.[ch]"`" for file in $fileList; do echo converting file: $file # Add LL to the end of any constant with 10 or more numbers sed 's/\([-+({ ][0-9]\{10,\}\)\([,;:)} ]\)/\1LL\2/g' < $file > TMP # Convert all decimal constants ending in L or UL. # Note: replacing strings with lower case l breaks a couple things, namely strings like "%+1ld" sed -e 's/\([-+* ,()=~&|%][0-9][0-9]*\)[L]\{1,2\}/\1LL/g' -e 's/\([-+* ,()=~&|%][0-9][0-9]*\)[uU][lL]\{1,2\}/\1ULL/g' < TMP > TMP2 # Convert all hexadecimal constants ending in L or UL. sed -e 's/\(0x[0-9a-fA-F][0-9a-fA-F]*\)[lL]\{1,2\}/\1LL/g' -e 's/\(0x[0-9a-fA-F][0-9a-fA-F]*\)[uU][lL]\{1,2\}/\1ULL/g' < TMP2 > TMP # String formatting conversions: %ld -> %lld, %lu -> %llu, %lx -> %llx. This will also handle cases like %+2ld and %0*lx # Replace formatting with microsoft ll convention, but only inside regular printfs (and it's variants) # Do nothing inside of pari_printf() or pari_sprintf(). sed -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)ld/\1lld/g' -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)lu/\1llu/g' -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)lx/\1llx/g' -e '/\"/ s/\(%[0-9]\*\)lx/\1llx/g' < TMP > $file # clean up rm TMP TMP2 done echo "Done." pari-2.7.5/config/get_fltk0000644000175000017500000000104412314242551014073 0ustar billbillif test -z "$with_fltk"; then with_fltk=yes fi FLTKDIR= case "$with_fltk" in yes) pth=$libpth; lib=fltk; . ./locatelib if test -n "$fltk"; then FLTKDIR=`dirname $fltk | sed -e 's/lib\/$//'` fi ;; *) if test ! -d "$with_fltk"; then echo "### FLTK directory '$with_fltk' not found" else FLTKDIR=$with_fltk fi;; esac if test -n "$FLTKDIR"; then echo "Using FLTK library, FLTKDIR = $FLTKDIR" FLTK_LIBS="`fltk-config --ldflags` -lstdc++" else echo "### FLTK not found. Building without FLTK support" FLTK_LIBS= fi pari-2.7.5/config/pari.nsi.SH0000644000175000017500000000023212314242551014326 0ustar billbillcfg=$config_dir obj=$objdir file="$obj/pari.nsi" if [ -f "$cfg/$osname-pari.nsi" ]; then echo "Extracting $file" "$cfg/$osname-pari.nsi" > "$file" fi pari-2.7.5/config/GEN_Make.SH0000644000175000017500000000421611636712103014160 0ustar billbilldir=examples name=Makefile.$osname-$arch file=$dir/$name lnfile=Makefile echo Extracting $file rm -f $file $dir/$lnfile if test -z "$DLLD"; then static=y; fi case "$static" in n) dft=dyn ;; y) dft=sta ;; esac RUNPTH= if test -n "$runpathprefix"; then RUNPTH=`config/ldflags "$LDneedsWl" "$runpathprefix $runpath"` fi cat > $file << EOT # Generic Makefile for PARI programs -- $pretty # # This file was created by Configure. Any change made to it will be # lost when Configure is run. # # make all will create # extgcd-dyn (linked dynamically with libpari) # extgcd-sta (linked statically) # libextgcd.so (to be used by "install" under GP) # # Under GP: install("extgcd", "GG&&", "gcdex", "./libextgcd.so") enables # you to subsequently use gcdex to call extgcd (see the reference manual). # # change this TARGET to compile your own programs TARGET = extgcd SHELL = $make_sh DBGFLAGS = $DBGFLAGS CFLAGS = $OPTFLAGS EXTRACFLAGS= #CFLAGS = \$(DBGFLAGS) # Various linkers use different flags to force static compilation. Choose # the one which is relevant for your installation. # # Solaris ld (global) #STATIC = -dn # Solaris ld (toggle: no shared object accepted until -B dynamic is seen #STATIC = -B static # gcc #STATIC = -static CC = $CC CPPFLAGS = -I. -I$includedir LD = $LD LDFLAGS = $LDFLAGS MODLD = $MODLD MODLDFLAGS = $MODLDFLAGS EXTRAMODLDFLAGS = $EXTRAMODLDFLAGS EXTRALIBS = RUNPTH = $RUNPTH DLCFLAGS = $DLCFLAGS LIBS = $LIBS -L$libdir -lpari RM = rm -f OBJS = \$(TARGET).o DYN = lib\$(TARGET).$DLSUFFIX ALL = \$(TARGET)-sta \$(TARGET)-dyn \$(DYN) dft: \$(TARGET)-$dft all: \$(ALL) sta: \$(TARGET)-sta dyn: \$(TARGET)-dyn dynlib: \$(DYN) \$(DYN): \$(OBJS) \$(MODLD) -o \$@ \$(MODLDFLAGS) \$(EXTRACFLAGS) \$(OBJS) \$(EXTRAMODLDFLAGS) \$(TARGET)-sta: \$(OBJS) \$(LD) -o \$@ \$(LDFLAGS) \$(EXTRACFLAGS) \$< \$(EXTRALIBS) \$(STATIC) \$(LIBS) \$(TARGET)-dyn: \$(OBJS) \$(LD) -o \$@ \$(LDFLAGS) \$(EXTRACFLAGS) \$< \$(EXTRALIBS) \$(RUNPTH) \$(LIBS) %.o: %.c \$(CC) -c \$(CFLAGS) \$(EXTRACFLAGS) \$(CPPFLAGS) \$(DLCFLAGS) \$< clean: -\$(RM) *.o \$(ALL) EOT ( cd $dir ; $ln_s $name $lnfile ) pari-2.7.5/config/has_opendir.c0000644000175000017500000000011511636712103015007 0ustar billbill#include #include main() { DIR *d = opendir("."); } pari-2.7.5/config/has_TIOCGWINSZ.c0000644000175000017500000000032012366172547015062 0ustar billbill#include #include #ifdef __sun # include #endif #include int main() { struct winsize s; int status = ioctl(0, TIOCGWINSZ, &s); return s.ws_col; } pari-2.7.5/config/install0000755000175000017500000000060011636712103013743 0ustar billbill#! /bin/sh mode=755 while test $# -gt 0; do case "$1" in -c);; -m) shift; mode="$1";; *) break;; esac shift done if test -d "$2"; then file="$2/`basename "$1"`" else file="$2" fi if test -d "$1"; then mkdir -p "$file" for f in `ls "$1"`; do "$0" -m "$mode" "$1/$f" "$file" done else cp "$1" "$2"; if test -f "$file"; then chmod "$mode" "$file"; fi fi pari-2.7.5/config/get_readline0000644000175000017500000000554712366172547014750 0ustar billbill#exported variables _readline_list="readline readline_version RLINCLUDE RLLIBS" readline= 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" x=`./locate 'readline/readline.h' '' $pth` case $x in ?:/*|/*) rl_include=`dirname $x` echo ..."Found readline header in $rl_include" if (echo $rl_include | grep "readline$" > /dev/null); then rl_include=`dirname $rl_include` RLINCLUDE="-I$rl_include" fi ;; *) echo ..."readline header file not found by Configure, trying to proceed" readline=;; esac exe=$osname-$arch-rlv$$ if test -n "$readline"; then RLLIBS="-L$readline -lreadline" else RLLIBS="-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" 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" else RLLIBS="$rllibs -ltermcap" fi cmd="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c $RLLIBS" . log_cmd fi readline_version= if test -r $exe; then readline_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$readline" $RUNTEST $exe`; fi rm -f $exe $exe$exe_suff; case "$readline_version" in *Editline*|*EditLine*) readline= echo "###" echo "### Editline wrapper detected, building without readline support" echo "###";; "") readline= echo "###" echo "### Readline library does not seem to work. Maybe install libncurses?" echo "###";; *) if test -z "$readline"; then readline=yes; fi;; esac if test -n "$readline"; then if test "$fastread" != yes; then cat << EOM ========================================================================== GNU readline provides line editing in the gp shell, with history and context-dependent completions. You should really answer 'yes' to the following question, unless you are trying to overcome a problem in the default build. EOM echo $n "Do you want to use GNU readline library within GP ? $c" rep='y n'; dflt=y; . ./myread case $ans in n) readline=;; esac fi fi if test -z "$readline"; then echo "### Building without GNU readline support" RLLIBS= RLINCLUDE= else echo "Using GNU readline, version $readline_version" fi pari-2.7.5/config/get_double_format0000644000175000017500000000310712366172547015775 0ustar billbillexe=$osname-$arch-endian$$ cmd="$CC $CFLAGS $extraflag endian.c -o $exe"; . log_cmd if test -r $exe; then doubleformat=`$RUNTEST $exe`; else echo "***************************************************************" echo "Cannot compile endian.c. Aborting. PLEASE REPORT!" exit 1 fi rm -f $exe $exe$exe_suff case "$doubleformat" in *IEEE*) echo "***************************************************************" echo "Your 'double' type does not follow the IEEE754 format. Aborting" echo "PLEASE REPORT! (dbltor/rtodbl need to be fixed)"; exit 1;; -) sizeof_long=8;; *) sizeof_long=4;; esac echo "Given the previous choices, sizeof(long) is $sizeof_long chars." if test "$fastread" != yes; then cat << EOT If your hardware supports different size of longs (e.g SGI/MIPS), and you want to use a different word size than the above. You should probably have specified some exotic compilation flag CFLAG (e.g -o32,-n32). EOT if test $doubleformat != "-"; then cat << EOT For 32-bit architecture, PARI needs to know the format of your 'double' type. PARI assumes doubles are stored in IEEE754 format [ (sign, exponent, mantissa high) on one word, (mantissa low) on another ]; assuming a union { double d; ulong l[2]; } x; are the double exponent and sign stored on x.i[0] (0) or on x.i[1] (1) ? Using \$CC \$CFLAGS with CC =$CC CFLAGS=$CFLAGS the answer is: $doubleformat. EOT fi fi case $doubleformat in 0) _format='l[0], l[1]';; 1) _format='l[1], l[0]';; -) _format='not needed (64bit)';; esac cat < $v rm -f $v.old fi tar cf $tarfile $dir rm -rf $dir rm -f $tarfile.gz gzip $tarfile pari-2.7.5/config/get_X110000644000175000017500000000273212314242551013511 0ustar billbilltdir=$osname-$arch-X11$$ mkdir $tdir; cp Imakefile $tdir; cd $tdir cmd="xmkmf"; . ../log_cmd if test -f Makefile; then eval `make gp-X11 >&5 2>&1 | grep -v make` x11pth="$usrlibdir $libdir"; fi cd ..; rm -rf $tdir # Check xmkmf answer # X11 -- Headers if test ! -f $Xincroot/X11/Xos.h; then x11pth="$addlib64\ /usr/openwin/share/lib\ /usr/openwin/lib\ /usr/X11R6/lib /usr/X11R5/lib /usr/X11R4/lib\ /usr/lib/X11R6 /usr/lib/X11R5 /usr/lib/X11R4\ /usr/local/X11R6/lib /usr/local/X11R5/lib /usr/local/X11R4/lib\ /usr/local/lib/X11R6 /usr/local/lib/X11R5 /usr/local/lib/X11R4\ /usr/X11/lib\ /usr/lib/X11\ /usr/local/X11/lib\ /usr/local/lib/X11\ /usr/XFree86/lib/X11\ /usr/lib\ /usr/local/lib\ /usr/athena/lib\ "; pth=`echo $x11pth | sed 's,/lib,/include,g'` x=`./locate X11/Xos.h '' $pth` case $x in /*) Xincroot=`echo $x | sed 's,/X11/Xos.h,,'`;; *) Xincroot=;; esac fi if test -f $Xincroot/X11/Xos.h; then echo ..."Found X11 header files in $Xincroot/X11" 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= fi fi rm -f $exe $exe$exe_suff; echo ..."X11 libraries: $X11_LIBS" pari-2.7.5/config/locatedir0000755000175000017500000000017211636712103014247 0ustar billbill#!/bin/sh t=$1; shift; for dir in $*; do file=$dir/$t if test -d $file; then echo $file; exit 0 fi done exit 1 pari-2.7.5/config/gmp_version.c0000644000175000017500000000035712533333715015061 0ustar billbill#include #include void f(void) { mpn_gcdext(NULL,NULL, NULL, NULL, 0, NULL, 0); } int main() { if (sizeof(mp_limb_t) == sizeof(long *)) printf("%s\n", gmp_version); else printf("unsupported\n"); return 0; } pari-2.7.5/config/has_log2.c0000644000175000017500000000011611636712103014213 0ustar billbill#include double (*f)(double) = log2; int main(){ return f != log2; } pari-2.7.5/config/objdir0000755000175000017500000000026611636712103013556 0ustar billbill#! /bin/sh tmp_host=`config/arch-osname` arch=`echo "$tmp_host" | sed -e 's/\(.*\)-.*/\1/'` osname=`echo "$tmp_host" | sed -e 's/.*-\(.*\)/\1/'` objdir=O$osname-$arch; echo $objdir pari-2.7.5/config/endian.c0000644000175000017500000000100712533333715013760 0ustar billbill#include #ifdef _WIN64 #define long long long #endif int main() { if (sizeof(long) == 4) { union {double d; unsigned long l[2];} x; x.d = 2.; if (x.l[0]==0 && x.l[1]==(1UL<<30)) printf("1\n"); else if (x.l[1]==0 && x.l[0]==(1UL<<30)) printf("0\n"); else printf("NOT IEEE (32 bit)\n"); } else { union {double d; unsigned long l;} x; x.d = 2.; if (x.l==((unsigned long)1)<<62) printf("-\n"); else printf("NOT IEEE (64 bit)\n"); } return 0; } pari-2.7.5/CHANGES0000644000175000017500000002234212613365604012112 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.7.5 (released 09/11/2015): [last column crossreferences current development release 2.8.0] Fixed 1- forprime engine could skip (fast) sieve in favour of (slow) nextprime [#1711] [F113] 2- 0^[1] -> domain error [#1713] [F114] 3- memory leaks (clones) in ellchangecurve [#1716] [F115] 4- zeta inaccurate around 0 [#1714] [F116] 5- bnrrootnumber did not support the trivial character [0,..,0] [F118] 6- default(log,1) when logfile is write-protected later lead to SEGV [F119] BA 7- 2-adic gamma function: fix accuracy loss [F120] 8- A==A -> 0 for A a t_SER of huge accuracy (so that A-A overflows valuation) [#1734] [F121] XR 9- P=Pol([1,-2,12,-12,-181,-4,-6899,9780,6360,702,-45]); for(i=1,10000,setrand(i);nfdisc(P)) -> crash [#1735] [F122] 10- select(x->x,Vecsmall([1,2,3]),1) -> crash [#1737] [F123] BA 11- [libpari] RgV_to_RgX_reverse did not work if v[1] or v[2] was 0 [F125] 12- bnfinit could fail at low precision [#1736] [F126] 13- Rg_to_ff: incorrect type in zk_to_ff [#1755] [F127] BA 14- nfsubfields could fail [#1758] [F128] 15- rare SEGV in ArtinNumber [#1759] [F129] Done for version 2.7.4 (released 19/06/2015): [last column crossreferences current development release 2.8.0] Fixed 1- divisors([2,1]) -> SEGV [#1664] [F84] 2- acos([Pol(1)]) -> GC bug [#1663] [F85] 3- primes([1,Pol(2)]) -> SEGV [#1668] [F87] 4- buffer overflow after default(format,"f.precision") [F95] 5- qfminim(A, 0, ...) -> stack overflow [#1682] [F97] 6- div_scal_rfrac could create an invalid t_POL [#1651] [F99] 7- polroots(t_POL with leading coeff = 0) -> fp exception [#1690] [F100] 8- \r cannot deal with very long filenames [#1616] [F101] 9- rnfisabelian(nf, non monic t_POL) -> SEGV [#1693] [F102] 10- possibly incorrect result in nfdisc(T,listP) [F104] 11- wrong dim(Ker) returned by ZM_pivot => SEGV in Z-linear algebra routines. E.g. setrand(1);quadclassunit(-612556842419) [#1700] [F105] 12- moebius(factor(18)) -> 1 instead of 0 [#1702] [F106] 13- ispower(-167^10) => domain error [#1703] [F107] 14- ispowerful(factor(0)) != ispowerful(0) [F108] 15- expm1(2*I) => wrong result [F109] 16- gamma(1+a*x+O(x^2)) => error [#1707] [F110] 17- printsep() printed its argument in random format instead of f_RAW [F111] 18- nfdisc(x^10 - 29080*x^5 - 25772600) -> oo loop [#1710] [F112] Added ED 1- mingw64 support [A111] Done for version 2.7.3 (released 18/02/2015): [last column crossreferences current development release 2.8.0] Fixed 1- [from 2.7.2] ??bnrL1 and ??ellL1 did not work anymore 2- thue(f^e*g, ...), e even, (f,g)=1 missed solutions such that f<0 [F22] XR 3- bnrL1(bnrinit(bnfinit(x^2-168),[6,[1,1]],1)) -> bug in ArtinNumber [F55] 4- nfisincl(t_POL, t_POL) could lead to wrong negative results [F58] 5- polresultant(1+x*z^2,1+y*z^4,z) -> GC error [#1614] [F59] BA 6- ellcard over non-prime fields could return wrong results [F60] 7- [libpari] FpX_roots could produce GC errors [#1618] [F61] 8- weber(1+I) was missing its imaginary part [F62] 9- (1+I)*(1+1/2*I) => wrong result (type errors) [#1619] [F63] 10- contfracpnqn([a]) => [1,a;0,1] instead of [a,1;1,0] [F64] 11- primes([2^50, 2^50+200000]) => stack overflow [F65] 12- issquare((x+1/2)^2,&z); z => 1.0*x+0.5 instead of x+1/2 [F66] 13- possibly missing roots in nfroots (when using Trager) [F68] 14- quadray(bnf, ideal) did not work [F69] 15- thue(-14*x^3 + 10*x^2 + 63*x - 5,1) -> "short continued fraction" [F70] 16- thue(29*x^3+130*x^2-35*x-48,1) -> "round error" bug [F71] 17- T=thueinit(10*x^3+6*x^2-41*x+8,1); thue(T,8) => SEGV [#1630] [F72] 18- ellrootno(e,p = 2 or 3) when e not minimal at p => random result [F73] 19- agm(1,2+O(5)) -> SEGV [#1645] [F76] BA 20- [cygwin64] ellap(ellinit([0,0,1,-1,0]),10007) was broken [F77] 21- primes([-5,5]) -> [5] (spurious absolute values) [F78] 22- matqr([;]) -> crash [F79] 23- Fp_rem_mBarrett could return a non-normalized result [F80] p=436^56-35;Mod(271,p)^((p-1)/2) -> p+1 24- plotcopy would corrupt "string" objects (ROt_ST) [F81] BA 25- [GP] default arguments to GP functions could cause corruption [F82] VBr26- [darwin] remove obsolete linker options that cause crashes [#1623] [F83] Done for version 2.7.2 (released 19/09/2014): [last column crossreferences current development release 2.8.0] 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 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] Done for version 2.7.1 (released 16/05/2014): [last column crossreferences current development release 2.8.0] 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] pari-2.7.5/COPYING0000644000175000017500000004325412141040641012142 0ustar billbill GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. pari-2.7.5/README-git0000644000175000017500000001032012314242551012542 0ustar billbillWe use the GIT open-source revision control system. For us developers, it provides network-transparent source control. For ordinary users it provides a convenient way to obtain patched versions in between releases, or follow development branches. GIT clients are available for all major platforms: Unix, MacOS, Windows, see http://git-scm.com/download In particular, the git command-line client is readily available in all Linux distributions. Note: We worked happily for many years with CVS, then Subversion, and provided anonymous read-only CVS / Subversion servers. The transition period is over: fetching PARI using this method is no longer possible; please upgrade to GIT. This file documents access to the PARI GIT server, which is intended for PARI lovers who want the very latest bleeding edge release and development branches. These sources may contain severe bugs, they may not even compile, benches may fail and so on. Stable releases are made available on a regular basis using the customary method: a message to pari-announce. Note that in order to use the sources fetched via GIT, you will need a working bison and perl installation, as well as the regular build toolchain. 1) First connection to the GIT repository: ========================================== To get a working copy, type the following command from the shell git clone http://pari.math.u-bordeaux.fr/git/pari.git This creates a local copy of the distribution from the distant repository in local directory pari, which you may move or rename as you wish. From now on, you can cd to this pari directory and use any git command directly, as long as you remain there, or in a subdirectory. 2) What can I do now ? ====================== * You can build pari in the usual way (see INSTALL) as if this 'pari' directory had been created by fetching, then extracting, an archive on an FTP server. * You can update your local copy at any time using git pull, which puts you in synch with the repository. * You can list all available development branches using git branch -a. To checkout a specific branch, type git checkout branchname. The two main branches are master (testing branch) and pari-2-5 (updates to old stable branch). Other branches are customarily named after the developer who sent the initial patch and the proposed feature, and eventually merged into master. * You can create your own private branches: for instance, the following creates a local branch my-branch, starting from a copy of some-branch you found on our server. git checkout origin/some-branch -b my-branch Of course, you can modify files in your copy and commit changes to your local branches. You can send the output of the relevant git diff command, to the pari-dev mailing list with a short description of what you have done. (No need to subscribe to the mailing list to post, but it will allow you to follow the discussion!) * On the other hand, you will not be able to commit your changes to our GIT repository using anonymous access. For this, you will need read-write access, which requires an account on our development machine. 3) Version tags and branches: ============================= Official releases (starting from version 2.0.17) are 'tagged' so that all files pertaining to a given release can be simultaneously accessed without tracking version numbers. Tag names are pari-version with dots replaced by dashes, e.g. pari-2-0-20 for 2.0.20. To fetch a specific version of pari (2.0.17 or more recent), type for instance git checkout pari-2-0-20 The branch pari-2-5 denotes the stable branch 2.5.* as a whole, and can be used to checkout up to date sources from that branch in between releases. For instance: git checkout pari-2-5 produces the latest stable distribution with all relevant patches (the ones not affecting stability) backported. Tips and Caveats: * git diff gives you the difference between your local copy and the sources they were based on, not with the current state of the testing branch on the PARI repository. Use 'git diff master' for that. * To see the log message associated to the last commit leading to the current state of your local repository, type 'git show'. You may add a file or directory name to get the log message for the last commit which modified it. pari-2.7.5/CHANGES-2.20000644000175000017500000064100111636712103012402 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.3.0 (released 19/05/2006): Fixed 1- ispower(HUGE t_INT, n) could give wrong results (rounding errors) 2- ellheightoo (internal) and RgXQ_norm (public) not declared BA 3- [m68k kernel] didn't compile + need -fPIC 4- libpari.so: soname was incorrect %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.13 (released 26/04/2006): Fixed BA 1-[HPUX] 'program' bench failed for gp-sta [install did not work] 2- made BITS_IN_LONG and related constants 'signed long' [ avoid problems like : exp(10^10) --> 10^10 + 1 (silent overflow) ] 3- --kernel=none : libpari ended up not containing the 'divll' symbol 4- polgalois(x^3-2) --> [,,,"A3"] when new_galois_format was unset. 5- problem with negative valuations in ggcd(t_PADIC) [#411] 6- Fp_pow for huge moduli could return a negative number [#417] 7- y;x/y/z/x --> error [#410] 8- polredabs(x^4-35048*x^2+1016392*x-7368842) --> same, instead of x^4 - 17524*x^2 + 69403802. Rounding error, due to setting the relative precision wrt the wrong reference object. 9- nfisideal() could raise an error instead of returning 0 10- nfreducemodpr only accepted nf's (not bnf's or richer) 11- 1/a/x --> 1/a/x; 1/(a*x) --> 1/(a*x). Now 1/(a*x) in both cases (unify t_RFRAC normalization routines) 12- content(1.*a*x) --> 1 [ now returns a ] 13- content(1./a*x) --> 1.00000/a, but content(1./a*x + 1./a) --> 1/a [ now returns 1/a ] 14- t_SER ^ t_FRAC introduced floating point numbers even when rational expression available, e.g (8 + x)^(1/3) 15- round(t_POL/t_SER, &e) with leading coeff rounded to zero 16- trace(Mod(y,x)) --> SEGV 17- gcd(1, 1/x) --> 1 [ gcd(Pol(1),1/x) correctly returns 1/x ] content(x/y + 1) --> 1 [ content(x/y) correctly returns 1/y ] content(x + 1/y) --> 1 [ also wrong in pari-2.1.7 ] content(1/x/y) --> 1 [ should be 1/y ] 18- missing vectors in qfminim(x,b,,2) [ m omitted ] 19- 'make test-kernel' [ wouldn't compile ] 20- matsnf(matrix with t_POL entries, 1) ---> incorrect matrix V 21- O((-2)^3) --> invalid object 22- (0.*x)*(0.*x) --> 0.E-57 [ instead of 0.E-57*x^2 ] 23- qfminim(x,,m,2) [b omitted] -> [n,B,v]: output correct vectors (v), but reported too many (n too large). 24- qfminim(x,,,2) wrong when x has huge entries. Work out a sensible default precision if x has exact entries. BA 25- HPPA 32bit level0 inline assembly addmul constraint was too weak. 26- factorback(x,y) --> error if x,y were valid t_VEC with exactly 6 components [ typo in checknf_i ] 27- [configure] shared libraries on 64bit sparc require -fPIC / -KPIC 28- (x^3/y^3)^(1/3) -> x + O(x^17) [ leading coeff sometimes lost #433 ] 29- ??INT worked, but not ??t_INT 30- inconsistencies wrt variables in t_POLMOD, e.g Mod(x*a,x^2)' ---> Mod(x, x^2) deriv(Mod(x*a,x^2)) ---> 0 31- contfrac(sqrt(19),2^31-1) --> overflow [ signed overflow can't be reliably tested, use unsigned computations ] BA 32- on x86_64 + gcc-4.0, CFLAGS was missing a -fno-gcse-after-reload 33- [output=3] give more time to external prettyprinter [#209] 34- rare SEGV in factor(t_INT) with low stack space [ #345 ] 35- ispower(1) --> error, ispower(-8) --> error [ allow negative numbers ] 36- Configure -a + kernel = $arch-gmp didn't work [missing -lgmp #438] 37- divisors([]) --> SEGV [#441] 38- missing GC in bernfrac 39- bnrrootnumber(bnrinit(bnfinit(x),1),[]) --> SEGV [#443] 40- f()= local(m = matrix(2,2)); m[1,1] = 1 f() --> m[1,2] also set to 1 41- make test-kernel would always fail with gmp kernel. 42- elllseries(e, 0.) --> error [ only elllseries(e,0) worked ] [#445] 43- 'ftime' was never detected by Configure 44- setrand(74);quadclassunit(-83138791008,,[0.2,6]) --> oo loop [ large prime relation hashtable corrupted when changing subfactorbase ] 45- a(k)=if(k==0,0,a(k)=a(k-1)) a(1) --> SEGV [#447] (add refcounts to 'user function' structs) 46- getheap() did not report properly the "size" of user functions (value too small) 47- add compatibility macro decomp -> Z_factor [ used by mwrank ] BA 48- minpoly(,,v) might return polynomials in x instead of v. 49- make test-kernel required inlining compiler 50- make test-kernel didn't work with C++ compilers 51- ia64 kernel assumed 64bit longs, whereas compilers can be configured for 32bit Changed 1- RgX_simple_gcd: make sure result has non-zero leading term [#412] 2- simplify(t_RFRAC): remove assumption that deg(denom) > 0 [#413] 3- split bfffo.h from level0.h 4- semantic of t_SER with inexact coefficients is now the same as for t_POL: the sign is 0 iff all coefficients are zero. Either there are no coefficients, or the leading coefficient is an inexact zero. 5- removed all non-inline assembler kernels : they were complicated to Configure, mostly untested, and inefficient ( function call overhead + must use global variable hiremainder/overlow when operating on limbs instead of LOCAL_HIREMAINDER trick ). If this slows down your application (it should not), install gcc or use the gmp kernel. 6- allow arbitrary n in divisors(n) and fordiv(n,), provided factor(n) succeeds [ was restricted to t_INT or their factorization matrix ] 7- made LLL the default algorithm in algdep / lindep again [ replaces PSLQ ] Our PSLQ implementation is slow and unstable, and LLL performs much better, see the example in ??algdep. 8- addrr: extend accuracy much less frequently 9- make sure all kernel symbols are present in all versions of libpari (addll & friends could be inline) 10- change the meaning of gcd(x) and lcm(x) when x has vector/matrix components (a global recursive gcd/lcm is taken, instead of a cartesian product of individual gcd/lcm) 11- disallow vecmin([]), vecmax([]) [ returning stoi(+/- BIGINT) is not helpful ] 12- [libpari] renamed lellseries -> elllseries [ as in GP ] 13- semantics of stackdummy() [ make it consistent with gerepile ] 14- never assume that part of an object is "permanent" when it is out of the stack (was used by INTMOD/POLMOD/PADIC). Always copy it. As a result, 'gmodulo' and 'forcecopy' become obsolete. 15- use quadclassunit in qfbhclassno for large D, thereby ASSUMING GRH. 16- ellan was bypassing the check for CM 17- uniformize the generation of parilvl0.h [ genkernel ] Added 1- [library] new function isinexact. BA 2- [elldata] function forell() to loop over elliptic curves. BA 3- [elldata] function ellconvertname() to parse curve name. 4- [library] new function RgX_shift, RgX_mulXn, RgX_shift_shallow, RgX_Rg_div BA 5- m68k level0 inline assembly kernel 6- [library] new function isint, issmall, mkrfrac 7- Configure --time=timing_fun 8- [Configure] genkernel script Removed 1- kernel functions shiftl / shiftlr (inefficient, unused, untested) [ backward compatibility version in src/kernel/level1.h ] 2- obsolete functions forcecopy (use gcopy) and gmodulcp (use gmodulo). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.12 (released 24/01/2006): Fixed 1- incorrect detection of EditLine library 2- issquare(Mod(2,9)) --> 1 [ should be 0 ]. Implicitly assumed v_p(N) odd for all primes divising the modulus N. BA 3- poltschirnhaus(ffinit(2,4)) could return 0. BA 4- Configure -a did not propose fltk and Qt as graphic engine. 5- g()=local(x;f) -- oo-loop [#352] 6- charpoly( Mod(a, b) ) --> wrong result when 'a' is not a t_POL or t_INT. 7- \p2051 log(exp(-1)) --> printing bug [#357] 8- bad argument checks in qfrep() / qfminim() [#359] 9- fix mkintn to work as documented (even when leading word is 0) BA 10- [Linux] gp only accepts one SIGINT in batch mode [#251, #370] (initial patch JD). 11- contfrac(5/3.) was wrong: [1,2] instead of [1,1,2]. For a t_REAL x, when the last partial quotients of a lower and upper bound differ by 1, choose the one associated to the digits of x (followed by infinitely many 0s) unless it was too small and the next partial quotient was 1. [#371] 12- bnfisintnorm: results could have a wrong sign [#372] 13- isprime(N,2): oo loop if N is a perfect square 14- \p n was limited to a value ~ 10 times smaller than the actual limit BA 15- qfbsolve fix 2.2.11-F86 was not sufficient. 16- (1 + O(2))^2 was less precise than sqr(1+O(2)) 17- in the extended help pager, typing ' ' then \n would skip one page [#375] BA 18- config/has_stat.c didn't work with g++ 19- charpoly/minpol(Mod(a,T)) was only monic if T was. BA 20- 'make install' did not work if 'prefix' contained spaces 21- has_dlopen always compiled in on Mac OS X, even if present in libc 22- unsafe handling of t_QFI/t_QFR (setsigne) [#384] 23- idealaddtoone didn't handle zero ideals [#386] 24- workaround a bug in g++ version 3.4.1 (Mandrakelinux 10.1 3.4.1-4mdk) infinite loop on factor(41093858855767145965571) 25- constlog2() was not restartable [ no way to set glog2 = NULL ] 26- sloppy arg check in ellchangecurve [#388] 27- [internal] gprec_w reduced the accuracy of real 0s [#396] 28- wrong arg check in matsolve [#400] 29- minpoly([;]) --> SEGV 30- y*x^3/( 1+x+x^2 +O(y)) -> gerepile error [#403] 31- poldivrem didn't handle properly multivariate polynomials [#402] 32- insufficient accuracy in ellheight --> singular curve, SEGV [#404] 33- [MacOS X + fltk] installed gp binary couldn't use hi-res graphics (resource fork not copied) IZ 34- [2.2.9-A20] -fno-strict-aliasing not supported in older gcc 35- heapsize reported by getheap() were wrong (overestimate). 36- gerepile error in nfgaloisapply [#408] 37- wrong results in bessel functions at non-integer indices (typo in isint(t_REAL) ) [#409] 38- vector(3,n,n*=10) -> [10, 100, 1000] ( now [10, 20, 30] ) 39- bnf.codiff didn't work 40- content([[2]]) --> error Changed 1- speed up prime() by using checkpoints. 2- allow lists with vector entries in listsort (use lexsort) 3- allow vector of points in ellisoncurve() 4- tunings in quadclassunit (#298 / #355) 5- [Configure:] take CPPFLAGS into account 6- 'int' C type is now reserved for -1/0/1 values. Use 'long' otherwise. 7- Fl_inv and Fl_div now raise an error when divisor not invertible [ used to return 0 ] 8- removed the threshold that prevented exponent overflow in exp(-10^10) and returnd 0. instead [ either return correct digits or raise an exception ]. VL 9- honor C_INCLUDE_PATH in Configure (for get_readline) 10- [readline] remove old hack bypassing a bug in readline-2.0 [ did not release SIGINT ]: useless nowadays, and used deprecated functions. 11- export combine_factors [ needed by giac ] 12- do not alias labs to abs in paricom.h 13- randomize polredabs() to improve bound on difficult fields, e.g. f(k) = { p = polcompositum(x^6-3*k^3,x^6-3*k^3)[4]; polredabs(poltschirnhaus(poltschirnhaus(p)),16) } for k = 2, 5, 6, 8, ... 14- try more names in 'pari_unique_filename' (26^2 instead of 26)) 15- remove GCC_INLINE from CFLAGS. Define DISABLE_INLINE or DISABLE_VOLATILE to prevent the compiler from inlining or using the 'volatile' keyword 16- let paripriv.h include parinf.h 17- rename 'prec' -> 'precreal' [ from paripriv.h ] BA 18- define INLINE to 'inline static' for C++ compilers also 19- rename polx -> pol_x, polun -> pol_1 20- make hell, hell2 static to elliptic.c 21- rename decomp -> Z_factor, decomp_limit -> Z_factor_limit 22- rename wf -> weberf, wf1 -> weberf1, wf2 -> weberf2 23- make incpos / incneg static 24- export setseriesprecision, setrealprecision BA 25- make pari restartable 26- [initialization of GP hashtables] remove the 'module' structure, simplify pari_addfunctions, plug helpmessages in initializing entree arrays. 27- rename err -> pari_err, pariputsf -> pariprintf 28- rename rnfhermitebasis -> rnfhnfbasis 29- forbid t_STR, t_VECSMALL and t_LIST in gvar. 30- cleanup mpqs use of temporary files 31- pari_unique_filename now MT-safe, returns a malloc'ed buffer. 32- default() now always returns the value of the (possibly changed) default. No need for a flag anymore. The construction default(def,,1) is still valid but deprecated (the flag is ignored). 33- increase default accuracy in ellinit() when curve has large coefficients [ avoid large relative error on periods, #404 ] 34- qfminim(,,,0) often gives wrong results for matrices with large entries. Test whether rounding errors occur and abort if so [#407] 35- qfminim(x,b,m,flag): b and m are now optional. Allow omitting b (formerly b=0) if flag = 2 also. 36- eval("1a") is now '1' again (was "a" since 2.2.10) Removed BA 1- gnuplot graphic engine (complicated, did not work from gnuplot-4 on) 2- has_sigrelse.c & has_sigsetmask.c [ deprecated, unused after C-10 ] 3- src/desc/Makefile 4- log2old ( = 2atanh(1/3) ) 5- src/desc/gen_help BA 6- obsolete macros INIT_JMP/INIT_SIG Added 1- library function ellisoncurve() BA 2- library functions related to sorting: gen_sort_aux, gen_search_aux, vecsmall_indexsort 3- functions strtoi, strtor BA 4- function minpoly() 5- function zeromatcopy() BA 6- support for GNU/kFreeBSD and other GNU userlands. 7- document ZY_ZXY_rnfequation and ZY_ZXY_resultant 8- function pari_warn() use instead of pari_err() for warnings 9- function pari_add_function, pari_add_module 10- doc/develop.tex 11- library function uisprime, uissquarerem, Z_issquare, Z_issquarerem 12- library function pari_unique_dir 13- library function gp_default 14- library function rowcopy (GP2C) 15- library function traverseheap %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.11 (released 19/10/2005): Fixed 1- a()=b(1,) --> error message 2- agm(-1.0000000004656,1) --> oo loop [Bug #214] 3- sdivss_rem(x,y,&rem) did not set rem, contrary to the documentation BA 4- ellzeta(ellinit([0,0,0,0,1]),1) --> gerepile error 5- random() was less random on 64 bit machines 6- typing 0.e-28 returned 0.E-38 (!) 7- ellminimalmodel(e).a2 was not always in {-1,0,1} 8- check arguments in elllocalred BA 9- [GP2C] type-checking codes generated for some types was wrong. 10- stray output: (a()= for(i=1,1, return);) a() --> 0 11- qfminim & qfrep didn't check their arguments 12- [library:] pariputsf() and GP print() used different output formats 13- nfdisc(x^4 - 2947*x^2 + 1553545) --> SEGV [ incorrect test for gcd in Round 4: gcmp1(d) --> degpol(d) == 0 ] 14- forvec(v=vector(4,k,[1,4]),,2) -> oo loop [bad initialization] 15- eta(x << 1) used far too much accuracy in intermediate computations GN 16- MPQS warning "factoring this number will take several/many hours" now assume more current hardware. 17- off-by-1 error in initprimes0 allocation [Bug #237] -> SEGV in default(primelimit,155100 + 41*7) 18-[Cygwin] incorrect links created by 'make install' 19- a( --> oo loop in parser [Bug #240] 20- at \p366, the last digits of Pi were wrong [ not enough iterations, from 2.2.9, A-2]. [Bug #238] GTo21- wrong prototype for qfrep 22- factornf(P, T) did not accept non-monic T [Bug #241] 23- lngamma(1E+10) --> "Impossible assignment I --> S" 24- "couldn't deal with this field" errors in bnfinit/quadclassunit for tiny discriminants, huge Bach constants (e.g. 12), and unlucky random seeds. Remove arbitrary limits and let the loop run to completion. 25- neither freadseq() nor readGEN() were able to parse '{' / '}' [Bug #216] 26- accuracy problem in polroots (--> division by zero) [Bug #252] 27- acos(x < 0) --> result off by Pi [ introduced in 2.2.9-A3 ] 28- ellrootno(e,p) incorrect in the case of good reduction [#262] 29- (rare) "impossible assignment I-->I" in contfrac 30- typo in qfbclassno's hash function (when D < 0, function can't handle 0). qfbclassno(-948) --> division by 0 [GMP kernel] 31- [Makefiles:] the behaviour of '//' as path leader is undefined. Make sure path prefixes are not '/' [ e.g $prefix/lib --> //lib ] 32- pollead(u*v + (v+1)/v, v) --> 'x' [ should raise an error ] GN 33- problems in MPQS : some factors missed e.g factor(2^263-9) --> expensive extra runs ( + possible stack corruptions when many factors found simultaneously ). 34- tanh(x) was actually computing tanh(|x|) for real x ([#269] from 2.2.8) 35- [MacOS X] dlopen is now part of the system library. Don't redefine dlopen in darwin.c if HAS_DLOPEN is defined. 36- fix Trager's trick in factorff (from 2.2.10) 37- rnfisnorminit(quadpoly(145,y),quadray(145,1)) --> stack overflow [#273] 38- matker([1,2,3;4,5,6]*1.) --> [;] (missing 1 vector) 39- rnfconductor(bnfinit(y),x,1) --> error [#277] 40- gcc-4.0 miscompiles PARI on ix86 [#274] ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23453 ) 41- truncate(1/4/x+1+O(x)) -> (x + 1/4)/x instead of (4*x + 1)/(4*x) [#276] 42- bitneg(2^32-1,32) -> corrupt integer [#279] 43- typo in rnf_is_abelian [#277] GN 44- several minor fixes in mpqs.c BA 45- ellrootno(e,2) was wrong for curves of Kodaira type 3 and -7. ([#212] from 2.2.9) BA 46- galoisfixedfield() was not robust enough ([#256, #228 from 2.2.9) 47- tanh(-10^20) --> error instead of -1 [tanh(10^20) was treated properly] BA 48- wrong rounding in wr_float: with default(format,"f0.10") 1.23456789049999999997 -> 1.234567891 GH 49- typo in thue.c:MiddleSols() --> missing solutions [#264] 50- default(prettyprinter,,1) --> t_POL instead of t_STR [#296] BA 51- truncate(1/x+O(x)) --> SEGV 52- overflow in Flm_gauss (when solving triangular system) --> wrong result [#284] 53- isprime(25, 2) *** impossible inverse modulo: Mod(5, 25). although it's useful to get a factor, it's not nice to raise an error, since 'trap' then becomes mandatory. Removed this feature: the factor is silently discarded (exceedingly rare anyway). 54- (-1)^(any integer >= 2^31) --> -1 [ from 2.2.9 ] GH 55- zncoppersmith(x,1002,1001) --> SEGV [#221] 56- subst(1+O(x),x,x^2+O(x^3)) --> SEGV [#287] (patch by MSo) subst(1+O(x^2),x, x^2+O(x^3)) --> 1 + O(x^3) [ should be O(x^4) ] 57- component() didn't work on lists [ SEGV ] 58- quadclassunit(D,, [c0 > 6]) --> weird error message 59- weird errors in bnrstark [#285] 60- (x^0)^2^31 --> length overflow 61- polroots(pollegendre(51),1) --> SEGV [#293] 62- print({}) --> oo loop BA 63- when choosing between (p-1) and APRCL, isprime() required a complete factorization of p-1, whereas accumuluting factors up to sqrt(p-1) was enough. (e.g 2^127 - 1) BA 64- function name not always properly reported on interrupt (e.g if, while) 65- content([-1]) --> -1 66- memory leaks in quadclassunit (#318) BA 67- [Configure] check that 'readline' is not an EditLine wrapper [ ==> compilation failure otherwise ] 68- Str() --> junk string (uninitialized data) (#326) 69- arg(I*O(7^5)+1) --> junk, exp(3*I + O(3^5)) --> junk. (#328) 70- powiu(2, ulong n) called int2n(long n), incorrect for huge n (#331) 71- Qfb(8,-4,1)*Qfb(5,-4,1) --> Floating Point Exception (BIB, #332) 72- t_QRF distance component was evaluated using an unstable algorithm, possibly leading to catastrophic cancellation (#333) 73- dbltor did not recognize Infinity, NaN, or unnormalized numbers. 74- makerfrac(1,quadgen(24)*x^0)%b --> SEGV, where GEN makerfrac(GEN p,GEN q) { GEN z=cgetg(3,t_RFRAC); z[1]=lcopy(p); z[2]=lcopy(q); return z; } BA 75- exp(x) gave imprecise results at huge accuracies for expo(x) >> 1. 76- valuation(x,p) using a divide & conquer algorithm would kill the session if p = 1 77- (2 + O(2^8))^(-1/3) --> SEGV [#341] 78- exp(0.E100) --> invalid GEN 79- stack corruption in gsubst [#343] 80- Pol([Mat(0.1)],x)^3. --> crash [#346] 81- besseljh(0,2^65) --> crash [#340] BA 82- [plotQt:] ^C while hi-res window is present would crash the session 83- Strtex(Vecsmall) --> SEGV [#348] 84- oo loop in zeta() [catastrophic cancellation in get_xinf() ] 85- oo loop in nfdisc() [#350] 86- Mod(1,2)*x / (1/2) --> incorrect t_POL 87- qfbsolve forgot some solutions: qfbsolve(Qfb(2,1,3),3) --> 0 88- multiplying ideals could lead to factoring big integers (failsafe algorithm in idealtwoelt, when random trials don't work): fix idealtwoelt. Changed BA 1- FpM_FpV_mul is renamed to FpM_FpC_mul, Flm_Flv_mul to Flm_Flc_mul and FlxV_to_ZXC to FlxC_to_ZXC, Flv_to_ZC to Flc_to_ZC, FqV_to_FlxC to FqC_to_FlxC, zv_to_ZC to zc_to_ZC BA 2- FpXV_FpV_innerprod renamed to FpXV_FpC_mul and FlxV_Flv_innerprod to FlxV_Flc_mul 3- retain 'CHANGES' revision after 'make distrib' GN 4- extensive re-tuning in MPQS (all sizes) and avoid "sizing marginal, index1 too large" warning 5- rename globalreduction -> ellglobalred, localreduction -> elllocalred 6- taniyama(e) is deprecated. Use elltaniyama(e, prec) instead of old = precdl; precdl = prec; x = taniyama(e); precdl = old; 7- [bnfinit] retune compute_R to try and detect cheating with Bach's constant. 8- rename lisexpr -> readexp, lisseq -> readseq, flisexpr -> freadexpr, flisseq -> freadseq 9- rename Fp_gener -> gener_Fp, Fl_gener -> gener_Fl 10- change TeX output so that it's easier to handle: - replace \over by \frac [ most people use AMS styles which forbids \over, not plain TeX, which doesn't have \frac ] - remove many extra braces { } [ would prevent line breaks ] - insert carriage returns 11- [GP handling of print1()] get rid of 'added_newline' hack, replace by monitoring in pariputc/pariputs.[#243] 12- do not install libpari.a.xxx [ include files are not versionned either and libpari.a is useless without the correct ones, contrary to .so ] 13- rename gtrans_i -> shallowtrans, concatsp -> shallowconcat. 14- add GC in parsing loop for huge input vectors [ needs roughly 2 or 3 times less memory ] 15- implement pari_is_dir() using stat() instead of opendir() 16- moved defaults from gp/gp.c to language/default.c [ -> into libpari ] 17- moved input_loop to language/es.c [-> into libpari ] 18- when called as 'gp --test', disregard actual terminal dimensions 19- allow ellinit over any ring (support only basic operations) 20- allow ellchangecurve on e = [a1,a2,a3,a4,a6]. 21- typecast cleanup: move most of paricast.h to pariold.h 22- rename readGEN -> gp_read_stream, freadseq -> gp_read_str. freadexpr/readexpr are deprecated, use gp_read_str/readseq 23- make sure GP_DATA is always defined --> default() becomes available in libpari 24- make gnil public 25- change content() so that it always returns the gcd of all entries (as documented). Used to return the gcd of all _contents_ of the entries of a t_VEC/t_COL/t_MAT. 26- backport into quadclassunit some of the bnfinit improvements [specifically, change subfactorbase, #298] BA 27- rewrite rectdraw in an object-oriented way [ reduce code duplication in hi-res plot routines ] BA 28- change the semantic of includedir to not include the pari suffix. Instead /pari is automatically added by make install. 29- improve plindep (use lllintpartial and floating point LLL) + allow lindep with p-adic entries BA 30- allow relative paths in Configure --with-xxx directives BA 31- allow sinh, cosh, tanh with t_PADIC arguments XR 32- bnrstark(): try harder to find solutions [increase precision faster #255] BA 33- rename coefs_to_xxx() to mkxxxn() for xxx in {vec,col,pol,int}. 34- semantics of gcd with inexact zeros: now gcd(0., a) is 1 [used to be a and led to problems: e.g 0./(1.*a)/(1.*a) not simplified ] 35- warn if 'perl' is found but doesn't seem to work 36- forbid the f'(x) construction when x is not a constant type [#327] Added BA 1- polgalois(): 4th component: transitive group name following GAP4 BA 2- new functions ZX_add, ZX_sub, ZX_neg, ZX_Z_add, ZX_Z_mul BA 3- new functions FpC_to_mod, FqV_to_FlxV, FpC_red 4- member functions r1, r2 5- functions factoru(), factoru_pow(), powiu(), powuu(). 6- symbolic link $MANDIR/gp-$version.1 -> $MANDIR/gp.1 7- new functions shallowcopy, shallowconcat, shallowtrans, vecslice, vecpermute, vecslicepermute, rowslice, rowpermute, rowslicepermute BA 8- support for gp2c-run on cygwin BA 9- new optional package 'elldata' and new GP functions ellsearch and ellidentify to access it. BA 10- support for ellinit("") through elldata. 11- new functions vec_ei / col_ei BA 12- new function FpC_Fp_mul, FpV_FpC_mul BA 13- new functions const_col, const_vec, vec_is1to1, vec_isconst 14- new function gp_read_file BA 15- new function substvec BA 16- new divide_conquer_assoc (make divide_conquer_prod thread-safe) 17- p-adic zeta, cos, sin, tan, cotan BA 18- p-adic gamma BA 19- new routine readvec() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.10 (released 17/04/2005): Fixed BA 1- gp2c description of == operator was broken. 2- asin(I) --> SEGV, acos(1 + 0. * I) --> SEGV, atan(I/2) --> SEGV sqrt(0*I),acosh(1+0*I) --> oo loop 3- make test-kernel didn't work [missing gen_m1 & int2n] 4- thetanullk(1/2,1) --> SEGV [from 2.2.9] 5- unit component in factor(t_INT + 0*I) was wrong 6- no typecheck for qfbhclassno input 7- diviuexact destroyed input and made further assumptions [=> wrong results in ellglobalred]. Replaced it by a clean wrapper. GH 8- thue(thueinit(x^3 - 2), 2) --> SEGV 9- reorder([1]) --> SEGV (bad input, but sanity check was wrong) 10- rnfconductor(,1) [ = rnf_is_abelian() ] didn't accept polynomials with POLMOD coeffs + used a wrong algorithm [ not modular + wrong result ] 11- broken code in hnfmodid() wrt GC (would add one 0 column, Bug #129) 12- sqrti(gen_0) --> SEGV [native kernel] BA 13- polrootsmod(,,1) could return a line vector instead of a column. 14- issquare(Pol(1)) --> SEGV BA 15- polsubcyclo() used too much memory for large conductors. 16- typo in quadtoc() --> quadgen(odd t_INT)*1. was wrong 17- subgrouplist([], [2]) --> [[;]] (instead of []) 18- typo in FqX_split [ (!degpol(x)) --> degpol(x) <= 0 ] -> very rare SEGV 19- after alias(a, b); kill(b), invoking 'a' would access corrupted data 20- round(-0.5) --> -1 [ should be 0, as was output by round(-0.5, &e) ] RS 21- gcc-3.4 breaks on compatibility code to support old readline versions [ pre-4.2 ]. Typecast parameters, not functions and dump (approximate) support for g++ + old readlines in gp_rl.c 22- \p 8000 E=ellinit([0,0,0,0,1296]); P=[-8,28]; ellpointtoz(E,P) --> oo loop 23- idealaddtoone(nfinit(y),[0]) --> SEGV [ BIB ] 24- aprcl would wrongly report composites [ introduced aprcl.c:1.48, before release-2-2-8 ] 25- ellchangecurve(e over Qp) --> e.w not updated 26- ellheight(e over Fp, pt) --> SEGV 27- issquare(Mat(2), &z); z --> SEGV [ don't allow matrices as input ] issquare(1/x^2) --> SEGV [ typo in polcarrecomplet ] 28- rnfkummer(over Q) --> type error. 29- allow qfbprimeform(d > 0, p < 0) 30- Since exp(-1e100) --> 0. [ tolerable: alternative being underflow error ], we shouldn't have exp(-1e100) --> truncation error. Fixed. 31- rnfkummer(bnrinit(bnfinit(y),nextprime(10^20),1),Mat(3)) --> module too large in Fp_shanks [ conductor() was computing unnecessarily tough discrete logs ] 32- [Configure:] add /lib64 and /usr/lib64 to library search path 33- SEGV in nfeltpowmodpr() for primes of degree 1 [see 2.2.7-F21] + inputs containing t_INTMODs yield unpredictable [wrong] results 34- znlog(x,g): first check whether x == g [ quite frequent ] 35- rnfisnorminit(nfinit(y^2+y+1), x^3-y,2) --> "incompatible variables" 36- nffactormod() returned a factorization which was not a proper t_MAT 37- rnfequation(y^2+1, x + Mod(z*y - 1, y^2+1)) --> SEGV [ BIB ] 38- many problems in matfrobenius for _inexact_ matrices LGr39- very rare SEGV in idealprimedec() [ typo in init_norm(), using FpX_red on a t_INT, which is no longer valid ] 40- [library:] precision() output "wrong" value for small non-zero t_REAL (depended on exponent, not the bit accuracy of the input). Change so that true bit accuracy is used unless input is 0 (then use exponent). 41- rare memory corruption in thue() [ SmallSols ] 42- gamma(z) for tiny z suffered from catastrophic cancellation 43- ??? sometimes output extra entries [ e.g. ???eigen output matfrobenius ] 44- bezout(0., 0.) --> division by 0 45- issquare(5, &n) --> SEGV 46- factor(x in Q[i] \ Z[i]) --> rubbish [ typo in factor_gauss() ] 47- ellrootno & elllseries didn't check their arguments 48- rnfisnorminit(non-monic polynomial) --> SEGV 49- prevent Ser & Pol from creating invalid objects (e.g Pol(x+y, y) -> y+y) 50- TODO item: polrootspadic(x^2+8*x+4, 2, 2) --> 2 + O(2^2), whereas there's no padic root. The documentation is not clear enough: should polrootspadic(x,p,r) find roots in Z/p^r [current behaviour], or use the precision of the supplied polynomial to compute roots in Qp, then return them at precision p^r [ better, polroots() and factorpadic() behave this way ] ? 51- padicappr(f, t_POLMOD) didn't work 52- rnfidealnormabs(rnfinit(nfinit(y),x^2+1),1) --> SEGV 53- no argument check in primepi() 54- ellminimalmodel(ellinit([1,2,3,4,5])) --> gerepile error 55- gcd([]) was 1 [ should be 0 ] + gcd([...]) used an inefficient algorithm 56- [readline] completion in extended help context ?? didn't include GP defaults 57- [from 2.2.9] nfsubfields(x) had become unable to exploit the trivial case when x is irreducible modulo some prime 58- [from 2.2.9] typo in krosi -> wrong result [ affected aprcl only ] 59- dirdiv([],[]) -> SEGV 60- using allocatemem() in files input with read() could corrupt stack allocatemem() does not end by a longjmp anymore; it is still impossible to use it in loops 61- typo in matrixqz: matrixqz(Mat([1,1]~)/2,0) --> "not a rational matrix" 62- [cf 2.2.7-F23-] use safer parameters in bernfrac(): bernfrac(166) was wrong. 63- [Bug #201] gp --test: line split mode initialized too late print(vector(1000)) would bypass it. 64- [Bug #200] gmul2n(t_POL, n) would not normalize the resulting polynomial [ needed in characteristic 2 for instance ]. 65- FpX_center and centermod didn't use the same normalizations. Fix FpX_center 66- factormod(T,p,1): output was not sorted BA 67- [from 2.2.9] -fPIC missing for gp2c-run on platforms that require it. 68- if(1,print,print(no)) --> no was printed [a function expecting any number of string objects, called without parentheses (no args), would read the following arguments as its own ] 69- more stringent tests in ideal* functions: don't accept t_COL with incorrect length as ideals ([]~ produced SEGV in many cases) 70- factorback([1,1; 0,1],nfinit(x^3+2)) --> SEGV 71- [Bug #156] kbessel was unstably evaluated ? besselk(1,120) %1 = 448600744132608.0000000000000 72- hyperu and kbessel(,1) inaccurate. E.g: hyperu(1,1,1) at \p28 -> last 3 digits wrong Added 1- routines equalsi/equalis, equaliu/equalui, cmpui/cmpiu 2- exported FFTinit() / FFT() wrappers to rootpol.c:fft() [not under GP yet] 3- routines Rg_to_Fl, Rg_to_Fp, RgX_to_FpX, RgX_to_FpXQX, RgX_to_FqX, RgV_to_FpV, RgXQ_mul, RgXQ_sqr, RgX_div_by_X_x, FpX_div_by_X_x, RgXV_unscale 4- file Qfb.c [ stuff related to binary quad. forms moved out of arith1.c ] 5- routines truedivii, truedvmdis, truedivis BA 6- [GMP] faster divri routine. BA 7- support for real forms for qfbsolve. 8- routines RgX_gcd_simple, RgX_extgcd_simple [ when no coeff explosion in base field ] BA 9- new algorithm for exp(t_REAL) [ Newton ] 10- new macro ndec2prec() 11- use Trager's trick in factorff() 12- member function .bid (from a bnr). Extend mod, clgp, no, cyc, gen to bid and bnr structure. 13- new keywords for ?? : bid, CFT, ideal, idele, modulus, rnf. 14- new construction %#: number of history entries so far PC 15- an optional 2nd argument to znorder() to limit the search space Changed 1- renamed gegal --> gequal, gegalgs --> gequalgs, gegalsg --> gequalsg, egalii --> equalii 2- improve trial division in all basic arithmetic functions [ e.g try for(i=1,10^5, factor(1009)), or moebius, or ... ]. Old logic was broken for small inputs (tried far too many primes) 3- improve quadclassunit(D >> 1), about 10 times faster in the 40 digits range [forbid long reduction cycles (too costly to update arch. info when a relation is found + streamline factorquad() ]. See Z_lvalrem_stop() + remove extra_relations() and use large prime variation all the way [almost all relations are found this way] 4- streamline/clean-up polroots [ complete rewrite, much faster for small degrees ]. 5- improved zetakinit() [save some multiplications, about half of them for quadratic fields. Less so as the degree increases. ] 6- renamed RgX_RgX_compo -> RgX_RgXQ_compo 7- renamed binome -> binomial, chinois -> chinese [ added chinese1(x) for chinese(x, NULL) ] 8- add GC in integer valuation functions + use recursive algorithm when valuation looks large 9- no longer raise an exception when online help used on unknown id or obsolete function [report 'unknown identifier' or 'obsolete function'] 10- removed buggy support for narrow class group in quadclassunit + rewrite binary quadratic forms [ qfr3 / qfr5 ]. TODO: move from arith1.c to qfb.c 11- reinstate cornacchia + cornacchia2 with a different interface [ use cornacchia in qfbsolve ] 12- allow non-real arguments in incgamc, incgam MW 13- ellap: if E has CM by a principal order, use Cornacchia instead of Shanks/Mestre 14- more efficient algorithm for issquare(t_FRAC | t_RFRAC) 15- don't return t_INTMODs component in *modpr routines, but lifted representatives. 16- FpX_roots, FpX_factor: normalize input first + direct support for quadratic and linear polynomials [ no need to compute X^p !] 17- FpXQ_powers and similar routines: use multiplications when input has small degree, squarings otherwise. 18- matsnf over polynomial rings: make sure elementary divisors are monic 19- ellpointtoz() now returns z such that 0 <= Im(z) < Im(w2), 0 <= Re(z) < Re(w1). 20- bnfinit(non-monic t_POL) --> now discard variable change 21- rename apprgen9 -> padicappr, factmod9 -> factorff 22- rewrite padicappr() 23- [COMPAT] bnrdisclist has lost its 4th argument 'flag', and omitting the archimedean component now means that all 2^r1 possible values are substituted (formerly: indicate no ramification at infinity). The prototype of bnrdisclist0 has likewise changed. 24- renamed isprincipalrayall -> bnrisprincipal, rayclassno -> bnrclassno rayclassnolist -> bnrclassnolist 25- Change the output of ideallist with technical (flag 2,3) [ with units ]: instead of two vectors, output a vector of 2-component vectors. Change the input of all list routines (bnrclassnolist, bnrdisclist) accordingly. 26- %0 (undocumented) is no longer accepted as an alias for % 27- renamed realzero -> real_0, realun -> real_1, realmun -> real_m1. GN 28- MPQS rewrite [cleaner, faster] Removed 1- obsolete implementation incgam1 [ use incgam. As far as private functions go, incgam2 is better ] 2- removed ideallistarch0, ideallistarchgen, ideallistunitarch, ideallistunitarchgen. Just use ideallistarch. 3- obsolete default 'buffersize'. Flag -b is a no-op. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.9 (released 23/12/2004): Fixed 1- ploth(,256). splines had stopped working 2- gamma(-1.), psi(-1.) [ non-positive integers masquerading as t_REALs ]: wrong results (oo) or 'division by 0' error messages 3- log(1. + 1e-20) --> print more decimals than are significant 4- [Mac OS X + Fltk]: remove the BROKEN_FORK assertion --> graphic window becomes independant of gp as under other OSes. 5- elllseries did not accept complex arguments GN 6- [ix86 + Sun cc] build fails [ unsatisfied symbol reference to 'mulll' ] 7- [libpari] gprec_w didn't behave well for real zero 8- gp -p 51234567890 --> internal overflow and primelimit set to smaller integer 9- [ GMP kernel ] incorrect resmod2n --> wrong 2-adic sqrt 10- [hi-res plot: fltk] fix compilation with g++-3.4 BA 11- [hi-res plot: fltk] line plotting was broken 12- oo loops in prodinf [ e.g prodinf(x=2, zeta(x)) ] 13- [compatible=3] wrong prototype for isoncurve, lex, sign, thetanullk 14- quadhilbert(D > 0) spent an unreasonable time to find a relative equation defined over Q [ use Galois theory instead of naive search ] 15- typo in resmod2n [ missing (ulong) typecast ] -> issquare((2^64+1)^2)=0 BA 16- galoisinit() could fail to find a polynomial defining the fixed field. 17- elllseries had an apparent singularity at s = 2 [ loss of accuracy ] 18- gcoeff, gmael & their variants were not lvalues. 19- typo in element_val(t_FRAC) [ "non invertible" errors in rnfpseudobasis ] 20- added -fno-strict-aliasing to gcc flags [ PARI code doesn't follow strict aliasing rules. In any case, gcc 3.3 can't handle new mael ] 21- 1.a --> 1.0000 [ should be error ]. (x.a = x+1); 1.a --> 1.0000 [ should be 2 ] 22- bnrdisclist(bnfinit(x,2),1) --> SEGV GN 23- [Solaris cc] use safer optimization flag [ -xalias_level=any, fix a pb with 18 above ] Changed 1- increased maximum binary exponent for t_REAL, and maximum GEN length on 64 bit machines. Bumped BINARY_VERSION for writebin --> objects saved in writebin format between 2.2.1 and 2.2.8 are incompatible. 2- use easier to differentiate colors for hi-res plots [ replace "sienna" by "violetred" and "cornsilk" by "green" ] 3- GP interface of function intnum [ old flags not recognized, much more elaborate interface ] 4- library interface of functions intnum, prodeuler, suminf, sumalt, sumalt2, sumpos, sumpos2, prodinf, prodinf1 [ GEN (*eval)(GEN,void*) everywhere instead of entree * ] BA 5- allow Configure -l [ in addition to /pari.cfg ] 6- renamed gzero --> gen_0, gun --> gen_1, gdeux --> gen_2. 7- replaced kludgy matexp.c example by straightforward extgcd Added 1- new algorithm for log( t_COMPLEX ), log(2) [ AGM ] 2- new algorithm for Pi [ AGM ] 3- new algorithm for atan, acos, asin [ AGM ] HC 4- "double exponential method" for numerical integration and sumation. See ??intnum. New functions intcirc, intfouriercos, intfourierexp, intfouriersin, intfuncinit, intlaplaceinv, intmellininv, intmellininvshort, intnuminit, intnuminitgen, intnumromb, intnumstep, sumnum, sumnumalt, sumnuminit 5- new universal constant gen_m1 6- [bench suite] test-intnum and test-stark toplevel targets %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.8 (released 25/11/2004): Fixed 1- gp --version: stack overflow 2- overflow (in C long multiplication) in zeta(4.45+292532.0*I) 3- setrand(1); bnr = bnrinit(bnfinit(quadpoly(1020,y)), 31,1); rnfkummer(bnr, matdiagonal([5,1,1])); --> SEGV ( typo in FpXQX_from_Kronecker ) 4- make -j4 bench could start the bench before the binary was built 5- matkerint had stopped working [from 2.2.7] GN 6- [Solaris + cc:] fix linker warnings (missing object types in src/kernel/*.S) 7- listsort(List([]), 1) --> SEGV 8- setrand(1582268146); bnr=bnrinit(bnfinit(y^12+6*y^10+31*y^8+84*y^6+159*y^4+166*y^2+1),4,1); rnfkummer(bnr,[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,2,1;0,0,0,0,0,1]); --> bug in gadd [ typo in FqX_split ] Smaller test-case: setrand(1701015992) factorff(x^2+y+2, 3, y^3+y^2+2) MSo 9- bug in print_version() --> SEGV on startup if cc version number too long 10- subst(O(x),x,x+O(x^2)) --> SEGV [ substituting in 0 t_SER ] MSo11- various bugs in anal.c: uninitialized reads in get_op_fun(), double_op() memory possibly freed twice because ep->args was not reset to NULL after being freed 12- (10^100 + 0.) / (10^100 + 1.) --> 0. [ display bug from 2.2.6 ] 13- rnfnormgroup(): restrict to primes of degree 1 [ much faster ] 14- gamma(351/2) --> 1.235874058265488750143951998 E740 [ = gamma(351) ] 15- gammah was much slower than gamma [ contrary to docs ] 16- problems with 0 t_SERs: O(y^5)/(1+x) + O(x^3) --> O(x^3) O(y^5)/(1+x+O(x^3)) --> O(y^5) + O(y^5)*x + O(y^5)*x^2 + O(x^3) O(y) / (1+x) --> O(y) O(y) * 1/(1+x) --> O(y) subst(x+O(b),x,a) --> a 17- (0. * x) / x --> 0.E-28 * x 18- content(0.*x) --> 0 19- nfinit([x^2+1, y]) --> SEGV (bad input) 20- lngamma(10^50*I) returned many more digits than were significant 21- bnfinit(x^4-768*x^3+220032*x^2-27869184*x+1316749312) --> recent oo loop 22- elllseries(large t_REAL) --> 0 [ instead of ~ 1 ] 23- erfc(0) --> error [ instead of 1 ] 24- bnfinit(,1) could return without giving fundamental units (if the computation is unfeasible). Raise an error instead. IS 25- config/get_head would not work only if one invoked $PWD/Configure 26- obscure simplification bug: x;s;t;u; a = -9*u*x^3+3*u*s*x^2-3*u*s^2*x+u*s^3+u^4 b = 9*u*x^3+3*u*s*x^2+3*u*s^2*x+u*s^3+u^4 bezout(a,b) * (2*u^4*s^3+2*u^7) --> involves terms like u^5/u^2 27- matrixqz(matrix(2,1,i,j,i-1),-2) --> [;] instead of [0;1] 28- possible SEGV in bnrinit [ when ray class group is trivial ] 29- negative definite forms allowed by Qfb() while most qfb* routines can only cope with positive definite forms. Explicitly disallow negative definite forms. 30- \p 38 ellinit([1,0,0,-19959260,-34323045317]) -> precision too low in initell 31- {p = x^36 - 252*x^34 + 27504*x^32 - 1723392*x^30 + 69300198*x^28 - 1894026456*x^2 6 + 36355251492*x^24 - 499350803616*x^22 + 4953373719489*x^20 - 355510821425 40*x^18 + 183790369965636*x^16 - 677399199594048*x^14 + 1751507793357696*x^1 2 - 3105079104411648*x^10 + 3651333353058816*x^8 - 2698458969378816*x^6 + 11 30370773667840*x^4 - 207898980728832*x^2 + 2879456034816; nfroots(nfinit(subst(p,x,y)), p); } --> loop forever in lllintpartial() Fix: abort lllintpartial if progress negligible (was: if _no_ progress) 32- some permanent structs not freed in freeall() 33- [--with-gmp] round(-4294967296.1) --> '-0' [ typo in mpent ] 34- polredabs(x^4-x^3-31*x^2-12*x+144) was not reduced [ typo in subfield detection algorithm ] 35- nffactor(nfinit(a^2+1),x^2+[]) --> SEGV GH 36- lngamma was not even continuous : its argument was reduced mod 2Pi 37- contfrac(sqrt(2)/2,,2) --> trying to overwrite a universal object 38- nfroots(nfinit(a^2+a+1),x^2-a/4) --> [] (leading coeff not properly taken into account in nf_DDF_roots) 39- Y=Mod(y,y+1);Mod(Y*x,x-1)^2 --> bug in FpX_divrem, p == NULL 40- return type for nffactormod was not a factorization (had become t_VEC) 41- Pol(Ser(1+x)) != 1+x [ bitmask not cleared properly in gconvsp() ] 42- default(datadir,"...") --> SEGV [ attempt to free a static string ] 43- Configure was missing log2/exp2 on systems that had it 44- typo in base2.c:init_norm() [ wrong result in idealprimedec for huge fields ] 45- matsnf([x,1; 0,x],6) --> incorrect type 46- qfgaussred(a) did not work if coefficients of a did not support the "sign" operation [ signature was computed internally ] BA 47- bitneg(1,0) --> SEGV (caused by 2.2.5 A10). 48- factorback([;]) didn't work [ should be 1 ] 49- f = factor(n); divisors(f) destroyed the factorization stored in f 50- add missing GC in hess() 51- [Configure:] runpathprefix was computed only in terms of $osname (assuming standard vendor supplied linker). At least check whether it's GNU ld first. 52- misleading error message rtodber "overflow or underflow in R->dbl" (in fact, only overflow) 53- quadgen(-8) * 0. --> SEGV 54- I + O(2^10) --> error 55- ((x + quadgen(-8))*Mod(1, i))/(x^2+1) --> SEGV [ from randomgen ] 56- Mod(a^0,i^0) --> Mod(1,1) [ should be Mod(0,1) ] 57- factor(HUGE, 100000) --> "pointers lost in gerepile" in random GC in ifac_realloc() [ missing copy() for (*partial)[2] ] 58- incorrect gerepile() behaviour on t_LIST [ would try to update non-existing components if list not full ] BA 59- quoted strings were not displayed properly quoted. 60- bestappr(0.1, 8) --> 0 [ should be 1/8 ] 61- rare bugs in copying routines [ clone bit sometimes not unset ] 62- SEGV in qfminim when integer entries and precision error occured BA 63- galoisidentify() could fail on WSS group with S4 residue. 64- t_POLMOD + t_MAT was incorrect. E.g Mat(1) + Mod(1,x) --> Mod(Mat(1),x) instead of Mat(Mod(1,x)) as for other scalars. 65- Mod(1,8) + O(2^2) --> Mod(1,8) [ should be error ] 66- lngamma(1.) returned a t_REAL of length 'realprecision' (instead of 3) BA 67- matsnf(Mat([])) was returning a matrix instead of a vector. 68- ellap(ellinit([0,1,0,1,0]), 100) --> FPE [ BIB: 100 is not prime, but make the routine more robust ] 69- give meaningful error messages (with context) for 1<<(1<<32), 1<S" ] 70- memory possibly freed twice in pop_val_if_newer() [ race condition on interrupt () during new_val_cell() ] 71- ellap(ellinit([0,1,0,1,0]),100) --> SEGV [ 100 is not prime ! ] MS 72- recover from readline history corruption [ don't trust history_length in history_is_new() ] 73- obscure bug in thue() [ unit of norm -1 not found due to interface inconsistencies ] t = thueinit(x^6 - 2); thue(t, 2638) --> [] JD 74- [Configure:] detection of times() 75- Forbid t_POL + t_VEC: useless and inconsistent [ we had: 1 + [] --> error, x + [] --> OK but x * [] --> [] instead of '[]*x' , etc. ] 76- obscure bugs wrt polynomials with t_MAT coefficients created via Pol() [ e.g content(x*[;]) --> [;], primitive_part(x*[;]) --> [;] ] 77- incorrect behaviour in scalarpol()/scalarser() for exact 0 argument 78- typo in ellap: e defined over Fp didn't work any more 79- t_SER ^ t_QUAD --> SEGV 80- nffactor(non-monic t_POL) --> SEGV due to FpX_red interface change [ don't allow t_INT argument, t_POL is mandatory ] 81- ZX_incremental_CRT: wrong handling of degree increase (--> oo loop) 82- SEGV in Karatsuba multiplication for polynomials, when high product was 0 (over a ring which is not an integral domain!) 83- 1 / Mod((a^2-a)*x^2-1,Mod(2,6)*x^3+Mod(1,2)*x^2+1) --> SEGV 84- ellap(e defined over F2, 2) gave wrong results [ assumed e defined over Q and reduced relevant data modulo 8 ] 85- matcompanion(degree 0 polynomial) --> stack corruption 86- incorrect handling of inexact polynomials in matsnf(,2) [ inexact leading 0 coefficients ] 87- writebin(file, 0) saved a "corrupted" object (0 couldn't be read back) 88- wrong prototype used in rnfdet() [ accepted 3 arguments instead of 2 ] 89- typo in to_Kronecker [ when at least 3 variables involved ] 90- typo in x = sqrt(t_PADIC) [ returned either x or -x ] 91- rare stack corruption in RgX_mul(t_POL, t_POL) [ when product of leading coefficient cancel, valuation is non-zero _and_ we use an "unsafe" gerepile right afterwards ] 92- component(Ser(x),2^31-1) --> SEGV 93- typos in krosi(), kronecker() [ e.g krosi(-4,1), kronecker(0,2^32+1) ] 94- agm(-1,2) --> oo loop 95- tanh(10^10) --> exponent overflow [ should be 1 ! ] 96- gamma(exp(-373)) --> exponent overflow 97- readline: assume a file 'foo' exists, \rf --> \foo [ r deleted! ] [\r f was OK]. Solution: just expand to '\r f'; hitting again completes properly --> \r foo. BA 98- Reduce stack consumption in ffinit and polsubcyclo. 99- (p/q)' wasn't simplified if q wasn't squarefree 100- polylog(n, x < 0) had a (small) non-zero imaginary part 101- 3 + O((-1)) --> oo loop 102- creating t_PADIC/t_SERs via x + O(...) eventually blew up the heap 103- fix memory leaks related to GP pointers and clones Changed 1- lgef / setlgef / evallgef removed. One may safely use lg for t_POLs. As a result maximal degree jumps to ~ 2^24 on 32bit machines 2- renamed *res(te) routines to *rem(ainder). Eg poldivres --> poldivrem, nfdivres --> nfdivrem BA 3- Internal u_Fp* routines now are renamed Fl* and made public. BA 4- [GMP kernel] Library soname changed to libpari-gmp[-2.2].so.N. BA 5- Library .so link changed to libpari.so for all versions. Static library changed to libpari.a for all versions. 6- COMPAT: ellheight now uses the standard normalization: twice the value it used to return. The values returned by ellbil() and ellheightmatrix are unaffected. In particular, ellheightmatrix() is the polar form of elleight(), and ellbil now satisfies the proper identity for B(P, Q) = (h(P+Q)-h(P)-h(Q)) / 2 7- renamed and declared gmul_mat_smallvec --> RM_zc_mul gmul_mati_smallvec--> ZM_zc_mul 8- move functions in highlvl.c to libpari, excluding install(). 9- bnfinit: use approximate integral LLL reduction (much faster than fp) 10- bnfinit: cache multiplication table by prime ideal anti-uniformizers (faster valuations) BA 11- improve binomial (use divide_conquer_prod) 12- improve bnrinit & idealstart when finite part of conductor is 1 (+ improve stability) 13- subgrouplist(bnr,...) does not require bnr to contain generators anymore ( bnrinit(,,1) ). Also much faster. 14- allow zetakinit() to use a bnf argument [ would be recomputed before, making it impossible to certify the result since bnfcertify could not be applied ] BA 15- error messages now mention the GP function when the error occured. 16- intro message [ no point in displaying "realprecision", "seriesprecision" and "format" on startup. One can query them individually, or ask for all defaults ] BA 17- macro varncmp(vx,vy) should now be used to compare variable numbers. BA 18- split substpol from subst ( reverse [ 2.2.1 C24 ] ). Use substpol for non-trivial algebraic substitution. 19- remove t_FRACN / t_RFRACN from \t output, add t_VECSMALL BA 20- bittest() now handle negative operand as 2-adic. BA 21- type() does not allow to change object types anymore. 22- internal routines setloop()/incloop() allocated 2 chunks of memory, then assumed they were connected [ true for the current allocation model ]. Remove that unecessary assumption. 23- more informative error messages in concat() 24- in affsi / affui (s, z) : do not check that lg(z) >= 3 25- replace gexpo(t_QUAD) by a rough aproximation (as t_COMPLEX): faster 26- made Mat(t_VEC of w t_COLs of the same length h) return a h x w matrix Used to be a 1 x w matrix whose elements were t_COLs. Obsoletes such hacks as: v = vector(...); v[1] = Mat(v[1]); concat(v). Now Mat(v) is enough. 27- move BEGINEXTERN / ENDEXTERN pairs out of kernel headers into pari.h 28- split the User's manual in two: PARI/GP and libpari. 29- updated and completed the tutorial 30- faster basic transcendental functions on small inputs (sqrt, log, exp) 31- rewrote basic generic kernel (add,mul,div) [ faster, less obfuscated ] 32- macroified gop1z, gop2z, gops2gsz, gops2sgz, gops2ssz 33- diviiz(x,y,z), divisz, divsiz and divssz always assign the euclidean quotient [ used to depend on the type of z: if t_REAL computed exact quotient ]. Use rdivii, rdivis, rdivsi, rdivss for analogous functionality (no "z" variant); 34- ensure proper rounding in divrs 35- renamed padiczero --> zeropadic [ as in zero[pol|ser|vec|col|mat] ] 36- macroified gcosz, gsinz, gexpz, etc + cleanup transcendental functions 37- macroified mulssz, addssz 38- rename mpent --> mpfloor 39- rename divise --> dvdii, gdivise --> gdvd, mpdivis --> dvdiiz, mpdivisis --> dvdisz 40- rename mpppcm --> lcmii, remove mppgcd [ use gcdii ] 41- rename resss --> remss, ressi --> remsi, resis --> remis, resii --> remii, gres --> grem 42- rename krogs --> krois, krosg --> krosi 43- rename FpXQX_FpXQ_mul -> FqX_Fq_mul, FpXQX_normalize -> FqX_normalize 44- rename adduumod, subuumod, muluumod, divuumod --> Fl_[add,sub,mul,div] invumod --> Fl_inv, invsmod --> Fl_inv_signed, powuumod --> Fl_pow powiumod --> Fp_powu, mpsqrtmod --> Fp_sqrt, mpsqrtnmod --> Fp_sqrtn 45- rename mpsqrt --> sqrtr, mpsqrtn --> sqrtnr 46- don't copy arguments of user functions for types which have no modifiable components (anything but VEC, COL, MAT, LIST, VECSMALL): much faster. 47- ':' no longer allowed as a substitute for ';' if compatible = 0. Use GP2C semantics [ x:int, v:vec ]. For the time being the type information is discarded. 48- modulargcd() was very inefficient for non-monic t_POLs [ e.g (poltchebi(x) - 1) / (x-1) ] JD 49- [timer: ] use sysconf(_SC_CLK_TCK) instead of CLK_TCK if available, and make sure one of these is available before choosing times() in Configure JD 50- check for 'exuberant-ctags' before 'ctags' in make_vi_tags [ and fail gracefully if neither is found ] BA 51- support for gp2c-run on Darwin 52- remove blanks in "raw" outputs ( default(output,0) ) 53- made .fu and .tu return t_POLMOD, not t_POL BA 54- [GMP kernel] use mpn_sqrtrem for sqrtr_abs 55- nfsubfields (use much less memory) GH 56- more robust thue(): faster enumeration of small solution, don't assume that the full unit group is known, warn when conditional result is obtained. 57- remove log() flag: decide alone whether to use AGM or not. Rewrote logagm and mpexp1 58- make ??? index search ignore case [ ???bernoulli will find Bernoulli ] 59- renamed svaluation --> u_lvalrem, pvaluation --> Z_pvalrem 60- change semantics of sqrtn to catch easily non-residues from the user's side 61- rewrote the 'tune' utility, add one tune.h file for each kernel, support for user override still needs to be rethought (or documented). Added 1- make test-all [ all available test suites (SLOW !)] BA 2- add support for GNU/Hurd. 3- conversion routines zv_to_ZC, zv_to_ZV, zm_to_ZM, and matrix multiplication: RgM_zm_mul, ZM_zm_mul. 4- output support for zm / Flm matrices (t_MAT with t_VECSMALLs instead of t_COLs) 5- FpM_rank 6- allow factor( an elt in Z[i] ) 7- put back bruteall [ used by Math::Pari ] BA 8- Configure support for sparc64, x86_64 and ppc64 BA 9- x86_64 level0 inline assembly kernel BA 10- add POSIX-style long options --fast, --quiet, --primelimit and --stacksize. 11- new internal library routine itos_or_0 12- new member function .index 13- rdivii, rdivis, rdivsi, rdivss to replace diviiz & co. 14- new routine mpround, mpfloor, mpceil, mptrunc, roundr, floorr, ceilr, truncr BA 15- galoisisabelian, galoisexport, galoisidentify and galoissubgroups now also accept subgroups returned by galoissubgroups. 16- new routine Fl_sqrt 17- new routines FpX_factor, FqX_factor, FpX_degfact, FqX_red 18- private header file pari-priv.h 19- new function ispower 20- forvec iterator GH 21- new function zncoppersmith 22- public interface to forvec() [ forvec_start + forvec_data, for GP2C ] 23- routine sqrtremi() [ Karatsuba square root ] 24- internal routine int2n() [ = 2^n ] 25- new functions Z_pval, Z_lval, u_lval 26- new function primepi BA 27- new default factor_add_primes BA 28- HPPA 32bit and 64bit level0 inline assembly kernel Removed 1- obsolete macro leadingcoeff [kept for backward compatibility but removed from the documentation]. Use leading_term. 2- obsolete undocumented type t_SMALL BA 3- revert 2.2.1 A14 and A17 (broken with GMP kernel, unmaintainable). BA 4- cornacchia, in favour of qfbsolve. 5- useless inefficient types FRACN / RFRACN 6- routines gred [useless] / gredz [ useless did not work ]. Define gred --> gcopy for backward compatibility 7- many obsolete error codes [ for err(...) ] 8- smodsi() [ useless, not well defined ] 9- buggy macros mppiz, mpeulerz [ undocumented, useless, broke compilation to use them ] 10- inconsistently named macros mpinv[sir]r [ were "z" functions ]. 11- public macros refering to static transcendental routines (e.g mpatanz) 12- undocumented, inconsistently named, useless, mulsii, addsii, divisii 13- useless routine umuluu [ use mulll ] 14- undocumented [macro] constants pariC1, pariC2, pariC3, pariK, pariK2, pariK4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.7 (released 18/12/2003): Fixed 1- bench input files: should all start by a 'gettime()' instruction 2- bnfisnorm(bnfinit(x^2-11),1) --> [Mod(1, #), 1] [ return a result involving MAXVARN on trivial input ] 3- [Mat(5)] * [[0]~]~ --> 0. Should be [0]~ [introduced in 2.2.6-C.25] 4- \p 1000 E=ellinit([1,0,1,-120039822036992245303534619191166796374,5042249924849106700108 01799168082726759443756222911415116]); x1=1e100; y1=ellordinate(E,x1)[1]; ellpointtoz(E,[x1,y1]); --> impossible addition t_VEC + t_VEC. [ precision error ] 5- erfc(non scalar) --> type error 6- raising to t_FRAC power didn't work with p-adics: (-1+O(5))^(1/2) --> 1 7- [ isprime / APRCL: ] integer overflow, e.g isprime(2^32 + 1, 2) 8- sum(i=2^32-10,2^32+10,1) --> 11 [ kind of overflow ] + didn't use the t_INT interface ==> broken with GMP kernel 9- polgalois(x^6-3*x^4+3) --> [24, -1, 1], should be [24, -1, 2]. From 2.2.4 10- nfisincl(x, x^2+1/2) --> SEGV [ assumed integral inputs ] 11- numbpart(10^15+2) --> SEGV [ check for x < 10^15 incorrect ] 12- polcompositum(x,x) --> SEGV [ problem with poldeflate(deg 0 pol) ] 13- zeta((1+I)/2^225) --> 7e28 [ precision error when using func. eq. ] 14- typos in qfsign/qfgaussred() [ aka sqred2 ]: wrong results: e.g qfsign([0, -1, 1, 1; -1, 0, 0, 1; 1, 0, 0, -1; 1, 1, -1, 0]) --> [2,2] ( should be [2,1] ) 15- numbpart(0) --> 0 [ should be 1 ] GN 16- assembler section of Sparc Makefiles relied on GNU make specific $< MSo17- off-by-1 error in Vec( t_STR ) [ memory corruption ] 18- off-by-1 error in itostr(), e.g 10^11 [ memory corruption ] BA 19- [hi-res plot: X-Windows] rescaling bug MSo20- bittest(1,32) --> 1 [ off-by-1 error ] 21- nfeltpowmodpr(nf,x, prime of degree 1) --> SEGV [ FpXQ_pow couldn't handle computation in prime fields ] 22- charpoly( Mod(mat, poly) ) --> SEGV [ out of stack components not treated properly ] 23- memory corruption when parsing floating point constants [ constante() ] 24- too little GC in serreverse() 25- bnfinit(huge field) --> "precision loss in truncation" [ missing term sqrt(disc(K)) in norm bound ] 26- allow conj(t_POLMOD) provided the modulus degree is <= 2. MSo27- ?0 with _many_ user functions defined --> SEGV [ typo in commands() ] 28- quadclassunit(5) --> PLEASE REPORT [ can't build subfactorbase, introduced in 2.2.6 ] 29- valuation(x^3, x^2) --> 3 [ valuation at a monomial assumed it had degree 1, introduced in 2.2.2 ] 30- Set(matid(2)) --> [ "[1, 0;\n0, 1]" ]. Ensure "raw" format is used, not "prettymat". 31- typo in rnfpolred(bnf, *). E.g rnfpolred(nfinit(polcyclo(3,a)),x^3-19) --> oo loop [ non-positive T_2 form ] 32- typo in ellap: rare wrong result. E.g E=ellinit([0,0,1,-5115523309,-140826120488927]); ellap(E, 1315717181) BA 33- qfbprimeform(-3, 1) --> data corruption [ gzero's signe set to 1 ] 34- qfbpowraw(x, n < 0) reduced its output 35- stack corruption when adding huge p-adics 36- idealintersect did not allow fractional ideals 37- Ser([1,2]) --> 1 + 2*x + O(x^2) [ OK ], but Ser([0,0]) --> O(x^16) 38- writebin() still produced incompatible output depending on the multiprecision kernel. 39- [alg | lin]dep( t_PADIC ) had stopped working in 2.2.6 40- some precision problems in polgalois(deg(p) > 7) [ changed slightly some heuristic settings: the algorithm is simply not rigorous... ] 41- typo in polredabs: polynomial of minimal T_2 norm might be missed [ actually found, then deleted due to a typo when "Sorting" small vectors, which would assess them the norm of a larger element ] 42- polredabs(,4): some polynomials of minimal norm could be eliminated due to fixed buffer size for the small vectors. Made that dynamic. 43- in certain situations (when using Allombert's algo.), subfields did not output subfields sorted by degree 44- [Windows installer:] online help did not work on most installations 45- lines continuation with \ did not work with DOS fileformat BG 46- random(2^31) returned integers in [0, 2^32-1] [ long/ulong problem ] 47- isprime(156499227435744375600531968861048687296374896432841731) --> SEGV [ missing case in aprcl:sqrmod5() ] BA 48- Configure: using gcc-3.3 + LANG=french, Configure failed to detect gcc [ messages translated ] 49- alpha kernel would not compile with a C++ compiler (missing extern "C") 50- rare stack corruption in gmul(t_COMPLEX, t_COMPLEX) [ when result is real ] 51- valuation(Mod(x,x^2), y) --> oo loop [ now 0 ] 52- optimization problems in new zeta() and gamma() [2.2.0 C13] ( e.g zeta(0.5 + 10000*I) was _much_ slower than before ) 53- precision problem in nffactor [ in get_R() ], could yield to a SEGV, e.g nffactor(nfinit(y^4+7^2),x^28-14*x^24+20321*x^20+166992*x^16+1171296*x^12+1342208*x^8-5005056*x^4+3211264); 54- contfrac(Pi/2,2) --> [1, 1] (doc says a_n != 1, so should be [2]) 55- factorint( 3280696195200006885547973357173182411881462602934802054749349683516314460050 2548596646024265171468102088952756084355402608216473040677346490348936595334 0299389230010814564530645152250241760175805765084544728012391149823776145022 4913178048870032606672750626773595019035786804361581343222144074318522768947 2061349830773562073895748494534362180537529975336881525935996152181576667869 0625865166662910961888106910345518707973056625912728422391238723575276042635 9727112469435556047168454738353621102783718736137552743946577993495054202848 9372915917197045423574773583244796785665263319216397122018435444897 ,11) --> impossible assignment I-->S [ stack corruption ]. 56- typo in kummer.c:invimsubgroup [ hnfmod --> hnfmodid ]. Very rare weird error message in rnfkummer(): "wrong subgroup in conductor". 57- typo in alglin2.c:hnfspec() [ same loop index used twice ] 58- zeta(x) very slow for large integer |x| (use new bernfrac() code) 59- removed -mimpure-text from DLLDFLAGS on non-sparc architecture XR 60- Configure/bench: use head -n # instead of head -# (deprecated and unsupported by GNU coreutils) 61- not enough GC in mpbern() [ Bernoulli numbers ] and psi() 62- \p50000, then polroots(x) --> exponent overflow 63- ellj( t_QUAD ) / eta( t_QUAD ) was forbidden. 64- polredabs(x,1) did not work when x was already reduced 65- polroots(x^3 + 0e-20) --> oo loop [ didn't handle nicely non-exact 0 as a constant coeff ] 66- 'make doc' always rebuilt the documentation, even if it was up to date Changed 1- bnfinit: [small_norm phase] speed up norm computations. 2- [make etags:] use $ETAGS instead of 'etags' if defined 3- [libpari:] renamed incgam4 --> incgam0, incgam3 --> incgamc BA 4- [Description system] Store GP functions in a database in src/functions/ instead of hard-coding them in C files. 5- [libpari:] modified zbrent interface to allow library programming 6- ellpointtoz(E, P): remove the test that P be on E [ useless and often wrong when P has inexact entries] 7- allow serconvol() with 0 series. MSo 8- allow numtoperm(0,k) [ --> [] ] 9- simplify result of basic op. involving complex numbers, e.g. I*I --> -1 as t_INT (was t_COMPLEX) 10- embedings of number fields: use x + iy --> (x + y, x - y) instead of (sqrt(2)x, sqrt(2)y) to map complex embeddings to R^2. 11- disallow Ser( t_MAT ) [ resulted in a series with t_COL coefficients ] 12- nf format to improve idealinv() [ nf[5][6] and nf[5][7] ] 13- disallow sqrtint( x < 0 ) 14- meaning of the GP_DATA_DIR global variable: now points to the directory _containing_ galdata, not to the galdata files 15- qfminim(,,2) + polredabs: look for points by (roughly) increasing norms (was: full enumeration and roughly decreasing norms) 16- exp(-10^10) --> 0.E2525223 [ was 'underflow' ] 17- polredabs: improve the search for subfields (no polynomial factorization required now, only linear algebra) 18- ellglobalred(): use gcd(e.c4, e.c6) to help factor e.disc 19- removed obsolete components ("checks", "bits of accuracy left in computation") from quadclassunit / bnfinit / bnfisprincipal / bnrisprincipal / bnfunit outputs. 20- 'make test-graphic' is gone. Use 'make test-ploth' HC 21- new implementation of gamma() 22- renamed Oxxx/dft.Config.in --> pari.cfg 23- new implementation of bernfrac() [ use zeta(2k), initial GP code by HC] 24- bernvec always calls bernfrac() [ hence has become useless ] 25- [sparcv8_super kernel:] replace asm divll with portable one (slightly slower but fixes many compilation problems, and easier to maintain on an architecture which has become hard to test) 26- buchall() [ bnfinit, etc ]: complete rewrite to avoid restarting from scratch after a precision increase. All relations stored in algebraic form, so that data is easily recomputed to higher accuracy if necessary. Use lower default precision. 27- remove special handling of t_STR by printtex / writetex [ 2-2-6-C19: a \ would be inserted in front of $, %, etc. ]. This broke things like printtex("$", x, "$"), and is better done by the user herself. 28- bnfinit(): remove useless components from the "technical parameter". Added 1- [Configure:] flag --with-ncurses-lib=* BA 2- support for FLTK graphical library [ hi-res plot ] BA 3- galoisidentify for order 96 to 127. 4- default 'datadir' [ to allow relocating 'galdata' for polgalois ] 5- hi-res plotting under Windows GTo 6- routine qfrep() BA 7- routine qfbsolve(Q,p) for Q imaginary and p prime 8- new testsuite: make test-galois (~ 1 minute) 9- new options to Configure: --with-fltk, --emacsdir, --datadir, --sysdatadir SG 10- updated micro-kernel for HPPA BA 11- Add code 'i' for functions returning C int (not long) Removed 1- bruteall [ useless, undocumented variant of 'brute' ] 2- option to Configure: --miscdir %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.6 (released 19/06/2003): Fixed 1- rnfidealtwoelt, rnfidealmult --> SEGV 2- agm(x+1, x+2) --> oo loop [2.2.5 F-61 was undone...] 3- setrand(1); elltors(ellinit(vector(5,k,random/random))) --> SEGV [ incorrect use of partial factorization in ellintegralmodel --> surviving denominator ] 4- old typo in cauchy_bound --> factor((x - 155)*(x^2 + 160*x + 12864)) returned a single irreducible factor [ missing factor 2: initial upper bound for roots was 125 instead of 250 ] 5- zeta(x) very slow near large negative integers 6- algdep(2^46,1) ---> 1 [from 2.2.5] 7- bnrclassnolist(bnfinit(y),[2,2]) --> SEGV IS 8- typo in paricom.h [extra , in enum] --> compilation failure IS 9- typo in part.c [ // comments ] --> compilation failure 10- y/(x/y) --> error [ wrong assumption that y is a genuine GEN in mulscalrfrac ] 11- example/Makefile wasn't up to date [ link with -lpari ] 12- zetak(zetakinit(y), 3-1e-28) --> -7.2e28 [ catastrophic precision loss triggered by anything non-integral but very close to an integer ] IS 13- gp-dyn build on AIX 14- subst(y*x,y^2,x) --> 0 15- rnfisnorminit(x,x^3-2) --> SEGV [ bad input. Missing argument checks ] 16- Compiling with g++ + gmp, missing gmp version number [missing stdio.h] IS 17- [AIX:] various compilation problems + select better CFLAGS (-qtune=auto -qmaxmem=8192) IS 18- [HPUX:] remove -E from DLCFLAGS 19- bnrconductor(bnfinit(x)) --> SEGV [ missing check ] 20- ellpow(E,...,-1) --> stack error [ from 2.2.5 ] 21- a:b:c; c/a/b == c/b/a --> 0 22- sparcv8 inline assembler kernel used global registers for hiremainder / overflow, which was dangerous, inefficient, and complicated. Now none of the inline kernels use any global variable. The non-inline assembler kernels do define and access globals hiremainder and overflow. BA 23- cos(2^2^22) --> precision too low [ idem sin, tan ] 24- setrand(1504969109; quadclassunit(-403195) --> incorrect. Check against L-value too liberal; now allow quotient in [ 0.8, 1.3 ], not [0.75,1.5] 25- TODO item: quadclassunit not reliable when fed non fundamental discriminant (oo loop [e.g quadclassunit(-352)], wrong result). [ fix: increase factor base ] 26- sign of elleisnum(E, 6, 1) was wrong BA 27- [GMP kernel] factor(18295370635792208009) --> error 28- idealprimedec(nfinit(x^16+16),256) --> SEGV [ bad input ] 29- setrand(1642014180);quadclassunit(1642014180) --> PLEASE REPORT [ bug in large prime relation code ] 30- TODO item: rnfpolred(nfinit(quadpoly(904,y)),quadray(904,1)) *** division by zero in gdiv, gdivgs or ginv BA 31- uninitialized memory read in divrr(x,y), when lg(y) < lg(x), leading to random rounding of result. 32- [Cygwin + bash >= 2.05a]: HOSTTYPE no longer auto-exported by bash --> Cygwin compilation broken. Define it to i386 by default. 33- TODO items related to polgalois + polgalois(x^8-1864259299553450972214799899167226732549697977945716*x^6+331143259018657601105207922631212331088735421305543663274125986698777318014979969*x^4-2225286541902342283500014249183311190477390*x^2+5); --> degree too large + setrand(7); polgalois(x^8+162644002617632464507038884216211529274267271168000002) --> wrong result + polgalois(x^11 - 2) took a looong time. 34- systematic warning in bnfisnorm() [ "useless flag" ] 35- charpoly could not handle t_POL in variable MAXVARN 36- \p400 + sin(2*Pi) boasted far too many significant digits 37- [Configure:] --with-readline=path did not work 38- [Configure:] $TOP/readline was added to search path for ncurses, termcap, etc 39- memory leak: x = vector(2); y = vectorv(2); while(1, m = matrix(2,2); m[2, ] = x; m[, 2] = y) --> out of memory 40- factor(12345)[,1][3] --> error 41- overflow in some GP interface routines: e.g default(realprecision,10^125) 42- polhensellift((x^2+1)*Mod(1,5),...) --> SEGV [ bad input ] 43- lindep([x,y]) --> SEGV [ bad input ] 44- polredabs(x^4+9670527181567158504671*x^2+4840282594390812607599424249,16); --> impossible concatenation in concat [ from 2.2.5 ] 45- [Cygwin compilation:] incorrect cygtop [ --> readline not found ] 46- [Cygwin:] DLL build. libpari.dll and gp-dyn build OK. Install does not work in gp-sta (SEGV) 47- rare SEGV in Round 4 when using non-primes in addprimes() 48- overflow when computing Euler's constant to 20000+ decimal digits MSo49- error message for unrecognized GP metacommand: off-by-1 error GN 50- Configure breaks if CFLAGS contains '/' (invoke sed with '!' separator) IZ 51- [tex2mail:] line couldn't start with {...\over...} (required indent) IZ 52- [tex2mail:] \over wasn't allowed within \left( \right) 53- ZX_QX_resultant (modular resultant with integer result): possible oo loop when the result is 0, and non trivial denominator. 54- elleta(E.omega) gave incorrect results [ conflicting normalizations ] 55- typo in charpoly(t_MAT) [ stack overflow after garbage collection ] 56- subst(y,x+y-x,y) --> 0 [ missing simplification ] 57- typo in nfroots [ returned inverse of roots when polynomial had small degree (using Trager's method) ] 58- 'path' default incorrectly set on Cygwin 59- [internal:] isprincipalfact() incorrect if flag contained nf_GEN_IF_PRINCIPAL (was unused). 60- bnfisintnorm(bnfinit(y^4+y+1), -1) --> SEGV [ could occur for any unit ] 61- stack corruption in matsnf() [ when GC occurs ] 62- vecsort(t_VECSMALL) --> SEGV 63- v = vector(2); j = 0; v[j++] = 1 --> j = 2 [ side effect of 2.2.4-F21: LHS for matrix assignment was evaluated twice ] Rem: v = vector(2); v[j++] = v = 0 --> SEGV. Don't cry. BA 64- [ix86 + gcc compilation]: fix "invalid preprocessing token" Warning BA 65- galoisinit could very rarely trigger a 'impossible inverse modulo' error. Changed 1- rnf structure (removed useless components) 2- rnfidealreltoabs, rnfidealup: now return a Z-basis as a vector of elements in the relative extension, instead of a meaningless HNF matrix wrt an unknown basis. Was especially dangerous if the extension also existed in nfinit form, since the HNF matrices were _not_ ideals wrt this nf structure. [ also consistent with rnfeltreltoabs ] 3- rnfidealabstorel now requires input in the above form, so use rnfidealabstorel(rnf, nf.zk * A), if A is a standard ideal in HNF form. Used to require matrices in HNF form, which was confusing since ideals such as A gave wrong results [ HNF wrt different implicit bases ]. 4- idealadd(x,y): multiply by lcm(denom(x), denom(y)), not their product 5- rewrote nfhnf/nfhnfmod/nfbezout [ many small improvements ] 6- rnf structure now filled incrementally [ absolute nf, data for norm computations ]. Use build_and_check_obj() mechanism already used for bnf: cycgen ( bnf.gen[i]^bnf.cyc[i] ) + matal (relations in algebraic form) 7- rewrote rnfpseudobasis, rnfordmax [+ new routine rnfallbase ] 8- always define checkmemory() in libpari [ was included only if MEMSTEP was defined ]. Could cause compilation failure when compiling with different flags. 9- upgrade pariemacs, see pariemacs.txt 10- faster divll for portable kernel [ inspired by GMP ] 11- allow system() under Windows (95 and higher) 12- use cmprr() in gegal(t_REAL, t_REAL) 13- have Configure check explicitly that the C compiler is ANSI 14- faster modular algorithm for characteristic polynomial of algebraic integers Mod(x, y) [ ZX_caract(): old would replace x by its integral part and correct at the end; new is fully modular ] 15- separated mpadd functions from [none|gmp]/mp.c --> kernel/add.c 16- use 'lgeflist' for t_LIST: remove the 65536 limit on list size 17- subst(1 + x^2 + O(x^5), x^2, y) --> 1 + y + O(y^2) 18- nffactor: allow modular factorization over primes of degree > 1 IZ 19- try to output usable TeX (avoid braces, let TeX split lines) 20- [libpari internals:] jmp_buf 'environnement' no longer global MSo21- allow poltchebi(n < 0) [ := poltchebi(-n), still satisfies the 3-term recursion ] IZ 22- prime sieve optimization [ primelimit ] 23- try to reduce the likelihood of an artefact relation in PSLQ [ use "confidence level" 2^(-20) ] IZ 24- [tex2mail:] add a "cut here" sign when expression does not fit in the linelength: \o3 \p240 [Pi, Pi]~ 25- faster multiplication [t_VEC | t_MAT] * t_COL for sparse t_COL [ induces faster charpoly for sparse t_MAT ] 26- matsnf: allow rectangular matrices + improvements for singular matrices 27- made startup errors ( GPRC ) non fatal. 28- allow vecsort(t_VECSMALL) 29- renamed mulssmod/divssmod --> muluumod/divuumod and changed their prototype (use ulong arguments, return ulong) [ was already the case, with various casts ] 30- renamed u_invmod --> invumod. Documented all level0 modular routines. [ also added invsmod ] 31- separated "negative or zero argument" (arither2) and "zero argument" (arither3) errors. Added 1- member function rnf.pol (polynomial generating absolute extension) 2- src/kernel/sparcv8_[micro|super] 3- in emacs/ : pari-completion.el pari-conf.el.in pari-fontification.el pari-help.el pari-messages.el sli-tools.el 4- Configure --builddir : find a decent name for build directory depending on kernel options (with/without gmp, exotic assembler kernel) GH 5- PowerPC level0 inline assembly kernel 6- support for install() on Mac OS X BA 7- GP function galoisexport IZ 8- logstyle and TeXstyle defaults 9- [GP defaults:] support 'G' suffix (for Giga) (already supported k and M) 10- extend GP command line: once flags (-xxx) are processed, remaining args are taken to be filenames, read upon startup [ _after_ the gprc read statements have been processed ] GH 11- IA64 level0 inline assembly kernel BA 12- GP function galoisidentify and groups identification facility 13- public function GENtoGENstr [ for GP2C ]. (was private: gtostr()) 14- function coefs_to_vec() NS 15- support for Qt graphical library [ hi-res plot ] Remove 1- remove emacs/compile [ integrated in Makefile ] 2- src/kernel/sparcv[89] 3- config/MANIFEST [ now built dynamically ] 4- config/Makefile.DLLs [ use recent libtool instead of dirty hacks ] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.5 (released 11/02/2003): Fixed 1- [bnfinit:] typo in be_honest() --> SEGV when cbach2 > cbach [from 2.2.4] 2- apprpadic() when p = 2 (could not work) + typos 3- typo in gphelp [detex mode]: ubiquitous "var" in translation [from 2.2.4] 4- typo in var_make_safe() [ protecting user variables after trapped "stack overflow" ] --> possible SEGV [from 2.2.4] BA 5- [Configure:] add -lm -lc to EXTRADLLDFLAGS, not DLLDFLAGS 6- typo in gp_main_loop: avma not restored properly after allocatemem. [from 2.2.4] 7- typo in [imag|real]_be_honest: SEGV in quadclassunit(D,,[c,c2]), c2 > c [from 2.2.4] 8- typo in rnfisnorminit (pol_up) 9- at \p28: x = (1. + 10^-28) - 1; for (j=1, 100, x = (x-10^-28) + 10^-28) now x has 200 words of precision 10- stack corruption in addition (t_INT + t_PADIC) 11- factorpadic(z+y,2,4) --> SEGV 12- wrong result in idealchinese when the y_i had denominator BA 13- sigma(n,-1) output a wrong result. BA 14- inline alpha assembler broken (registers clobbered) GH 15- polsturm(1, 0, 1) ---> error [ return 0! ] 16- "break loop" did not react correctly to allocatemem() read from a file with \r (stopped reading file right away) 17- matker(x, 1): internal loop forgot a pointer when garbage collecting --> SEGV (or weird error, e.g division by 0) 18- ideallog(nfinit(y),2,idealstar(nfinit(y),4,1)) --> SEGV [bad input] 19- ellrootno(ellinit([0,-25,0,-1250,0])) --> SEGV [from 2.2.3] 20- typo in elllocalred (wrong Tamagawa number, case I0). [from 2.2.4] 21- idealtwoelt(nfinit(y),2/3,1) --> SEGV [bad input] 22- for transcendental function f and polynomial p, f(p) only gave seriesprecision significant terms when val(p) = 0 23- Ser(a/b) --> 1 + O(x^16) (!!) 24- (x^2)^(1/2) --> error 25- idealnorm(nfinit(y),matdiagonal([1+I])) --> SEGV [bad input] 26- polylog(10,x^10) --> O(x^6) at \ps16 [ 16 significant terms ?] --> x^10 + O(x^21) at \ps 21 [missing x^20 term] 27- nffactor/nfroots: SEGV over Q 28- missing sanity checks in install() [ did not check the parser code ] 29- typo in nilord() [lg-->lgefint]: nfdisc() didn't work on 64bit HP 30- ellisoncurve(ellinit([0,0,0,0,1]),[1/2-sqrt(3)/2*I,0]) --> 0 31- type 'gphelp' from command line: carriage return is missing 32- typo in LLL_cmbf() [ rare oo loop in factor() over Z[X] ] IS 33- [HPUX:] should compile with cc -Ae, not -Aa 34- excessive memory usage in bnrstark() [ InitPrimes ] 35- bessel[jk](t_SER) not implemented around a!=0, but gave (bogus) results [output error message for now] IZ 36- [OS/2:] rename static functions _core[2] (conflict with stdlib.h) IZ 37- [OS/2:] ^C would only work once 38- algdep(.1^5,1,10) --> 1 39- { "a b" } \\ with an explicit \n produced "ab", whereas whitespace in strings is to be retained. 40- inconsistencies in return type from lindep [t_VEC/t_COL]. 41- possible oo loop in ellap [ typo in appell1 ] 42- made PSLQ (algdep/lindep) insensitive to 'realprecision' [use precision of the input] 43- nfinit(x^2-4*3,4) --> SEGV 44- Compilation failure on ORIGIN + Irix: rename 'sgi' --> 'SG' in basemath/galconj.c 45- '\r a' where file 'a' is empty --> "a is not a GP binary file". 46- make sure qflll[gram](x) never fails when x has exact entries [ much faster than qflll(x,1) when the entries are large ] 47- increase subFB sooner in buchall() + add GC in Q_denom { bnfinit(x^8 - 4*x^7 + 462*x^6 - 1372*x^5 + 85789*x^4 - 169296*x^3 + 7540560*x^2 - 7456140*x + 263038707) } took a long time, then overflowed the stack 48- make test-kernel did not work anymore (prototype error in kerntest.c) 49- overflow in u_FpM_gauss (oo loop in ZM_inv for huge matrices) 50- polcoeff(1+O(x^2),1,y) --> SEGV 51- content(y/x) --> 1 [ should be y ] 52- divrem(x,2) --> x/2 instead of [x/2, 0]~ 53- divrem([1.,2],x) --> stack corruption 54- ff(n)=local(v=[],w=[]);n f(n)=n ff(f(n))=n --> error (OK) + SEGV on Linux (same data freed twice) 55- qflll(matrix(2,3,x,y,x+y)) --> SEGV IZ 56- default(primelimit, 2156858852) --> SEGV and other signed/unsigned conversion problems. IZ 57- printtex("x1") and printtex("x_1") gave same output IZ 58- printtex(t_STR) [ protect special characters, eg ~ or \ ] IZ 59- [readline:] support old versions (1.0), try to recover from mismatched headers wrt. library, report version of loaded library in gp header [as opposed to library version at Configure time] BA 60- add "const" keyword to allow building with g++ 61- agm(1+x,2+x) --> oo loop 62- lindep([1,0]) --> error [ problem with trivial cases in PSLQ ] 63- wrong reconstruction bounds in nffactor 64- short help message for isprime/ispseudoprime 65- issquare(t_FRAC or t_RFRAC, &x) did not work [ worked without &x ] 66- nfgaloisconj(x^2+1,4, 0) --> SEGV [ bad input ] 67- typo in quadhilbert(-D): required O(D) memory instead of O(sqrt(D)) 68- all signed/unsigned compiler warnings 69- \p29, tan(Pi/2) --> "division by zero". Made error more explicit 70- nfnewprec(nfinit(x,3)) --> SEGV 71- bnrconductorofchar(0,0)--> SEGV [bad input] 72- qfjacobi( non-square matrix ) --> SEGV [bad input] 73- matmultodiagonal([;],matrix(0,1)); --> SEGV [bad input] 74- [GP, trap:] prevent oo recursion if default exception handler itself raises an exception 75- allow qfbred(,2) [don't update Shanks's distance] also for definite forms [ignore flag]. 76- lex(x,"y") --> error [ should be -1 ] 77- algdep(0,1) --> 0 [ should be x ] 78- log(1, AGM) --> oo loop 79- [Configure+gcc] remove useless -m* arguments from CFLAGS [ obsolete ] 80- improper rounding when printing floats: 1.2 --> 1.199999999 81- [default:] realprecision was allowed to be 0, and then treated as 9. 82- Precision loss in inputs of large exponent: 1e100000 -->9.99999824 E99999 83- quadgen / quadpoly accepted square inputs --> weird bugs later. 84- poldegree(x^2 / y^4, y) --> -1 85- setrand(178);quadclassunit(82421) --> 2 instead of 1 [from 2.2.4:] 86- polroots( Pol(subst([1,0,4*x,0,2*x^2+24,0,16*x,0,16],x,10^2589) ) --> division by zero [ double overflow ] 87- LLL-reduction over polynomial rings (almost always failed) 88- (x/y)*(y/x) --> y/y 89- fix pari_init_stackcheck to avoid bogus "deep recursion" messages on broken machines. 90- reused invalid (gerepile'd) pointer in mat_ideal_two_elt. Changed: 1- "not enough precomputed primes": output largest needed p if available XR 2- factorpadic so that factorback gives back the original polynomial, up to a power of p 3- type of avma, bot, top to 'pari_sp' (pari stack pointer) [does not break existing code] 4- [library:] make floating point assignments round the inputs (used to truncate) 5- ensure proper rounding in divrr/mulrr() [ important for numbers input in scientific format, e.g. 1e20 ] BA 6- moved internals of mppgcd to mp.c/gcdii BA 7- moved internals of genrand to mp.c/randomi BA 8- renamed mymyrand --> pari_rand31 9- bnrstark: use partial factorization of discriminant when (pol)reducing the polynomial [could embark into hopeless factorizations] 10- primedec: improved search for uniformizers when p | index IZ 11- [OS/2:] improve dlopen(NULL,...) IZ 12- [OS/2:] enable dynamic-linking build IZ 13- [OS/2:] use same CFLAGS as under Linux IZ 14- when using external prettyprinter, write in raw format to logfile [not in TeX format sent to prettyprinter] IZ 15- don't output pseudo-TeX sequences to logfile when using external prettyprinter (raw format) IZ 16- make X11.builtin-gnuplot-dynamic the default graphic library. IZ 17- allow changing the gnuplot DLL name for gnuplot-dynamic at Configure-time e.g. Configure --graphic=gnuplot-dynamic,gnpltdrw 18- allow Vecsmall(t_STR) 19- polredabs heuristic (try harder to detect subfields). Ex: try it on polcompositum(x^2 - d, polcyclo(11)); MSo20- simplified polzagier() DS 21- improvements in elltors() [ faster torsion bound, check bound > 1 before checking precision ] 22- minor improvements in plindep() [p-adic lindep/algdep] 23- 'make all' now builds the documentation [ that way, 'make install' need not run a bunch of TeX commands as root ] 24- improved idealaddtoone/idealchinese/idealapprfact [use dedicated HNF variant + simpler uniformizers in idealapprfact] 25- rnfkummer: do not return rational coeffs as POLMODs: -1, not Mod(-1,pol) 26- improved idealval() 27- simplified element_reduce, idealmodidele (redideal), compute_raygen (create bnr.gen): faster, smaller elements 28- new algorithm for conductor() and bnrdisc() [much faster, does not need bnr.gen]: find minimal f such that P_{1,f}(K) \subset H, computations are done for a fixed modulus F instead of computing the image of H in Cl_f(K) for many f | F. IZ 29- improve portability of make_vi_tags (cf 'make ctags') 30- using install() twice on the same symbol now updates the prototype code 31- re-enable ranlib support (disabled in 2.0.13) 32- declare first argument in pariputs[f] as 'const char*' 33- enabled Karatsuba multiplication for t_REAL 34- broken Configure into many smaller files (config/get_*) 35- let gphelp write all cross-references as [label:LABELNAME] (was [??]) IZ 36- cache optimization in initprimes() [ default(primelimit,.) ] 37- Str() now takes multiple arguments as print(). Str(,1) replaced by Strexpand() 38- prototype of strtoGENstr() [remove flag] 39- remove -Wno-implicit from CFLAGS 40- prototype code 's*' now produces a t_VEC of GENs [callee's business to call GENtostr] (used to be a NULL-terminated list) 41- [gphelp:] if perl not available, don't pretend extended help is. 42- try harder to detect precision problems in floating point lllgram 43- [ix86 kernel:] macroified bfffo() 44- made all GEN macros return signed types [ had inadvertently switched to ulong as a side effect of some other change, long ago ] BA 45- split kernel Makefiles in MakeLVL0 and MakeLVL1. BA 46- --disable-kernel Configure option replaced by --kernel=none 47- compute_polrel() [rnfkummer] was very slow for [L:K] > 5 (compute Newton sums directly) 48- simplified fincke_pohst() [don't recompute gram_matrix] 49- faster trueeta(), faster quadhilbert(D < 0) 50- faster isprime (trial divide by small primes, recognize 1-word moduli) 51- ellheight: use Mestre's AGM to compute Archimedean height 52- poldegree(0) is now VERYBIGINT 53- alpha + gcc: compile with -O3 [ since F14 fixed the optimizer "bugs" ] Added: 1- [TeXmacs:] contextual completion () BA 2- routines ishiftr, gfloor2n, isqrti, randomi 3- routine random_bits BA 4- [Configure:] --builddir flag IZ 5- File README.os2 6- Allow nfroots(, P) [ roots in Q ] 7- routines Strexpand(), Strtex() IZ 8- detect oo recursion on OS/2 [as on Unix systems] (cf STACK_CHECK) RS 9- routine numbpart() BA 10- GMP kernel BA 11- --kernel Configure option IZ 12- allow an arbitrary polynomial as a 2nd argument to subst() 13- many files in config/ [ from Configure ] Removed 1- macro definition BITS_IN_RANDOM (useless) 2- appr_reduce() [static base4.c]: lllreducemodmatrix does the same. Faster. 3- [useless,undocumented]: idealoplll, idealmullll, idealdivlll 4- 68k assembler kernel [ unmaintained, obsoleted by the GMP kernel ] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.4 (released 12/09/2002): Fixed 1- add default 'new_galois_format' to make 2.2.3 C-22 optional (by default, old format will be used, preserving compatibility) BA 2- FreeBSD: DL_DFLT_NAME value was incorrect 3- Configure: TIOCGWINSZ not detected on Linux BA 4- FpV_roots_to_pol not reduced when applied to a singleton 5- (a.x = [a]); "a".x ---> [a] \\ should be ["a"] 6- (a.x = [a]); print("a".x) ---> a0.E-28x \\ should be ["a"] 7- (a.x = [a]); 1.x ---> error \\ should be [1] 8- wrong rnfidealnorm[rel | abs] (wrong result if O_L not free O_K-module) 9- gcd(x + 1, x + 1/2) --> 1 \\ should be 1/2 [introduced in 2.2.1] 10- gcd for multivariate polynomials over finite fields slower than in characteristic 0 11- [library:] typo in vpariputs: pariputsf("%Z%Z",x,y) did not work (prints x and address of y) IZ 12- [gnuplot + dynamic link:] allow building even when dlopen() not available 13- [CVS:] warnings about unknown files (added .cvsignore files) 14- f()=return \\ return "void" g()=return(f()) \\ return eval("void") = 0 now g() returns "void" also 15- f(x=11,y=x)=local(t=ff(),u=t);1 --> parse error 16- conjvec([[],[],[]]) --> SEGV 17- galoisisabelian(x) --> SEGV 18- nfeltreducemodpr(nfinit(x),1,1) --> SEGV 19- idealmul(nf, principal ideal, prime ideal) returned wrong result [introduced sometime in 2.2] 20- elltors(ellinit([...], 1)) --> SEGV 21- try to make sure life of GP variables is not too short. Was: v = [0,0]; v + [v=0,v=0] --> SEGV u = Mod(x*Mod(1,2),polcyclo(25)*Mod(1,2)); sum(i=1,4,u=u^32) --> SEGV 22- typo in to_Fp_simple [ bnfcertify(bnfinit(x^2-40!)) --> type error ] 23- memory leak in gp when handling '&' arguments 24- removed hack in gcopy [ did not reset the isclone() flag because gunclone checks isonstack(). But other routines may want to use it ]. 25- apparent oo loop in bnfcertify [when computing lower bound for regulator] 26- ideallistarch(nfinit(x),[1,1],0); --> SEGV [bad input] 27- factor(x-I) --> x - #<16382> 28- ellsigma(...,matid(1)) --> SEGV [bad input] 29- ideleprincipal([],1) --> SEGV [bad input] 30- factorback(matid(1),nfinit(x)) --> SEGV [bad input] 31- incomplete help message for vecsort 32- polredabs fails to reduce x^8-2*x^7-34*x^6+78*x^5+265*x^4-628*x^3-389*x^2+1237*x-449 [typo in chk_gen_init: skipfirst not initialized properly] MW 33- (recent) typo in localred (char 2) 34- 2.2.3-C20 had broken backward compatibility: restore [inefficient, useless] previous output of nfelt*modpr routines 35- idealappr(nfinit(y),matid(2),1) --> SEGV [bad input] 36- sqrtn(0,...) ---> error 37- galoisinit(x^4 + 5264*x^3 + 8034856*x^2 + 4205424384*x + 504485485632) --> weird error 38- qfsign([;]) --> SEGV MW 39- torsion group of [0,0,0,-6648,208633] reported as C2 instead of C6 40- bnfinit: very rare stack corruption 41- bnfinit: used too much memory when needing huge number of relations [when computing fundamental units] 42- bnrL1(bnr with conductor 1) --> SEGV 43- "impossible inverse modulo ..." when using addprimes() + ROUND 2 MSo44- [gp: \x] missing 'break' statement in escape() 45- wrong bound in nf_LLL_cmbf (nffactor) [no counter example to the old bound, but proof was wrong anyway...] 46- [gp:] memory leak when assigning to multidimensional arrays (x[i][j]=1) 47- added user-friendly error message if Configure not run properly + fix INSTALL.tex about make gp.dbg / gp.prf 48- matcompanion(x*y) --> weird error 49- typos in hilbert(), e.g hilbert(Mod(1,2), y) --> SEGV, hilbert(-1+O(2^3), 12 + O(2^3)) accepted wheras 2-adic precision too low to decide BA 50- [FreeBSD:] PORTOBJFORMAT undefined by the system --> Configure fails 51- rnfisnorm() [errors, SEGV]. Had to change the prototype. BA 52- Oxxx/Makefile was not compatible with BSD make. 53- errors in files read from .gprc, containing trap() --> SEGV 54- bezoutres(Pol(sin(x)+Pi),Pol(cos(x))) --> "bug in subresext" 55- nfsubfields had a different output format when using galoissubfieds 56- polcoeff(1/x, -3) --> SEGV 57- (-2/x)/(-1/x) --> -2/-1 BA 58- [GP internals:] trap() had an invalid prototype [DI,DI] 59- M[,2][1]=1 --> error; M[1,][2]=1 --> no effect [ now <==> M[1,2]=1 ] 60- [GP:] newline in multiline comments /* */ was not ignored 61- [GP:] when using default 'colors' for input at \gn>1, first debugging msg could be colored 62- [GP:] in break loop, trailing ; was ignored (all results were printed) XR 63- smarter precision increase in update_alpha() (ROUND 4) [stick to padics don't go over Z] Ex: factorpadic(polzagier(18,3), 2, 30) much faster than before. 64- E=ellinit([0,0,0,-10301051460877581926458079712219,-12725370882271967125361344545020920373899020890]); ellap(E,1167254453) --> wrong result 65- factor(x^2 + I*1.) --> SEGV 66- when printing x < 0 t_REAL, was rounded in the wrong direction 67- [WINCE port:] small and SID are already defined in windows.h Changed 1- remove most global variables from gp.c (put them in struct gp_data). 2- use better bounds for size of factors in nffactor() 3- tuning for van Hoeij's factorizer (factor + nffactor) nffactor: call factornf when deg(pol) << deg(nf) + remove a priori overlift for d-1/d-2 test [major overkill] 4- automatic concatenation for strings: use longest match for expression. print("a"[1]) is not valid since "a" is not a vector print("a", [1]) prints 'a[1]' IZ 5- [gphelp:] allow uninstalled operation from $TOPDIR or $TOPDIR/Oarch IZ 6- [gphelp:] better error messages in case TeX compilation fails 7- [development version:] add version number for this file to the gp header when using CVS IZ 8- [library:] unified access to diffptr (NEXT_PRIME_VIADIFF macro) 9- buchall: re-use the same random seed when doubling prec (for units) 10- major cleanup in thue / thueinit 11- major improvements in rnfkummer (use elements in factored form): much faster, give smaller elements, allow arbitrary prime degree 12- improved quadray(D < 0) when relative degree is huge 13- improved bnfisprincipal when class group large: use factorisation (+idealred) instead of arch. components (require much less precision) 14- [library:] allow trapping invmoder and recovering the offending INTMOD 15- improved factor over Z[X] for _huge_ degrees (factorizations mod p) 16- change in ordering for primedec output [use cmp_prime_over_p] 17- [library:] moved (formerly) gp-specific write* and print* to libpari 18- input format to rnfisnorm() [use rnfisnorminit] 19- [GP:] break loop prompt from '>' to 'break>' 20- [GP:] don't get out of break loop after \r 21- type f(x=1)=; twice ---> x = 1 22- [trap:] the way default error handlers operate, how to get out of break loops (see section 2.7 of manual) Added BA 1- Add PARI_VERSION and PARI_VERSION_CODE to paricfg.h BA 2- Add pari_release at top of dft.Config.in 3- rnfpolredabs: flag to use partial factorization 4- [gprc:] test against VERSION number in .gprc 5- [gprc:] multiline constructs IZ 6- mnemonics for flags 7- internal flag nf_GEN_IF_PRINCIPAL to bnfisprincipal [isprincipalall] 8- routine rnfisnorminit() BA 9- [Makefile:] bzdist target 10- [library:] CATCH / TRY mechanism [ encapsulate err_catch ] Removed 1- (useless, undocumented) macros buchgen*, buchinit* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.3 (released 10/06/2002): Fixed 1- bnrinit(bnfinit(subst(polsubcyclo(89,8),x,-x)),4) --> SEGV [make sure isprincipalfact is used in makecygen, even in case of precision problems] 2- bnrisprincipal --> warning + "not an element in ..." [missing nf_FORCE] 3- oo loop in isprincipalfact when increasing bnf precision 4- stack corruption in ellap (LARGE p) 5- zeta(s) destroyed the Bernoulli cache when using the functional equation 6- oo loop in random_relation (called from bnfinit) 7- fixed lower bound for p in nfsubfields (could get oo loop: pol never squarefree mod p) 8- [Vecsmall([1, 2])][1][2][1] --> SEGV 9- typo in t_FRAC + t_PADIC [only numerator of t_FRAC used] 10- factorback(t,nfinit(x)) --> SEGV IZ 11- shift(x > 0,, flag!=0) didn't act as the docs said [flag now ignored] 12- lindep(Vec(x^48)) --> oo loop 13- could get NaN in max_modulus (polroots) --> havoc later 14- missing normalizepol() in centermod(t_POL,) 15- [Follow-up to 2.2.2-F10] even more recent pdftex failed again 16- not enough GC when printing a huge t_PADIC 17- factorpadic(x*(x+1),3,10) would corrupt polx --> SEGV later 18- delayed carry treated improperly in red_montgomery 19- F() = 0; local(x) ==> confusing error message IZ 20- OS/2: make bench didn't work [env wouldn't start shell scripts] BA 21- sqrtn(Mod(1,7),2,&z)-->z=1 should be -1 HC 22- Standard transcental functions exp, sin, cos, ^, *, are now orders of magnitude faster for t_POL arguments of small degree. HC 23- fixed a severe bug in p-adic/integer addition (1+3^4+O(3^10))+3 didn't work. HC 24- Corrected p-adic initell. 25- ellj / eta (t_SER) truncated result to seriesprecision 26- possible overflow in u_FpM_gauss (from ZM_inv) 27- various problems with C++ compilers 28- polredabs could fail to reduce "obvious" input, e.g x^2 + n*x + n^2 29- gcd(x,y,1) didn't check its arguments 30- typo in elltors: could forget a point of order 2 31- gdivgs(t_RFRAC,x) incorrect (if numerator had denominator) 32- serreverse(O(x) or x + O(x^2)) --> SEGV 33- dbltor(0) returned 2^-308, instead of 10^-308 34- precision problems in thue/thueinit setrand(5);tnf=thueinit(x^3 + x^2 - 43690*x - 3529208) --> error in mplog 35- typo in bnfnarrow ("impossible inverse") 36- subst(x,x^0,x) --> floating point exception ISo37- many typos in the documentation 38- [DOS/Windows]: incorrect conversion between 'double' and t_REAL 39- polrootspadic(4*x^2-1,2,2) --> impossible inverse: Mod(2, 16). [specific to 2, and non-monic equations] 40- discrepancy between bnfsunit output and docs [ bnfS[5][2] was t_MAT ] 41- matdet: pivoting strategy incorrectly chosen ("incorrect type in gexpo") 42- polcompositum output ordering depended on random seed 43- plotrecthraw(0,[0]) --> SEGV 44- plothraw([],[]) --> SEGV IZ 45- ix86 inline assembler compilation problem [divll] XR 46- forgotten case in Round4 [ nfdisc(x^12-10*x^11-57*x^10+740*x^9+353*x^8-16130*x^7+17749*x^6+100120*x^5-108466*x^4-292200*x^3+128380*x^2+380800*x+133112) --> impossible inverse: Mod(2, ...) ] 47- sin(1e-100) ---> 9.999999999999999999735998397 E-101 [ precision loss ] 48- idealpow(nf,x, n < 0, 1) did not reduce the result 49- gcd(0, -1) --> -1, content([0, Pi]) --> 3.14, content([0,Pi,Pi]) --> 1 BA 50- compilation problem on OSF (RTLD_GLOBAL undefined) BA 51- [X-Windows] hi-res plot: window not redrawn properly (BackingStore pb) 52- problems with tex2mail output (wrong alignment, wrong colors) 53- contfrac(sin(Pi/4),,2) --> impossible assignment 54- oo recursion in gaffect(t_POL, scalar) 55- content([-1]) was -1 [ should be 1 ] 56- stack corruption in u_FpV_polint (used by modular bivariate resultant) 57- polroots() used too high a precision when checking errors a posteriori (--> slow) 58- contfrac(1/x) --> SEGV 59- typo in sinh(0) --> wrong zero exponent 60- exp(O(x^-1)) = O(x^(-1)) [ouch...] 61- dilog(O(x^10)) = O(1) 62- cosh(O(1)) --> division by 0 63- sqrt(4*x^2) --> not an integer exponent for non invertible series in gpow 64- besselj(0,O(1)) [or besseli] --> precision<=0 in gprec. 65- O(1)' --> O(x^-1) 66- gcd(O(2^1), O(2^10)) --> O(2^10) 67- polrootspadic(x^2+8*x+4,2,2) --> "impossible assignment" 68- one could write() an object to a binary file, corrupting it MW 69- ellap(ellinit([0,0,1,-7077,235516]), 1075060289) --> "zero argument in an arithmetic function" MW 70- ellap(ellinit([0,0,1,-7077,235516]),1135392007) --> SEGV BA 71- user's manual index truncated if LANG=fr_FR 72- lex(string1, string2) could return something not in {-1,0,1} 73- bnfisprincipal(bnf,x, 0) was not instantaneous when bnf.no = 1 74- no GC in poleval 75- make clean did not remove libpari-2.2.* 76- incorrect result in gaffsg(s < 0, t_PADIC) [ wrong valuation ] Changed BA 1- improved Fp_isom IZ 2- remove all dependance on __OPTIMIZE__ for inlining [cf 2.0.14 F-24] 3- implementation of psi() [very slow + wrong results at low accuracy] 4- cleaned up forvec() [no more global variables] 5- improvements in bnrstark (precompute common data) BA 6- improved ffinit() 7- rewrote time-critical parts of bnrstark 8- all 'input filter' code removed from GP. es.c:filtre() now handles the full filtering [and has become reentrant] 9- isprime() now guarantees primality BA 10- improved polsubcyclo() BA 11- new interface for galoissubcyclo HC 12- gamma function for integral/rational arguments 13- faster factornf / nfgcd 14- removed readline-specific code from gp.c 15- allow bnrstark over Q 16- 'subgroup' argument made optional in bnrL1, bnrstark, rnfkummer 17- use relative van Hoeij algorithm in nffactor [can handle huge number of modular factors] 18- rewrote factorff() to use new modular functions 19- rewrote primedec() to use new modular functions 20- rewrote most *modpr functions 21- modified diagnostics for integral LLL to match floating point version 22- INCOMPATIBILITY: polgalois(); changed 3rd component of result so that it gives the numbering among all transitive subgroups of S_n [ was ad hoc up to 7, then as described above for n >= 8 ] 23- INCOMPATIBILITY: nf.zk is now T2-LLL-reduced 24- idealtwoelt was very slow when a small prime with many divisors divided the index (use approximation theorem) 25- content(scalar) = abs(scalar) [when it makes sense] 26- changed the interface to ispseudoprime and isprime 27- [internal] element_muli: check input is consistent 28- rewrote all LLL algorithms (use Householder, not Gram-Schmidt; do not use Gram matrix; unified code). 29- INCOMPATIBILITY: the internal components of nf[5] have changed (MC and T2 not needed anymore) 30- INCOMPATIBILITY: [library] polred & polredabs do not take a 'prec' argument anymore 31- unified nfinit, polred* [use dedicated structs internally] 32- rnfconductor(..., 1) doesn't need GRH anymore 33- extracted FpXQ_gener from idealstar 34- allow more types in gdivround 35- improved root_bound (first step in factor() over Z[X]) for huge pols. 36- faster bernfrac / bernvec 37- INCOMPATIBILITY: removed gentimer() / genmsgtimer(). Use TIMER/msgTIMER 38- let nfsubfields call galoissubfields (much faster when field is Galois) 39- Configure (locatelib): don't look for lib*.so.x [ pb on Linux with [readline | ncurses]-devel.rpm. Added 1- mplog2() function --> faster mplog() 2- gcd for Gaussian integers HC 3- APRCL primality test 4- (strong) Lucas primality test + Baillie-Pomerance-Selfridge-Wagstaff test BA 5- Facilities for permutation groups (perm.c). BA 6- New functions galoissubgroups, galoisubfields. HC 7- Implemented all Bessel functions J, I, N, K, H1, H2, and Bessel functions for power series and polynomials. HC 8- Implemented PSLQ [preliminary] GTo 9- Implemented Cipolla's algorithm for sqrt(Mod(x, p)) 10- library functions FpM_ker, FpM_deplin, diviiround, centermodii 11- library function gerepileall 12- library functions corepartial, core2partial 13- library functions affui, itou, stor, itor 14- library function lllint_ip (in place) 15- library functions Q_primitive_part, Q_primpart, Q_remove_denom, Q_denom 16- allow polredabs to use a partial factorisation of disc(nf) [as polred, but inconsistent values for flag. Backward compatibility problem here...] 17- routine ellminimalmodel() IZ 18- systems/ directory (currently for OS/2 only) IZ 19- [OS/2:] install() for OS/2 system (using builtin dlopen) IZ 20- gnuplot and X11 are now simultaneously supported %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.2 (released 10/01/2002): Fixed 1- qfbred(Qfb(4, 17, 18)) --> SIGFPE 2- broken compilation in arith.c when CC != gcc 3- nfhilbert (local case pr | 2) expected POLMOD argument without check 4- poldegree(P, t) slow when t != varn(P), and may not work in library mode 5- polrootspadic only worked when leading coeff was a unit 6- paddicappr was very slow (esp. when p was large) 7- Configure: check for 'double endianness' [used for double --> t_REAL conversion]. Previous check was failing on ARM architecture. 8- forsubgroup state not properly restored after ^C 9- libpari.so included symbols from libc without linking it explicitly (Debian requirement, and cleaner anyway) 10- recent pdftex failed to compile users.tex (\pdfannotlink undefined) 11- !nf.sign[1] was parsed as (!nf.sign)[1] 12- matrix(0,1) --> "identical index variables in matrix" [from 2.2.1 F48] 13- bnfinit could miss some relations in the "small norm" phase 14- x % y incorrect when y < 0 inexact (2 % -3. --> -1.) 15- typo in gcdreal (result < 0) [introduced in 2.2.1] 16- some obscure problems in rnfkummer 17- not enough GC in hnflll 18- sqrt(25 + O(2^5))^2 - 25 = O(2^4) 19- not enough GC when writing a t_PADIC 20- user member functions were very slow (unnecessary copy) 21- cd Oxxx; make -j4 bench ran things in the wrong order 22- poltchebi, pollegendre gave bogus output for negative degrees 23- possible SEGV or oo loop in polrootsmod when p not a prime 24- nfnewprec(bnf) could change bnf.gen (due to round-off errors) 25- SEGV in gcd(x,y) when operands have coeffs of the form Mod(t_INT,t_POL) 26- not enough GC in poldivres (= t_POL % t_POL) 27- issquare(Mod(3,27)) = 1 [from 2.2.1 C 10] 28- [BUG] message in 'elliptic' bench [made polroots more canonical] Changed 1- allow compressing *.dvi files for the online help system 2- index bound was restricted to MAXLONG in subgrouplist. Made it a GEN 3- try to guess correct precision earlier in polgalois/polroots 4- allow GP pointers to 'matrix components', e.g issquare(25,&x[i][j]) 5- changed assignment semantics to make it closer to C: x = y understood as (evaluate Y:=y, then set x:=Y), e.g i=0; i += (i=2) sets i to 4 (was 2) 6- output VECSMALLs as 'Vecsmall([...])' 7- more efficient polcoeff [also: made it independent of MAXVARN] 8- retuned bnfinit (let subfactorbase increase further): setrand(1);bnfinit(x^4 + 1159*x^2 + 335241) would never finish. 9- specified precisely lex() [see manual]. Now: lex([0,0],[0]) = 1 (was -1), lex(0,[0]) = -1 (was 0) 10- allow factorback(x, e) for prod x[i]^e[i] 11- don't store empty lines in history [cf 2.2.1 F57] 12- extend x \ y, x \/ y and divrem(x,y) XR 13- improvements in bnrstark (try harder to find modulus, need less memory) 14- global(x): ignore if x already global (used to raise a warning) BA 15- install: add RTLD_GLOBAL to dlopen flags [so that symbols can be used in other .so] 16- removed hack in gp_init.c [used "constant default args" to call print0] Added BA 1- New function 'vectorsmall'. 2- allow setting variable in divrem 3- GP operator #l for length(l) 4- a warning in zsign ("increase precision?") when dubious result 5- Montgomery reduction (only used in powmodulo() for now) 6- [experimental] basic tuning utilities (src/test/tune.c) [make tune] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.1 (released 18/10/2001): Fixed 1- typo in factornf (factor of degree 3 --> error message) 2- rnflllgram(), idealinv() didn't check their arguments 3- [readline] \r would complete using files matching r* 4- wrong result in ZY_ZXY_resultant when degree dropped in ERS 5- factor(x^2 + I*1.) --> stack corruption 6- \r directory was silently accepted 7- check arguments in polcompositum() TH 8- [Cygwin:] fixed paths for readline on cygwin 1.* XR 9- possible overflow in ComputeCoeff [ bnrstark() ] 10- numtoperm(2,x) --> SEGV [check arguments now] 11- rnfkummer could fail with "missing units" 12- factornf(P, non-monic t) --> error 13- forsubgroup/subgrouplist didn't check their arguments nor accepted SNF matrices XR 14- typo in nilord4 --> SEGV, e.g. nfdisc(x^16-363*x^14+53550*x^12-4091823*x^10+170172414*x^8 \ -3663509067*x^6+33703350345*x^4-63300912912*x^2+32451860736) 15- some messages didn't distinguish between MBytes and millions of Bytes 16- typo in BuildTree [hensel lift]: SEGV 17- (rare) oo loop in polroots, e.g. x^5-2*x^4-32*x^3+72*x^2+218*x-491 18- oo loop in ellpointtoz on certain rare inputs 19- stack corruption in factorff BA 20- better interface for galoissubcyclo BA 21- galoisfixedfield(,,2) now works with non Galois subfields BA 22- nfgaloisconj now use `d-1'-test + better strategy BA 23- fix accuracy problems in vandermondeinverse 24- missed some simplifications when handling multivariate t_RFRAC 25- [Cygwin:] incorrect default 'path' (used : instead of ;) 26- element_sqr didn't check its arguments (SEGV if bad input) 27- possible stack corruption in polroots (+ improved GC there) 28- typo in nfsubfields (incorrect bound: could miss a subfield) 29- typo in zsimpjoin (concat error in bnrdisclist, intr. in 2.2.0) IZ 30- typo in Configure [rl_save_prompt and _eprintf not found in target libs] MD 31- oo loop in ellap [uninitialized array length in apell1] 32- stack corruption in addfrac [wrong result for large denominators] MD 33- resmod2n [called from powmodulo] could return unnormalized integers 34- not enough GC in nfinit for huge degrees [get_mul_table] 35- intformal(1/2/t^2) --> apparent oo loop 36- polredabs(degree 1 polynomial) --> x [could be very slow] 37- polredabs() could use a basis which was not LLL reduced BA 38- pariformats (e.g %Z) incorrect on 64bit machines 39- polhensellift(x,[x,1],2,2) --> "bug in multiplication" 40- glitches in readline completion (random() * ne inserted args) IZ 41- CLK_TCK may reside in time.h 42- misleading definition for ?omega / ?bigomega 43- on \q, "Good bye" --> Goodbye 44- install() accepted gpnames which were not valid identifiers 45- bnfinit(x^4+65,,[.1]) --> SEGV (whenever c < c2) 46- when host badily configured (~ not expanded), gp would die on startup XR 47- factorpadic(, not a prime, ) --> SEGV 48- matrix(2,2,i,i, ...) allowed, with weird result BA 49- better arguments checking for galoisfixedfield 50- psi(I) --> incorrect type in rtodbl XR 51- increase precision automatically when needed in quadhilbertreal 52- idealstar(bnfinit(polcyclo(5)),11).clgp --> stack error 53- default(format,"g0.4"); 3./10 --> 0.300004577 [now: 0.3000] 54- subst() didn't check its arguments (e.g SEGV on t_STR) 55- qfbclassno(x < 0): wrong algo when x non fundamental 56- obscure bugs with types FRACN/RFRACN [when simplifies to INT/POL] IZ 57- readline history: while inputing continuation lines, the partial command was not put into history until full command was run 58- not enough GC in polroots (dft) for huge degrees 59- Cygwin: don't try to build gp-dyn.exe [crashes] 60- use vsnprintf to fix a long-standing bug in PARI output (using formats) used a fixed-length buffer that could overflow. If vsnprintf is not found by Configure, the bug remains. Changed 1- removed useless parameter prec in many bnr* and rnf* functions 2- major update of bnr* functions [use elements in factored form] 3- use /tmp instead of /var/tmp as default tmp directory [faster on Solaris] BA 4- Fp_PHlog (Pohlig-Hellman) can use a factorization of the subgroup order 5- major update of buchall() [bnfinit]: accurate precision increase, use multiplicative archimedean components (fewer logs), cleanup 6- [libpari:] rename permute/permuteInv to GP names numtoperm/permtonum 7- scalar + [;] --> error [made it [;]] BA 8- factorback, chinese, lcm and gcd now accept a single vector 9- Use I \cap Z instead of NI in hnfideal_inv 10- improved issquare(t_INTMOD) 11- improved subresultant routines (new function pseudodiv) 12- command-line options to Configure (installation directories) 13- rnfequation: use modular (bivariate) resultant 14- polynomial gcd (srgcd): uses modular algo (modulargcd,nfgcd) if possible 15- unified internal hnf* functions 16- improved nfsubfields [Hensel lift, allow nfsubfields(pol) instead of nf] 17- merged all "integer logarithms" + "safe ceil" functions (mylogint, get_e, floor_bound, myceil) 18- readline: TAB on empty parentheses following a function name has the same effect as M-h (used to insert args). IZ 19- faster computation of prime number table [better cache use] IS 20- obscure compiler bug in rootpol.c:max_modulus() [don't modify tau] 21- make bench ('elliptic'): explained [BUG] message 22- allow lift(t_PADIC) 23- faster polroots for Q of the form P(x^k) 24- allow subst(t, x^n, x) 25- ?user_fun: do not include function text if help available from addhelp [always include it for ??user_fun] 26- default values for used defined function arguments are evaluated when the function is called [used to be "when it's defined"] 27- allow subgrouplist(znstar(5)) [didn't accept groups in general form] 28- taught GP about GP2C-style type declaration [ignored] 29- 0. [realzero()] is now coded on 2 words (was 3, with third one ignored) IZ 30- readline history: lines are remembered as they were input (whitespace was deleted) Added BA 1- function pith() [= pi(x), naive implementation] 2- new target for Makefile: gp.dbg BA 3- library functions FpX_roots_to_pol, FqX_roots_to_pol BA 4- library function FpX_FpXQ_compo (Brent & Kung) 5- library function FpM_inv, FpM_gauss, ZM_inv, QM_inv 6- library function primitive_part IZ 7- readline: allow switching readline editing on/off [for commandtools] IZ 8- readline: F1 has same effect as M-h, and F1F1 as M-H (short/long help) 9- function writebin XR 10- new error message "precer" (precision too low in...) 11- allow minimal handling of t_VECSMALL under GP IZ 12- add error messages (as in err(shier2)) to emacs tag file 13- add error messages (as in err(shier2)) to vi tag file IZ 14- add flag to shift() to enable consistency with 2-complement semantic IZ 15- default 'prompt_cont' for continuation lines IZ 16- default 'readline' to switch readline on/off in readline-able binaries IZ 17- capabilities to 'bittest' (return bitmap, 2-complement arithmetic) GH 18- inline assembler micro-kernel for alpha + recent gcc (at least 2.95.3) Removed 1- obsolete functions twototwo, threetotwo, threetotwo2 XR 2- error message truer2 (superseded by precer) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.0 (released 30/04/2001): Fixed BA 1- gpflog could print some lines twice 2- return() could forget objects on heap 3- polhensellift didn't accept factors which were not squarefree 4- Configure missed some shared libraries (when only .so.version was there) 5- possible symlink attacks against mpqs() 6- internal requests for precision of bnfinit(x) [ = Q ] could yield SEGV 7- compatible = 3 not taken into account when reading a file 8- cbezout(0,0) = 1 (should be 0) 9- when lines > 0, output driver didn't reset properly after user output 10- nfdisc(x^5+2*x^4+3*x^3-3*x^2+122*x-1) --> impossible inverse 11- bug in gcc-2.95 -O3 -fomit-frame-pointer [Linux]: SEGV in quicksqri 12- addrfrac: could return a t_RFRAC whose denominator wasn't a t_POL 13- bnfcertify (zimmertbound): off by two error when reading bound 14- very inefficient Hensel lift (used ideas from Shoup's NTL) 15- incorrect assumption on factor degrees in polcompositum (SEGV in rare cases) 16- Vec(VECSMALL) --> incorrect object 17- galoispermtopol didn't check permutation length (--> SEGV on bad input) XR 18- rnfinit(nf, T) -> bug in multiplication if nf = Q 19- Pol(cotan(x)) -> SEGV 20- factor(tough polynomial over Z[X]) --> possible SEGV when padic precision is increased [e.g factor(polzagier(60,0))] XR 21- bug in ideal bound computation in rnfnormgroup 22- bnrisprincipal(...,y+z) --> SEGV 23- GP could forget about a function whose redefinition was stopped by a syntax error (sometimes with a delay!) 24- bnfisnorm result would include pols in MAXVARN: e.g. Mod(1, #) BA 25- pbs in Fp_factor_irred (factoring over Fq a pol. defined over Fp) 26- missing macros for gphelp (tex-mode) in chapter 5 27- nfsubfields(nfinit(polcyclo(13))) --> impossible inverse Mod(0, 29) 28- argument checks for element_mulid, nf_get_r1 (access to nf.sign) 29- typo in quadhilbertimag (SEGV for very large discriminants) 30- wrong precision used in numerical derivation BA 31- isprime(n < 2, 1 or 2) gave wrong result IZ 32- \r C:\a.gp wouldn't work [ : and \ forbidden... ] BA 33- bad PARI prototypes in init.c [were confusing GP2C] XR 34- nfdisc: fixed cache system in nilord (esp. precision handling) BA 35- nfgaloisconj(polcyclo(40)): accuracy lost nfgaloisconj(polcyclo(11)+1): oo loop IS 36- typo in squfof tuning on 64bit machines 37- -lm doesn't exist on MacOS X BD 38- typo in src/kernel/l0asm.c: ulong not recognized by MSVC IZ 39- TeX quasi-parsing in gphelp 40- ^C in gp would kill an xdvi launched by gphelp via ?? [detach from tty] 41- factor(P in Z[X]): wrong bound used in LLL_cmbf --> "no factor" 42- one extra blank line printed with some error messages [errcontext] 43- no typechecks in subgrouplist and forsubgroup 44- round4 [dbasis]: make sure polmodi gets a polynomial, not an int (SEGV) 45- various typos in rnfkummer (SEGV or 'non-maximal rank in nfhermite') 46- Configure -l (no argument) didn't work anymore BA 47- incorrect quoting in src/make_vi_tags (make ctags) 48- 1/[;] --> error, whereas [;]^-1 --> [;] [ now, allow 1/[;] ] 49- ??real only gave the help on t_REALs, not on real() 50- eigen: "missing eigenspace" [roundoff pb in ker() compared to exact 0] 51- error messages on GP metacommands (\...) indicated wrong context 52- bnr functions might fail with "indefinite matrix in lllgram" [prec pb] 53- nfhilbert(nf,a,b, pr | 2) would give bogus result if nf in variable 0 (x) MD 54- real(1 / (a+quadgen(...)*b)) was a / (a^2 + b^2) [assumed quadgen(-4) !] 55- wrong HNF (reduction not finished) when nblines >> nbcol [hnf(,0) only] 56- rare problem in isprincipal (large non Galois base field)--> wrong result (generators not required) or oo loop. 57- compatibility problems with readline-4.2 (build would fail) BA 58- pari format %Z (pariputsf) treated incorrectly on 64bit machines XR 59- typo in smallvectors (polredabs): possible oo loop Changed 1- DOS distribution archives (GPM removed) XR 2- round 4 algorithm: compute characteristic polynomials via Newton sums XR 3- nffactormod now calls factmod / factmod9 when possible XR 4- don't compute discriminant in nffactor/nfroots + better bounds in nfsqff 5- input loops rewritten (filtre more flexible + unified common code) 6- better modular arithmetic for polynomials (+ uniformized names) 7- bnfinit: "looking hard" part overdone in random relations. Tuned down. XR 8- added flag in rnfconductor to check extension is abelian (under GRH) 9- made Vec("pari") return ["p","a","r","i"] instead of ["pari"] 10- renamed library function gsize() to sizedigit() [conflict with gtk] XR 11- bnrstark: check if N0 is too large (=> computation impossible) IK 12- let readGEN() return NULL when EOF is met (was oo loop) 13- algorithm for zeta(), gamma() [initial GP code by HC] 14- improved rnfnormgroup() [reduce number of calls to isprincipal] IZ 15- flags for OS/2 build + use generic [pre|suf]fix for object files IZ 16- readline: hit_return() would not work after Esc-H extend online help recognition capabilities (Esc h/H, F1) 17- install the whole distribution (see ?12) 18- clean up in the bnrdisclist ray class group internal functions 19- naming scheme for development versions library: libpari-2.2.so.0.0.0 20- new Configure flags --share-prefix, --host 21- allow library functions to return NULL to the GP interpreter 22- let A^-1 and 1/A return a left inverse of A if it exists [A had to be square] 23- retuned factorization over Z[X] (+ "d-1 test" in naive recombination) 24- sort factorpadic() output Added 1- files README.WIN, config/[arch-osname|locatesymbol], doc/tex2mail.1 GN 2- Jebelean extended gcd + rational number reconstruction XR 3- new flag to rnfconductor (check extension is abelian) IZ 4- set of default colors (boldfg) 5- modular polynomial arithmetic ([uni|bi]variate resultant over Z, characteristic polynomial of algebraic numbers, nfgcd). [undocumented, experimental] 6- Pohlig-Hellman discrete log over Fp and nf.zk / pr BA 7- flag to galoissubcyclo (also output conductor) Changed 1- start using the new modular functions [polcompositum] BA 2- sqrtn, aka mpsqrtnmod (modular n-th root) uses Fp_shanks now Removed 1- obsolete undocumented functions oldidealinv, idealinv0 2- buggy function hnfhavas (hnflll is a better alternative) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.1.0 (released 17/11/2000): Fixed 1- non portable \e in es.c (pb with Sun cc) 2- ^C while prettyprinter in action --> gp crash 3- polresultant(a,b,x,2) --> b 4- exp(log(1.+x+y)) --> division by 0 TH 5- support cygwin version 1 6- TeXmacs interface 7- GP parser codes (sqrtint, idealprimedec) 8- trap (break loop) + NO readline + ^C at input time --> exit. 9- qfminim(,,,1) --> nonsensical result (typo) 10- SPARC + gcc-2.97 --> bug in addsmulsi (register reset too soon) 11- trapping allocatemem() could crash GP Changed 1- release PARI under the GNU GPL. Remove COPYRIGHT file, add COPYING =========================================================================== Done for version 2.0.21 (released 27/10/2000): Fixed 1- trap(gdiver2,a,1/0) trap(,a,1/0); trap(gdiver2,a,1/0) --> crash 2- lllgramintern could reduce a wrong lattice (after precision problems) XR 3- not enough GC in bezout() 4- use hnfmodid in ideallllred (work mod I \cap Z, not mod N(I)) IS 5- C++ compilation problem (compl is a C++ operator + casts) 6- factor(x^2 - 16810110*x + 62994937599000) --> division by 0 BA 7- Pocklington-Lehmer didn't stop factorisation after sqrt(N) 8- exp(log(Pi+x+y)*1.) --> SEGV (still gives an error, but a decent one) 9- factorff needed a prime field F_p where p was single precision 10- more digits than were significant could be printed (ex: precision(Pi,1)) 11- rnfisnorm didn't accept vectors on Zk basis as argument 12- [cygwin] fixed timer (always returned 0) IS 13- function prototypes (missing 'extern') 14- quadray(bnf, ...) didn't work when bnf.disc < 0. Could also return a relative equation over an intermediate field 15- deficient argument checks: asinh(2*x-1), agm(1,1-x), zetakinit(2*x-1), idealinv( , wrongtype), nfnewprec([2*x-1]), thueinit(non-monic or degree 1), lcm(x, 0) rnfidealmul(2*x-1,0), galoisfixedfield(2*x-1), qfbnupow(2*x-1, 0), polred([x,x]), bezout(Mod(x,x^2+1),0), numtoperm(-1,0), polred(nf), idealhnf(nf,y+z), factorpadic(,y,), nfelftreduce, rnfsteinitz, idealappr(not an nf, ...): SEGV 16- check variable numbers in algtobasis: nfalgtobasis(nfinit(P(y), x)) 17- factorcantor(x^4 - x^3 - 2*x - 1, 3) --> SEGV [typo!] 18- matsupplement(non-exact entries): fixed zero test (--> |x| < eps) 19- precision(I*1.) --> +oo (should be realprecision) 20- global() could check uninitialized memory 21- default(prettyprinter,"non-existent-file") ---> SIGPIPE and GP crash 22- gamma(1+O(3^2)+x) --> SIGFPE 23- typo in cxgamma (gamma(-4.1+Pi*I/2) --> exponent overflow) 24- Odos/paricfg.h defined PARIINFO incorrectly 25- inconsistenty t_POLMOD specification: Mod(x,y)+16 --> invalid object 26- bnfsunit error (impossible I-->S) when large class group 27- qfminim([;],...) / qfperfection([;]) --> SEGV 28- idealpow(,,,1) only reduced at the end, not after each multiplication 29- typo in zbrent (always used bisection) BA 30- cotan(x) wasn't accepted 31- wrong internal prototype for thetanullk (prec not taken into account) 32- various bugs in gphelp -detex (??\a) 33- trap + ^C + next would interrupt \r or read() IZ 34- external prettyprinter incompatible with colors 35- idealval used much larger numbers than necessary 36- sqrtint very inefficient (computed with full precision all along) 37- bnfisprincipal couldn't deal with some non-Galois fields 38- listcreate allowed creating longer lists than GP could later handle 39- INPUT colors was "leaking out" (affected status messages) 40- idealpowred(, power > 2^32) --> wrong result 41- when lines > 0, output driver didn't reset properly after overflow 42- huge precision losses in bnfinit computations (--> truncation error) 43- mateigen([1,2;3,4]) wouldn't work at default precision 44- leftover debugging statements in gphelp -to_pod 45- zeta(x) didn't always use the precision of x (contrary to the other trans. functions) 46- some Warnings from MIPSPro 7.2.1 compiler (contributed by PM) BA 47- gdiv(SER,POL) --> SEGV when POL has lgef < lg 48- check relative pol is monic before calling a rnf* function XR 49- cleaned up bnrL1 character computations XR 50- round 4: possible problems when increasing p-adic precision 51- stack corruption in mppgcd(huge t_FRAC, huge t_FRAC) BA 52- abs(t_SER) not allowed 53- nfdisc(non monic polynomial,, disc factorization) returned wrong answer 54- rnfidealnormrel(rnfinit(nfinit(y^2-2),x),2) --> SIGBUS 55- hardcoded paths in a few scripts (tex2mail, gpflog, make_vi_tags) Changed BA 1- more efficient quadratic Hensel lift 2- made ya optional in polinterpolate BA 3- more efficient factorff when pol belongs to Fp[X] (based on Fp_isom) 4- catch SIGFPE 5- made poltchebi efficient 6- write all real zeroes in exponential format (0e28) in format 'g' 7- bnfsunit: try to compute S-units even when the class group is large reduce class group generators 8- 0.e N now inputs a real 0 of decimal exponent N (was N-defaultprecision) 9- try to avoid errors due to precision loss (while computing archimedian components) in bnfnewprec/bnfmake 10- restore \o2 to previous meaning, use \o3 for alternate prettyprinter 11- normalized output of idealfactor (sort factors) 12- better TeXization (\left / \right) 13- allow color changes in error messages (when sample input is given) 14- format for bnf[9] (new isprincipal) 15- cleaned up isprincipal + bnfinit (small_norm, getfu, class_group_gen) XR 16- added flag for D>0 in quadhilbert: if non-zero, try more modulii 17- idealred: reduce huge ideals as Z-module first (using lllintpartial) 18- TeXmacs interface Added 1- library function zerovec 2- van Hoeij's algo. for modular factors recombination (factor over Z[X]) 3- algdep for p-adic numbers IZ 4- default values for 'colors' (light/dark) and 'prettyprinter' (tex2mail) 5- hnflll implementation (old one was preliminary and didn't work at all) GN 6- squfof implementation 7- numerical derivation XR 8- GP interface to hensel_lift functions (polhensellift) Removed 1- quadrayimagwei, preliminary implementation to quadray(D < 0) =========================================================================== Done for version 2.0.20.beta (released 07/06/2000): Fixed 1- gp -p1e -->SEGV 2- nfinit([x,1]) --> SEGV 3- ensure stack large enough [allocatemem(1) painted user in a corner] 4- make sure mpinl.o is linked (binaries may fail to build otherwise) 5- make sure sqrt(Mod(a,b)) terminates 6- memory leak with PARI pointers (issquare(4,&x)) 7- 'make clean' didn't affect doc 8- Configure didn't detect some SuperSparc + Linux combination 9- forprime (and friends) could crash when loop index was tampered with 10- trap(, -1, (1/0)) == -1 ---> -1 (analyseur not reset) XR 11- bnrstark initializations (incorrect when field not totally real) 12- member functions not very robust [e.g. ellinit(e,1).roots --> SEGV] 13- compiler warnings (gcc -O -Wall) 14- trap() not robust enough in library mode (nested handlers) 15- (x^2+3)/(2*x)*x --> invalid RFRAC 16- factorpadic result used too high a precision (+improved handling of nonmonic polynomials) 17- sqrt(Mod(0,1)) --> oo loop (+ improved a bit mpsqrtmod) 18- no GC in norml2 IZ 19- tex2mail had difficulties with rational functions 20- (rare) SIGBUS in quadclassunit(non-fundamental discriminant) 21- g()=f()==0 --> syntax error 22- } as last char of an input file (missing a final \n) caused problems 23- ??keyword@ didn't work properly (pattern modified between chapters) BA 24- bug in galconj.c:corediscpartial (could return half integer) 25- factorff and ffinit "not random enough" TH 26- Configure doesn't handle cygwin new directory structure CW 27- polsturm(x,0,1) = 1 (should be 0) 28- [library:] gentimer(3) didn't work PW 29- various bugs in qfminim(,,2) [bound was rounded up + stack corruption] 30- ellap(e,2) gave wrong result when 2 | e.disc 31- factorint: isprime() used on factors even within smallfact() GN 32- SEGV in mpqs main sieving routine (unsigned comparison) 33- prevent polredabs from keeping small vectors accumulating in a subfield Changed 1- renamed .DOC files to .txt (Explorer was getting confused...) 2- moved MANIFEST to config/MANIFEST IZ 3- meaning of flags > 1 in plothraw IZ 4- output of \x (a bit more verbose) 5- unified basic t_QFR routines (use exponential distance internally) Added BA 1- Pocklington-Lehmer primality prover BA 2- Fp_isom (library) BA 3- Mod(a,b)^(c/d) for a,b,c,d integers 4- flag to vecsort (decreasing order) BA 5- function sqrtn =========================================================================== Done for version 2.0.19.beta (released 17/03/2000): Fixed 1- buffer overflow in ploth (when extrema too large) 2- trap(,"") didn't work IS+BA 3- various fixes necessary for g++ 3- prototype inconsistency in level1.h (evalexpo/evalvalp) 4- trouble with pgcc -mk6 + variable k6 in elliptic.c HC 5- nfnewprec(bnf) could contain objects of low accuracy XR 6- check subgroup argument in bnrL1 7- typo in ideal_two_elt (oo loop) 8- pb with GNU as + preprocessor on Sparc 9- incorrect result in matdet over Z[1/n] (Gauss-Bareiss) [gdivexact] 10- solve(x=0,1,deriv(x)) --> SEGV 11- ??' --> weird error 12- generic SNF (polynomial entries) couldn't handle 0s on diagonal 13- incorrect handling of 0 ideals in some functions XR 14- typos in bnrL1 15- bad input not handled in rnfcharpoly() IZ 16- delay rounding in rectplot structures until plotting device 17- Mod(1,x) / matid(2) --> incorrect object 18- avoid getrusage on alpha (pb with gp-dyn) 19- incorrect file inclusions when using gas on Sparc (-->undefined symbols) 20- massive cancellations in zetak(nfz,) when current prec lower than nfz's XR 21- bnrstark(): fixed inconsistency between 32bit & 64bit versions + check maxprime() before starting the computation PW 22- hyperu bad input bug PW 23- intnum(x=1,2,0) --> oo loop 24- sin(x + y) --> error 25- next(i > 1) didn't work (part of the last loop could be executed) 26- typo in polrootspadic(p, 2, *) [singular case] Changed XR 1- bnrL1 now takes a congruence subgroup as second argument 2- allow some functions to modify bnf/bnr structures (matal + cycgen) CB 3- modified TeX macros for pdftex 4- have abs(t_COMPLEX) give an exact result if possible [abs(0*I) was 0.0] IS 5- improved generic gcc compilation flags 6- in qfbclassno(), compute in G^2 to get rid of cycli factors 7- improved bnrdisc/bnrconductor Added BA 1- function galoissubcyclo() BA 2- (for now internal) function inverseimage_mod_p() BA 3- optional arguments (vertical range) to plot() IZ 4- `ticks' on hi-res plots IZ 5- prettyprinter default and tex2mail file BA 6- new function Fq_ker =========================================================================== Done for version 2.0.18.beta (released 20/12/1999): Fixed 1- wrong method chosen in isinexactfield for 0 polynomials 2- stack corruption in sylvestermatrix(0,...): Mod(x,x)^-1 --> SEGV 3- garbage left on stack in ginv(1 / n) 4- typo: carreparfait --> gcarreparfait in nfiso0() 5- for (A=1, 2, A = -A) --> SEGV IZ 6- [gnuplot] couldn't set terminal as the first graphing operation DE 7- typo in kernel/sparcv7/level0.S: err --> pari_err 8- TeXmacs interface (use new protocol) 9- call simplify() before applying GP '==' and '!=' operators Ex: x;n;k;m; (n+m)==(k+1-k)*(n+m) was false. 10- sumdiv(N,...) required single precision N BA 11- bound problems in nfgaloisconj() 12- oo loop in do_agm() 13- "Warning: in Gauss lg(a)=1..." from isprincipalall0 14- specific error for precision problems with p-adic ell. curves IZ 15- ploth() plots are 1/2-pixel off BA 16- result was not always complete in nfgaloisconj() 17- type(1/y, RFRACN) --> SEGV + check compatibility before applying type() 18- made 'secure' safer. Confirm before write, prevent from changing 'help' 19- gettime() called the wrong timer(): was reset in debug mode 20- missing case (doubling) in apell1 21- gmod(x, mod) replaced by gmul(x, gmodulcp(gun,mod)) in poldivres [obscure bugs when dividing complicated polynomials with mixed polmods/intmods]. 22- Make sure result is a t_POL before doing a setvarn in caract2_i() 23- precision problems in ClxModulus (bnrstark()) [check leading term!=0] 24- elltors() could miss some points: determine needed precision first 25- clean up files after an error (not only under GP) 26- divisors(highly composite integer) --> "cryptic" error message 27- 'make clean' wasn't thorough 28- ellpointtoz(e, [0,0]) could correspond to the inverse point 29- "ideals not coprime" in rnfsteinitz BA 30- typo in Configure [CPP] (cc --> CC) BA 31- member functions for galoisinit 32- allowed power series in Mod(). Fixed cryptic error messages. 33- precision problems in zsigne 34- value of 'gzip' found by Configure overwritten in TOP_Make.SH XR 35- precision loss in Round 4 XR 36- ensure that fundamental unit is computed in quadray (if D > 0) XR 37- precision fixes in stark.c (inconsistencies 32/64 bit + early abort) 38- bug in P*Q for polynomials over (non prime) finite fields if Q is defined over the prime field XR 39- [stark.c]: bugs in RecCoeff3, reduced memory use in ComputeArtinNumber 40- core dump on oo recursion under GP 41- use appropriate precision in torselldoud (could be much too large) 42- removeprimes(addprimes) didn't work 43- (at least part of) numerical instability of LLL over R 44- f() = bug(x, &y) ---> syntax error XR 45- inefficiencies in ComputeArtinNumber for large modulus HC 46- no GC in dirmul 47- meaningless heap count for user functions 48- setrand(16);quadclassunit(48893) --> oo loop 49- rnfpolred(bnfinit(y^2+1),x) --> SEGV 50- float overflow in polroots (e.g polroots(x^3 + 2^1024*x + 1)) 51- charpoly(Mod(1,x^2+1)) --> SEGV 52- added GC in polsturm BA 53- bugs involving rarely used type combinations in generic operations 54- check x >= 0 in lllgramint(x) 55- in rnfdedekind: use rnfhermitemod, not rnfhermite (slooow) XR 56- updated factorpadic to use new Round 4 BA 57- nfgaloisconj: discrepancies between 32/64 bits architectures 58- random(1 << 32) could have 32 bits 59- missing newline in error messages on startup (reading .gprc) 60- silent codeword overflows (e.g. O(x^100000)) IZ 61- updated gnuplot support 62- x="a"; eval(x) --> error 63- general flakiness with buffer handling under GP (Ex: input() + allocatemem --> SEGV) 64- [1] == 2 --> error (instead of 0) 65- lngamma(-0.106) --> SEGV 66- quadray(-11,3) --> x^2 XR 67- typo in nilord2 (wrong value for modular reduction) 68- unsafe division t_SER / t_SER with clonable components 69- polroots(1E-28*I*x^2+1) --> bug in roots (conjugates) 70- typo in cxlngamma [ lngamma(-7.4927-0.418564*I) --> SEGV ] 71- polroots(polynomial of very small Norm wrt prec) behaved badly (SEGV) 72- polylog(1, Mod(1,2)) --> SEGV 73- zeta(22!/23) --> SEGV 74- not enough GC in rnformax 75- over-reactive 'secure' default (+ moved it later in default .gprc) 76- sqrt(Mod(15,y^2+1) + O(x^5)) --> SEGV BA 77- typo in isinexactfield 78- sum(x=1,10, expr1; seq) : seq silently ignored 79- ellan and elltaniyama didn't check their arguments 80- simplify(t_POLMOD) could create invalid objects (mod not a t_POL) 81- primes(-1) --> SEGV 82- addprimes(0) wasn't rejected 83- various inconsistant error bessages (e.g. factor("a")) 84- estimate for the precision of unit embeddings in isprincipalall 85- global("b") --> polvar corrupt 86- hnfmod --> hnfmodid whenever possible 87- check arguments in incgamc 88- non-rectangular matrices could trigger a SEGV (in error msg!) 89- qfminim(,,2) didn't like mixed t_REAL/ t_FRAC entries (typo) 90- inconsistant spacing after GP error messages 91- regrouped code between idealred and idealmin 92- prevent 'install' in secure mode DS 93- typo in bnfisnorm(,,flag > 1) [extraneous gtrans] 94- don't reset pariErr in err_recover() 95- highlevel.c had become dependent from gp.c XR 96- incorrect output of quadray(D,,1) when D>0 and rayclass is trivial 97- typo in lllall_trivial --> matkerint([0;0]) didn't work BA 98- incorrect object for gerepileupto in gscalcol 99- try to detect bad input (e.g quad. form not > 0) in (integral) LLL XR100- typo in nffactor ("keep the value of i") IS101- work around an obscure gcc bug (gcc-2.96, alpha-linux) in stark.c 102- rnfcharpoly(nfinit(y^2+1),1,1) --> SEGV BA103- tan(t_COMPLEX) gave bogus result BA104- trace([;]) --> SEGV Added IZ 1- [gnuplot] look up directory tree for gnuplot related files 2- improved on-line help wrt to defaults and ambiguities (? default/some_default, ? some_default) 3- library functions gentimer, genmsgtimer, get_timer HC 4- optional argument to direuler (length of result) 5- low-level kernel function for integer squarings (twice faster) 6- error trapping in library mode and under GP 7- break loop to investigate errors under GP 8- "sprintf-rounding" under GP IZ 9- string justification in high-res plot IZ 10- bit operations ( bit[ and | or | neg | negimply | xor ] ) XR 11- add new flag value in bnrstark/quadray: try to find a better modulus 12- Configure flags to indicate where gmp/readline library/headers are to be found Changed 1- default binary produced by Configure -g is now static 2- improved the heuristics in ellisoncurve HC 3- extend the range of direuler (maxp was 2^16) 4- trial divide by the "private primes" before the primality tests 5- don't double stack automatically 6- disable ff_poltype correction (for lack of decent finite fields) in gmul 7- slight optimization to hnf / hnfmod (skip zeroes) XR 8- nfsqff: choose a prime ideal with few factors + better heuristic bound IS 9- default CFLAGS on linux-alpha 10- improved factorcantor / factorff 11- default multiprecision kernel is GMP if the library is installed Removed 1- sunview "support" (didn't work, hard to test, X11 is a better standard) =========================================================================== Done for version 2.0.17.beta (released 24/09/1999): Fixed XR 1- typo in zarchstar (result possibly incorrect when more than two places) 2- check_unit not severe enough ([;] --> session could die !) 3- wrong error message when using global var as argument to user function 4- typo in boundfact(t_FRAC) --> SEGV 5- buchall: don't compute xarch if not needed 6- remove limit on string size + silent overflow, e.g Str(10^5000) 7- "break status" not checked often enough: [break, 1] --> SEGV 8- rewrote errcontext (use print_text to fit messages on terminal) BD 9- added workarounds against some MSVC annoyances (Windows version) IZ 10- typo in Gnuplot.h 11- typo in Configure ("2>&1 >/dev/null" replaced by ">/dev/null 2>&1") 12- simplified incgam[23] + typo (mulrr --> gmul) IZ 13- typo in LD_LIBRARY_PATH setting (benches) 14- inconsistency in gadd(0., FRAC) (should give 0. if FRAC small enough) 15- libraries/headers ordering inconsistent in Configure (report: IZ and KO) 16- typo in ff_poltype [symptom: (Mod(1, y^2 + 1)*x + 1)*x --> garbage] 17- qfbprimeform(4, [2]) --> SEGV 18- overflow in factorcantor(2*x^3+3*x^2+x, 2^31-1) 19- memory corruption in apell1 + no garbage collection, rewrote the function to parallel apell0, replaced hashing by sorting, use Montgomery's trick, removed the p < 10^25 limit IS 20- cc -64 warning in mp.c:vals() 21- bad free in gp_expand_path 22- extract([;], "..") --> SEGV 23- not enough GC in hnfall 24- recover gracefully when precision too low in lindep/algdep IS 25- cleaned up unused variables, fixed some missing casts 26- algdep(x) --> undefined behavior when x exact. Replace by decimal approximation IS 27- C++ keywords (new, class) occurred as variable names 28- arguments of ideallistarch not checked 29- Mod(t_FRAC or t_PADIC, t_INT) --> garbage 30- gcmp1(t_REAL) always false: polylog(2, 1) --> error 31- (spurious) compiler warnings about variables used before initialization 32- memory (possibly) freed twice in buchall + unsafe allocation of matcopy 33- online help for matsnf not updated 34- rnfequation() didn't check its arguments correctly 35- removed spurious special case in compute_class_number() 36- typo in the compatibility macros mpabsz / mpnegz (missing ;) 37- "lost pointers in gerepile" in bnfisprincipal(Q, ...) 38- bnfisprincipal(..., Pol(0)) accepted 39- [Configure] Makefile name didn't necessarily match object directory 40- zetak(nfz, integer + 0.) --> stack corruption 41- for(i=1, ..., zetak(nfz, any complex number)) went slower and slower 42- poltchebi(.,y), pollegendre(.,y) didn't work 43- confusing "array index out of allowed range" message (e.g [1-0]) IS 44- fixed obscure compiler optimization bugs in smithall() and eint1() GN 45- weird results in ellisoncurve() due to misguided precision heuristics 46- typo in forvec([],...): readexpr() --> readseq() 47- check arguments in ploth() XR 48- rare bug in bnrL1 (wrong value!) 49- precision problems in polredabs 50- division by 0 in rnfordmax [typo in mymod()] 51- removed all dangerous occurences of constpi/consteuler (cf 41-) 52- typo in det() [forgot to divide by a pivot] 53- divide by 0 error in lllgramintern (precision problem) 54- suminf(k=1,suminf(j=1,.067^(k+j)/k^4/(k+j))) ran forever 55- factor(2*x + 2) --> [2*x + 2, 1] (instead of stripping the content) 56- (ultra-rare) stack corruption in mpqs_solve_linear_system() 57- rl_refresh_line() prototype changed across readline's versions 58- incorrect handling of INTMODs modulo integers of different magnitude XR 59- matsnf(3 x 3 matrix, 4) --> SEGV 60- some pathological bnfinit() computations (strive to get maximal rank) XR 61- precision problems in nfsqff() [increase precision for T2-norm bound] 62- time wasted checking generators of the form [x,0,...,0] in polredabs 63- variables deleted too late in freeall() Changed XR 1- modulus choice in bnrstark 2- make sure that addii(x,y) returns gzero, not icopy(gzero) 3- cutoff in ellap to use Jacobi sums (457 --> 100) 4- pariputsf("%Z",(long)g): removed the casts (not needed) 5- cleaned up hnfspec 6- look for at least MIN_EXTRA extra relations in buchall 7- simplified calling interface to hnfspec/add 8 Used hnfspec in bnfsunit, changed the way S-units are found 8- output of bnfsunit modified (removed res[3], made res[2] suitable for hnfadd) 9- listput and listinsert now return the inserted element, not the list 10- check_break_status rewritten: was very inefficient 11- Used parser code DG whenever it was possible (moved reorder to init.c) 12- faster isunit() 13- added GC in expr() 14- buchall(): increase subfactorbase without starting over GN 15- minor tuning in pollardbrent() for huge integers (call ECM sooner) 16- renamed directories dos -> Odos, o.xxx.xxx --> Oxxx. Moved win32/* --> Odos OR 17- new version of pari.el XR 18- new modular round 4 implementation (nilord2) BA 19- improved algorithms in galconj.c Added 1- an optional argument to next() 2- MANIFEST YU 3- support for FreeBSD ELF binary format 4- file CVS.DOC 5- support for Windows CE (Nigel Smart + coworkers) BA 6- functions related to Galois theory: galoisinit, galoisfixedfield, etc 7- [library] trivial function realun() Removed 1- #define HIGHBITM1 (useless) 2- files config/tar_[include | exclude] (obsoleted by MANIFEST) =========================================================================== Done for version 2.0.16.beta (released 29/06/1999): Fixed 1- paricfg.tex (needed to compile INSTALL.tex) missing if Configure is not run. Added a test in parimacro.tex 2- non-portable casts in galconj.c 3- 64-bit graph benches (extra spaces) IZ 4- typos in plotgnuplot.c 5- unnecessary plothsizes in "graph" bench (fails if no X server) 6- typo in ff_poltype IZ 7- check rectwindow in rectcopy and rectclip IZ 8- /opt/local/lib missing in Configure's library path IZ 9- [Math::Pari] needs pariErr->die _before_ pariErr->flush IZ 10- wrong valence code for plotcolor, plotclip IS 11- obscure inlining bug (pgcc 1.1.3 -O3) in stark.c:ComputeKernel0() 12- gcc -E doesn't define __GNUC__. Add it explicitly to KERNELCPPFLAGS 13- whatnow(sigmak) didn't tell the arguments have been swapped 14- [1]~ * [[1]] --> SEGV 15- lim=(av+ x * bot) >> y can overflow if large addresses are available (e.g Linux...). Use lim_stack() instead 16- algdep(I,1), lindep([I,1]) entered an oo loop 17- removed the maxHastad (= 50) limit in algdep/lindep 18- typo in polrootspadic(,,1) --> SEGV 19- GC not frequent enough in idealval 20- in split_ideal (isprincipal), LLL-reduce first if ideal is big 21- factorpadic(,,,1) didn't work anymore 22- round 2 (= nfbasis(,2)) used too much memory 23- idealval did not accept all types of ideals GN 24- unsafe stack handling in auxdecomp 25- polroots[mod|padic] returned a t_VEC, not a t_COL (as polroots) 26- check coeffs of polynomials with coeffs in nf (rnf* functions) 27- typos in polredabs0 (get_Bnf + nf_RAW in storeallpols) BA 28- nfgaloisapply could forget to clean up the stack 29- typo in gp_rl.c (rl_save_prompt <--> rl_restore_prompt) DE 30- arch="sun4" non reconnu par Configure 31- uninitialized variable (prec) in quadhilbertimag IS 32- pari.el.in was not updated when gphelp was moved from miscdir to bindir 33- rnfkummer(bnrinit(bnfinit(y^2-y-1),101,1),[1,0;0,2]) --> gerepile error IZ 34- update gnuplot interface a) Strings were put too low in gnuplot terminal; b) Allow setting of output file sizes, as in plotterm("gif=300,200"); c) Allow querying of possible output terminals, via plotterm("?") d) Update to newer Gnuplot-interface-layer (Gnuplot.h) allows compilation on Linux (stdout was bad as an initializer), corrects bugs in processing of terminal options 35- in buchall, allow minfsb to increase before doubling cbach (bnfinit(x^4+5*239*x^2+5*239^2) couldn't be computed) 36- bnfnewprec can't handle bnf = bnfinit(,2) --> SEGV (now, error) 37- typo in pseudorem (didn't recognize 0 properly) GH 38- weird bugs in thue() on alpha: typo int <--> long in thue.c 39- bnrisconductor assumed moduli had small norm (< VERYBIGINT) 40- bnfnewprec didn't accept imaginary quadratic fields ("missing units") 41- inefficiency in zarchstar (VERYBIGINT --> BIGINT) (rnfconductor(bnfinit(y^3+972*y-12),x^2+x+1) ran forever) 42- too much memory used in rnfordmax (+ removed some inefficiencies) 43- try to recover in nffactormod if input not prime (SEGV) 44- SEGV in nffactormod if degree(pol) > 100 45- factornf(p(x), q(x)) was accepted (and produced incorrect objects) 46- nfisincl / nfisiso made use of the bug above 47- subgrouplist(bnr) with trivial ray class group --> SEGV 48- background color was assumed to be "white" (by gphelp and gp) Made it "transparent" by default 49- pages shifted by 1 in User's Manual's table of contents 50- Mod(x, x^2+1) + x return Mod(2*x, x^2+1), not x + Mod(x,x^2+1) (fixed gadd, gmul, gdiv) 51- for certain flag combinations buchrayall unsuitable for gerepileupto (+ cleaned up the code) 52- ^C in smithclean corrupt existing objects 53- silent overflow in qfbhclasso 54- nfreducemodpr didn't check its arguments 55- confusing error messages when precision too low in initell 56- polx[0] modified in nfsubfields(P(y)) 57- various memory optimizations in bnrstark 58- incorrect debugging output in calc_bloc (at \g6) 59- rare memory corruption when garbage collecting in mppgcd 60- type t_STR not treated correctly in changevar 61- C-long overflow in ellan 62- memory use in the incgam* functions 63- bad input bug: qfperfection(indefinite matrix) --> SEGV 64- mateigen dropped some eigenvectors when precision was too low Changed 1- err() --> parierr() [conflict with system library in Redhat 6.0] 2- use Doud's algorithm in elltors [initial patch: HC] 3- new (internal) function get_mul_table (for nfinit, padicff) 4- disable LD_LIBRARY_PATH before running benches 5- strtoGEN() --> strtoGENstr() + added flag 6- optimized stack usage in pollardbrent (in place) 7- don't try to compute units in buchrayall if bnf doesn't contain them 8- simplified misc/gprc.* (esp. colors) 9- use C long to keep track of exponent in regula 10- src/kernel/sparcv7/level0.s --> level0.S + include preprocessing stuff 11- extended matsnf flags: immediate cleanup (backward compatible) 12- arguments swapped in veceint1 13- allow @ markers (??keyword@) in extended help (was apropos only) 14- do all computations in mppgcd in place (as in Changed-6) OR 15- new pari.el (cf emacs/pariemacs.txt) 16- search multiple lines in apropos extended help (???key) Removed 1- make test duplicated the "make bench" computations. Removed the test and dotest targets 2 -veceint1() function. Can be reached in library mode or using a flag to eint1 Added 1- default 'secure' 2- optional flag to Str() 3- expand environment variables in filenames 4- TODO file 5- man page for gphelp 6- Trivia section in the pari/gp man page =========================================================================== Done for version 2.0.15.beta (released 21/05/1999): Fixed 1- ?? (TeX mode) didn't work anymore 2- rl_save_prompt incorrectly detected on a.out systems 3- allow extra_relation() (bnfclassunit) to abort 4- allow cbach to double once more before triggering PLEASE REPORT (introduced in 2.0.14) 5- check for non-monic pol in smallbuchinit 6- vecex --> SEGV on some Linux systems (typo in match_concat) 7- exceedingly rare but possible overflow in forvec(, flag == 1) 8- factorff(x^7-3,3,y^3+2) --> SEGV DC 9- ghpelp doesn't exit when problems arise in TeX processing 10- made idealprimedec random again (also use det_mod_P_n to compute norm) 11- inefficiencies in nfeltval (computing norm is a waste of time) 12- did same prime twice when collecting garbage in modulargcd (=> error) 13- ffinit(huge prime,) output a weird error message 14- highly inefficient memory use in nfsubfields IS 15- [cygwin] typo in Makefile generation 16- file leak in mpqs (COMB) 17- allow prime_to_ideal to be called with a t_INT argument (for quadray) 18- typo in nf_shanks (calling Fp_shanks with wrong parameters) 19- polun (possibly) destroyed in bnrstark IS 20- keep logfile in synch with screen output 21- reset DEBUGLEVEL correctly on ^C (was sometimes set to 0) 22- bnrstark does not require anymore the modulus to be the conductor 23- check bnrstark's arguments in the right order (bnrstark(1,0) --> SEGV) 24- inefficiencies in idealval (removed element_mulh) 25- idealadd unsuitable for gerepileupto HC 26- quadray should work in all cases now and give better polynomials XR 27- bnrstark should return smaller polynomials 28- very inefficient pseudo-remainder routine (psres) 29- forstep(x=a,b, 1/2, ...) --> SEGV (signe -> gsigne) IS 30- [Cygwin] Configure fix (use $HOSTTYPE instead of uname -m) 31- polcoeff(a*x^-1*y^-1+O(x^2)+O(y^2),-1,y) --> 0 HC 32- (false) accuracy problem in mpsc1 ("truncation error") 33- don't use mpqs_diffptr in mpqs_find_k, set it in mpqs_create_FB 34- (very rare) "precision loss in truncation" in buchall 35- C-long overflow in zarchstar 36- C-long overflow in zprimestar 37- (old versions of) GNU as not recognized correctly BA 38- ?? in TeX mode could not process some sections (missing macros) 39- factor(polynomial with t_PADIC coeffs) didn't work (factorpadic assumed coeffs were integers) 40- T=[1,x; x,1]; charpoly(T,Z) produced object with wrong variable ordering 41- polrootsmod(x^n,p) could corrupt the stack 42- Warnings/errors from HPUX and AIX native compilers OR 43- many problems in the emacs interface pari.el (introduced in 2.0.14) 44- factorpadic treated only monic polynomials 45- gphelp TeX mode (use general macros instead of a specific file) 46- under readline, input lines of length > 2048 could trigger SEGV 47- more thorough check in checkbid (accepted prime ideals->SEGV) GH 48- possible stack corruption in thueinit(totally real field) XR 49- various problems in bnrstark (oo loop in fincke_pohst) 50- in doc/Makefile: removed GNU-style make macros + put a missing TAB 51- sloppy garbage collecting in hnfperm 52- HPUX+cc: work around a compiler bug (wr_float) 53- warnings in make_emacs_tags (perl5.005) 54- Configure --static should not disable install() 55- in rare cases reduction not complete in lllgramall (off-by-1 error) 56- addshiftw (polynomial case) could produce non-normalized polynomials 57- take content into account in modulargcd as in srgcd (not normalized) GH 58- uninitialized variable in poldisc0 (purify warning) 59- inefficiencies in round 4: modular computations [more needed!] (starting from a patch by DF+XR) GN 60- lllintpartial did not output the right matrix 61- huge memory leaks in bnrstark 62- signed int overflow in allocatemem 63- parisize (local to gp/gp.c) not updated properly 64- *sol not properly initialized in subresall 65- in idealpowred, check whether |n| < 16, not n < 16 (would slow down bnfinit a lot when class number is large) 66- polrootsmod(x^6-10,25) --> SEGV (now error message) 67- SEGV when renormalizing zero series in gdiv XR 68- unify precision choice in bnrstark (4 different formulae used...) GN 69- oo loop in mpqs (64bits machines + harsh compiler) when more factors were found than were hoped for (1 <--> 1L) GN 70- SIGFPE in buchall (double didn't fit in 32-bit integer) 71- also check sign in real0 (internal: called by gauss_pivot) 72- use current realprecision in plot() (was fixed: 28 digits) 73- memory use in subgrouplist(bnr) 74- in bnfcertify: "Too many iterations in isprincipal" 75- auto detect precision in quadhilbertimag ("overflow in I+R") 76- error message numbers in src/kernel/m68k/mp.s 77- polroots(x^3-x-422!) --> "impossible R-> dbl conversion" 78- not enough modular reductions in buchrayall (bnrinit) 79- technical argument in quadclassunit not read correctly 80- factor(x^3-1 + 0.*I) --> gerepile error GN 81- gp -p (close to a p^2) --> p possibly missing in the prime table 82- until narrow class group in quadclassunit is implemented, non-zero flag raises an error IZ 83- some code numbers in functions_basic (for Math::Pari) 84- precision problem in initell (AGM) 85- "impossible assignment I-->S" in ellrootno 86- missing break in poltype (factor) Changed 1- ?? (no arguments) opens the users'manual in xdvi 2- print readline version in header on startup 3- compute multiplication table first in element_mulvec[row] 4- nf[5][7] is now stored in two-element form (faster ideal inversion) 5- install gphelp in BINDIR, not MISCDIR 6- simplified output of trivial matrices 7- replaced square_free_factorization by mysquare_free_factorization 8- call LLL before using idealtwoelt GH 9- choose random elements in idealtwoelt, and allow bigger ones in two_elt 10- cleaned up lllgramall/lllgramintern + give quality ratio as argument 11- in rnflllgram, try to survive lllgram errors (findmin) 12- simplified rnfpolredabs (simple interface to polredabs). Should be much more efficient 13- replace many gdiv by 1 ginv + many gmul in sqred1intern 14- optimized polredabs (always do the initial polred now: it is for free) 15- more efficient ideal multiplication in random_relation (bnfinit) 16- library names nfhermite[mod|basis] <--> nfhnf[mod|basis] 17- subgrouplist function (use Birkhoff algorithm) 18- improve recovery in lllgramintern 19- improved checkgenerator in polredabs (look directly for double roots) 20- for consistency, return S-units in t_POL format (as fundamental units) IZ 21- revamp gnuplot autodetection by Configure BA 22- nfgaloisconj(nf, 4) uses Allombert's algorithm instead of Kluners's Added 1- install-doc target 2- make install makes a symlink pari.1 --> gp.1 3- ??tutorial/refcard opens tutorial/refcard.dvi in xdvi 4- posibility to extract the complement in vecextract HC 5- Ducos's subresultant algorithm (polresultant(,,2)) HC 6- accept a "vector of steps" in forstep 7- examples/classno.gp XR 8- new function bnrL1 9- new function gdivexact (used in subresultant, Gauss-Bareiss...) 10- new function bnfnewprec 11- optional argument to \l and \e shortcut 12- nfinit,polred[abs] accept input of the form [pol, HNF basis for Z_K] 13- q-Pascal triangle (matpascal(n,q)) 14- file src/basemath/subgroup.c, new function forsubgroup() IZ 15- function plotclip IZ 16- new file examples/taylor.gp (nice example for plotclip) BA 17- new file galconj.c =========================================================================== Done for version 2.0.14.alpha (released 05/03/1999): Fixed 1- factormod(2*x+1, 2) --> "factor for general pol. not implemented" IK 2- gphelp could leak temporary files BD 3- for native Win32 build: buffer overflow in get_home, incomplete paricfg.h, typo in try_pipe (#endif misplaced) 4- nfsubfields: could miss subfields if index > 1 5- removed 3 useless setrand(1) in subfields.c 6- rare and obscure memory bug in inverseimage (lost pointers in gerepile) 7- memory bug in factorpadic4 (prime not copied before result) 8- memory consumption in round2 (allbase) GT 9- m68k version: duplicate symbols from mp.c IS 10- Cygwin: in mpqs.c, open files in binary mode (otherwise fseek goes crazy) 11- bnfisprincipal().gen gives the expected answer IZ 12- signatures for Math::Pari in highlvl.c / init.c + GNUPLOT set-output-file problem 13- if we think readline needs libiberty, check whether it's installed first DB 14- PowerMac: header inclusion in highlvl.c, lround def'd in system headers XR 15- rnfkummer makes sure to return an integer XR 16- rnfconductor accepts polynomials with rational coeffs 17- polredabs + internal precision change --> nfnewprec forgets nf[5][1] 18- don't log lines twice when pariecho is set 19- glitches in content() (e.g content("a") --> SEGV) 20- get_sep(2) reacted incorrectly to empty strings 21- rootmod could destroy its argument 22- Fp_pow_mod_pol(x, 1,...) should return gcopy(x), not x 23- galoisconj1 computed wrongly the precision needed (+ prototype change) IZ 24- remove __OPTIMIZE__ dependence (define GCC_INLINE instead) 25- off-by-1 error in apell1 26- misleading error message in minimalexponent() XR 27- in nffactor, forgot to update precision when increasing exponent (+ various typos) 28- sparc + non-gcc --> kernel2 possibly not included: compilation failure 29- when echo is set don't print prompt if line is empty 30- ellpointtoz sometimes return -x instead of x 31- gp -b 1 --> hangs gp DE 32- many glitches in manual 33- mathnf(x, 3) when x hasn't maximal rank (SEGV) 34- differences in buchall 32bit/64bit (PRECREG too high. bnfinit(x^13-6)) 35- various inefficiencies in nfshanks ("module too large in nfshanks") 36- memory leak in buchall (= bnf*) 37- "not a definite matrix in lllgram" after a call to bnf* 38- typo in factorff(x^3+2,3,y^2+1) --> SEGV 39- [internal] missing tags (e.g zprimestar) after make ctags 40- idealstar(*, big prime) --> cryptic error msg (more tolerant now) 41- have Mod(0,1)^-1 return Mod(0,1) (fixes znstar(prime)) 42- ginv(-1/2) --> 2 43- heap leak when using local() 44- overflow in addssmod 45- changed the syntax of round() 46- sqrt(1. + O(x)) --> oo recursion IZ 47- don't create GP variables when expanding strings 48- internal variable 'parisize' not properly updated after allocatemem() IS 49- config/display didn't work properly with ActivePerl IS 50- Configure didn't handle most recent Cygwin 51- polinterpolate([],[]) --> SEGV 52- adapted gp_rl.c to readline 4.0 53- glitches in whatnow database (new file src/gp/whatnow.c) 54- all warnings from gcc 2.8.1 55- uninitialized tetpil in gscal() (bnfreg(x^2+1)) 56- precision problems in polgalois (degree > 7) 57- config/locatelib prompted a lot of useless work (returning too many libraries) and could pick up the wrong library 58- very rare bug in nfbasis (discriminant ok, but wrong basis) 59- quadclassunit: make sure sub factor base is big enough (oo loop) 60- more flexible "colors" default (initial work IZ) Changed 1- x.fu outputs polynomials (as all bnf* functions), not polmods 2- improved mppgcd (including vali) 3- improved division vector/scalar 4- \x to print a * in front of out-of-stack moduli (t_[INT|POL]MOD) IZ 5- better commandline usage message 6- don't buffer log messages going to pari.log 7- accept [nf, t_POLMOD] where nf is expected 8- poldisc() and quadgen() accept an optional variable name 9- when defining user function check for duplicate variable names 10- [internal] is_entry always uses function_hash (use is_entry_intern) OR 11- pari.el updated (see emacs/pariemacs.txt) 12- removed shiftl from lgcdii 13- use roots_to_pol in polgalois 14- precision heuristic in gauss_get_prec 15- cleaned up lllall and lllgramall 16- sort the output of nffactor, nfroots, factorff and factornf 17- nfgaloisconj now guaranteed to find all conjugates (use nffactor) 18- Removed flag 1 in nfisisom/nfisincl: function checks its arguments, and uses the best algorithm (both guaranteed complete). Changed the names (nfiso/nfincl) in library mode to match GP usage 19- gerepile(ltop,lbot,0) no longer returns ltop - lbot 20- improved floor and round(t_FRAC) 21- removed some duplicate code from nffactor 22- passing a pointer to GEN in a GP funciton now explicitly requires an & IZ 23- more verbose error messages for online help 24- increased a bit poltschirnaus's period 25- DOS version: don't use more for external help 26- cleaned up buchall code 27- removed unnecessary gres from polarit1.c:to_fq() Added 1- apropos command in gphelp (-k switch), ??? under GP 2- function global() 3- function gp_variable to use sums, etc in library mode 4- [internal] new functions mulmat_real 5- new functions gerepileupto[leaf|int] 6- function znlog() IZ 7- added default(color, "yes" / "no") 8- --static flag to Configure GH 9- inline alpha assembler (gcc specific) Removed 1- isinclfast/isisomfast 2- rounderror =========================================================================== Done for version 2.0.13 alpha (released 14/12/98): Fixed IK 1- Configure hangs on FreeBSD systems RD 2- Roland's patch (2.0.11: Fixed- 42) had been incorrectly applied 3- stack corruption in glcm (if operands > 10^155) 4- index wrap-around in polsubcyclo (n > sqrt(2^31)) 5- incorrect placement of strings in psdraw 6- memory corruption in rhoimag0 7- fix up memory debug mode (\gm) when switching to alternate stack 8- memory corruption (new_chunk + mulii) in gmul/gdiv (t_FRAC) 9- escape chars in GP strings sometimes parsed twice (e.g Str("\\") --> "") 10- nfinit(x^18+16) --> impossible inverse mod(0,2) (bug in eltppm() introduced in 2.0.12) 11- weird SEGVs due to variable handling (changed the 'bloc' structure) 12- moved highlvl.c to src/gp (libpari was missing symbols from plotport) 13- polcyclo ignored its second argument (introduced in 2.0.12) TP 14- minor fixes in paridecl.h (poldivres, gredsp: C++ compiler exits) HC 15- still sign problems in resultant (see 2.0.12: Fixed-58) 16- (Solaris):GNU ld doesn't like empty object files: remove kernel2.o IZ 17- make bench forgot to treat the install() BUG in a special way 18- factor(x^2 + I) --> SEGV (also with t_QUADs) 19- factornf(x^3+1,y^2-1) --> stack doubling (now output error msg) IZ 20- for Math::Pari fix valence of factormod() IZ 21- outfile rename pari_outfile (conflict with gnuplot headers) 22- DEBUGLEVEL could be modified and not reset upon interrupt IK 23- make perl -wc gphelp happy 24- incorrect use of gettime() in the library (nffactor) --> wrong timings (in particular for the 'nfield' bench) 25- polred/polredabs used different types for output. Made both t_VEC 26- remove duplicate polynomials in polredabs(x,4) and polred XR 27- precision fixes in modules/[nffactor|stark].c 28- in compatible mode, \precision didn't work anymore 29- typo in Round4 (case "p small" and "p huge" were swapped) 30- incorrect prototype for conductor in compatible mode 31- factor((x^2-1)/2) --> SEGV (factpol assumed integer entries) 32- memory usage in Round2: nfbasis(*, 2) (also cleared some inefficiencies) IK 33- typo in primitive_pol_to_monic 34- deplin did not check its arguments 35- quadray() assumed variable "y" was not in use Changed 1- glength() returns a C-long integer 2- in hnfmodid(x,d) reduce mod d immediately 3- allow vector(n), and matrix(n,m) (filled with 0s) 4- under GP, wait for input if line ends with '=' (cf \) 5- wait for input when a line ends with an '=' sign 6- modified extended help to (potentially) search the whole manual 7- in nfdisc, specific error message if discriminant is 0 8- use divide_conquer_prod() in factorback() IZ 9- in test suite, add setrand(1) in front of poltschirnaus IZ 10- M-( bound by default IZ 11- improved gnuplot support 12- improved gcmp[1|_1](t_REAL) OR 13- new pari.el (see emacs/pariemacs.txt) Added 1- members e, f, p, gen for prime ideals 2- mathnf([M, M2]) computes mathnf(M), updating M2 (equivalent to v=mathnf(M,1) then M2*v[2], but much faster if M2 is small or over a finite field) 3- local() keyword for user function definitions in GP IZ 4- new functions plotfile(), plotpointsize() IZ 5- splines for ploth (flag 256) Removed 1- \k metacommand =========================================================================== Done for version 2.0.12 alpha (released 06/11/98): Fixed 1- GNU as incorrectly treated by Configure GN 2- various fixes in mpqs.c (incl. file descriptor leak) GN 3- [From 2.0.11- Fixed 14] floating point exponents: 1E1 --> possibly 0.1 4- 1 % Pol(2) still wasn't right [cf 2.0.11- Fixed 31] 5- src/test/dotest for DOS boxes (running sh) 6- removed unreachable err() in factor() 7- system() is defined under EMX, so make it available for DOS 8- possibly use / as path separator under EMX, check COMSPEC and EMXSHELL 9- compatible = 3 downcased all the following lines in gprc and caused incorrect behaviour of preprocessing statements 10- unified default commands + better checks (e.g: default(log,0)->SEGV) 11- memory leak in gp_main_loop: bufferlisit wasn't reset on error 12- gptimer() not initialized properly if ^C was first command 13- extra space (sometimes) output by command line completion in DOS version 14- modifying histsize could corrupt the history stack 15- incorrect error messages in gsqr 16- not enough garbage collection in rootmod (polgcdnun) TP 17- compilation using cc -64 on 64-bit SGI IS+GN 18- "(hit return to continue)" message did not flush stdin GN 18- ECM rewrite 19- incorect absi_cmp in buch3.c 20- useless garbage collecting in sqred2 21- O(1)^(1/2) --> SEGV 22- forvec(i=[],...) --> SEGV GN 23- deriv(x*y, y) --> 0 GN 24- inefficient GC in ispseudoprime() 25- fixed some (not all) compiler warnings (char * --> unsigned char *) 26- exp(too large number) now gives a meaningful error message AW 27- getrusage still not detected on FreeBSD 2.2.5 GN 28- off by 1 error in initprimes() (--> not enough calculated primes) 29- inefficiencies in factor(t_POL) HC 30- bug in rnfelementabstorel for Mod(scalar, t_POL) HC 31- typo in gaussmoduloall 32- idealred(principal ideal) always returned an archimedean part HC 33- idealpowprime wrong for negative powers 34- typo in binomial(n,k) (wrong answer if n<=k) 35- online help for polinterpolate 36- incorrect garbage collecting in quickmulii/quicksqri 37- reformatted the output in test mode (gp -test) 38- polroots((x-7)*(x-8)*(x+16)) took far too much time 39- ellap assumed ell was given in characteristic 0 IZ 40- outlook of plot function (better labels, better choice of chars) RD 41- when factoring over a non prime finite field and found a p-th power, forgot about Frobenius GN 42- rare memory bug in ellfacteur 43- gscalmat was not suitable for gerepileupto 44- polredabs(,2) didn't handle non-monic polynomials 45- check for various overflows (x ^ 1000000, etc.) 46- printtex(I) --> missing closing brace 47- setisset() did not check that elements were strings 48- typo in gdiv(t_POLMOD, t_POLMOD) with different variables KO 49- missing ; in level1.h (Windows specific code) 50- forprime(p=0,10,) indeed started at p=0 51- (cf 2.0.11 Fixed-1) put back 3 cgeti in galois.c (were necessary) 52- factorpadic could overstate the precision of the result 53- (very) rare memory corruption in allhnfmod (when cleaning up) PM 54- prototypes in paridecl.h (fussy IRIX compiler), cc -64 in MACHINES 55- factormod implemented for all primes (p = 2 and p > 2^31 called factorcantor which was much slower) 56- check for unsuitable input in [factor|roots] (SEGV for multivar. pol) 57- polresultant sometimes gave the wrong sign 58- extraneous space in err(impl,"") (= "sorry,... not implemented") 59- aliases treated incorrectly during error recovery (--> obscure bugs) 60- obscure bug when normalizing rational functions with real coeffs (corrected content()) Changed 1- paricfg.h in dos and win32 extracted by Configure before the release (to get version number right) 2- GPRC logic: try $GPRC, then look in $HOME, /etc (/ and C:/ under EMX) 3- make sure the output of pari_unique_filename() doesn't exist already 4- use a stack of files to gracefully handle errors/interrupts without leaking file descriptors 5- replaced fixed-size buffers by dynamically allocated ones (es.c/gp.c) 6- rename INSTALL.QUICK --> INSTALL.DOC (updated) Changelog --> CHANGES (looks better under DOS) 7- mention ?12 in the header 8- use ; (instead of :) as PATH separator under DOS, OS/2 or Windows (for drive letter) GN 9- ECM tunings 10- check for overflow in cget* (instead of silent wraparound) 11- gp_main_loop cut into (improved) pieces 12- simplified normalizepol 13- Warn when trying to replace an existing function with install (previously error) 14- new function mpcopy. replaced some inlined function (rcopy, absi, absr, negi, negr) by compatibility macros 15- gphelp now uses GPDOCDIR and GPTMPDIR 16- improved rational arithmetic by computing smaller gcds (gredsp removed) GN 17- improvements in MPQS (use less memory, count relations precisely) 18- text-mode (non-TeX) extended help printed screen by screen 19- retuned integer multiplication, and made polkaramul the default polynomial multiplication XR 20- stark.c rewritten IZ 21- updated the pariperl interface 22- improved handling of t_INTMODs (less GC) 23- improved (a lot) factoring/root finding for intmod polynomials 24- modified poldivres to avoid computing remainder when useless 25- removed inefficient shiftl/shiftlr from the kernel 26- from the same sources, Configure can now simultaneously run on different architectures 27- polynomial factorizer now sorts the factors (increasing degree) 28- ?an_obsolete_function now calls whatnow 29- .pol operates also on t_POLMOD 30- random() argument can have arbitrary length IZ 31- with gnuplot, pick a sensible terminal when X11 is not around IZ 32- change valences for use with Math::PARI IZ 33- various interface patches (new file highlvl.c, different prototype for foreignAutoload...) 34- optimized permute() 35- setrand, getrand, getstack, gettime return a C long, and not a GEN 36- pari_randseed no longer global. Don't reset random number generator when entering certain functions 37- improved smallvectors() (correcting the "not enough storage" bug) 38- improved computation of special polynomials ([sub]cyclo,tchebi,legendre) 39- read() and extern() are timed as a whole now 40- check if LONG_IS_64BIT is correctly defined in pari_init (in case we include the wrong pari.h) GN 41- use Lehmer-Jebelean to compute inverse mod p (TODO: extended gcd) 42- moved subcyclo() to bibli2.c 43- improved polredabs, suppressed flag 8 44- improved ground(), case t_REAL 45- modified the internal SMALL nf structure (add matrix M, for polredabs) Removed 1- doc/Makefile.SOS, since make should succeed even if Configure failed 2- many error messages from the analyzer (referer*, trucer1, matvecter...), better handled by talker2 3- obsolete test %_ in bench 4- polkaramul(), which is now the default multiplication 5- factmoder error message 6- obsolete function polredabsfast Added 1- `pipes' for DOS running EMX, i.e extern() and extended help are available (perl needed for the latter) 2- file handling functions pari_fopen, pari_fclose, pari_unlink 3- new default `debugfiles' 4- file README.DOS IZ 5- target etags in top Makefile 6- target ctags IZ 7- gnuplot support HC 8- elliptic functions package (ellzeta, ellwp, ellsigma) HC 9- quadray function, extending quadhilbert 10- files src/basemath/polarit3.c and src/gp/highlvl.c 11- user-defined member functions 12- possibility to choose sizeof(long) at Configure time when the hardware suports it (eg. MIPS) =========================================================================== Done for version 2.0.11 beta (released 30/07/98): Fixed 1- removed all dummy cgeti (--> new_chunk) 2- stack corruption in gcarreparfait (t_INTMOD) 3- incorrect Fq-loop in apprgen9 4- removed useless normalize in gdivgs, gdiv 5- some {} Warnings from gcc -Wall (unjustified, but doesn't hurt) 6- incorrect zero series return by deriv 7- gaffsg(, t_PADIC) misused the valuation (symptom: deriv((1+O(2^2))*x^2) 8- online help for ellinit GN 9- default gp built without X11 in presence of some versions of xmkmf 10- ggval: zero series + simplified the code in there 11- subst(O(q),q,x) --> O(q) 12- newtonpoly did not treat correctly zero coefficients IK 13- getrusage incorrectly detected (at least on Linux/FreeBSD machines) 14- constante() used far too much memory (+ an int should have been a long + an lg should have been an lgefint). Reading in a huge bnf needs much less memory now 15- y[2] checked in divri instead of is_bigint (see 2.0.10, Changed 2) 16- powgi, default case: missing gcopy + incorrect gerepilemany if y==NULL Also, uniformized random GC with gpowgs 17- stack corruption in hil(x,y,p) when typ(x) > typ(y) 18- SEGV if DISPLAY was unset and hi-res routine under X11 is called GN 19- ispseudoprime(negative integer) 20- removed -static from the CFLAGS of profiling version (didn't build) 21- linear algebra routines involving polynomials with real coeffs 22- compiles properly under DOS + EMX GN 23- Warnings from C++ compiler (include unistd.h and sys/ioctl.h where needed) 24- znprimroot(0) --> oo loop GN 25- various fixes in mpqs GN 26- add safety parentheses to macros in paricom.h 27- polroots needed too much precision (two extra words) 28- factor(1. * x + I) ---> rubbish or SEGV (bug in polynomialtype automat) 29- possible address wrapparound in gerepile* (cast to ulong) 30- in gerepile: useless special case for t_SER 31- Pol(1) % 1 returned 1, not 0 32- matdet([x1,1,1/x1; x2,1,1/x2 ; x3,1,1/x3]) returned wrong result (call to gdeuc should have been gdiv in all cases in det()) 33- SEGV in powmodulo (access garbage pointer just before exiting) GN 34- various problems in rho and mpqs Changed 1- simplified detint, fibo 2- simplified GC and optimized gmul: t_SERxt_SER, t_POLxt_POL, and gsqr (same types) 3- streamlined binomial 4- replaced all abusive cmpsi by the relevant egalii 5- prototype for error types [gmuler|gadder|gdiver][fi], assign[ri] using new function type_name 6- uniformized the test suites (make test*,bench,...) GN 7- add random GC in mppgcd. Use modified plus-minus algorithm (new cgcd) 8- format of bench files (to reduce size) 9- cleaned up factor and polynomialtype 10- matdet tries to return a significant 0 when called with a non-invertible argument, e.g matdet([1+O(3),1+O(3);O(3),O(3)]) --> O(3), not 0 11- made the output of make bench/test slightly more informative Removed 1- mpkaramul 2- error messages expter1 and gaffer13 Added 1- misc/gprc.dos a sample gprc for DOS boxes 2- Configure --prefix=dir is now recognized (in addition to -p) =========================================================================== Done for version 2.0.10 beta (released 09/07/98): Fixed 1- integer factoring engine (ECM): sisprime killed N XR 2- file closed twice in MPQS GN 3- bad argument checking in [next|prec]prime BD 4- warnings from MSVC compiler 5- warnings from purify (vpariputs + puissii) 6- sample program and Makefile in examples/ 7- v=...; forvec(a=v, v=...) ==> SEGV LG 8- support for HP running NextStep GN 9- have checkmemory (in cget*) check for overflows LG 10- avoid a bug in cc compiler (version 4.2) under Solaris (in factmod()) LG 11- some missing prototypes and typecasts (for C++) GN 12- add LOCAL_HIREMAINDER in mulssmod (factor(17!+1) => SEGV on some PCs) 13- non portable pari_is_rwxdir GN 14- lots of typos in the documentation Changed GN 1- add debugging output to ECM 2- forvec implementation (+ new flags) GN 3- rewrote the integer factorizer (use Pollard-Brent + improved ECM + new MPQS code from 2.0.9) 4- disabled pari-matched-insert under Emacs 5- reorganized vecsort & co 6- in library mode, classno3 --> hclassno XR 7- improved the nffactor module HC 8- elllseries (use ellglobalred + ellrootno) Added 1- new function in library mode readGEN() HC 2- new GP function ellrootno Removed 1- error message vecsorter2 2- functions vecindexsort, veclexsort (use vecsort with flag) =========================================================================== Done for version 2.0.9 alpha (released 16/06/98): Fixed 1- typo in qfbhclassno (SEGV when result in (1/3)Z) 2- too much memory allocated in factmod /factcantor (use clones) 3- removed the -DREADLINE_LIBRARY hack, use and not 4- version 2.0.8 did not compile with readline 1.* 5- after gaffect(0, padic), padic was unsuitable for further gaffect 6- length(a string) gave number of non code words, not string length 7- factorpadic(polynomial of degree one) did not convert coeffs to padics 8- reduction mod p^r forgotten in gaffsg(s,t_PADIC) 9- default(realprecision,,1) did not return # significant digits 10- typo in nfmodprinit (return x instead of 1-x) 11- matinverseimage did not check its arguments 12- mathess([;]) --> SEGV 13- matid(-100) --> SEGV 14- mateigen([;]) --> SEGV 15- matmultodiagonal([;],Mat(1)) --> SEGV 16- vecextract([;],"..") --> SEGV 17- introduced in 2.0.8 (Added 3-): aliases/user function + ==> SEGV GN 18- (t_RFRAC) ^ t_INT took an unreasonable amount of time 19- prevent quick succession of ^C from corrupting memory in recover() 20- hyperu could enter an oo loop due to round-off errors XR 21- matadjoint(Mat(n)) returned Mat(n), not Mat(1) 22- matadjoint([;]) returned [[;]] (???) 23- wrap some long error messages XR 24- inefficiencies in rnfpolredabs XR 25- nffactor (wrong format for discriminant computation + problems with unseparable polynomials + compute disc only once) HC 26- typos in kummer.c GN 27- check environment variable LINES, not ROWS 28- introduced in 2.0.7 (Fixed 7-): lift(Mod(O(2^0)*x, x^3 - 2)^4) was a zero polynomial with non-zero sign (=> pb when normalizing in poldivres) 29- timer always returned 0 if times() was used (e.g linux-alpha) 30- kill'ing the argument of a user function corrupted the function 31- make clean did not remove pariinline.h 32- incorrect memcopy in identifier, case 's' (removed * sizeof(long)) 33- online help for ?. (nf.nf does not exist) 34- lisseq0: gnil not respected after break/next. avma=av too brutal after return 35- ellwp assumed precdl > 3 36- under emacs, \c + hit return froze emacs (Emmanuel Kowalski) 37- (f()= f()=x); f; didn't set f properly GN 38- comments in anal.c 39- qflllgram([;]) --> SEGV 40- no online help for bernfrac 41- from 2.0.6 (Fixed-8): in padicff2, forgot to raise ideal to power e Changed 1- improved (trivially) gneg (case t_INTMOD), gtopoly 2- use macro is_bigint() instead of tests (ulong)x[2] < VERYBIGINT (led to typos as in Fixed-4 in 2.0.8) 3- improved poldivres by replacing many gsub by 1 gneg + many gadd 4- in pvaluation check for small integer 5- internal function rnfelement_*mod (prhall=NULL instead of gzero) 6- improved mathess 7- added error message "inconsistent data in" in parierr.h 8- gpui[gs] renamed to gpow[gs] GN 9- improved probable-primality tests ('end matching') 10- moved pseudo primality and ECM stuff into ifactor1.c GN 11- raise to an integer power using left-shift binary (new functions powi and powgi) 12- add some details in the online help headers GN 13- nextprime, precprime now accept real arguments TP 14- improved the alpha micro kernel (addllx and subllx) 15- simplified poltschirnaus 16- cleaned up identifier(): #ifdef __hpux__ + call_fun() modified 17- taylor() improved (one gerepile removed) 18- unified the treatment of zero series 19- gerepilemany faster and more efficient memory-wise (copy to heap first) GN 20- improved stack checking in lllgramall Removed 1- global variable defaultpadicprecision 2- function compute_prhall (nfmodprinit is better) 3- function [g]pseudopremier (miller[rabin] better) Added 1- function egalii 2- support for cygwin32 in Configure (Andy Stubbs) 3- new function gunclone to delete a clone (killbloc should be used by the analyser only) 4- comments in anal.c TP/XR 5- new function factorint(), using MPQS (_experimental_) =========================================================================== Done for version 2.0.8.alpha (released 07/05/98): Fixed 1- improved garbage collecting in polroots 2- zetak did not check its nfz argument properly 3- warnings from MSVC GN 4- isprime() did not work for numbers in [2^(BIL-1), 2^BIL-1] GN 5- precprime sometimes missed a prime 6- quaddisc(x in Q\Z) did not always work 7- powering of zero series 8- factorization of null matrices (SEGV) 9- mateigen for non-diagonalizable matrices (SEGV) GN 10- oo loops in some arithmetical functions when arg = big prime GN 11- cleaned up paridecl.h 12- gimag/greal for type t_RFRAC/t_RFRACN (fix: Terje Sparre Olsen) GN 13- ordinal numbers to number components seen through \x HC 14- lllgram: incorrect gabage collecting in first "warnmem" 15- theta(q exact, z) entered oo loop 16- typo in gdiventres (x<-->y in last line) MS 17- gtrunc for p-adics when valp(x) < 0 MS 18- polresultant(u+v,u-v,v) => x + u; polresultant(u+v,u-v) => 2*u MS 19- issquare(Pol), where Pol(0) = 0 IZ 20- use 15 points (by default) for recursive plotting as documented 21- matsnf for singular matrices (supersedes a patch by GN) LG 22- micro kernel support for HPUX LG 23- compilation with Sun's C++ compiler (version 4.2) 24- SEGV when factoring polynomials of huge degree (removed expos[100],etc) 25- garbage collection in gpuigs GN/BH 26- micro kernel support for ix86 running SunOS HC 27- handling of 0x0 matrix in some hnf* functions HC 28- bug in discrayabslist* (try bnrdisclist(bnfinit(y^2-2),200,,1) in 2.0.7) Changed: 1- moved hnf and snf from base1.c to alglin2.c (base1.c too big) 2- use gexpo in linear algebra functions when entries contain real numbers (work for inexact polynomial entries now). Still does not work properly for p-adics GN 3- in sigma() fall back to numbdiv() or sumdiv() when k < 2 4- made comments started in file through read("file") local to file (not so \r file) 5- valuation(0) now returns VERYBIGINT instead of raising an error MS 6- simplified gegal in case t_FRAC IZ/GN 7- faster initprimes, using less memory LG 8- improved Configure Added: 1- new function write1 MS 2- new Lisp-like quote operator 'a IZ 3- readline: electric parentheses, move across balanced expressions, add formal arguments to completion of GP command (when unique) 4- micro-kernel for hppa 5- quiet mode (gp -q) to suppress headers =========================================================================== Done for version 2.0.7.alpha (released 21/03/98): Fixed XR 1- SEGV in get_regulator for imag. quad. fields 2- "beautified" output (still ugly, less buggy, ok for simple objects) 3- error during "print()" could change output default 4- SEGV when syntax errors in gprc 5- make install failed when libpari.$sodest had been removed 6- moved term_width and term_heigth to es.c HC 7- inefficiency in mulii (Karatsuba used too easily) XR 8- many problems in stark.c XR 9- bugs in rnfpolredabs (+ new flag) GN 10- _many_ typos in tutorial and user's manual. New, much nicer, layout 11- whatnow not robust enough + faulty call by err_new_fun ==> SEGV 12- idealadd treated incorrectly the 0 ideal 13- default(realprecision) gave wrong value when format had been changed 14- bnfs structure was inefficient for applications (inverted 2nd comp.) 15- buffersize was incorrectly updated during complicated read() 16- one-line comments "ignored" if buffersize too small 17- using eval on object containing killed variables caused a SEGV 18- contfrac lost last term when first parameter was rational and numerators were supplied 19- problems when dividing with polynomials/series whose leading coeff is non-exact 0 BD 20- missing #ifdef ZCAT in es.c BD 21- check in paricom.h whether min / max are already defined BD 22- universal_constants freed early in freeall() (problems on Windows NT) BH 23- update Makefile.dos (nf.h --> parinf.h) BH 24- changed kernel/ix86/level0asm.c (FUNBEGIN/FUNEND + ALIGN) 25- cleaned the gauss_pivot functions + garbage collecting in gauss() 26- mathnfmod did not check its second argument 27- since 2.0.4 (item 24) install did not work anymore on FreeBSD + gp-dyn 28- cleaner malloc in plotX.c (to remove Warnings when debugmem > 0) 29- slightly optimized matdet (gsub --> gadd(,gneg)) 30- ? x=1; Pol(1) *** variable name expected: x,n, ^--- is fixed everwhere (wherever an optional variable name is expected) setting "x" to some value is now safe IZ 31- nicer looking plot() function 32- warnings while building for m68k arch 33- sqrt(Mod(1,2)) went into an oo loop 34- ?? did not resolve aliases 35- besselk near integers entered an oo loop 36- p-adic sqrt (bad valp) 37- hnfmodid could output wrong results (wrong diagonal) and wreck the powering of prime ideals 38- added garbage collecting in izeta 39- ??a_number now works as gphelp 40- in prettymatrix format, matrices 0xn and nx0 are always printed as [;] 41- 1 - "a" ==> SEGV Changed 1- reorganized output functions (es.c) 2- have mulir check if integer is small 3- part of GENtostr inlined (check_output_length()) HC 4- functions where it makes sense now admit an optional argument for "variable number" (intformal, deriv, things having to do with polynomials, etc) 5- lines of any length can be input interactively (previously 1k at most) 6- remove {} and \ from readline history 7- improve treatment of sample programs in gphelp -d 8- uniformized debugmem messages MSo 9- simplify the coinit function 10- changing the function set through default(compatible,) no longer resets installed functions 11- renamed nfker-->nfkermodpr, nfgauss-->nfsolvemodpr 12- simplified/extended dummycopy 13- listput gives more informative error messages Added 1- default: lines HC 2- (made known to GP) functions nfmodprinit, nfkermodpr & nfsolvemodpr XR 3- function bnrstark 4- install code D& (optional pointer) 5- function name_var (to use after fetch_var) 6- concatenation of lists (or row vectors) of objects (overloaded concat) 7- ranges for vecextract (eg. vecextract(x, "1..3")) Removed 1- useless code 'F' in analyzer 2- perl directory (moved the files in ./perl to ./doc) =========================================================================== Done for version 2.0.6.alpha (released 22/02/98): Fixed 1- \x (voir2) did not always print the correct number of words 2- in changevar, type POLMOD, modulus and polynomial were interchanged 3- all occurences of former header file names in the documentation 4- (from 2.0.5. item C5) using allocatemem in a script aborted file reading 5- expanded the documentation for bnrrootnumber 6- factor(pol. with rational non integer coeff) could corrupt the stack 7- Euler gave wrong results when prec > 80502 digits (also cleaned up Pi) 8- cleaned up ggcd, grando0, tayl and factorpadic2 9- is_scalar_t --> is_const_t in gvar/gvar2 IZ 10- Configure and example Makefile for OS/2 11- idealprincipal did not accept n x 1 matrices 12- idealhnf(nf,a,b) did not work for quadratic fields 13- matsolve[mod]([;],.) could corrupt the stack or accept incorrect input 14- modules/galois.c unnecessarily included BH 15- symbol name problem in level0asm.c (cancels patch by IZ) XR 16- fixes in stark.c 17- cleaned all occurences of HIGHVALPBIT and HIGHEXPOBIT 18- serconvol assumed main variable was "x" 19- (x + O(x^2))^(3/2) gave a stupid error message 20- types not checked correctly in gtoser 21- check more seriously arguments to default() 22- in Makefile: added some missing $(RM), changed an "ln -s" in $(LN) 23- extra '\n' after print1 + sequence of warnings 24- simplified a statement in addii() 25- typo in classno() (classno(-200183): "division by 0") + cleaned classno 26- all compiler warnings + most of lint's 27- make install would not work anymore if emacs was not found 28- HNF reduction not always complete when rank is small compared to dim 29- gphelp -d did not handle ~ properly (+ cosmetic changes) Removed 1- unused files src/kernel/ix86/{asmi386.h,asmi386inline.h} 2- useless macro gcopyifstack and global variable RAVYZARC 3- useless error message gcder1 4- useless (undocumented) function fasthnf Changed 1- simplified isonstack 2- extended valid inputs for matsolvemod 3- don't output a '\n' before an empty matrix 4- mpsincos no longer static (so that it can be installed) 5- reorganized gp_initrc() to cater for for non-UNIX arch 6- the "obsolete function" message now launches whatnow() directly (and caters for the special cases "i" and "o" now) 7- improved stack management in hnf/allhnfmod/fasthnf 8- moved powering functions to trans1.c 9- disable logfile while reading .gprc 10- (slightly) the output of whatnow() Added BH 1- support for DOS build using EMX (dos directory + fixes) 2- function cotan() and bernfrac() 3- a code for pointers (&) for analyzer and install() 4- ??readline now includes info about completion and online help =========================================================================== Done for version 2.0.5.alpha (released 07/02/98): Fixed BH 1- LOCAL_HIREMAINDER added twice more in mp.c LG 2- some symbols declared extern in gp_rl.c to avoid compiler warnings LG 3- isprime could corrupt the stack (isprime_proto removed) LG 4- possible redeclaration of macro from system header (MAX in bibli1.c) 5- typos in the user's manual 6- removed unused error numbers and fixed their ordering in mp.s 7- a ; or : after read/extern was not always correctly taken into account 8- a bug in polroots (possible SEGV in very rare cases) (Paul Zimmermann) Changed LG 1- (huge) reorganization of PARI kernel and headers 2- logfile example in gprc.dft to take advantage of "time expansion" XR 3- stark units module rewritten HC 4- rnfpolredabs improved 5- errors now cause GP to close any file it was reading instead of going on 6- increased the static limit for the number of files opened simultaneously Added XR 1- function bnrrootnumber =========================================================================== Done for version 2.0.4.alpha (released 26/01/98): Fixed 1- recovery on startup was not correctly disabled GN 2- pari.el (see emacs/pari.el-changes) 3- "" missing around a DLLD caused Configure to fail if shared library not available 4- component of GEN could be created before its root in gadd(t_SER, t_SER) 5- nffactormod did not like big primes 6- removed the `.' binary concat operator introduced in last update (broke semantics). Instead Str() argument evaluated in string context 7- solve did not find some obvious zeroes (solve(x=-2,1,x) for instance) 8- Configure -pg did not work 9- 68k version didn't work: corrected mp.s, moved some code & defines 10- subst(x,variable(x),1) did not work 11- flag acted contrary to doc in matsolvemod 12- in rare cases the prompt could still start at column > 1 13- bnfissunit much faster now 14- idealval could make mistakes with non-integers 15- Mat([1])[1,] gave a stack error 16- zetakinit(x-1) as well 17- zetakinit(K, even integer) gave a wrong result whenever r1(K)>0 18- typo in whatnow(hermite) and ?bnfsunit 19- missing newline in user error after print1 20- various typos and omissions in chapters 1, 2 and 5 of manual 21- (x-x)==(y-y) returned FALSE 22- polfactormod(f,0) gave a SIGFPE 23- some missing #ifdef UNIX BH 24- install() now works for gp-sta under Linux and OSF BH 25- gcc Warnings in gp.c + es.c BH 26- problems when installing from a different non-priviledged account BH 27- inefficiencies in mpinline.h (replace memory access by a constant) Changed 1- when logging mode is on, record command line as well as result, and flush buffer often 2- subdirectory lib now called misc. Changed some filenames in it 3- defaults psfile and logfile are now run through strftime 4- for benches total time now taken into account ([BUG] was excluded) 5- noerr is now the LAST error message (for CLISP interface) 6- cleaned path expansion (default(path,...)) 7- renamed types.h and cast.h (prefixed by "pari") 8- renamed type Rect to PariRect DB 9- kernel/kerPPC.s replaced by kernel/kerPPC.c 10- made static the arrays in check_isin() (for the Mac port) BH 11- overflow/hiremainder use local variables as much as possible 12- prompt not printed during a batch job, unless echo is set commands not echoed twice in interactive mode Added 1- gplogfilter script in misc 2- check for strftime in Configure 3- support for alpha running linux (include portability fix on keralpha.s) 4- file MACHINES 5- made message for "array index out of range" error more precise 6- more frequent garbage collecting in mathnf BH 7- inline asm for i386 GN 8- support for native compiler on AIX Removed 1- support for dynamic linking on AIX (did not work) =========================================================================== Done for version 2.0.3.alpha (released 13/01/98): Fixed: 1- rare bug in gadd (PADIC + PADIC) which caused one of the arguments to be overwritten 2- typos in refcard 3- galois.c still couldn't compile on the HP (_INCLUDE_POSIX_SOURCE) 4- introduced in 2.0.2: item 14 used gexpo incorrectly (bnfinit sometimes did not give units it could have computed) 5- replaced INFINITY by pariINFINITY in rootpol.c (cancels Warning on OS/2) 6- on OS/2, target ../gp-$dft in o.xxx/Makefile could not be built (extraneous $exe_suff) 7- command line switches so that one can enter them with or without white space (new function read_arg in gp.c) 8- setdcolors so that it can't unset disable_colors if we are under emacs 9- random did not check its argument correctly (random(2^32) was accepted) 10- b=10; for(a=1,b, b=2) exited immediately, whereas the upper bound is supposed to be evaluated only once 11- reorganized the error recovery system (initially because errpile could cause SEGV on Linux systems) 12- typo. problems in doc and refcard (interletter spacing in $nfz$...) Changed: 1- Reorganized Makefile.SH: extraction twice as fast 2- pari.menu and pariemacs.txt rewritten, pari.el updated 3- expanded the man gp.1 to mention command line switches 4- the implied input from non-interactive input command (like extern and read) does not go into the GP history (%x) anymore (it never went into readline's). The final output (value of last expression evaluated) of course still does! 5- updated chapter 5 of the User's Manual (removed obsolete information) Added: 1- better settings for handling the Meta key under readline in examples/Inputrc YU 2- support for shared libraries under FreeBSD 3- colors under Emacs 1) emulate exactly the "colors" default after a M-x gp 2) .gp files edited get a special highlighting 4- a flag to default() to get the result under GP 5- overloaded the "." (member) operator to concatenate as strings if LHS is a string 6- .gprc accepts some limited preprocessing directive (#if READL and #if EMACS (and #ifnot as well)). Updated lib/gprc.default to reflect the changes Removed: 1- some unused, undocumented functions (allocatemem(), checksqid()) made static some other (op_ReIm) =========================================================================== Done for version 2.0.2.alpha (released 15/12/1997): Fixed: 1- typos in the documentation for the random() function 2- removed an extra -emacs flag in pari.el 3- decodefactor was incorrectly remembered by whatnow (it's factorback now) 4- test mode did not prevent all prompt expansion (==> bug in make test) 5- gphelp stopped abruptly when meeting a cross-referencing macro 6- zetainit now aborts cleanly when disc. too big (caused memory fault) 7- exceedingly rare bug in the printing of real numbers (missing decimals) 8- too early rounding in polroots which in rare cases made GP think some error had happened 9- text overflowed the manual pages (and tutorial) on non-A4 paper 10- polred incorrectly assumed that nf arguments were totally real (in a non critical part: that just led to some unnecessary computations) 11- polred(f,2) could try to overwrite universal integer gzero 12- check if we are using GNU as or GNU ld in Configure 13- empty -R argument to $CC when building GP without graphics (==> link failed) 14- bnfinit acts sensibly when fundamental units are too large (before: "overflow in R*R") 15- cleaned up buch2.c (removed ideallllredpart1, removed gerepile in class_group_generators(), not_given now called from getfu) 16- nfgaloisconj(...,2) was unusable (tried an illegal multiplication) 17- is_totally_split was very inefficient (==> nfgaloisconj was very slow) 18- some unimportant typos (gexpo) in polgalois 19- compiling without readline gave a Warning in gp.c (already_hist) 20- some make programs don't like $< (suppressed from doc/Makefile) 21- ellap sometimes assumed wrongly that coeffs of the curve were integers 22- flag 0 and 1 in ellap had been mixed up 23- print an extra \n before an error message if last output did not include it 24- component(any non recursive type) gave a SEGV 25- suminf / prodinf / prodeuler assumed they treated a real expression 26- lindep / algep had problems with numbers having a rational component 27- last significant digits of bessel* and hyperu were wrong (now only the last one is) 28- expi now returns a long as documented (expi(gzero) returned 0 on 64-bit machines!) 29- g++ could not compile libpari.a (casts missing, extraneous extern "C", faulty inline, etc.) 30- cleaned up the enums in gp.h 31- incorrect target veryclean in doc/Makefile Changed: 1- '_' is now valid in GP identifiers 2- removed subsections from table of contents. pages in the manual are now numbered consecutively 3- gexpo now accepts exact 0 arguments (return -HIGHEXPOBIT) gexpo for complex numbers now return max(gexpo(Re), gexpo(Im)) 4- parts of lib/gprc.default 5- the second argument of subgrouplist is now optional Removed: 1- buggy label/goto functions 2- (now unused) error messages: labeler, gexpoer2 3- _ as shorthand for conj() 4- (useless, undocumented) function gnormalize 5- some files in the lib directory (functions, gp) Added: 1- some files in the lib directory (README, pari.xbm, xgp) ============================================================================== Done for version 2.0.1.alpha (released 29/11/1997): Fixed: 1- multiple factors forgotten when factoring univariate pols over Z 2- extraneous modifications of the random seed (period of random generator was ridiculously small for some buchxxx functions). Change the bench results (in a non essential way) 3- bad terminal size determination 4- aliases incorrectly killed (possible SEGV) 5- incrementing/decrementing array elements with the (valid) syntax v[i]++ / v[i]-- caused a weird error message 6- subgrouplist() could end up by a SEGV on Linux systems LG 7- on HP-UX, flag -Aa not taken into account in Configure (caused it to fail on has_TIOCGWINSZ.c) LG 8- added a missing #define _INCLUDE_POSIX_SOURCE in galois.c (7 & 8 independently fixed by OV) GN 9- the script examples/cl.gp called vecconcat() instead of concat() GN 10- make install-sta rebuilt gp-sta unnecessarily GN 11- many, many typos in the tutorial 12- tu / fu applied incorrectly to a bnfclassunit 13- bnfclassunit did not output a valid object (matrix whose elements were rows instead of columns) 14- conversion bug from t_QUAD to t_REAL/t_COMPLEX 15- off-by-1 error in the history recovery after an error 16- in fprintferr() (debug messages), embedded %Z did not work correctly 17- rnfequation over Q yielded a SEGV 18- string() in compatibility mode corrupted the stack 19- it is now safe to have colours in prompt and input line under readline 20- default colours restored upon exiting 21- default colors in lib/gprc.default used 0 instead of -1 for "no color" 22- psi and lngamma could give wrong results when the argument was not real 23- the make test-graphic bench was missing a newline 24- Pol(break) gave a SEGV 25- x=1; Pol(1) gave a stupid error message IZ 26- tutorial.tex was unnecessarily rebuilt 27- typos in ggcd (cases nobody will ever access: gcd of a non-reduced LG fraction with an intmod, etc.) LG 28- incorrect handling of integrals of vectors 29- gcd of polynomials with non-exact coeffs gave stupid results (they are still often wrong, since the mathematical notion is rather imprecise) 30- typos in rnfkummer (incorrect flag handling) 31- typo in idealpowprime (negative exponent gave wrong denominator) 32- multiplication t_COMPLEX x t_COMPLEX used 4 mult. instead of 3 33- some modular functions (j, f, f2) rewritten to take advantage of new eta function (trueta) Changed: 1- ?? (gphelp) starts in detex mode (-d) from a console window. tmp files now placed according to the $TMPDIR environment variable (in /tmp by default) 2- /usr/local/lib/pari/data is a better place for the Galois resolvents (which are not included yet in the standard distribution) 3- The example for prompt in gprc.default to discuss escape sequences under readline 4- Configure now starts by searching the toplevel directory for a temporary readline installation 5- The output of default(colors) was confusing. It is a string now 6- third argument of polinterpolate can be arbitrary and is now optional ("x" by default) (it had to be numeric) 7- directory configure renamed config, some of the Makefiles in there as well (to avoid confusion) 8- the low_stack macro to facilitate dynamic stack expansion 9- if, back to GP main loop, the last command was a print1(), output an extra newline. This way the prompt is guaranteed to be anchored on column 1 (suppresses a readline display bug as well) 10- Due to 9, pari.el now supposes the prompt starts in col. 1 11- Better handling of version numbers (LG) 12- decodefactor() renamed to factorback() Removed: 1- The (unused, undocumented) Malloc_Procs functions and macros 2- The (now unused) error message numvarer 3- some (useless, undocumented) targets in the top Makefile 4- (useless, undocumented) function polgcd() Added: 1- This file ! 2- new flags -ch, -cb, -cu (colour support) to gphelp (see its header) IZ 3- OS/2 (+ enough tools...) supported by Configure 4- file examples/Inputrc (example of .inputrc for readline) 5- Weber f1 function implemented 6- Karatsuba multiplication t_REAL x t_REAL (development code, not used by PARI yet). Test it with install if you wish pari-2.7.5/COMPAT0000644000175000017500000010733312405547147012034 0ustar billbillThis file lists the incompatible changes between Version 2.x and older versions %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.6 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - eval() no longer evaluates its arguments in "permissive" mode: eval("1a") now produces a syntax error. - '|' is no longer a synonym for '||' (boolean 'or'); '&' for '&&' is still supported but deprecated. - GP set elements are no longer converted to t_STR (requiring "eval" to recover the underlying object). Arbitrary GENs can be stored in a set. - no longer allow 3 arguments in bestappr() [useless], no longer mix Pade approximants and continued fractions [too confusing: must a t_SER be converted to a t_RFRAC or be treated coefficientwise?]. Use bestapprPade() to obtain rational functions, and bestappr() to obtain rational numbers. - [non-Unix systems] the name of the preferences file is now "gprc.txt" (it remains ".gprc" on Unix systems) - removed rootsold() code : polroots(x, 1) is no longer accepted. - format of cached Bernoulli table: now a t_VEC of t_FRAC / t_REALs. Removed bern() macro. The new data must be accessed using bernfrac / bernreal. - forprime loop: no longer allow to modify the loop index ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. - rename ellpow -> ellmul - polrootsmod(, 4) is no longer accepted. The second argument must be prime. - binary(0) now return [] - arithmetic functions no longer accept vector / matrix arguments [ to later allow passing factorization matrices ]: use apply() - permtonum/numtoperm now use the standadr lexicographic numbering. - ellsigma: removed flags 3 and 4 [ inefficient algorithm using the product formula ] - removed member function 'w' (this is technical, and no longer needed:-) - ellpointtoz(E / Qp, ...), now return phi(P) [ used to return the same result for phi(P) and phi(-P) [ split multiplicative reduction ], resp. phi(P) + 1/phi(P) [ non-split reduction ] - ellinit(E / Qp).tate : the u component is now always a square root of u2, also in the non-split case (in which case it lives in a quadratic extension of Qp) - when timer = 1, no longer print timing if the time is negligible; in particular, no timing should be printed when defining a user function or and alias. - change nfbasis(T, flag, fa) to nfbasis(T, listP). flag was used to invoke round2 instead of round4 (inefficient=> useless) OR to only partially factor poldisc(T), up to primelimit (very dangerous since primelimit is a global variable). Now listP describes a list of primes, and we return a basis of an order which is p-maximal at all those primes: either a vector of primes, a factorisation (as fa before) or an integer B to indicated {p <= B} (a safe and flexible version of nfbasis(T, 1)). nfdisc() was changed similarly. - The proper way to initialize an nf structure when the polynomial discriminant is hard to factor is nfinit([T, listP]), where listP specifies a list of primes (see ??nfinit). nfdisc, nfbasis, all the polred functions allow analogous arguments. This is cleaner and more flexible than optionnal flags relying on the value primelimit (e.g. nfinit([T, nfbasis(T, 1)]), now deprecated). Also, the nfinit function now sees the local specifications directly and can take steps to fix problems. The result can also be certified (nfcertify) - renamed bezout() -> gcdext(), polresultant() -> polresultantext() - the prime table is now computed once and for all on startup and can no longer be increased by modifying primelimit: the dynamic forprime machinery allows fast primes up to primelimit^2 which is more than enough even with a small table. The default value of 500.000 is already larger than necessary - removed optional flag to factorpadic() / factorpadic0() [ enabling Buchman-Lenstra + round2 ] Use the default factorpadic(T, p, r), both under GP and in library mode. - default help text for a user function is now as in \u: ?fun produces fun = (args)->body - after addhelp(f,...), ?f no longer include default help text for a user function (function code). Type 'f' to see the function code. - rnf structure: added new components - lift(x,'v) / centerlift(x,'v) now only lift t_POLMODs in variable v, no longer (most) t_INTMOD / t_PADICs met along the way - 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. - the prid structure returned by idealprimedec: the anti-uniformizer tau (pr_get_tau / pr[5]) is now stored via its multiplication table * Specific to the PARI library: =============================== - renamed all libpari error codes [ pari_err() arguments ] - ellwp0(): remove precdl argument - rename stackmalloc -> stack_malloc - rename ggval -> gvaluation - simplify init_primepointer(n, p, &pd) interface => init_primepointer(n, &pd). Remove argument 'p', ignore the previous value of pd [ remove assumption that it pointed into a prime table ] and always set pd to a pointer into the private prime table. - powell, addell, subell renamed to ellpow, elladd, ellsub. - last tow arguments of FpX_factorff and FpX_rootsff have been swapped. - rnf_fix_pol() takes an extra argument, the calling function's name - rename leftright_pow_fold -> gen_pow_fold, leftright_pow_fold_i -> gen_pow_fold_i - upowuu(x,n) now returns 0 on overflow. Used to return x^n mod 2^BITS_IN_LONG - rename RgX_check_ZXY -> RgX_check_ZXX, ZXY_max_lg -> to ZXX_max_lg - removed gisfundamental, gkronecker, gbigomega, geulerphi, gissquarefree, gmoebius, gnextprime, gnumbdiv, gomega, gprecprime, gsumdiv, gdumdivk, znprimroot0 - rename zv_cmp0 -> to zv_equal0 - removed obsolete function weipell(). Use ellwpseries() - the prototype of nfbasis() changed [ remove 'flag'; if you needed it, use nfmaxord() ]. The old nfbasis0 / nfdisc0 are deprecated: don't use them. - removed obsolete Polred(): use polred() or polredbest() - rename exp_Ir -> expIr - the *_invimage function no longer accept a t_COL second argument. Use the RgM_RgC_invimage variant. They now return NULL when no solution exist (used to return a t_COL / t_MAT of length 1) - the forvec_start() function has been replaced by a standard iterator: forvec_init() / forvec_next() - renamed rnfelementxxx -> rnfeltxxx, rnfidealhermite -> rnfidealhnf - removed useless wrappers map_proto_GG, map_proto_GL, map_proto_lGG - renamed ZM_hnfremdiv -> ZM_hnfdivrem - removed useless functions gand, gor - removed useless function ratlift [ use Fp_ratlift ] - renamed gcmpX -> gequalX - renamed ordred -> polredord: useless function, use polredbest! - renamed recip -> serreverse - renamed FlxYqQ_pow -> FlxYqq_pow - FpXYQQ_pow/FlxYqq_pow: the order of the moduli S,T have been swapped to match FpXQXQ_pow - renamed gsh -> gsinh, gch -> gcosh, gth -> gtanh, gash -> gasinh, gach -> gacosh, gath -> gatanh, ggamd -> ggammah (follow GP names) %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - The "break loop" is now *on* by default, and no longer controlled by trap(), but by the default 'breakloop'. To get out of a break loop, hit or type 'next', 'return', or 'break' - trap() no longer allows installing default error handlers. - GP's break loop is now *enabled* by default [ set breakloop = 0 in your gprc to disable it ] - random() now uses Brent's XORGEN (replaces congruential linear generator) As a consequence, getrand() returns the FSR internal state array, used by setrand() and the prototypes of both functions changed. To adapt simple library code, replace long seed = getrand(); ...; (void)setrand(seed); by GEN seed = getrand(); ...; setrand(seed); The sequence of generated pseudo-random numbers are completely different. - install(): parser code 'E' and 'I' now refer to closure, not strings: 'I': closure whose value is ignored, like in for() loop 'E': closure whose value is used, like in sum() loop - changevar() [ use substvec ] and reorder() [ use variable() for the list of user variables ] have been removed - The quasi-periods e.eta (and elleta(e)) are now twice the old value, so that e.eta = 2 ellzeta(e,e.omega/2) - Change e.omega so that e.omega[1] / e.omega[2] belongs to the Poincare half plane [ used to be the inverse ]. - indexrank, indexsort and indexlexsort now return t_VECSMALLs - besselk no longer admits a flag, the default implementation caters for all cases - removed (obsolete) optional flag in ellap(), Mod() and gcd() - the weird extra argument to listcreate() [ maximal length ] has disappeared. In fact, listcreate() is now obsolete: juste use List() to create an empty list. It will grow as needed. - listkill() is also obsolete: no need for a specific function to kill old lists floating around. L = List() reclaims memory just as efficiently as listkill(L) would. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns; no need to kill the ones which are lists specifically. - local variables declared implicitly (user function parameters, loop indices) are now lexically-scoped. The keyword 'my' allows to declare lexically-scoped variables explicitly. - global(), being awkward to implement in the new parser model and essentially useless is now a no-op, scheduled for removal. - PariEmacs is now distributed as a separate package, and is no longer included in the PARI distribution - distinction between user functions and user variables has been removed. As a consequence, calling a user function without parentheses no more evaluate it. - syntax errors are no longer trap-ped, only runtime errors are. First, error trapping and compile-time errors are best left unrelated. Second, since the code is first byte-compiled, then evaluated, it made no sense trapping a syntax error that would necessarily occur in the first milliseconds after inputing the command to the interpreter. (Not so in the old evaluator which could notice syntax errors very late, and one was happy to be able to still salvage something when it bombed.) - quadray no longer allows an (optional) 3rd argument: was not properly documented, broke the symmetry between real / imaginary case (was ignored if D > 0), complicated the code, and was rather useless in any case. - the "minimum field width" component of the 'format' default is now ignored (was used only for integers in 'prettyprint' output mode and defaulted to 0 [no effect]). Use printf ! - removed the fieldw "minimum field width" field from the undocumented pariout_t struct - remove obsolete "prettyprint" support: printp / printp1 now act as print/print1 - the conversion style 'g' of the 'format' default now printfs in style 'f' if the decimal exponent is < -4 ( was: if the binary exponent is < -32 ), in order to conform to standard printf specifications. - all LLL variants now use an implementation of NGuyen & Stehle's algorithm The LLL-reduced bases will be different from previous versions. - plotinit: change the way default arguments are evaluated (omit dimension, instead of interpreting 0 in a special way) - nfbasistoalg / nfalgtobasis no longer accept t_VEC/t_COL/t_MAT (not being able to apply nfbasistoalg to nfalgtobasis(nf,x) was awkward and inconsistent; the doc stated that those were inverse functions, but they were not). Use matbasistoalg / matalgtobasis, which now also accept t_VEC/t_COL. - removed obsolete optional argument to quadhilbert(D < 0) - removed obsolete GP functions printp, printp1. Use print. - bittest(x, n) no longer accepts t_VEC arguments n - remove obsolete GP functions bnfclassunit, bnfreg, bnfclgp, bnfunit. Use bnfinit. - remove obsolete GP functions bnrclass. Use bnrinit or bnrclassno. - remove awkward flag '3' for bnfinit. Use bnfcompress(). - remove badly named bnfmake. Use bnfinit(sbnf). - idealmin now returns a number field element, instead of the associated "principal idele" - removed obsolete GP functions idealprincipal. Use number field elements "as is". - Functions quadunit(), quadregulator(), and factor() no longer apply componentwise to vector / matrix arguments. Use apply() - factorback() no longer accepts an optional 3rd argument (nf). Use idealfactorback(). See also nffactorback(). - no longer export private library function incgam2. Remove it also under GP when compatible = 3. Situation is the same as incgam1 (removed long ago), 1.39.15 doc stated both were provided "for debugging only". - Change of behaviour for Set(t_STR): Set("1") used to return ["1"], now it returns ["\"1\""], i.e returns the set whose element evaluates to the character string "1". - Flags 4, 5, 6 (useless) have disappeared in nfinit() - norml2(t_POL) now returns the expected (square of) the polynomial L^2 norm. Use x * conj(x) to get back the old behaviour. norml2 now raises an error on t_POLMOD and t_FFELT components; used to add relative norms as in ? norml2([Mod(Mod(1,3)*x,x^2-2), 2]) %1 = Mod(2, 3) - kill(z) has essentially the same effect as z = 'z [ it also kills addhelp messages attached to z, and works for aliases and installed functions too ] - removed optional flag to rnfconductor, use rnfisabelian. - changed the "zetakinit" format: bnf no longer included - factor(t_INT/t_FRAC, lim) used to trial divide by primes up to min(lim, primelimit). Now we trial divide up to lim and raise an error if lim > primelimit. [ Having the routine return an obviously "wrong" result depending on an invisible parameter was not a good idea. ] - factor(t_INT/t_FRAC, 1) was the same as factor(t_INT/t_FRAC, 0). Now abide by the input value and leave (..., 0) as the single special case (shortcut for "the largest precomputed prime") - listsort(L) no longer returns the list L: it now returns nothing. (No point in sorting in place if we must immediately copy the result.) - ellwp now outputs a number of terms equal to the default seriesprecision, instead of *twice* that number. - inverse trigonometric functions (acos,asin,atan,acosh,asinh,atanh): values on the branch cuts changed to conform to standards, e.g. "implementations shall map a cut so the function is continuous as the cut is approached coming around the finite endpoint of the cut in a counter clockwise direction." (ISO C99) - bnfinit no longer outputs a warning when fundamental units couldn't be computed (annoying and rather useless) [#1166] -[Configure] no longer support a link to an uninstalled readline library in PARI toplevel - thue() no longer outputs a Warning when the result is conditional on the GRH. - addprimes() now includes its argument as-is (used to take gcds, making an insertion linear in the table size instead of O(1); filling an inially empty table was quadratic in the final table size). They must be true primes, otherwise number theoretic routines may return wrong values. [#322] * Specific to the PARI library: =============================== - allocatemoremem() is gone. Use allocatemem(). - rename fprintferr() -> err_printf(). - rename TIMER -> timer_delay, TIMERread -> timer_get, TIMERstart -> timer_start, msgTIMER -> timer_printf - rename gener_Fp -> pgener_Fp, gener_Fl -> pgener_Fp [ contrary to 'gener', these assume that their argument is prime ] - rename Flx_rand -> random_Flx, FpX_rand -> random_FpX - rename cyclo -> polcyclo (GP name), subcyclo -> polsubcyclo (GP name), tchebi -> polchebyshev (GP name), legendre -> pollegendre (GP name) - only scalar types (and vectors/matrices of such) are allowed in gaffect and gaffsg. - pol_x and pol_1 are now functions, not global arrays. Use pol_x(v) instead of pol_x[v]. polvar[] and ordvar[] have disappeared - rename ZY_ZXY_resultant -> ZX_ZXY_resultant, ZY_ZXY_rnfequation -> ZX_ZXY_rnfequation and FpY_FpXY_resultant -> FpX_FpXY_resultant - FpX_ functions no longer accept p==NULL. - Fl_pow renamed to Fl_powu [ exponent may not be negative ] - rename pointch -> ellchangepoint, coordch -> ellchangecurve, ordell -> ellordinate - remove obsolete undocumented functions outerr, outbeauterr, outsor, outtex. Rename voir -> dbgGEN. Functions brute, outbrute, matbrute, outmat, sor, outbeaut are obsoleted and no longer documented. - rename errfile -> pari_errfile, infile -> pari_infile, logfile -> pari_logfile - manage_var obsoleted (kept for backward compatibility, to be removed), use pari_var_init, pari_var_next, pari_var_max_avil, pari_var_create instead. - rename sqred -> qfgaussred, signat -> qfsign - rename gscalmat -> scalarmat, gscalsmat -> scalarmat_s, gscalcol -> scalarcol, gscalcol_i -> scalarcol_shallow - removed obsolete apell2, ellap0. Rename apell -> ellap. - typedef for type col_counter [last argument of unused, undocumented plot_count()] changed (must be malloced since MAX_COLORS is no longer a constant) - rename gissquarerem -> gissquareall, uissquarerem -> uissquareall, Z_issquarerem -> Z_issquareall (analogy with sqrtrem was faulty: we do not store a remainder but the square root) - rename assmat -> matcompanion, polymodrecip -> modreverse - removed obsolete undocumented bruteall() - %Z is no longer a valid conversion specification for PARI formats, since this is now handled as a length modifier. Use %Ps instead. - rename pariprintf -> pari_printf (%Z conversion disappeared, use %Ps) - rename pariputc -> pari_putc, pariputs -> pari_puts, pariflush -> pari_flush - rename gpmalloc -> pari_malloc, gprealloc -> pari_realloc, gpfree -> pari_free - rename derivpol -> RgX_deriv - obsolete library functions roots2 and rootsold are no longer public - rename factorpadic4 -> factorpadic, factorpadic2 now static - the "prec" parameter has disappeared in all floating point LLL various - remove obsolete function factpol() - rename library functions nfhermite -> nfhnf, nfhermitemod -> nfhnfmod, nfsmith -> nfsnf - rename subres -> resultant, subresall -> resultant_all. - remove obsolete discsr. Use RgX_disc (or quad_disc, qfb_disc...) - remove obsolete allbase, base, base2, factoredbase, smallbase, discf2, factoreddiscf, smalldiscf. Use nfbasis0 / nfdisc0 / nfmaxord - rename library functions matrixqz2 -> QM_ImZ_hnf, matrixqz3 -> QM_ImQ_hnf, matrixqz -> QM_minors_coprime - rename library functions hil0->hilbert, hilii->hilbertii - rename library functions srgcd -> RgX_gcd - rename library functions ismonome -> RgX_is_monomial - remove obsolete buchray, buchrayinit, buchrayinitgen: use Buchray. - rename library functions minideal -> idealmin and change prototype - rename library functions element_mulmodpr -> nfmulmodpr, element_powmodpr -> nfpowmodpr, element_val -> nfval, element_add -> nfadd, element_divmodpr -> nfdivmodpr, element_mul -> nfmul, element_pow -> nfpow, element_div -> nfdiv. - remove obsolete library function smallfact; use boundfact or Z_factor_limit - rename mu -> moebius, gmu -> gmoebius, phi -> eulerphi, gphi -> geulerphi, phiu -> eulerphiu, gener -> znprimroot, ggener -> znprimroot0, racine -> sqrtint [ NO COMPATIBILITY #define PROVIDED: too dangerous ] - rename regula -> quadregulator, fundunit -> quadunit - remove obsolete library function gracine - remove obsolete library function ispsp, gispsp. Use ispseudoprime or BPSW_psp. - remove obsolete library function gregula, gfundunit. Use quadregulator and quadunit - removed obsolete 'prec' argument from prototypes of idealmul0, idealmulred, idealpow0, idealpowred, ideallllred, algdep, algdep0, lindep, lindep0 - removed obsolete library functions ideallistunit, ideallistunitgen, ideallistzstar, ideallistzstargen. Use ideallist0. - removed obsolete library function algdep2. Use algdep0 (same arguments). - removed obsolete library function Mod0. Use gmodulo. - factorback() now accepts a single argument. - rename library functions factorback0 -> factorback2, subfields0 -> nfsubfields, ideallllred -> idealred0, zideallog -> ideallog, isunit -> bnfisunit, ideal_two_elt* -> idealtwoelt* - changed prototypes of bnrdisc, bnrconductor, bnrisconductor [ actually renamed bnrdisc0, bnrconductor0, bnrisconductor0 ]. Just use the new prototype, it's more convenient. - removed obsolete library function kerin1. Use kerint or [simpler if LLL reduction of the returned basis is not deisred] ZM_lll(,0.99,LLL_KER) - rename library functions initell -> ellinit, smallinitell -> smallellinit initalg -> nfinit, initalgred -> nfinitred -> initalgred2 -> nfinitred2 primedec -> idealprimedec, powraw -> qfbpowraw, compraw -> qfbcompraw - rename library function u2toi -> uu32toi. - remove obsolete library functions sor, outbrute, outbeaut - basic kernel functions involving a t_INT and a t_REAL now return a t_REAL, e.g. divsr(0, x) or mulir(gen_0,x) return real_0(...) [ used to return gen_0 ] ==> much better control of object types when writing kernel code. Generic functions (gmul, gdiv), as called from gp still return a result as precise as possible given the input: 0 * 1. --> gen_0 - deprecated global constants gi; use mulcxI, gen_I() or mkcomplex(). - deprecated global constants geuler & gpi; use mpeuler() & mppi(). - changed prototype of galoisconj: galoisconj(x) -> galoisconj(x,NULL) - commented out a large section of pariold.h. Define PARI_OLD_NAMES to recover compatibility macros for old friends like 'un' and 'lstoi' - rename greffe -> RgX_to_ser and remove the "use_pari_stack" flag - rename Buchall -> Buchall_param and export a new Buchall with a simplified interface. - rename certifybuchall -> bnfcertify - the bitvec family function was replaced by the new F2v family functions. - prototype change: added a flag to the (mostly useless) function rnfdedekind(), the version with the flag set is more useful. - rename gcmp0 -> gequal0, gcmp1 -> gequal1, gcmp_1 -> gequalm1 - rename ZX_caract -> ZXQ_charpoly and swap arguments. - rename RgXQ_u_pow -> RgXQ_powu - remove function delete_named_var (using kill0 instead). - remove RgM_ishnf (use ZM_ishnf instead). - rename leftright_pow to gen_pow, leftright_pow_u to gen_powu. - remove unused 'prec' argument in rnfinitalg(). Rename rnfinitalg -> rnfinit - remove unused 'prec' argument in bnfisnorm() - add a third precdl argument to gtoser() - the last 2 arguments of ellwp0 (prec and precdl) have been swapped - prototype of "summation" functions (suminf,intnum,prodinf,etc.) now is fun(void *E, GEN call(void*, GEN),...) %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * General: [ use GP function names in description ] ========== - Default args for user defined functions now evaluated when function is called (used to be: at definition time) E.g f(x) = local(z = x); z. Before: f(2) -> x Now: f(2) -> 2 - rnfisnorm() input format has changed. Older version was complicated and only worked if rnfequation(bnf, p, 1)[3] == 0 [otherwise, crash]. Use rnfisnorminit() now. - rnfidealreltoabs, rnfidealup: now return a Z-basis as a vector of elements in the relative extension, instead of a meaningless HNF matrix wrt an unknown basis. Was especially dangerous if the extension also existed in nfinit form, since the HNF matrices were _not_ ideals wrt this nf structure. [ also consistent with rnfeltreltoabs ]. Use the following construction instead, referring to an explicit NF structure: \\ return y = rnfidealup(rnf,...) as an ideal in HNF form associated to \\ nf = nfinit(rnf.pol); idealgentoHNF(nf, y) = mathnf( Mat( nfalgtobasis(nf, y) ) ); - the "bit accuracy component" for computations of principal ideal generators (bnfisprincipal), units (bnfunit), and some of the bnf structures has been removed. - the "technical parameter" to bnfinit() has been shortened to 3 components (the others were deprecated / useless): [c, c2, nrpid]. The output format has changed (technical components). - poldegree(0) now returns -VERYBIGINT, not -1. Before using d = poldegree(x), always check for 0 first: either (x == 0) or (d >= 0) as you prefer. Never check for d == -1 or -2^31-1 which is not portable. - ellheight now uses the standard normalization: twice the value it used to return. The values returned by ellbil() and ellheightmatrix are unaffected. In particular, ellheightmatrix() is the polar form of elleight(), and ellbil now satisfies the proper identity B(P, Q) = (h(P+Q)-h(P)-h(Q)) / 2 - ':' no longer allowed as a substitute for ';' if compatible = 0. Use GP2C semantics [ x:int, v:vec ]. For the time being the type information is discarded. - log(x, {flag}): optional flag removed. Decide alone whether to use AGM. - valuation(x, 1) used to return 1, valuation(x, -1) returned 0 if (x >= 0) and 1 otherwise. Not anymore: error message. - bnrdisclist has lost its 4th argument 'flag', and omitting the archimedean component now means that all 2^r1 possible values are substituted (formerly: indicate no ramification at infinity). - 'buffersize' default has disappeared: it is adjusted internally whenever needed. The -b xxx flag to gp is a no-op. - the member function bnr.zkst is deprecated, use bnr.bid.clgp - the member function bnr.futu is deprecated. Please don't use bnr.tufu either. - use \frac instead of \over in TeX output. Define \def\frac#1#2{{#1\over#2}} if you insist on using plain TeX and run into problems. - automatic concatenation for strings: use longest match for expression. print("a"[1]) is not valid since "a" is not a vector print("a", [1]) prints 'a[1]'. - isprime() now guarantees primality, use ispseudoprime() for fast pseudo-primality tests. - default() now always returns the value of the (possibly changed) default. No need for a flag anymore. - semantic of t_SER with inexact coefficients is now the same as for t_POL: the sign is 0 iff all coefficients are zero. Either there are no coefficients, or the leading coefficient is an inexact zero. - No longer assume that part of an object is "permanent" when it is out of the stack (was used by INTMOD/POLMOD/PADIC). Always copy it. As a result, 'gmodulo' and 'forcecopy' become obsolete. Rename gmodulcp -> gmodulo. * Specific to the PARI library: =============================== Incompatible changes: --------------------- - gsize() -> gsizeword() [conflict with gtk] taille2 -> gsizebyte() - hnfhavas removed (didn't work properly, hnflll provides an alternative) - real zeroes are now coded on 2 words. Beware of constructs like t = cgetg(lg(x), t_REAL); gaffect(y, t). If x = 0, so will be t. - polgalois(): old format deprecated. New preferred format for result has 3rd component giving numbering among all transitive subgroups of S_n [ was ad hoc up to 7, as described above for n >= 8 ]. Old format is still the default, but will eventually change. Use default(new_galois_format, 1) or, in library mode, set global variable new_galois_format to 1 to enable the new format. - The nf structure output by nfinit has changed: *) nf.zk is now T2-LLL-reduced, not in HNF wrt the power basis *) the internal components of nf[5] have changed (MC and T2 not needed anymore) - polred & polredabs do not take a 'prec' argument anymore [was unused] - gentimer / genmsgtimer / get_timer have been removed. They are superseded by TIMER and msgTIMER which are fully reentrant and easier to use. - (undocumented) macros buch[gen | genfu | init | iniftu] - rnfisnorm() prototype has changed [ + need to call rnfisnorminit first ] - incgam4 renamed to incgam0, incgam3 renamed to incgamc - prototypes of buchall and smallbuchinit have changed (much simpler) - co8() renamed to quadtoc() - ker_mod_p() renamed to FpM_ker [ and supplemented with many analogous modular routines ] - nfreducemodpr2() removed, use an nfmodpr structure from nfmodprinit() or zkmodprinit() instead - smodsi() removed [ not well defined ]. Use either modsi() or umodui() - Many error codes were removed. It is usually better to use only talker outside libpari. - Macro BITS_IN_RANDOM has been removed. Used to be 32. - mymyrand() has been removed, use pari_rand31() or pari_rand() instead - diviiz(x,y,z), divisz, divsiz and divssz always assign the euclidean quotient [ used to depend on the type of z: if t_REAL computed exact quotient ]. Use rdivii, rdivis, rdivsi, rdivss for analogous functionality (no "z" variant); - mpdivz(x,y,z) assigns the euclidean quotient when x,y are t_INT (used to depend on the type of z) - removed inconsistently named macros mpinv[sir]r [ were "z" functions ] - removed useless routine shifts [ use shifti( stoi() ) ] - library interface of functions intnum, prodeuler, suminf, sumalt, sumalt2, sumpos, sumpos2, prodinf, prodinf1 [ use GEN (*eval)(GEN,void*) everywhere instead of entree * ] - changed the prototype of bnrdisclist0 - removed ideallistarch0, ideallistarchgen, ideallistunitarch, ideallistunitarchgen. Just use ideallistarch. - change the output of ideallist with technical (flag 2,3) [ with units ]: instead of two vectors, output a vector of 2-component vectors. change the input of all list routines (bnrclassnolist, bnrdisclist) accordingly. - rename gtrans_i -> shallowtrans, concatsp -> shallowconcat. - pari_err(warner | warnmem | warnfile | warnprec,) no longer accepted. Use pari_warn. Partially compatible changes: ----------------------------- [ not mandatory for your program to work with 2.3, since compatibility macros support the old names but are likely to become mandatory in 2.4, so we advise you to update soon ] - typecasting macros (e.g. ladd(), lmul() ...) are obsolete and shouldn't be used in new programs. Use accessors gel() and friends. - stack locations used to be of type long or ulong, now they have a dedicated type pari_sp [ pari stack pointer ] - in order to compare variable numbers, use the macro varncmp() instead of < or > operators. - access to the prime numbers table is done via the macros NEXT_PRIME_VIADIFF or NEXT_PRIME_VIADIFF_CHECK. - direct access to the mantissa of t_INT is deprecated. Instead you should use the t_INT API (macros int_MSW, int_LSW, int_precW, int_nextW, int_W). This will ensure your code is compatible with both native and GMP kernels. - the macros lgef / setlgef / evallgef have been removed. t_POLs no longer include an "effective length". One should use lg() for t_POLs as for most other types. Don't use lgef() in new code. lgef() and setlgef() are aliased to lg() and setlg(). They will break on hackish code accessing directly the first component of t_POL objets, e.g x = cgetg(20, t_POL); x[1] = evalsigne(1) | evalvarn(0) | evallgef( 10 ) /* 10, not 20 */ ... setlgef(x, 20); /* now create/use further coefficients */ - types t_FRACN, t_RFRACN and gred() have been removed (complicated, unused, and very inefficient). There are now aliases to t_FRAC, t_RFRAC and gcopy respectively for backward compatibility. - renamed nfdivres -> nfdivrem, poldivres -> poldivrem - renamed permute -> numtoperm, permuteInv -> permtonum - renamed gzero -> gen_0, gun -> gen_1, gdeux -> gen_2, polx -> pol_x, polun -> pol_1 - renamed gegal -> gequal, gegalgs -> gequalgs, gegalsg -> gequalsg, egalii -> equalii - renamed binome -> binomial, chinois -> chinese - renamed apprgen9, apprgen -> padicappr, factmod9 -> factorff - rename resss -> remss, ressi -> remsi, resis -> remis, resii -> remii, gres -> grem - rename divise -> dvdii, gdivise -> gdvd, mpdivis -> dvdiiz, mpdivisis -> dvdisz - rename mpent -> mpfloor - rename isprincipalrayall -> bnrisprincipal, rayclassno -> bnrclassno rayclassnolist -> bnrclassnolist - rename globalreduction -> ellglobalred, localreduction -> elllocalred - taniyama(e) is deprecated. Use elltaniyama(e, prec) instead of old = precdl; precdl = prec; x = taniyama(e); precdl = old; - rename lisexpr -> readexp, lisseq -> readseq - rename flisexpr, flisseq -> gp_read_str - rename lisGEN -> gp_read_stream - rename idmat -> matid - rename coefs_to_col -> mkcoln, coefs_to_int -> mkintn coefs_to_pol -> mkpoln, coefs_to_vec -> mkvecn - rename wf -> weberf, wf1 -> weberf1, wf2 -> weberf2 - rename err -> pari_err, pariputsf -> pariprintf - rename rnfhermitebasis -> rnfhnfbasis - rename gcarreparfait -> gissquare, gcarrecomplet -> gissquarerem - rename lseriesell -> elllseries - gmodulo and forcecopy are obsolete. Use gmodulcp and gcopy. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * The calculator GP: ==================== - most function names have changed (see misc/new.dic or use whatnow under GP) - lowercase / uppercase letters distinguished. - the syntax \var = value is not recognized anymore. Use standard metacommands instead. (setting the compatibility level "compatible" to 3, with "default" will give you those three back). - strict parenthesis matching before executing the command (set strictmatch to 0 to get old behaviour) - functions label / goto have been removed (use break/next/return instead). - conjugation x_ has been removed. '_' can be freely used in identifiers. - \k metacommand removed - result history is now cyclic (older results are erased when the maximal size "histsize" is reached). - the Set() function turns objects into strings (so that set functions are able to treat arbitrary objects). Use eval to turn them back to GENs. - the type() function returns a string and not a number. - sum(X=a,b,...,x) yields x if b oo-loop if class number is divisible by 27449 [#1197] BA 4- [gp2c] error("foo") did not work. 5- wrong generators in quadclassunit(D > 0) [ fix qfr3_pow / qfr5_pow ] [#1195] 6- setrand(45);quadclassunit(185477) -> SEGV [#1200] 7- fix derivnum for large arguments [#1201] 8- "#if READL" always evaluated to "FALSE" in gprc [#1202] 9- matsnf(non-square matrix, 4) --> SEGV [#1208] HC 10- fix p-adic Gamma inefficiency for small p: gamma(O(2^20))->no answer %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.4 (released 29/04/2011): Fixed BA 1- FpX_gcd did not garbage-collect for large input. BA 2- 'make all' failed to build the documentation. 3- typo in polgalois() when new_galois_format is 0 : returned [3,1,2] instead of [3,1,1] for C_3 4- rnfkummer was using too much stack. 5- nfgaloisapply did not work on extended ideals. 6- Strprintf and printf0 prototypes were wrong. 7- Mod(4*x+1,Mod(1,2)*x) -> SEGV [#1116] 8- gcd(t_INTMOD, t_FRAC) -> SEGV 9- qfjacobi failed on a matrix of zeros (or in presence of 0s of large exponent) [#990] 10- t_SER / t_SER where denominator has 0 leading term -> SEGV [#1120] 11- (t_COMPLEX of t_INTMOD) + t_PADIC -> SEGV [#1121] 12- (t_QUAD of t_INTMOD) + t_PADIC -> SEGV [#1122] LGr13- bnfinit: various performance improvement. BA 14- several instance of random garbage collection were broken. BA 15- [install]: support for D0,G, and D"str",s, in prototype code. BA 16- [gp2c]: foo(x:mp)=... did not work. 17- when the divisor's leading term was 0, RgX_divrem(,,&rem) created rem before the quotient (invalidating the use of cgiv() suggested in the documentation) [#1129] 18- gadd(t_COMPLEX of t_REAL, t_QUAD = 0) -> SEGV [#1131] 19- log(11+11^2+O(11^3)) -> bug in log_p [#1136] BA 20- (ffgen(ffinit(2,10))*0)^-1 -> oo-loop BA 21- ispseudoprime(-3,0) != ispseudoprime(-3,1) BA 22- text form of a closure now include the closure context. BA 23- reading compressed files could corrupt the stack. BA 24- t_CLOSURE==t_CLOSURE and t_CLOSURE===t_CLOSURE did not work. 25- gequal1(0.*x + 1) returned 0 26- ispower((100!)^2) -> 0 [#1155] Affected pure powers divisible by more than 22 of the 26 primes <= 101. (introduced in 2.4.3) BA 27- LLL could fail (rarely) due to insufficient precision [#1154] 28- rnfisnorminit(y,x^2-Mod(2+y,y)): polynomial not in Z[X] in nfinit [#1157] 29- factorff failed to merge identical irreducible factors [#1159] BA 30- ploth(x=0,1,0,"Complex|Recursive") -> SEGV [#1163] 31- mathnf(dim > 8) could return a non-HNF upper triangular matrix [#1153] BA 32- forsubgroup() did not handle break/next/return. 33- modular resultant, e.g. rnfequation(polcyclo(17,y), x+y^6,1) [#1151] 34- gequal1(x) / gequalm1(x) did not implement gequal(x, 1) for t_COL/t_MAT 35- matsize(vecextract(M,0,y)) -> [;] instead of matrix with 0 and the requested number of columns [#1170] 36- readline completion : allow commas ',' in directory names [#105] 37- List() == List() returned 0. 38- [Configure] C_INCLUDE_PATH was not used when looking for libgmp BA 39- polroots(1) returned [] instead of []~. 40- a succession of in breakloop context would reinitialize timer 41- matsnf(matdiagonal([x,0])) --> [x,0] instead of [0,x] BA 42- qfbred(large discriminant, small prec): precision too low in truncr [#1173] PMo43- erfc(large x) was slow and inaccurate [#364] 44- erfc() : allow t_COMPLEX inputs 45- stack corruption in ifac_decomp_break() [#1115] 46- factor(0) returned 0^1, but factorint(0) raised an error. Allow factorint(0), core(0), coredisc(0), etc. 47- ellwp, ellzeta, ellsigma only used realprecision, instead of the input precision [#1184] BA 48- tuning for 32bit and 64bit, with or without GMP5. 49- idealintersect(K, 1/2,1/2) -> 1/4 instead of 1/2 [#1192] Changed LGr1- universal constants (gen_0,gen_1, etc.) are now read-only 2- qfjacobi : sort eigenvalues by increasing order 3- [libpari] gtoser : add a third precdl argument. 4- [libpari] swap the last 2 arguments of ellwp0 (prec and precdl) 5- ellwp now outputs a number of terms equal to the default seriesprecision, instead of *twice* that number. 6- Ser, ellwp, taylor, elltaniyama: add an optional 'precdl' argument (by default equal to 'seriesprecision'). One no longer has to rely on (and change locally) a global variable to handle conversion to power series. LGr7- add information to the version() output [backward compatible if version() used as recommended in the documentation] [#1130] 8- O(x^0) is now printed as is, not as O(1). t_SER and t_PADIC are now treated in the same way. 9- inverse trigonometric functions (acos,asin,atan,acosh,asinh,atanh): values on the branch cuts changed to conform to standards, e.g. "implementations shall map a cut so the function is continuous as the cut is approached coming around the finite endpoint of the cut in a counter clockwise direction." (ISO C99) [initial patch Richard Kreckel, #1084] BA 10-[libpari] nf_get_TrInv renamed to nf_get_diff 11- Qfb() : forbid square discriminants (-> corrupted objects [#1145]) 12- allow gequal1 / gequalm1 to return 'true' for t_SER 13- follow-up to (2.4.3, C104) [#1156]: - stop using the undocumented feature Z_factor_limit(x,1) = Z_factor(x). - abide by the "lim" parameter in all cases : factor(100,1 or 2) -> [10; 2] (was [2,2; 5,2]) 14- include GP defaults in the function description system + use standard hashtables instead of ad hoc types 15- cleanup and document term_color() and term_get_color() BA 16- prototype of summations functions now is fun(void *E, GEN call(void*, GEN),...) BA 17- traversesubgroups renamed to forsubgroup. 18- t_QFR with the same coefficients but different distance component are now tested equal by == (they are still different according to ===). 19- bnfinit no longer outputs a warning when fundamental units couldn't be computed (annoying and rather useless) [#1166] 20-[Configure] no longer support a link to an uninstalled readline library in PARI toplevel 21- thue() no longer outputs a Warning when the result is conditional on the GRH. 22- [libpari] rename TIMER -> timer_delay, TIMERread -> timer_get, TIMERstart -> timer_start, msgTIMER -> timer_printf BA 23- polrootsff now returns a t_COL 24- default(a, b) used to return "b". Now returns gnil 25- [libpari] remove allocatemem0 [make it private to GP], write allocatemem 26- matdet() : allow Guass-Bareiss to develop somewhat wrt. rows/columns [ cf test O1 in Lewis-Wester's bench ] 27- addprimes() now includes its argument as-is (used to take gcds, making an insertion linear in the table size instead of O(1); filling an inially empty table was quadratic in the final table size). They must be true primes, otherwise number theoretic routines may return wrong values. [#322] 28- rename fprintferr -> err_printf, flusherr -> err_flush 29- ellpow (CM case). Try to determine the discriminant of the endomorphism ring first [#1186] Added BA 1- trap keyword "syntaxer" to trap syntax error from eval. BA 2- Flx_shift now support negative shift BA 3- [gp2c] add description _(_) for closure evaluation BA 4- PARI function FpX_halfgcd() and subquadratic FpX_gcd(), FpX_extgcd() BA 5- PARI function Flx_halfgcd() and subquadratic Flx_gcd(), Flx_extgcd() BA 6- random() now allow to draw random polynomials BA 7- PARI functions pol_0, pol0_Flx, pol0_F2x VB 8- [mingw] --datadir=@ option to Configure BA 9- PARI functions FlxqX_div 10- PARI function ismpzero BA 11- PARI function bnr_get_clgp 12- new default 'histfile' (to save readline history in between sessions) 13- PARI function cmp_universal BA 14- [gp2c] add descriptions to support intnum/suminf type functions. BA 15- function diffop 16- PARI function zero_Flm_copy 17- PARI function mantissa_real BA 18- PARI functions F2v_clear, F2m_clear, Z_to_F2x, F2x_set, F2x_clear, F2x_flip, F2x_coeff BA 19- PARI functions F2xq_sqrt, F2x_deriv BA 20- PARI functions FpXQ_trace, Flxq_trace, F2xq_trace BA 21- PARI functions FpM_det, Flm_det, F2m_det Removed BA 1- PARI function CM_CardEFp (ellsea script deprecated). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.3 (released 08/10/2010): Fixed 1- \h m-n no longer worked BA 2- some error messages displayed internal token names (e.g for '1) 3- named colors in 'graphcolormap' were not portable across graphic drivers 4- setunion(Set(),Set()) -> SEGV [#714] DE 5- [Solaris] pari.desc won't compile [#715] 6- 822.pm broke the formatting of inline program examples 7- memory leaks in pari_close_opts [ freeep(), parser stacks, some defaults... ]. FIXME: calls to getpwuid introduce (small) leaks 8- ZV_Z_mul might not reset clonebit. 9- nfeltreducemodpr --> gerepile errors [#716]. Also SEGV for residue degre > 1 (when p does not divide the index) JD 10- write1("/dev/null", foo);1 --> extra newline JD 11- is_dir_stat() gave incorrect results on special files (pipes,...) JD 12- read() would block on pipes 13- nfeltreducemodpr used different canonical representatives than all other modpr routines [#719] 14- rnfconductor(,,1) did not recognize some abelian extensions [#718] (when the discriminant of a defining polynomial for the absolute number field could not be factored). Related to Changed-4. 15- polgalois could confuse S_11 and F_110(11) if a certain polynomial discriminant could not be fully factored. Related to Changed-4. 16- a = 0./x; a+a --> 0. BA 17- [from 2.4.2] use of pointers in recursive expressions [#717] BA 18- [from 2.4.2] trap() did not restore evaluator states [#722] 19- simplifications missed when adding t_RFRAC [#721] 20- gtofp(1 + 0*I, prec) should not return 1. + 0.*I but 1. gtofp(0 + (tiny real) * I, prec) should make sure the real part is converted to a zero of sufficiently small exponent (otherwise the modulus of the result is zero, because 1E-100 + 0E-28 = 0E-28) 21- factor(500501^36): impossible assignment I-->S 22- quadray(-7,6) [or other "impossible conductors"] --> oo loop [#725] 23- acosh([Pol(1)]) -> gerepile error [#728] (same asin, asinh) 24- rnf functions sometimes do not reduce their output when relative extension has degree 1 [#727] 25- zetakinit(bnfinit(...)) -> gerepile error 26- zeta(1-2^31 or 1-2^63) -> SEGV [#730] BA 27- priority of << had become lower than priority of * (should be =) 28- last digit of polylogs was wrong BA 29- missing GC in the leftrightpow functions 30- bnr=bnrinit(bnfinit(y^2-229,1),5,1); rnfkummer(bnr,,3) --> oo loop 31- mathnf(a,1) could have negative entries if non-trivial kernel [#741] 32- [Configure -pg] some variables not written to pari.cfg 33- missing subfields in nfsubfields [#744] 34- [readline] or would fail on 'fun()'. Delete trailing garbage in help routine. 35- modular matrix inversion routines used O(n^2) inversions instead of O(n) 36- print1() + read() or extern() + error/warning ==> missing \n 37- infinite loop in nffactor [#751] 38- ellordinate couldn't handle t_FFELTs 39- eint1(10,10) completely wrong 40- ispower broken due to 1) uninitialized variable, 2) insufficient precision [#916] 41- compilation fails with yacc unable to handle parse.y [ add explicit rule in Makefile to prevent from generating a wrong one ] 42- duplicate factors in nffactor (easy cases) [#761] 43- ellisoncurve(e, P) didn't check that "point" P had the correct format 44- znlog(...,znprimroot(p)) --> SEGV [#765] 45- wrong signs in bnfisintnorm e.g. [bnfinit(x^3+5), 5] -> x [#767] 46- x/(x+2) * Mod(1,2) -> Mod(1, 2)*x/(x + 2) [ should be Mod(1,2) ] 47- substpol(x/(y^3*x+1),y^2,1) -> x/(y^3*x + 1) [ should be x/(y*x+1) ] 48- missing sanity checks in rnfbasistoalg() 49- setrand(1); E=ellinit([0,0,0,1,T^4]*Mod(1,ffinit(2,7,T))) --> "weird base ring; can't divide" 50- nffactor(nfinit(y),x*y) nffactor(nfinit(y),x^2*y+1) nffactor(nfinit(y),x^2*y) --> errors or SEGV. [#769] 51- hilbert(1,1,1) --> oo loop [#770] 52- nffactor(y^2+1, x+1/2) --> x+1/2 [ not integral ] 53- nffactor(y^2+1,x*y+1) --> x*y + 1 [ not normalized, missing POLMOD ] 54- nffactor(y^2+1,x^2+2*y+1) --> x^2+2*y+1 [ missing POLMOD ] 55- ellpow() with CM raised a "division by 0" instead of returning [0] [#777] 56- ellpow(e,z,2^20*I) --> norm too large in CM. 57- p=x^4-x^3+x^2-x+1; tnf = thueinit(p); thue(tnf,1) -> missing solutions (could occur whenever p has no real root) [#764] 58- missing GC in numtoperm() 59- harmless uninitialized memory read in mulrrz_i() 60- sigma(..., 2) --> SEGV [ introduced in 2.4.1 ] [#783] 61- tuning problems in bnfinit bnfinit(polredabs(quadhilbert(-2939))) --> oo loop 62- minor inaccuracy in GMP kernel (affir) 63- missing GC in gamma / lngamma 64- obscure SEGV when setting 'log' in a file read from command-line as gp foo.gp [#789] 65- check that moduli are compatible in Rg_to_Fp(t_INTMOD, t_INT) 66- matsolve([1;2;3],[1,2,4]~) --> [1]~ (should raise an error) 67- allow polredabs(x in Q[X]) BA 68- [galoisinit] Documentation of "weakly" supersolvable was incorrect. 69- binomial(t_REAL or t_COMPLEX, k) was very slow for large k 70- quadclassunit(-3 or -4) --> one extra (obsolete) component. BA 71- the evaluator did not garbage collect huge expressions [#713] BA 72- changing a function in use caused a crash [#784] 73- vecsort() would not check the type of element in 1-dimensional vector [ e.g. vecsort([I] now raises an error ] 74- RgX_val would raise a SEGV on t_POLs with exact *non-rational* 0 leading coeff, e.g. Mod(0,2)*x 75- SEGV (stack corruption) in idealval(K, rational number, pr) [#808] 76- All the charpoly(x,v) variants failed when v > variable(x) BA 77- conjvec did not support FFELTs. 78- memory leak in t_LIST handling 79- polrootsmod(,1) could return an incomplete result [when 0 was a root or there was a double root], e.g. polrootsmod(x^3 + x^2 + 21*x,23,1) IM 80- lngamma(x) gave incorrect results (off by 2*Pi*I) when real(x) was a negative half-integer. 81- trying to write to a binary file and failing leaked a file descriptor 82- long-standing stack corruption when pressed during gclone [#458] 83- idealaddtoone had problems with 0 ideals [#829] 84- wrong results in qfgaussred() [only totally real case was correct] 85- uninitialized memory read in divrr (both kernels), would only affect the last bit of the result, but could cause SEGV on empty stack. 86- After A=1/(y + 0.); B=1. + O(y); all of A*B, A/B, B/A caused an error 87- wrong result in ellap(E, 2) if bad reduction 88- 0.*x+1 == 1 --> 1 but 0.*x^2+x == x --> 0 [ latter is now 1 ] 89- ffinit(2,30) --> division by 0 [typo in FlxY_Flx_div], [#859] 90- when unexpected exception/signal raised (^C, stack overflow, out of memory), == would cancel it and silently return wrong value [#329] 91- reading recently freed memory in popinfile() 92- contfrac(1,[],-1) ==> SEGV [#865] 93- missing type checks in bnrconductorofchar [#867], nfhilbert [#868] 94- unstable evaluation of tan(t_COMPLEX); at \p9, try ploth(t=-0.1,0.1,abs(tan(10*I+t))) BA 95- Vecsmall([1,1])^-1 returned garbage 96- was not handling nffactor(*huge degree* nf, *non-monic* t_POL) properly --> wrong result and possible memory corruption [#870] 97- polredabs: excessive stack usage [#872] 98- besselj(0., 0) --> error [#880] 99- polred didn't accept non-monic inputs 100- factor(..., 10^100) ==> "overflow in t_INT-->long conversion" [#855] IZ101- missing `const's in groupid.c cause massive copying to stack. 102- [native kernel only] int_normalize() didn't treat properly inputs of lgefint 2 103- gerepile errors in quadclassunit(13).gen or .cyc 104- from_Kronecker & FpXQX_from_Kronecker returned polynomials with invalid first codeword [ unused bits not reset to 0 ] 105- gred_rfrac_simple(n,d) [ basic constructor for t_RFRAC n/d ] did not cater for d = constant polynomial 106- RgX_extgcd created invalid objects in trivial cases [ gen_0 used by RgX-only routines ] BA107- Fix detection for ppc64 running in 32bit mode. 108- Fp_div used remii instead of modii: Mod(3,5)-1/3 -> Mod(0, 5) [#893] 109- trying to prevent accuracy problems in thue() caused oo loop 110- wrong results in matsnf with t_POL entries [#901] minpoly(matrix(4,4,i,j,i/j)) -> x^3 - 4*x^2 + x 111- thue(thueinit(x^3-100,1), 25) -> "Short continued fraction" 112- thue(thueinit(x^3-48, 320) -> missing solutions (similar problem when LHS is a polynomial of degree d and RHS includes a d-th power). 113- completely wrong results in nfsnf 114- intformal(A,Y) -> 1/2*A^2 115- uninitialized memory read in sin / cos / exp (possibly fed random final digits to the algorithm, normally truncated away before returning) 116- nffactor(): SEGV if "relifting" was necessary (very rare) 117- nffactor(): obscure "no factor" bug [when trial division found and extracted *non monic* factors], #930 118- incorrect output type in FpX_factor [#933] 119- possible stack corruption in polylog() + missing imaginary part. 120- incorrect final simplification in idealtwoelt(nf, x, y). Eg: idealtwoelt(nfinit(x^2+23), 3, 6) -> [0, 0]~ BA121- listsort() could return a pointer referencing freed memory: make it return void BA122- src/kernel/ix86/asm0.h had an incorrect #line entry. 123- rnfkummer could miss some fields ( bug in rnfnormgroup() ), e.g. bnrM = bnrinit(bnfinit(X^4 - 34*X^2 + 1189,1), 5, 1); rnfkummer(bnrM, matdiagonal([3,1,1])) 124- nfgaloisconj(y,1) -> invalid object 125- weird error message in ellpointtoz on loss of accuracy [#962] 126- ^C before inital prompt appears ==> SEGV [#965] BA127- ellsea(,,1) did not work BA128- COMPAT file was missing some functions renamed in 2.3: flisexpr, flisseq -> gp_read_str; lisGEN -> gp_read_stream AF129- fix for documentation of polcoeff, extern and readvec BA130- 1/matrix(2,2,i,j,Mod(0, 2)) -> SEGV 131- wrong results for qfminim(A,,,2) if minimal norm < 1. E.g. A = matid(2)/2 BA132- besselk(0.001,1) -> SEGV BA133- galoisinit(x).gen was not a t_VEC 134- lngamma(10^1000) -> precision too low in truncr. Same for psi() 135- nffactor could segfault. [#979] 136- Mod(10,37)^10000000000 -> SEGV 137- missing Flx_renormalize at the end of Flx_mulspec_basecase() & Flx_sqrspec_basecase() [#984] 138- after \y0, [1,x]*[0,0]~ returned 0 t_INT, which should be a t_POL [#983] 139- isprime(x) possibly incorrect on 64 bit machines when 10^15 < x < 2^64 LM140- fix for the documentation of deriv, intformal, poldisc and taylor. JD141- fix for the documentation of install, matsnf and polsturm. LM142- general documentation spelling fixes. BA143- detection of exp2 and log2 was broken with C++ BA144- support for shared library on netbsd. IZ145- [readline] 'foo)' + M-C-b -> infinite loop 146- factorff / polrootsff : wrong result if t_FFELT coefficients in variable 'x BA147- nfisideal did not reject invalid hnf ideal matrices [#999] 148- v=vectorv(1);concat([matrix(0,0),v,v,v,v,v,v,v,v,v,v,v,v,v,v,v,v]) -> SEGV [#1002] BA149- minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]/3) -> wrong result[#994] BA150- 2/O(5) -> O(5^-1) (should raise an error) [#1009] 151- factor(13533236897) -> I/O Warning [#1012] BA152- usqrtsafe result could be off by one. BA153- faster algorithm for nfgaloisapply. 154- bnfisnorm: output could have constant t_POL(MAXVARN) components instead of t_INT. E.g. bnfisnorm( bnfinit(x^2+10), 1690 ) [#1026] IZ155- [OS/2] Fix warning about string signedness. IZ156- [OS/2] Fix symbol checking in Configure. BA157- upowuu(2,31) returned a wrong result [#1031] BA158- [from 2.4.2] issquare(x^2+y^2) -> SEGV [#1027] BA159- [from 2.4.2] pointers to Vecsmall components were broken. BA160- [from 2.4.2] ellap could return a wrong result. [#1030] 161- thue() could return wrong results (ZX_Z_normalize() didn't follow its documentation) [#1032] 162- qfminim([1,2;2,1]*1.,,,2) -> SEGV [#1033] 163- [doc] const_col, const_vec: typo in prototype [#1040] BA164- precision(0.E100) returned an invalid object. 165- nbits2nlong, nbits2prec, nbits2nchar : avoid overflow [#1037] 166- normalization problems in RgX_Rg_add & friends, leading to t_POL with sign incorrectly set to 0, e.g. O(2)*x + 1 [#1042] 167- t_FFELT + t_FRAC -> SEGV (missing case in gadd) 168- polred(x) -> stack overflow [#1044] 169- sign of t_POL whose coefficients were all equal to 0 was not always set to 0 (RgX_add / RgX_sub) [#1053] 170- problems with p-adic gamma function : - remove extra digit in Morita's algorithm [ e.g. gamma(1/2+O(3^10)) ] - better threshold between Morita and Dwork's algorithm BA171- qfbhclassno(x) was wrong for x<0 172- subst(t_LIST,x,y) returned a copy without substituting [#969] substvec & substpol didn't work on t_LISTs BA173- RETRY macro was incorrect and could cause crash [#1064] BA174- factorpadic(,,,1) was actually using ROUND4 [#1064 again] 175- nfbasis(x^2+1,,factor(-4)) --> oo loop [#1072] 176- factorpadic: incorrect conversion from ZX to ZpX [#1073] 177- bnfinit() : possible overflow in double -> long conversion [#1099] 178- various inconsistencies in polinterpolate() [#1096] 179- rnfequation() broken when called over the prime field Q [#1079] BA180- F2x_divrem could call bfffo(0) which is not defined. 181- remove restriction on forsubgroup / subgrouplist that cyclic factors of all p-Sylows should have less than 2^32 / 2^64 elements Changed 1- [libpari] prototype of gpmalloc, gprealloc [ return void * ] 2- contfrac(x, b): no longer allow (undocumented) type t_MAT for b BA 3- builtin-in GP functions can now be used as closures. 4- allow nffactor(t_POL, t_POL), nfroots(t_POL, t_POL) [ necessary when nf.disc could not be factored and addprimes() would have to be used ] 5- removed undocumented interface FpM_mul(x,y,NULL), and analogously for FpV_dotproduct, FpV_dotsquare, FpM_FpC_mul 6- [library] major names cleanup; rename *lots* of functions: BSW_* -> BPSW_* Z_factor_limit -> Z_factor_until, auxdecomp -> Z_factor_limit assmat -> matcompanion certifybuchall -> bnfcertify derivpol -> RgX_deriv discf -> nfdisc, nfdiscf0 -> nfdisc0 element_div -> nfdiv, element_divmodpr -> nfdivmodpr, element_mul -> nfmul, element_mulmodpr -> nfmulmodpr, element_pow -> nfpow, element_powmodpr -> nfpowmodpr, element_reduce -> nfreduce, element_val -> nfval factorback0 -> factorback2 factorpadic4 -> factorpadic, factorpadic2 now static fundunit -> quadunit gcmp0 -> gequal0, gcmp1 -> gequal1, gcmp_1 -> gequalm1 Flx_cmp1->Flx_equal1, F2x_cmp1->F2x_equal1, FF_cmp1->FF_equal1 FF_cmp0->FF_equal0, FF_cmp_1->FF_equalm1 ZV_cmp0 -> ZV_equal0 gener -> znprimroot, ggener -> znprimroot0 greffe -> RgX_to_ser (+ change prototype) hil0 -> hilbert, hilii -> hilbertii [ delete useless hil() ] ideal_two_elt* -> idealtwoelt*, idealhermite -> idealhnf initalg -> nfinit, initalgred -> nfinitred, initalgred2 -> nfinitred2 initell -> ellinit, smallinitell -> smallellinit isfundamental -> Z_isfundamental ismonome -> RgX_is_monomial isunit -> bnfisunit matrixqz -> QM_minors_coprime matrixqz2 -> QM_ImZ_hnf matrixqz3 -> QM_ImQ_hnf minideal -> idealmin and change prototype mu -> moebius, gmu -> gmoebius, nfhermite -> nfhnf, nfhermitemod -> nfhnfmod, nfsmith -> nfsnf phi -> eulerphi, gphi -> geulerphi, phiu -> eulerphiu, poldeflate -> RgX_deflate_max polymodrecip -> modreverse powraw -> qfbpowraw, compraw -> qfbcompraw primedec -> idealprimedec racine -> sqrtint, regula -> quadregulator rename cmp_ZV -> ZV_cmp smith2 -> smithall, gsmith2 -> gsmithall srgcd -> RgX_gcd subfields0 -> nfsubfields, subres -> resultant, subresall -> resultant_all. torsell -> elltors and document it zideallog -> ideallog RgXQ_caract -> RgXQ_charpoly ZX_caract -> ZXQ_charpoly ZX_isirreducible -> ZX_is_irred pariputc -> pari_putc, pariputs -> pari_puts, pariflush -> pari_flush, gpmalloc -> pari_malloc, gprealloc -> pari_realloc, gpfree -> pari_free ordell -> ellordinate 7- polvaluation -> RgX_valrem(x, pz) and no longer accept pz = NULL (use RgX_val). Same for ZX_valuation -> ZX_valrem [ & ZX_val ] 8- rename u2toi -> uu32toi [ paste two 32-bit unsigned into a t_INT ] Write uutoi for the more natural operation of pasting two ulongs into a t_INT. 9- prototype of FpX_center [ add one argument ] BA 10- [svn/CVS] number development snapshots according to repository version 11- delete CVS.txt and replace it with README-subversion 12- syntax errors, SIGINT and "PARI bugs" are no longer trapped 13- quadray no longer allows an (optional) 3rd argument 14- 'format' was updated after each 'realprecision' change. Don't update if 'format' is Xm.-1 (show all significant digits). 15- the algorithm used to round t_REAL for output 16- the "minimum field width" component of the 'format' default is now ignored (was used only for integers in 'prettyprint' output mode and defaulted to 0 [no effect]). Use printf ! 17- %Z is no longer a valid conversion specification for PARI formats, since this is now handled as a length modifier. Use %Ps instead (P stands for PARI). 18- remove the (ugly) prettyprint engine ('output' = 2), render as matbrute. printp / printp1 now act as print/print1 19- pariprintf renamed to pari_printf, %Z conversion disappeared (use %Ps) 20- check for small prime divisors in ispower [ large speedup ] 21- the conversion style 'g' of the 'format' default now printfs in style 'f' if the decimal exponent is < -4 ( was: if the binary exponent is < -32 ), in order to conform to standard printf specifications. 22- [GMP kernel] enable GMP exact division 23- matdetint: use less memory + faster finish 24- change the default algorithm for mathnf(a) [ much faster ], flag 0 is no longer deprecated 25- library/GP function galoisinit() now returns NULL/0 on failure (used to raise an exception) 26- allow nfgaloisconj(t_POL, 1) [ cf C-4 ], never resort to nfgaloisconj(,2) [ slow, unreliable ] with default flag = 0 27- [library]: gsub now implemented directly when typ(x) = typ(y) BA 28- all LLL variants now use an implementation of NGuyen & Stehle's algorithm 29- [library]: the "prec" parameter of floating point LLLs has disappeared 30- Vecrev(x) now equivalent to extract(Vec(x), "-1..1") [was only for t_POL] 31- allow t_COMPLEX as well as t_QUAD in ellpow 32- we used to have Set(1) == Set("1") ( = ["1"] ). Now the latter returns ["\"1\""] (the Set whose element evaluate to the character string "1") 33- plotinit: change the way default arguments are evaluated (omit, instead of interpreting 0 in a special way) 34- nfbasistoalg / nfalgtobasis no longer accept t_VEC/t_COL/t_MAT, use matbasistoalg / matalgtobasis, which now also accept t_VEC/t_COL 35- uniformize factornf and nffactor outputs (+ speed them up for non-squarefree inputs: compute valuations mod a suitable prime) 36- treat Mat(t_LIST) as Mat(t_VEC) 37- t_POL^0 always returned t_INT 1 [ try to return 1 in coefficient ring ] 38- polresultant(x,y,,0) now chooses the best algorithm by itself [Ducos, modular, Sylvester], polresultant(x,y,,2) is now a synonym for the default. The change also improves poldisc(). 39- regression tests in src/test/in/ no longer need to end with 'print("Total time spent: ",gettime)' 40- arguments of stirling1 / stirling2 are now ulongs [ were longs ] BA 41- user variables can now be aliased [#790] 42- conjvec(POLMOD of INTMODs) was slow 43- bnfcertify can now handle Zimmert/Minkowski bounds > 2^31 44- moved misc/dico.new to src/whatnow + integrate it in the description system [ new script desc/whatnow ] 45- bittest(x, n) no longer accepts t_VEC arguments n 46- split library function disable_dbg() -> dbg_block() / dbg_release() 47- make the semantics of substpol more precise and less surprising: substpol((x^2+x+1)/(x^2+x-1),x^2,x^3) -> (x^3 + x + 1)/(x^3 + x - 1) [ was: (x^6 - x^3 - 2*x - 1)/(x^6 - 3*x^3 + 1) ] 48- deprecated flag '2' for bnfinit [ don't compute units ] is now ignored ==> bnfunit becomes totally useless. 49- the last component in prime ideals "primedec" format is a number field element, but no longer necessarily in t_COL form 50- no longer allow ideals in *non-square* t_MAT form 51- idealmin now returns a number field element, instead of the associated "principal idele" 52- cleared up the confusion caused by PARI "ideles", which were remotely related to the mathematical notion, and covered two distinct uses. The first one (ideal + list of real places) is now called "divisor"; the second one (ideal + factorization matrix, which used to be a vector of logarithms of complex embeddings) is now called "extended ideal". 53- Allow Scalar + t_COL: x + y returns [ y[1]+x, y[2],... ]. Consistent with RgC_Rg_add and RgV_isscalar, and allows linear algebra over number fields with less rigid data types (can mix freely t_COL, t_INT and t_FRAC, instead of converting everything to t_COL). 54- Functions quadunit(), quadregulator(), and factor() no longer apply componentwise to vector / matrix arguments. Use apply() 55- [libpari] removed obsolete 'prec' argument from prototypes of idealmul0, idealmulred, idealpow0, idealpowred, ideallllred, algdep, algdep0, lindep, lindep0 56- factorback() no longer accepts an optional 3rd argument (nf). Use idealfactorback(). See also nffactorback(). 57- Extend polhensellift to work over unramified extensions of Q_p [ was Q_p only ] 58- [libpari] changed prototypes of bnrdisc, bnrconductor, bnrisconductor 59- slightly change the matrices used in idealmin (round them): the elements returned are a little different. 60- no longer export private library function incgam2. Remove it also under GP when compatible = 3. Like incgam1 (suppressed), 1.39.15 doc stated it was provided "for debugging only". 61- addhelp: TABs are now treated properly (would overflow line without wrapping) and \n are no longer ignored. No longer add a trailing '.' when missing. 62- Useless nfinit flags 4, 5 (partial polred) removed. 63- Split off inline functions unrelated to the kernel from src/kernel/level1.h 64- Swap the order of the 2 arguments to select(): selection function now comes first [ as in apply() ] 65- error() messages now prefixed with the customary *** [ used to be ### ] 66- dvmdiiz(x, y, z) now expects z to be a t_INT [ to be consistent with all other xxxz functions where xxx includes only i,s,u arguments ] 67- improved charpoly(,,2) [ Hessenberg form ] 68- allow Flxq_mul and Flxq_sqr to call Flx_rem_montgomery 69- t_POLMOD * t_POLMOD with same modulus: if all coefficients are in Z/NZ, call specialized functions FpXQ_mul / Flxq_mul [ analog with gsqr, gdiv, ginv, powgi ] 70- bezout(): make sure the leading term of the gcd of 2 polynomials is positive (when it makes sense), as was already the case for gcd() 71- mpcopy, Flv_copy, Flx_copy, vecsmall_copy have all become aliases for leafcopy. 72- trap(,,foo) was actually equivalent to trap(,foo) changing the global exception handler, which was awkward an unintended 73- norml2(t_POL) now returns the expected (square of) the standard L^2 norm. Use x * conj(x) to get back the old behaviour. norml2 now raises an error on t_POLMOD and t_FFELT components; used to add relative norms as in ? norml2([Mod(Mod(1,3)*x,x^2-2), 2]) %1 = Mod(2, 3) 74- [library] kernel functions involving a t_INT and a t_REAL now return a t_REAL, e.g. divsr(0, x) or mulir(gen_0,x) return real_0(...) [ used to return gen_0 ] ==> much better control of object types when writing kernel code. Generic functions (gmul, gdiv), as called from gp still return a result as precise as possible given the input: 0 * 1. --> gen_0 75- [library] cleanup t_COMPLEX arithmetic to take advantage of real parts equal to a t_INT 0. Imaginary parts equal to 0 should never be created by our generic functions (so no need to cater for them specially: they will be very rare, produced by ad hoc routines). Special case trigonometric functions on pure imaginary arguments. 76- kill(z) no longer destroys user variable, only resets them to their "undefined" value (as z = 'z would). 77- [library] prototype of galoisconj [ add one argument ], and made it correspond to the default nfgaloisconj flag 78- allow ordinary sorted vectors in set* functions [ sets are still t_VECs of t_STR, but if components can be directly compared, ordinary vectors are simpler and faster ] 79- allow arbitrary nf entries in relative matrices; nfhnf and nfhnfmod return matrices whose entries may be t_INT or t_FRAC besides the traditionnal nfalgtobasis form. Allow ideals in arbitrary form [was: necessarily HNF] 80- linear algebra routines: determines first whether we are over Z/NZ then call specialized FpM_* routines if possible [fixes #376] 81- [library] commented out a large section of pariold.h. Define PARI_OLD_NAMES to recover compatibility macros for old friends like 'un' and 'lstoi' 82- Mat(t_QFI or t_QFR) now returns the associated 2x2 symmetric matrix 83- [library] rename Buchall -> Buchall_param and export a new Buchall with a simplified interface. 84- trap() no longer allows installing default error handlers. 85- GP's break loop is now *enabled* by default [ set breakloop = 0 in your gprc to disable it ], and no longer controlled by trap(). To get out of a break loop, hit Return three times (next, return, break are no longer accepted) BA 86- factormod and matker: faster linear algebra over F2. 87- remove duplicate polynomials in polred output [#874] 88- let forvec(X = v,...) respect the type of v (t_VEC or t_COL) 89- polred: compute characteristic polynomials as in polredabs [ using complex embeddings, not ZX_charpoly ] PMo90- algorithm for nfrootsof1 now defaults to nffactor: generically a little slower than qfminim, but safer and sometimes much faster (e.g. 1mn against a few hours) 91- added a new component nf_get_roundG to the nf structure [ to speed up ideal reductions ] BA 92- make test-xxx: trap SIGINT in benching script to exit on 93- removed optional flag to rnfconductor, use rnfisabelian. 94- improved dirzetak() by an order of magnitude: e.g. K=nfinit(x^3-10*x+8), dirzetak(K, 10^6) from 4min (2.4.2) to 2.5s 95- renormalize rnfkummer output so that it cannot be written as P(C * x)*C^(-deg P) for any integer C > 1 [ saves large powers of C in disc P ] 96- added a flag to the (mostly useless) function rnfdedekind(), the version with the flag set is a little more useful. Allow list of prime ideals instead of single prime ideal, and make this list optional (omitted = test for maximality at ALL primes) 97- the "zetakinit" format: bnf no longer included 98- thueinit / thue: allow reducible and non-monic polynomials 99- rnfdedekind: allow non-monic polynomials 100- bnrclassno(bnr,id) : allow bid as well as modules for the 'id' argument. 101- GP 'path' now also applies for file paths containing a '/' provided they do not *start* with a '/' (i.e. not an absolute path) 102- [library mode] the function znlog now takes an extra "order" argument 103- added an optional "order" argument to znlog, fflog, elllog, znorder, fforder, ellorder, whose preferred format is [ord, factor(ord)] and ord is the order of the group 104- factor(t_INT/t_FRAC, lim) used to trial divide by primes up to min(lim, primelimit). Now we trial divide up to lim and raise an error if lim > primelimit. [ Having the routine return an obviously "wrong" result depending on an invisible parameter was not a good idea. ] 105- factor(t_INT/t_FRAC, 1) was the same as factor(t_INT/t_FRAC, 0). Now abide by the input value and leave (..., 0) as the single special case (shortcut for "the largest precomputed prime") BA106- [native kernel] Schoenhage-Strassen multiplication/squaring 107- factorff(A, p, T): make p & T optional if A has t_FFELT coefficients BA108- [TLS] Change pari_thread calling convention 109- allow x.a1, ..., x.a6 for an "ell5" x (5-component vector) 110- removed 'primelimit' grom gp_data struct: we now print the actual limit of the primetable, not the value input by the user (which may be a little less) BA111- listsort(L) no longer returns the list L: it now returns nothing. (No point in sorting in place if we must immediately copy the result.) 112- allow component(t_VECSMALL,...) [#957] 113- allow bestappr(x) [2nd argument made optional] BA114- GMP kernel chosen by default when GMP is available BA115- Rename RgXQ_u_pow to RgXQ_powu 116- Darwin: add -search_paths_first to LDFLAGS (try to solve the Editline / Readline conflict in a user-friendly way) BA117- [enable-tls] Library soname changed to libpari[-gmp]-tls[-2.4].so.N. 118- integrate a final polredabs in quadhilbertreal() BA119- Rename leftright_pow to gen_pow, leftright_pow_u to gen_pow_u and implement sliding window powering. BA120- galoisapply now accept automorphisms in t_COL format. 121- allow moduli equal to 0 in matsolvemod (was SEGV) [#947] + rigorously size-reduce the output in all cases. 122- the bnr structure in a minor way (bnr[6] has 3 components now) 123- cleaned up the code used by the GP evaluator to call PARI (and installed) functions. Functions can now have 20 arguments [#795] BA124- galoisfixedfield now accept subgroups. 125- ellap(E, p) second argument now optional if E has t_INTMOD or t_PADIC coefficients. 126- generalize the "generic pivot" strategy to all linear algebra (support RgM_solve and det() in addition to existing functions); implement maximal pivot strategy for p-adics [#1054] BA127- padic_sqrt -> Qp_sqrt, padic_sqrtn -> Qp_sqrtn, gammap -> Qp_gamma 128- rename rnfinitalg -> rnfinit 129- [readline + vi-mode] h/H no longer clobbered by online help. 'h' will now act as expected (= 'move left one character') 130- any of break / next / return now get out of the break loop debugger (as they used to in 2.3) 131- typing thrice no longer gets out of the break loop : use break 132- faster eta(,1), weber() and quadhilbert() [ rewrite using eta's functional equation explicitely ] 133- checked that no 2-strong pseudoprime passes BSPW primality test up to 2^64 (use Feitsma's list, extending Galway's) Added 1- many new benches (make test-all) 2- split up some large monolithic files: new files src/basemath/ RgV.c, FpV.c, ZX.c, ZV.c, concat.c, lll.c, hnf_snf.c prime.c, bit.c src/modules/ QX_factor.c, Hensel.c, DedekZeta.c 3- split off module of general inline functions: src/headers/pariinl.h. 4- Write or rename / document many convenience library functions: pari_calloc, cgetalloc mkfraccopy, mkquad, mkvecsmall4, absfrac, sqrfrac, mul_content, mul_denom roundr_safe, trunc_safe shallowextract, shallowconcat1, concat1, BPSW_psp & BPSW_isprime Z_smoothen, Z_ispower, Z_ispowerall Z_isanypower, chinese_coprime_Z, Z_chinese, Z_chinese_all, Z_chinese_coprime, Z_chinese_post, Z_chinese_pre, Z_incremental_CRT, Z_init_CRT, ZM_incremental_CRT, ZM_init_CRT, ZX_incremental_CRT, ZX_init_CRT, ZX_to_monic, ZX_primitive_to_monic, ZX_squff, ZX_gcd_all, nfgcd, nfgcd_all, RgX_disc, quad_disc, qfb_disc, ZpX_liftfact, ZpX_gcd, ZpX_reduced_resultant, ZpX_reduced_resultant_fast Fp_center, FpM_center, FpV_center Fp_ratlift, FpM_ratlift, FpX_ratlift FpM_FpC_mul_FpX Fp_red, FpXQ_red Flxq_add, Flxq_sub, FpXQ_add, FpXQ_sub, FqXQ_add, FqXQ_sub FqX_add, FqX_sub FqX_roots, FpX_factorff, FpX_rootsff FpXQX_div, FpXQX_rem, FpXQXQ_mul, FpXQXQ_sqr, FpXQXQ_pow FpXQXQ_inv, FpXQXQ_invsafe, FpXQXQ_div FqXQ_mul, FqXQ_sqr, FqXQ_pow, FqXQ_inv, FqXQ_invsafe, FqXQ_div FqX_extgcd ZC_ZV_mul, ZM_is_identity, ZM_copy, ZM_neg, ZM_add, ZM_mul, ZM_pow ZM_max_lg, ZM_sub, ZM_ZC_mul, ZXV_Z_mul, ZM_Z_mul, ZV_Z_mul, ZV_isscalar, ZV_copy, ZV_neg, ZV_neg_inplace ZV_togglesign, ZV_indexsort ZMrow_ZC_mul, ZV_ZM_mul, ZV_cmp0, ZV_content, ZV_equal, ZC_lincomb, ZC_lincomb1_inplace, ZC_z_mul, ZV_prod, ZV_pval, ZV_pvalrem zv_prod ZM_Z_divexact, ZC_Z_divexact, ZX_Z_divexact, ZM_charpoly, Flm_charpoly, Flm_hess Z_ZX_sub, ZX_Z_sub, Fp_FpX_sub, Flc_Fl_div, Flc_Fl_div_inplace, Flc_Fl_mul, Flc_Fl_mul_inplace, Flm_Fl_mul, Flm_Fl_mul_inplace, Flm_copy, Flm_mul, Flm_inage, Flv_Fl_mul_inplace, Flv_add, Flv_add_inplace, Flv_copy, Flv_dotproduct, Flv_sub, Flv_sub_inplace, Fl_order, Flx_nbfact_by_degree, Flx_roots_naive, FF_sub, Fp_mulu, FpV_inv, FpXQ_inv, FqV_inv, FpXY_eval, FpXY_evalx, FpXY_evaly, Flx_Fl_mul_to_monic, FlxqX_Flxq_mul_to_monic, FlxqX_rem, FlxqX_gcd, FlxqX_extgcd, FlxqXQ_mul, FlxqXQ_sqr, FlxqXQ_inv, FlxqXQ_invsafe, pol1_FlxX, FpX_Fp_sub, FpX_Fp_sub_shallow, FpX_Fp_mul_to_monic, FqX_Fq_mul_to_monic, FpXX_Fp_mul, RgM_check_ZM, RgM_det_trianguar, RgM_isdiagonal, RgV_check_ZV, RgV_neg, RgV_add, RgV_sub, RgV_Rg_mul, RgC_neg, RgC_add, RgC_sub, RgC_Rg_div, RgC_Rg_mul, RgM_neg, RgM_add, RgM_sub, RgM_Rg_div, RgM_Rg_mul, RgC_RgM_mul, RgC_RgV_mul, RgM_RgC_mul, RgM_RgV_mul, RgM_mul, RgM_sqr, RgV_RgM_mul, RgV_RgC_mul, RgV_add, RgV_neg, RgV_sub, RgC_Rg_add RgM_diagonal, RgM_diagonal_shallow, RgM_inv, RgM_solve, RgM_mulreal, mulreal, RgX_RgM_eval RgV_sum, RgV_sumpart, RgV_sumpart2 RgX_neg, RgX_add, RgX_add_shallow, RgX_sub, RgX_Rg_add, RgX_Rg_sub, Rg_RgX_sub, RgX_equal, RgX_equal_var, RgX_translate, RgX_to_nfX, RgM_to_nfM, RgC_to_nfC, RgX_type, RgX_type_decode, RgX_type_is_composite, RgX_Rg_divexact, RgXQ_norm, RgXQ_pow, RgXQ_caract, RgXQ_reverse RgXQX_translate, RgXQV_to_mod, RgXQXV_to_mod RgXQX_pseudorem, RgXQX_pseudodivrem, RgX_check_ZX, RgX_check_ZXY, RgX_pseudodivrem, RgX_pseudorem, RgX_recip, RgX_recip_shallow, ZC_hnfrem, ZC_hnfremdiv, ZM_det_triangular, ZM_detmult, ZM_equal, ZM_hnf, ZM_hnfall, ZM_hnfcenter, ZM_hnflll, ZM_hnfmod, ZM_hnfmodid, ZM_hnfmodall, ZM_hnfrem, ZM_hnfremdiv, ZM_hnfperm, ZM_snf, ZM_snfall, ZM_snfall_i, ZM_snf_group, ZM_snfclean ZM_lll, ZM_lll_norms, hnfmerge_get_1, ZXY_max_lg, ZX_copy, ZX_equal, ZX_max_lg, row_Flm, row_zm, scalar_ZX, scalar_ZX_shallow, deg1pol, deg1pol_shallow togglesign_safe, setabssign, zero_Flm, zero_Flv, zero_zm, zero_zv, zm_copy, zv_cmp0, zv_copy, zv_equal, zv_content, zx_renormalize, identity_perm, cyclic_perm, perm_mul, perm_commute, perm_inv, perm_pow, cyc_pow_perm, cyc_pow, perm_cycles, perm_order, vecperm_orbits bitvec_test_set, RgX_get_0, RgX_get_1, resultant, resultant_all, QX_disc, QX_resultant, lllfp, lllintpartial, lllintpartial_inplace, reducemodlll, reducemodinvertible, closemodinvertible, init_primepointer, galoisinit0, get_nfpol, get_bnfpol, get_prid, bnf_get_nf, bnr_get_bnf, bnr_get_bid, bnr_get_mod, bnr_get_nf nf_get_r1, nf_get_r2, nf_get_roots, nf_get_sign, nf_get_roots, nf_get_M, nf_get_G, nf_get_roundG, nf_get_Tr, nf_get_TrInv, nf_get_disc, nf_get_index, nf_get_pol, nf_get_zk nf_get_prec (was nfgetprec), nf_to_scalar_or_basis, nf_to_scalar_or_alg nf_to_Fq_init, nf_to_Fq, Fq_to_nf, zkmodprinit, zk_to_Fq_init, zk_to_Fq, nfM_to_FqM, FqM_to_nfM, nfX_to_FqX, FqX_to_nfX zk_multable, zk_scalar_or_multable, multable, tablemul, tablemul_ei, tablemul_ei_ej, tablemulvec, tablesqr, ei_multable. nfordmax, nfarchstar (was zarchstar), nfadd, nfsign, nfnorm, nftrace nfsign_arch, nfsign_units, nfsign_from_logarch, Buchquad, Buchall, Idealstar, idealaddtoone_i, idealcoprimefact, nfinvmodideal, nfpowmodideal, idealsqr, nfpow_u numberofconjugates, bnrisconductor0, bnrdisc0, bnrconductor0, bnrsurjection, ABC_to_bnr, idealred, idealred0 (was ideallllred), idealred_elt, idealred_elt0 ellinit_padic, ellinit_real, ellinf, ell_is_inf, ell_is_padic, ell_is_real, checkerr_real, checkell_padic, checksmallell, checkell5, checkellpt trueeta, exp_Ir, roots_from_deg1, deg1_from_roots 5- [libpari] public generic hashtables 6- library functions sqrr and invr [ Newton inversion, called by ginv() ] BA 7- library functions checkgroup, galois_group, cyclicgroup, dicyclicgroup, abelian_group, group_domain, group_elts, group_order, group_isabelian, group_abelianHNF, group_abelianSNF, group_isA4S4, group_leftcoset, group_rightcoset, group_perm_normalize, group_quotient, quotient_perm, quotient_group, quotient_subgroup_lift, group_subgroups, groupelts_abelian_group, groupelts_center, group_export, group_ident 8- library functions pr_get_p, pr_get_gen, pr_get_e, pr_get_f, pr_get_tau to access components of prime ideals BA 9- handle numerical derivation as an operation on closure. RB 10- GP functions printf, Strprintf 11- pari_printf, pari_fprintf, pari_sprintf, pari_vfprintf, pari_vprintf, pari_vsprintf BA 12- docpdf and install-docpdf targets (toplevel Makefile) JD 13- add an optional argument to quit() 14- universal constant gen_m2, for symmetry 15- GP function version() [ current version number ] BA 16- [ellap] Port of SEA algorithm from the ellsea GP package BA 17- new alarm GP function and alarmer error code RM 18- partitions() 19- New chapters in Libpari Guide: usersch6.tex, usersch7.tex 20- library function dbg_pari_heap 21- function bnfcompress() [ to create a "small bnf" from a true bnf, to be recoved using bnfinit ]. More consistent than old bnfnit(,3) / bnfmake. 22- a concept of "extended ideal" [I, t], where t is an algebraic number (possibly in factored form). The pair represents the ideal I x (t) In applications the norm of I stays bounded for a given base field, and t keeps track of the "principal part" of the ideal (usually in factored form to avoid coefficient explosion). 23- public interface to forsubgroup: traversesubgroups() 24- library function bnfisprincipal0 (with new public flags, see nf_GENMAT) 25- GP functions nffactorback / idealfactorback JD 26- GP function warning() 27- new flag to charpoly [ integral matrix, modular algorithm ] BA 28- GP function galoisisnormal() BA 29- F2x functions family for polynomials over GF(2) and BA 30- t_FFELT subtype_FF_F2xq for GF(2^n) BA 31- F2v/F2m functions family and F2m_ker for linear algebra over GF(2) BA 32- extra debugging data in t_CLOSURE and debugging facility. BA 33- compile-time copy optimizer BA 34- elliptic discrete logarithm function elllog() BA 35- direct implementation of ZX_mul, ZX_sqr using Kronecker's trick + mulii 36- rnfisabelian GP function 37- default 'recover' 38- more possibilities to draw "random" elements in natural sets using random(), e.g. finite fields, elliptic curve over finite field. 39- GP routines nfeltadd, nfelttrace, nfeltnorm BA 40- Pollard rho discrete logarithm algorithm (function gen_Pollard_log) 41- GP routine polrootsff 42- matadjoint: implement division-free algorithm (flag = 1) [#937] BA 43- GP routines and PARI functions ellweilpairing, elltatepairing and ellgroup BA 44- FpE functions family for points on E(F_p) BA 45- GP routine galoisgetpol and PARI function galoisgetpol, galoisnbpol BA 46- GP routine and PARI function elldivpol BA 47- GP routine and PARI function ellmodulareqn BA 48- function RgXQ_ratlift for reconstruction of rational functions. 49- optional flag to bnfcertify : only check that the correct class group is a quotient of the computed one. VB 50- mingw support VB 51- plotwin32 graphic engine 52- plotQt4 graphic engine BA 53- low-level accessors functions gal_get_* for galoisinit objects 54- libpari functions cvstop2, z_lval, z_lvalrem, z_pvalrem 55- GP function externstr() 56- library function ZC_reducemodmatrix, ZM_reducemodmatrix, ZC_reducemodlll, ZM_reducemodlll BA 57- libpari functions vecsmall_max and vecsmall_min BA 58- GP functions idealfrobenius and idealramgroups BA 59- library functions Zn_sqrt, Zn_issquare 60- library function gidentical BA 61- GP operator === that use gidentical 62- GP function sumdedekind() JD 63- [gphelp] support for bzip2 compressed documentation. Removed 1- obsolete GP functions printp, printp1. Either replace them by print / print1 [ or the new printf ], or define aliases alias(printp, print); alias(printp1, print1) 2- obsolete GP functions bnfclassunit, bnfreg, bnfclgp, bnfunit. Use bnfinit. 3- obsolete GP functions bnrclass. Use bnrinit or bnrclassno. 4- obsolete GP function idealprincipal. Use number field elements "as is" 5- obsolete GP function ideleprincipal. No routine remains that would use the auxiliary "archimedean information" 6- obsolete library functions extract and matextract 7- obsolete optional argument to quadhilbert(D < 0) 8- unused undocumented library functions os_open/os_read/os_close 9- obsolete README.DOS and README.WIN 10- cant_deflate, elliper1, lllger3, varer1, obsoler, infprecer, errlg, errexpo, errvalp, rtodber, affer2, primer2, siginter error codes 11- obsolete library function bruteall 12- useless undocumented library function gkrogs (use krois) 13- obsolete library functions roots2 and rootsold are no longer public 14- useless library function isnfscalar 15- obsolete undocumented library function factpol(), lift_to_pol() 16- library function combine_factors() is no longer public 17- obsolete undocumented library function rnfdet0, rnfdet2 18- obsolete library function discsr(). Use RgX_disc (or quad_disc, qfb_disc) 19- obsolete library function element_powmodidele() [use element_powmodideal + set_sign_mod_idele], ideleaddone, reducemodmatrix, nfreducemodidele, nfreducemodideal, nfreducemodideal_i, elementinv_modpr 20- useless macros gaddgsz, gaddsgz, gdiventgsz, gdiventsgz, gdivgsz, gdivsgz, gmaxgsz, gmaxsgz, gmingsz, gminsgz, gmodgsz, gmodsgz, gmulgsz, gmulsgz, gsubgsz, gsubsgz, gachz, gacosz, gashz, gasinz, gatanz, gathz, gchz, gcosz, gcotanz, gexpz, ggamdz, ggammaz, glngammaz, glogz, gpsiz, gshz, gsinz, gsqrtz, gtanz, gthz, gzetaz, gmaxz, gminz, TRgopgz, mpfloorz, mptruncz, mpdvmdz 21- obsolete library function gmillerrabin, gpolcomp, caradj0 22- obsolete library functions allbase, base, base2, factoredbase, smallbase, discf2, factoreddiscf, smalldiscf. Use nfbasis0 / nfdisc0 / nfmaxord 23- obsolete library function pari_rand31 [ use pari_rand ] 24- obsolete undocumented library function bruterr 25- obsolete library function smallbuchinit 26- awkward flag '3' for bnfinit. Use bnfcompress(). 27- badly named bnfmake. Use bnfinit(sbnf). 28- useless component v[6] in "small bnfs" (was 'different', is 0) 29- obsolete library functions buchray, buchrayinit, buchrayinitgen: use Buchray. 30- obsolete library function smallfact [ use boundfact or Z_factor_limit ] 31- obsolete library function gracine [ use sqrtint ] 32- obsolete library function ispsp, gispsp. Use ispseudoprime or BPSW_psp. 33- obsolete library function gregula, gfundunit, gboundfact. Use quadregulator, quadunit, boundfact 34- obsolete library functions ideallistunit, ideallistunitgen, ideallistzstar, ideallistzstargen. Use ideallist0. 35- obsolete library function algdep2. Use algdep0 (same arguments). 36- obsolete library function Mod0. Use gmodulo. 37- obsolete undocumented library function poldvd. Use RgX_divrem(x,y, ONLY_DIVIDES) 38- obsolete library function kerint1. Use kerint or ZM_lll(,0.99,LLL_KER) 39- header file paritype.h [ split between parigen.h and pariinl.h ] 40- obsolete library functions sor, outbrute, outbeaut 41- dangerous macros max & min [ use maxss/minss, maxuu/minuu, maxdd/mindd ] 42- deprecated global constants gi, geuler, gpi. Use mulcxI/mkcomplex/gen_I(), mpeuler() and mppi(). BA 43- bitvec family function. Use F2v instead. BA 44- useless prototype code 'S'. Use 'r' instead. BA 45- useless function delete_named_var. 46- obsolete and dangerous switch_stack() [#1013] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.2 (released 22/12/2007): Fixed 1- divrs(0., negative integer) had the wrong exponent 2- vecsort(,,4) was broken in 2.4.1 3- allocatemem(z) didn't check that z >= 0 [#556] 4- remove hack in internal function 'readbin' that used the clone bit as a special marker hence returned an invalid object, which could be propagated to higher level public functions. BA 5- sqrtn(Mod(a,p),..) and factorff() were broken in 2.4.1 BA 6- bitnegimply(1,2^65) returned a wrong result [#560] 7- nfeltreduce(nf,t_POLMOD,id) didn't work [#558] 8- [library] missing function intfourierexp() 9- segv in polrootspadic / repeated roots in FpX_root (only in deg 2) [#562] 10- log(2+O(4^4)) --> oo loop 11- log(exp(1e-100)) -> 1.000000000149525401279188592 E-100 [ for some accuracies, log & exp inacurate near 1 and 0 resp. ] 12- numbpart inaccurate (and slow). E.g numbpart(52602) off by 1 [#557]. BA 13- &, |, && and || were right-associative instead of left-associative 14- remove type assumptions in mulcxI, mulcxmI: unsafe [#516]] 15- too much memory allocated to print real numbers 16- (y/x)/(x^0/y) not correctly simplified 17- \s reported a misleading number of available user variables 18- 1/(quadgen(-4)*x)+0. -> exponent overflow [#591] 19- sumpos(x=1,1/x^2,1) had the wrong sign [#587] 20- matrixqz(x,0) would not work if first two determinants were 0 + might lose pointers in gerepile 21- sumpos(x=1,0) -> oo loop [#585] 22- qfminim([[;]],,,2) --> SEGV [#598] 23- intformal(1) --> incorrect object 24- intformal(y,x) --> y*y 25- matadjoint(0) --> gerepile error 26- prodinf(x=0,0), prodinf(x=0,-1,1) --> oo loop 27- agm(-1, 1+1e-55) --> oo loop, agm(-1,1) --> wrong result LGr28- killing hi-res graphic window created zombie process (missing wait()) 29- missing type check in eint1(x,n) 30- ploth(...) + Ctrl-C --> hi-res graphic window killed [use pari_daemon()] 31- quadgen([]) --> incorrect object [#606] 32- hyperu(0,1,1) --> oo loop [#608] 33- fix headers so that ulong is always defined 34- read("a b.gz") \\ filename contains a space gzip: ./a.gz: No such file or directory 35- logagmcx inaccurate [ used for log(t_COMPLEX), large precision ] 36- RgX_divrem: prevent "impossible" situations for weird base rings 1/ Mod((y-1)*x-1, Mod(2,6)*x^3-Mod(1,2)*x^2-1) --> SEGV 37- gclone didn't work on t_INTs with lg > lgefint 38- GC error in add_rfrac() [#612] 39- missing type check in subgrouplist [#616] 40- inconsistent type checking in nfeltdivmodpr [#617] 41- nfdisc(x^32+24888960*x^30+227077545803904*x^28+887225199431341086720*x^26+1145458263702669503266741248*x^24-459489127319699704284694158213120*x^22+73430099675988831740428200872826863616*x^20-6599321778961370851005469933592282336329728*x^18+369563540304176984501448638025309170375722401792*x^16-13214618078037183940422584396181416089308059714715648*x^14+291247424536170563676138246427605494527806096141868597248*x^12-3407227562250271661213064368167141844394234574629997803208704*x^10+8699659624155196549893192408316795253695601521375537680749690880*x^8+153390110447793800411208197070089975539253907830958400507847198638080*x^6-34704742472413552993642506624568826441560550586777137133227202205188096*x^4+43389826962123095743039577910848855441856968086933919852164410699581227008*x^2+336462877895453750216450425189196151877685043455706101021513167474262016, 1) --> "not a prime" error (help Round4 to recover when using non-primes, instead of raising immediate errors) [#624] 42- vecextract: C14 in 2.4.0 didn't work for large masks [#623] 43- clean up version handling: move version setting code to config/version and always set PARIVERSION from CHANGES if 'CVS' [ used to require a 'Configure' ] 44- zeta(0e1) --> SEGV [#627], exp(0e1*I) --> SEGV [#630] 45- exp(2^200*I) --> catastrophic cancellation [cos/sin were OK] [#631] DE 46- on NFS filesystems, make install would rebuild all [#503] 47- default(compatible,3); default(compatible,1) --> case no longer taken into account [#629] 48- missing GC in 'sigma' 49- eta(x): valuation would overflow if seriesprecision is large 50- typo in src/kernel/none/mp.c:convi --> inefficiency 51- concat(v) used too much memory (quadratic in #v, make it linear) [#634] BA 52- gp -q -f < eval('y) --> SEGV 53- "significant pointers lost" for objects involving 0 t_SERs [#635] 54- for trivial x, isanypower(x,&p) would not set p MSo55- [Configure] don't rely on $CC exit status, check whether a non-0 size executable is produced [ problems with tcc ] BA 56- wrong Prototype for subgrouplist [ extra 'p' ] 57- hole in 'secure' mode: don't allow changing psfile / logfile [#645] 58- nf.codiff was only correct up to multiplication by some rational number [cf #510 & 2.4.1-F7] 59- cgiv failed to delete the last object on stack [ if recursive ] LGr60- first default(parisize,*) would segfault [due to C-1, #569] 61- pariputs("") --> invalid read of size 1 [ valgrind ] 62- ell.omega, ell.eta, pr.gen could lead to gerepile error [#641] 63- y=[x];eval('y) --> error [#652] 64- incorrect use of gerepileupto in inittestlift [ galoisconj ] 65- extra multiplication in the innermost loop of Cholesky decomposition (qfgaussred, etc). 66- made FpX_add, FpX_sub, Fq_add, Fq_sub stack-clean. FpX_neg, Fq_neg returned an incorrect result if input was not reduced mod p 67- setrand(4);polgalois(x^8-264*x^6+25410*x^4-1054152*x^2+15856203) --> wrong result [#660] 68- build fails with "env: parameter list too long" [#661] 69- factorff did not accept inputs with t_FFELT coeffs 70- could use PARI stack while reading gprc [ before pari_init ] 71- Mod(Mod(1,v),v) --> invalid object. 72- a = Mod(y, v); y = Mod(1,v); eval(a) --> invalid object 73- for some complicated t_RFRAC z: z' --> impossible assignment I-->S 74- typo in bnfisintnorm(): missed some solutions [ couldn't find a unit of norm -1 even though one exists ] 75- ffprimroot(ffgen( t_POL of degree 1)) --> oo loop 76- wrong result in theta(q, z) if sin(nz) was small for some small n [#667] 77- 1/Mod(0,2) --> impossible inverse modulo: Mod(2, 2) 78- alias(a,b), then ?a --> 'a is aliased to a' 79- -Mod(0,2) --> Mod(2,2) MA 80- [Linux-PPC] missing -fPIC in DLCFLAGS 81- possible oo loop in _isprincipal [ precision was supposed to increase, but could in fact remain the same ] 82- quadregulator(y) -> SEGV [#674] 83- acos(x^0) -> division by 0 [ instead of O(x^8), at \ps 16 ] Analogously, acosh(x^0), asin(x^0), asinh(I+O(x)) --> division by 0 84- dilog(-1) [ more generally polylog of < 0 t_REALs ] should have 0 imaginary part 85- problems with [ build/install ] directory names containing spaces 86- avoid catastrophic cancellation in 3M [ Karatsuba ] formula for t_COMPLEX * t_COMPLEX 87- ix86, x86_64: missing earlyclobber constraint for addllx, subllx, divll 88- ploth(,4) --> huge memory use for large plots 89- stirling(0,0,2) --> 0 [ should be 1, #690 ] 90- deriv(x/(x+1),y) --> invalid t_RFRAC with exact 0 numerator [#687] 91- issquare(t_POL) assumed characteristic 0 [#549] 92- sqrt(Mod(4,5) + x) --> error [ e.g. stack overflow ] 93- hyperu(0*I,1,1) --> forbidden assignment t_COMPLEX --> t_REAL. BA 94- fix compilation problem with g++-4.2 and GMP. 95- ??factor_proven, ??factor_add_primes did not work 96- typo in znprimroot: wrong result for large moduli znprimroot(5*2^127+1) --> 2 [#696] 97- ffgen(x*Mod(1,2)) --> x [ should be 0 ] 98- ffprimroot(ffgen((x+1)*Mod(1,2))) --> oo loop 99- nffactor(nfinit(y),x^2+Mod(1,y)) --> SEGV [#699] 100- "precision error in minim0" on qfminim(G, norml2(M[,1]), 100) from tutorial 101- nffactor(nfinit(y^2+1),(2*x+1)*x*(x+1)) --> SEGV [#702] 102- isprime((6^2176+1)/(6^128+1)) --> length (lg) overflow [#697] [ analogous problems for any large integer ] 103- various problems related to allocatemem() [ + document quirks ] Remove the br_ALOCATEMEM construct and end allocatemem0() by a longjmp 104- missing GC in det_simple_gauss() [ matdet for inexact inputs ] 105- rare stack corruption in add_rfrac [#700] 106- add missing GC in gsubst 107- polred([pol, b]) computed unnecessary but possibly expensive invariants of pol [ e.g. disc, index ] 108- compilation failed on AIX [ YYSIZE_T, pow ] 109- ? Mod(1,2)*x + Mod(1,2)*y %1 = Mod(1, 2)*x + (Mod(1, 2)*y) \\ extra parentheses in constant term ? % + 0*z %2 = Mod(1, 2)*x + Mod(1, 2)*y 110- factornf(x^5+(-a+2)*x^4-a*x^3+(3*a-6)*x^2+(5*a-10)*x+(2*a-5), a^2-5) --> SEGV [ not squarefree -> denominators creeping in ] [#708] 111- problems with isexactzero and t_INTMODs. Mod(0,2)*x*1. -> 0, Pol(Mod(0,2))+2 -> 2, (2+0*I)+I*Mod(0,4)->Mod(2,4), Mod(0,2)/x -> 0 Use isrationalzero instead. 112- substvec(x^2, [x^2], [y]) --> y^2 [ should be an error ] 113- typo in FpM_gauss_pivot: FpM_rank, FpM_image, FpM_suppl, FpM_indexrank much slower than they should be. Analogous problem in FqM_gauss_pivot. BA114- missing GP2C descriptions for Pol and Polrev. BA115- zero FFELTs were not considered as exact zeros [#710] 116- rare SEGV in gp when recovering from error (dereferencing global_err_data equal to BREAK_LOOP) 117- vecsort(t_LIST) returned a t_VEC 118- gp "huge file" + stack overflow --> stack overflow in next interactive command (+ minor memoryleak) [#712] Changed BA 1- The combined GP parser/evaluator has been replaced by a bytecode compiler and a bytecode evaluator BA 2- install(): parser code 'E' and 'I' now refer to closures, not strings: 'I': closure whose value is ignored, like in for() loop 'E': closure whose value is used, like in sum() loop 3- Fl_pow renamed to Fl_powu [ exponent may not be negative ] 4- split usersch3.tex moving function documentation to src/functions/* 5- simplify table of contents for users.dvi 6- rename Flx_rand -> random_Flx, FpX_rand -> random_FpX BA 7- use factor_pn_1 to compute various orders in FF.c 8- file usersch3.tex is now generated from functions/* 9- rewrote logr_abs [ inaccurate + slow for x = 2^k * (1 - epsilon) ] 10- rewrote exp1r_abs [ inaccurate + slow ] and mpexp_basecase [ reduce input mod log(2) ] 11- rewrote mpsc1 [ slow ] -> faster sin and cos 12- [library] rename pointch -> ellchangepoint, coordch -> ellchangecurve 13- prototype of constpi, consteuler. 14- use a little less memory to compute pi, euler, log(2) 15- qfminim(x,b,m,flag) made 'm' parameter optionnal also when flag=0 16- made second argument to matrixqz optional, allow non-prime values 17- matpascal(n < -1), mathilbert(n < 0) now raise an error 18- add optional extra argument to ffprimroot, fforder, fflog 19- allow znlog(x,g) where g a t_PADIC or an t_INTMOD modulo any N that znprimroot(N) would accept 20- log(x t_PADIC): check whether x = 1 (mod p) before replacing x <- x^(p-1) 21- znprimroot(p^k): use isanypower() instead of factor(). E.g. znprimroot(nextprime(10^20)^1000): 8mn --> 12ms znprimroot(N) no longer checks reliably whether (Z/N)^* is cyclic. Result undefined if it is not. 22- padic sqrt much faster [ small and large accuracies ] 23- let primes() indicate a value of primelimit if unable to answer [#625] 24- remove variable names from ?0 25- exp(0e10) returned 1.000, made it 0exxx [ no significant digit ] MSo26- define polchebyshev(n, 1 or 2), pollegendre(n) for n < 0 27- znorder faster for non-prime modulus [ try it for Mod(2,5^10*7^10) ] (compute lcm of local p-adic orders) 28- changed icopyifstack / copyifstack macros so that their arguments are GENs, not GENs typecast to long. 29- add -funroll-loops to gcc flags when compiling arithmetic kernel 30- improve ellap (Shanks) by computing #E(F_p) mod 2 [ idea stolen from Pierrick Gaudry ] 31- nfreducemodpr was exceedingly slow for large t_POL inputs, e.g. w=x^48 + 158*x^46 + 4*x^45 + 12103*x^44 + 448*x^43 + 597874*x^42 + 23928*x^41 + 21373779*x^40 + 802424*x^39 + 588314524*x^38 + 18516794*x^37 + 12951694530*x^36 + 294992428*x^35 + 233870773964*x^34 + 2752210590*x^33 + 3524535272389*x^32 - 5797649292*x^31 + 44873186922754*x^30 - 798816466566*x^29 + 486736157075707*x^28 - 18082470992066*x^27 + 4523171646555185*x^26 - 271968456240780*x^25 + 36127625049532658*x^24 - 3144283847234232*x^23 + 248308835345289047*x^22 - 29271322082172250*x^21 + 1467438460133718165*x^20 - 223406933340907742*x^19 + 7435650911902583447*x^18 - 1405525828628464338*x^17 + 32139937168429173010*x^16 - 7272631544138987758*x^15 + 117563850386577478340*x^14 - 30686320483051428956*x^13 + 359649878031434743177*x^12 - 103986861631984042496*x^11 + 904392935429691313557*x^10 - 276283466933590000414*x^9 + 1822091999374665372405*x^8 - 554259164403897051340*x^7 + 2827767569115449802250*x^6 - 788757355446858093774*x^5 + 3170224521565069297504*x^4 - 708295322502763110380*x^3 + 2280480720610858280676*x^2 - 300602103002034938488*x + 788466592242441477569; nf=nfinit([w, nfbasis(w,1)]); modpr=nfmodprinit(nf, idealprimedec(nf,5)[1]); L = nfgaloisconj(w); vector(#L,i, nfeltreducemodpr(nf,L[i],modpr)); (in this example, the last reduction is down from ~ 1minute to ~ 2s) 32- make sure nfmodprininit chooses a monic T to represent Fq ~ Fp[X]/(T) [#646] 33- remove obsolete undocumented functions outerr, outbeauterr, outsor, outtex. Rename voir -> dbgGEN. Functions brute, outbrute, matbrute, outmat, sor, outbeaut are obsoleted and no longer documented. 34- rename errfile -> pari_errfile, infile -> pari_infile, logfile -> pari_logfile 35- extra test infrastructure [ drop file in src/test/in and possibly src/test/[32|64], then run Configure, no need to edit config/get_tests ] 36- inline gerepileupto/gerepileuptoleaf + improve gerepileupto 37- [libpari] cleanup of user / temp variable handling. manage_var obsoleted (kept for backward compatibility, to be removed), see Section 5.9 for new equivalents. Fixes #633, #650 38- fix t_LIST as components: v = [List()]; listput(v[1],) didn't work [#468] 39- listcreate() and listkill() are obsolete, don't use them. L = List() should be enough in all cases. All lists now grow as needed, without requiring an awkward maximal length (from listcreate). 40- rename sqred -> qfgaussred, signat -> qfsign, sqred1 -> qfgaussred_positive 41- rename gaddmat -> RgM_Rg_add and swap arguments. Add RgM_Rg_add_shallow 42- document library functions zv_neg, zm_transpose, fix typo in documentation for RgX_neg 43- document library functions gmaxgs, gmaxsg, gmings, gminsg. 44- document library function gfloor2n 45- document library function zx_shift 46- cleaned up splines handling [ ploth(,,,256) ] : remove quark_gen & QUARK BA 47- implicitly local variables are lexically-scoped BA 48- local and my can now appear anywhere in a program. 49- [library] rename apell -> ellap 50- Removed the OK_ULONG macro and renamed u_OK_ULONG -> SMALL_ULONG 51- Rename BIGINT -> NO_VARIABLE [used by gvar()], VERYBIGINT -> LONG_MAX, MAXULONG -> LONG_UMAX. Remove BYTES_IN_LONG, TWOPOTBYTES_IN_LONG 52- implement directly gsubsg [ was a macro calling a trivial wrapper ] 53- optimize multiplication for quadratic t_POLMOD [ t_QUAD remains faster ] 54- theta(q,z) very inefficient for large accuracies 55- remove support for nf of the form [nf, change of variable] in nfnewprec() [#672] 56- global() now obsolete and scheduled for removal LGr57- 'make ctags' gctags-specific flags [ add #defines, typedefs ] 58- prototype of nfsubfields [ 2nd argument GEN -> long ] 59- allow t_FFELT in issquare / issquarerem / ispower 60- sqrt(t_SER) now uses Newton iteration 61- rename gissquarerem -> gissquareall, uissquarerem -> uissquareall, Z_issquarerem -> Z_issquareall (analogy with sqrtrem was faulty: we do not store a remainder but the square root) BA 62- User functions are now regular variables holding values of type t_CLOSURE 63- Output of \u is now sorted 64- More explicit error messages in gp_history, e.g. *** History result %10 not available [%1-%6] BA 65- vecsmall_uniq(v) no longer assumes that v is sorted 66- allow ellorder to handle curves over Fp, add an optional parameter to indicate a multiple of the order as in znorder. 67- allow polcyclo(n, a) for an arbitrary a [ had to be a variable ] + major speedups: polcyclo(10^6) 5min -> 16ms. Similarly for polchebyshev, pollegendre and polhermite 68- ?0 listed all "user-defined identifiers". Restrict to "functions" 69- use simplify in setsearch() and Set() [#707] 70- change gcd(t_POL, t_POL) so that inexact inputs have scalar gcd [ used to compute a "sensible" approximate gcd ] Added 1- library functions expu, adduu, subuu 2- library functions divisorsu, factor_pn_1 (using cyclotomic factors and Aurifeuille), merge_factor 3- library function divru, dbllog2r 4- library function ZX_gcd, ZX_isirreducible 5- library function gtos 6- library function pari_daemon 7- library function Fp_sqr, padicsqrtlift 8- library function RgXQ_inv 9- bench 'extract' 10- charpoly: Berkowitz division-free algorithm (new default) [#541] 11- library function phiu 12- library function mkvecsmalln 13- library function chk_gerepileupto, dbg_gerepile, dbg_gerepileupto 14- library function gen_sort_uniq, gen_indexsort_uniq+add flag 8 in vecsort 15- library function remi2n, cmp_RgX, gen_cmp_RgX 16- library function RgV_dotproduct, ZV_dotproduct, RgV_dotsquare, ZV_dotsquare, FpV_dotproduct, FpV_dotsquare 17- library function FpX_Fp_add_shallow 18- library function Q_pval BA 19- new keyword "my" to declare lexically-scopped local variables. 20- new GP function listpop() 21- library function RgX_inflate, RgX_deflate, Flx_inflate, Flx_deflate, poldeflate 22- library function Fp_neg, Fp_add, Fp_sub 23- library function ugcd 24- library function vecinv, vecmul, vecpow, vecdiv, vecmodii 25- library function RgM_isidentity, RgV_isin 26- library function nfnewprec_shallow, bnfnewprec_shallow, bnrnewprec_shallow 27- library function Zp_issquare 28- library function dvmdsBIL, divsBIL, remsBIL 29- library functions gassoc_proto, map_proto_G, map_proto_GG, map_proto_GL, map_proto_lG, map_proto_lGG, map_proto_lGL [ were private with other names ] 30- default factor_proven 31- experimental -balloon option to gphelp LGr32- defaults graphcolormap, graphcolors [runtime-defined colormap for plots] LGr33- bit 4096 [ complex ] to ploth 34- member function .p / .mod for t_PADIC 35- same mnemonic flags to plotrecth as in ploth BA 36- member function .pol, .mod and .p for t_FFELT BA 37- New type t_CLOSURE to store GP functions 38- Ability to use arbitrary comparison functions in vecsort() 39- library functions closure_callgen1, closure_callgen2, closure_callgen, closure_callgenvec. 40- GP function apply(), select() 41- library functions FF_issquare, FpXQ_issquare, Flxq_issquare BA 42- library function vecsmall_uniq_sorted 43- bench 'ff', 'exact0' 44- has_getenv.c 45- library function FpX_oneroot 46- library function gcmpX 47- library functions ZV_sort, ZV_sort_uniq, ZV_search Removed 1- obsolete function kbessel2 (now static). Removed optional flag in besselk 2- Removed obsolete optional flag in ellap(), Mod() and gcd() 3- Rename gen_search_aux -> gen_search and document it [ old gen_search disappears: use tablesearch() ] 4- undocumented library functions gpolylogz, polylog, polylogd, polylogp, polylogdold. Use polylog0 with appropriate flags. 5- undocumented library function ghell2. Use ellheight0 with appropriate flag. 6- obsolete function log0; use glog 7- obsolete undocumented library function mpdivz, polzagreel, RgX_powers (use RgXQ_powers) 8- obsolete undocumented library function sqred3 9- the emacs/ directory: PariEmacs is now distributed separately. 10- obsolete functions ellap0, apell2 11- obsolete header file pariport.h 12- obsolete error codes paramer1, valencer1, accurer, caracer1 13- removed obsolete system-specific #ifdefs (macintosh, alliant) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.1 (released 28/03/2007): Fixed 1- qflll / qflllgram (t_MAT with t_FRAC entries) would not reduce to the integer case (--> insufficient precision, SEGV) [#505] 2- [Cygwin] missing -L... -lgmp when compiling with gmp. 3- ispower(522^3) -> 0 [ looked like a 7th power to is_357_power(), which then forgot to test for cubes ] [#506] LGr 4- [gphelp] race condition --> incomplete cleanup (improved patch BA) 5- Cleanup library linking: do not link libpari with -ld [only gp], do not link gp with -lgmp [only libpari]. Side effect: libgmp.so no longer needed for modules compiled by gp2c-run 6- when nf.disc < 0, nf.diff was an incorrect PARI ideal [#510] 7- nf.codiff was only correct up to multiplication by some rational number (a divisor of nf.disc) [#510] 8- inaccuracy (>= 2ulp) in [cached] log(2) [#498] 9- exp, sinh, asinh, tanh, atanh were inaccurate near 0 10- [GMP kernel] forvec(x=[[-1,0]],print(x)) --> error [#509] [ 'resetloop' failed when passing through '0' ] 11- nfbasistoalg(nfinit(y),x) created an invalid t_POLMOD 12- incorrect result in ZX_resultant (accuracy loss in bound computation) 13- bnfinit(): avoid further precision problems for large degree fields 14- [Configure] gcc-specific flags were used on linux/freebsd/cygwin, even when __gnuc__ was unset 15- factor( pure power FqX ) --> SEGV 16- [GMP kernel] polrootsmod(f, 4) --> wrong result [ low level t_INT manipulation not using the int_* macros ] 17- polrootspadic(f, 2, r) --> some roots would be found twice [ due to FpX_roots(f, 4) called ] [#521] 18- ??sumalt doesn't compile: in GPHELP, treat \ref in verbatim mode [#518] 19- matinverseimage returned [;] when no pre-image exists. Conform to the docs: "an empty vector or matrix", depending on the input types. 20- [Configure] abort when $CFLAGS is not supported by $CC 21- 3.5 % 2 --> error [ should be 0.5 ] 22- sin(1/10^100) --> 0e-28 [ also affected cos,tan,cotan ] 23- fix e.eta and elleta such that e.eta = 2 ellzeta(e,e.omega/2) [ was ellzeta(e,e.omega/2) ]. COMPAT. 24- elleta(e) was different from elleta(e.omega). Analogous problems in all quasi-elliptic functions. COMPAT: change e.omega so that e.omega[1] / e.omega[2] belongs to the Poincare half plane [ used to be the inverse ]. Together with 24: the Legendre relation now reads w1 e2 - w2 e1 = 2 I Pi Rationale: 1) the action of Sl_2(R) becomes the standard one, not a twisted one 2) fixes quite a few normalization problems in our code. 25- check that k >= 0 in thetanullk [#531] 26- isprime(-2,1) returned 1 27- Fix 'Not enough precision in thue' error BA 28- [OS X] Fix kernel detection on x86_64-darwin 29- Remove "VERY long time" Warning in bnfcertify (few minutes nowadays) BA 30- missing prototype for documented function ZY_ZXY_rnfequation 31- sqrt(x^2/y^2) --> SEGV [#536] 32- \r foo no longer worked if foo was a directory and foo.gp a valid input file [#540] BA 33- [Configure] spectacular failure to recognize gcc under some locales. 34- polredabs(x^8+2*x^6-5*x^4+78*x^2+9) was incorrect [ missed x^8+6*x^6-x^4+54*x^2+25 due to incorrect "skipfirst" ] [#542] 35- typo in resmod2n (both kernels) [#546] 36- At \p28, 0.1 - 0.1 would return 0.E-30 instead of 0.E-29 BA 37- missing prototype for documented function FpX_div_by_X_x 38- isprime(,0) very slow when primelimit is large [#546] 39- nfmodprinit could create FpX's which were not reduced mod p 40- O(x^3)^(1/2) was O(x^2) instead of O(x) RB 41- the following TODO item: v = vector(2); v[1] = v = 0 --> SEGV. Occurs with high probability if any variable is "deleted", while it (or part of it) is still in use Reference count could be helpful here. 42- substpol(x^-2+O(x^-1),x^2,x) --> error [#555] BA 43- [TLS] addss, addsr and subsr were not reentrant. Changed 1- concat(t_VECSMALL, t_VECSMALL) to return the concatenated vector [was: a vector with two t_VECSMALL entries] 2- pariprintf() so that it handles t_STR as print() [ don't include quotes ] LGr 3- [Makefile] make generated src/funclist independent of locale 4- Extend Pocklington-Lehmer to the case N-1 = FU, F > N^(1/3) BA 5- Much faster base-2 to base-10 conversion. BA 6- FpX_Fp_add() is now clean. BA 7- rename ZY_ZXY_resultant -> ZX_ZXY_resultant, ZY_ZXY_rnfequation -> ZX_ZXY_rnfequation and FpY_FpXY_resultant -> FpX_FpXY_resultant. BA 8- FpV_polint() now take a variable number as last parameter. 9- use Miller-Rabin-like improvement in znprimroot and FpXQ_gener 10- indexrank, indexsort and indexlexsort now return t_VECSMALLs 11- API for gen_sort, vecsort Added BA 1- derivnum(x=a,expr) for numerical derivations BA 2- library function strntoGENstr 3- function Vecrev BA 4- ppc64 level0 inline assembly kernel 5- library function floor_safe() 6- library function itostr() BA 7- library function Fp_div(), Fp_mul() BA 8- library function FpXQ_norm() BA 9- library functions FlxX_resultant() and Flx_FlxY_resultant() BA 10- library function FlxY_Flx_div() BA 11- library function Flm_transpose() BA 12- library function Flx_Fl_add() BA 13- library function Flxq_div() BA 14- function stirling (Stirling numbers of 1st and 2nd kind) BA 15- library function FpX_valrem() 16- library function Flxq_gener BA 17- library function Flxq_norm, Flxq_minpoly, Flxq_charpoly BA 18- [toplevel benchmark] ffisom BA 19- library functions Fp_order, FpXQ_order, FpXQ_log, FpXQ_sqrtn, Flxq_order, Flxq_log, Flxq_sqrtn 20- library functions gen_sort_inplace, gen_indexsort, sort_factor, indexvecsort BA 21- New PARI type t_FFELT and support functions (FF_*) for finite field elements. BA 22- functions ffgen, fforder, fflog, ffprimroot for finite field elements. Removed 1- obsolete functions readexpr(), readexpr_nobreak() 2- pariemacs support from Configure 3- obsolete functions sindexsort, sindexlexsort, sindexrank %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.0 (released 06/10/2006): Fixed 1- typo in remiimul: wrong result in a "failsafe" branch (hardly ever taken). May affect modular powering /Fp if p >> 10^1300 [#457] Also affects the gmp kernel, for p >> 10^5800. 2- rare accuracy problem in bnfinit P=x^8-787856*x^6+232721637848*x^4-30546112988506688*x^2+1503204734505922286224; setrand(1974190693); bnfinit(P) --> non invertible matrix in gauss 3- inconsistent return type in nffactormod [#460] 4- the following TODO item bnfinit may give wrong answers because we cheat on the value of Bach's bound, using B := 0.3 log^2 D by default, where 0.3 should really be 12 (under GRH). If the prime ideals of norm <= B do not generate the classgroup, we may not detect it, and compute junk. Ex: * setrand(3); bnfinit(y^4 + 1190*y^2 + 1416100).cyc --> [8,2,2,2]. The correct structure is [8,4,2]. * setrand(1414185642); bnfinit(y^4 + 635*y^2 + 403225).reg [twice the correct value] * setrand(867341586); bnfinit(y^4-y^3+6122*y^2+6121*y+37466641).gen[2] [is principal]. Group structure and regulator are correct! Retune check_bach() IZ 5- remove bogus test for "external help" (= ??) IZ 6- [OS/2]: stack check [prevent oo recursion] present but not enabled IZ 7- [OS/2]: bogus [BUG] in 'program' bench (install pb not detected) 8- gammah(1+O(3^5)) --> incorrect type in ggamd. 9- invalid read in copy_leaf [ SEGV in some libc ] BA 10- ellheight short help was accidentally truncated. 11- substpol(1+O(x^(2*n)),x^2,x) --> 1+O(x) instead of 1+O(x^n) [#470] 12- [OS X] only use -no-cpp-precomp with Apple cc 13- divrem(x,x,y) --> [1/y*x, 0] 14- (1+x)/(1-x)/(1+x)^2 not simplified [#472] 15- typo in qflll: in rare cases (exact input+floating point computation+ precision increase in last-but-1 step), the returned base change is not properly updated in last iteration --> basis not LLL-reduced 16- simplification missed in div_scal_rfrac() [ #473 ] 17- ispower(x^k, k) would answer 0 for some x and k in {3,5,7} [#476] 18- content(t_MAT with exactly 1 col) gave a wrong result 19- random(N) was not uniformly distributed in [0,N-1] (use a reject strategy instead of moding out) [#210] 20- rare bug in red_montgomery (returning 0 with + sign, an incorrect object) [ polrootspadic(x^11+x,11,10) --> corrupts gen_0 ] 21- qfbsolve(Qfb(1,2,10),5) --> [0,0; 0,0] instead of 0 [#479] 22- ispower(0, n, &z) would not set z 23- wrong result in conversion t_QUAD -> t_PADIC whenever disc = 1 (4) JJ 24- gaddgsz macro was wrong [#481] 25- gener_Fl(p^k) can't handle k > 1, use gener_Zl instead [#480] SC 26- [GMP] mp_set_memory_functions was called with an incompatible realloc function. [#484] 27- raising a t_QFI or t_QFR to the power n would return a reduced form (OK) except when n = 1. Make it systematic. 28- in rare cases (return 0, native kernel) int_normalize was not suitable for gerepileupto 29- idealnorm(nf, t_POL) didn't work AM 30- [TeXmacs] typo in texmacs_output: x --> [#491] 31- accuracy errors in bnfinit: setrand(3); bnfinit(x^2+999999999999971) [ use a failsafe version of gmod (modr_safe), and increase accuracy if necessary ] 32- possible corruption of gen_2 in mynegi() [ hnflll ] 33- factor(4/x) --> [2, 2; x -1] (content not removed) BA 34- bnrstark prototype code was non-standard. 35- rnfkummer(,,degree) often found too many fields [#482] 36- loss of accuracy in p-adic ellinit: wrong digits and spurious errors: E.g i = 5; ellinit([1, -1, 1, -1, -14]*(1+O(17^i))) 37- missing GC in forvec(,,2) BA 38- Interrupting GP could lead to a freeze. [#488] 39- possible stack corruption in charpoly(,1) 40- Ser(x) raised an error [#499] Changed 1- moved cgiv, gtofp to inline kernel 2- reduce amount of memory needed by APRCL 3- remove CPP from Configure tests (not needed) 4- allow arbitrary sequences (not only expressions) in sum, prod, etc. sum(i = 1, 2, 1;2) --> 4 [ was: error ] 5- checked that no 2-strong pseudoprime passes BSPW primality test up to 10^15 (use Galway's list, extending Pinch's 10^13) 6- random() now uses Brent's XORGEN (replaces congruential linear generator) getrand() returns the FSR internal state array, used by setrand(). The latter no longer returns the input seed. (Initial patch by RR) 7- for install(): parser code 'E' is now obsolete, use 'I' 8- if issquare(x, &n) == 1, always set n to a square root of x 9- if ispower(x, k, &n) == 1, always set n to a k-root of x 10- issquare(t_QFI or t_QFR) now is an error. Use explicitly issquare(component(x,1)) if you relied(?) on the old behaviour 11- [library] rename gener_Fp -> pgener_Fp, gener_Fl -> pgener_Fp [ contrary to 'gener', these assume that their argument is prime ] 12- [library] rename cyclo -> polcyclo, subcyclo -> polsubcyclo, tchebi -> polchebyshev1, legendre -> pollegendre 13- restrict the types allowed in gaffect and gaffsg to scalar types and vectors of such. 14- vecextract(x, bitmask) much faster [ read bits, don't use shifts ] 15- improve hyperu 16- remove gp-specific signal handler. Use the one in libpari 17- [library] pol_1 and pol_x are no longer global arrays but functions 18- [GMP] was inefficient for small sizes (e.g. 1-word operands) 19- optimized rectplothrawin & plot (remove gaffect, use gtodouble whenever possible). Coordinate computations should be faster and more accurate. Added BA 1- function Flm_rank BA 2- Add experimental --enable-tls Configure option and thread-local stack support. Warning: using this option break the ABI. 3- centerlift(t_PADIC) 4- pgener_Zp, pgener_Zl 5- dvdiu, dvdis, dvdiu, dvdsi, affgr 6- cgetipos, cgetineg, togglesign RM 7- polhermite, polchebyshev2 8- allow rnf.zk and rnf.nf 9- [toplevel benchmarks] bnfisintnorm, quadclassunit, rnfkummer 10- ZX_factor, QX_factor 11- allow gzip'ped elldata & galdata files 12- allow t_VECSMALL in vecmin / vecmax BA 13- add pari_stackcheck_init() function to control deep recursion detection 14- Configure --tune flag Removed 1- Odos/Makefile (no longer functional, obsolete) 2- old CodeWarrior-specific hack (malloc) 3- error code: intger2, affer3, overwriter 4- useless static function gp_handle_SIGINT 5- functions changevar() [ use substvec ] and reorder() [ use variable() to get the list of user variables ], global arrays pol_1[], pol_x[] ordvar[] and polvar[] pari-2.7.5/CHANGES-2.60000644000175000017500000014412512405547147012424 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.7.0 (released 21/03/2014): Fixed 1- e = ellinit(E over Qp); ellztopoint(e, 3) --> SEGV 2- thue((x^2+1)^2*(x^2-2),-4) --> missing solutions [+-1, +-1] BA 3- spaces in directory names were not supported 4- silent overflow when inputing t_REAL of huge exponent [#1526] 5- zeta(2+10^-101*I) -> overflow 6- RgX_mullow(f,g,n) could return a result of degree n (instead of < n) Same with RgX_sqrlow 7- ellrootno(E) could lead to a SEGV [#1527] 8- issquare(Mod(3,22)) -> 0 [#1528] JD 9- polcyclo(5, Mod(-1,3)) was the negative of correct value JD 10- elltors(ellinit("90c3")) returned Z/12 but a generator of order 6 11- thue(thueinit(x^3-x-1),1578191) => oo loop [#1532] 12- catastrophic cancellation in eint1 (x moderately large) 13- SEGV in ellweilpairing [#1535] 14- factor(Mod(1,2)*Pol(1)) -> [Mod(0, 2) 1] 15- Mod(Pol(0), 2) -> 0, instead of Mod(0,2) 16- QXQ_to_mod was called with t_POLMOD arguments 17- ellwp(E, 'z) had stopped working for E not defined over C 18- nfdisc(T, t_MAT=partial discriminant factorization) => corruption [#1542] 19- norm(Mod(z,T)) where z is not a t_POL or in a different variable than T => wrong result [#1539] 20- polresultant(Pol(Mod(0,2)), x) -> 0 instead of Mod(0,2) 21- nffactor(T, pol) possibly wrong results when nfinit(T) is not rigorously computed [#1545] 22- gmodgs(t_POLMOD,): incorrect implementation BA 23- library functions Fp_pow/Fp_pow mishandled negative basis 24- gcd(1/(2^64*y),Mod(x^2,2^64*x^3)) --> inconsistent gcd [#1541] 25- matadjoint([x,0,0;0,0,0;0,0,0]) => wrong variables [#1547] 26- ellordinate(e, exact t_COMPLEX) => either a wrong result (no solution) or a solution computed at an incorrect accuracy (DEFAULTPREC) [#1548] 27- weber(1.0*I,1) => SEGV [#1549] 28- primepi(2^32) => oo loop [on 32-bit machine] 29- primepi(N >= 2^32 or 2^64) off by 1 JD 30- [libpari] initprimetable(2^20): infinite recursion 31- very inefficient div_rfrac_pol() [#1537] 32- polresultantext(x+1,x^2) -> [-# + 1, 1, 1] 33- for(i=a, b, ) where a < 0, b < 0 : go through wrong indices if #a != #b 34- printf("%1.2f",Mat([1.,2.])) -> SEGV [#1550] Added BA 1- library functions FlxX_to_FlxC, FlxXV_to_FlxM, polx_FlxX BA 2- library function Flx_lead 3- library function RgV_to_RgM Done for version 2.6.2 (released 30/01/2014): Fixed 1- eulerphi(t_INT factorization) corrupted the input BA 2- 8bit chars were interpreted as end of input 3- Bernoulli numbers were no longer cached [2.6.0] 4- typo in Brillhart, Lehmer, Selfridge primality test [#1467] 5- [Configure] confusing error messages when C compiler doesn't work 6- scalar + t_SER = 0 => wrong valuation (1+O(x)-1 => O(x^2)) BA 7- squaring of t_REAL was not faster than multiply 8- 1+O(2^(2^18)) => O(2^0) (silent overflow) PB 9- Mod(1, 2) - Mod(2, 4) => Mod(-1,2) [#1469] 10- memory corruption in subgrouplist: e.g. subgrouplist([53835600, 29], 5) 11- SEGV in zncoppersmith (when auxilliary polynomial was non-monic) 12- division by 0 in Fl_ellcard_Shanks [2.6.1, #1474] 13- ellwp([1,I]) -> stack overflow [2.6.0] 14- sumdedekind(h < 0, k < 0) wrong result; if gcd(h,k) > 0 as well 15- galoisexport(G, 1) -> SEGV 16- ??default(log) no longer worked 17- rnfalgtobasis, rnfbasistoalg, rnfeltup, rnfeltdown, rnfeltabstorel, rnfeltreltoabs were not treating their inputs consistently, and accepted (or crashed on) too many incorrect inputs. 18- rnfideal* did not handle correctly the 0 ideal 19- rnfidealtwoelt(non integral ideal) => crash 20- nfeltreducemodpr(K, non invertible elt mod pr,...) => wrong result (now an e_INV error) 21- rnfbasis: wrong result due to a mistake in gen_if_principal [2.6.0, revert d62f0de01] 22- nfsolvemodpr(nf,a,b,P): a must be invertible, as in matsolve (was not documented, used to SEGV). Raise an error if not. 23- various bnrdisclist crashes 24- bnrclassno(bnf, prime ideal) -> SEGV 25- forpart(x=k,) raised an exception if k < 0 [ now empty loop ] 26- deriv(constant) now returns 0 in the base ring (not gen_0). 27- inconsistencies and mistakes in deriv / intformal of t_POLMOD: forbid integration wrt the main variable of x.mod, deriv(Mod(x, x^2),x) was Mod(1,x^2) and deriv(Mod(y,x^2),y) was 0 instead of respectively 0 and Mod(1,x^2) 28- idealchinese with t_POLMOD inputs -> input error 29- idealchinese with denominators -> SEGV 30- qflll(Mat(0)) returned Mat(1) 31- infinite loop in sumpos: sumpos(n=1,-log(cos(1/n))) [#1481] BA 32- doing allocatemem in the break loop would corrupt the new break loop 33- relative error in eint1 was larger than expected 34- select(t_LIST,,1) [ indirect select ] didn't work 35- vecsort(List(),,4) -> SEGV 36- factorpadic / polrootspadic lost accuracy when converting output from integers to t_PADICs (factorpadic(t^2 + 3^5, 3, 5) -> irreducible factor (1 + O(3^5))*t^2 + O(3^5)*t + O(3^0) 37- Mod(0,0) is no longer valid => division by 0 (as Mod(x,0) for x != 0) 38- RgX_to_RgV no longer accepts other types than t_POL. Use Rg_to_RgV for a more permissive function 39- broken Fq_sqrt when T != NULL and t_INT input 40- ispower(1009^11) -> 0 [2.6.0] 41- ellinit([0,1,1,0,1],2).group -> SEGV 42- nfroots(nf, deg 1 polynomial) -> wrong result 43- Configure --time=ftime: wrong reported timings 44- mateigen(rational matrix): inconsistent concatenation [#1489,2.6.0] 45- polroots(): wrong accuracy of (real) 0 components 46- randomprime(2) -> SEGV [#1493, 2.6.0] 47- forqfvec(v,[;],0,) -> SEGV [#1495] 48- poliscyclo(x^0) -> 2 49- truncation (precision) errors in bnfnarrow [#1491] 50- matadjoint assumed that n! is invertible. If this is not the case, now use a safe algorithm 51- leading coefficient of elldivpol ignored the characteristic,e.g. E=ellinit([a1,a2,a3,a4,a6*Mod(1,2)]); elldivpol(E,2) 52- gcd involving a t_FFELT -> SEGV 53- oo loop in ispower for huge arguments / oo loop in prime iterator in congruence classes [#1498, 2.6.0] 54- L=[1,2,3]; apply(x->L=x,L) -> SEGV ( idem select and [|x<-] operators ) 55- (k+1.)/k - (2*k+1.)/k -> incorrect object 56- gcd(x,0.) -> 1 but gcd(x,Pol(0.)) -> x [ the former is correct, since 0. is inexact and may represent an arbitrary small non-zero real number ] 57- eint1 misbehaved at large precision [#1499] 58- polredbest(T,1) incorrect if T non-monic or degree 1 59- nfcertify might miss a factor to be certified, e.g. P=polcompositum(x^4+437*x+19,x^5-571*x+27)[1]; nfcertify(nfinit(P, [2,3,5])) was empty 60- polresultantext(t_POL in y, t_POL in y,y) -> U/V as t_POL in x [#1509] 61- inconsistent handling of t_POL "divided by" scalar among the variants of Euclidean division (%, divrem, \, ...). E.g. x % 2 is OK, but x % Mod(2,3) was not. We now follow the semantic of grem/gdeuc/poldivrem: a scalar is understood as a t_POL of degree 0 in the proper variable [#1510] 62- incorrect rounding in mulur BA 63- Configure: --includedir was ignored 64- add GC in RgV_dotproduct / RgV_dotsquare 65- ZX equal was checking variables, contrary to the spirit of the specification (and contrary to RgX_equal). Specify behaviour properly: none of the internal .*[xX]_equal function check variable numbers. 66- arithmetic functions did not accept factorizations of negative integers (whereas most of them are defined for negetive integers) BA 67- Configure --time=ftime actually tested times, not ftime. Remove ftime from the default list of timer functions (reports wallclock time, not CPU time) [#1523] 68- polredabs() could (find then) forget some polynomials [#1511] 69- poldisc(x^3 + Mod(2,3)*x^2) --> e_INV 70- (Mod(4.,y^2+1)*(1 + O(x)))^(1/2) -> junk (= [2.0+O(x)),2.0+O(x)]~). Worse if other t_POLMOD coefficients. Now exception. 71- sin(O(p)) returned 1+O(p) instead of O(p) Changed 1- default help text for a user function is now as in \u: fun = (args)->body 2- after addhelp(f,...), ?f no longer include default help text for a user function (function code). Type 'f' to see the function code. 3- primes([a,b]) now returns the primes in the interval [a,b] 4- install: add symbol name in library and GP prototype to default help 5- the rnf structure format 6- library functions: rename rnfelementxxx -> rnfeltxxx, rnfidealhermite -> rnfidealhnf 7- allow mathnf(t_VEC) [ apply Mat() automatically ], gives acces to the ZV_gcdext() routine. 8- mathnf(,2) (generic vs integral t_MAT) is deprecated: we always test the matrix entries and choose the appropriate routine 9- bnrclassno: allow all standard ways to define class fiels (A,B,C), not only bnf + module 10- bnrinit(bnf,f): allow using idealstar(bnf,f) in place of f 11- Let Set(t_VECSMALL v) behave as Set(Vec(v)) 12- ffgen(T) now checks whether T is squarefree (testing for irreducibility is too expensive) 13- variable() no longer raises exceptions: if no variable can be associated to the object, return 0. Thus "if (!variable(x), )" may be used to test wether x has a "variable". JD 14- polcyclo(n, x) now works for all roots of 1 15- quadpoly no longer accepts vector/matrix arguments, see 2.6.0,C94 16- [libpari] renamed ZM_hnfremdiv -> ZM_hnfdivrem 17- x t_REAL * y t_INT: either convert y to t_REAL (as before) or use integer multiplication (if lg(x) >> lg(y)) 18- GP: all results are now stored in GP history, together with the time to obtain them [ we used to only store non-gnil results, and no timings ] 19- chinese(t_POL,t_POL): allow polynomials of different degrees 20- deplin(): use FpM/Flm/F2m routines if possible (like all other generic linear algebra routines) 21- FpM_gauss(a,b,) from modular kernel no longer allow all types of input: split into FpM_FpC_gauss (b t_COL) and FpM_gauss (b t_MAT). Same for all modular xxx_gauss functions 22- O(1/x^2) --> error [ now equivalent to O(x^-2) ] 23- faster evaluated polhermite/pollegendre 24- polhensellift / ZpX_liftfact: use quasi-linear ZXX_mul_Kronecker instead of RgX_mul (~ Karatsuba) 25- [libpari] renamed gcmpX -> gequalX 26- [libpari] renamed ordred -> polredord 27- the prid structure returned by idealprimedec: the anti-uniformizer tau (pr_get_tau) is now stored via its multiplication table 28- rnfpolredabs(x,3) did not conform to the documentation (which did not make sense). Fix documentation and function, for rnfpolredbest as well. 29- [libpari] renamed recip -> serreverse 30- lift(x,'v) / centerlift(x,'v) now only lift t_POLMODs in variable v, no longer (most) t_INTMOD / t_PADICs met along the way 31- lift / centerlift no longer raise an exception when they encounter a non-arithmetic type (e.g. a t_REAL or even a t_STR) in a structure. They just copy the offending sub-object as-is. 32- generic polynomial Euclidean division (grem, gmod, poldivrem): when result is the zero polynomial, use RgX_get_0, not gen_0 / pol_0 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 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 37- define eulerphi(0) = 2 [ now eulerphi(n) = znstar(n).no for all n ] 38- allow subst(t_SER,x,exact 0): subst(2+O(x),x,Mod(0,3))->Mod(2,3) [#1513] 39- [libpari] rename gsh -> gsinh, gch -> gcosh, gth -> gtanh, gash -> gasinh, gach -> gacosh, gath -> gatanh, ggamd -> ggammah (follow GP names) 40- no longer naively use the Karatsuba/3M formula to multiply t_COMPLEX of t_REALs: loss of accuracy is too important and unpredictable from the user's point of view [ e.g. (1+ 1e-90*I)*(1e90+I) -> 1. E90 + 0.E52*I, when the definition directly yields 1. E90 + 2*I ]. Could use it when the exponents of real/imaginary parts are close, increasing the precision by the exponent difference (increasing overhead...): not done yet. 41- renamed mpexp1 -> mpexpm1, cxexp1 -> cxexpm1 42- change prototye of mpsincos1 and rename -> mpsincosm1 Added EP 1- Configure option for gcov/lcov support 2- libpari function FF_f, member function g.f for t_FFELT (definition field has p^f elements) 3- libpari functions gprimepi_upper_bound, gprimepi_lower_bound, primepi_lower_bound, primes_interval, primes_interval_zv, primes_upto_zv, primes0 4- libpari functions rnf_get_absdegree, rnf_get_invzk, rnf_get_map, rnf_get_nf, rnf_get_nfdegree, rnf_get_nfpol, rnf_get_nfvarn, rnf_get_pol, rnf_get_polabs, rnf_get_zk, rnf_get_nfzk, rnf_get_varn, rnf_get_disc, rnf_get_index, RgV_is_QV, RgX_equal_var 5- allow rnf.disc, rnf.index 6- functions rnfelttrace, rnfeltnorm 7- function ZV_gcdext, based on ZM_hnflll (simplified) 8- allow ffgen(p^f) instead of ffgen(ffinit(p,f)) 9- [libpari] Fq_sqrtn 10- mathnfmodid(m, d): allow d an arbitrary vector of positive integers. The old syntax (d an integer, representing a vector of equal integers) is still allowed LGr11- GP function Colrev 12- GP operator %#n to recover time used to compute history result %n 13- GP function getabstime() 14- [libpari] Rg_to_F2, RgV_to_F2v, RgM_to_F2m, F2c_to_mod, F2m_to_mod, Flc_to_mod, Flm_to_mod, F2m_F2c_invimage, F2m_invimage, F2m_suppl, Flm_suppl, F2m_rank, Flm_rank, F2m_rowslice, F2v_slice, F2v_ei BA 15- Parallel GP support (parapply, pareval, parfor, parforprime, parselect, parsum, parvector) 16- [libpari] residual_characteristic 17- GP function characteristic() 18- [libpari] muluui, diviuuexact 19- [libpari] Kronecker_to_ZXX, ZXX_mul_Kronecker BA 20- conversion from matrices of FFELTs to low level (Fq/Flxq/F2xq) kernels for faster treatment. 21- FqM_det, FlxqM_det, FlxqM_inv, F2xqM_det, F2xqM_inv, F2xqM_image, F2xqM_image, F2xqM_rank, FFM_det, FFM_image, FFM_ker, FFM_rank, FFM_inv 22- ZM_rank, ZM_indexrank, ZM_indeximage 23- GP function normlp BA 24- GP function vecsum 25- [libpari] pr_equal, ZC_nfval, ZC_nfvalrem, ZC_prdvd, ZV_Z_dvd 26- allow .p / .e / .f / .gen for modpr structures 27- function rnfpolredbest 28- functions qfnorm, qfbil 29- [libpari] ZM_multosym, RgM_multosym, RgMrow_RgC_mul, RgM_transmul, RgM_transmultosym, ZM_transmultosym 30- [libpari] nf_rnfeq, nf_rnfeqsimple, eltreltoabs, eltabstorel, eltabstorel_lift, nf_nfzk, nfeltup, QXV_QXQ_eval, QXX_QXQ_eval 31- [libpari] factor_pn_1_limit 32- [libpari] get_FpXQ_star, gener_FpXQ_local BA 33- move gpinstall to libpari 34- liftall() lifts recursively all t_INTMOD/t_PADIC/t_POLMOD components 35- liftint() lifts recursively all t_INTMOD/t_PADIC components 36- liftpol() lifts recursively all t_POLMOD components BA 37- GP function logint PB 38- [libpari] gen_matmul, gen_matcolmul, FFM_mul, FqM_FqC_mul, FqM_mul, F2xqM_mul, F2xqM_F2xqC_mul, FlxqM_FlxqC_mul, FlxqM_mul. 39- [libpari] Flx_equal, F2x_equal BA 40- [libpari] FpM_powu/Flm_powu/F2m_powu 41- new GP function idealprincipalunits 42- [libpari] checkabgrp, abgrp_get_no, abgrp_get_cyc, abgrp_get_gen, bid_get_grp, bid_get_no 43- [libpari] FpX_disc 44- [libpari] retmkcomplex 45- GP function expm1 (= exp - 1, avoiding cancellation) Removed 1- optional flag to factorpadic() [ enabling Buchman-Lenstra + round2 ] Use the default = round4 2- useless wrappers map_proto_GG, map_proto_GL, map_proto_lGG 3- [libpari] useless functions gand, gor 4- [libpari] useless function ratlift [ use Fp_ratlift ] Done for version 2.6.1 (released 20/09/2013): Fixed 1- Allow compounding 1-letter flags to gp, e.g. qp -qf [ used to silently ignore the 'f' ] 2- ellminimalmodel, followed by ellchangecurve ==> structure incorrectly updated [wrong Q_MINIMALMODEL component] [2.6.0, #1416] 3- lift(1/2+O(2))=2/1 --> incorrect result + corrupt object [2.6.0, #1424] 4- local() could corrupt polynomial variable of the same name 5- write did not fclose() the output file handle [2.6.0, #1425] PB 6- issquare(Mod(1,2)) -> domain error [2.6.0, #1429] PB 7- issquare(Mod(0,2),&s); s -> Mod(2,0) error [2.6.0, #1430] 8- ellheight(E not given by minimal model,P) -> domain error [2.6.0, #1432] 9- ellchangecurve(E, [1,0,0,0]) lost Q_MINIMALMODEL ->SEGV later [2.6.0] 10- warning() would print "warning: user warning:"-> "user warning:" [2.6.0] 11- matinverseimage(A, t_MAT B) would treat individual columns B[,i] independently and successively. Now use a single Gauss reduction. 12- Flm_Fl_mul returned a wrong result 13- ellinit(ellfromj(Mod(0,17))) -> curve defined over Z [2.6.0, #1436] 14- allocatemem: make sure fix_size() is called to avoid alignment problems [#1437] 15- ellmodulareqn(2) did not clean the stack properly [2.6.0, #1442] 16- issquare(Mod(13,121)) --> not an n-th power residue in Qp_sqrt [2.6.0] 17- stack corruption in carberkowitz / charpoly(,,3) [ session crash ] 18- ellinit(E over Fp, t_FFELT) => error [2.6.0] 19- mateigen([5/3,7/45;0,21/10]) => precision error (missing eigenspace) 20- subst(O(x^2),x,0*x) => SEGV [#1447] 21- memory corruption in aprcl [2.6.0] 22- factormod(,2) => wrong result [2.6.0, #1451] 23- dirmul/dirdiv: incorrect result length when valuation > 1 24- x,y a t_PADIC, x === y always returned 0 [2.6.0] 25- bernpol(0) => memory corruption [2.6.0, #1458] 26- round((1e-40+x) / (1e-39+x)) would create the invalid object x/x 27- polgalois(x^11 + 627*x^4 - 584) -> F_110 instead of S_11 [#1460] 28- input lines with more than 2^31 characters (without \n) resulted in a truncated read [#1461] 29- znlog(1,Mod(8,9)) -> division by 0 [#1463] 30- plot(x=1,2,x) gave a graph with 0<=y<=2, instead of ymin<=y<=ymax 31- ?= or even = would apparently hang GP (waiting for further input) Added 1- genus2red: an implementation of Liu's algorithm to determine the reduction of a genus 2 curve (at p > 2). Based on genus2reduction-0.3, http://www.math.u-bordeaux1.fr/~liu/G2R/ (Cohen & Liu, 1994) mostly rewritten from scratch: - adapted to pari-2.* - somewhat modularized - fixes all known instances of 'bug27' and 'bug28' (at p = 3, reported through Sage users). - bench 'genus2red' contains a check of at least one instance of each of Namikawa-Ueno's types + all cases on which the original genus2reduction was known to fail. [CAVEAT: the interface will change] 2- allow to startup gp with flags --default key=val (or -D key=val): execute default(key,val) on startup BA 3- functions Flm_center, Flv_center, zv_to_Flv, zm_to_Flm, zm_mul, zm_zc_mul, scalar_Flm BA 4- function minim_raw 5- function QX_complex_roots PMo 6- function forpart for looping over partitions 7- [libpari] forcomposite_init / forcomposite_next, reimplement forcomposite() using this iterator 8- Configure now generates a file 'config.log' to help debugging when it makes a mistake (contains all messages from compilers) 9- [libpari] RgM_invimage, RgM_RgC_invimage, FpM_invimage, FpM_FpC_invimage, Flm_invimage, Flm_Flc_invimage, Flm_neg 10- [libpari] serchop0, integser functions 11- psi(t_SER) using Luke's recursion, then lngamma, gamma, gammah for t_SER arguments around an arbitrary complex z0 (was implemented for z0 = 0,1 only) PB 12- PARI functions FlxqM_gauss, FlxqM_inv and FqM_gauss 13- PARI functions FpM_hess, FpM_charpoly, charpoly, RgM_Rg_sub, RgM_Rg_sub_shallow 14- generic driver for GP's charpoly(): select appropriate algorith (flag) depending on input type. BA 15- allow ellsearch(t_VEC) : search for curve with given name, in given isogeny class or with given conductor; alias for the existing ellsearch(t_STR) as per the ellconvertname correspondance 16- option flag to mateigen: also return the eigenvalues 17- [libpari] Z_lvalrem_stop, u_lvalrem_stop 18- [libpari] ZX_rescale_lt BA 19- Port of the program ISOM by Bernt Souvignier for computation of automorphisms and isomorphisms of lattices. New GP functions qfauto, qfisom, qfisominit, qfautoexport 20- [libpari] RgX_mullow, RgX_sqrlow 21- [libpari] embed_T2, embednorm_T2, embed_roots, embed_disc, embed_norm 22- arithmetic functions now accept factorization matrices, you can use any of f(N), f(factor(N)) or f([N, factor(N)]) 23- GP function readstr 24- allow lists of elements in chinese() Changed 1- gp --primelimit lim (gp -p lim) is deprecated. Use the generic form 'gp -D primelimit=lim' (setting primelimit is now mostly useless, anyway) 2- gp --stacksize lim is deprecated. Use gp -s lim or the generic form 'gp -D parisize=lim' 3- partitions() interface to match forpart() 4- improve qfbred(t_QFI) for "small" inputs 5- bnfnewprec: ensure we recompute bnf from scratch at most once (could happen many times in makematal()) 6- [make bench] properly align results if 'printf' is available 7- [libpari] the *_invimage function no longer accept a t_COL second argument: use the RgM_RgC_invimage variant. They now return NULL when no solution exist (used to return a t_COL / t_MAT of length 1) 8- [libpari] replace the forvec_start() function by a standard iterator: forvec_init() / forvec_next() 9- [libpari] Z_lvalrem would destroy its argument. No longer. 10- znprimroot(p^k) now always returns the smallest primitive root (was only true for k = 1) 11- gmul / gsqr for t_SER with t_INTMOD coefficients: reduce to Z[X] + Kronecker substititution (quasi-linear vs. Karatsuba) 12- Mulders/Hanrot-Zimmerman short products for power series HC 13- new mpveceint1 implementation: faster and more precise 14- version string for development versions: added number of reachable commits (as per git rev-list). Affects version() [#1346] Removed 1- drop support for "gp -b buffersize" (obsolete since 2.2.10, 04/2005) 2- drop backward compatibility 'gp -emacs', 'gp -test'. Use the '--emacs' and '--test' forms. Done for version 2.6.0 (released 15/05/2013): Fixed 1- Euclidean chains were confused by t_POLs with t_INTMOD/t_POLMOD coeffs [ because a 0 polynomial could have lg() == 3 ] 2- numerical instability in ellheightoo [#1204] 3- Flm_gauss(m, smallish p): fix and enable the OK_ulong switch [ faster ] 4- remi2n didn't allow negative arguments [native kernel] [#1215] 5- ellrootno(e, p) started by computing a global minimal model for e instead of a local one at p. 6- qfbred(t_QFR) wrong when frac( sqrt(D) ) > 0.5 7- add GC in sumalt() 8- problems with diagnostic messages when changing a 'default', e.g. \o3 9- divru() could call bfffo(0) => overflow in expo() AMe10- (t_FRAC<0) * t_INTMOD => wrong result 11- trace(t_POL or t_SER) could yield an unormalized object [0 leading term] LGr12- off-by-1 error in primepi() when argument is = primelimit 13- bestappr(0.*x+1) -> incorrect object 14- znlog(3, Mod(3,8), 2) -> error 15- crash when default(prettyprinter,...) points to a non-existent command 16- qfperfection(): wrong result in unlucky cases [#1223] 17- allocatemem() did not reset parse error [#1226] BA 18- (x->vector(1,j,x))(1) --> significant pointers lost [#1211] VL 19- [makefile] Incorrect -I and -L flags order [#1212] 20- nfbasis / nfdisc(f,, partial factorization) would sometimes spend a lot of time trying to factorize a discriminant [#1227] 21- numerical instability in qfgaussred / qfsign [#1232] 22- missing consistency checks in conjvec [#1231] 23- numerical instability in polredabs [#1228, #1229] 24- wrong result in bezoutres [#1233] 25- wrong sign in polresultant() [#1234] 26- change default(realprecision) so that it returns the internal precision [ as precision(1.) ], not the number of printed digits. [#1235] 27- subst(Y/X,X,x) -> 0 PB 28- polrootsff(x^2-x-ffgen((v^2+1) * Mod(1,3))) -> SEGV [#1241] 29- intnum(t=[0,0],[1],(sin(t)/t)^2) -> "precision too low in mpsc1" BA 30- functions ending by the x[y]=z construct could corrupt the stack. 31- nfbasis(pol, 0, factorization containing (-1)^1) -> wrong [#1244] 32- qfminim(): better type checks for matrix entries 33- qfminim(): incorrect GC in smallvectors() 34- padicappr(x^2+1+O(3), -1+O(5^10)) --> no error 35- tests test-kernel and test-ploth were broken 36- lots of missing sanity checks in hilbert(x,y,p) [ e.g. hilbert(O(3), Pi, 5) -> 0 ] BA 37- for(i=1,10^7,) + SIGINT -> SEGV [#1249] 38- ellwp: take flag into account also for t_SER output [ was: numerical case only ] 39- factor(p) was much slower than isprime(p) for p a "small" prime BA 40- mateigen precision error was not trappable. 41- accuracy problems in bnfisunit [#1253] 42- broken rnfeltup [#1255] 43- x===y was always wrong for x,y t_SER BA 44- gamma(t_SER) with positive valuation did not work. 45- ispower(x < 0) could return an even value ! [#1259] 46- ispower(1 / n) return a wrong result [#1259] BA 47- [breakloop] initial context could be lost. BA 48- Ser([1+O(x)],x) returned an invalid object. BA 49- ispseudoprime used too much stack for huge operands. 50- [rnfidealup doc] idealgentoHNF() was incorrect. DS 51- elldivpol returned wrong result for degree n >=8. 52- overflow in mpbern(n) for huge n [#1256] 53- idealfactor(nf, non integral ideal) would remove a rational content instead of factoring A/B with A,B coprime integer ideal. Which led to costly factorizations [#1158] LGr54- the global variables associated to the primetable _maxprime / diffptr could become inconsistent 55- psdraw() ignored plot colors BA 56- stack_base() was not C89 standard compliant. BA 57- my(f(x)=x+1);f --> SEGV [#1273] 58- ellheight([0, 0, 1, -1, 0], [0., 0.]) -> BUG 59- allow bnrL1 over Q [#1279] 60- factorpadic(,,,1) => SEGV when linear factors/Q [#1278] 61- mathnf(..., 4) didn't remove 0 columns from HNF [#1271] JD 62- possible SEGV in pari_init_opts [#1264] BA 63- ellorder(E,P*Mod(1,p)) did not work if E was defined over Z 64- allow writebin to save user functions (t_CLOSURE) [#1171] 65- sqrtn(1+O(5),5) -> error, ispower(1+O(5),5) -> error [#1261] 66- parimacro.tex: pdftex --output-format dvi would produce a PDF BA 67- pari_close failed to free all allocated memory [#1297] BA 68- pari_close did not restore GMP memory functions 69- avoid outputing ANSI escape sequences to reset terminal state when unnecessary [#1289] BA 70- ellpointtoz was numerically unstable 71- issquarefree(0) => error [#1304] 72- sizebyte(t_LIST) returned the size of the wrapper type, not the list itself [#1307] 73- ellgroup(E over Q, p) now returns the structure of the group of non-singular points, when the curve has bad reduction at p. 74- factor_proven not taken into account in factor(n), where n is a BPSW-pseudoprime 75- core(5*(huge composite)^2) was very slow [#1305] 76- sqrt(0.E-97-1.12-97*I) -> div by 0 [#1309] BA 77- FpX_gcd(0,x) -> div by 0 78- x; y; p; q; subst(Mod(q,p), q, x + y) --> Mod(1, p)*x [#1321] 79- off-by-1 error when placing prime table sentinel after e.g. default(primelimit, 2); 80- t_REAL with huge exponents print incorrectly [#1322] 81- a1;a2;a3;a4;a6;ellinit([a1,a2,a3,a4,a6],1) was very slow BA 82- FpX_factorff and FpX_rootsff were not using standard argument order PB 83- printf("%.6f", 5E-5) -> SEGV [#1328] BA 84- diffop(Mod(y,x^2-y),[y],[1]) -> wrong result BA 85- calling a GP function with a lot of omitted arguments could cause a crash GH 86- missing solutions in thue(), e.g. thue(thueinit(x^3+92*x+1),3^3) 87- t_RFRAC == t_RFRAC could return a wrong result [#1339] 88- obscure bug in polroots() (sage #13314) 89- polinterpolate([1,2] * Mod(1,7), [2,3], 0) -> incorrect type in gabs BA 90- printf() did not flush output 91- logint() used too much memory and could return a wrong result: logint(3^64, 3) --> 33 92- eint1(x < 0) normalization. Now eint1(x) = incgam(0, x) [#418] 93- polrootsff(2*x+1,2,y) -> SEGV [#1350] 94- resultant(x,x,y) -> 0 and related problems 95- thue((x^4+1)^2, 4) -> no solution BA 96- idealramgroups() and idealfrobenius() did not accept a bnf 97- using new operators with default(compatible,3) caused a crash 98- rare corruption in ECM [#1240] factorint(,1) => SEGV 99- add missing call to normalize() in lift(t_POL/t_SER) [#1359] BA 100- listput was not SIGINT safe BA 101- znorder(Mod(5,16),200) -> 5 instead of 4 102- e.tate lost accuracy 103- 2-adic ellinit 104- allow ellinit over C 105- ellpointtoz(E / Qp, ...) [ wrong result / error messages ] JD 106- galoisinit(x^3+x^2-2*x-1) -> uninitialized read [#1389] BA 107- polhermite(66) -> corrupted result [#1393] 108- nfhnf() would only accept matrices of maximal rank BA 109- galoisfixedfield() could return a wrong result for polynomials with large roots [#1406] 110- bnrdisc could return a wrong result if the modulus had more than 2 prime divisors [#1399] 111- a = Mod(1,2)*x; gcd(a,a) return x instead of Mod(1,2)*x 112- changing primelimit from within forprime loop yielded unpredictable results (potential SEGV) 113- y;z;(x^2+y)*w/z/x -> significant pointers lost [#1248] 114- log(t_FRAC close to 1) => junk (idem lngamma) [#1238] 115- thue(thueinit(x^3-1493,1),3) -> error LGr116- typo in modr_safe -> precision error [#1413] 117- nfhnfmod(non-integral module) => wrong result nf=nfinit(y); A = [[1,1/2;0,1],[1,1]]; nfhnfmod(nf, A, nfdetint(nf,A)) BA 118- [native kernel] FFT mulii relied on unspecified order of evaluation Changed 1- mathnf: swapped flag 3 and 5. 2- allow ellinit([a4,a6]) [#1213] 3- ellinit(... singular curve ...]): return [] instead of raising an error 4- GP set elements are no longer converted to t_STR (requiring "eval" to recover the underlying object). Arbitrary GENs can be stored in a set. 5- moved Odos/* to relevant src/systems subdirectory 6- removed Odos directory 7- no longer allow Vec()/Vecrev(), Col(), Vecsmall(), without argument. Use [], []~, Vecsmall([]), respectively. 8- allow specifying an optional dimension in Vec/Vecrev, Col, Vecsmall. 9- allow Vecsmall(t_POL or t_SER) LGr10- nicer printout of small matrices: justify columns 11- improve gmul(t_REAL, t_FRAC) when numerator of t_FRAC is 1 BA 12- [darwin] do not use dylib_ prefix to ld options [#1210] 13- allow idealhnf(nf, t_QFI / t_QFR) for quadratic fields 14- no longer allow 3 arguments in bestappr() [useless], no longer mix Pade approximants and continued fractions [too confusing: must a t_SER be converted to a t_RFRAC or be treated coefficientwise?] 15- if znlog() has no solution, return [] instead of error 16- znlog(x, g): no longer assume that g is a primitive root, nor that the underlying (Z/N)^* is cyclic 17- renamed gen_eltorder -> gen_order 18- logfile: strip properly color escape sequences [#1225] 19- change nfbasis(T, flag, fa) to nfbasis(T, listP). flag was used to invoke round2 instead of round4 (inefficient=> useless) OR to only partially factor poldisc(T), up to primelimit (very dangerous since primelimit is a global variable). Now listP describes a list of primes, and we return a basis of an order which is p-maximal at all those primes: either a vector of primes, a factorisation (as fa before) or an integer B to indicated {p <= B} (a safe and flexible version of nfbasis(T, 1)). nfdisc() was changed similarly. 20- first call isanypower() in BPSP_psp_nosmalldiv() when input is > 2^512 [ < 1% of required time, 1 order of magnitude faster when it succeeds ] [ #1074 ] 21- sort polroots() output so that it no longer depends on current precision 22- delete README-subversion, replace with README-git 23- move README.os2 to src/system/os2/README 24- change compiler version printout in gp header 25- much faster final divisibility test in nfgcd() [#1214] 26- error type sqrter5 "not a quadratic residue in sqrt" now generalized to denote "not an n-th power residue in sqrtn" BA 27- global_err_data is now a GEN. BA 28- more usable form of alarm(s, code): evaluate code, aborting after s seconds. Return the result or a t_ERROR object. 29- [non-Unix systems] the name of the preferences file is now "gprc.txt" (it remains ".gprc" on Unix systems) 30- also look for the preferences file in PARI's "datadir" 31- removed rootsold() code : polroots(x, 1) is no longer accepted 32- rewrite ellan using C-longs + new function anellsmall() 33- renamed all libpari error codes [ pari_err() arguments ] 34- allow t_VECSMALL in vecextract 35- look for a few more short vectors in polred(), only return subfields and the best primitive polynomial [wrt discriminant] 36- [library] remove precdl argument in ellwp0: use a t_SER argument like in all other transcendental functions. 37- ellsigma / ellzeta: allow t_SER arguments, like ellwp. 38- polcoeff(x+2*y,1,y) -> 2 [ was 2*x^0 ] 39- quadhilbert / quadray: replace final polredabs call by polredbest [#1025] 40- listsort() now uses the cmp() comparison function, and becomes fully compatible with setsearch() [#1167] 41- vecsort(,,2) [lexicographic order] is now always on. The flag is now deprecated and ignored. 42- allow t_SER with integral coefficients to use asymptotically fast (ZX_mul / ZX_sqr) polynomial multiplication LGr43- let initprimes0 use an existing prime table 44- rename stackmalloc -> stack_malloc. Add stack_calloc 45- matimagecompl() now returns a permutation (t_VECMALL) no longer a t_VEC 46- remove config/gitversion from 'make snapshot' tarball JM 47- Better implementation of ellweilpairing/elltatepairing BA 48- agm now returns the optimal AGM 49- unify make_emacs_tags / make_vi_tags => make_tags + fix problems for (exuberant-ctags)-based etags. Both tag files (emacs / vi) contain the same tags now. 50- ellglobalred(E) now also returns the conductor factorization [4th compo] 51- library functions *_incremental_CRT no longer need the product of the moduli, instead they compute it and update the running modulus. 52- factor_proven now affects all the factoring machinery, as documented, i.e also multiplicative function (moebius, sumdiv,...) 53- allow t_VECSMALL in lex() 54- nfrootsof1(K) check whether K.pol is a translate of a cyclotomic pol. [initial patch LGr, #1175] 55- format of cached Bernoulli table: now a t_VEC of t_FRAC / t_REALs. Removed bern() macro. The new data must be accessed using bernfrac / bernreal. 56- [libpari] simplify init_primepointer(n, p, &pd) interface => init_primepointer(n, &pd). Remove argument 'p', ignore the previous value of pd [ remove assumption that it pointed into a prime table ] and always set pd to a pointer into the private prime table. 57- forprime loop: no longer allow to modify the loop index ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. 58- faster forparii() [ for() with t_INT lower bound ] 59- forprime(p = a, b, ...) now iterates over arbitrary ranges of primes, independently of 'primelimit'. Parameter 'b' can be omitted (no upper limit). More generally primelimit is no longer a true limit to iterate over primes: all libpari functions use the forprime_t interface 60- rename ggval -> gvaluation BA 70- GP function ellpow is renamed to ellmul BA 71- rename powell->ellmul, addell->elladd, subell->ellsub 72- is_pth_power interface [ pass a forprime_t iterator ] 73- polrootsmod(, 4) is no longer accepted 74- revert to Ramanujan's formula to compute Pi [ + binary splitting ] 75- polinterpolate(,, 'x) use divide & conquer algorithm BA 76- binary(0) now return [] 77- polisirreducible() now avoids factoring in most cases HC 78- reimplement incgam() 79- allow eint1(t_COMPLEX) 80- when 'echo = 1', no longer echo commands if they were entered interactively [commands ended up printed twice] 81- unless 'echo = 1', no longer log commands entered non-interactively when 'log = 1'. '\r file' used to log the entire content of 'file'. 82- allow thue(t_POL, rhs) for thue(thueinit(t_POL, rhs)) 83- elltors now uses division polynomials by default 84- modified "Hit Return to Continue" message so that it becomes a comment when copy-pasted 85- rnf_fix_pol() takes an extra argument, the calling function's name 86- fast gerepilecopy() for leaves 87- rename leftright_pow_fold -> gen_pow_fold, leftright_pow_fold_i -> gen_pow_fold_i 88- upowuu now returns 0 on overflow 89- primes(n) no longer needs precomputed primes 90- prime(n) no longer needs precomputed primes 91- primepi(n) no longer needs precomputed primes 92- removed 3s delay when recompiling PARI after modifying a header [ Was there to avoid problems on slightly out-of-synch NFS fileserver host. Had become an annoyance on fast multicore servers, esp. when bisecting to find a broken commit. ] 93- improve Configure --tune + let tune -t/-tt/-ttt print more and more verbose messages [ old 'tune -t' corresponds to current 'tune -tt' ] 94- arithmetic functions no longer accept vector / matrix arguments [ to later allow passing factorization matrices ]: use apply() BA 95- rename RgX_check_ZXY -> RgX_check_ZXX, ZXY_max_lg -> to ZXX_max_lg 96- elleta() and elleisnum(e, 2) to use a theta series formula in O~(prec^(3/2)) instead of O~(prec^2). BA 97- zv_cmp0 renamed to zv_equal0 98- allow ellinit / Qp for arbitrary reduction type 99- ellpointtoz(E / Qp, ...), now return phi(P) [ used to return the same result for phi(P) and phi(-P) [ split multiplicative reduction ], resp. phi(P) + 1/phi(P) [ non-split reduction ] 100- ellinit(E / Qp).tate : the u component is now always a square root of u2, also in the non-split case (in which case it lives in a quadratic extension of Qp) 101- renamed library function divsum() => sumdivexpr() 102- listpop(empty list) => no-op [ was "domain error" ] 103- ellap, ellak, ellan: allow non-minimal model 104- when timer = 1, no longer print timing if the time is negligible; in particular, no timing should be printed when defining a user function or and alias. 105- The proper way to initialize an nf structure when the polynomial discriminant is hard to factor is nfinit([T, listP]), where listP specifies a list of primes (see ??nfinit). nfdisc, nfbasis, all the polred functions allow analogous arguments (see Changed-19). This is cleaner and more flexible than old flags relying on the value primelimit (e.g. nfinit([T, nfbasis(T, 1)]), now deprecated). Also, the nfinit function now sees the local specifications and can take steps to avoid problems (instead of taking for granted a basis, without knowing whether it is correct or not). The result can also be certified (nfcertify) 106- polredabs() with (deprecated) nf_PARTIALFACT flag (or new [T,listP] argument) now returns 0 if the resulting order cannot be proven to be maximal. 107- rename bezout() -> gcdext(), polresultant() -> polresultantext() 108- the prime table is now computed once and for all on startup and can no longer be increased by modifying primelimit: the dynamic forprime machinery allows fast primes up to primelimit^2 which is more than enough even with a small table. The default value of 500.000 is already larger than necessary 109- removed the mechanism allowing prime gaps larger than 255 in the prime table: as a result it now limited to 436273290, allowing fast primes up to 1.9 10^17 BA110- permtonum/numtoperm now use the standard lexicographic numbering 111- issquare(t_INTMOD), ispower(t_INTMOD): factor modulus incrementally, in case we hit a local non-residue -> early abort [#1376] 112- gphelp + OS/X : make "open" the default PDF viewer (was "acroread") 113- renamed exp_Ir -> expIr Added 1- mathnf for matrices over K[X] [#41] BA 2- GP function ellheegner BA 3- asm inline macro addllx8 for faster addition BA 4- Library function FpXQ_autpowers 5- GP default 'linewrap' 6- functions Fp_issquare, Fq_issquare. 7- GP function cmp [ universal comparison ] 8- library functions Fp_addmul, addmulii, addmulii_inplace, addmuliu, addmuliu_inplace, lincombii, mulsubii, submulii, submuliu, submuliu_inplace LGr 9- Catalan's constant [ Catalan() ] BA 10- library functions F2x_issquare/F2x_sqrt BA 11- [INSTALL] Documentation of RUNTEST 12- library function bestapprPade 13- library function gen_factored_order, Fp_factored_order 14- macros retmkvec, retmkvec2, retmkvec3, retmkvec4, retmkcol, retmkcol2, retmkmat, retmkmat2, retmkintmod, retmkpolmod retmkintmod, retmkpolmod, retconst_col, retconst_vec 15- allow Ser(t_VECSMALL) BA 16- library function gsprintf/gvsprintf BA 17- new PARI type t_ERROR (error messages) BA 18- new error trapping system and GP functions iferr,iferrname BA 19- implement lngamma(t_PADIC) LGr20- new PARI functions F2m_gauss, F2m_inv, F2m_rank, F2m_image, matid_F2m, F2m_mul, F2m_F2c_mul BA 21- GP function getenv 22- new error class e_PRIME [ pari_err() ] BA 23- low-level function int_bit 24- library function stack_strcat 25- function polredbest [ adapting a preliminary patch by BA ] BA 26- library functions Fl_invsafe, F2x_halfgcd, Flx_Flxq_eval and Flx_FlxqV_eval. BA 27- support for sparse matrix and Wiedemann algorithm 28- GP function vecsearch() [ use with vecsort() ] BA 29- library function Z_issmooth BA 30- linear sieve algorithm for Fp_log/znlog BA 31- library functions Flx_to_FlxX, F2m_to_Flm, F2c_to_Flc, and Flxq_powu 32- GP function idealnumden() LGr33- library function uprecprime() 34- library function ZM_pivots() 35- library functions nm_Z_mul, ZM_togglesign, ZM_nm_mul [ to improve Zlm_gauss ] BA 36- [breakloop] GP functions dbg_up/dbg_down (like gdb up/down) 37- library functions rootsof1_Fp, rootsof1u_Fp, rootsof1_Fl BA 38- GP functions dbg_x (like \x) and dbg_err (current error data) 39- matconcat() BA 40- library functions Flm_Fl_add, Flm_invimage, FlxY_evalx BA 41- library functions Flx_ffisom, Flx_ffintersect, Flxq_ffisom_inv BA 42- library functions Flx_is_irred, Flx_is_smooth, F2x_is_irred BA 43- accessors functions for t_CLOSURE: closure_arity,closure_codestr,closure_get_* 44- library functions ZMs_ZC_mul, ZpMs_ZpCs_solve, gen_ZpM_Dixon BA 45- [breakloop] GP function breakpoint BA 46- GP function ffnbirred BA 47- cubic sieve algorithm for Flxq_log BA 48- library functions F2x_F2xqV_eval, F2x_F2xq_eval BA 49- forqfvec() BA 50- library functions FqM_image, FqM_rank, FpXQXQ_powers, FpXQXQ_matrix_pow BA 51- ellgroup(,,1): also return the generators BA 52- library functions FpVV_to_mod, FpE_changepoint, FpE_changepointinv BA 53- GP syntax [a..b] : [a,a+1,...,b] BA 54- GP syntax [a(x)|x<-b,c(x)] : apply(a,select(c,b)) BA 55- GP syntax M[a..b,^c] : vecextract(M,"a..b","^c") BA 56- library function FpE_log 57- select(f, v, 1) for indirect selection 58- hamming() function [initial implementation CG] 59- ispowerful() function 60- polgraeffe() function 61- functions poliscyclo(), poliscycloprod(), polcyclofactors() 62- function setbinop(f,X,Y) = { f(x,y), x in X, y in Y } 63- libpari function moebiusu() 64- sumdigits() function 65- libpari functions addiu, addui, subiu, subui, uissquare 66- randomprime() function. Allow random([a,b]) (return n, a <= n <= b) 67- ispolygonal() function 68- libpari functions uissquarefree, uposisfundamental, unegisfundamental 69- istotient() function 70- implement Haible/Papanikolaou binary splitting BA 71- PARI functions FlxqX_nbroots, FpXQX_nbroots, FpXQX_nbfact. BA 72- PARI function zv_search BA 73- GP syntax: multiif if(a==1,b,a==2,c,default). BA 74- GP syntax: multi assignement: [a,b,c]=V -> a=V[1];b=V[2];c=V[3] BA 75- PARI functions gen_gener, gen_ellgroup, gen_ellgens, gen_powers BA 76- FlxqE functions family (for elliptic curves over field of small characteristic>3) BA 77- PARI functions Flxq_sqrt, FpXQ_sqrt 78- bernpol() function 79- sumformal() function BA 80- PARI functions ZX_equal1, zvV_equal, ZXV_equal, FpXX_neg, FqX_neg BA 81- FpXQE functions family (for elliptic curves over field of large characteristic) BA 82- added GP function ellcard BA 83- PARI functions FpXQ_powu, Fq_powu, FpXX_mulu, Fq_mulu, Fq_div BA 84- PARI functions FqXQ_powers, FqXQ_matrix_pow, FqX_mulu, FqX_Fq_add BA 85- PARI functions FqXY_eval, FqXY_evalx, FpXY_Fq_evaly BA 86- SEA over non-prime finite field (for char p > 1000) LGr87- Add clock_gettime timer option 88- add new error type e_DOMAIN BA 89- Add black box finite fields for generic linear algebra BA 90- PARI functions FlxqM_image, FlxqM_ker, FqM_deplin BA 91- GP function ellneg BA 92- PARI functions Fp_ellcard, FpXQ_ellcard, Flxq_ellcard LGr93- vecmax / vecmin: add optional pointer argument (to hold index of a largest/smallest entry) 94- printsep() function CG 95- isprimepower() function 96- PARI functions F2v_to_F2x, F2x_valrem, F2x_deflate, F2x_shift 97- PARI function RgV_polint BA 98- GP function digits 99- GP default 'sopath' [ rewritten from initial patch by GTo ] LGr100- allow polylog(n, t_SER) around a != 0 BA 101- PARI functions ZX_shifti, ZX_remi2n, ZXV_remi2n 102- PARI functions cxexp1, mpsincos1 BA 103- GP function ellfromj 103- GP function forcomposite 104- new error class e_PRIORITY [ pari_err() ] BA 105- Add black box algebra for Brent and Kung algorithm 106- PARI function RgM_dimensions() BA 107- PARI functions RgX_splitting(), Flx_splitting() 108- made public the CATCH / TRY interface, renamed pari_CATCH / pari_TRY PARI functions err_get_num(), err_get_compo(), pari_err_last() 109- PARI function stack_sprintf() 110- PARI function RgX_is_QX() BA 111- PARI functions retmkmat2,retmkcol2,mkmat2,mkcol2,mkcols,mkcol2s et al. BA 112- PARI functions ZXV_dotproduct(), ZXX_Z_divexact() BA 113- PARI function gen_ZpX_Newton() 114- optional argument to contfracpnqn: return all convergents up to p_n/q_n, not only the last 2 BA 115- PARI functions Flxq_autpow, F2xq_autpow BA 116- PARI functions FpX_divrem_Barrett and unconditional FpX_rem_Barrett BA 117- PARI functions F2xq_sqrt_fast, Flxq_lroot, Flxq_lroot_fast BA 118- PARI functions FlxqV_dotproduct, FlxV_red BA 119- PARI functions ZpXQ_inv, ZpXQ_invlift, ZpXQ_log 120- PARI functions absi_shallow, mpabs_shallow, absfrac_shallow, Q_abs_shallow BA 121- PARI functions FlxX_Flx_add, FlxX_Fl_mul, FlxX_Flx_mul, FlxX_neg BA 122- PARI functions Fp_ellj, FpXQ_ellj, Flxq_ellj BA 123- PARI functions FpX_mulu, Flx_mulu, ZX_mulu BA 124- PARI functions FlxqXQV_autpow, FlxqXQV_autsum BA 125- PARI functions FpXQXQV_autpow, FpXQXQV_autsum BA 126- PARI functions FpXT_red, FlxT_red, ZXT_to_FlxT, ZXT_remi2n BA 127- Support for preconditionned reduction in FpXQ/Flxq 128- PARI functions padic_to_Q, padic_to_Q_shallow, QpV_to_QV, Q_pvalrem, ZX_Zp_root, Zp_appr, Fp_muls, retmkfrac BA 129- Add safegel et al. for GP2C -C option HC 130- Function sqrtnint 131- sumdivmult() to sum multiplicative functions 132- ?? online help: allow searching labels, e.g. ??"se:priority"@ 133- PARI function ZpM_echelon, zlm_echelon 134- GP functions matqr and mathouseholder, PARI functions QR_init, QgM_QR_init, gaussred_from_QR, R_from_QR, gtomp, RgC_gtomp, RgM_gtomp 135- PARI functions trivial_fact, prime_fact 136- PARI function rfrac_to_ser 137- PARI functions padic_lindep, Xadic_lindep 138- GP function seralgdep BA 139- arm, mips and mips64 level0 inline assembly kernel 140- new error class e_COMPONENT 141- PARI functions init_primepointer_geq, init_primepointer_gt, init_primepointer_leq, init_primepointer_lt BA 142- new default strictargs for mandatory arguments 143- GP function nfcertify 144- GP function ellchangepointinv 145- optional 'variable' argument to polresultantext() 146- export part of the ifac_* interface (ifact_start, ifact_next, ifac_read, ifac_skip, ifac_isprime) 147- PARI function expIxy 148- poor man's graphic engine 'plotps' (Configure --graphic=ps) when no graphic library is available; dumps the hi-res plot to a temporary PostScript file, then opens a PostScript viewer ('open -W' by default, $GP_POSTSCRIPT_VIEWER otherwise). Works around #1354 on OS/X. PMo149- GP function lambertw / library functions mplambertW, glambertW Removed 1- dropped DOS support 2- qfrep(): bit 2 of flag is now meaningless, we now always return a t_VECSMALL 3- file language/errmsg.c and global errmessage[] array: all error messages are now part of pari_err_display()) 4- error types arither1,mattype1,notpoler (merged with typeer), matinv1 (merged with gdiver) 5- legacy lindep and PSLQ implementations [algdep/lindep with negative flags]: now use LLL in all cases. BA 6- [libpari] removed unusable functions dbg_close/dbg_release. 7- [libpari] gisfundamental, gkronecker, gbigomega, geulerphi, gissquarefree, gmoebius, gnextprime, gnumbdiv, gomega, gprecprime, gsumdiv, gdumdivk, znprimroot0 8- ellsigma: flags 3 and 4 [ inefficient algorithm using the product formula ] 9- Member function 'w' (this is technical, and no longer needed:-) 10- obsolete function weipell(). Use ellwpseries() 11- [libpari] obsolete function Polred. Use polredbest 12- old logo misc/pari.xpm, see http://pari.math.u-bordeaux1.fr/logo.html pari-2.7.5/AUTHORS0000644000175000017500000001146012533333715012165 0ustar billbillThe PARI/GP project started around 1985 in the Laboratoire A2X (Universite Bordeaux 1, France) and a first version was written by Christian Batut, Dominique Bernardi, Henri Cohen and Michel Olivier and maintained by Henri Cohen till 1995. Karim Belabas took over the maintainance between 1995 and 2001, the project has been jointly maintained by Bill Allombert and Karim Belabas since 2002. A great number of people have contributed code through the successive stages which eventually resulted in the present version of PARI/GP. Even more people, too numerous to list, contributed by testing, reporting bugs or suggesting improvements, Igor Schein foremost among them. We would like to thank them all here. Current lead developers: Bill ALLOMBERT (Bordeaux) Karim BELABAS (Bordeaux) 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 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 Henri COHEN: original designer and project leader, native multiprecision kernel, arithmetic functions, LLL, transcendental functions, number fields, elliptic curves 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 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 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 Thomas PAPANIKOlAOU: MPQS integration, Pari-Lidia project Xavier ROBLOT: MPQS integration, Stark, original nffactor Denis SIMON: Norm equations, S-units, Hilbert symbols Emmanuel TOLLIS: primedec, zetak Ilya ZAKHAREVITCH: prime sieves, gphelp, tex2mail, major cleanup of the graphics and GP parser code, gnuplot support, readline support, OS/2 support, DOS/EMX support Other contributors: the 2 or 3 letter code refer to the CHANGES file. Please, kindly remind us if you have been forgotten! = Karim Belabas (maintainer) AF = Aurimas Fiseras AM = Alex V. Myltsev AMe= Anton Mellit AW = Aleksander Wittlin AS = Andy Stubbs BA = Bill Allombert BD = Bill Daly BG = Brian Gladman BH = Bruno Haible BK = Bruce Kaskel CB = Cliff Bergman CG = Charles Greathouse CW = Carl Witty DB = Dominique Bernardi DCa= David Carlisle DC = Dan Christensen DE = Denis Excoffier DF = David Ford DS = Denis Simon ED = Eric Driver EP = Esa Peuha GH = Guillaume Hanrot GN = Gerhard Niklasch GT = Glenn Thobe GTo= Gonzalo Tornaria HC = Henri Cohen HR = Harvey Rose IK = Iwao Kimura IM = Ivan Middleton IS = Igor Schein ISo= Ignat Soroko IZ = Ilya Zakharevich JD = Jeroen Demeyer JJ = John Jones JM = Jerome Milan JS = Juhana Sadeharju KO = Kiyoshi Ohgishi KPN= Klaus-Peter Nischke LG = Louis Granboulan LGr= Loic Grenie LM = Lorenz Minder MA = Michael Abshoff MD = Mark Dickinson MH = Marije Huizing MS = Michael Stoll MSo= Michael Somos MW = Mark Watkins NS = Nils Skoruppa OR = Olivier Ramare OV = Oliver Voigt PB = Peter Bruin PC = Phil Carmody PM = Peter Montgomery PMo= Pascal Molin PW = Paul van Wamelen RB = Remi Butel RM = Richard J. Mathar RS = Ralf Stephan RR = Randall Rathbun SC = Sylvain Chevillard SG = Scott Garee TH = Teluhiko Hilano TP = Thomas Papanikolaou VB = Vasili Burdo VBr= Volker Braun VL = Vincent Lefevre XR = Xavier Roblot YU = Yoshiaki Uchikawa pari-2.7.5/NEW0000644000175000017500000007337512366172547011516 0ustar billbillThis file highlights some of the novelties in PARI/GP 2.x compared to 1.39.15 (last release in the 1.x series). The detailed Changelog is in CHANGES. Incompatible changes are described in COMPAT. See TODO for possible future improvements. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.7 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [Configure] - Configure --mt=pthread or --mt=mpi: GP now supports POSIX threads and MPI. See doc/parallel.dvi for an introduction, and have a look at the new parxxx GP functions. - Configure -gcov: support for gcov/lcov. As a result, the regression suite (make test-all) has been much expanded and lots of obscure bugs fixed. See http://pari.math.u-bordeaux1.fr/lcov-report/ for current coverage test reports. - Configure now generates a file 'config.log' to help diagnose problems (contains all messages from compilers) [The GP language] - Ranges and slices: [a..b], x[a..b], x[^a] ? v = [2..8] %1 = [2, 3, 4, 5, 6, 7, 8] ? v[2..4] %2 = [3, 4, 5] ? v[^2] \\ remove 2nd element %3 = [2, 4, 5, 6, 7, 8] ? M = matid(3); M[1..2, ^2] \\ first two rows, remove 2nd col %4 = [1 0] [0 0] - Set notations: ? [ p | p <- primes(10), isprime(p+2) ] %1 = [3, 5, 11, 17, 29] - Multiple assignments: [a,b,c] = V, for a = V[1], b = V[2], c = V[3] ? [D,U,V] = matsnf(A, 1) \\ returns SNF and transformation matrices - Error trapping: iferr() + a new data type 't_ERROR' to represent error contexts. See ??iferr \\ Compute [B]P on a "curve over Z/NZ". If an exception occurs, \\ we found a zero divisor in Z/NZ, thereby factoring N. ECM(N, B = 1000!, nb = 100)= { for(a = 1, nb, iferr(ellmul(ellinit([a,1], N), [0,1], B), E, return(gcd(lift(component(E,2)),N)), errname(E) == "e_INV")); } ? ECM(2^101-1) %1 = 7432339208719 - Timeouts: alarm(delay, expr) spends 'delay' seconds trying to evaluate 'expr', then aborts returning a t_ERROR object. - Multi-if: to simplify successive 'else' clauses ? if (a == 1, print("1"), \ a < 0, print("negative"), \ isprime(a), print("prime"), \ print("generic")) - new function cmp() to "compare" arbitrary objects (transitive order relation, returns 0 iff x === y). Useful for sets. - new function getenv() [The GP calculator] - parallel GP support: parapply, pareval, parfor, parforprime, parselect, parsum, parvector. E.g. ? parapply(factor, [2^256 + 1, 2^193 - 1]) will factor these two integers in parallel. - forprime(p = a, b, ...) now iterates over arbitrary ranges of primes, independently of 'primelimit'. Parameter 'b' can be omitted (no upper limit). More generally, primelimit is now deprecated: libpari functions can quickly produce their own primes without relying on (enough) precomputed primes. - new iterators: forcomposite(), forpart() forqfvec(), to loop over composite integers, (possibly restricted) partitions and integer points in ellipsoids. - GP debugger, new functions expanding the 'break loop' mechanism: dbg_up(), dbg_down(), dbg_x(), breakpoint() - liftall(), liftint(), liftpol() give more flexibility than lift() in complicated situations - characteristic(x) returns the "characteristic" of the base ring over which x is defined. - ffgen(p^f), as an alias for ffgen(ffinit(p,f)) - vecsum(v), as an alias for sum(i=1,#v,v[i]) - variable() no longer raise exceptions, but returns 0 if the object has no main variable. - getabstime() returns the CPU time elapsed since gp startup, providing a reentrant version of gettime() - %#n returns the time it took to compute history result %n - new default 'linewrap' - arbitrary GP 'defaults' can now be set via the command-line: gp -D default=value gp --primelimit lim (gp -p lim) and gp --stacksize=lim are deprecated. Use the generic form (-D parisize=lim or -D primelimit=lim) [Multiprecision Kernel & Transcendental functions] - binary splitting: Catalan's constant, Pi, log(2) (to be expanded) - logint(x,b) for floor(log(x) / log(b)), avoiding rounding problems - sqrtnint(x,b) for floor(x^(1/b)) - expm1(x) for exp(x) - 1, but also accurate for x ~ 0 [Polynomial Arithmetic & Power series] - Mulders/Hanrot-Zimmerman short products for power series - Allow t_SER arguments for gamma, lngamma, and psi around arbitrary complex numbers (was either forbidden or limited to z = 0 or 1) - seralgdep: to find linear relations with polynomial coefficients ? s = 1+1/2*y+3/8*y^2-3/16*y^3+3/128*y^4+15/256*y^5-57/1024*y^6 + O(y^7); ? seralgdep(s,2,2) \\ relation of degree <= 2, degree(coeffs) <= 2 %2 = -x^2 + (y^2 + y + 1) - polgraeffe(f): returns g such that g(x^2) = f(x)f(-x) - poliscyclo(), poliscycloprod(), polcyclofactors(): cyclotomic factors of rational polynomials [Linear Algebra] - port of the program ISOM by Bernd Souvignier for computation of automorphisms and isomorphisms of lattices. New GP functions: qfauto, qfisom, qfisominit, qfautoexport - linear algebra routines now try to convert generic GP constructions involving t_INTMODs or t_FFELTs to appropriate (faster, more memory efficient) representations, then call routines in the libpari modular kernel (FpM, Flm, F2m, FqM, FlxqM, F2xqM). - add optional flag to mateigen to also return the eigenvalues - charpoly() now selects an appropriate algorithm by itself, depending on the input. Using a flag should no longer be necessary and is deprecated. - mathnf for matrices over K[X] - mathnfmodid(x,D), where D = [d1,...,dn] compute the HNF of concat(x,matdiagonal(D)); in a more efficient way - matqr() to compute the QR-decomposition of a real square matrix; mathouseholder() to apply a sequence of Householder transforms - internal support for sparse matrices and Wiedemann algorithm; currently only used by the discrete log algorithms. - matinverseimage(A, t_MAT B) would treat individual columns B[,i] independently and successively. Now use a single Gauss reduction. - normlp(): true L^p norm [ N.B. the old norml2() is still available, and returns the *square* of the L^2 norm ]. - clean generalizations of current norml2: qfnorm(), qfbil() [Elementary Number Theory] - arithmetic functions now accept factorization matrices as input, you can use any of f(N), f(factor(N)) or f([N, factor(N)]). - arithmetic functions no longer apply componentwise to vector / matrix arguments [ to allow passing factorization matrices ]: use apply() - new convenience functions: hamming(), ispowerful(), digits() / sumdigits(), ispolygonal(), istotient(), isprimepower() - randomprime(), random([a,b]) - Bernoulli polynomials: bernpol() and sumformal() ? sumformal(n^2) \\ F such that F(b) = \sum_{n <= b} n^2 %1 = 1/3*n^3 + 1/2*n^2 + 1/6*n - sumdivmult: to sum multiplicative expressions - sieve algorithms for znlog() and fflog(), computing discrete logs in F_q^* [Elliptic curves & Arithmetic geometry] - new dynamic implementation of the 'ell' data structure: ellinit is now used to record the coefficients of the curve and the domain over which it is defined. Further data is added to the structure on demand, if and when it is needed, e.g. cardinality and group structure. See ??ellinit. - elliptic curves functions no longer assume that a curve over Q is given by a minimal model. A non-miminal model used to silently produce wrong answers; no longer! - allow ellinit(E / Qp) for arbitrary p (also p = 2) and reduction type (no longer restricted to Tate curves) - allow ellinit(E / Fq) for non-prime finite fields, incl. point counting (SEA, Harley) - allow ellinit(E / C) - new function ellheegner() to find a non-torsion rational point on E / Q of rank 1. - new implementation of ellweilpairing / elltatepairing - ellsearch now accepts both syntaxes allowed by ellconvertname(), e.g. "11a3" / "11a" and [11,0,3] / [11,0] - extend ellinit inputs: ellinit([a4, a6]). On singular curve, return [] instead of raising an error. New function ellfromj(). - genus2red: an implementation of Liu's algorithm to determine the reduction of a genus 2 curve (at p > 2). Based on genus2reduction-0.3, http://www.math.u-bordeaux1.fr/~liu/G2R/ (Cohen & Liu, 1994) mostly rewritten from scratch, and fixing known problems in the original implementation (so-called bug27, bug28). The regression bench contains a check of at least one instance of each of Namikawa-Ueno's types + all cases on which the original genus2reduction was known to fail. CAVEAT: the interface will probably change & reduction at p = 2 not handled [Number Fields] - maximal orders (when the discriminant is hard to factor): allow to specify a list of primes at which the order nf.zk must be maximal. This [T, listP] format supersedes the old addprimes() hack as well as rigid optional flags for nfbasis, nfdisc, polredabs. (And no longer depends on the global 'primelimit'...) See ??nfinit ? T = polcompositum(x^5 - 101, polcyclo(7))[1]; ? nf = nfinit( [T, 10^3] ); ? nfcertify(nf) %3 = [] A priori, nf.zk defines an order which is known to be maximal at all p <= 10^3. The final certification step proves it is in fact globally maximal. - polredbest / rnfpolredbest: "best-effort" variants of polredabs / rnfpolredabs. Not canonical but often smaller, and run in poly-time ! - idealprincipalunits: structure of the multiplicative group (1 + pr) / (1 + pr^k), for a prime ideal pr [ special case of idealstar, faster ] [COMPATIBILITY WARNING] - lift(x,'v) / centerlift(x,'v) now only lift t_POLMODs in variable v, no longer (most) t_INTMOD / t_PADICs met along the way - rnf.pol (absolute defining polynomial / Q) has been renamed rnf.polabs. rnf.pol is now the relative polynomial, defining the relative extension over the base. - as a side effect of the new %#n construction, all GP results are now stored as history entries, including the "void" object returned by functions such as print() or for(). - renamed bezout() -> gcdext() - renamed ellpow() -> ellmul() %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [Libpari Build & Configuration] - 'Configure --tune' fine-tunes gp and the PARI library for a given host. On some machines this leads to noticeable performance improvements, esp. when using the GMP multiprecision kernel. - 'Configure --enable-tls' makes libpari thread-safe, for multi-threaded applications. See Appendix B in the "User's Guide to the PARI Library" [Multiprecision Kernel] - The GMP library is now used by default if Configure can find it. - Schoenhage-Strassen big integers multiplication to native kernel (very useful if GMP not available) [Polynomial Arithmetic] - faster multiplication of integer polynomials (Kronecker's trick) - subquadratic gcd over prime finite fields - special polynomials (polcyclo, polchebyshev, pollegendre...) are orders of magnitude faster ( polcyclo(10^6): 1min 30s (2.3) -> 4ms (2.5) ) and directly allow evaluation at a given point, e.g. polcyclo(n, 2) for Phi_n(2). - issquare(t_POL) now works reliably over prime finite fields ( we used to have issquare(Mod(1,2)*(x^2+1)) -> 0, or error messages in more complicated cases ). - charpoly no longer assumes that the characteristic is 0 or large enough (Berkowitz division-free algorithm). [Linear Algebra] - all LLL variants use an implementation of NGuyen & Stehle's L^2 algorithm : stabler, much faster - better resultants [Elliptic curves] - ellap() now uses the SEA algorithm (port of GP's ellsea package). - discrete logarithm [ elllog() ], group structure of E(Fp) [ ellgroup() ], - division polynomials [ elldivpol() ] - Tate and Weil pairings [ elltatepairing() / ellweilpairing() ] [Number Fields] - Class-field theoretic functions (e.g. bnfinit) no longer cheat on Bach's constant. They now use safe bounds by default, correct under GRH, and no slowdown has been observed. - bnfinit: huge improvements for fields of large degree or admitting non-trivial automorphisms (series of patches by Loic Grenie). - faster quadhilbert(D < 0) [ Hilbert class field via CM ] - Frobenius elements [ idealfrobenius() ] - ramification groups [ idealramgroups() ] [GP defaults] - new default "factor_proven" to guarantee that all integer factorizations outputs proven primes (the default is to be happy with strong pseudoprimes). - new defaults "graphcolormap" and "graphcolors" to allow arbitrary colormaps in hi-res plots. - new default 'histfile', to save your typing history in between sessions ! [GP data structures] - Lists now grow as needed, without imposing an awkward maximal length. v = List() is now sufficient to initialize an empty list, instead of v = listcreate(100) to initialize a list which wouldn't grow past 100 elements. - New GP type to handle non-prime finite fields in a reasonably efficient way. E.g: ? T = ffinit(7,5); \\ irreducible of degree 5 in F_7[x] ? t = ffgen(T); \\ The element x mod (T,p) in Fp[x] / (T) ~ F_{7^5} %2 = x \\ this has type t_FFELT ? t^10 \\ handled like Mod(x, T) but faster, and less cumbersome %3 = 5*x^4 + 5*x^2 + 5*x + 6 ? fforder(t) %4 = 5602 \\ multiplicative order ? g = ffprimroot(t); \\ primitive element ? fflog(g^1000,g) %6 = 1000 - In GP-2.3, it was not possible to use the same identifier for variables and functions; in GP-2.5 there is nothing wrong with defining f(x,y)=x^2+y^2 then setting f = 1 (thereby deleting the user function). In fact, the distinction between variables and functions has been abolished: anonymous functions (closures) may be defined and assigned to variables, e.g. the old f(x,y) = x^2+y^2 is now an alias for f = (x,y) -> x^2+y^2 [GP] - the debugger, or "break loop", is now enabled by default [ set breakloop = 0 in your gprc to disable it ], and no longer controlled by trap(). The debugger is more verbose: ? f(x) = g(x); ? g(y) = 1/y; ? f(0) *** at top-level: f(0) *** ^---- *** in function f: g(x) *** ^---- *** in function g: 1/y *** ^-- *** _/_: division by zero *** Break loop: type 'break' to go back to GP break> y 0 - all GP functions are now understood by GP2C - formatted printing : printf(), Strprintf() - alarm(n) to abort a lengthy computation after n seconds. - === "isidentical" operator, much stricter than == - The introducion of anonymous functions had a number of useful side effects; for instance, it made possible two new functions select() and apply(), as well as arbitrary comparisons in vecsort(): \\ primes in { i^2+1 : i <= 50 } ? select(x->isprime(x), vector(50,i,i^2+1)) %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] ? apply(x->x^2, [1,2,3,4]) %2 = [1, 4, 9, 16] \\ sorts a vector of polynomials by increasing discriminant ? vecsort( v, (x,y) -> sign(poldisc(x) - poldisc(y)) ) [Main Backward Compatibility issues] see the 'COMPAT' file in the distribution for the full list. - The main issue with existing GP scripts has to do with the scope of private variables (my vs. local), see section 2.6 in User's Manual. Indeed, variables implicitly scoped to loop or function bodies are now lexically scoped. From GP-2.5 on, in constructs like for(i = 1, 10, g()) f(i) = g() the index i is truly local to the loop/function body. It is no longer seen by the function g(), as used to be the case in GP-2.3. One can declare lexicaly-scoped variable anywhere using the construct my(x, y, z, t), possibly with initializations: my(x = 1, y = x). The old "local" keyword keeps the same semantic (dynamic scoping) and is mostly obsolete, outside of very specific situations beyond the scope of these release notes. - function calls *must* include parentheses. I.e. typing 'f()' calls the function f without arguments as expected, typing 'f' returns an anonymous function with the same definition as f; for instance, v[1] = f is valid, assigning the closure f to the first entry of vector v. - private "prime table" (addprimes) must now contain primes only: its entries are now used in all arithmetic functions - The pseudo-random number generator has been changed. The old linear congruential generator has been replaced by Brent's XORGEN, which uses a Linear Feedback Shift Register: pseudo-random sequences are much better behaved, e.g. matdet(matrix(5,5,i,j, random())) is no longer guaranteed to be divisible by 2^90 or so. There is no simple way to emulate GP-2.3 pseudo-random sequences in GP-2.5. - PariEmacs is no longer distributed with PARI/GP. The "PARI Emacs shell" is available as a separate package, to be downloaded once if at all. - | and & were accepted as aliases for || and && respectively. This construction still works in GP-2.5, but is scheduled to disappear. We strongly advise to update scripts to use the proper '||' and '&&' constructions. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * The GP2C compiler is available at http://pari.math.u-bordeaux.fr/download.html#gp2c GP2C compiles GP scripts to the C language, easing the task of writing PARI programs. It can transparently compile them to object code and load the resulting functions in gp. Low-level gp2c-compiled scripts typically run 3 or 4 times faster. Minor hand editing (specifying types) typically gains a further factor 2. * Cremona's database of elliptic curves is available through the 'elldata' package [ to be downloaded separately ] ? E = ellinit([1,1,0,10,10]); ? id = ellidentify(E)[1] \\ [1] = discard change of variables %2 = ["69950b1", [1, 1, 0, 10, 10], [[-1, 1], [-1/4, 23/8]]] \\ gives name and generators ? E = ellinit("11a1"); E.disc %3 = -161051 ? ellsearch(11); \\ all curves of conductor 11 ? forell(E, 10,20, print(E)) \\ iterate over curves of conductor 10-20 ["11a1", [0, -1, 1, -10, -20], []] ... Kernel: * Use 'Configure --with-gmp' to replace the native multiprecision kernel by the GNU MP library (featuring asymptotically fast arithmetic). * Cleanup of all architecture specific kernels (all macroized); added support for x86_64, ppc64, hppa and hppa64, ia64, sparc64, m68k. * Faster algorithms for "transcendental" functions (divide/conquer square root, AGM for log and Pi, Newton for exp and most trigonometric functions, AGM for inverse trigonometric functions, rewrite for gamma and zeta => faster Bernoulli, Mestre's AGM for ellheight) * Faster and cleaner kernel for modular arithmetic. Try e.g. factormod/factorff or polcompositum. * Major internal cleanups: separate lgef for t_POLs is gone, zero t_SER and t_POL now handled in a uniform way, heuristic soft copies in t_INTMOD, t_POLMOD, t_PADIC are gone [ led to fatal errors in complex scripts, no performance penalty ] * The "syntax" of GP routines and operators are no longer hard-coded in the sources, but maintained in a separate database (pari.desc). This way, external tools like GP2C need not be modified when the GP language is changed. Algebraic number Theory: * Faster integral LLL (still not super fast, but getting better), and polynomial factorization routines (over finite fields [ new modular kernel ], Q or general number fields [ van Hoeij's algorithm ]) * Faster maximal order (round4 rewrite) and polredabs (esp. with flag 16: don't factor the discriminant; yields a canonical equation for a field), faster ideal arithmetic (prime decomposition, approximation, multiplication). * Faster and more reliable class-field theoretic functions quadclassunit, bnfinit, bnfisprincipal, bnrinit (and related functions, e.g. bnrconductor or bnrdisc), rnfkummer, thue (fast enumeration of small solutions, don't assume the full unit group is known). * A set of fast routines for Galois theory (galoisininit, nfgaloisconj, galoisisabelian, galoisfixedfield, galoissubfields, galoissubcyclo for abelian fields, galoisidentify to identify large Galois fields up to degree 127). 'galdata' package [ to be downloaded separately ]: polgalois is safer and orders of magnitudes faster in tough cases, output is now human readable ? polgalois(x^11-2) time = 1,759 ms. \\ used to be ~ 1 hour %1 = [110, -1, 4, "F_110(11)=11:10"] Miscellaneous: * For convenience, the manual was split in two parts: the GP user's manual and the libpari user's manual, the latter being substantially expanded. Many formerly private functions have been renamed, specified, cleaned up and documented. * Initial implementation of the APR-CL primality prover, faster compositeness tests (BPSW) * A new set of fast numerical summation and integration routine, variations on the Ooura-Mori "double exponential" method. See ??intnum Library interface to all these functions and standard iterators (e.g. forvec) * Error messages now mention the GP function where the error occured. * Input/output and convenience functions: Str(a,1,c) --> "a1c", Strexpand("~") --> "/home/a2x/belabas", substvec (parallel substitutions), substpol(expr, x^2, y), writebin (write objets in binary format for fast retrieval), readvec (load a file's content into a vector) * Support for new graphic libraries (Qt, FLTK) [ ==> hi-res plots now also available under Mac OS X and Windows ] %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * PARI/GP is now released under the GNU General Public License. * PARI now has a CVS server which is intended for PARI lovers who want the very latest bleeding edge release (see the CVS.txt file). * Argument checks have been added to prevent unpredictable results when the input is incorrect. * Errors can be trapped to avoid abort and recover computations. * extended on-line help: ?? (no arguments) opens the users'manual in xdvi, ?? tutorial / refcard opens tutorial / refcard in xdvi, ??? keyword searches for topic in the manual. * Arithmetic: much faster integer factorization with several factoring engines including Pollard Rho, SQUFOF, improved ECM, and an MPQS/PMPQS implementation derived from LiDIA's, with kind permission from the LiDIA team * Polynomials: - much faster factorization over Z[X] (van Hoeij's algorithm) or Fq[X] (more efficient modular kernel), esp. when the polynomial is defined over Fp. - Ducos' subresultant algorithm for resultants * Number field: - improved ROUND 4 for computations of integral basis/discriminant - faster polredabs / rnfpolredabs polynomial reductions functions - Galois extensions of Q: Fixed fields, Galois conjugates using Allombert's algorithm. * Class group, ray-class group: - improved bnf/bnr functions (faster, numerically stabler), in particular bnfisprincipal - computations of explicit defining equations of abelian extensions of imaginery quadratic fields (using complex multiplication) of totally real abelian extensions (using Stark units). * Elliptic functions: Weierstrass and Weber functions. * Plotting: support of gnuplot, new functions (possiblity to plot directly in a file). %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The GP/PARI structure has been cleaned up. * The whole configuration process has been automated, and a Configure file is provided. Just typing `./Configure' should see you home in most cases. * PARI is now available as a dynamic library, thanks to Louis Granboulan. (you can link GP with it, if you wish to). This saves a tremendous amount of disk space, and is generally more convenient as you don't need to re-link your files when updating the library (or when debugging. or profiling, or...). * types now have a symbolic mnemonic name (e.g t_INT for an integer, t_VEC for a vector, and so on). * General speed-up (depends on your applications, about 40% for our generic testing file). * Experimental module loading structure (the actual function tree has not yet been cut into modules, but for the GP specific functions). ========================================================================== Many new or improved functions in the PARI library. * MANY class-field related functions. In particular: - is it now possible to try and remove the GRH assumption on class group computations. - ray class groups computations (including discrete log). - explicit defining equations in simple cases (Kummer extensions of prime degree, quadratic base field). * computation of Galois groups up to degree 11 * roots is now entirely reliable, thanks to Xavier Gourdon. * some core routines have been optimized: Karatsuba fast multiplication, a specific function gsqr() for squarings,... * input/output is much more flexible now: - a function GENtostring has been added, generalizing gitoascii to any PARI object (with a simpler syntax: GENtostring(g) returns a malloc'ed string containing g as gp would print it). - readexpr has a relative freadexpr (for filtered readexpr), which enables you to use input containing whitespaces. - you can use GENs in formatted output, a la printf. * improved garbage collecting. * private variables can be created without an explicit readexpr(), using fetch_var() and delete_var(). ========================================================================== GP has been completely re-written: * lowercase/uppercase are now significant. All predefined constants (Euler, I, Pi) have been renamed (as well, the o() notation for series and padics has been superseded by O()). for (i=1,10, print(i)) will not yield an error anymore. * human-readable error messages, including a caret to indicate where a GP syntax error occurred. * function names were renamed according to a more logical scheme. The file new.dico provides a translation (available under GP using "whatnow") * You can retrieve basic information from complicated objects using member functions. For instance x.disc will yield the discriminant of x, whether it was created by nfinit (aka initalg), bnfinit (aka buchinit), ellinit (aka initell). * A `gprc' file is available to set "permanent" defaults (such as global variables, aliases, custom user functions, etc...). For instance, you can put all your scripts in some special directories, and point them out to GP using "path". See misc/gprc.dft for examples. The function "default" enables to change most defaults under gp. For instance: default(compatible, 2) will give you back the former gp function names and helpmessages. [default(compatible, 3) undoes the lowercaps/uppercaps changes as well]. Try "default". * basic C idiosyncrasies such as for instance i++ (for i=i+1), i<<1 (for left shift) or i+=j (for i=i+j) are now allowed within GP scripts. /* */ multi-line comments are understood. * lists and (primitive) string support have been added. Characters can be quoted with the usual meaning. As a result, set functions can now be used with arbitrary elements. * if your terminal supports color (variants of color_xterm for instance), you can tell GP to highlight its output in different (user configurable) colors. This is done by fiddling with the default "colors". * The familiar functions "break", "next" and "return" are now available. These should supersede the buggy label/goto provided in older versions. * Enhanced on-line help. If you have perl on your system, try ?? function-name (e.g ?? bnfinit) This is provided by external scripts which can be used independently, outside of the GP session. * If readline is installed on your system, a context-dependent completion (not yet user-programmable) is now available (try hitting here and there). Try ?? readline. * many functions now have default arguments (shown between braces {} in the on-line description). gp first reads user-supplied arguments, and then fills in the arg list with these default values. Optional args can be entirely omitted, comma included (for a function with no mandatory arguments, even parentheses are optional !). For instance: Mat = Mat() bnfclassunit(x^2+1,0) = bnfclassunit(x^2+1) bnfclassunit(x^2+1,,[0.2,0.2]) = bnfclassunit(x^2+1,0,[0.2,0.2]) The "else" part of the "if" function can be entirely omitted. if (a,1) is now correct; of course, the former syntax if (a,1,) is still valid. * functions "extern" and "system" have been added to interface with external programs (UNIX only). You can do for instance extern("myprog"), or system("ls -l *.gp"). * even better, "install" enables you to load any function provided by a dynamically linked library, and have the GP interpreter use it. This makes it easy to have your own customized version of GP with your own set of functions on startup (you can document them using "addhelp"). * On 32-bit machines, maximum number of variables has been increased from 254 to 16382. Arrays can have up to 16777214 elements (instead of 65534). In addition vector/matrix operations in GP now perform orders of magnitudes faster than in version 1.39 pari-2.7.5/examples/0000755000175000017500000000000012613365633012734 5ustar billbillpari-2.7.5/examples/bench.gp0000644000175000017500000000022212314242551014326 0ustar billbill{ u=v=p=q=1; for (k=1, 2000, [u,v] = [v,u+v]; p *= v; q = lcm(q,v); if (k%50 == 0, print(k, " ", log(p)/log(q)) ) ) } pari-2.7.5/examples/lucas.gp0000644000175000017500000000012512314242551014360 0ustar billbilllucas(p) = { my(u = 4, q = 1<

1 using Shanks's SQUFOF squfof(n) = { my (p, D, d, a, b, b1, f, g, l, bb, gs); if (isprime(n) || issquare(n, &n), return(n)); p = factor(n,0)[1,1]; if (p != n, return(p)); if (n%4==1, D = n; d = sqrtint(D); b = (((d-1)\2) << 1) + 1 , D = n << 2; d = sqrtint(D); b = (d\2) << 1 ); f = Qfb(1, b, (b^2-D)>>2); l = sqrtint(d); q = []; lq = 0; i = 0; while (1, i++; f = qfbred(f, 3, D, d); a = component(f, 1); if (!(i%2) && issquare(a, &as), my(j = 1); while (j<=lq, if (as == q[j], break); j++ ); if (j > lq, break) ); if (abs(a) <= l, q = concat(q, abs(a)); print(q); lq++; ) ); print("i = ", i); print(f); bb = component(f, 2); gs = gcd([as, bb, D]); if (gs > 1, return (gs)); f = Qfb(as, -bb, as*component(f,3)); g = qfbred(f, 3, D, d); b = component(g, 2); until (b1 == b, b1 = b; g = qfbred(g, 3, D, d); b = component(g, 2); ); a = abs(component(g, 1)); if (a % 2, a, a>>1); } pari-2.7.5/examples/thread.c0000644000175000017500000000327611636712103014347 0ustar billbill#include /* Include PARI headers */ #include /* Include POSIX threads headers */ void * mydet(void *arg) { GEN F, M; /* Set up thread stack and get thread parameter */ M = pari_thread_start((struct pari_thread*) arg); F = det(M); /* Free memory used by the thread */ pari_thread_close(); return (void*)F; } void * myfactor(void *arg) /* same principle */ { GEN F, N; N = pari_thread_start((struct pari_thread*) arg); F = factor(N); pari_thread_close(); return (void*)F; } int main(void) { GEN M,N1,N2, F1,F2,D; pthread_t th1, th2, th3; /* POSIX-thread variables */ struct pari_thread pth1, pth2, pth3; /* pari thread variables */ /* Initialise the main PARI stack and global objects (gen_0, etc.) */ pari_init(4000000,500000); /* Compute in the main PARI stack */ N1 = addis(int2n(256), 1); /* 2^256 + 1 */ N2 = subis(int2n(193), 1); /* 2^193 - 1 */ M = mathilbert(80); /* Allocate pari thread structures */ pari_thread_alloc(&pth1,4000000,N1); pari_thread_alloc(&pth2,4000000,N2); pari_thread_alloc(&pth3,4000000,M); /* pthread_create() and pthread_join() are standard POSIX-thread * functions to start and get the result of threads. */ pthread_create(&th1,NULL, &myfactor, (void*)&pth1); pthread_create(&th2,NULL, &myfactor, (void*)&pth2); pthread_create(&th3,NULL, &mydet, (void*)&pth3); /* Start 3 threads */ pthread_join(th1,(void*)&F1); pthread_join(th2,(void*)&F2); pthread_join(th3,(void*)&D); /* Wait for termination, get the results */ pari_printf("F1=%Ps\nF2=%Ps\nlog(D)=%Ps\n", F1, F2, glog(D,3)); pari_thread_free(&pth1); pari_thread_free(&pth2); pari_thread_free(&pth3); /* clean up */ return 0; } pari-2.7.5/examples/cl.gp0000644000175000017500000000525512314242551013660 0ustar billbillrgcd(a,b)= { [a,b] = [abs(a), abs(b)]; while (b > 0.01, [a,b] = [b,a%b]); a; } global(nf, km, m, clh, R, areg, re, res, mreg); f(a,b, nf,v,ind)= { my(u, vreg); my(n = idealnorm(nf, a + b*variable(nf.pol))); my(mv = vectorv(#v)); forprime (p=2, #ind, my (l = valuation(n,p)); if (l, my(cp, j = ind[p]); n /= p^l; cp = v[j][2]; while((a+b*cp)%p, j++; cp = v[j][2] ); mv[j] = l ) ); if (n!=1, return); my (r1 = nf.sign[1]); /* found a relation */ vreg = vectorv(#re,j, u = a+b*re[j]; if (j<=r1, abs(u), norm(u)) ); mreg = concat(mreg, log(vreg)); m = concat(m, mv); areg = concat(areg, a+b*t); print1("(" res++ ": " a "," b ")"); } clareg(pol, plim=19, lima=50, extra=5)= { my(coreg,lireg,r1,ind,fa,co,a,b,mh,ms,mhs,mregh); nf=nfinit(pol); pol=nf.pol; re = nf.roots; r1=nf.sign[1]; if (nf.index > 1, /* power basis <==> index = 1 */ error("sorry, the case 'index>1' is not implemented") ); printf("discriminant = %s, signature = %s\n", nf.disc, nf.sign); lireg = sum(i=1,2, nf.sign[i]); /* r1 + r2 */ ind=vector(plim); v=[]; forprime(p=2,plim, my (w = factormod(pol,p)); my (e = w[,2]); my (find = 0); for(l=1,#e, fa = lift(w[l,1]); if (poldegree(fa) == 1, if (!find, find=1; ind[p]=#v+1); v = concat(v, [[p,-polcoeff(fa,0),e[l]]]) ) ) ); co = #v+extra; res=0; print("need ", co, " relations"); areg=[]~; mreg = m = [;]; a=1; b=1; f(0,1, nf,v,ind); while (reslima, b++; a=1) ); print(" "); mh=mathnf(m); ms=matsize(mh); if (ms[1]!=ms[2], print("not enough relations for class group: matrix size = ",ms); return ); mhs = matsnf(mh,4); clh = prod(i=1,#mhs, mhs[i]); printf("class number = %s, class group = %s\n", clh, mhs); areg=Mat(areg); km=matkerint(m); mregh=mreg*km; if (lireg==1, R = 1 , coreg = #mregh; if (coreg < lireg-1, print("not enough relations for regulator: matsize = ", matsize(mregh)); R = "(not given)"; , mreg1 = mregh[1 .. lireg-1, ]; R = 0; for(j=lireg-1,coreg, a = matdet(mreg1[, j-lireg+2 .. j]); R = rgcd(a,R) ) ) ); print("regulator = " R); } check(lim=200) = { my(r1,r2,pol,z,Res,fa); [r1,r2] = nf.sign; pol = nf.pol; z = 2^r1 * (2*Pi)^r2 / sqrt(abs(nf.disc)) / nfrootsof1(nf)[1]; Res = 1.; \\ Res (Zeta_K,s=1) ~ z * h * R forprime (q=2,lim, fa = factormod(pol,q,1)[,1]; Res *= (q-1)/q / prod(i=1, #fa, 1 - q^(-fa[i])) ); z * clh * R / Res; } fu() = vector(#km, k, factorback(concat(areg, km[,k]))); pari-2.7.5/examples/Inputrc0000644000175000017500000000055011636712103014273 0ustar billbill# initialization file used by the readline library # modify it then copy it to $HOME/.inputrc "\C-h": backward-delete-char "\e\C-h": backward-kill-word "\C-xd": dump-functions $if Pari-GP set convert-meta on set output-meta off set show-all-if-ambiguous # toggle between normal-mode (electric parentheses) and copy-paste mode "\C-q": "\M--2(" $endif pari-2.7.5/examples/EXPLAIN0000644000175000017500000001111012366172547013756 0ustar billbillThis directory contains: * Inputrc: an example of .inputrc file for the readline library. * A generic Makefile for PARI programs, adapted to your system by Configure. * the C program extgcd.c using the Pari library described in Chapter 4 of the users' manual. To build it, run: make TARGET=extgcd * the C program minigp.c using the Pari library to implement a basic GP interpretor (Need readline). To build it, run make TARGET=minigp EXTRALIBS=-lreadline * the C program pari-mt.c using the Pari library interface for parallel computation. To build it, run make TARGET=pari-mt * the C program thread.c using the Pari library in a multi-threaded context, POSIX threads version, as described in Appendix D of the users' manual. This requires that PARI is Configured with --enable-tls. To build it, run make TARGET=thread EXTRALIBS=-lpthread * the C program openmp.c using the Pari library in a multi-threaded context, OpenMP version, as described in Appendix D of the users' manual. This requires that PARI is Configured with --enable-tls. To build it, run make TARGET=openmp EXTRACFLAGS=-fopenmp * Several examples of complete GP programs. The rest of this file gives a brief description of these programs. They should be read into GP by the command \r file. -- bench.gp: This program computes the first 1000 terms of the Fibonacci sequence, the product p of successive terms, and the lowest common multiple q. It outputs the ratio log(p)/log(q) every 50 terms, which tends to Pi^2/6 as k tends to infinity. The name bench.gp comes from the fact that this program is one (among many) examples where GP/PARI performs orders of magnitude faster than systems such as Maple or Mathematica. (Try it!) -- cl.gp: Written entirely in the GP language without using bnfinit, the programs included in this file computes the class number, the structure of the class group and a system of fundamental units of a general number field. It sometimes fail to give an answer and works only if nfinit finds a power basis. Evidently it is less powerful, less reliable and much slower than bnfinit, but it is given as an example of a sophisticated use of GP. The first thing to do is to call clareg(pol, {limp=19},{lima=50},{extra=5}) where pol is the monic irreducible polynomial defining the number field, limp is the prime factor base limit (try values between 19 and 113), lima is another search limit (try 50 or 100) and extra is the number of desired extra relations (try 2 to 10). Default values are provided, so that you need only supply pol. The program prints the number of relations that it needs, and tries to find them. If you see that it slows down too much before succeeding, abort and try other values. If it succeeds, it will print the class number, class group and regulator. These are tentative values. Then use check({lim = 100}) to check if the value is consistent with the value of the L-series (the value returned should be close to 1). Finally, fu() (no parameters) returns a family of units which generates the unit group (you must extract a system of fundamental units yourself). -- classno.gp: a simple function to compute analytically the class number of imaginary quadratic fields (written by Fernando Rodriguez Villegas) -- contfrac.gp: period(D) computes period of continued fraction for sqrt(D) [slower than quadregulator, which does a bit more work, but is written in C!] (written by Igor Schein) -- lucas.gp: The function lucas(p) defined in this file performs the Lucas-Lehmer primality test on the Mersenne number 2^p-1. If the result is 1, the Mersenne number is prime, otherwise not. -- rho.gp: a simple implementation of Pollard's rho method. The function rho(n) outputs the complete factorization of n in the same format as factor. -- squfof.gp: This defines a function squfof of a positive integer variable n, which may allow you to factor the number n. SQUFOF is a nice factoring method invented in the 70's by Dan Shanks for factoring integers, and is reasonably fast for numbers having up to 15 or 16 digits. The squfof program given here is a crude implementation, which prints out some intermediate information as it goes along. The final result is some factor of the number to be factored. -- taylor.gp: the function plot_taylor(f,xmin,xmax, ordlim, first,step) plots the Taylor polynomials T_i (truncated series expansion of order i) of the function f in the interval [xmin,xmax]; i goes from first to ordlim in increments of steps. Sensible default values are provided for all arguments (adapted from an original idea by Ilya Zakharevich). A few examples are provided, together with a simple colormap generator pari-2.7.5/examples/taylor.gp0000644000175000017500000000341612366172547014607 0ustar billbill\\ adapted from an original idea by Ilya Zakharevich \\ generate an RGB color triple from a "magnitude" between 0 and 255 \\ (low = close to a cold blue, high = close to a hot red). \\ To generate simple colormaps. rgb(mag) = { my(x = mag/255., B, G, R); B = min(max(4*(0.75-x), 0), 1); R = min(max(4*(x-0.25), 0), 1); G = min(max(4*abs(x-0.5)-1, 0), 1); return (floor([R, G, B]*255)); } default(graphcolormap, concat(["white","black","blue"], vector(25,i,rgb(10*i)))); default(graphcolors, vector(25,i,i+2)); \\ plot Taylor polynomials of f, \\ of index first + i*step <= ordlim, for x in [xmin,xmax]. plot_taylor(f, xmin=-5, xmax=5, ordlim=16, first=1, step=1) = { my(T,s,t,w,h,dw,dh,cw,ch,gh, extrasize = 0.6); my(Taylor_array); default(seriesprecision,ordlim+1); T = f('q); ordlim = (ordlim-first)\step + first; Taylor_array = vector(ordlim+1); forstep(i=ordlim+1, 1, -1, T += O('q^(1 + first + (i-1)*step)); Taylor_array[i] = truncate(T) ); t = plothsizes(); w=floor(t[1]*0.9)-2; dw=floor(t[1]*0.05)+1; cw=t[5]; h=floor(t[2]*0.9)-2; dh=floor(t[2]*0.05)+1; ch=t[6]; plotinit(2, w+2*dw, h+2*dh); plotinit(3, w, floor(h/1.2)); \\ few points (but Recursive!), to determine bounding box s = plotrecth(3, x=xmin,xmax, f(x), "Recursive|no_X_axis|no_Y_axis|no_Frame", 16); gh=s[4]-s[3]; plotinit(3, w, h); plotscale(3, s[1], s[2], s[3]-gh*extrasize/2, s[4]+gh*extrasize/2); plotrecth(3, x=xmin,xmax, subst(Taylor_array, 'q, x), "no_Rescale"); plotclip(3); plotcopy(3, 2, dw, dh); plotmove(2, floor(dw+w/2-15*cw), floor(dh/2)); plotstring(2, "Multiple Taylor Approximations"); plotdraw([2, 0, 0]); } \p9 plot_taylor(sin) plot_taylor(exp,-3,3) plot_taylor(x->besselk(2,x), 1,5) plot_taylor(x->1/(1+x^2), -1.2,1.2) pari-2.7.5/examples/rho.gp0000644000175000017500000000144111636712103014044 0ustar billbillrho1(n)= { my(x = 2,y = 5); while(gcd(y-x,n) == 1, x = (x^2+1)%n; y = (y^2+1)%n; y = (y^2+1)%n ); gcd(n, y-x); } rho2(n)= { my(m = rho1(n)); if (isprime(m), print(m), rho2(m)); if (isprime(n/m), print(n/m), rho2(n/m)); } rho(n)= { my(m = factor(n,0)); print(m); m = m[,1]; n = m[#m]; if (!isprime(n), rho2(n)); } rhobrent(n)= { my(x,y,x1,k,l,p,c,g); x1 = x = y = 2; k = l = p = 1; c = 0; while (1, x=(x^2+1)%n; p=(p*(x1-x))%n; c++; if (c==20, if (gcd(p,n)>1, break); y = x; c = 0 ); k--; if (!k, if (gcd(p,n)>1, break); x1 = x; k = l; l <<= 1; for (j=1,k, x = (x^2+1)%n); y = x; c = 0 ) ); until (g != 1, y = (y^2+1)%n; g = gcd(x1-y,n) ); if (g==n, error("algorithm fails")); g; } pari-2.7.5/examples/minigp.c0000644000175000017500000000425212405547147014367 0ustar billbill#include #include #include #include #include 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); } 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) int main(int argc, char **argv) { pari_init(8000000,500000); pari_add_module(functions_gp); pari_add_defaults_module(default_gp); sd_colors("lightbg",d_INITRC); sd_prompt("? ",d_INITRC); pari_printf("Welcome to minigp!\n"); cb_pari_err_recover = gp_err_recover; (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); pari_timer T; long time; if (!in) break; if (!*in) continue; add_history(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); } 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; } return 0; } pari-2.7.5/examples/extgcd.c0000644000175000017500000000162112314242551014345 0ustar billbill#include /* GP;install("extgcd", "GG&&", "gcdex", "./libextgcd.so"); */ /* return d = gcd(a,b), sets u, v such that au + bv = gcd(a,b) */ GEN extgcd(GEN A, GEN B, GEN *U, GEN *V) { pari_sp av = avma; GEN ux = gen_1, vx = gen_0, a = A, b = B; if (typ(a) != t_INT) pari_err_TYPE("extgcd",a); if (typ(b) != t_INT) pari_err_TYPE("extgcd",b); if (signe(a) < 0) { a = negi(a); ux = negi(ux); } while (!gequal0(b)) { GEN r, q = dvmdii(a, b, &r), v = vx; vx = subii(ux, mulii(q, vx)); ux = v; a = b; b = r; } *U = ux; *V = diviiexact( subii(a, mulii(A,ux)), B ); gerepileall(av, 3, &a, U, V); return a; } int main() { GEN x, y, d, u, v; pari_init(1000000,2); printf("x = "); x = gp_read_stream(stdin); printf("y = "); y = gp_read_stream(stdin); d = extgcd(x, y, &u, &v); pari_printf("gcd = %Ps\nu = %Ps\nv = %Ps\n", d, u, v); pari_close(); return 0; } pari-2.7.5/examples/classno.gp0000644000175000017500000000165312314242551014722 0ustar billbill\\ --------------- GP code --------------------------------------- \\ \\ Time-stamp: \\ \\ Description: Compute class number of imaginary quadratic field \\ analytically \\ \\ File: classno.gp \\ \\ Original Author: Fernando Rodriguez-Villegas \\ villegas@math.utexas.edu \\ University of Texas at Austin \\ \\ Created: Fri Mar 26 1999 \\----------------------------------------------------------------- \\ Class number h(-d), -d fundamental. \\ Adjust constant cc for accuracy, default at least 9 decimal places. cl(d, cc = 5) = { my(q0,sd,c, s = 0, q = 1); if (!isfundamental(-d), error("Discriminant not fundamental")); sd = sqrt(d); q0 = exp(-2*Pi/sd); c = -4*Pi/sd; for (n=1, ceil(sd*cc), my(t); q *= q0; t = 1/(1-q); s += kronecker(-d,n) * q * t * (1 + c*t*n) ); if (d==3, s *= 3, d==4, s *= 2); -2*s; } pari-2.7.5/examples/openmp.c0000644000175000017500000000240511636712103014367 0ustar billbill#include /* Include PARI headers */ #include /* Include OpenMP headers */ #define MAXTHREADS 3 /* Max number of parallel threads */ int main(void) { GEN M,N1,N2, F1,F2,D; struct pari_thread pth[MAXTHREADS]; int numth = omp_get_max_threads(), i; /* Initialise the main PARI stack and global objects (gen_0, etc.) */ pari_init(4000000,500000); if (numth > MAXTHREADS) { numth = MAXTHREADS; omp_set_num_threads(numth); } /* Compute in the main PARI stack */ N1 = addis(int2n(256), 1); /* 2^256 + 1 */ N2 = subis(int2n(193), 1); /* 2^193 - 1 */ M = mathilbert(80); /*Allocate pari thread structures */ for (i = 1; i < numth; i++) pari_thread_alloc(&pth[i],4000000,NULL); #pragma omp parallel { int this_th = omp_get_thread_num(); if (this_th) (void)pari_thread_start(&pth[this_th]); #pragma omp sections { #pragma omp section { F1 = factor(N1); } #pragma omp section { F2 = factor(N2); } #pragma omp section { D = det(M); } } /* omp sections */ if (this_th) pari_thread_close(); } /* omp parallel */ pari_printf("F1=%Ps\nF2=%Ps\nlog(D)=%Ps\n", F1, F2, glog(D,3)); for (i = 1; i < numth; i++) pari_thread_free(&pth[i]); return 0; } pari-2.7.5/examples/contfrac.gp0000644000175000017500000000036011636712103015052 0ustar billbillperiod(D) = { my(u,v,j,r,s); if (type(D) != "t_INT" || D < 2, return(-1)); u = sqrtint(D); v = D-u^2; if (!v, return(0)); s = v; r = u; j = 0; until (u == r && v == s, u = (r+u)\v * v - u; v = (D-u^2)\v; j++; ); j; } pari-2.7.5/examples/pari-mt.c0000644000175000017500000000276112366172547014464 0ustar billbill#include /* Include PARI headers */ GEN my_worker(GEN d, long l) { return l==1 ? Z_factor(d) : det(d); } int main(void) { long i; GEN M,N1,N2, F1,F2,D; GEN input, output; struct pari_mt pt; GEN done, worker; long workid, pending; entree ep_worker={"_worker",0,(void*)my_worker,14,"GL",""}; /* Initialize the main PARI stack and global objects (gen_0, etc.) Postpone initialization of parallelism */ pari_init_opts(8000000,500000,INIT_JMPm | INIT_SIGm | INIT_DFTm | INIT_noIMTm); /* Add my_worker function to gp */ pari_add_function(&ep_worker); /* Initialize parallelism, now that my_worker is registered */ pari_mt_init(); /* Compute in the main PARI stack */ N1 = addis(int2n(256), 1); /* 2^256 + 1 */ N2 = subis(int2n(193), 1); /* 2^193 - 1 */ M = mathilbert(80); /* Create input and output vectors */ input = mkvec3(N1,N2,M); output = cgetg(4,t_VEC); /* Initialize parallel evaluation of my_worker */ worker = strtofunction("_worker"); mt_queue_start(&pt, worker); for (i=1; i<=3 || pending; i++) { /* submit job (input) */ mt_queue_submit(&pt, i, i<=3? mkvec2(gel(input,i),i<=2 ? gen_1: gen_2): NULL); /* get result (output) */ done = mt_queue_get(&pt, &workid, &pending); if (done) gel(output,workid) = done; } /* end parallelism */ mt_queue_end(&pt); F1 = gel(output,1); F2 = gel(output,2); D = gel(output,3); pari_printf("F1=%Ps\nF2=%Ps\nlog(D)=%Ps\n", F1, F2, glog(D,3)); pari_close(); return 0; } pari-2.7.5/src/0000755000175000017500000000000012613365633011705 5ustar billbillpari-2.7.5/src/headers/0000755000175000017500000000000012613365633013320 5ustar billbillpari-2.7.5/src/headers/parinf.h0000644000175000017500000001374412405547147014762 0ustar billbill/* 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. */ /* output of get_nf and get_bnf */ enum { typ_NULL = 0, typ_POL, typ_Q, typ_NF, typ_BNF, typ_BNR, typ_ELL, /* elliptic curve */ typ_QUA, /* quadclassunit */ typ_GAL, /* galoisinit */ typ_BID, typ_PRID, typ_MODPR, typ_RNF }; /* idealtyp */ enum { id_PRINCIPAL = 0, id_PRIME, id_MAT }; typedef struct { GEN x; /* defining polynomial (monic, integral) */ GEN x0; /* original defining polynomial (integral) */ GEN bas; /* Z-basis of O_K (t_VEC of t_POL) */ long r1; /* number of real places of K */ /* possibly NULL = irrelevant or not computed */ GEN dK; /* disc(K) */ GEN dKP; /* "primes" dividing disc(K) [if we have a composite in the list then the structure may not be correct] */ GEN index; /* [O_K : Z[X]/(x)] */ GEN unscale; /* x = C*x0(X / unscale), rational */ GEN dx; /* disc(x) */ GEN basden; /* [nums(bas), dens(bas)] */ } nfbasic_t; typedef struct { GEN T, dT; /* monic defining polynomial, disc(T) */ GEN T0; /* ORIGINAL polynomial T0 */ GEN unscale; /* T = C*T0(x / unscale), rational */ GEN dK; /* field discriminant */ GEN index; /* index of power basis in maximal order */ GEN dTP, dTE; /* (possibly partial) factorization of dT, primes / exponents */ GEN dKP, dKE; /* (possibly partial) factorization of dK, primes / exponents */ GEN basis; /* Z-basis for maximal order */ } nfmaxord_t; typedef struct { GEN x; GEN ro; /* roots of x */ long r1; GEN basden; long prec; /* possibly -1 = irrelevant or not computed */ long extraprec; /* possibly NULL = irrelevant or not computed */ GEN M; GEN G; } nffp_t; /* qfr3 / qfr5 */ struct qfr_data { GEN D, sqrtD, isqrtD; }; /* various flags for nf/bnf routines */ enum { nf_ORIG = 1, nf_GEN = 1, nf_ABSOLUTE = 2, nf_FORCE = 2, nf_ALL = 4, nf_GENMAT = 4, nf_INIT = 4, nf_RAW = 8, nf_RED = 8, nf_PARTIALFACT = 16, nf_ROUND2 = 64, /* obsolete */ nf_ADDZK = 256, nf_GEN_IF_PRINCIPAL = 512 }; enum { rnf_REL = 1, rnf_COND = 2 }; /* LLL */ enum { LLL_KER = 1, /* only kernel */ LLL_IM = 2, /* only image */ LLL_ALL = 4, /* kernel & image */ LLL_GRAM = 0x100, LLL_KEEP_FIRST = 0x200, LLL_INPLACE = 0x400 }; /* HNF */ enum { hnf_MODID = 1, hnf_PART = 2, hnf_CENTER = 4 }; /* for minim */ enum { min_ALL = 0, min_FIRST = 1, min_PERF = 2, min_VECSMALL = 3, min_VECSMALL2 = 4 }; /* for fincke_pohst() */ typedef struct FP_chk_fun { GEN (*f)(void *,GEN); /* f_init allowed to permute the columns of u and r */ GEN (*f_init)(struct FP_chk_fun*,GEN,GEN); GEN (*f_post)(struct FP_chk_fun*,GEN,GEN); void *data; long skipfirst; } FP_chk_fun; /* for ideallog / zlog */ typedef struct { GEN lists; /* lists[i] = */ GEN ind; /* ind[i] = start of vector */ GEN P, e; /* finit part of conductor = prod P^e */ GEN archp; /* archimedean part of conductor, in permutation form */ long n; /* total number of generators for all (O_K/P^e)^* and (O_K/f_oo) */ GEN U; /* base change matrix from generators to bid.gen */ } zlog_S; GEN fincke_pohst(GEN a,GEN BOUND,long stockmax,long PREC, FP_chk_fun *CHECK); void remake_GM(GEN nf, nffp_t *F, long prec); GEN nfbasic_to_nf(nfbasic_t *T, GEN ro, long prec); void init_zlog_bid(zlog_S *S, GEN bid); GEN log_gen_arch(zlog_S *S, long index); GEN log_gen_pr(zlog_S *S, long index, GEN nf, long e); GEN zlog(GEN nf, GEN a, GEN sgn, zlog_S *S); /* conversions basis / alg */ /* nf a genuine NF, x an nfelt (t_COL) or t_MAT whose columns represent nfelts. * Return the corresponding elements as t_POLs (implicitly mod nf.pol) */ #define coltoliftalg(nf,x) (gmul(gel((nf),7), (x))) GEN poltobasis(GEN nf,GEN x); GEN coltoalg(GEN nf,GEN x); /* Other number fields routines */ 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); GEN checkbid_i(GEN bid); GEN checkbnf_i(GEN bnf); GEN checknf_i(GEN nf); 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); GEN get_bas_den(GEN bas); void nf_set_multable(GEN nf, GEN bas, GEN basden); GEN get_nfindex(GEN bas); GEN get_proj_modT(GEN basis, GEN T, GEN p); GEN get_roots(GEN x,long r1,long prec); GEN get_theta_abstorel(GEN T, GEN pol, GEN k); GEN idealsqrtn(GEN nf, GEN x, GEN gn, int strict); GEN init_unif_mod_fZ(GEN L); GEN init_units(GEN BNF); GEN make_integral(GEN nf, GEN L0, GEN f, GEN listpr); GEN maxord_i(GEN p, GEN f, long mf, GEN w, long flag); GEN nf_deg1_prime(GEN nf); GEN nfpol_to_Flx(GEN nf, GEN pol, ulong *ptp); GEN nfroots_split(GEN nf, GEN pol); GEN pidealprimeinv(GEN nf, GEN x); GEN primedec_apply_kummer(GEN nf,GEN pol,long e,GEN p); GEN prodid(GEN nf, GEN I); GEN rnfallbase(GEN nf, GEN *ppol, GEN *pD, GEN *pd, GEN *pfi); GEN rnf_basM(GEN rnf); 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 unif_mod_fZ(GEN pr, GEN F); GEN unnf_minus_x(GEN x); GEN ideallog_sgn(GEN nf, GEN x, GEN sgn, GEN bid); GEN zlog_units(GEN nf, GEN U, GEN sgnU, GEN bid); GEN zlog_units_noarch(GEN nf, GEN U, GEN bid); /* Dedekind zeta */ GEN zeta_get_limx(long r1, long r2, long bit); long zeta_get_i0(long r1, long r2, long bit, GEN limx); long zeta_get_N0(GEN C, GEN limx); pari-2.7.5/src/headers/paristio.h0000644000175000017500000001315112405547147015325 0ustar billbill/* 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. */ /* This file contains memory and I/O management definitions */ typedef struct { long s, us; } pari_timer; typedef unsigned char *byteptr; typedef ulong pari_sp; /* iterator over primes */ typedef struct { int strategy; /* 1 to 4 */ GEN bb; /* iterate through primes <= bb */ ulong c, q; /* congruent to c (mod q) */ /* strategy 1: private prime table */ byteptr d; /* diffptr + n */ ulong p; /* current p = n-th prime */ ulong b; /* min(bb, ULONG_MAX) */ /* strategy 2: sieve, use p */ unsigned char *sieve; ulong cache[9]; /* look-ahead primes already computed */ ulong chunk; /* # of odd integers in sieve */ ulong a, end, sieveb; /* [a,end] interval currently being sieved, * end <= sieveb = min(bb, maxprime^2, ULONG_MAX) */ ulong pos, maxpos; /* current cell and max cell */ /* strategy 3: unextprime, use p */ /* strategy 4: nextprime */ GEN pp; } forprime_t; typedef struct { int first; GEN b, n, p; forprime_t T; } forcomposite_t; typedef struct forvec_t { long first; GEN *a, *m, *M; /* current n-uplet, minima, Maxima */ long n; /* length */ GEN (*next)(struct forvec_t *); } forvec_t; /* Iterate over partitions */ typedef struct { long k; long amax, amin, nmin, nmax, strip; GEN v; } forpart_t; /* binary I/O */ typedef struct GENbin { size_t len; /* gsizeword(x) */ GEN x; /* binary copy of x */ GEN base; /* base address of p->x */ int canon; /* 1: t_INT in canonical (native kernel) form, 0: t_INT according to current kernel */ } GENbin; struct pari_mainstack { pari_sp top, bot, avma; size_t memused; }; struct pari_thread { struct pari_mainstack st; GEN data; }; typedef struct pariFILE { FILE *file; int type; const char *name; struct pariFILE* prev; struct pariFILE* next; } pariFILE; /* pariFILE.type */ enum { mf_IN = 1, mf_PIPE = 2, mf_FALSE = 4, mf_OUT = 8, mf_PERM = 16 }; typedef struct entree { const char *name; ulong valence; void *value; long menu; const char *code; const char *help; void *pvalue; long arity; struct entree *next; } entree; struct pari_parsestate { long node; int once; long discarded; const char *lex_start, *unused_chars; GEN lasterror; }; struct pari_compilestate { long opcode, operand, data, localvars, frames, dbginfo; long offset; const char *dbgstart; }; struct pari_evalstate { pari_sp avma; long sp; long rp; long var; long lvars; long trace; long pending_threads; struct pari_compilestate comp; }; struct gp_context { long listloc; long prettyp; struct pari_evalstate eval; struct pari_parsestate parse; pariFILE *file; jmp_buf *iferr_env; GEN err_data; }; struct mt_state { GEN worker; GEN pending; long workid; }; struct pari_mt { struct mt_state mt; GEN (*get)(struct mt_state *mt, long *workid, long *pending); void (*submit)(struct mt_state *mt, long workid, GEN work); void (*end)(void); }; typedef struct PariOUT { void (*putch)(char); void (*puts)(const char*); void (*flush)(void); } PariOUT; /* hashtables */ typedef struct hashentry { void *key, *val; ulong hash; /* hash(key) */ struct hashentry *next; } hashentry; typedef struct hashtable { ulong len; /* table length */ hashentry **table; /* the table */ ulong nb, maxnb; /* number of entries stored and max nb before enlarging */ ulong pindex; /* prime index */ ulong (*hash) (void *k); /* hash function */ int (*eq) (void *k1, void *k2); /* equality test */ int use_stack; /* use stack_malloc instead of malloc ? */ } hashtable; typedef struct { void **data; long n; long alloc; size_t size; } pari_stack; /* Common global variables: */ extern PariOUT *pariOut, *pariErr; extern FILE *pari_outfile, *pari_logfile, *pari_infile, *pari_errfile; extern ulong logstyle; enum logstyles { logstyle_none, /* 0 */ logstyle_plain, /* 1 */ logstyle_color, /* 2 */ logstyle_TeX /* 3 */ }; enum { c_ERR, c_HIST, c_PROMPT, c_INPUT, c_OUTPUT, c_HELP, c_TIME, c_LAST, c_NONE = 0xffffUL }; enum { TEXSTYLE_PAREN=2, TEXSTYLE_BREAK=4 }; extern THREAD pari_sp avma, bot, top; #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=bot &&_t=bot &&_t>(n))) #ifndef SIG_IGN # define SIG_IGN (void(*)())1 #endif #ifndef SIGINT # define SIGINT 2 #endif pari-2.7.5/src/headers/pariold.h0000644000175000017500000002760612405547147015137 0ustar billbill/* 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. */ /* For compatibility with 1.x.x */ /*functions renamed*/ #define mpexp1 mpexpm1 #define ggamd ggammah #define gach gacosh #define gash gasinh #define gath gatanh #define gch gcosh #define gsh gsinh #define gth gtanh #define recip serreverse #define gcmpX gequalX #define ZM_hnfremdiv ZM_hnfdivrem #define rnfidealhermite rnfidealhnf #define rnfelementabstorel rnfeltabstorel #define rnfelementreltoabs rnfeltreltoabs #define rnfelementdown rnfeltdown #define rnfelementup rnfeltup #define exp_Ir expIr #define vecbezout gcdext0 #define vecbezoutres polresultantext #define init_primepointer init_primepointer_geq #define geulerphi eulerphi #define numbdiv numdiv #define gnumbdiv numdiv #define gsumdivk sumdivk #define gnextprime nextprime #define gprecprime precprime #define leftright_pow_fold gen_pow_fold #define leftright_pow_u_fold gen_powu_fold #define subell ellsub #define addell elladd #define powell ellmul #define ggval gvaluation #define stackmalloc stack_malloc #define fprintferr err_printf #define msgTIMER timer_printf #define TIMER timer_delay #define TIMERread timer_get #define TIMERstart timer_start #define rnfinitalg rnfinit #define ordell ellordinate #define gcmp0 gequal0 #define gcmp1 gequal1 #define gcmp_1 gequalm1 #define nfsmith nfsnf #define certifybuchall bnfcertify #define greffe(x,y,z) (RgX_to_ser(x,y)) #define newbloc newblock #define killbloc killblock #define taille2 gsizeword #define taille gsizebyte #define polymodrecip modreverse #define primedec idealprimedec #define initalg nfinit #define initalgred nfinitred #define initalgred2 nfinitred2 #define initell ellinit #define smallinitell smallellinit #define isunit bnfisunit #define zideallog ideallog #define ideallllred idealred0 #define ideal_two_elt idealtwoelt #define ideal_two_elt2 idealtwoelt2 #define ideal_two_elt0 idealtwoelt0 #define gregula quadregulator #define gfundunit quadunit #define minideal(x,y,z,t) idealmin(x,y,z) #define idealhermite idealhnf #define srgcd(x) RgX_gcd(x) #define nfdiscf0(x) nfdisc0(x) #define discf(x) nfdisc(x) #define discsr(x) poldisc0((x),-1) #define factorpadic4 factorpadic #define smith2 smithall #define gsmith2 gsmithall #define derivpol RgX_deriv #define gpmalloc pari_malloc #define gprealloc pari_realloc #define gpfree pari_free #define pariprintf pari_printf #define pariputc pari_putc #define pariputs pari_puts #define pariflush pari_flush #define ellap0(e,p,flag) ellap(e,p) #define apell2(e,p) ellap(e,p) #define apell ellap #define gscalsmat scalarmat_s #define sqred qfgaussred #define signat qfsign #define infile pari_infile #define errfile pari_errfile #define logfile pari_logfile #define voir dbgGEN #define pointch ellchangepoint #define coordch ellchangecurve #define Flx_rand random_Flx #define FpX_rand random_FpX #define galois polgalois #define sindexlexsort indexlexsort #define sindexsort indexsort #define sindexrank indexrank #define decomp Z_factor #define gmodulcp gmodulo #define forcecopy gcopy #define lseriesell elllseries #define uissquarerem uissquareall #define Z_issquarerem Z_issquareall #define gissquarerem gissquareall #define gcarrecomplet gissquareall #define gcarreparfait gissquare #define rnfhermitebasis rnfhnfbasis #define wf weberf #define wf1 weberf1 #define wf2 weberf2 #define coefs_to_col mkcoln #define coefs_to_int mkintn #define coefs_to_pol mkpoln #define coefs_to_vec mkvecn #define localreduction elllocalred #define idmat matid #define globalreduction ellglobalred #define taniyama(e) elltaniyama((e),precdl) #define chinois chinese #define binome binomial #define egalii equalii #define gegal gequal #define gegalgs gequalgs #define gegalsg gequalsg #define gzero gen_0 #define gun gen_1 #define gdeux gen_2 #define realzero real_0 #define realzero_bit real_0_bit #define realun real_1 #define realmun real_m1 #define gen2str GENtostr #define gpui gpow #define gpuigs gpowgs #define classno3 hclassno #define strtoGEN gp_read_str #define flisexpr gp_read_str #define flisseq gp_read_str #define lisseq readseq #define lisGEN gp_read_stream #define lisexpr readseq #define permute numtoperm #define permuteInv permtonum #define evallgef(x) 0 #define lgef lg #define setlgef setlg #define leadingcoeff(x) (pollead((x),-1)) #define poldivres poldivrem #define nfdivres nfdivrem #define gred gcopy #define pvaluation Z_pvalrem #define svaluation u_lvalrem #define isprincipalrayall bnrisprincipal #define rayclassno bnrclassno #define rayclassnolist bnrclassnolist #define idealhermite2 idealhnf0 #define gener_Fp pgener_Fp #define gener_Fl pgener_Fl #define cyclo polcyclo #define tchebi polchebyshev1 #define legendre pollegendre #define subcyclo polsubcyclo #define leftright_pow gen_pow #define leftright_pow_u gen_powu #define apprgen padicappr #define apprgen9 padicappr #define factmod9 factorff #define ggrandocp ggrando #define glogagm glog #define logagm mplog #define mpsqrtz gopgz(absr,(x),(y)) #define adduumod Fl_add #define subuumod Fl_sub #define muluumod Fl_mul #define divuumod Fl_div #define powuumod Fl_powu #define invumod Fl_inv #define invsmod Fl_inv_signed #define mpinvmod Fp_inv #define powmodulo Fp_pow #define mpsqrtmod Fp_sqrt #define mpsqrtnmod Fp_sqrtn #define mpsqrt sqrtr #define mpsqrtn sqrtnr #define resii remii #define resis remis #define ressi remsi #define resss remss #define resiiz remiiz #define resisz remisz #define ressiz remsiz #define resssz remssz #define gres grem #define lres lrem #define gdivise gdvd #define divise dvdii #define mpdivis dvdiiz #define mpdivisis dvdisz #define mpent mpfloor #define mpentz mpfloorz #define mpnegz(x,y) \ STMT_START {pari_sp _av=avma;mpaff(mpneg(x),y);avma=_av;} STMT_END #define mpabsz(x,y) \ STMT_START {pari_sp _av=avma;mpaff(mpabs(x),y);avma=_av;} STMT_END #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 #define zero (long)gen_0 #define un (long)gen_1 #define deux (long)gen_2 #define lhalf (long)ghalf /* removed GEN subtypes */ #define t_FRACN t_FRAC #define t_RFRACN t_RFRAC #define is_frac_t(t) ( (t) == t_FRAC ) #define is_rfrac_t(t) ( (t) == t_RFRAC ) /*casts*/ #define labsi (long)absi #define labsr (long)absr #define lach (long)gacosh #define lacos (long)gacos #define ladd (long)gadd #define laddgs (long)gaddgs #define laddii (long)addii #define laddir (long)addir #define laddis (long)addis #define laddrr (long)addrr #define laddsg (long)gaddsg #define laddsi (long)addsi #define laddrs (long)addrs #define laddsr (long)addsr #define ladj (long)adj #define larg (long)garg #define lash (long)gasinh #define lasin (long)gasin #define lassmat (long)matcompanion #define latan (long)gatan #define lath (long)gatanh #define lbezout (long)bezout #define lbinome (long)binomial #define lcaract (long)caract #define lcaradj (long)caradj #define lceil (long)gceil #define lch (long)gcosh #define lchangevar (long)changevar #define lclone (long)gclone #define lconcat (long)concat #define lconj (long)gconj #define lcontent (long)content #define lcopy (long)gcopy #define lcos (long)gcos #define lcvtoi (long)gcvtoi #define lderiv (long)deriv #define ldet2 (long)det2 #define ldet (long)det #define ldeuc (long)gdeuc #define ldiscsr (long)discsr #define ldiventgs (long)gdiventgs #define ldiventsg (long)gdiventsg #define ldivgs (long)gdivgs #define ldivii (long)divii #define ldivir (long)divir #define ldivis (long)divis #define ldivmod (long)gdivmod #define ldivri (long)divri #define ldivrr (long)divrr #define ldivrs (long)divrs #define ldivsg (long)gdivsg #define ldivsi (long)divsi #define ldivsr (long)divsr #define ldvmdii (long)dvmdii #define ldvmdis (long)dvmdis #define ldvmdsi (long)dvmdsi #define lexp (long)gexp #define lfibo (long)fibo #define lfloor (long)gfloor #define lfrac (long)gfrac #define lgamd (long)ggammah #define lgamma (long)ggamma #define lgauss (long)gauss #define lgcd (long)ggcd #define lgetg (long)cgetg #define lgeti (long)cgeti #define lgetp (long)cgetp #define lgetr (long)cgetr #define licopy (long)icopy #define limag (long)gimag #define linteg (long)integ #define linv (long)ginv #define linvmat (long)RgM_inv #define linvmod (long)ginvmod #define llegendre (long)legendre #define llift (long)lift #define llngamma (long)glngamma #define llog (long)glog #define lmaxgs (long)gmaxgs #define lmax (long)gmax #define lmaxsg (long)gmaxsg #define lmings (long)gmings #define lmin (long)gmin #define lminsg (long)gminsg #define lmodgs (long)gmodgs #define lmodii (long)modii #define lmod (long)gmod #define lmodsg (long)gmodsg #define lmodsi (long)modsi #define lmodulcp (long)gmodulo #define lmodulo (long)gmodulo #define lmpabs (long)mpabs #define lmpadd (long)mpadd #define lmpcos (long)mpcos #define lmpdiv (long)mpdiv #define lmpent (long)mpent #define lmpeuler (long)mpeuler #define lmpexp1 (long)mpexpm1 #define lmpexp (long)mpexp #define lmpfact (long)mpfact #define lmplog (long)mplog #define lmpmul (long)mpmul #define lmpneg (long)mpneg #define lmppgcd (long)mppgcd #define lmppi (long)mppi #define lmpshift (long)mpshift #define lmpsin (long)mpsin #define lmpsqrt (long)mpsqrt #define lmpsub (long)mpsub #define lmptrunc (long)mptrunc #define lmul2n (long)gmul2n #define lmulgs (long)gmulgs #define lmulii (long)mulii #define lmulir (long)mulir #define lmulis (long)mulis #define lmul (long)gmul #define lmulri (long)mulri #define lmulrr (long)mulrr #define lmulrs (long)mulrs #define lmulsg (long)gmulsg #define lmulsi (long)mulsi #define lmulsr (long)mulsr #define lmulss (long)mulss #define lnegi (long)negi #define lneg (long)gneg #define lnegr (long)negr #define lnorml2 (long)gnorml2 #define lnorm (long)gnorm #define lpile (long)gerepile #define lpilecopy (long)gerepilecopy #define lpileupto (long)gerepileupto #define lpileuptoint (long)gerepileuptoint #define lpileuptoleaf (long)gerepileuptoleaf #define lpoleval (long)poleval #define lpowgs (long)gpowgs #define lprec (long)gprec #define lpsi (long)gpsi #define lpuigs (long)gpuigs #define lpui (long)gpui #define lquadgen (long)quadgen #define lquadpoly (long)quadpoly #define lracine (long)sqrtint #define lrcopy (long)rcopy #define lreal (long)greal #define lrecip (long)recip #define lred (long)gred #define lremii (long)remii #define lrem (long)grem #define lrndtoi (long)grndtoi #define lroots (long)roots #define lscalmat (long)scalarmat #define lscalsmat (long)scalarmat_s #define lsh (long)gsinh #define lshifti (long)shifti #define lshift (long)gshift #define lshiftr (long)shiftr #define lsin (long)gsin #define lsqri (long)sqri #define lsqr (long)gsqr #define lsqrt (long)gsqrt #define lstoi (long)stoi #define lsub (long)gsub #define lsubgs (long)gsubgs #define lsubii (long)subii #define lsubir (long)subir #define lsubis (long)subis #define lsubres (long)resultant #define lsubri (long)subri #define lsubrr (long)subrr #define lsubrs (long)subrs #define lsubst (long)gsubst #define lsubsg (long)gsubsg #define lsubsi (long)subsi #define lsubsr (long)subsr #define ltan (long)gtan #define ltchebi (long)polchebyshev #define lth (long)gtanh #define ltrace (long)gtrace #define ltrans (long)gtrans #define ltrunc (long)gtrunc #define lutoi (long)utoi #define lround (long)ground #define ldiv (long)gdiv #endif pari-2.7.5/src/headers/paripriv.h0000644000175000017500000005416112413013143015314 0ustar billbill/* Copyright (C) 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. */ BEGINEXTERN /* hashtables */ hashtable *hashstr_import_static(hashentry *e, ulong size); void hashstr_dbg(hashtable *h); /* for qsort */ typedef int (*QSCOMP)(const void *, const void *); #define ucoeff(a,i,j) (((ulong**)(a))[j][i]) #define umael(a,i,j) (((ulong**)(a))[i][j]) #define uel(a,i) (((ulong*)(a))[i]) /* to manipulate 'blocs' */ #define BL_HEAD 4 #define bl_base(x) (void*)((x) - BL_HEAD) #define bl_refc(x) (((GEN)x)[-4]) #define bl_next(x) (((GEN*)x)[-3]) #define bl_prev(x) (((GEN*)x)[-2]) #define bl_num(x) (((GEN)x)[-1]) INLINE void clone_lock(GEN C) { if (isclone(C)) ++bl_refc(C); } INLINE void clone_unlock(GEN C) { if (isclone(C)) gunclone(C); } /* swap */ #define lswap(x,y) {long _z=x; x=y; y=_z;} #define pswap(x,y) {GEN *_z=x; x=y; y=_z;} #define swap(x,y) {GEN _z=x; x=y; y=_z;} #define dswap(x,y) { double _t=x; x=y; y=_t; } #define pdswap(x,y) { double* _t=x; x=y; y=_t; } #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 */ struct abpq { GEN *a, *b, *p, *q; }; struct abpq_res { GEN P, Q, B, T; }; void abpq_init(struct abpq *A, long n); void abpq_sum(struct abpq_res *r, long n1, long n2, struct abpq *A); /* generic */ GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, GEN *tau, pari_sp *av, GEN *res); GEN sort_factor_pol(GEN y, int (*cmp)(GEN,GEN)); /* loops */ GEN incloop(GEN a); GEN resetloop(GEN a, GEN b); GEN setloop(GEN a); /* parser */ GEN iferrpari(GEN a, GEN b, GEN c); void forpari(GEN a, GEN b, GEN node); void untilpari(GEN a, GEN b); void whilepari(GEN a, GEN b); GEN ifpari(GEN g, GEN a, GEN b); GEN andpari(GEN a, GEN b); GEN orpari(GEN a, GEN b); void ifpari_void(GEN g, GEN a, GEN b); GEN ifpari_multi(GEN g, GEN a); GEN geval_gp(GEN x, GEN t); GEN gadde(GEN *x, GEN y); GEN gadd1e(GEN *x); GEN gdive(GEN *x, GEN y); GEN gdivente(GEN *x, GEN y); GEN gdivrounde(GEN *x, GEN y); GEN gmode(GEN *x, GEN y); GEN gmule(GEN *x, GEN y); GEN gshiftle(GEN *x, long n); GEN gshiftre(GEN *x, long n); GEN gsube(GEN *x, GEN y); GEN gsub1e(GEN *x); GEN gshift_right(GEN x, long n); GEN derivnum0(GEN a, GEN code, long prec); GEN derivfun0(GEN code, GEN args, long prec); GEN direuler0(GEN a, GEN b, GEN code, GEN c); void forcomposite(GEN a, GEN b, GEN code); void fordiv(GEN a, GEN code); void forell0(long a, long b, GEN code); void forprime(GEN a, GEN b, GEN code); void forstep(GEN a, GEN b, GEN s, GEN code); void forsubgroup0(GEN cyc, GEN bound, GEN code); void forvec(GEN x, GEN code, long flag); void forpart0(GEN k, GEN code , GEN nbound, GEN abound); GEN intcirc0(GEN a, GEN R, GEN code, GEN tab, long prec); GEN intfourcos0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec); GEN intfourexp0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec); GEN intfoursin0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec); 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); GEN prodeuler0(GEN a, GEN b, GEN code, long prec); GEN prodinf0(GEN a, GEN code, long flag, long prec); GEN produit(GEN a, GEN b, GEN code, GEN x); GEN somme(GEN a, GEN b, GEN code, GEN x); GEN sumalt0(GEN a, GEN code,long flag, long prec); GEN sumdivexpr(GEN num, GEN code); 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); GEN vecteursmall(GEN nmax, GEN code); GEN vecteur(GEN nmax, GEN n); GEN vvecteur(GEN nmax, GEN n); GEN zbrent0(GEN a, GEN b, GEN code, long prec); /* mt */ void mt_sigint(void); void mt_err_recover(long er); 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); GEN parfor_worker(GEN i, GEN C); void parforprime(GEN a, GEN b, GEN code, GEN code2); GEN parvector_worker(GEN i, GEN C); /* multiprecision */ GEN addrex01(GEN x); GEN adduispec_offset(ulong s, GEN x, long offset, long nx); int lgcdii(ulong* d, ulong* d1, ulong* u, ulong* u1, ulong* v, ulong* v1, ulong vmax); ulong rgcduu(ulong d, ulong d1, ulong vmax, ulong* u, ulong* u1, ulong* v, ulong* v1, long *s); ulong xgcduu(ulong d, ulong d1, int f, ulong* v, ulong* v1, long *s); ulong xxgcduu(ulong d, ulong d1, int f, ulong* u, ulong* u1, ulong* v, ulong* v1, long *s); GEN divgunu(GEN x, ulong i); GEN divrunu(GEN x, ulong i); GEN muliispec(GEN x, GEN y, long nx, long ny); GEN red_montgomery(GEN T, GEN N, ulong inv); GEN sqrispec(GEN x, long nx); GEN subrex01(GEN x); GEN modr_safe(GEN x, GEN y); ulong *convi(GEN x, long *l); int approx_0(GEN x, GEN y); GEN bernfrac_using_zeta(long n); /* powers */ GEN rpowuu(ulong a, ulong n, long prec); ulong u_pow10(int n); /* floats */ double dabs(double s, double t); void dcxlog(double s, double t, double *a, double *b); double dnorm(double s, double t); double dbllog2(GEN z); /* hnf */ GEN hnfadd(GEN m,GEN p,GEN* ptdep,GEN* ptA,GEN* ptC,GEN extramat,GEN extraC); GEN hnfadd_i(GEN m,GEN p,GEN* ptdep,GEN* ptA,GEN* ptC,GEN extramat,GEN extraC); GEN hnfspec_i(GEN m,GEN p,GEN* ptdep,GEN* ptA,GEN* ptC,long k0); GEN hnfspec(GEN m,GEN p,GEN* ptdep,GEN* ptA,GEN* ptC,long k0); GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC); GEN ZM_hnfmodall_i(GEN x, GEN dm, long flag); GEN LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, long *ti_LLL); GEN extendedgcd(GEN A); /* miscellaneous linear algebra */ GEN imagecomplspec(GEN x, long *nlze); GEN ZM_imagecomplspec(GEN x, long *nlze); GEN dim1proj(GEN prh); GEN detcyc(GEN cyc, long *L); GEN merge_factor_i(GEN f, GEN g); /* integer factorization / discrete log */ GEN coprime_part(GEN x, GEN f); ulong ucoprime_part(ulong x, ulong f); ulong is_kth_power(GEN x, ulong p, GEN *pt); GEN mpqs(GEN N); ulong gcduodd(ulong x, ulong y); /* Polynomials */ /* a) Arithmetic/conversions */ GEN addmulXn(GEN x, GEN y, long d); GEN addshiftpol(GEN x, GEN y, long d); GEN lift_if_rational(GEN x); GEN monomial(GEN a, long degpol, long v); GEN monomialcopy(GEN a, long degpol, long v); GEN mulmat_pol(GEN A, GEN x); GEN ser2pol_i(GEN x, long lx); GEN ser2rfrac_i(GEN x); GEN shiftpol_i(GEN x, long v); GEN swap_vars(GEN b0, long v); GEN RgX_recipspec_shallow(GEN x, long l, long n); /* b) Modular */ GEN bezout_lift_fact(GEN T, GEN Tmod, GEN p, long e); long F2x_split_Berlekamp(GEN *t); long Flx_split_Berlekamp(GEN *t, ulong p); long FpX_split_Berlekamp(GEN *t, GEN pp); long FqX_split_Berlekamp(GEN *t, GEN T, GEN p); GEN FpX_quad_root(GEN x, GEN p, int unknown); GEN FqX_split_all(GEN z, GEN T, GEN p); long FqX_split_by_degree(GEN *pz, GEN u, GEN T, GEN p); long FqX_split_deg1(GEN *pz, GEN u, GEN T, GEN p); GEN FqX_split_roots(GEN z, GEN T, GEN p, GEN pol); GEN polsym_gen(GEN P, GEN y0, long n, GEN T, GEN N); GEN ZXQ_charpoly_sqf(GEN A, GEN B, long *lambda, long v); GEN ZX_disc_all(GEN,ulong); GEN ZX_resultant_all(GEN A, GEN B, GEN dB, ulong bound); GEN ZX_ZXY_resultant_all(GEN A, GEN B, long *lambda, GEN *LPRS); 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); GEN fact_from_DDF(GEN fa, GEN e, long n); GEN initgaloisborne(GEN T, GEN dn, long prec, GEN *pL, GEN *pprep, GEN *pdis); GEN logmax_modulus_bound(GEN p); GEN polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy); GEN quicktrace(GEN x, GEN sym); GEN special_pivot(GEN x); GEN vandermondeinversemod(GEN L, GEN T, GEN den, GEN mod); GEN ZX_monic_factorpadic(GEN f, GEN p, long prec); /* Finite fields */ enum { t_FF_FpXQ = 0, t_FF_Flxq = 1, t_FF_F2xq = 2 }; GEN FF_ellinit(GEN E, GEN fg); GEN FF_elldata(GEN E, GEN fg); /* Elliptic curves */ /* common to Q and Rg */ enum { R_PERIODS = 1, R_ETA, R_ROOTS, R_AB }; enum { Qp_ROOT = 1, Qp_TATE }; enum { Q_GROUPGEN = 5, Q_GLOBALRED, Q_ROOTNO, Q_MINIMALMODEL }; /* common to Fp and Fq */ enum { FF_CARD = 1, FF_GROUP, FF_GROUPGEN, FF_O }; /* for Buchall_param */ enum { fupb_NONE, fupb_RELAT, fupb_LARGE, fupb_PRECI }; /* Allocation / gerepile */ void setdebugvar(long n); void debug_stack(void); void fill_stack(void); void init_dalloc(void); double *dalloc(size_t n); void minim_alloc(long n, double ***q, GEN *x, double **y, double **z, double **v); int pop_entree_block(entree *ep, long loc); int pop_val_if_newer(entree *ep, long loc); /* general printing */ void print_errcontext(PariOUT *out, const char *msg, const char *s, const char *entry); void print_prefixed_text(PariOUT *out, const char *s, const char *prefix, const char *str); INLINE void print_text(const char *s) { print_prefixed_text(pariOut, s,NULL,NULL); } INLINE void out_print_text(PariOUT *out, const char *s) { print_prefixed_text(out, s,NULL,NULL); } INLINE long 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 pari_sigint(const char *s); pariFILE *pari_last_tmp_file(void); void* get_stack(double fraction, long min); void init_graph(void); void free_graph(void); void initout(int initerr); void resetout(int initerr); void init_linewrap(long w); void pari_kernel_init(void); void pari_kernel_close(void); void print_functions_hash(const char *s); void print_all_user_fun(int member); GEN readbin(const char *name, FILE *f, int *vector); int term_height(void); 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; void lim_lines_output(char *s, long n, long max); void gen_output(GEN x, pariout_t *T); void fputGEN_pariout(GEN x, pariout_t *T, FILE *out); void parsestate_reset(void); void parsestate_save(struct pari_parsestate *state); void parsestate_restore(struct pari_parsestate *state); void compilestate_reset(void); void compilestate_save(struct pari_compilestate *comp); void compilestate_restore(struct pari_compilestate *comp); void evalstate_clone(void); 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 mtstate_save(long *pending); void mtstate_reset(void); 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; char **dir; } forpath_t; void forpath_init(forpath_t *T, gp_path *path, const char *s); char *forpath_next(forpath_t *T); /* GP output && output format */ void gpwritebin(const char *s, GEN x); extern char *current_logfile; /* colors */ 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) #define EpSETSTATIC(ep) ((ep)->valence |= 0x100) enum { EpNEW = 100, EpALIAS, EpVAR, EpINSTALL }; #define initial_value(ep) ((ep)+1) /* functions lists */ 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 { char *buf; ulong len; jmp_buf env; } Buffer; Buffer *new_buffer(void); void delete_buffer(Buffer *b); 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; 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); 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); const char *pari_default_path(void); int path_is_absolute(char *s); typedef struct input_method { /* mandatory */ char * (*fgets)(char *,int,FILE*); char * (*getline)(char**, int f, struct input_method*, filtre_t *F); int free; /* boolean: must we free the output of getline() ? */ /* for interactive methods */ const char *prompt, *prompt_cont; /* for non-interactive methods */ FILE *file; } input_method; int input_loop(filtre_t *F, input_method *IM); char *file_input(char **s0, int junk, input_method *IM, filtre_t *F); 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); GEN redrealsl2(GEN V, GEN d, GEN rd); GEN redrealsl2step(GEN A, GEN d, GEN rd); GEN redtausl2(GEN t, GEN *U); /* alglin1.c */ typedef long (*pivot_fun)(GEN,GEN,long,GEN); GEN ZM_pivots(GEN x0, long *rr); GEN RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot); /* arith1.c */ int is_gener_Fp(GEN x, GEN p, GEN p_1, GEN L); int is_gener_Fl(ulong x, ulong p, ulong p_1, GEN L); /* arith2.c */ int divisors_init(GEN n, GEN *pP, GEN *pE); 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); /* 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 */ void check_listpr(GEN x); GEN extideal_HNF_mul(GEN nf, GEN x, GEN y); GEN factor_norm(GEN x); GEN factorbackprime(GEN nf, GEN L, GEN e); 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); /* buch1.c */ GEN form_to_ideal(GEN x); GEN qfbforms(GEN D); /* buch2.c */ typedef struct GRHprime_t { ulong p; double logp; GEN dec; } GRHprime_t; typedef struct GRHcheck_t { double cD, cN; GRHprime_t *primes; long clone, nprimes, maxprimes; ulong limp; forprime_t P; } GRHcheck_t; void free_GRHcheck(GRHcheck_t *S); void init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD); void GRH_ensure(GRHcheck_t *S, long nb); ulong GRH_last_prime(GRHcheck_t *S); int GRHok(GRHcheck_t *S, double L, double SA, double SB); GEN check_and_build_matal(GEN bnf); GEN extract_full_lattice(GEN x); GEN init_red_mod_units(GEN bnf, long prec); GEN isprincipalarch(GEN bnf, GEN col, GEN kNx, GEN e, GEN dx, long *pe); GEN red_mod_units(GEN col, GEN z); /* buch3.c */ GEN minkowski_bound(GEN D, long N, long r2, long prec); int subgroup_conductor_ok(GEN H, GEN L); GEN subgrouplist_cond_sub(GEN bnr, GEN C, GEN bound); /* ellsea.c */ void pari_close_seadata(void); void pari_init_seadata(void); /* es.c */ const char * eng_ord(long i); char * env_ok(const char *s); void filestate_restore(pariFILE *F); void killallfiles(void); pariFILE* newfile(FILE *f, const char *name, int type); void pari_init_homedir(void); void pari_close_homedir(void); void pari_init_files(void); void pari_close_files(void); int popinfile(void); pariFILE* try_pipe(const char *cmd, int flag); /* Flxq_log.c */ GEN Flxq_log_index(GEN a0, GEN b0, GEN m, GEN T0, ulong p); /* FlxqE.c */ GEN ZpXQ_norm_pcyc(GEN x, GEN T, GEN q, GEN p); long zx_is_pcyc(GEN T); /* galconj.c */ GEN galoiscosets(GEN O, GEN perm); 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); /* galois.c */ GEN polgaloisnamesbig(long n, long k); /* gen1.c */ int ff_poltype(GEN *x, GEN *p, GEN *pol); GEN gred_frac2(GEN x1, GEN x2); GEN gred_rfrac2(GEN x1, GEN x2); GEN gred_rfrac_simple(GEN n, GEN d); GEN sqr_ser_part(GEN x, long l1, long l2); /* gen3.c */ 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); /* ifactor1.c */ GEN ellfacteur(GEN n, int insist); GEN pollardbrent(GEN n); ulong snextpr(ulong p, byteptr *d, long *rcn, long *q, long k); GEN squfof(GEN n); /* prime.c */ long BPSW_psp_nosmalldiv(GEN N); int Fl_MR_Jaeschke(ulong n, long k); int MR_Jaeschke(GEN n, long k); long isanypower_nosmalldiv(GEN N, GEN *px); void prime_table_next_p(ulong a, byteptr *pd, ulong *pp, ulong *pn); int uisprime_101(ulong n); int uisprime_661(ulong n); /* init.c */ void pari_init_defaults(void); void pari_init_stack(size_t size, size_t old); /* nffactor.c */ int nfissplit(GEN nf, GEN x); /* perm.c */ long cosets_perm_search(GEN C, GEN p); GEN group_export_GAP(GEN G); GEN group_export_MAGMA(GEN G); GEN perm_generate(GEN S, GEN H, long o); long perm_relorder(GEN p, GEN S); GEN perm_to_GAP(GEN p); /* polarit1.c */ GEN F2x_Berlekamp_ker(GEN u); GEN Flx_Berlekamp_ker(GEN u, ulong p); GEN FpX_Berlekamp_ker(GEN u, GEN p); GEN FlxqX_Berlekamp_ker(GEN u, GEN T, ulong p); GEN FpXQX_Berlekamp_ker(GEN u, GEN T, GEN p); GEN F2x_factcantor(GEN f, long flag); GEN Flx_factcantor(GEN f, ulong p, long flag); GEN FpX_factcantor(GEN f, GEN pp, long flag); GEN FqX_rand(long d1, long v, GEN T, GEN p); int cmp_padic(GEN x, GEN y); GEN factcantor0(GEN f, GEN pp, long flag); /* polarit2.c */ GEN sylvestermatrix_i(GEN x, GEN y); /* QX_factor */ void factor_quad(GEN x, GEN res, long *ptcnt); /* FpX.c */ GEN FpX_gcd_check(GEN x, GEN y, GEN p); /* polarit3.c */ GEN Flm_Frobenius_pow(GEN M, long d, GEN T, ulong p); GEN FpM_Frobenius_pow(GEN M, long d, GEN T, GEN p); GEN FpX_compositum(GEN A, GEN B, GEN p); GEN FpX_direct_compositum(GEN A, GEN B, GEN p); ulong ZX_ZXY_ResBound(GEN A, GEN B, GEN dB); GEN ffinit_Artin_Shreier(GEN ip, long l); GEN ffinit_rand(GEN p, long n); void init_modular(forprime_t *S); GEN polint_triv(GEN xa, GEN ya); /* random.c */ void pari_init_rand(void); /* rootpol.c */ GEN FFT(GEN x, GEN Omega); GEN FFTinit(long k, long prec); /* subcyclo.c */ GEN bnr_to_znstar(GEN bnr, long *complex); GEN galoiscyclo(long n, long v); GEN znstar_bits(long n, GEN H); long znstar_conductor(long n, GEN H); GEN znstar_cosets(long n, long phi_n, GEN H); GEN znstar_elts(long n, GEN H); GEN znstar_generate(long n, GEN V); GEN znstar_hnf(GEN Z, GEN M); GEN znstar_hnf_elts(GEN Z, GEN H); GEN znstar_hnf_generators(GEN Z, GEN M); GEN znstar_reduce_modulus(GEN H, long n); GEN znstar_small(GEN zn); /* trans1.c */ GEN logagmcx(GEN q, long prec); void pari_init_floats(void); void pari_close_floats(void); GEN rootsof1complex(GEN n, long prec); GEN rootsof1padic(GEN n, GEN y); GEN zellagmcx(GEN a0, GEN b0, GEN r, GEN t, long prec); /* trans2.c */ GEN cxpsi(GEN s0, long prec); double darg(double s, double t); /* trans3.c */ GEN bernreal_using_zeta(long n, GEN iz, long prec); GEN czeta(GEN s0, long prec); GEN double_eta_quotient(GEN a, GEN w, GEN D, long p, long q, GEN pq, GEN sqrtD); GEN inv_szeta_euler(long n, double lba, long prec); GEN polylogd0(long m, GEN x, long flag, long prec); GEN trueE2(GEN tau, long prec); GEN twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff); ENDEXTERN pari-2.7.5/src/headers/paricast.h0000644000175000017500000000251712366172547015311 0ustar billbill/* 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. */ #define mael2(m,x1,x2) (((GEN*) (m))[x1][x2]) #define mael3(m,x1,x2,x3) (((GEN**) (m))[x1][x2][x3]) #define mael4(m,x1,x2,x3,x4) (((GEN***) (m))[x1][x2][x3][x4]) #define mael5(m,x1,x2,x3,x4,x5) (((GEN****)(m))[x1][x2][x3][x4][x5]) #define mael mael2 #define gmael1(m,x1) (((GEN*) (m))[x1]) #define gmael2(m,x1,x2) (((GEN**) (m))[x1][x2]) #define gmael3(m,x1,x2,x3) (((GEN***) (m))[x1][x2][x3]) #define gmael4(m,x1,x2,x3,x4) (((GEN****) (m))[x1][x2][x3][x4]) #define gmael5(m,x1,x2,x3,x4,x5) (((GEN*****)(m))[x1][x2][x3][x4][x5]) #define gmael(m,x,y) gmael2(m,x,y) #define gel(m,x) gmael1(m,x) #define gcoeff(a,i,j) (((GEN**)(a))[j][i]) #define coeff(a,i,j) (((GEN*)(a))[j][i]) #define GSTR(x) ((char*) (((GEN) (x)) + 1 )) pari-2.7.5/src/headers/paritune.h0000644000175000017500000000645512314242551015321 0ustar billbill#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 DIVRR_GMP_LIMIT; extern long Flx_MUL_KARATSUBA_LIMIT; extern long Flx_SQR_KARATSUBA_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_MULII2_LIMIT; extern long Flx_SQR_SQRI2_LIMIT; extern long Flx_INVBARRETT_LIMIT; extern long Flx_DIVREM_BARRETT_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 FpX_BARRETT_LIMIT; extern long FpX_HALFGCD_LIMIT; extern long FpX_GCD_LIMIT; extern long FpX_EXTGCD_LIMIT; extern long EXPNEWTON_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 RgX_MUL_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 #endif pari-2.7.5/src/headers/parierr.h0000644000175000017500000000201212366172547015135 0ustar billbill/* 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. */ enum err_list { /* Force errors into non-0 */ e_SYNTAX = 1, e_BUG, e_ALARM, e_FILE, e_MISC, e_FLAG, e_IMPL, e_ARCH, e_PACKAGE, e_NOTFUNC, e_PREC, e_TYPE, e_DIM, e_VAR, e_PRIORITY, e_USER, e_STACK, e_OVERFLOW, e_DOMAIN, e_COMPONENT, e_MAXPRIME, e_CONSTPOL, e_IRREDPOL, e_COPRIME, e_PRIME, e_MODULUS, e_ROOTS0, e_OP, e_TYPE2, e_INV, e_MEM, e_SQRTN, /* NO ERROR */ e_NONE }; enum { warner, warnprec, warnfile, warnmem, warnuser }; pari-2.7.5/src/headers/pari.h0000644000175000017500000000271312366172547014434 0ustar billbill/* 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. */ #ifndef __GENPARI__ #define __GENPARI__ #include "paricfg.h" #include /* malloc, free, atoi */ #ifdef UNIX # define _INCLUDE_POSIX_SOURCE /* for HPUX */ # include /* size_t */ #endif #ifdef WINCE # include #else # include # include #endif #include #include #include #if !defined(_WIN32) && !defined(WINCE) # include #else # include #endif #include #include #include #ifdef WINCE # include "pariCE.h" #endif #include "parisys.h" #include "parigen.h" #include "paricast.h" #include "paristio.h" #include "paricom.h" #include "pariold.h" #include "parierr.h" BEGINEXTERN #include "paridecl.h" #include "paritune.h" #include "parimt.h" #ifndef PARI_NO_MPINL_H # include "mpinl.h" #endif #ifndef PARI_NO_PARIINL_H # include "pariinl.h" #endif ENDEXTERN #endif pari-2.7.5/src/headers/pariinl.h0000644000175000017500000020700312601623026015117 0ustar billbill/* Copyright (C) 2000-2010 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. */ /*******************************************************************/ /* */ /* CONSTRUCTORS */ /* */ /*******************************************************************/ #define retmkfrac(x,y)\ do { GEN _v = cgetg(3, t_FRAC);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkintmod(x,y)\ do { GEN _v = cgetg(3, t_INTMOD);\ gel(_v,1) = (y);\ gel(_v,2) = (x); return _v; } while(0) #define retmkcomplex(x,y)\ do { GEN _v = cgetg(3, t_COMPLEX);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkpolmod(x,y)\ do { GEN _v = cgetg(3, t_POLMOD);\ gel(_v,1) = (y);\ gel(_v,2) = (x); return _v; } while(0) #define retmkvec(x)\ do { GEN _v = cgetg(2, t_VEC);\ gel(_v,1) = (x); return _v; } while(0) #define retmkvec2(x,y)\ do { GEN _v = cgetg(3, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkvec3(x,y,z)\ do { GEN _v = cgetg(4, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkqfi(x,y,z)\ do { GEN _v = cgetg(4, t_QFI);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkqfr(x,y,z,d)\ do { GEN _v = cgetg(5, t_QFR);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (d); return _v; } while(0) #define retmkquad(x,y,z)\ do { GEN _v = cgetg(4, t_QUAD);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkvec4(x,y,z,t)\ do { GEN _v = cgetg(5, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkvec5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkcol(x)\ do { GEN _v = cgetg(2, t_COL);\ gel(_v,1) = (x); return _v; } while(0) #define retmkcol2(x,y)\ do { GEN _v = cgetg(3, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkcol3(x,y,z)\ do { GEN _v = cgetg(4, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkcol4(x,y,z,t)\ do { GEN _v = cgetg(5, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkcol5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkmat(x)\ do { GEN _v = cgetg(2, t_MAT);\ gel(_v,1) = (x); return _v; } while(0) #define retmkmat2(x,y)\ do { GEN _v = cgetg(3, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkmat3(x,y,z)\ do { GEN _v = cgetg(4, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkmat4(x,y,z,t)\ do { GEN _v = cgetg(5, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkmat5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) INLINE GEN mkintmod(GEN x, GEN y) { retmkintmod(x,y); } INLINE GEN mkintmodu(ulong x, ulong y) { GEN v = cgetg(3,t_INTMOD); gel(v,1) = utoipos(y); gel(v,2) = utoi(x); return v; } INLINE GEN mkpolmod(GEN x, GEN y) { retmkpolmod(x,y); } INLINE GEN mkfrac(GEN x, GEN y) { retmkfrac(x,y); } INLINE GEN mkfraccopy(GEN x, GEN y) { retmkfrac(icopy(x), icopy(y)); } INLINE GEN mkrfrac(GEN x, GEN y) { GEN v = cgetg(3, t_RFRAC); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN mkrfraccopy(GEN x, GEN y) { GEN v = cgetg(3, t_RFRAC); gel(v,1) = gcopy(x); gel(v,2) = gcopy(y); return v; } INLINE GEN mkcomplex(GEN x, GEN y) { retmkcomplex(x,y); } INLINE GEN gen_I(void) { return mkcomplex(gen_0, gen_1); } INLINE GEN cgetc(long l) { retmkcomplex(cgetr(l), cgetr(l)); } INLINE GEN mkquad(GEN n, GEN x, GEN y) { GEN v = cgetg(4, t_QUAD); gel(v,1) = n; gel(v,2) = x; gel(v,3) = y; return v; } /* vecsmall */ INLINE GEN mkvecsmall(long x) { GEN v = cgetg(2, t_VECSMALL); v[1] = x; return v; } INLINE GEN mkvecsmall2(long x,long y) { GEN v = cgetg(3, t_VECSMALL); v[1]=x; v[2]=y; return v; } INLINE GEN mkvecsmall3(long x,long y,long z) { GEN v = cgetg(4, t_VECSMALL); v[1]=x; v[2]=y; v[3]=z; return v; } 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 mkqfi(GEN x, GEN y, GEN z) { retmkqfi(x,y,z); } /* vec */ INLINE GEN mkvec(GEN x) { retmkvec(x); } INLINE GEN mkvec2(GEN x, GEN y) { retmkvec2(x,y); } INLINE GEN mkvec3(GEN x, GEN y, GEN z) { retmkvec3(x,y,z); } INLINE GEN mkvec4(GEN x, GEN y, GEN z, GEN t) { retmkvec4(x,y,z,t); } INLINE GEN mkvec5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkvec5(x,y,z,t,u); } INLINE GEN mkvecs(long x) { retmkvec(stoi(x)); } INLINE GEN mkvec2s(long x, long y) { retmkvec2(stoi(x),stoi(y)); } INLINE GEN mkvec3s(long x, long y, long z) { retmkvec3(stoi(x),stoi(y),stoi(z)); } INLINE GEN mkvec4s(long x, long y, long z, long t) { retmkvec4(stoi(x),stoi(y),stoi(z),stoi(t)); } INLINE GEN mkveccopy(GEN x) { GEN v = cgetg(2, t_VEC); gel(v,1) = gcopy(x); return v; } INLINE GEN mkvec2copy(GEN x, GEN y) { GEN v = cgetg(3,t_VEC); gel(v,1) = gcopy(x); gel(v,2) = gcopy(y); return v; } /* col */ INLINE GEN mkcol(GEN x) { retmkcol(x); } INLINE GEN mkcol2(GEN x, GEN y) { retmkcol2(x,y); } INLINE GEN mkcol3(GEN x, GEN y, GEN z) { retmkcol3(x,y,z); } INLINE GEN 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 mkcols(long x) { retmkcol(stoi(x)); } INLINE GEN mkcol2s(long x, long y) { retmkcol2(stoi(x),stoi(y)); } INLINE GEN mkcol3s(long x, long y, long z) { retmkcol3(stoi(x),stoi(y),stoi(z)); } INLINE GEN mkcol4s(long x, long y, long z, long t) { retmkcol4(stoi(x),stoi(y),stoi(z),stoi(t)); } INLINE GEN mkcolcopy(GEN x) { GEN v = cgetg(2, t_COL); gel(v,1) = gcopy(x); return v; } /* mat */ INLINE GEN mkmat(GEN x) { retmkmat(x); } INLINE GEN mkmat2(GEN x, GEN y) { retmkmat2(x,y); } INLINE GEN mkmat3(GEN x, GEN y, GEN z) { retmkmat3(x,y,z); } INLINE GEN mkmat4(GEN x, GEN y, GEN z, GEN t) { retmkmat4(x,y,z,t); } INLINE GEN mkmat5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkmat5(x,y,z,t,u); } 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; } /* pol */ INLINE GEN pol_x(long v) { GEN p = cgetg(4, t_POL); p[1] = evalsigne(1)|evalvarn(v); gel(p,2) = gen_0; gel(p,3) = gen_1; return p; } INLINE GEN pol_1(long v) { GEN p = cgetg(3, t_POL); p[1] = evalsigne(1)|evalvarn(v); gel(p,2) = gen_1; return p; } INLINE GEN pol_0(long v) { GEN x = cgetg(2,t_POL); x[1] = evalvarn(v); return x; } #define retconst_vec(n,x)\ do { long _i, _n = (n);\ GEN _v = cgetg(_n+1, t_VEC), _x = (x);\ for (_i = 1; _i <= _n; _i++) gel(_v,_i) = _x;\ return _v; } while(0) INLINE GEN const_vec(long n, GEN x) { retconst_vec(n, x); } #define retconst_col(n,x)\ do { long _i, _n = (n);\ GEN _v = cgetg(_n+1, t_COL), _x = (x);\ for (_i = 1; _i <= _n; _i++) gel(_v,_i) = _x;\ return _v; } while(0) INLINE GEN const_col(long n, GEN x) { retconst_col(n, x); } INLINE GEN const_vecsmall(long n, long c) { long i; GEN V = cgetg(n+1,t_VECSMALL); for(i=1;i<=n;i++) V[i] = c; return V; } /*** ZERO ***/ /* O(p^e) */ INLINE GEN zeropadic(GEN p, long e) { GEN y = cgetg(5,t_PADIC); gel(y,4) = gen_0; gel(y,3) = gen_1; gel(y,2) = icopy(p); y[1] = evalvalp(e) | _evalprecp(0); return y; } INLINE GEN zeropadic_shallow(GEN p, long e) { GEN y = cgetg(5,t_PADIC); gel(y,4) = gen_0; gel(y,3) = gen_1; gel(y,2) = p; y[1] = evalvalp(e) | _evalprecp(0); return y; } /* O(pol_x(v)^e) */ INLINE GEN zeroser(long v, long e) { GEN x = cgetg(2, t_SER); x[1] = evalvalp(e) | evalvarn(v); return x; } /* 0 * pol_x(v) */ INLINE GEN zeropol(long v) { return pol_0(v); } /* vector(n) */ INLINE GEN zerocol(long n) { GEN y = cgetg(n+1,t_COL); long i; for (i=1; i<=n; i++) gel(y,i) = gen_0; return y; } /* vectorv(n) */ INLINE GEN zerovec(long n) { GEN y = cgetg(n+1,t_VEC); long i; for (i=1; i<=n; i++) gel(y,i) = gen_0; return y; } /* matrix(m, n) */ INLINE GEN zeromat(long m, long n) { GEN y = cgetg(n+1,t_MAT); GEN v = zerocol(m); long i; for (i=1; i<=n; i++) gel(y,i) = v; return y; } /* = zero_zx, sv is a evalvarn()*/ INLINE GEN zero_Flx(long sv) { return pol0_Flx(sv); } INLINE GEN zero_Flv(long n) { GEN y = cgetg(n+1,t_VECSMALL); long i; for (i=1; i<=n; i++) y[i] = 0; return y; } /* matrix(m, n) */ INLINE GEN zero_Flm(long m, long n) { GEN y = cgetg(n+1,t_MAT); GEN v = zero_Flv(m); long i; for (i=1; i<=n; i++) gel(y,i) = v; return y; } /* matrix(m, n) */ INLINE GEN zero_Flm_copy(long m, long n) { GEN y = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(y,i) = zero_Flv(m); return y; } INLINE GEN zero_F2v(long m) { long l = nbits2nlong(m); GEN v = zero_Flv(l+1); v[1] = m; return v; } INLINE GEN zero_F2m(long m, long n) { long i; GEN M = cgetg(n+1, t_MAT); GEN v = zero_F2v(m); for (i = 1; i <= n; i++) gel(M,i) = v; return M; } INLINE GEN zero_F2m_copy(long m, long n) { long i; GEN M = cgetg(n+1, t_MAT); for (i = 1; i <= n; i++) gel(M,i)= zero_F2v(m); return M; } /* matrix(m, n) */ INLINE GEN zeromatcopy(long m, long n) { GEN y = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(y,i) = zerocol(m); return y; } /* i-th vector in the standard basis */ INLINE GEN col_ei(long n, long i) { GEN e = zerocol(n); gel(e,i) = gen_1; return e; } INLINE GEN vec_ei(long n, long i) { GEN e = zerovec(n); gel(e,i) = gen_1; return e; } INLINE GEN F2v_ei(long n, long i) { GEN e = zero_F2v(n); F2v_set(e,i); return e; } INLINE GEN vecsmall_ei(long n, long i) { GEN e = zero_zv(n); e[i] = 1; return e; } INLINE GEN Rg_col_ei(GEN x, long n, long i) { GEN e = zerocol(n); gel(e,i) = x; return e; } INLINE GEN shallowcopy(GEN x) { return typ(x) == t_MAT ? RgM_shallowcopy(x): leafcopy(x); } /* routines for naive growarrays */ INLINE GEN vectrunc_init(long l) { GEN z = new_chunk(l); z[0] = evaltyp(t_VEC) | _evallg(1); return z; } INLINE void vectrunc_append(GEN x, GEN t) { long l = lg(x); gel(x,l) = t; setlg(x, l+1); } INLINE void vectrunc_append_batch(GEN x, GEN y) { long i, l = lg(x), ly = lg(y); GEN z = x + l-1; for (i = 1; i < ly; i++) gel(z,i) = gel(y,i); setlg(x, l+ly-1); } INLINE GEN vecsmalltrunc_init(long l) { GEN z = new_chunk(l); z[0] = evaltyp(t_VECSMALL) | _evallg(1); return z; } INLINE void vecsmalltrunc_append(GEN x, long t) { long l = lg(x); x[l] = t; setlg(x, l+1); } /*******************************************************************/ /* */ /* VEC / COL / VECSMALL */ /* */ /*******************************************************************/ /* shallow*/ INLINE GEN vec_shorten(GEN v, long n) { long i; GEN V = cgetg(n+1,t_VEC); for(i=1;i<=n;i++) gel(V,i) = gel(v,i); return V; } /* shallow*/ INLINE GEN vec_lengthen(GEN v, long n) { long i; long l=lg(v); GEN V = cgetg(n+1,t_VEC); for(i=1;i t) t = x[i0=i]; return i0; } INLINE long vecsmall_max(GEN x) { long i, t = x[1], lx = lg(x); for (i=2; i t) t = x[i]; return t; } INLINE long vecsmall_indexmin(GEN x) { long i, i0 = 1, t = x[1], lx =lg(x); for (i=2; i 1) if (signe(gel(x, l))) return 0; return 1; } INLINE int QV_isscalar(GEN x) { long lx = lg(x),i; for (i=2; i2; i--) if (!gequal0(gel(x, i))) return 0; return 1; } INLINE long RgX_equal_var(GEN x, GEN y) { return varn(x) == varn(y) && RgX_equal(x,y); } INLINE int RgX_is_rational(GEN x) { long i; for (i = lg(x)-1; i > 1; i--) if (!is_rational_t(typ(gel(x,i)))) return 0; return 1; } INLINE int RgX_is_ZX(GEN x) { long i; for (i = lg(x)-1; i > 1; i--) if (typ(gel(x,i)) != t_INT) return 0; return 1; } INLINE int RgX_is_QX(GEN x) { long k = lg(x)-1; for ( ; k>1; k--) if (!is_rational_t(typ(gel(x,k)))) return 0; return 1; } INLINE int RgX_is_monomial(GEN x) { long i; if (!signe(x)) return 0; for (i=lg(x)-2; i>1; i--) if (!isexactzero(gel(x,i))) return 0; return 1; } INLINE int RgV_is_ZV(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) if (typ(gel(x,i)) != t_INT) return 0; return 1; } INLINE int RgV_is_QV(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) if (!is_rational_t(typ(gel(x,i)))) return 0; return 1; } /********************************************************************/ /** **/ /** Dynamic arrays implementation **/ /** **/ /********************************************************************/ INLINE void ** pari_stack_base(pari_stack *s) { return s->data; } INLINE void pari_stack_init(pari_stack *s, size_t size, void **data) { s->data = data; *data = NULL; s->n = 0; s->alloc = 0; s->size = size; } INLINE void pari_stack_alloc(pari_stack *s, long nb) { void **sdat = pari_stack_base(s); if (s->n+nb <= s->alloc) return; if (!s->alloc) s->alloc = nb; else { while (s->n+nb > s->alloc) s->alloc <<= 1; } *sdat = pari_realloc(*sdat,s->alloc*s->size); } INLINE long pari_stack_new(pari_stack *s) { pari_stack_alloc(s, 1); return s->n++; } INLINE void pari_stack_delete(pari_stack *s) { void **sdat = pari_stack_base(s); if (*sdat) free(*sdat); } INLINE void pari_stack_pushp(pari_stack *s, void *u) { long n = pari_stack_new(s); void **sdat =(void**) *pari_stack_base(s); sdat[n] = u; } /*******************************************************************/ /* */ /* EXTRACT */ /* */ /*******************************************************************/ INLINE GEN vecslice(GEN A, long y1, long y2) { long i,lB = y2 - y1 + 2; GEN B = cgetg(lB, typ(A)); for (i=1; i 0) y[i] = x[i]; y[0] = evaltyp(t_INT)|evallg(lx); return y; } /* copy leaf x as if we had avma = av */ INLINE GEN leafcopy_avma(GEN x, pari_sp av) { long i = lg(x); GEN y = ((GEN)av) - i; while (--i > 0) y[i] = x[i]; y[0] = x[0] & (~CLONEBIT); return y; } INLINE GEN gerepileuptoleaf(pari_sp av, GEN x) { long lx; GEN q; if (!isonstack(x) || (GEN)av<=x) { avma = av; return x; } lx = lg(x); q = ((GEN)av) - lx; avma = (pari_sp)q; while (--lx >= 0) q[lx] = x[lx]; return q; } INLINE GEN gerepileuptoint(pari_sp av, GEN x) { if (!isonstack(x) || (GEN)av<=x) { avma = av; return x; } avma = (pari_sp)icopy_avma(x, av); return (GEN)avma; } INLINE GEN gerepileupto(pari_sp av, GEN x) { if (!isonstack(x) || (GEN)av<=x) { avma = av; return x; } switch(typ(x)) { /* non-default = !is_recursive_t(tq) */ case t_INT: return gerepileuptoint(av, x); case t_REAL: case t_STR: case t_VECSMALL: return gerepileuptoleaf(av,x); default: /* NB: x+i --> ((long)x) + i*sizeof(long) */ return gerepile(av, (pari_sp) (x+lg(x)), x); } } /* gerepileupto(av, gcopy(x)) */ INLINE GEN gerepilecopy(pari_sp av, GEN x) { if (is_recursive_t(typ(x))) { GENbin *p = copy_bin(x); avma = av; return bin_copy(p); } else { avma = av; if (x < (GEN)av) { if (x < (GEN)bot) new_chunk(lg(x)); x = leafcopy_avma(x, av); avma = (pari_sp)x; } else x = leafcopy(x); return x; } } /* Takes an array of pointers to GENs, of length n. Copies all * objects to contiguous locations and cleans up the stack between * av and avma. */ INLINE void gerepilemany(pari_sp av, GEN* gptr[], int n) { int i; for (i=0; i=0; i--) *gptr[i] = bin_copy((GENbin*)*gptr[i]); } else { GEN **gptr = (GEN**) pari_malloc(n*sizeof(GEN*)); for (i=0; i=0; i--) *gptr[i] = bin_copy((GENbin*)*gptr[i]); pari_free(gptr); } } INLINE void gerepilecoeffs(pari_sp av, GEN x, int n) { int i; for (i=0; ix back to stack, then destroy p */ INLINE GEN bin_copy(GENbin *p) { GEN x, y, base; long dx, len; x = p->x; if (!x) { pari_free(p); return gen_0; } len = p->len; base= p->base; dx = x - base; y = (GEN)memcpy((void*)new_chunk(len), (void*)GENbinbase(p), len*sizeof(long)); y += dx; if (p->canon) shiftaddress_canon(y, (y-x)*sizeof(long)); else shiftaddress(y, (y-x)*sizeof(long)); pari_free(p); return y; } INLINE GEN GENbinbase(GENbin *p) { return (GEN)(p + 1); } INLINE void cgiv(GEN x) { pari_sp av = (pari_sp)(x+lg(x)); if (isonstack((GEN)av)) avma = av; } INLINE void killblock(GEN x) { gunclone(x); } INLINE int is_universal_constant(GEN x) { return (x >= gen_0 && x <= ghalf); } /*******************************************************************/ /* */ /* CONVERSION / ASSIGNMENT */ /* */ /*******************************************************************/ /* z is a type which may be a t_COMPLEX component (not a t_QUAD) */ INLINE GEN cxcompotor(GEN z, long prec) { switch(typ(z)) { case t_INT: return itor(z, prec); case t_FRAC: return fractor(z, prec); case t_REAL: return rtor(z, prec); default: pari_err_TYPE("cxcompotor",z); return NULL; /* not reached */ } } INLINE GEN cxtofp(GEN x, long prec) { retmkcomplex(cxcompotor(gel(x,1),prec), cxcompotor(gel(x,2),prec)); } INLINE double gtodouble(GEN x) { if (typ(x)!=t_REAL) { pari_sp av = avma; x = gtofp(x, DEFAULTPREC); if (typ(x)!=t_REAL) pari_err_TYPE("gtodouble [t_REAL expected]", x); avma = av; } return rtodbl(x); } INLINE long gtos(GEN x) { if (typ(x) != t_INT) pari_err_TYPE("gtos [integer expected]",x); return itos(x); } INLINE GEN absfrac(GEN x) { GEN y = cgetg(3, t_FRAC); gel(y,1) = absi(gel(x,1)); gel(y,2) = icopy(gel(x,2)); return y; } INLINE GEN absfrac_shallow(GEN x) { return signe(gel(x,1))>0? x: mkfrac(negi(gel(x,1)), gel(x,2)); } INLINE GEN Q_abs(GEN x) { return (typ(x) == t_INT)? absi(x): absfrac(x); } INLINE GEN Q_abs_shallow(GEN x) { return (typ(x) == t_INT)? absi_shallow(x): absfrac_shallow(x); } /* Force z to be of type real/complex with floating point components */ INLINE GEN gtofp(GEN z, long prec) { switch(typ(z)) { case t_INT: return itor(z, prec); case t_FRAC: return fractor(z, prec); case t_REAL: return rtor(z, prec); case t_COMPLEX: { GEN a = gel(z,1), b = gel(z,2); if (isintzero(b)) return cxcompotor(a, prec); if (isintzero(a)) { GEN y = cgetg(3, t_COMPLEX); b = cxcompotor(b, prec); gel(y,1) = real_0_bit(expo(b) - prec2nbits(prec)); gel(y,2) = b; return y; } return cxtofp(z, prec); } case t_QUAD: return quadtofp(z, prec); default: pari_err_TYPE("gtofp",z); return NULL; /* not reached */ } } /* Force z to be of type real / int */ INLINE GEN gtomp(GEN z, long prec) { switch(typ(z)) { case t_INT: return z; case t_FRAC: return fractor(z, prec); case t_REAL: return rtor(z, prec); case t_QUAD: z = quadtofp(z, prec); if (typ(z) == t_REAL) return z; default: pari_err_TYPE("gtomp",z); return NULL; /* not reached */ } } INLINE GEN RgX_gtofp(GEN x, long prec) { long l; GEN y = cgetg_copy(x, &l); while (--l > 1) gel(y,l) = gtofp(gel(x,l), prec); y[1] = x[1]; return y; } INLINE GEN RgC_gtofp(GEN x, long prec) { long l = lg(x); GEN y = cgetg(l, t_COL); while (--l > 0) gel(y,l) = gtofp(gel(x,l), prec); return y; } INLINE GEN RgM_gtofp(GEN x, long prec) { long l; GEN y = cgetg_copy(x, &l); while (--l > 0) gel(y,l) = RgC_gtofp(gel(x,l), prec); return y; } INLINE GEN RgC_gtomp(GEN x, long prec) { long l = lg(x); GEN y = cgetg(l, t_COL); while (--l > 0) gel(y,l) = gtomp(gel(x,l), prec); return y; } INLINE GEN RgM_gtomp(GEN x, long prec) { long l; GEN y = cgetg_copy(x, &l); while (--l > 0) gel(y,l) = RgC_gtomp(gel(x,l), prec); return y; } INLINE GEN RgX_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgX_gtofp(x, prec))); } INLINE GEN RgC_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgC_gtofp(x, prec))); } INLINE GEN RgM_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgM_gtofp(x, prec))); } /* y a t_REAL */ INLINE void affgr(GEN x, GEN y) { pari_sp av; switch(typ(x)) { case t_INT: affir(x,y); break; case t_REAL: affrr(x,y); break; case t_FRAC: rdiviiz(gel(x,1),gel(x,2), y); break; case t_QUAD: av = avma; affgr(quadtofp(x,realprec(y)), y); avma = av; break; default: pari_err_TYPE2("=",x,y); } } INLINE GEN affc_fixlg(GEN x, GEN res) { if (typ(x) == t_COMPLEX) { affrr_fixlg(gel(x,1), gel(res,1)); affrr_fixlg(gel(x,2), gel(res,2)); } else { avma = (pari_sp)(res+3); res = cgetr(realprec(gel(res,1))); affrr_fixlg(x, res); } return res; } INLINE GEN trunc_safe(GEN x) { long e; return gcvtoi(x,&e); } /*******************************************************************/ /* */ /* LENGTH CONVERSIONS */ /* */ /*******************************************************************/ INLINE long ndec2nlong(long x) { return 1 + (long)((x)*(LOG2_10/BITS_IN_LONG)); } INLINE long ndec2prec(long x) { return 2 + ndec2nlong(x); } /* Fast implementation of ceil(x / (8*sizeof(long))); typecast to (ulong) * to avoid overflow. Faster than 1 + ((x-1)>>TWOPOTBITS_IN_LONG)) : * addl, shrl instead of subl, sarl, addl */ INLINE long nbits2nlong(long x) { return (long)(((ulong)x+BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } INLINE long nbits2extraprec(long x) { return (long)(((ulong)x+BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } /* Fast implementation of 2 + nbits2nlong(x) */ INLINE long nbits2prec(long x) { return (long)(((ulong)x+3*BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } INLINE long nbits2lg(long x) { return (long)(((ulong)x+3*BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } /* ceil(x / sizeof(long)) */ INLINE long nchar2nlong(long x) { return (long)(((ulong)x+sizeof(long)-1) >> (TWOPOTBITS_IN_LONG-3L)); } INLINE long bit_accuracy(long x) { return (x-2) * BITS_IN_LONG; } INLINE double bit_accuracy_mul(long x, double y) { return (x-2) * (BITS_IN_LONG*y); } INLINE double prec2nbits_mul(long x, double y) { return (x-2) * (BITS_IN_LONG*y); } INLINE long bit_prec(GEN x) { return bit_accuracy(realprec(x)); } INLINE long prec2nbits(long x) { return bit_accuracy(x); } INLINE long prec2ndec(long x) { return (long)prec2nbits_mul(x, LOG10_2); } INLINE long precdbl(long x) {return (x - 1) << 1;} INLINE long divsBIL(long n) { return n >> TWOPOTBITS_IN_LONG; } INLINE long remsBIL(long n) { return n & (BITS_IN_LONG-1); } /*********************************************************************/ /** **/ /** OPERATIONS MODULO m **/ /** **/ /*********************************************************************/ /* Assume m > 0, more efficient if 0 <= a, b < m */ INLINE GEN Fp_red(GEN a, GEN m) { return modii(a, m); } INLINE GEN Fp_add(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p = addii(a,b); long s = signe(p); if (!s) return p; /* = gen_0 */ if (s > 0) /* general case */ { GEN t = subii(p, m); s = signe(t); if (!s) { avma = av; return gen_0; } if (s < 0) { avma = (pari_sp)p; return p; } if (cmpii(t, m) < 0) return gerepileuptoint(av, t); /* general case ! */ p = remii(t, m); } else p = modii(p, m); return gerepileuptoint(av, p); } INLINE GEN Fp_sub(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p = subii(a,b); long s = signe(p); if (!s) return p; /* = gen_0 */ if (s > 0) { if (cmpii(p, m) < 0) return p; /* general case ! */ p = remii(p, m); } else { GEN t = addii(p, m); if (!s) { avma = av; return gen_0; } if (s > 0) return gerepileuptoint(av, t); /* general case ! */ p = modii(t, m); } return gerepileuptoint(av, p); } INLINE GEN Fp_neg(GEN b, GEN m) { pari_sp av = avma; long s = signe(b); GEN p; if (!s) return gen_0; if (s > 0) { p = subii(m, b); if (signe(p) >= 0) return p; /* general case ! */ p = modii(p, m); } else p = remii(negi(b), m); return gerepileuptoint(av, p); } /* assume 0 <= u < p and ps2 = p>>1 */ INLINE GEN Fp_center(GEN u, GEN p, GEN ps2) { return absi_cmp(u,ps2)<=0? icopy(u): subii(u,p); } /* x + y*z mod p */ INLINE GEN Fp_addmul(GEN x, GEN y, GEN z, GEN p) { pari_sp av; if (!signe(y) || !signe(z)) return Fp_red(x, p); if (!signe(x)) return Fp_mul(z,y, p); av = avma; return gerepileuptoint(av, modii(addii(x, mulii(y,z)), p)); } INLINE GEN Fp_mul(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+lg(b)+(lg(m)<<1)); p = mulii(a,b); avma = av; return modii(p,m); } INLINE GEN Fp_sqr(GEN a, GEN m) { pari_sp av=avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk((lg(a)+lg(m))<<1); p = sqri(a); avma = av; return modii(p,m); } INLINE GEN Fp_mulu(GEN a, ulong b, GEN m) { long l = lgefint(m); if (l == 3) { ulong mm = m[2]; return utoi( Fl_mul(umodiu(a, mm), b, mm) ); } else { pari_sp av = avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+1+(l<<1)); p = muliu(a,b); avma = av; return modii(p,m); } } INLINE GEN Fp_muls(GEN a, long b, GEN m) { long l = lgefint(m); if (l == 3) { ulong mm = m[2]; if (b < 0) { ulong t = Fl_mul(umodiu(a, mm), -b, mm); return t? utoipos(mm - t): gen_0; } else return utoi( Fl_mul(umodiu(a, mm), b, mm) ); } else { pari_sp av = avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+1+(l<<1)); p = mulis(a,b); avma = av; return modii(p,m); } } INLINE GEN Fp_inv(GEN a, GEN m) { GEN res; if (! invmod(a,m,&res)) pari_err_INV("Fp_inv", mkintmod(res,m)); return res; } INLINE GEN Fp_invsafe(GEN a, GEN m) { GEN res; if (! invmod(a,m,&res)) return NULL; return res; } INLINE GEN Fp_div(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+(lg(m)<<1)); p = mulii(a, Fp_inv(b,m)); avma = av; return modii(p,m); } INLINE GEN Flx_mulu(GEN x, ulong a, ulong p) { return Flx_Fl_mul(x,a%p,p); } /*******************************************************************/ /* */ /* ADDMULII / SUBMULII */ /* */ /*******************************************************************/ /* x - y*z */ INLINE GEN submulii(GEN x, GEN y, GEN z) { long lx = lgefint(x), ly, lz; pari_sp av; GEN t; if (lx == 2) { t = mulii(z,y); togglesign(t); return t; } ly = lgefint(y); if (ly == 2) return icopy(x); lz = lgefint(z); av = avma; (void)new_chunk(lx+ly+lz); /* HACK */ t = mulii(z, y); avma = av; return subii(x,t); } /* y*z - x */ INLINE GEN mulsubii(GEN y, GEN z, GEN x) { long lx = lgefint(x), ly, lz; pari_sp av; GEN t; if (lx == 2) return mulii(z,y); ly = lgefint(y); if (ly == 2) return negi(x); lz = lgefint(z); av = avma; (void)new_chunk(lx+ly+lz); /* HACK */ t = mulii(z, y); avma = av; return subii(t,x); } /* x - u*y */ INLINE GEN submuliu(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return icopy(x); av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); avma = av; return subii(x, y); } /* x + u*y */ INLINE GEN addmuliu(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return icopy(x); av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); avma = av; return addii(x, y); } /* x - u*y */ INLINE GEN submuliu_inplace(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); avma = av; return subii(x, y); } /* x + u*y */ INLINE GEN addmuliu_inplace(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); avma = av; return addii(x, y); } /* ux + vy */ INLINE GEN lincombii(GEN u, GEN v, GEN x, GEN y) { long lx = lgefint(x), ly; GEN p1, p2; pari_sp av; if (lx == 2) return mulii(v,y); ly = lgefint(y); if (ly == 2) return mulii(u,x); av = avma; (void)new_chunk(lx+ly+lgefint(u)+lgefint(v)); /* HACK */ p1 = mulii(u,x); p2 = mulii(v,y); avma = av; return addii(p1,p2); } /*******************************************************************/ /* */ /* GEN SUBTYPES */ /* */ /*******************************************************************/ INLINE int is_const_t(long t) { return (t < t_POLMOD); } INLINE int is_extscalar_t(long t) { return (t <= t_POL); } INLINE int is_intreal_t(long t) { return (t <= t_REAL); } INLINE int is_matvec_t(long t) { return (t >= t_VEC && t <= t_MAT); } INLINE int is_noncalc_t(long tx) { return (tx) >= t_LIST; } INLINE int is_rational_t(long t) { return (t == t_INT || t == t_FRAC); } INLINE int is_recursive_t(long t) { return lontyp[t]; } INLINE int is_scalar_t(long t) { return (t < t_POL); } INLINE int is_vec_t(long t) { return (t == t_VEC || t == t_COL); } /*******************************************************************/ /* */ /* TRANSCENDENTAL */ /* */ /*******************************************************************/ INLINE GEN sqrtr(GEN x) { long s = signe(x); if (s == 0) return real_0_bit(expo(x) >> 1); if (s >= 0) return sqrtr_abs(x); retmkcomplex(gen_0, sqrtr_abs(x)); } /* x^(1/n) */ INLINE GEN sqrtnr(GEN x, long n) { return mpexp(divrs(mplog(x), n)); } /*******************************************************************/ /* */ /* MISCELLANEOUS */ /* */ /*******************************************************************/ INLINE int ismpzero(GEN x) { return is_intreal_t(typ(x)) && !signe(x); } INLINE int isintzero(GEN x) { return typ(x) == t_INT && !signe(x); } INLINE int isint1(GEN x) { return typ(x)==t_INT && equali1(x); } INLINE int isintm1(GEN x){ return typ(x)==t_INT && equalim1(x);} INLINE int equali1(GEN n) { return (ulong) n[1] == (evallgefint(3UL) | evalsigne(1)) && n[2] == 1; } INLINE int equalim1(GEN n) { return (ulong) n[1] == (evallgefint(3UL) | evalsigne(-1)) && n[2] == 1; } /* works only for POSITIVE integers */ INLINE int is_pm1(GEN n) { return lgefint(n) == 3 && n[2] == 1; } INLINE int is_bigint(GEN n) { long l = lgefint(n); return l > 3 || (l == 3 && (n[2] & HIGHBIT)); } 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<> (BITS_IN_LONG - k); } /* assume x != 0 and x t_REAL, return an approximation to log2(|x|) */ INLINE double dbllog2r(GEN x) { return log2((double)(ulong)x[2]) + (double)(expo(x) - (BITS_IN_LONG-1)); } INLINE GEN mul_content(GEN cx, GEN cy) { if (!cx) return cy; if (!cy) return cx; return gmul(cx,cy); } INLINE GEN mul_denom(GEN dx, GEN dy) { if (!dx) return dy; if (!dy) return dx; return mulii(dx,dy); } /* POLYNOMIALS */ INLINE GEN constant_term(GEN x) { return signe(x)? gel(x,2): gen_0; } INLINE GEN leading_term(GEN x) { return lg(x) == 2? gen_0: gel(x,lg(x)-1); } INLINE ulong Flx_lead(GEN x) { return lg(x) == 2? 0: x[lg(x)-1]; } INLINE long degpol(GEN x) { return lg(x)-3; } INLINE long lgpol(GEN x) { return lg(x)-2; } INLINE long lgcols(GEN x) { return lg(gel(x,1)); } INLINE long nbrows(GEN x) { return lg(gel(x,1))-1; } INLINE GEN truecoeff(GEN x, long n) { return polcoeff0(x,n,-1); } INLINE GEN RgXQ_mul(GEN y, GEN x, GEN T) { return RgX_rem(RgX_mul(y, x), T); } INLINE GEN RgXQ_sqr(GEN x, GEN T) { return RgX_rem(RgX_sqr(x), T); } INLINE GEN ZXQ_mul(GEN y, GEN x, GEN T) { return ZX_rem(ZX_mul(y, x), T); } INLINE GEN ZXQ_sqr(GEN x, GEN T) { return ZX_rem(ZX_sqr(x), T); } INLINE GEN RgX_copy(GEN x) { long lx, i; GEN y = cgetg_copy(x, &lx); y[1] = x[1]; for (i = 2; i= 2; i--) gel(y,i) = gel(x,i); for (i = v+1; i >= 2; i--) gel(x,i) = gen_0; /* leave x[1] alone: it is correct */ x[0] = evaltyp(t_POL) | evallg(lx+v); return x; } /* LINEAR ALGEBRA */ INLINE GEN zv_to_ZV(GEN x) { return vecsmall_to_vec(x); } INLINE GEN zc_to_ZC(GEN x) { return vecsmall_to_col(x); } INLINE GEN ZV_to_zv(GEN x) { return vec_to_vecsmall(x); } INLINE GEN zx_to_zv(GEN x, long N) { return Flx_to_Flv(x,N); } INLINE GEN zv_to_zx(GEN x, long sv) { return Flv_to_Flx(x,sv); } INLINE GEN zm_to_zxV(GEN x, long sv) { return Flm_to_FlxV(x,sv); } INLINE GEN zero_zm(long x, long y) { return zero_Flm(x,y); } INLINE GEN zero_zv(long x) { return zero_Flv(x); } INLINE GEN zm_transpose(GEN x) { return Flm_transpose(x); } INLINE GEN zm_copy(GEN x) { return Flm_copy(x); } INLINE GEN zv_copy(GEN x) { return Flv_copy(x); } INLINE GEN row_zm(GEN x, long i) { return row_Flm(x,i); } INLINE GEN ZC_hnfrem(GEN x, GEN y) { return ZC_hnfremdiv(x,y,NULL); } INLINE GEN ZM_hnfrem(GEN x, GEN y) { return ZM_hnfdivrem(x,y,NULL); } INLINE GEN ZM_lll(GEN x, double D, long f) { return ZM_lll_norms(x,D,f,NULL); } INLINE void RgM_dimensions(GEN x, long *m, long *n) { *n = lg(x)-1; *m = *n? nbrows(x): 0; } INLINE GEN RgM_inv(GEN a) { return RgM_solve(a, NULL); } INLINE GEN RgM_shallowcopy(GEN x) { long l; GEN y = cgetg_copy(x, &l); while (--l > 0) gel(y,l) = leafcopy(gel(x,l)); return y; } INLINE GEN F2m_copy(GEN x) { return RgM_shallowcopy(x); } INLINE GEN Flm_copy(GEN x) { return RgM_shallowcopy(x); } /* divisibility: return 1 if y[i] | x[i] for all i, 0 otherwise. Assume * x,y are ZV of the same length */ INLINE int ZV_dvd(GEN x, GEN y) { long i, l = lg(x); for (i=1; i < l; i++) if ( ! dvdii( gel(x,i), gel(y,i) ) ) return 0; return 1; } /* Fq */ INLINE GEN Fq_red(GEN x, GEN T, GEN p) { return typ(x)==t_INT? Fp_red(x,p): FpXQ_red(x,T,p); } /* FpXQX */ INLINE GEN FpXQX_div(GEN x, GEN y, GEN T, GEN p) { return FpXQX_divrem(x, y, T, p, NULL); } INLINE GEN FlxqX_rem(GEN x, GEN y, GEN T, ulong p) { return FlxqX_divrem(x, y, T, p, ONLY_REM); } INLINE GEN FlxqX_div(GEN x, GEN y, GEN T, ulong p) { return FlxqX_divrem(x, y, T, p, NULL); } /* FqX */ INLINE GEN FqX_red(GEN z, GEN T, GEN p) { return T? FpXQX_red(z, T, p): FpX_red(z, p); } INLINE GEN FqX_add(GEN x,GEN y,GEN T,GEN p) { return T? FpXX_add(x,y,p): FpX_add(x,y,p); } INLINE GEN FqX_neg(GEN x,GEN T,GEN p) { return T? FpXX_neg(x,p): FpX_neg(x,p); } INLINE GEN FqX_sub(GEN x,GEN y,GEN T,GEN p) { return T? FpXX_sub(x,y,p): FpX_sub(x,y,p); } INLINE GEN FqX_Fp_mul(GEN P, GEN u, GEN T, GEN p) { return T? FpXX_Fp_mul(P, u, p): FpX_Fp_mul(P, u, p); } INLINE GEN FqX_Fq_mul(GEN P, GEN U, GEN T, GEN p) { return typ(U)==t_INT ? FqX_Fp_mul(P, U, T, p): FpXQX_FpXQ_mul(P, U, T, p); } INLINE GEN FqX_mul(GEN x, GEN y, GEN T, GEN p) { return T? FpXQX_mul(x, y, T, p): FpX_mul(x, y, p); } INLINE GEN FqX_mulu(GEN x, ulong y, GEN T, GEN p) { return T? FpXX_mulu(x, y, p): FpX_mulu(x, y, p); } INLINE GEN FqX_sqr(GEN x, GEN T, GEN p) { return T? FpXQX_sqr(x, T, p): FpX_sqr(x, 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 FqX_rem(GEN x, GEN y, GEN T, GEN p) { return T? FpXQX_rem(x,y,T,p): FpX_rem(x,y,p); } 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_gcd(GEN P,GEN Q,GEN T,GEN p) {return T? FpXQX_gcd(P,Q,T,p): FpX_gcd(P,Q,p);} INLINE GEN FqX_extgcd(GEN P,GEN Q,GEN T,GEN p, GEN *U, GEN *V) { return T? FpXQX_extgcd(P,Q,T,p,U,V): FpX_extgcd(P,Q,p,U,V); } /*FqXQ*/ INLINE GEN FqXQ_add(GEN x, GEN y, GEN S/*unused*/, GEN T, GEN p) { (void)S; return T? FpXX_add(x,y,p): FpX_add(x,y,p); } INLINE GEN FqXQ_sub(GEN x, GEN y, GEN S/*unused*/, GEN T, GEN p) { (void)S; return T? FpXX_sub(x,y,p): FpX_sub(x,y,p); } INLINE GEN FqXQ_div(GEN x, GEN y, GEN S, GEN T, GEN p) { return T? FpXQXQ_div(x,y,S,T,p): FpXQ_div(x,y,S,p); } INLINE GEN FqXQ_inv(GEN x, GEN S, GEN T, GEN p) { return T? FpXQXQ_inv(x,S,T,p): FpXQ_inv(x,S,p); } INLINE GEN FqXQ_invsafe(GEN x, GEN S, GEN T, GEN p) { return T? FpXQXQ_invsafe(x,S,T,p): FpXQ_inv(x,S,p); } INLINE GEN FqXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p) { return T? FpXQXQ_mul(x,y,S,T,p): FpXQ_mul(x,y,S,p); } INLINE GEN FqXQ_sqr(GEN x, GEN S, GEN T, GEN p) { return T? FpXQXQ_sqr(x,S,T,p): FpXQ_sqr(x,S,p); } INLINE GEN FqXQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p) { return T? FpXQXQ_pow(x,n,S,T,p): FpXQ_pow(x,n,S,p); } /*FpXQ*/ INLINE GEN FpXQ_add(GEN x,GEN y,GEN T/*unused*/,GEN p) { (void)T; return FpX_add(x,y,p); } INLINE GEN FpXQ_sub(GEN x,GEN y,GEN T/*unused*/,GEN p) { (void)T; return FpX_sub(x,y,p); } /*Flxq*/ INLINE GEN Flxq_add(GEN x,GEN y,GEN T/*unused*/,ulong p) { (void)T; return Flx_add(x,y,p); } INLINE GEN Flxq_sub(GEN x,GEN y,GEN T/*unused*/,ulong p) { (void)T; return Flx_sub(x,y,p); } /* F2x */ INLINE ulong F2x_coeff(GEN x,long v) { ulong u=(ulong)x[2+divsBIL(v)]; return (u>>remsBIL(v))&1UL; } INLINE void F2x_clear(GEN x,long v) { ulong* u=(ulong*)&x[2+divsBIL(v)]; *u&=~(1UL< 0) return powiu(x, n[2]); z = cgetg(3, t_FRAC); gel(z,1) = gen_1; gel(z,2) = powiu(x, n[2]); return z; } if (ln == 2) return gen_1; /* rare */ /* should never happen */ return powgi(x, n); /* overflow unless x = 0, 1, -1 */ } INLINE GEN powIs(long n) { switch(n & 3) { case 1: return mkcomplex(gen_0,gen_1); case 2: return gen_m1; case 3: return mkcomplex(gen_0,gen_m1); } return gen_1; } /*******************************************************************/ /* */ /* ASSIGNMENTS */ /* */ /*******************************************************************/ INLINE void mpexpz(GEN x, GEN z) { pari_sp av = avma; gaffect(mpexp(x), z); avma = av; } INLINE void mplogz(GEN x, GEN z) { pari_sp av = avma; gaffect(mplog(x), z); avma = av; } INLINE void mpcosz(GEN x, GEN z) { pari_sp av = avma; gaffect(mpcos(x), z); avma = av; } INLINE void mpsinz(GEN x, GEN z) { pari_sp av = avma; gaffect(mpsin(x), z); avma = av; } INLINE void gnegz(GEN x, GEN z) { pari_sp av = avma; gaffect(gneg(x), z); avma = av; } INLINE void gabsz(GEN x, long prec, GEN z) { pari_sp av = avma; gaffect(gabs(x,prec), z); avma = av; } INLINE void gaddz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gadd(x,y), z); avma = av; } INLINE void gsubz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gsub(x,y), z); avma = av; } INLINE void gmulz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gmul(x,y), z); avma = av; } INLINE void gdivz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gdiv(x,y), z); avma = av; } INLINE void gdiventz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gdivent(x,y), z); avma = av; } INLINE void gmodz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gmod(x,y), z); avma = av; } INLINE void gmul2nz(GEN x, long s, GEN z) { pari_sp av = avma; gaffect(gmul2n(x,s), z); avma = av; } INLINE void gshiftz(GEN x, long s, GEN z) { pari_sp av = avma; gaffect(gshift(x,s), z); avma = av; } /*******************************************************************/ /* */ /* ELLIPTIC CURVES */ /* */ /*******************************************************************/ INLINE GEN ell_get_a1(GEN e) { return gel(e,1); } INLINE GEN ell_get_a2(GEN e) { return gel(e,2); } INLINE GEN ell_get_a3(GEN e) { return gel(e,3); } INLINE GEN ell_get_a4(GEN e) { return gel(e,4); } INLINE GEN ell_get_a6(GEN e) { return gel(e,5); } INLINE GEN ell_get_b2(GEN e) { return gel(e,6); } INLINE GEN ell_get_b4(GEN e) { return gel(e,7); } INLINE GEN ell_get_b6(GEN e) { return gel(e,8); } INLINE GEN ell_get_b8(GEN e) { return gel(e,9); } INLINE GEN ell_get_c4(GEN e) { return gel(e,10); } INLINE GEN ell_get_c6(GEN e) { return gel(e,11); } INLINE GEN ell_get_disc(GEN e) { return gel(e,12); } INLINE GEN ell_get_j(GEN e) { return gel(e,13); } INLINE long ell_get_type(GEN e) { return mael(e,14,1); } INLINE GEN ellff_get_field(GEN x) { return gmael(x, 15, 1); } INLINE GEN ellff_get_a4a6(GEN x) { return gmael(x, 15, 2); } INLINE GEN ellQp_get_zero(GEN x) { return gmael(x, 15, 1); } 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 int ell_is_inf(GEN z) { return lg(z) == 2; } INLINE GEN ellinf(void) { return mkvec(gen_0); } /*******************************************************************/ /* */ /* ALGEBRAIC NUMBER THEORY */ /* */ /*******************************************************************/ 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 */ INLINE long pr_get_e(GEN pr) { return gel(pr,3)[2]; } INLINE long pr_get_f(GEN pr) { return gel(pr,4)[2]; } INLINE GEN pr_get_tau(GEN pr){ return gel(pr,5); } INLINE int pr_is_inert(GEN P) { return pr_get_f(P) == lg(pr_get_gen(P))-1; } INLINE GEN pr_norm(GEN pr) { return powiu(pr_get_p(pr), pr_get_f(pr)); } /* assume nf a genuine nf */ INLINE long nf_get_varn(GEN nf) { return varn(gel(nf,1)); } INLINE GEN nf_get_pol(GEN nf) { return gel(nf,1); } INLINE long nf_get_degree(GEN nf) { return degpol( nf_get_pol(nf) ); } INLINE long nf_get_r1(GEN nf) { GEN x = gel(nf,2); return itou(gel(x,1)); } INLINE long nf_get_r2(GEN nf) { GEN x = gel(nf,2); return itou(gel(x,2)); } INLINE GEN nf_get_disc(GEN nf) { return gel(nf,3); } INLINE GEN nf_get_index(GEN nf) { return gel(nf,4); } INLINE GEN nf_get_M(GEN nf) { return gmael(nf,5,1); } INLINE GEN nf_get_G(GEN nf) { return gmael(nf,5,2); } INLINE GEN nf_get_roundG(GEN nf) { return gmael(nf,5,3); } INLINE GEN 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_roots(GEN nf) { return gel(nf,6); } INLINE GEN nf_get_zk(GEN nf) { return gel(nf,7); } INLINE GEN nf_get_invzk(GEN nf) { return gel(nf,8); } INLINE void nf_get_sign(GEN nf, long *r1, long *r2) { GEN x = gel(nf,2); *r1 = itou(gel(x,1)); *r2 = itou(gel(x,2)); } INLINE GEN abgrp_get_no(GEN x) { return gel(x,1); } INLINE GEN abgrp_get_cyc(GEN x) { return gel(x,2); } INLINE GEN abgrp_get_gen(GEN x) { return gel(x,3); } INLINE GEN bnf_get_nf(GEN bnf) { return gel(bnf,7); } INLINE GEN bnf_get_clgp(GEN bnf) { return gmael(bnf,8,1); } INLINE GEN bnf_get_no(GEN bnf) { return abgrp_get_no(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_cyc(GEN bnf) { return abgrp_get_cyc(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_gen(GEN bnf) { return abgrp_get_gen(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_reg(GEN bnf) { return gmael(bnf,8,2); } INLINE GEN bnf_get_logfu(GEN bnf) { return gel(bnf,3); } INLINE GEN bnf_get_tuU(GEN bnf) { return gmael3(bnf,8,4,2); } INLINE long bnf_get_tuN(GEN bnf) { return gmael3(bnf,8,4,1)[2]; } INLINE GEN bnf_get_fu(GEN bnf) { GEN fu = bnf_get_fu_nocheck(bnf); if (typ(fu) == t_MAT) pari_err(e_MISC,"missing units in bnf"); return fu; } INLINE GEN bnf_get_fu_nocheck(GEN bnf) { return gmael(bnf,8,5); } INLINE GEN bnr_get_bnf(GEN bnr) { return gel(bnr,1); } INLINE GEN bnr_get_bid(GEN bnr) { return gel(bnr,2); } INLINE GEN bnr_get_mod(GEN bnr) { return gmael(bnr,2,1); } INLINE GEN bnr_get_nf(GEN bnr) { return gmael(bnr,1,7); } INLINE GEN bnr_get_clgp(GEN bnr) { return gel(bnr,5); } INLINE GEN bnr_get_no(GEN bnr) { return abgrp_get_no(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_cyc(GEN bnr) { return abgrp_get_cyc(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_gen_nocheck(GEN bnr) { return abgrp_get_gen(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_gen(GEN bnr) { GEN G = bnr_get_clgp(bnr); if (lg(G) != 4) pari_err(e_MISC,"missing bnr generators: please use bnrinit(,,1)"); return gel(G,3); } INLINE GEN bid_get_mod(GEN bid) { return gel(bid,1); } INLINE GEN bid_get_ideal(GEN bid) { return gmael(bid,1,1); } INLINE GEN bid_get_arch(GEN bid) { return gmael(bid,1,2); } INLINE GEN bid_get_grp(GEN bid) { return gel(bid,2); } INLINE GEN bid_get_no(GEN bid) { return abgrp_get_no(bid_get_grp(bid)); } INLINE GEN bid_get_cyc(GEN bid) { return abgrp_get_cyc(bid_get_grp(bid)); } INLINE GEN bid_get_gen_nocheck(GEN bid) { return abgrp_get_gen(bid_get_grp(bid)); } INLINE GEN bid_get_gen(GEN bid) { GEN G = bid_get_grp(bid); if (lg(G) != 4) pari_err(e_MISC,"missing bid generators. Use idealstar(,,2)"); return abgrp_get_gen(G); } INLINE GEN gal_get_pol(GEN gal) { return gel(gal,1); } INLINE GEN gal_get_p(GEN gal) { return gmael(gal,2,1); } INLINE GEN gal_get_e(GEN gal) { return gmael(gal,2,2); } INLINE GEN gal_get_mod(GEN gal) { return gmael(gal,2,3); } INLINE GEN gal_get_roots(GEN gal) { return gel(gal,3); } INLINE GEN gal_get_invvdm(GEN gal) { return gel(gal,4); } INLINE GEN gal_get_den(GEN gal) { return gel(gal,5); } INLINE GEN gal_get_group(GEN gal) { return gel(gal,6); } INLINE GEN gal_get_gen(GEN gal) { return gel(gal,7); } INLINE GEN gal_get_orders(GEN gal) { return gel(gal,8); } /* assume rnf a genuine rnf */ INLINE long rnf_get_degree(GEN rnf) { return degpol(rnf_get_pol(rnf)); } INLINE long 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_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);} INLINE GEN rnf_get_polabs(GEN rnf) { return gmael(rnf,11,1); } INLINE GEN rnf_get_pol(GEN rnf) { return gel(rnf,1); } INLINE GEN rnf_get_disc(GEN rnf) { return gel(rnf,3); } INLINE GEN rnf_get_index(GEN rnf) { return gel(rnf,4); } INLINE long rnf_get_varn(GEN rnf) { return varn(gel(rnf,1)); } INLINE GEN rnf_get_nfpol(GEN rnf) { return gmael(rnf,10,1); } INLINE long rnf_get_nfvarn(GEN rnf) { return varn(gmael(rnf,10,1)); } INLINE GEN rnf_get_zk(GEN rnf) { return gel(rnf,7); } INLINE GEN rnf_get_map(GEN rnf) { return gel(rnf,11); } INLINE GEN rnf_get_invzk(GEN rnf) { return gel(rnf,8); } /* I integral (not necessarily HNF), G ZM, rounded Cholesky form of a weighted * T2 matrix. Return m in I with T2(m) small */ INLINE GEN idealpseudomin(GEN I, GEN G) { GEN u = ZM_lll(ZM_mul(G, I), 0.99, LLL_IM); return ZM_ZC_mul(I, gel(u,1)); } /* I, G as in idealpseudomin. Return an irrational m in I with T2(m) small */ INLINE GEN idealpseudomin_nonscalar(GEN I, GEN G) { GEN u = ZM_lll(ZM_mul(G, I), 0.99, LLL_IM); GEN m = ZM_ZC_mul(I, gel(u,1)); if (ZV_isscalar(m) && lg(u) > 2) m = ZM_ZC_mul(I, gel(u,2)); return m; } INLINE GEN idealred_elt(GEN nf, GEN I) { pari_sp av = avma; GEN u = idealpseudomin(I, nf_get_roundG(nf)); return gerepileupto(av, u); } INLINE GEN idealred(GEN nf, GEN I) { return idealred0(nf, I, NULL); } /*******************************************************************/ /* */ /* CLOSURES */ /* */ /*******************************************************************/ INLINE long closure_arity(GEN C) { return C[1]; } 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); } INLINE GEN closure_get_data(GEN C) { return gel(C,4); } INLINE GEN closure_get_dbg(GEN C) { return gel(C,5); } INLINE GEN closure_get_text(GEN C) { return gel(C,6); } INLINE GEN closure_get_frame(GEN C) { return gel(C,7); } /*******************************************************************/ /* */ /* ERRORS */ /* */ /*******************************************************************/ INLINE long err_get_num(GEN e) { return e[1]; } INLINE GEN err_get_compo(GEN e, long i) { return gel(e, i+1); } INLINE void pari_err_BUG(const char *f) { pari_err(e_BUG,f); } INLINE void pari_err_CONSTPOL(const char *f) { pari_err(e_CONSTPOL, f); } INLINE void pari_err_COPRIME(const char *f, GEN x, GEN y) { pari_err(e_COPRIME, f,x,y); } INLINE void pari_err_DIM(const char *f) { pari_err(e_DIM, f); } INLINE void pari_err_FILE(const char *f, const char *g) { pari_err(e_FILE, f,g); } INLINE void pari_err_FLAG(const char *f) { pari_err(e_FLAG,f); } INLINE void pari_err_IMPL(const char *f) { pari_err(e_IMPL,f); } INLINE void pari_err_INV(const char *f, GEN x) { pari_err(e_INV,f,x); } INLINE void pari_err_IRREDPOL(const char *f, GEN x) { pari_err(e_IRREDPOL, f,x); } INLINE void pari_err_DOMAIN(const char *f, const char *v, const char *op, GEN l, GEN x) { pari_err(e_DOMAIN, f,v,op,l,x); } INLINE void pari_err_COMPONENT(const char *f, const char *op, GEN l, GEN x) { pari_err(e_COMPONENT, f,op,l,x); } INLINE void pari_err_MAXPRIME(ulong c) { pari_err(e_MAXPRIME, c); } INLINE void pari_err_OP(const char *f, GEN x, GEN y) { pari_err(e_OP, f,x,y); } INLINE void pari_err_OVERFLOW(const char *f) { pari_err(e_OVERFLOW, f); } INLINE void pari_err_PREC(const char *f) { pari_err(e_PREC,f); } INLINE void pari_err_PACKAGE(const char *f) { pari_err(e_PACKAGE,f); } INLINE void pari_err_PRIME(const char *f, GEN x) { pari_err(e_PRIME, f,x); } INLINE void pari_err_MODULUS(const char *f, GEN x, GEN y) { pari_err(e_MODULUS, f,x,y); } INLINE void pari_err_ROOTS0(const char *f) { pari_err(e_ROOTS0, f); } INLINE void pari_err_SQRTN(const char *f, GEN x) { pari_err(e_SQRTN, f,x); } INLINE void pari_err_TYPE(const char *f, GEN x) { pari_err(e_TYPE, f,x); } INLINE void pari_err_TYPE2(const char *f, GEN x, GEN y) { pari_err(e_TYPE2, f,x,y); } INLINE void pari_err_VAR(const char *f, GEN x, GEN y) { pari_err(e_VAR, f,x,y); } INLINE void pari_err_PRIORITY(const char *f, GEN x, const char *op, long v) { pari_err(e_PRIORITY, f,x,op,v); } pari-2.7.5/src/headers/paricom.h0000644000175000017500000000760712366172547015142 0ustar billbill/* Copyright (C) 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. */ /******************************************************************/ /* */ /* PARI header file (common to all versions) */ /* */ /******************************************************************/ #ifdef STMT_START /* perl headers */ # undef STMT_START #endif #ifdef STMT_END # undef STMT_END #endif /* STMT_START { statements; } STMT_END; * can be used as a single statement, as in * if (x) STMT_START { ... } STMT_END; else ... * [ avoid "dangling else" problem in macros ] */ #define STMT_START do #define STMT_END while (0) /*=====================================================================*/ /* pari_CATCH(numer) { * recovery * } pari_TRY { * code * } pari_ENDCATCH * will execute 'code', then 'recovery' if exception 'numer' is thrown * [ any exception if numer == CATCH_ALL ]. * pari_RETRY = as pari_TRY, but execute 'recovery', then 'code' again [still catching] */ extern THREAD jmp_buf *iferr_env; extern const long CATCH_ALL; #define pari_CATCH2(var,err) { \ jmp_buf *var=iferr_env; \ jmp_buf __env; \ iferr_env = &__env; \ if (setjmp(*iferr_env)) \ { \ GEN __iferr_data = pari_err_last(); \ iferr_env = var; \ if (err!=CATCH_ALL && err_get_num(__iferr_data) != err) \ pari_err(0, __iferr_data); #define pari_CATCH2_reset(var) (iferr_env = var) #define pari_ENDCATCH2(var) iferr_env = var; } } #define pari_CATCH(err) pari_CATCH2(__iferr_old,err) #define pari_RETRY } iferr_env = &__env; { #define pari_TRY } else { #define pari_CATCH_reset() pari_CATCH2_reset(__iferr_old) #define pari_ENDCATCH pari_ENDCATCH2(__iferr_old) extern const double LOG2, LOG10_2, LOG2_10; #ifndef PI # define PI (3.141592653589) #endif /* Common global variables: */ extern int new_galois_format, factor_add_primes, factor_proven; extern ulong DEBUGFILES, DEBUGLEVEL, DEBUGMEM, precdl; extern long DEBUGVAR; extern ulong pari_mt_nbthreads; extern THREAD GEN bernzone; extern GEN primetab; extern GEN gen_m1,gen_1,gen_2,gen_m2,ghalf,gen_0,gnil,err_e_STACK; extern THREAD VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending; extern const long lontyp[]; extern void (*cb_pari_ask_confirm)(const char *); extern int (*cb_pari_whatnow)(PariOUT *out, const char *, int); extern void (*cb_pari_sigint)(void); extern int (*cb_pari_handle_exception)(long); extern void (*cb_pari_pre_recover)(long); extern void (*cb_pari_err_recover)(long); 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 }; /* pari_init_opts */ enum { INIT_JMPm = 1, INIT_SIGm = 2, INIT_DFTm = 4, INIT_noPRIMEm = 8, INIT_noIMTm = 16 }; #ifndef HAS_EXP2 # undef exp2 # define exp2(x) (exp((double)(x)*LOG2)) #endif #ifndef HAS_LOG2 # undef log2 # define log2(x) (log((double)(x))/LOG2) #endif #define ONLY_REM ((GEN*)0x1L) #define ONLY_DIVIDES ((GEN*)0x2L) #define NEXT_PRIME_VIADIFF(p,d) STMT_START { (p) += *(d)++; } STMT_END #define PREC_PRIME_VIADIFF(p,d) STMT_START { (p) -= *--(d); } STMT_END #define NEXT_PRIME_VIADIFF_CHECK(p,d) STMT_START \ { if (!*(d)) pari_err_MAXPRIME(0); NEXT_PRIME_VIADIFF(p,d); } STMT_END pari-2.7.5/src/headers/paridecl.h0000644000175000017500000045541512531362535015267 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* DECLARATIONS of PUBLIC FUNCTIONS */ /* */ /*******************************************************************/ #include "parinf.h" /* black box groups */ struct bb_group { GEN (*mul)(void *E, GEN, GEN); GEN (*pow)(void *E, GEN, GEN); GEN (*rand)(void *E); ulong (*hash)(GEN); int (*equal)(GEN,GEN); int (*equal1)(GEN); GEN (*easylog)(void *E, GEN, GEN, GEN); }; /* black box fields */ struct bb_field { GEN (*red)(void *E ,GEN); GEN (*add)(void *E ,GEN, GEN); GEN (*mul)(void *E ,GEN, GEN); GEN (*neg)(void *E ,GEN); GEN (*inv)(void *E ,GEN); int (*equal0)(GEN); GEN (*s)(void *E, long); }; /* black box algebra */ struct bb_algebra { GEN (*red)(void *E, GEN x); GEN (*add)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); GEN (*one)(void *E); GEN (*zero)(void *E); }; /* OBSOLETE */ GEN bernvec(long nomb); GEN buchimag(GEN D, GEN c1, GEN c2, GEN gCO); GEN buchreal(GEN D, GEN gsens, GEN c1, GEN c2, GEN gRELSUP, long prec); GEN zidealstar(GEN nf, GEN x); GEN zidealstarinit(GEN nf, GEN x); GEN zidealstarinitgen(GEN nf, GEN x); GEN rootmod(GEN f, GEN p); GEN rootmod2(GEN f, GEN p); GEN factmod(GEN f, GEN p); GEN simplefactmod(GEN f, GEN p); GEN listcreate(void); void listkill(GEN list); GEN discrayabs(GEN bnr,GEN subgroup); GEN discrayabscond(GEN bnr,GEN subgroup); GEN discrayrel(GEN bnr,GEN subgroup); GEN discrayrelcond(GEN bnr,GEN subgroup); GEN isprincipalforce(GEN bnf,GEN x); GEN isprincipalgen(GEN bnf, GEN x); GEN isprincipalgenforce(GEN bnf,GEN x); /* F2x.c */ GEN F2c_to_Flc(GEN x); GEN F2c_to_ZC(GEN x); GEN F2c_to_mod(GEN x); GEN F2m_rowslice(GEN x, long a, long b); GEN F2m_to_Flm(GEN z); GEN F2m_to_ZM(GEN z); GEN F2m_to_mod(GEN z); void F2v_add_inplace(GEN x, GEN y); ulong F2v_dotproduct(GEN x, GEN y); GEN F2v_slice(GEN x, long a, long b); GEN F2x_F2xq_eval(GEN Q, GEN x, GEN T); GEN F2x_F2xqV_eval(GEN P, GEN V, GEN T); GEN F2x_1_add(GEN y); GEN F2x_add(GEN x, GEN y); GEN F2x_deflate(GEN x0, long d); long F2x_degree(GEN x); GEN F2x_deriv(GEN x); GEN F2x_divrem(GEN x, GEN y, GEN *pr); void F2x_even_odd(GEN p, GEN *pe, GEN *po); GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv); GEN F2x_gcd(GEN a, GEN b); GEN F2x_halfgcd(GEN a, GEN b); int F2x_issquare(GEN a); GEN F2x_mul(GEN x, GEN y); GEN F2x_rem(GEN x, GEN y); GEN F2x_shift(GEN y, long d); GEN F2x_sqr(GEN x); GEN F2x_sqrt(GEN x); GEN F2x_to_F2v(GEN x, long n); GEN F2x_to_Flx(GEN x); GEN F2x_to_ZX(GEN x); long F2x_valrem(GEN x, GEN *Z); GEN F2xC_to_ZXC(GEN x); GEN F2xV_to_F2m(GEN v, long n); GEN F2xq_Artin_Schreier(GEN a, GEN T); GEN FlxqXQV_autsum(GEN aut, long n, GEN S, GEN T, ulong p); GEN F2xq_autpow(GEN x, long n, GEN T); GEN F2xq_conjvec(GEN x, GEN T); GEN F2xq_div(GEN x,GEN y,GEN T); GEN F2xq_inv(GEN x, GEN T); GEN F2xq_invsafe(GEN x, GEN T); GEN F2xq_log(GEN a, GEN g, GEN ord, GEN T); GEN F2xq_matrix_pow(GEN y, long n, long m, GEN P); GEN F2xq_mul(GEN x, GEN y, GEN pol); GEN F2xq_order(GEN a, GEN ord, GEN T); GEN F2xq_pow(GEN x, GEN n, GEN pol); GEN F2xq_powu(GEN x, ulong n, GEN pol); GEN F2xq_powers(GEN x, long l, GEN T); GEN F2xq_sqr(GEN x,GEN pol); GEN F2xq_sqrt(GEN a, GEN T); GEN F2xq_sqrt_fast(GEN c, GEN sqx, GEN T); GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta); ulong F2xq_trace(GEN x, GEN T); GEN Flm_to_F2m(GEN x); GEN Flv_to_F2v(GEN x); GEN Flx_to_F2x(GEN x); GEN Rg_to_F2xq(GEN x, GEN T); GEN RgM_to_F2m(GEN x); GEN RgV_to_F2v(GEN x); GEN RgX_to_F2x(GEN x); GEN Z_to_F2x(GEN x, long v); GEN ZM_to_F2m(GEN x); GEN ZV_to_F2v(GEN x); GEN ZX_to_F2x(GEN x); GEN ZXT_to_FlxT(GEN z, ulong p); GEN ZXX_to_F2xX(GEN B, long v); GEN gener_F2xq(GEN T, GEN *po); const struct bb_field *get_F2xq_field(void **E, GEN T); GEN random_F2x(long d, long vs); /* F2xqE.c */ GEN F2xq_ellcard(GEN a2, GEN a6, GEN T); GEN F2xq_ellgens(GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T); GEN F2xq_ellgroup(GEN a2, GEN a6, GEN N, GEN T, GEN *pt_m); GEN F2xqE_add(GEN P, GEN Q, GEN a2, GEN T); GEN F2xqE_changepoint(GEN x, GEN ch, GEN T); GEN F2xqE_changepointinv(GEN x, GEN ch, GEN T); GEN F2xqE_dbl(GEN P, GEN a2, GEN T); GEN F2xqE_log(GEN a, GEN b, GEN o, GEN a2, GEN T); GEN F2xqE_mul(GEN P, GEN n, GEN a2, GEN T); GEN F2xqE_neg(GEN P, GEN a2, GEN T); GEN F2xqE_order(GEN z, GEN o, GEN a2, GEN T); GEN F2xqE_sub(GEN P, GEN Q, GEN a2, GEN T); GEN F2xqE_tatepairing(GEN t, GEN s, GEN m, GEN a2, GEN T); GEN F2xqE_weilpairing(GEN t, GEN s, GEN m, GEN a2, GEN T); 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); /* Flx.c */ GEN Fl_to_Flx(ulong x, long sv); 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_polint(GEN xa, GEN ya, ulong p, long vs); GEN Flv_roots_to_pol(GEN a, ulong p, long vs); GEN Fly_to_FlxY(GEN B, long v); 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_Flxq_eval(GEN f,GEN x,GEN T,ulong p); GEN Flx_FlxqV_eval(GEN f,GEN x,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); GEN Flx_double(GEN y, ulong p); 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); 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); GEN Flx_get_red(GEN T, ulong p); GEN Flx_halfgcd(GEN a, GEN b, ulong p); 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_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_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); ulong Flx_resultant(GEN a, GEN b, ulong p); GEN Flx_shift(GEN a, long n); GEN Flx_splitting(GEN p, long k); GEN Flx_sqr(GEN x, ulong p); GEN Flx_sub(GEN x, GEN y, ulong p); GEN Flx_to_Flv(GEN x, long N); GEN Flx_to_FlxX(GEN z, long v); GEN Flx_to_ZX(GEN z); GEN Flx_to_ZX_inplace(GEN z); GEN Flx_triple(GEN y, ulong p); long Flx_val(GEN x); long Flx_valrem(GEN x, GEN *Z); GEN FlxC_to_ZXC(GEN x); GEN FlxM_Flx_add_shallow(GEN x, GEN y, ulong p); GEN FlxM_to_ZXM(GEN z); GEN FlxT_red(GEN z, ulong p); GEN FlxV_to_ZXV(GEN x); GEN FlxV_Flc_mul(GEN V, GEN W, ulong p); GEN FlxV_red(GEN z, ulong p); GEN FlxV_to_Flm(GEN v, long n); GEN FlxX_Fl_mul(GEN x, ulong y, ulong p); GEN FlxX_Flx_add(GEN y, GEN x, ulong p); GEN FlxX_Flx_mul(GEN x, GEN y, ulong p); GEN FlxX_add(GEN P, GEN Q, ulong p); GEN FlxX_double(GEN x, ulong p); GEN FlxX_neg(GEN x, ulong p); GEN FlxX_sub(GEN P, GEN Q, ulong p); GEN FlxX_swap(GEN x, long n, long ws); GEN FlxX_renormalize(GEN x, long lx); GEN FlxX_shift(GEN a, long n); GEN FlxX_to_Flm(GEN v, long n); GEN FlxX_to_FlxC(GEN x, long N, long sv); 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_Flx_div(GEN x, GEN y, ulong p); GEN FlxY_evalx(GEN Q, ulong x, ulong p); 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); GEN Flxq_charpoly(GEN x, GEN T, ulong p); GEN Flxq_conjvec(GEN x, GEN T, ulong p); GEN Flxq_div(GEN x, GEN y, GEN T, ulong p); GEN Flxq_inv(GEN x,GEN T,ulong p); GEN Flxq_invsafe(GEN x, GEN T, ulong p); int Flxq_issquare(GEN x, GEN T, ulong p); int Flxq_is2npower(GEN x, long n, GEN T, ulong p); GEN Flxq_log(GEN a, GEN g, GEN ord, GEN T, ulong p); GEN Flxq_lroot(GEN a, GEN T, long p); GEN Flxq_lroot_fast(GEN a, GEN sqx, GEN T, long p); GEN Flxq_matrix_pow(GEN y, long n, long m, GEN P, ulong l); GEN Flxq_minpoly(GEN x, GEN T, ulong p); GEN Flxq_mul(GEN x, GEN y, GEN T, ulong p); ulong Flxq_norm(GEN x, GEN T, ulong p); GEN Flxq_order(GEN a, GEN ord, GEN T, ulong p); GEN Flxq_pow(GEN x, GEN n, GEN T, ulong p); GEN Flxq_powu(GEN x, ulong n, GEN T, ulong p); GEN Flxq_powers(GEN x, long l, GEN T, ulong p); GEN Flxq_sqr(GEN y,GEN T,ulong p); GEN Flxq_sqrt(GEN a, GEN T, ulong p); GEN Flxq_sqrtn(GEN a, GEN n, GEN T, ulong p, GEN *zetan); ulong Flxq_trace(GEN x, GEN T, ulong p); GEN FlxqV_dotproduct(GEN x, GEN y, GEN T, ulong p); GEN FlxqV_roots_to_pol(GEN V, GEN T, ulong p, long v); GEN FlxqX_FlxqXQ_eval(GEN Q, GEN x, GEN S, GEN T, ulong p); GEN FlxqX_FlxqXQV_eval(GEN P, GEN V, GEN S, GEN T, ulong p); GEN FlxqX_Flxq_mul(GEN P, GEN U, GEN T, ulong p); GEN FlxqX_Flxq_mul_to_monic(GEN P, GEN U, GEN T, ulong p); GEN FlxqX_divrem(GEN x, GEN y, GEN T, ulong p, GEN *pr); GEN FlxqX_extgcd(GEN a, GEN b, GEN T, ulong p, GEN *ptu, GEN *ptv); GEN FlxqX_gcd(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_invBarrett(GEN T, GEN Q, ulong p); GEN FlxqX_mul(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_normalize(GEN z, GEN T, ulong p); GEN FlxqX_pow(GEN V, long n, GEN T, ulong p); GEN FlxqX_red(GEN z, GEN T, ulong p); GEN FlxqX_rem_Barrett(GEN x, GEN mg, GEN T, GEN Q, ulong p); GEN FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_sqr(GEN x, GEN T, ulong p); GEN FlxqXQ_div(GEN x, GEN y, GEN S, GEN T, ulong p); GEN FlxqXQ_inv(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_invsafe(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_matrix_pow(GEN x, long n, long m, GEN S, GEN T, ulong p); GEN FlxqXQ_mul(GEN x, GEN y, GEN S, GEN T, ulong p); GEN FlxqXQ_pow(GEN x, GEN n, GEN S, GEN T, ulong p); GEN FlxqXQ_powers(GEN x, long n, GEN S, GEN T, ulong p); GEN FlxqXQ_sqr(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQV_autpow(GEN x, long n, GEN S, GEN T, ulong p); GEN FlxqXV_prod(GEN V, GEN T, ulong p); GEN Kronecker_to_FlxqX(GEN z, GEN T, ulong p); ulong Rg_to_F2(GEN x); ulong Rg_to_Fl(GEN x, ulong p); GEN Rg_to_Flxq(GEN x, GEN T, ulong p); GEN RgX_to_Flx(GEN x, ulong p); GEN Z_to_Flx(GEN x, ulong p, long v); GEN ZX_to_Flx(GEN x, ulong p); GEN ZXV_to_FlxV(GEN v, ulong p); GEN ZXX_to_FlxX(GEN B, ulong p, long v); GEN ZXXV_to_FlxXV(GEN V, ulong p, long v); GEN gener_Flxq(GEN T, ulong p, GEN *o); long get_Flx_degree(GEN T); GEN get_Flx_mod(GEN T); long get_Flx_var(GEN T); 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 zxX_to_Kronecker(GEN P, GEN Q); /* FlxqE.c */ 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); 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); GEN FlxqE_dbl(GEN P, GEN a4, GEN T, ulong p); GEN FlxqE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, ulong p); GEN FlxqE_mul(GEN P, GEN n, GEN a4, GEN T, ulong p); GEN FlxqE_neg(GEN P, GEN T, ulong p); GEN FlxqE_order(GEN z, GEN o, GEN a4, GEN T, ulong p); GEN FlxqE_sub(GEN P, GEN Q, GEN a4, GEN T, ulong p); GEN FlxqE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN T, ulong p); GEN FlxqE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN T, ulong p); const struct bb_group * get_FlxqE_group(void **E, GEN a4, GEN a6, GEN T, ulong p); GEN RgE_to_FlxqE(GEN x, GEN T, ulong p); 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); 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); 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); GEN FpE_changepointinv(GEN x, GEN ch, GEN p); GEN FpE_dbl(GEN P, GEN a4, GEN p); GEN FpE_log(GEN a, GEN b, GEN o, GEN a4, GEN p); GEN FpE_mul(GEN P, GEN n, GEN a4, GEN p); GEN FpE_neg(GEN P, GEN p); GEN FpE_order(GEN z, GEN o, GEN a4, GEN p); GEN FpE_sub(GEN P, GEN Q, GEN a4, GEN p); GEN FpE_to_mod(GEN P, GEN p); GEN FpE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN p); GEN FpE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN p); GEN FpXQ_ellcard(GEN a4, GEN a6, GEN T, GEN p); 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); 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); GEN FpXQE_dbl(GEN P, GEN a4, GEN T, GEN p); GEN FpXQE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, GEN p); GEN FpXQE_mul(GEN P, GEN n, GEN a4, GEN T, GEN p); GEN FpXQE_neg(GEN P, GEN T, GEN p); GEN FpXQE_order(GEN z, GEN o, GEN a4, GEN T, GEN p); GEN FpXQE_sub(GEN P, GEN Q, GEN a4, GEN T, GEN p); GEN FpXQE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN T, GEN p); GEN FpXQE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN T, GEN p); GEN Fq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, GEN p); GEN RgE_to_FpE(GEN x, GEN p); 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); /* FpX.c */ int Fp_issquare(GEN x, GEN p); GEN Fp_FpX_sub(GEN x, GEN y, GEN p); GEN Fp_FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p); GEN FpV_inv(GEN x, GEN p); GEN FpV_roots_to_pol(GEN V, GEN p, long v); GEN FpX_Fp_add(GEN x, GEN y, GEN p); GEN FpX_Fp_add_shallow(GEN y,GEN x,GEN p); GEN FpX_Fp_mul(GEN x, GEN y, GEN p); GEN FpX_Fp_mul_to_monic(GEN y,GEN x,GEN p); GEN FpX_Fp_mulspec(GEN y,GEN x,GEN p,long ly); 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_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_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_gcd(GEN x, GEN y, GEN p); GEN FpX_get_red(GEN T, 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_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_red(GEN z, GEN p); GEN FpX_rem(GEN x, GEN y, GEN p); GEN FpX_rescale(GEN P, GEN h, GEN p); 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 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); GEN FpXQ_charpoly(GEN x, GEN T, GEN p); GEN FpXQ_conjvec(GEN x, GEN T, GEN p); GEN FpXQ_div(GEN x,GEN y,GEN T,GEN p); GEN FpXQ_inv(GEN x,GEN T,GEN p); GEN FpXQ_invsafe(GEN x, GEN T, GEN p); int FpXQ_issquare(GEN x, GEN T, GEN p); GEN FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p); GEN FpXQ_matrix_pow(GEN y, long n, long m, GEN P, GEN l); GEN FpXQ_minpoly(GEN x, GEN T, GEN p); GEN FpXQ_mul(GEN y,GEN x,GEN T,GEN p); GEN FpXQ_norm(GEN x, GEN T, GEN p); GEN FpXQ_order(GEN a, GEN ord, GEN T, GEN p); GEN FpXQ_pow(GEN x, GEN n, GEN T, GEN p); GEN FpXQ_powu(GEN x, ulong n, GEN T, GEN p); GEN FpXQ_powers(GEN x, long l, GEN T, GEN p); GEN FpXQ_red(GEN x, GEN T, GEN p); GEN FpXQ_sqr(GEN y, GEN T, GEN p); 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 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 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); GEN gener_FpXQ_local(GEN T, GEN p, GEN L); long get_FpX_degree(GEN T); GEN get_FpX_mod(GEN T); long get_FpX_var(GEN T); const struct bb_group *get_FpXQ_star(void **E, GEN T, GEN p); GEN random_FpX(long d, long v, GEN p); /* FpX_factor.c */ GEN F2x_factor(GEN f); int F2x_is_irred(GEN f); void F2xV_to_FlxV_inplace(GEN v); void F2xV_to_ZXV_inplace(GEN v); int Flx_is_irred(GEN f, ulong p); GEN Flx_degfact(GEN f, ulong p); GEN Flx_factor(GEN f, ulong p); 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); 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); long FlxqX_nbroots(GEN f, GEN T, ulong p); void FlxV_to_ZXV_inplace(GEN v); GEN FpX_degfact(GEN f, GEN p); int FpX_is_irred(GEN f, GEN p); int FpX_is_totally_split(GEN f, GEN p); GEN FpX_factor(GEN f, GEN p); GEN FpX_factorff(GEN P, GEN T, GEN p); long FpX_nbfact(GEN f, GEN p); 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 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); GEN FpXQXQ_halfFrobenius(GEN a, GEN S, GEN T, GEN p); GEN FqX_deriv(GEN f, GEN T, GEN p); GEN FqX_factor(GEN x, GEN T, GEN p); long FqX_is_squarefree(GEN P, GEN T, GEN p); long FqX_nbfact(GEN u, GEN T, GEN p); long FqX_nbroots(GEN f, GEN T, GEN p); GEN FqX_roots(GEN f, GEN T, GEN p); GEN factcantor(GEN x, GEN p); GEN factorff(GEN f, GEN p, GEN a); GEN factormod0(GEN f, GEN p,long flag); GEN polrootsff(GEN f, GEN p, GEN T); GEN rootmod0(GEN f, GEN p,long flag); /* FpXX.c */ 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_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_extgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv); 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_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); GEN FpXQX_sqr(GEN x, GEN T, GEN p); GEN FpXQXQ_div(GEN x,GEN y,GEN S, GEN T,GEN p); GEN FpXQXQ_inv(GEN x, GEN S, GEN T,GEN p); GEN FpXQXQ_invsafe(GEN x, GEN S, GEN T, GEN p); GEN FpXQXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p); GEN FpXQXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p); GEN FpXQXQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p); GEN FpXQXQ_powers(GEN x, long n, GEN S, GEN T, GEN p); GEN FpXQXQ_sqr(GEN x, GEN S, GEN T, GEN p); GEN FpXQXQV_autpow(GEN aut, long n, GEN S, GEN T, GEN p); GEN FpXQXQV_autsum(GEN aut, long n, GEN S, GEN T, GEN p); GEN FpXQXV_prod(GEN V, GEN Tp, GEN p); GEN FpXX_Fp_mul(GEN x, GEN y, GEN p); GEN FpXX_FpX_mul(GEN x, GEN y, GEN p); GEN FpXX_add(GEN x, GEN y, GEN p); GEN FpXX_mulu(GEN P, ulong u, GEN p); 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_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); 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); /* FpV.c */ GEN F2m_F2c_mul(GEN x, GEN y); GEN F2m_mul(GEN x, GEN y); GEN F2m_powu(GEN x, ulong n); GEN Flc_Fl_div(GEN x, ulong y, ulong p); void Flc_Fl_div_inplace(GEN x, ulong y, ulong p); GEN Flc_Fl_mul(GEN x, ulong y, ulong p); void Flc_Fl_mul_inplace(GEN x, ulong y, ulong p); void Flc_Fl_mul_part_inplace(GEN x, ulong y, ulong p, long l); GEN Flc_to_mod(GEN z, ulong pp); 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_center(GEN z, ulong p, ulong ps2); GEN Flm_mul(GEN x, GEN y, ulong p); GEN Flm_neg(GEN y, ulong p); GEN Flm_powu(GEN x, ulong n, ulong p); GEN Flm_to_mod(GEN z, ulong pp); 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); 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); ulong Flv_sum(GEN x, ulong p); 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); GEN FpC_red(GEN z, GEN p); GEN FpC_to_mod(GEN z, 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); 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); GEN FpM_to_mod(GEN z, GEN p); GEN FpMs_FpC_mul(GEN M, GEN B, GEN p); GEN FpMs_FpCs_solve(GEN M, GEN B, long nbrow, GEN p); GEN FpMs_FpCs_solve_safe(GEN M, GEN A, long nbrow, GEN p); GEN FpMs_leftkernel_elt(GEN M, long nbrow, GEN p); GEN FpC_add(GEN x, GEN y, GEN p); GEN FpC_sub(GEN x, GEN y, GEN p); GEN FpV_FpMs_mul(GEN B, GEN M, GEN p); GEN FpV_add(GEN x, GEN y, GEN p); GEN FpV_sub(GEN x, GEN y, GEN p); GEN FpV_dotproduct(GEN x, GEN y, GEN p); GEN FpV_dotsquare(GEN x, GEN p); GEN FpV_red(GEN z, GEN p); GEN FpV_to_mod(GEN z, GEN p); GEN FpVV_to_mod(GEN z, GEN p); GEN FpX_to_mod(GEN z, GEN p); GEN ZV_zMs_mul(GEN B, GEN M); GEN ZpMs_ZpCs_solve(GEN M, GEN B, long nbrow, GEN p, long e); GEN gen_FpM_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p); GEN gen_ZpM_Dixon(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e); GEN gen_matid(long n, void *E, const struct bb_field *S); GEN matid_F2m(long n); GEN matid_Flm(long n); GEN matid_F2xqM(long n, GEN T); GEN matid_FlxqM(long n, GEN T, ulong p); 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); /* Hensel.c */ 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_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 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_sqrtnlift(GEN b, GEN n, GEN a, 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, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)); GEN 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)); GEN polhensellift(GEN pol, GEN fct, GEN p, long exp); ulong quadratic_prec_mask(long n); /* QX_factor.c */ GEN QX_factor(GEN x); GEN ZX_factor(GEN x); long ZX_is_irred(GEN x); GEN ZX_squff(GEN f, GEN *ex); GEN polcyclofactors(GEN f); long poliscyclo(GEN f); long poliscycloprod(GEN f); /* RgV.c */ GEN RgC_Rg_add(GEN x, GEN y); GEN RgC_Rg_div(GEN x, GEN y); 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); GEN RgC_neg(GEN x); GEN RgC_sub(GEN x, GEN y); GEN RgM_Rg_add(GEN x, GEN y); GEN RgM_Rg_add_shallow(GEN x, GEN y); GEN RgM_Rg_div(GEN x, GEN y); GEN RgM_Rg_mul(GEN x, GEN y); GEN RgM_Rg_sub(GEN x, GEN y); GEN RgM_Rg_sub_shallow(GEN x, GEN y); GEN RgM_RgC_mul(GEN x, GEN y); GEN RgM_RgV_mul(GEN x, GEN y); GEN RgM_add(GEN x, GEN y); GEN RgM_det_triangular(GEN x); int RgM_is_ZM(GEN x); int RgM_isdiagonal(GEN x); int RgM_isidentity(GEN x); int RgM_isscalar(GEN x, GEN s); GEN RgM_mul(GEN x, GEN y); GEN RgM_multosym(GEN x, GEN y); 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_transmul(GEN x, GEN y); GEN RgM_transmultosym(GEN x, GEN y); GEN RgM_zc_mul(GEN x, GEN y); GEN RgM_zm_mul(GEN x, GEN y); GEN RgMrow_RgC_mul(GEN x, GEN y, long i); GEN RgV_RgM_mul(GEN x, GEN y); GEN RgV_RgC_mul(GEN x, GEN y); GEN RgV_Rg_mul(GEN x, GEN y); GEN RgV_add(GEN x, GEN y); GEN RgV_dotproduct(GEN x, GEN y); GEN RgV_dotsquare(GEN x); int RgV_is_ZMV(GEN V); long RgV_isin(GEN v, GEN x); GEN RgV_neg(GEN x); GEN RgV_sub(GEN x, GEN y); GEN RgV_sum(GEN v); GEN RgV_sumpart(GEN v, long n); GEN RgV_sumpart2(GEN v, long m, long n); GEN RgV_zc_mul(GEN x, GEN y); GEN RgV_zm_mul(GEN x, GEN y); GEN RgX_RgM_eval(GEN x, GEN y); GEN RgX_RgMV_eval(GEN x, GEN y); int isdiagonal(GEN x); GEN matid(long n); GEN scalarcol(GEN x, long n); GEN scalarcol_shallow(GEN x, long n); GEN scalarmat(GEN x, long n); GEN scalarmat_shallow(GEN x, long n); GEN scalarmat_s(long x, long n); /* RgX.c */ GEN Kronecker_to_mod(GEN z, GEN pol); GEN QX_ZXQV_eval(GEN P, GEN V, GEN dV); GEN QXQ_powers(GEN a, long n, GEN T); GEN QXQX_to_mod_shallow(GEN z, GEN T); 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 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_Rg_add(GEN y, GEN x); GEN RgX_Rg_add_shallow(GEN y, GEN x); GEN RgX_Rg_div(GEN y, GEN x); GEN RgX_Rg_divexact(GEN x, GEN y); GEN RgX_Rg_mul(GEN y, GEN x); GEN RgX_Rg_sub(GEN y, GEN x); GEN RgX_add(GEN x, GEN y); GEN RgX_blocks(GEN P, long n, long m); GEN RgX_deflate(GEN x0, long d); GEN RgX_deriv(GEN x); GEN RgX_div_by_X_x(GEN a, GEN x, GEN *r); GEN RgX_divrem(GEN x,GEN y,GEN *r); GEN RgX_divs(GEN y, long x); long RgX_equal(GEN x, GEN y); 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_pseudodivrem(GEN x, GEN y, GEN *ptr); GEN RgX_pseudorem(GEN x, GEN y); GEN RgX_recip(GEN x); GEN RgX_recip_shallow(GEN x); GEN RgX_renormalize_lg(GEN x, long lx); GEN RgX_rescale(GEN P, GEN h); GEN RgX_rotate_shallow(GEN P, long k, long p); 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_translate(GEN P, GEN c); GEN RgX_unscale(GEN P, GEN h); GEN Rg_RgX_sub(GEN x, GEN y); GEN ZX_translate(GEN P, GEN c); GEN ZX_unscale(GEN P, GEN h); GEN ZX_unscale_div(GEN P, GEN h); int ZXQX_dvd(GEN x, GEN y, GEN T); long brent_kung_optpow(long d, long n, long m); GEN gen_bkeval(GEN Q, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)); 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)); /* 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 ZC_ZV_mul(GEN x, GEN y); GEN ZC_Z_add(GEN x, GEN y); GEN ZC_Z_divexact(GEN X, GEN c); GEN ZC_Z_mul(GEN X, GEN c); 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); 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); GEN ZC_reducemodlll(GEN x,GEN y); 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_divexact(GEN X, GEN c); GEN ZM_Z_mul(GEN X, GEN c); GEN ZM_add(GEN x, GEN y); GEN ZM_copy(GEN x); GEN ZM_det_triangular(GEN mat); int ZM_equal(GEN A, GEN B); GEN ZM_hnfdivrem(GEN x, GEN y, GEN *Q); int ZM_ishnf(GEN x); int ZM_isidentity(GEN x); long ZM_max_lg(GEN x); GEN ZM_mul(GEN x, GEN y); GEN ZM_multosym(GEN x, GEN y); GEN ZM_neg(GEN x); GEN ZM_nm_mul(GEN x, GEN y); 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_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_transmultosym(GEN x, GEN y); GEN ZMV_to_zmV(GEN z); void ZM_togglesign(GEN M); GEN ZM_zc_mul(GEN x, GEN y); GEN ZM_zm_mul(GEN x, GEN y); GEN ZMrow_ZC_mul(GEN x, GEN y, long i); GEN ZV_ZM_mul(GEN x, GEN y); int ZV_abscmp(GEN x, GEN y); int ZV_cmp(GEN x, GEN y); GEN ZV_content(GEN x); GEN ZV_dotproduct(GEN x,GEN y); GEN ZV_dotsquare(GEN x); int ZV_equal(GEN V, GEN W); int ZV_equal0(GEN V); long ZV_max_lg(GEN x); void ZV_neg_inplace(GEN M); GEN ZV_prod(GEN v); GEN ZV_sum(GEN v); GEN ZV_to_Flv(GEN x, ulong p); GEN ZV_to_nv(GEN z); void ZV_togglesign(GEN M); GEN gram_matrix(GEN M); GEN nm_Z_mul(GEN X, GEN c); GEN zm_mul(GEN x, GEN y); GEN zm_to_Flm(GEN z, ulong p); GEN zm_to_ZM(GEN z); GEN zm_zc_mul(GEN x, GEN y); GEN zmV_to_ZMV(GEN z); long zv_content(GEN x); long zv_dotproduct(GEN x, GEN y); int zv_equal(GEN V, GEN W); int zv_equal0(GEN V); GEN zv_neg(GEN x); GEN zv_neg_inplace(GEN M); long zv_prod(GEN v); GEN zv_prod_Z(GEN v); long zv_sum(GEN v); GEN zv_to_Flv(GEN z, ulong p); GEN zv_z_mul(GEN v, long n); int zvV_equal(GEN V, GEN W); /* ZX.c */ void RgX_check_QX(GEN x, const char *s); void RgX_check_ZX(GEN x, const char *s); void RgX_check_ZXX(GEN x, const char *s); GEN Z_ZX_sub(GEN x, GEN y); GEN ZX_Z_add(GEN y,GEN x); GEN ZX_Z_add_shallow(GEN y, GEN x); GEN ZX_Z_divexact(GEN y,GEN x); GEN ZX_Z_mul(GEN y,GEN x); 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); int ZX_equal(GEN V, GEN W); GEN ZX_eval1(GEN x); long ZX_max_lg(GEN x); GEN ZX_mod_Xnm1(GEN T, ulong n); GEN ZX_mul(GEN x, GEN y); GEN ZX_mulspec(GEN a, GEN b, long na, long nb); 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_rescale(GEN P, GEN h); GEN ZX_rescale_lt(GEN P); GEN ZX_shifti(GEN x, long n); GEN ZX_sqr(GEN x); GEN ZX_sqrspec(GEN a, long na); GEN ZX_sub(GEN x, GEN y); long ZX_val(GEN x); long ZX_valrem(GEN x, GEN *Z); GEN ZXT_remi2n(GEN z, long n); GEN ZXV_Z_mul(GEN y, GEN x); 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); long ZXX_max_lg(GEN x); GEN ZXX_renormalize(GEN x, long lx); GEN ZXX_to_Kronecker(GEN P, long n); GEN ZXX_to_Kronecker_spec(GEN P, long lP, long n); GEN scalar_ZX(GEN x, long v); GEN scalar_ZX_shallow(GEN x, long v); GEN zx_to_ZX(GEN z); /* alglin1.c */ GEN F2m_F2c_gauss(GEN a, GEN b); GEN F2m_F2c_invimage(GEN A, GEN y); GEN F2m_deplin(GEN x); ulong F2m_det(GEN x); ulong F2m_det_sp(GEN x); GEN F2m_gauss(GEN a, GEN b); GEN F2m_image(GEN x); GEN F2m_indexrank(GEN x); GEN F2m_inv(GEN x); GEN F2m_invimage(GEN A, GEN B); GEN F2m_ker(GEN x); GEN F2m_ker_sp(GEN x, long deplin); long F2m_rank(GEN x); GEN F2m_suppl(GEN x); GEN F2xqM_F2xqC_mul(GEN a, GEN b, GEN T); GEN F2xqM_det(GEN a, GEN T); GEN F2xqM_ker(GEN x, GEN T); GEN F2xqM_image(GEN x, GEN T); GEN F2xqM_inv(GEN a, GEN T); GEN F2xqM_mul(GEN a, GEN b, GEN T); long F2xqM_rank(GEN x, GEN T); GEN Flm_Flc_gauss(GEN a, GEN b, ulong p); GEN Flm_Flc_invimage(GEN mat, GEN y, ulong p); GEN Flm_deplin(GEN x, ulong p); ulong Flm_det(GEN x, ulong p); ulong Flm_det_sp(GEN x, ulong p); GEN Flm_gauss(GEN a, GEN b, ulong p); GEN Flm_image(GEN x, ulong p); GEN Flm_invimage(GEN m, GEN v, ulong p); GEN Flm_indexrank(GEN x, ulong p); GEN Flm_inv(GEN x, ulong p); GEN Flm_ker(GEN x, ulong p); GEN Flm_ker_sp(GEN x, ulong p, long deplin); long Flm_rank(GEN x, ulong p); GEN Flm_suppl(GEN x, ulong p); GEN FlxqM_FlxqC_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_FlxqC_mul(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_det(GEN a, GEN T, ulong p); GEN FlxqM_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_ker(GEN x, GEN T, ulong p); GEN FlxqM_image(GEN x, GEN T, ulong p); GEN FlxqM_inv(GEN x, GEN T, ulong p); GEN FlxqM_mul(GEN a, GEN b, GEN T, ulong p); long FlxqM_rank(GEN x, GEN T, ulong p); GEN FpM_FpC_gauss(GEN a, GEN b, GEN p); GEN FpM_FpC_invimage(GEN m, GEN v, GEN p); GEN FpM_deplin(GEN x, GEN p); GEN FpM_det(GEN x, GEN p); GEN FpM_gauss(GEN a, GEN b, GEN p); GEN FpM_image(GEN x, GEN p); GEN FpM_indexrank(GEN x, GEN p); GEN FpM_intersect(GEN x, GEN y, GEN p); GEN FpM_inv(GEN x, GEN p); GEN FpM_invimage(GEN m, GEN v, GEN p); GEN FpM_ker(GEN x, GEN p); long FpM_rank(GEN x, GEN p); GEN FpM_suppl(GEN x, GEN p); GEN FqM_FqC_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_FqC_mul(GEN a, GEN b, GEN T, GEN p); GEN FqM_deplin(GEN x, GEN T, GEN p); GEN FqM_det(GEN x, GEN T, GEN p); GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_ker(GEN x, GEN T, GEN p); GEN FqM_image(GEN x, GEN T, GEN p); GEN FqM_inv(GEN x, GEN T, GEN p); GEN FqM_mul(GEN a, GEN b, GEN T, GEN p); long FqM_rank(GEN a, GEN T, GEN p); GEN FqM_suppl(GEN x, GEN T, GEN p); GEN QM_inv(GEN M, GEN dM); GEN RgM_Fp_init(GEN a, GEN p, ulong *pp); GEN RgM_RgC_invimage(GEN A, GEN B); GEN RgM_diagonal(GEN m); GEN RgM_diagonal_shallow(GEN m); GEN RgM_Hadamard(GEN a); GEN RgM_inv_upper(GEN a); GEN RgM_invimage(GEN A, GEN B); GEN RgM_solve(GEN a, GEN b); GEN RgM_solve_realimag(GEN x, GEN y); void RgMs_structelim(GEN M, long N, GEN A, GEN *p_col, GEN *p_lin); GEN ZM_det(GEN a); GEN ZM_detmult(GEN A); GEN ZM_gauss(GEN a, GEN b); GEN ZM_imagecompl(GEN x); GEN ZM_indeximage(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); GEN closemodinvertible(GEN x, GEN y); GEN deplin(GEN x); GEN det(GEN a); GEN det0(GEN a,long flag); GEN det2(GEN a); GEN detint(GEN x); GEN eigen(GEN x, long prec); GEN gauss(GEN a, GEN b); GEN gaussmodulo(GEN M, GEN D, GEN Y); GEN gaussmodulo2(GEN M, GEN D, GEN Y); GEN gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff); GEN 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); GEN gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff); GEN gen_matcolmul(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matmul(GEN a, GEN b, void *E, const struct bb_field *ff); GEN image(GEN x); GEN image2(GEN x); GEN imagecompl(GEN x); GEN indexrank(GEN x); GEN inverseimage(GEN mat, GEN y); GEN ker(GEN x); GEN keri(GEN x); GEN mateigen(GEN x, long flag, long prec); GEN matimage0(GEN x,long flag); GEN matker0(GEN x, long flag); GEN matsolvemod0(GEN M, GEN D, GEN Y,long flag); long rank(GEN x); GEN reducemodinvertible(GEN x, GEN y); GEN reducemodlll(GEN x,GEN y); GEN split_realimag(GEN x, long r1, long r2); GEN suppl(GEN x); /* alglin2.c */ 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 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 ZM_charpoly(GEN x); GEN adj(GEN x); GEN adjsafe(GEN x); GEN caract(GEN x, long v); GEN caradj(GEN x, long v, GEN *py); GEN carberkowitz(GEN x, long v); GEN carhess(GEN x, long v); 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 gnormlp(GEN x, GEN p, long prec); GEN gnorml2(GEN x); GEN gsupnorm(GEN x, long prec); void gsupnorm_aux(GEN x, GEN *m, GEN *msq, long prec); GEN gtrace(GEN x); GEN hess(GEN x); GEN intersect(GEN x, GEN y); GEN jacobi(GEN a, long prec); GEN matadjoint0(GEN x, long flag); GEN matcompanion(GEN x); GEN matrixqz0(GEN x, GEN pp); GEN minpoly(GEN x, long v); GEN qfgaussred(GEN a); GEN qfgaussred_positive(GEN a); GEN qfsign(GEN a); /* alglin3.c */ GEN apply0(GEN f, GEN A); GEN diagonal(GEN x); GEN diagonal_shallow(GEN x); GEN extract0(GEN x, GEN l1, GEN l2); GEN genapply(void *E, GEN (*f)(void *E, GEN x), 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); GEN gtrans(GEN x); 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); GEN parselect(GEN C, GEN D, long flag); GEN select0(GEN A, GEN f, long flag); GEN shallowextract(GEN x, GEN L); GEN shallowtrans(GEN x); GEN vecapply(void *E, GEN (*f)(void* E, GEN x), GEN x); GEN veccatapply(void *E, GEN (*f)(void* E, GEN x), GEN x); GEN veccatselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun, GEN (*fun)(void* E, GEN x), GEN A); GEN vecrange(GEN a, GEN b); GEN vecrangess(long a, long b); GEN vecselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun, GEN (*fun)(void* E, GEN x), GEN A); GEN vecselect(void *E, long (*f)(void* E, GEN x), GEN A); GEN vecslice0(GEN A, long y1, long y2); GEN vecsum(GEN v); /* anal.c */ void addhelp(const char *e, char *s); 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); 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_init(void); long pari_var_next(void); long pari_var_next_temp(void); void pari_var_create(entree *ep); void name_var(long n, const char *s); GEN readseq(char *t); GEN* safegel(GEN x, long l); long* safeel(GEN x, long l); GEN* safelistel(GEN x, long l); GEN* safegcoeff(GEN x, long a, long b); GEN strntoGENstr(const char *s, long n0); GEN strtoGENstr(const char *s); GEN strtoi(const char *s); GEN strtor(const char *s, long prec); GEN type0(GEN x); /* aprcl.c */ long isprimeAPRCL(GEN N); /* Qfb.c */ GEN Qfb0(GEN x, GEN y, GEN z, GEN d, long prec); void check_quaddisc(GEN x, long *s, long *r, const char *f); void check_quaddisc_imag(GEN x, long *r, const char *f); void check_quaddisc_real(GEN x, long *r, const char *f); long cornacchia(GEN d, GEN p, GEN *px, GEN *py); long cornacchia2(GEN d, GEN p, GEN *px, GEN *py); GEN nucomp(GEN x, GEN y, GEN l); GEN nudupl(GEN x, GEN l); GEN nupow(GEN x, GEN n); GEN primeform(GEN x, GEN p, long prec); 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 qfbsolve(GEN Q, GEN n); GEN qfi(GEN x, GEN y, GEN z); GEN qfi_1(GEN x); GEN qficomp(GEN x, GEN y); GEN qficompraw(GEN x, GEN y); GEN qfipowraw(GEN x, long n); GEN qfisolvep(GEN Q, GEN p); GEN qfisqr(GEN x); GEN qfisqrraw(GEN x); GEN qfr(GEN x, GEN y, GEN z, GEN d); GEN qfr3_comp(GEN x, GEN y, struct qfr_data *S); GEN qfr3_pow(GEN x, GEN n, struct qfr_data *S); GEN qfr3_red(GEN x, struct qfr_data *S); GEN qfr3_rho(GEN x, struct qfr_data *S); GEN qfr3_to_qfr(GEN x, GEN z); GEN qfr5_comp(GEN x, GEN y, struct qfr_data *S); GEN qfr5_dist(GEN e, GEN d, long prec); GEN qfr5_pow(GEN x, GEN n, struct qfr_data *S); GEN qfr5_red(GEN x, struct qfr_data *S); GEN qfr5_rho(GEN x, struct qfr_data *S); GEN qfr5_to_qfr(GEN x, GEN d0); GEN qfr_1(GEN x); void qfr_data_init(GEN D, long prec, struct qfr_data *S); GEN qfr_to_qfr5(GEN x, long prec); GEN qfrcomp(GEN x, GEN y); GEN qfrcompraw(GEN x, GEN y); GEN qfrpow(GEN x, GEN n); GEN qfrpowraw(GEN x, long n); GEN qfrsolvep(GEN Q, GEN p); GEN qfrsqr(GEN x); GEN qfrsqrraw(GEN x); GEN quadgen(GEN x); GEN quadpoly(GEN x); GEN quadpoly0(GEN x, long v); GEN redimag(GEN x); GEN redreal(GEN x); GEN redrealnod(GEN x, GEN isqrtD); GEN rhoreal(GEN x); GEN rhorealnod(GEN x, GEN isqrtD); /* arith1.c */ ulong Fl_order(ulong a, ulong o, ulong p); ulong Fl_powu(ulong x, ulong n, ulong p); ulong Fl_sqrt(ulong a, ulong p); 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_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_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); GEN Z_chinese_post(GEN a, GEN b, GEN C, GEN U, GEN d); void Z_chinese_pre(GEN A, GEN B, GEN *pC, GEN *pU, GEN *pd); GEN Z_factor_listP(GEN N, GEN L); long Z_isanypower(GEN x, GEN *y); 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); long Zp_issquare(GEN a, GEN p); GEN bestappr(GEN x, GEN k); GEN bestapprPade(GEN x, long B); long cgcd(long a,long b); GEN chinese(GEN x, GEN y); GEN chinese1(GEN x); GEN chinese1_coprime_Z(GEN x); GEN classno(GEN x); GEN classno2(GEN x); long clcm(long a,long b); GEN contfrac0(GEN x, GEN b, long flag); GEN contfracpnqn(GEN x, long n); GEN fibo(long n); GEN gboundcf(GEN x, long k); GEN gcf(GEN x); GEN gcf2(GEN b, GEN x); const struct bb_field *get_Fp_field(void **E, GEN p); ulong pgener_Fl(ulong p); ulong pgener_Fl_local(ulong p, GEN L); GEN pgener_Fp(GEN p); GEN pgener_Fp_local(GEN p, GEN L); ulong pgener_Zl(ulong p); GEN pgener_Zp(GEN p); long gisanypower(GEN x, GEN *pty); GEN gissquare(GEN x); GEN gissquareall(GEN x, GEN *pt); GEN hclassno(GEN x); long hilbert(GEN x, GEN y, GEN p); long hilbertii(GEN x, GEN y, GEN p); 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 issquare(GEN x); long issquareall(GEN x, GEN *pt); long krois(GEN x, long y); 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 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 odd_prime_divisors(GEN q); GEN order(GEN x); GEN pnqn(GEN x); GEN qfbclassno0(GEN x,long flag); GEN quaddisc(GEN x); GEN quadregulator(GEN x, long prec); GEN quadunit(GEN x); ulong rootsof1_Fl(ulong n, ulong p); GEN rootsof1_Fp(GEN n, GEN p); GEN rootsof1u_Fp(ulong n, GEN p); GEN sqrtint(GEN a); ulong ugcd(ulong a,ulong b); long uisprimepower(ulong n, ulong *p); long uissquare(ulong A); long uissquareall(ulong A, ulong *sqrtA); long unegisfundamental(ulong x); long uposisfundamental(ulong x); GEN znlog(GEN x, GEN g, GEN o); GEN znorder(GEN x, GEN o); GEN znprimroot(GEN m); GEN znstar(GEN x); /* arith2.c */ GEN Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pe); GEN boundfact(GEN n, ulong lim); GEN check_arith_pos(GEN n, const char *f); GEN check_arith_non0(GEN n, const char *f); GEN check_arith_all(GEN n, const char *f); GEN clean_Z_factor(GEN f); GEN corepartial(GEN n, long l); GEN core0(GEN n,long flag); GEN core2(GEN n); GEN core2partial(GEN n, long l); GEN coredisc(GEN n); GEN coredisc0(GEN n,long flag); GEN coredisc2(GEN n); 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); byteptr initprimes(ulong maxnum, long *lenp, ulong *lastp); void initprimetable(ulong maxnum); ulong init_primepointer_geq(ulong a, byteptr *pd); ulong init_primepointer_gt(ulong a, byteptr *pd); ulong init_primepointer_leq(ulong a, byteptr *pd); ulong init_primepointer_lt(ulong a, byteptr *pd); int is_Z_factor(GEN f); int is_Z_factornon0(GEN f); int is_Z_factorpos(GEN f); ulong maxprime(void); void maxprime_check(ulong c); GEN sumdigits(GEN n); ulong sumdigitsu(ulong n); /* DedekZeta.c */ GEN glambdak(GEN nfz, GEN s, long prec); GEN gzetak(GEN nfz, GEN s, long prec); GEN gzetakall(GEN nfz, GEN s, long flag, long prec); GEN initzeta(GEN pol, long prec); GEN dirzetak(GEN nf, GEN b); /* base1.c */ GEN FpX_FpC_nfpoleval(GEN nf, GEN pol, GEN a, GEN p); GEN embed_T2(GEN x, long r1); GEN embednorm_T2(GEN x, long r1); GEN embed_norm(GEN x, long r1); void check_ZKmodule(GEN x, const char *s); void checkbid(GEN bid); GEN checkbnf(GEN bnf); void checkbnr(GEN bnr); void checkbnrgen(GEN bnr); void checkabgrp(GEN v); void checksqmat(GEN x, long N); GEN checknf(GEN nf); GEN checknfelt_mod(GEN nf, GEN x, const char *s); void checkprid(GEN bid); void checkrnf(GEN rnf); GEN factoredpolred(GEN x, GEN fa); GEN factoredpolred2(GEN x, GEN fa); GEN galoisapply(GEN nf, GEN aut, GEN x); GEN get_bnf(GEN x, long *t); GEN get_bnfpol(GEN x, GEN *bnf, GEN *nf); GEN get_nf(GEN x, long *t); GEN get_nfpol(GEN x, GEN *nf); GEN get_prid(GEN x); GEN idealfrobenius(GEN nf, GEN gal, GEN pr); GEN idealramgroups(GEN nf, GEN gal, GEN pr); GEN nf_get_allroots(GEN nf); long nf_get_prec(GEN x); GEN nfcertify(GEN x); GEN nfgaloismatrix(GEN nf, GEN s); GEN nfinit(GEN x, long prec); GEN nfinit0(GEN x, long flag, long prec); GEN nfinitall(GEN x, long flag, long prec); GEN nfinitred(GEN x, long prec); GEN nfinitred2(GEN x, long prec); GEN nfisincl(GEN a, GEN b); GEN nfisisom(GEN a, GEN b); GEN nfnewprec(GEN nf, long prec); GEN nfnewprec_shallow(GEN nf, long prec); GEN nfpoleval(GEN nf, GEN pol, GEN a); 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 polred2(GEN x); GEN polredabs(GEN x); GEN polredabs0(GEN x, long flag); GEN polredabs2(GEN x); GEN polredabsall(GEN x, long flun); GEN polredbest(GEN x, long flag); GEN rnfpolredabs(GEN nf, GEN pol, long flag); GEN rnfpolredbest(GEN nf, GEN relpol, long flag); GEN smallpolred(GEN x); GEN smallpolred2(GEN x); GEN tschirnhaus(GEN x); GEN ZX_Q_normalize(GEN pol, GEN *ptlc); GEN ZX_Z_normalize(GEN pol, GEN *ptk); GEN ZX_to_monic(GEN pol, GEN *lead); GEN ZX_primitive_to_monic(GEN pol, GEN *lead); /* base2.c */ GEN Fq_to_nf(GEN x, GEN modpr); GEN FqM_to_nfM(GEN z, GEN modpr); GEN FqV_to_nfV(GEN z, GEN modpr); GEN FqX_to_nfX(GEN x, GEN modpr); GEN Rg_nffix(const char *f, GEN T, GEN c, int lift); GEN RgV_nffix(const char *f, GEN T, GEN P, int lift); GEN RgX_nffix(const char *s, GEN nf, GEN x, int lift); long ZpX_disc_val(GEN f, GEN p); GEN ZpX_gcd(GEN f1,GEN f2,GEN p, GEN pm); GEN ZpX_reduced_resultant(GEN x, GEN y, GEN p, GEN pm); GEN ZpX_reduced_resultant_fast(GEN f, GEN g, GEN p, long M); long ZpX_resultant_val(GEN f, GEN g, GEN p, long M); void checkmodpr(GEN modpr); 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 indexpartial(GEN P, GEN DP); GEN modpr_genFq(GEN modpr); GEN nf_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p); GEN nf_to_Fq(GEN nf, GEN x, GEN modpr); 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); void nfmaxord(nfmaxord_t *S, GEN T, long flag); GEN nfmodprinit(GEN nf, GEN pr); GEN nfreducemodpr(GEN nf, GEN x, GEN modpr); GEN polcompositum0(GEN P, GEN Q,long flag); GEN idealprimedec(GEN nf,GEN p); GEN rnfbasis(GEN bnf, GEN order); GEN rnfdedekind(GEN nf, GEN T, GEN pr, long flag); GEN rnfdet(GEN nf, GEN order); GEN rnfdiscf(GEN nf, GEN pol); GEN rnfequation(GEN nf, GEN pol); GEN rnfequation0(GEN nf, GEN pol, long flall); GEN rnfequation2(GEN nf, GEN pol); GEN nf_rnfeq(GEN nf, GEN relpol); GEN nf_rnfeqsimple(GEN nf, GEN relpol); GEN rnfequationall(GEN A, GEN B, long *pk, GEN *pLPRS); GEN rnfhnfbasis(GEN bnf, GEN order); long rnfisfree(GEN bnf, GEN order); GEN rnflllgram(GEN nf, GEN pol, GEN order,long prec); GEN rnfpolred(GEN nf, GEN pol, long prec); GEN rnfpseudobasis(GEN nf, GEN pol); GEN rnfsimplifybasis(GEN bnf, GEN order); GEN rnfsteinitz(GEN nf, GEN order); long factorial_lval(ulong n, ulong p); GEN zk_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p); GEN zk_to_Fq(GEN x, GEN modpr); GEN zkmodprinit(GEN nf, GEN pr); /* base3.c */ GEN Idealstar(GEN nf, GEN x,long flun); GEN RgC_to_nfC(GEN nf,GEN x); 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 ideallist(GEN nf,long bound); GEN ideallist0(GEN nf,long bound, long flag); GEN ideallistarch(GEN nf, GEN list, GEN arch); GEN idealprincipalunits(GEN nf, GEN pr, long e); GEN idealstar0(GEN nf, GEN x,long flag); GEN indices_to_vec01(GEN archp, long r); GEN matalgtobasis(GEN nf, GEN x); GEN matbasistoalg(GEN nf, GEN x); GEN nf_to_scalar_or_alg(GEN nf, GEN x); GEN nf_to_scalar_or_basis(GEN nf, GEN x); GEN nfadd(GEN nf, GEN x, GEN y); 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 nfinv(GEN nf, GEN x); GEN nfinvmodideal(GEN nf, GEN x, GEN ideal); GEN nfmod(GEN nf, GEN a, GEN b); GEN nfmul(GEN nf,GEN x,GEN y); GEN nfmuli(GEN nf,GEN x,GEN y); GEN nfnorm(GEN nf, GEN x); GEN nfpow(GEN nf,GEN x,GEN k); GEN nfpow_u(GEN nf, GEN z, ulong n); GEN nfpowmodideal(GEN nf,GEN x,GEN k,GEN ideal); GEN nfsign(GEN nf,GEN alpha); GEN nfsign_arch(GEN nf,GEN alpha,GEN arch); GEN nfsign_from_logarch(GEN Larch, GEN invpi, GEN archp); 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); 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); GEN rnfalgtobasis(GEN rnf, GEN x); GEN rnfbasistoalg(GEN rnf, GEN x); 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 vecmodii(GEN a, GEN b); GEN ideallog(GEN nf,GEN x,GEN bigideal); GEN multable(GEN nf, GEN x); GEN tablemul(GEN TAB, GEN x, GEN y); GEN tablemul_ei(GEN M, GEN x, long i); GEN tablemul_ei_ej(GEN M, long i, long j); GEN tablemulvec(GEN M, GEN x, GEN v); GEN tablesqr(GEN tab, GEN x); GEN ei_multable(GEN nf, long i); long ZC_nfval(GEN nf, GEN x, GEN P); long ZC_nfvalrem(GEN nf, GEN x, GEN P, GEN *t); GEN zk_multable(GEN nf, GEN x); GEN zk_scalar_or_multable(GEN, GEN x); int ZC_prdvd(GEN nf, GEN x, GEN P); /* base4.c */ GEN RM_round_maxrank(GEN G); GEN ZM_famat_limit(GEN fa, GEN limit); 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); GEN famat_mul(GEN f, GEN g); GEN famat_pow(GEN f, GEN n); GEN famat_sqr(GEN f); GEN famat_reduce(GEN fa); 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 idealtwoelt(GEN nf, GEN ix); GEN idealtwoelt0(GEN nf, GEN ix, GEN a); GEN idealtwoelt2(GEN nf, GEN x, GEN a); GEN idealadd(GEN nf, GEN x, GEN y); GEN idealaddmultoone(GEN nf, GEN list); GEN idealaddtoone(GEN nf, GEN x, GEN y); GEN idealaddtoone_i(GEN nf, GEN x, GEN y); GEN idealaddtoone0(GEN nf, GEN x, GEN y); GEN idealappr(GEN nf, GEN x); GEN idealappr0(GEN nf, GEN x, long fl); GEN idealapprfact(GEN nf, GEN x); GEN idealchinese(GEN nf, GEN x, GEN y); GEN idealcoprime(GEN nf, GEN x, GEN y); GEN idealcoprimefact(GEN nf, GEN x, GEN fy); GEN idealdiv(GEN nf, GEN x, GEN y); GEN idealdiv0(GEN nf, GEN x, GEN y,long flag); GEN idealdivexact(GEN nf, GEN x, GEN y); GEN idealdivpowprime(GEN nf, GEN x, GEN vp, GEN n); GEN idealmulpowprime(GEN nf, GEN x, GEN vp, GEN n); GEN idealfactor(GEN nf, GEN x); GEN idealhnf(GEN nf, GEN x); GEN idealhnf_principal(GEN nf, GEN x); GEN idealhnf_shallow(GEN nf, GEN x); 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 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); GEN idealmul_HNF(GEN nf, GEN ix, GEN iy); GEN idealmulred(GEN nf, GEN ix, GEN iy); GEN idealnorm(GEN nf, GEN x); GEN idealnumden(GEN nf, GEN x); GEN idealpow(GEN nf, GEN ix, GEN n); GEN idealpow0(GEN nf, GEN ix, GEN n, long flag); GEN idealpowred(GEN nf, GEN ix, GEN n); GEN idealpows(GEN nf, GEN ideal, long iexp); GEN idealprodprime(GEN nf, GEN L); GEN idealsqr(GEN nf, GEN x); long idealtyp(GEN *ideal, GEN *arch); long idealval(GEN nf,GEN ix,GEN vp); long isideal(GEN nf,GEN x); GEN idealmin(GEN nf,GEN ix,GEN vdir); GEN nf_get_Gtwist(GEN nf, GEN vdir); GEN nf_get_Gtwist1(GEN nf, long i); 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 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 nfsolvemodpr(GEN nf, GEN a, GEN b, GEN modpr); GEN to_famat(GEN x, GEN y); GEN to_famat_shallow(GEN x, GEN y); GEN vecdiv(GEN x, GEN y); GEN vecinv(GEN x); GEN vecmul(GEN x, GEN y); GEN vecpow(GEN x, GEN n); /* base5.c */ GEN eltreltoabs(GEN rnfeq, GEN x); GEN eltabstorel(GEN eq, GEN P); GEN eltabstorel_lift(GEN rnfeq, GEN P); void nf_nfzk(GEN nf, GEN rnfeq, GEN *zknf, GEN *czknf); GEN nfeltup(GEN nf, GEN x, GEN zknf, GEN czknf); GEN rnfeltabstorel(GEN rnf, GEN x); GEN rnfeltdown(GEN rnf, GEN x); GEN rnfeltreltoabs(GEN rnf, GEN x); GEN rnfeltup(GEN rnf, GEN x); GEN rnfidealabstorel(GEN rnf, GEN x); GEN rnfidealdown(GEN rnf, GEN x); GEN rnfidealhnf(GEN rnf, GEN x); GEN rnfidealmul(GEN rnf,GEN x,GEN y); GEN rnfidealnormabs(GEN rnf, GEN x); GEN rnfidealnormrel(GEN rnf, GEN x); GEN rnfidealreltoabs(GEN rnf, GEN x); GEN rnfidealtwoelement(GEN rnf,GEN x); GEN rnfidealup(GEN rnf, GEN x); GEN rnfinit(GEN nf,GEN pol); /* bb_group.c */ 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_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, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)); GEN gen_ellgroup(GEN N, GEN F, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)); GEN gen_factored_order(GEN a, GEN o, void *E, const struct bb_group *grp); GEN gen_order(GEN x, GEN o, void *E, const struct bb_group *grp); GEN gen_select_order(GEN o, void *E, const struct bb_group *grp); GEN gen_plog(GEN x,GEN g0,GEN q, void *E, const struct bb_group *grp); GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_pow_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_pow_fold(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_pow_fold_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_powers(GEN x, long l, int use_sqr, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN), GEN (*one)(void*)); GEN gen_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_powu_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_powu_fold(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_powu_fold_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); /* bibli1.c */ int QR_init(GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec); GEN R_from_QR(GEN x, long prec); int RgM_QR_init(GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec); GEN Xadic_lindep(GEN x); 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 lindep0(GEN x, long flag); GEN lindep(GEN x); GEN lindep2(GEN x, long bit); GEN mathouseholder(GEN Q, GEN v); GEN matqr(GEN x, long flag, long prec); GEN minim(GEN a, GEN borne, GEN stockmax); GEN minim_raw(GEN a, GEN borne, GEN stockmax); GEN minim2(GEN a, GEN borne, GEN stockmax); GEN padic_lindep(GEN x); GEN perf(GEN a); GEN qfrep0(GEN a, GEN borne, long flag); GEN qfminim0(GEN a, GEN borne, GEN stockmax,long flag, long prec); GEN seralgdep(GEN s, long p, long r); GEN zncoppersmith(GEN P0, GEN N, GEN X, GEN B) ; /* bibli2.c */ GEN QXQ_reverse(GEN a, GEN T); GEN RgV_polint(GEN X, GEN Y, long v); GEN RgXQ_reverse(GEN a, GEN T); GEN ZV_indexsort(GEN L); long ZV_search(GEN x, GEN y); GEN ZV_sort(GEN L); GEN ZV_sort_uniq(GEN L); GEN ZV_union_shallow(GEN x, GEN y); GEN binomial(GEN x, long k); GEN binomialuu(ulong n, ulong k); int cmp_nodata(void *data, GEN x, GEN y); int cmp_prime_ideal(GEN x, GEN y); int cmp_prime_over_p(GEN x, GEN y); int cmp_RgX(GEN x, GEN y); int cmp_universal(GEN x, GEN y); GEN convol(GEN x, GEN y); int gen_cmp_RgX(void *data, GEN x, GEN y); GEN polcyclo(long n, long v); GEN polcyclo_eval(long n, GEN x); GEN dirdiv(GEN x, GEN y); GEN dirmul(GEN x, GEN y); GEN gen_indexsort(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); GEN gen_indexsort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); long gen_search(GEN x, GEN y, long flag, void *data, int (*cmp)(void*,GEN,GEN)); GEN gen_setminus(GEN set1, GEN set2, int (*cmp)(GEN,GEN)); GEN gen_sort(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); void gen_sort_inplace(GEN x, void *E, int (*cmp)(void*,GEN,GEN), GEN *perm); GEN gen_sort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); long getstack(void); long gettime(void); long getabstime(void); GEN gprec(GEN x, long l); GEN gprec_wtrunc(GEN x, long pr); GEN gprec_w(GEN x, long pr); GEN gtoset(GEN x); GEN indexlexsort(GEN x); GEN indexsort(GEN x); GEN indexvecsort(GEN x, GEN k); GEN laplace(GEN x); GEN lexsort(GEN x); GEN mathilbert(long n); GEN matqpascal(long n, GEN q); GEN merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN)); GEN merge_sort_uniq(GEN x, GEN y, void *data, int (*cmp)(void *,GEN,GEN)); GEN modreverse(GEN x); GEN numtoperm(long n, GEN x); GEN permtonum(GEN x); GEN polhermite(long n, long v); GEN polhermite_eval(long n, GEN x); GEN pollegendre(long n, long v); GEN pollegendre_eval(long n, GEN x); GEN polint(GEN xa, GEN ya, GEN x, GEN *dy); GEN polchebyshev(long n, long kind, long v); GEN polchebyshev_eval(long n, long kind, GEN x); GEN polchebyshev1(long n, long v); GEN polchebyshev2(long n, long v); GEN polrecip(GEN x); GEN setbinop(GEN f, GEN x, GEN y); GEN setintersect(GEN x, GEN y); long setisset(GEN x); GEN setminus(GEN x, GEN y); long setsearch(GEN x, GEN y, long flag); GEN setunion(GEN x, GEN y); GEN sort(GEN x); GEN sort_factor(GEN y, void *data, int (*cmp)(void*,GEN,GEN)); GEN stirling(long n, long m, long flag); GEN stirling1(ulong n, ulong m); GEN stirling2(ulong n, ulong m); long tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN)); GEN vecbinome(long n); long vecsearch(GEN v, GEN x, GEN k); GEN vecsort(GEN x, GEN k); GEN vecsort0(GEN x, GEN k, long flag); long zv_search(GEN x, long y); /* bit.c */ GEN binaire(GEN x); long bittest(GEN x, long n); GEN gbitand(GEN x, GEN y); GEN gbitneg(GEN x, long n); GEN gbitnegimply(GEN x, GEN y); GEN gbitor(GEN x, GEN y); GEN gbittest(GEN x, long n); GEN gbitxor(GEN x, GEN y); long hammingweight(GEN n); GEN ibitand(GEN x, GEN y); GEN ibitnegimply(GEN x, GEN y); GEN ibitor(GEN x, GEN y); GEN ibitxor(GEN x, GEN y); /* buch1.c */ GEN Buchquad(GEN D, double c1, double c2, long prec); GEN quadclassunit0(GEN x, long flag,GEN data, long prec); GEN quadhilbert(GEN D, long prec); GEN quadray(GEN bnf, GEN f, long prec); /* buch2.c */ GEN bnfcompress(GEN bnf); GEN bnfinit0(GEN P,long flag,GEN data,long prec); GEN bnfnewprec(GEN nf, long prec); GEN bnfnewprec_shallow(GEN nf, long prec); GEN bnrnewprec(GEN bnr, long prec); GEN bnrnewprec_shallow(GEN bnr, long prec); GEN Buchall(GEN P, long flag, long prec); GEN Buchall_param(GEN P, double bach, double bach2, long nbrelpid, long flun, long prec); GEN isprincipal(GEN bnf, GEN x); GEN bnfisprincipal0(GEN bnf, GEN x,long flall); GEN isprincipalfact(GEN bnf, GEN C, GEN L, GEN f, long flag); GEN isprincipalfact_or_fail(GEN bnf, GEN C, GEN P, GEN e); GEN bnfisunit(GEN bignf, GEN x); GEN signunits(GEN bignf); GEN nfsign_units(GEN bnf, GEN archp, int add_zu); /* buch3.c */ GEN ABC_to_bnr(GEN A, GEN B, GEN C, GEN *H, int gen); GEN Buchray(GEN bnf, GEN module, long flag); GEN bnrclassno(GEN bignf,GEN ideal); GEN bnrclassno0(GEN A,GEN B,GEN C); GEN bnrclassnolist(GEN bnf,GEN listes); GEN bnrconductor0(GEN A, GEN B, GEN C, long flag); GEN bnrconductor(GEN bnr, GEN H0, long flag); 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 bnrinit0(GEN bignf,GEN ideal,long flag); long bnrisconductor0(GEN A, GEN B, GEN C); long bnrisconductor(GEN bnr, GEN H); GEN bnrisprincipal(GEN bnf, GEN x,long flag); GEN bnrsurjection(GEN bnr1, GEN bnr2); GEN buchnarrow(GEN bignf); long bnfcertify(GEN bnf); long bnfcertify0(GEN bnf, long flag); GEN decodemodule(GEN nf, GEN fa); GEN discrayabslist(GEN bnf,GEN listes); GEN discrayabslistarch(GEN bnf, GEN arch, ulong bound); GEN discrayabslistlong(GEN bnf, ulong bound); GEN idealmoddivisor(GEN bnr, GEN x); GEN isprincipalray(GEN bnf, GEN x); GEN isprincipalraygen(GEN bnf, GEN x); GEN rnfconductor(GEN bnf, GEN polrel); long rnfisabelian(GEN nf, GEN pol); GEN rnfnormgroup(GEN bnr, GEN polrel); GEN subgrouplist0(GEN bnr, GEN indexbound, long all); /* buch4.c */ GEN bnfisnorm(GEN bnf,GEN x,long flag); GEN rnfisnorm(GEN S, GEN x, long flag); GEN rnfisnorminit(GEN bnf, GEN relpol, int galois); GEN bnfissunit(GEN bnf,GEN suni,GEN x); GEN bnfsunit(GEN bnf,GEN s,long PREC); long nfhilbert(GEN bnf,GEN a,GEN b); 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); /* compile.c */ GEN closure_deriv(GEN G); long localvars_find(GEN pack, entree *ep); GEN localvars_read_str(const char *str, GEN pack); GEN snm_closure(entree *ep, GEN data); GEN strtoclosure(const char *s, long n, ...); GEN strtofunction(const char *s); /* concat.c */ GEN concat(GEN x, GEN y); GEN concat1(GEN x); GEN matconcat(GEN v); GEN shallowconcat(GEN x, GEN y); GEN shallowconcat1(GEN x); GEN shallowmatconcat(GEN v); GEN vconcat(GEN A, GEN B); /* default.c */ 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); GEN sd_TeXstyle(const char *v, long flag); GEN sd_colors(const char *v, long flag); GEN sd_compatible(const char *v, long flag); GEN sd_datadir(const char *v, long flag); GEN sd_debug(const char *v, long flag); GEN sd_debugfiles(const char *v, long flag); GEN sd_debugmem(const char *v, long flag); GEN sd_factor_add_primes(const char *v, long flag); GEN sd_factor_proven(const char *v, long flag); GEN sd_format(const char *v, long flag); GEN sd_histsize(const char *v, long flag); GEN sd_log(const char *v, long flag); GEN sd_logfile(const char *v, long flag); 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_path(const char *v, long flag); GEN sd_prettyprinter(const char *v, long flag); GEN sd_primelimit(const char *v, long flag); GEN sd_realprecision(const char *v, long flag); GEN sd_secure(const char *v, long flag); GEN sd_seriesprecision(const char *v, long flag); GEN sd_simplify(const char *v, long flag); GEN sd_sopath(char *v, int flag); 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_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); /* ellanal.c */ GEN ellanalyticrank(GEN e, GEN eps, long prec); GEN ellL1(GEN e, long r, long prec); /* elldata.c */ GEN ellconvertname(GEN s); GEN elldatagenerators(GEN E); GEN ellidentify(GEN E); GEN ellsearch(GEN A); 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}; GEN akell(GEN e, GEN n); GEN anell(GEN e, long n); GEN anellsmall(GEN e, long n); GEN bilhell(GEN e, GEN z1, GEN z2, long prec); void checkell(GEN e); void checkell_Fq(GEN e); void checkell_Q(GEN e); void checkell_Qp(GEN e); void checkellpt(GEN z); void checkell5(GEN e); GEN ellanal_globalred(GEN e, GEN *gr); GEN ellQ_get_N(GEN e); void ellQ_get_Nfa(GEN e, GEN *N, GEN *faN); GEN ellQp_Tate_uniformization(GEN E, long prec); GEN ellQp_u(GEN E, long prec); GEN ellQp_u2(GEN E, long prec); GEN ellQp_q(GEN E, long prec); GEN ellQp_ab(GEN E, long prec); GEN ellQp_root(GEN E, long prec); GEN ellR_ab(GEN E, long prec); GEN ellR_eta(GEN E, long prec); 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); GEN ellcard(GEN E, GEN p); GEN ellchangecurve(GEN e, GEN ch); GEN ellchangeinvert(GEN w); GEN ellchangepoint(GEN x, GEN ch); GEN ellchangepointinv(GEN x, GEN ch); GEN elldivpol(GEN e, long n, long v); GEN elleisnum(GEN om, long k, long flag, long prec); GEN elleta(GEN om, long prec); GEN ellff_get_card(GEN E); GEN ellff_get_gens(GEN E); GEN ellff_get_group(GEN E); GEN ellff_get_o(GEN x); GEN ellff_get_p(GEN E); GEN ellfromj(GEN j); 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 ellinit(GEN x, GEN p, long prec); GEN ellisoncurve(GEN e, GEN z); 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 ellneg(GEN e, GEN z); GEN ellorder(GEN e, GEN p, GEN o); GEN ellordinate(GEN e, GEN x, long prec); GEN ellperiods(GEN w, long flag, long prec); GEN ellrandom(GEN e); long ellrootno(GEN e, GEN p); long ellrootno_global(GEN e); GEN ellsigma(GEN om, GEN z, long flag, long prec); GEN ellsub(GEN e, GEN z1, GEN z2); GEN elltaniyama(GEN e, long prec); GEN elltatepairing(GEN E, GEN t, GEN s, GEN m); GEN elltors(GEN e); GEN elltors0(GEN e, long flag); 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 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 zell(GEN e, GEN z, long prec); /* ellsea.c */ GEN Fp_ellcard_SEA(GEN a4, GEN a6, GEN p, long early_abort); GEN Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long early_abort); GEN ellmodulareqn(long l, long vx, long vy); GEN ellsea(GEN E, GEN p, long early_abort); /* es.c */ GEN GENtoGENstr_nospace(GEN x); GEN GENtoGENstr(GEN x); char* GENtoTeXstr(GEN x); char* GENtostr(GEN x); char* GENtostr_unquoted(GEN x); GEN Str(GEN g); GEN Strchr(GEN g); GEN Strexpand(GEN g); GEN Strtex(GEN g); void brute(GEN g, char format, long dec); void dbgGEN(GEN x, long nb); void error0(GEN g); void dbg_pari_heap(void); 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_stream(FILE *f); GEN gp_readvec_file(char *s); GEN gp_readvec_stream(FILE *f); void gpinstall(const char *s, const char *code, const char *gpname, const char *lib); GEN gsprintf(const char *fmt, ...); GEN gvsprintf(const char *fmt, va_list ap); char* itostr(GEN x); void matbrute(GEN g, char format, long dec); char* os_getenv(const char *s); void (*os_signal(int sig, void (*f)(int)))(int); void outmat(GEN x); void output(GEN x); char* RgV_to_str(GEN g, long flag); void pari_add_hist(GEN z, long t); void pari_ask_confirm(const char *s); void pari_fclose(pariFILE *f); void pari_flush(void); pariFILE* pari_fopen(const char *s, const char *mode); pariFILE* pari_fopen_or_fail(const char *s, const char *mode); pariFILE* pari_fopengz(const char *s); void pari_fprintf(FILE *file, const char *fmt, ...); void pari_fread_chars(void *b, size_t n, FILE *f); GEN pari_get_hist(long p); long pari_get_histtime(long p); char* pari_get_homedir(const char *user); int pari_is_dir(const char *name); int pari_is_file(const char *name); int pari_last_was_newline(void); void pari_set_last_newline(int last); ulong pari_nb_hist(void); void pari_printf(const char *fmt, ...); void pari_putc(char c); void pari_puts(const char *s); pariFILE* pari_safefopen(const char *s, const char *mode); char* pari_sprintf(const char *fmt, ...); int pari_stdin_isatty(void); char* pari_strdup(const char *s); char* pari_strndup(const char *s, long n); char* pari_unique_dir(const char *s); char* pari_unique_filename(const char *s); void pari_unlink(const char *s); void pari_vfprintf(FILE *file, const char *fmt, va_list ap); void pari_vprintf(const char *fmt, va_list ap); char* pari_vsprintf(const char *fmt, va_list ap); char* path_expand(const char *s); void out_print0(PariOUT *out, const char *sep, GEN g, long flag); void out_printf(PariOUT *out, const char *fmt, ...); void out_putc(PariOUT *out, char c); void out_puts(PariOUT *out, const char *s); void out_term_color(PariOUT *out, long c); void out_vprintf(PariOUT *out, const char *fmt, va_list ap); char* pari_sprint0(const char *msg, GEN g, long flag); void print(GEN g); enum { f_RAW = 0, f_PRETTYMAT = 1, f_PRETTY = 3, f_TEX = 4 }; void print0(GEN g, long flag); void print1(GEN g); void printf0(const char *fmt, GEN args); void printsep(const char *s, GEN g, long flag); void printsep1(const char *s, GEN g, long flag); void printtex(GEN g); char* stack_sprintf(const char *fmt, ...); char* stack_strcat(const char *s, const char *t); char* stack_strdup(const char *s); void strftime_expand(const char *s, char *buf, long max); GEN Strprintf(const char *fmt, GEN args); FILE* switchin(const char *name); void switchout(const char *name); void term_color(long c); char* term_get_color(char *s, long c); void texe(GEN g, char format, long dec); const char* type_name(long t); void warning0(GEN g); void write0(const char *s, GEN g); void write1(const char *s, GEN g); void writebin(const char *name, GEN x); void writetex(const char *s, GEN g); /* eval.c */ enum { br_NONE = 0, br_BREAK, br_NEXT, br_MULTINEXT, br_RETURN }; void bincopy_relink(GEN C, GEN vi); GEN break0(long n); GEN closure_callgen1(GEN C, GEN x); GEN closure_callgen2(GEN C, GEN x, GEN y); GEN closure_callgenall(GEN C, long n, ...); GEN closure_callgenvec(GEN C, GEN args); void closure_callvoid1(GEN C, GEN x); long closure_context(long start, long level); void closure_disassemble(GEN n); void closure_err(long level); GEN closure_evalbrk(GEN C, long *status); GEN closure_evalgen(GEN C); GEN closure_evalnobrk(GEN C); GEN closure_evalres(GEN C); void closure_evalvoid(GEN C); GEN closure_trapgen(GEN C, long numerr); GEN copybin_unlink(GEN C); GEN get_lex(long vn); GEN gp_call(void *E, GEN x); 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); long loop_break(void); GEN next0(long n); GEN pareval(GEN C); GEN parsum(GEN a, GEN b, GEN code, GEN x); GEN parvector(long n, GEN code); void pop_lex(long n); void push_lex(GEN a, GEN C); GEN return0(GEN x); void set_lex(long vn, GEN x); /* FF.c */ GEN FF_1(GEN a); GEN FF_Z_Z_muldiv(GEN x, GEN y, GEN z); GEN FF_Q_add(GEN x, GEN y); GEN FF_Z_add(GEN a, GEN b); GEN FF_Z_mul(GEN a, GEN b); GEN FF_add(GEN a, GEN b); GEN FF_charpoly(GEN x); GEN FF_conjvec(GEN x); GEN FF_div(GEN a, GEN b); GEN FF_ellcard(GEN E); GEN FF_ellgens(GEN E); GEN FF_ellgroup(GEN E); GEN FF_elllog(GEN E, GEN P, GEN Q, GEN o); GEN FF_ellmul(GEN E, GEN P, GEN n); GEN FF_ellorder(GEN E, GEN P, GEN o); GEN FF_ellrandom(GEN E); GEN FF_elltatepairing(GEN E, GEN P, GEN Q, GEN m); GEN FF_ellweilpairing(GEN E, GEN P, GEN Q, GEN m); int FF_equal(GEN a, GEN b); int FF_equal0(GEN x); int FF_equal1(GEN x); int FF_equalm1(GEN x); long FF_f(GEN x); GEN FF_inv(GEN a); long FF_issquare(GEN x); long FF_issquareall(GEN x, GEN *pt); long FF_ispower(GEN x, GEN K, GEN *pt); GEN FF_log(GEN a, GEN b, GEN o); GEN FF_minpoly(GEN x); GEN FF_mod(GEN x); GEN FF_mul(GEN a, GEN b); GEN FF_mul2n(GEN a, long n); GEN FF_neg(GEN a); GEN FF_neg_i(GEN a); GEN FF_norm(GEN x); GEN FF_order(GEN x, GEN o); GEN FF_p(GEN x); GEN FF_p_i(GEN x); GEN FF_pow(GEN x, GEN n); GEN FF_primroot(GEN x, GEN *o); GEN FF_q(GEN x); int FF_samefield(GEN x, GEN y); GEN FF_sqr(GEN a); GEN FF_sqrt(GEN a); GEN FF_sqrtn(GEN x, GEN n, GEN *zetan); GEN FF_sub(GEN x, GEN y); GEN FF_to_F2xq(GEN x); GEN FF_to_F2xq_i(GEN x); GEN FF_to_Flxq(GEN x); GEN FF_to_Flxq_i(GEN x); GEN FF_to_FpXQ(GEN x); GEN FF_to_FpXQ_i(GEN x); GEN FF_trace(GEN x); GEN FF_zero(GEN a); GEN FFM_FFC_mul(GEN M, GEN C, GEN ff); GEN FFM_det(GEN M, GEN ff); GEN FFM_image(GEN M, GEN ff); GEN FFM_inv(GEN M, GEN ff); GEN FFM_ker(GEN M, GEN ff); GEN FFM_mul(GEN M, GEN N, GEN ff); long FFM_rank(GEN M, GEN ff); GEN FFX_factor(GEN f, GEN x); GEN FFX_roots(GEN f, GEN x); GEN Z_FF_div(GEN a, GEN b); GEN ffgen(GEN T, long v); GEN fflog(GEN x, GEN g, GEN o); GEN fforder(GEN x, GEN o); GEN ffprimroot(GEN x, GEN *o); GEN ffrandom(GEN ff); 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); /* galconj.c */ GEN checkgal(GEN gal); GEN checkgroup(GEN g, GEN *S); GEN embed_disc(GEN r, long r1, long prec); GEN embed_roots(GEN r, long r1); GEN galois_group(GEN gal); GEN galoisconj(GEN nf, GEN d); GEN galoisconj0(GEN nf, long flag, GEN d, long prec); GEN galoisexport(GEN gal, long format); GEN galoisfixedfield(GEN gal, GEN v, long flag, long y); GEN galoisidentify(GEN gal); GEN galoisinit(GEN nf, GEN den); GEN galoisisabelian(GEN gal, long flag); long galoisisnormal(GEN gal, GEN sub); GEN galoispermtopol(GEN gal, GEN perm); GEN galoissubgroups(GEN G); GEN galoissubfields(GEN G, long flag, long v); long numberofconjugates(GEN T, long pdepart); GEN vandermondeinverse(GEN L, GEN T, GEN den, GEN prep); /* galpol.c */ GEN galoisnbpol(long a); GEN galoisgetpol(long a, long b, long s); /* gen1.c */ GEN conjvec(GEN x,long prec); GEN gadd(GEN x, GEN y); GEN gaddsg(long x, GEN y); GEN gconj(GEN x); GEN gdiv(GEN x, GEN y); GEN gdivgs(GEN x, long s); GEN ginv(GEN x); GEN gmul(GEN x, GEN y); GEN gmul2n(GEN x, long n); GEN gmulsg(long s, GEN y); GEN gsqr(GEN x); GEN gsub(GEN x, GEN y); GEN gsubsg(long x, GEN y); GEN inv_ser(GEN b); GEN mulcxI(GEN x); GEN mulcxmI(GEN x); GEN ser_normalize(GEN x); /* gen2.c */ GEN gassoc_proto(GEN f(GEN,GEN),GEN,GEN); GEN map_proto_G(GEN f(GEN), GEN x); GEN map_proto_lG(long f(GEN), GEN x); GEN map_proto_lGL(long f(GEN,long), GEN x, long y); long Q_pval(GEN x, GEN p); long Q_pvalrem(GEN x, GEN p, GEN *y); long RgX_val(GEN x); long RgX_valrem(GEN x, GEN *z); long RgX_valrem_inexact(GEN x, GEN *Z); int ZV_Z_dvd(GEN v, GEN p); long ZV_pval(GEN x, GEN p); long ZV_pvalrem(GEN x, GEN p, GEN *px); long ZV_lval(GEN x, ulong p); long ZV_lvalrem(GEN x, ulong p, GEN *px); long ZX_lvalrem(GEN x, ulong p, GEN *px); long ZX_lval(GEN x, ulong p); long ZX_pval(GEN x, GEN p); long ZX_pvalrem(GEN x, GEN p, GEN *px); long Z_lval(GEN n, ulong p); long Z_lvalrem(GEN n, ulong p, GEN *py); long Z_lvalrem_stop(GEN *n, ulong p, int *stop); long Z_pval(GEN n, GEN p); long Z_pvalrem(GEN x, GEN p, GEN *py); GEN cgetp(GEN x); GEN cvstop2(long s, GEN y); GEN cvtop(GEN x, GEN p, long l); GEN cvtop2(GEN x, GEN y); GEN gabs(GEN x, long prec); void gaffect(GEN x, GEN y); void gaffsg(long s, GEN x); int gcmp(GEN x, GEN y); int gequal0(GEN x); int gequal1(GEN x); int gequalX(GEN x); int gequalm1(GEN x); int gcmpsg(long x, GEN y); GEN gcvtop(GEN x, GEN p, long r); int gequal(GEN x, GEN y); int gequalsg(long s, GEN x); long gexpo(GEN x); long gvaluation(GEN x, GEN p); int gidentical(GEN x, GEN y); long glength(GEN x); GEN gmax(GEN x, GEN y); GEN gmaxgs(GEN x, long y); GEN gmin(GEN x, GEN y); GEN gmings(GEN x, long y); GEN gneg(GEN x); GEN gneg_i(GEN x); GEN RgX_to_ser(GEN x, long l); GEN RgX_to_ser_inexact(GEN x, long l); int gsigne(GEN x); GEN gtolist(GEN x); long gtolong(GEN x); int lexcmp(GEN x, GEN y); GEN listinsert(GEN list, GEN object, long index); void listpop(GEN L, long index); GEN listput(GEN list, GEN object, long index); void listsort(GEN list, long flag); GEN matsize(GEN x); GEN mklistcopy(GEN x); GEN normalize(GEN x); GEN normalizepol(GEN x); GEN normalizepol_approx(GEN x, long lx); GEN normalizepol_lg(GEN x, long lx); ulong padic_to_Fl(GEN x, ulong p); GEN padic_to_Fp(GEN x, GEN Y); GEN quadtofp(GEN x, long l); GEN rfrac_to_ser(GEN x, long l); long sizedigit(GEN x); long u_lval(ulong x, ulong p); long u_lvalrem(ulong x, ulong p, ulong *py); long u_lvalrem_stop(ulong *n, ulong p, int *stop); long u_pval(ulong x, GEN p); long u_pvalrem(ulong x, GEN p, ulong *py); long vecindexmax(GEN x); long vecindexmin(GEN x); GEN vecmax0(GEN x, GEN *pv); GEN vecmax(GEN x); GEN vecmin0(GEN x, GEN *pv); GEN vecmin(GEN x); long z_lval(long s, ulong p); long z_lvalrem(long s, ulong p, long *py); long z_pval(long n, GEN p); long z_pvalrem(long n, GEN p, long *py); /* gen3.c */ GEN padic_to_Q(GEN x); GEN padic_to_Q_shallow(GEN x); GEN QpV_to_QV(GEN v); GEN RgM_mulreal(GEN x, GEN y); GEN RgX_RgM_eval_col(GEN x, GEN M, long c); GEN RgX_deflate_max(GEN x0, long *m); GEN RgX_integ(GEN x); GEN ceil_safe(GEN x); GEN ceilr(GEN x); GEN centerlift(GEN x); GEN centerlift0(GEN x,long v); GEN compo(GEN x, long n); GEN deg1pol(GEN x1, GEN x0,long v); GEN deg1pol_shallow(GEN x1, GEN x0,long v); long degree(GEN x); GEN denom(GEN x); GEN deriv(GEN x, long v); GEN derivser(GEN x); GEN diffop(GEN x, GEN v, GEN dv); GEN diffop0(GEN x, GEN v, GEN dv, long n); GEN diviiround(GEN x, GEN y); GEN divrem(GEN x, GEN y, long v); GEN floor_safe(GEN x); GEN gceil(GEN x); GEN gcvtoi(GEN x, long *e); GEN gdeflate(GEN x, long v, long d); GEN gdivent(GEN x, GEN y); GEN gdiventgs(GEN x, long y); GEN gdiventsg(long x, GEN y); GEN gdiventres(GEN x, GEN y); GEN gdivmod(GEN x, GEN y, GEN *pr); GEN gdivround(GEN x, GEN y); int gdvd(GEN x, GEN y); GEN geq(GEN x, GEN y); GEN geval(GEN x); GEN gfloor(GEN x); GEN gtrunc2n(GEN x, long s); GEN gfrac(GEN x); GEN gge(GEN x, GEN y); GEN ggrando(GEN x, long n); GEN ggt(GEN x, GEN y); GEN gimag(GEN x); GEN gle(GEN x, GEN y); GEN glt(GEN x, GEN y); GEN gmod(GEN x, GEN y); GEN gmodgs(GEN x, long y); GEN gmodsg(long x, GEN y); GEN gmodulo(GEN x,GEN y); GEN gmodulsg(long x, GEN y); GEN gmodulss(long x, long y); GEN gne(GEN x, GEN y); GEN gnot(GEN x); GEN gpolvar(GEN y); long gprecision(GEN x); GEN greal(GEN x); GEN grndtoi(GEN x, long *e); GEN ground(GEN x); GEN gshift(GEN x, long n); GEN gsubst(GEN x, long v, GEN y); GEN gsubstpol(GEN x, GEN v, GEN y); GEN gsubstvec(GEN x, GEN v, GEN y); GEN gtocol(GEN x); GEN gtocol0(GEN x, long n); GEN gtocolrev(GEN x); GEN gtocolrev0(GEN x, long n); GEN gtopoly(GEN x, long v); GEN gtopolyrev(GEN x, long v); GEN gtoser(GEN x, long v, long precdl); GEN gtovec(GEN x); GEN gtovec0(GEN x, long n); GEN gtovecrev(GEN x); GEN gtovecrev0(GEN x, long n); GEN gtovecsmall(GEN x); GEN gtovecsmall0(GEN x, long n); GEN gtrunc(GEN x); long gvar(GEN x); long gvar2(GEN x); GEN hqfeval(GEN q, GEN x); GEN imag_i(GEN x); GEN integ(GEN x, long v); GEN integser(GEN x); int iscomplex(GEN x); int isexactzero(GEN g); int isrationalzeroscalar(GEN g); int isinexact(GEN x); int isinexactreal(GEN x); int isint(GEN n, GEN *ptk); int isrationalzero(GEN g); int issmall(GEN n, long *ptk); GEN lift(GEN x); GEN lift0(GEN x,long v); GEN liftall(GEN x); GEN liftall_shallow(GEN x); GEN liftint(GEN x); GEN liftint_shallow(GEN x); GEN liftpol(GEN x); GEN liftpol_shallow(GEN x); GEN mkcoln(long n, ...); GEN mkintn(long n, ...); GEN mkpoln(long n, ...); GEN mkvecn(long n, ...); GEN mkvecsmalln(long n, ...); GEN mulreal(GEN x, GEN y); GEN numer(GEN x); long padicprec(GEN x, GEN p); long padicprec_relative(GEN x); GEN polcoeff0(GEN x,long n,long v); GEN polcoeff_i(GEN x, long n, long v); long poldegree(GEN x,long v); long RgX_degree(GEN x,long v); GEN poleval(GEN x, GEN y); GEN pollead(GEN x,long v); long precision(GEN x); GEN precision0(GEN x,long n); GEN qf_apply_RgM(GEN q, GEN M); GEN qf_apply_ZM(GEN q, GEN M); GEN qfbil(GEN x, GEN y, GEN q); GEN qfeval(GEN q, GEN x); GEN qfevalb(GEN q, GEN x, GEN y); GEN qfnorm(GEN x, GEN q); GEN real_i(GEN x); GEN round0(GEN x, GEN *pte); GEN roundr(GEN x); GEN roundr_safe(GEN x); GEN scalarpol(GEN x, long v); GEN scalarpol_shallow(GEN x, long v); GEN scalarser(GEN x, long v, long prec); GEN ser_unscale(GEN P, GEN h); GEN serreverse(GEN x); GEN simplify(GEN x); GEN simplify_shallow(GEN x); 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); /* genus2red.c */ GEN genus2red(GEN Q, GEN P, GEN p); /* groupid.c */ long group_ident(GEN G, GEN S); long group_ident_trans(GEN G, GEN S); /* hash.c */ hashtable *hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack); void hash_insert(hashtable *h, void *k, void *v); hashentry *hash_search(hashtable *h, void *k); hashentry *hash_remove(hashtable *h, void *k); void hash_destroy(hashtable *h); ulong hash_str(const char *str); ulong hash_str2(const char *s); ulong hash_GEN(GEN x); /* 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 ZM_hnfmod(GEN x, GEN d); GEN ZM_hnfmodall(GEN x, GEN dm, long flag); GEN ZM_hnfmodid(GEN x, GEN d); GEN ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm); void ZM_snfclean(GEN d, GEN u, GEN v); GEN ZM_snf(GEN x); GEN ZM_snf_group(GEN H, GEN *newU, GEN *newUi); GEN ZM_snfall(GEN x, GEN *ptU, GEN *ptV); GEN ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, int return_vec); GEN zlm_echelon(GEN x, long early_abort, ulong p, ulong pm); GEN ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm); GEN gsmith(GEN x); GEN gsmithall(GEN x); GEN hnf(GEN x); GEN hnf_divscale(GEN A, GEN B,GEN t); GEN hnf_solve(GEN A, GEN B); GEN hnf_invimage(GEN A, GEN b); GEN hnfall(GEN x); int hnfdivide(GEN A, GEN B); GEN hnflll(GEN x); GEN hnfmerge_get_1(GEN A, GEN B); GEN hnfmod(GEN x, GEN d); GEN hnfmodid(GEN x,GEN p); GEN hnfperm(GEN x); GEN matfrobenius(GEN M, long flag, long v); GEN mathnf0(GEN x, long flag); GEN matsnf0(GEN x, long flag); GEN smith(GEN x); GEN smithall(GEN x); GEN smithclean(GEN z); /* ifactor1.c */ GEN Z_factor(GEN n); GEN Z_factor_limit(GEN n, ulong all); GEN Z_factor_until(GEN n, GEN limit); long Z_issmooth(GEN m, ulong lim); GEN Z_issmooth_fact(GEN m, ulong lim); long Z_issquarefree(GEN x); GEN absi_factor(GEN n); GEN absi_factor_limit(GEN n, ulong all); long bigomega(GEN n); GEN core(GEN n); ulong coreu(ulong n); GEN eulerphi(GEN n); ulong eulerphiu(ulong n); ulong eulerphiu_fact(GEN f); GEN factorint(GEN n, long flag); GEN factoru(ulong n); int ifac_isprime(GEN x); int ifac_next(GEN *part, GEN *p, long *e); int ifac_read(GEN part, GEN *p, long *e); void ifac_skip(GEN part); GEN ifac_start(GEN n, int moebius); int is_357_power(GEN x, GEN *pt, ulong *mask); int is_pth_power(GEN x, GEN *pt, forprime_t *T, ulong cutoffbits); long ispowerful(GEN n); long issquarefree(GEN x); long istotient(GEN n, GEN *px); long moebius(GEN n); long moebiusu(ulong n); GEN nextprime(GEN n); GEN numdiv(GEN n); long omega(GEN n); GEN precprime(GEN n); GEN sumdiv(GEN n); GEN sumdivk(GEN n,long k); ulong tridiv_bound(GEN n); int uis_357_power(ulong x, ulong *pt, ulong *mask); int uis_357_powermod(ulong x, ulong *mask); long uissquarefree(ulong n); long uissquarefree_fact(GEN f); ulong unextprime(ulong n); ulong uprecprime(ulong n); 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); int chk_gerepileupto(GEN x); GENbin* copy_bin(GEN x); GENbin* copy_bin_canon(GEN x); void dbg_gerepile(pari_sp av); void dbg_gerepileupto(GEN q); GEN errname(GEN err); GEN gclone(GEN x); GEN gcloneref(GEN x); void gclone_refc(GEN x); GEN gcopy(GEN x); GEN gcopy_avma(GEN x, pari_sp *AVMA); GEN gcopy_lg(GEN x, long lx); GEN gerepile(pari_sp ltop, pari_sp lbot, GEN q); void gerepileallsp(pari_sp av, pari_sp tetpil, int n, ...); void gerepilecoeffssp(pari_sp av, pari_sp tetpil, long *g, int n); void gerepilemanysp(pari_sp av, pari_sp tetpil, GEN* g[], int n); GEN getheap(void); void gp_context_save(struct gp_context* rec); void gp_context_restore(struct gp_context* rec); long gsizeword(GEN x); long gsizebyte(GEN x); void gunclone(GEN x); void gunclone_deep(GEN x); GEN listcopy(GEN x); void timer_printf(pari_timer *T, const char *format, ...); void msgtimer(const char *format, ...); long name_numerr(const char *s); 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); void obj_free(GEN S); GEN obj_init(long d, long n); GEN obj_insert(GEN S, long K, GEN O); 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); int pari_daemon(void); void pari_err(int numerr, ...); GEN pari_err_last(void); char * pari_err2str(GEN err); void pari_init_opts(size_t parisize, ulong maxprime, ulong init_opts); void pari_init(size_t parisize, ulong maxprime); void pari_stackcheck_init(void *pari_stack_base); void pari_sig_init(void (*f)(int)); void pari_thread_alloc(struct pari_thread *t, size_t s, GEN arg); 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); GEN pari_version(void); void pari_warn(int numerr, ...); GEN trap0(const char *e, GEN f, GEN r); void shiftaddress(GEN x, long dec); void shiftaddress_canon(GEN x, long dec); long timer(void); long timer2(void); void traverseheap( void(*f)(GEN, void *), void *data ); /* intnum.c */ GEN intcirc(void *E, GEN (*eval) (void *, GEN), GEN a, GEN R, GEN tab, long prec); GEN intfouriercos(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, GEN x, GEN tab, long prec); GEN intfourierexp(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN x, GEN tab, long prec); GEN intfouriersin(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, GEN x, GEN tab, long prec); GEN intfuncinit(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, long m, long flag, long prec); GEN intlaplaceinv(void *E, GEN (*eval) (void *, GEN), GEN sig, GEN x, GEN tab, long prec); GEN intmellininv(void *E, GEN (*eval) (void *, GEN), GEN sig, GEN x, GEN tab, long prec); GEN intmellininvshort(GEN sig, GEN x, GEN tab, long prec); GEN intnum(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, GEN tab, long prec); GEN intnuminit(GEN a, GEN b, long m, long prec); GEN intnuminitgen(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, long m, long flext, long prec); GEN intnumromb(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, long flag, long prec); long intnumstep(long prec); GEN sumnum(void *E, GEN (*f) (void *, GEN), GEN a, GEN sig, GEN tab, long flag, long prec); GEN sumnumalt(void *E, GEN (*f) (void *, GEN), GEN a, GEN s, GEN tab, long flag, long prec); GEN sumnuminit(GEN sig, long m, long sgn, long prec); /* krasner.c */ GEN padicfields0(GEN p, GEN n, long flag); GEN padicfields(GEN p, long m, long d, long flag); /* kummer.c */ GEN rnfkummer(GEN bnr, GEN subgroup, long all, long prec); /* lll.c */ GEN ZM_lll_norms(GEN x, double D, long flag, GEN *B); GEN kerint(GEN x); GEN lll(GEN x); GEN lllfp(GEN x, double D, long flag); GEN lllgen(GEN x); GEN lllgram(GEN x); GEN lllgramgen(GEN x); GEN lllgramint(GEN x); GEN lllgramkerim(GEN x); GEN lllgramkerimgen(GEN x); GEN lllint(GEN x); GEN lllintpartial(GEN mat); GEN lllintpartial_inplace(GEN mat); GEN lllkerim(GEN x); GEN lllkerimgen(GEN x); GEN matkerint0(GEN x,long flag); GEN qflll0(GEN x, long flag); GEN qflllgram0(GEN x, long flag); /* members.c */ GEN member_a1(GEN x); GEN member_a2(GEN x); GEN member_a3(GEN x); GEN member_a4(GEN x); GEN member_a6(GEN x); GEN member_area(GEN x); GEN member_b2(GEN x); GEN member_b4(GEN x); GEN member_b6(GEN x); GEN member_b8(GEN x); GEN member_bid(GEN x); GEN member_bnf(GEN x); GEN member_c4(GEN x); GEN member_c6(GEN x); GEN member_clgp(GEN x); GEN member_codiff(GEN x); GEN member_cyc(GEN clg); GEN member_diff(GEN x); GEN member_disc(GEN x); GEN member_e(GEN x); GEN member_eta(GEN x); GEN member_f(GEN x); GEN member_fu(GEN x); GEN member_futu(GEN x); GEN member_gen(GEN x); GEN member_group(GEN x); GEN member_index(GEN x); GEN member_j(GEN x); GEN member_mod(GEN x); GEN member_nf(GEN x); GEN member_no(GEN clg); GEN member_omega(GEN x); GEN member_orders(GEN x); GEN member_p(GEN x); GEN member_pol(GEN x); GEN member_polabs(GEN x); GEN member_reg(GEN x); GEN member_r1(GEN x); GEN member_r2(GEN x); GEN member_roots(GEN x); GEN member_sign(GEN x); GEN member_t2(GEN x); GEN member_tate(GEN x); GEN member_tufu(GEN x); GEN member_tu(GEN x); GEN member_zk(GEN x); GEN member_zkst(GEN bid); /* 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_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); int absi_equal(GEN x, GEN y); int absr_cmp(GEN x, GEN y); GEN addii_sign(GEN x, long sx, GEN y, long sy); GEN addir_sign(GEN x, long sx, GEN y, long sy); GEN addrr_sign(GEN x, long sx, GEN y, long sy); GEN addsi_sign(long x, GEN y, long sy); GEN addui_sign(ulong x, GEN y, long sy); GEN addsr(long x, GEN y); GEN addumului(ulong a, ulong b, GEN Y); 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); int cmpii(GEN x, GEN y); int cmprr(GEN x, GEN y); long dblexpo(double x); ulong dblmantissa(double x); GEN dbltor(double x); GEN diviiexact(GEN x, GEN y); GEN divir(GEN x, GEN y); GEN divis(GEN y, long x); GEN divis_rem(GEN x, long y, long *rem); GEN diviu_rem(GEN y, ulong x, ulong *rem); GEN diviuuexact(GEN x, ulong y, ulong z); GEN diviuexact(GEN x, ulong y); GEN divri(GEN x, GEN y); GEN divrr(GEN x, GEN y); GEN divrs(GEN x, long y); GEN divru(GEN x, ulong y); GEN divsi(long x, GEN y); GEN divsr(long x, GEN y); GEN divur(ulong x, GEN y); GEN dvmdii(GEN x, GEN y, GEN *z); int equalii(GEN x, GEN y); int equalrr(GEN x, GEN y); GEN floorr(GEN x); GEN gcdii(GEN x, GEN y); GEN int2n(long n); GEN int2u(ulong n); GEN int_normalize(GEN x, long known_zero_words); int invmod(GEN a, GEN b, GEN *res); ulong invmod2BIL(ulong b); GEN invr(GEN b); GEN mantissa_real(GEN x, long *e); GEN modii(GEN x, GEN y); void modiiz(GEN x, GEN y, GEN z); GEN mulii(GEN x, GEN y); GEN mulir(GEN x, GEN y); GEN mulrr(GEN x, GEN y); GEN mulsi(long x, GEN y); GEN mulsr(long x, GEN y); GEN mulss(long x, long y); GEN mului(ulong x, GEN y); GEN mulur(ulong x, GEN y); GEN muluu(ulong x, ulong y); GEN muluui(ulong x, ulong y, GEN z); GEN remi2n(GEN x, long n); double rtodbl(GEN x); GEN shifti(GEN x, long n); GEN sqri(GEN x); GEN sqrr(GEN x); GEN sqrs(long x); GEN sqrtr_abs(GEN x); GEN sqrtremi(GEN S, GEN *R); GEN sqru(ulong x); GEN subsr(long x, GEN y); GEN truedvmdii(GEN x, GEN y, GEN *z); GEN truedvmdis(GEN x, long y, GEN *z); GEN truedvmdsi(long x, GEN y, GEN *z); GEN trunc2nr(GEN x, long n); GEN mantissa2nr(GEN x, long n); GEN truncr(GEN x); ulong umodiu(GEN y, ulong x); long vals(ulong x); /* nffactor.c */ GEN FpC_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom); GEN FpM_ratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom); GEN FpX_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom); 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); GEN nfroots(GEN nf,GEN pol); GEN polfnf(GEN a, GEN t); GEN rootsof1(GEN x); GEN rootsof1_kannan(GEN nf); /* paricfg.c */ extern const char *paricfg_datadir; extern const char *paricfg_version; extern const char *paricfg_buildinfo; extern const long paricfg_version_code; extern const char *paricfg_vcsversion; extern const char *paricfg_compiledate; extern const char *paricfg_mt_engine; /* part.c */ void forpart(void *E, long call(void*,GEN), long k, GEN nbound, GEN abound); void forpart_init(forpart_t *T, long k, GEN abound, GEN nbound); GEN forpart_next(forpart_t *T); GEN forpart_prev(forpart_t *T); GEN numbpart(GEN x); GEN partitions(long k, GEN nbound, GEN abound); /* perm.c */ GEN abelian_group(GEN G); GEN cyclicgroup(GEN g, long s); GEN cyc_pow(GEN cyc, long exp); GEN cyc_pow_perm(GEN cyc, long exp); GEN dicyclicgroup(GEN g1, GEN g2, long s1, long s2); GEN group_abelianHNF(GEN G, GEN L); GEN group_abelianSNF(GEN G, GEN L); long group_domain(GEN G); GEN group_elts(GEN G, long n); GEN group_export(GEN G, long format); long group_isA4S4(GEN G); long group_isabelian(GEN G); GEN group_leftcoset(GEN G, GEN g); long group_order(GEN G); long group_perm_normalize(GEN N, GEN g); GEN group_quotient(GEN G, GEN H); GEN group_rightcoset(GEN G, GEN g); GEN group_set(GEN G, long n); long group_subgroup_isnormal(GEN G, GEN H); GEN group_subgroups(GEN G); GEN groupelts_abelian_group(GEN S); GEN groupelts_center(GEN S); GEN groupelts_set(GEN G, long n); int perm_commute(GEN p, GEN q); GEN perm_cycles(GEN v); long perm_order(GEN perm); GEN perm_pow(GEN perm, long exp); GEN quotient_group(GEN C, GEN G); GEN quotient_perm(GEN C, GEN p); GEN quotient_subgroup_lift(GEN C, GEN H, GEN S); GEN subgroups_tableset(GEN S, long n); long tableset_find_index(GEN tbl, GEN set); GEN trivialgroup(void); GEN vecperm_orbits(GEN v, long n); GEN vec_insert(GEN v, long n, GEN x); int vec_is1to1(GEN v); int vec_isconst(GEN v); long vecsmall_duplicate(GEN x); long vecsmall_duplicate_sorted(GEN x); GEN vecsmall_indexsort(GEN V); void vecsmall_sort(GEN V); GEN vecsmall_uniq(GEN V); GEN vecsmall_uniq_sorted(GEN V); GEN vecvecsmall_indexsort(GEN x); long vecvecsmall_search(GEN x, GEN y, long flag); GEN vecvecsmall_sort(GEN x); GEN vecvecsmall_sort_uniq(GEN x); /* mt.c */ void mt_broadcast(GEN code); void mt_sigint_block(void); void mt_sigint_unblock(void); void mt_queue_end(struct pari_mt *pt); GEN mt_queue_get(struct pari_mt *pt, long *jobid, long *pending); void mt_queue_start(struct pari_mt *pt, GEN worker); void mt_queue_submit(struct pari_mt *pt, long jobid, GEN work); void pari_mt_init(void); void pari_mt_close(void); /* polarit1.c */ 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 */ GEN Q_content(GEN x); GEN Q_denom(GEN x); GEN Q_div_to_int(GEN x, GEN c); GEN Q_gcd(GEN x, GEN y); GEN Q_mul_to_int(GEN x, GEN c); GEN Q_muli_to_int(GEN x, GEN d); GEN Q_primitive_part(GEN x, GEN *ptc); GEN Q_primpart(GEN x); GEN Q_remove_denom(GEN x, GEN *ptd); GEN RgXQ_charpoly(GEN x, GEN T, long v); GEN RgXQ_inv(GEN x, GEN y); GEN RgX_disc(GEN x); GEN RgX_extgcd(GEN x, GEN y, GEN *U, GEN *V); GEN RgX_extgcd_simple(GEN a, GEN b, GEN *pu, GEN *pv); 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_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); GEN ZX_content(GEN x); GEN centermod(GEN x, GEN p); GEN centermod_i(GEN x, GEN p, GEN ps2); GEN centermodii(GEN x, GEN p, GEN po2); GEN content(GEN x); GEN deg1_from_roots(GEN L, long v); GEN divide_conquer_assoc(GEN x, void *data, GEN (*mul)(void*,GEN,GEN)); GEN divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN)); GEN factor(GEN x); GEN factor0(GEN x,long flag); GEN factorback(GEN fa); GEN factorback2(GEN fa,GEN e); GEN famat_mul_shallow(GEN f, GEN g); GEN gbezout(GEN x, GEN y, GEN *u, GEN *v); GEN gdivexact(GEN x, GEN y); GEN gen_factorback(GEN L, GEN e, GEN (*_mul)(void*,GEN,GEN), GEN (*_pow)(void*,GEN,GEN), void *data); GEN ggcd(GEN x, GEN y); GEN ggcd0(GEN x, GEN y); GEN ginvmod(GEN x, GEN y); GEN glcm(GEN x, GEN y); GEN glcm0(GEN x, GEN y); GEN gp_factor0(GEN x, GEN flag); GEN idealfactorback(GEN nf, GEN L, GEN e, int red); long isirreducible(GEN x); GEN newtonpoly(GEN x, GEN p); GEN nffactorback(GEN nf, GEN L, GEN e); GEN nfrootsQ(GEN x); GEN poldisc0(GEN x, long v); GEN polresultant0(GEN x, GEN y,long v,long flag); GEN polsym(GEN x, long n); GEN primitive_part(GEN x, GEN *c); GEN primpart(GEN x); GEN reduceddiscsmith(GEN pol); GEN resultant2(GEN x, GEN y); GEN resultant_all(GEN u, GEN v, GEN *sol); GEN rnfcharpoly(GEN nf, GEN T, GEN alpha, long v); GEN roots_from_deg1(GEN x); GEN roots_to_pol(GEN a, long v); GEN roots_to_pol_r1(GEN a, long v, long r1); long sturmpart(GEN x, GEN a, GEN b); GEN subresext(GEN x, GEN y, GEN *U, GEN *V); GEN sylvestermatrix(GEN x,GEN y); GEN trivial_fact(void); GEN gcdext0(GEN x, GEN y); GEN polresultantext0(GEN x, GEN y, long v); GEN polresultantext(GEN x, GEN y); GEN prime_fact(GEN x); /* polarit3.c */ GEN Flx_FlxY_resultant(GEN a, GEN b, ulong pp); GEN Flx_factorff_irred(GEN P, GEN Q, ulong p); void Flx_ffintersect(GEN P,GEN Q,long n,ulong l,GEN *SP,GEN *SQ,GEN MA,GEN MB); GEN Flx_ffisom(GEN P,GEN Q,ulong l); GEN Flx_roots_naive(GEN f, ulong p); GEN FlxX_resultant(GEN u, GEN v, ulong p, long sx); GEN Flxq_ffisom_inv(GEN S,GEN Tp, ulong p); GEN FpV_polint(GEN xa, GEN ya, GEN p, long v); GEN FpX_FpXY_resultant(GEN a, GEN b0, GEN p); GEN FpX_factorff_irred(GEN P, GEN Q, GEN p); void FpX_ffintersect(GEN P,GEN Q,long n,GEN l,GEN *SP,GEN *SQ,GEN MA,GEN MB); GEN FpX_ffisom(GEN P,GEN Q,GEN l); GEN FpX_translate(GEN P, GEN c, GEN p); GEN FpXQ_ffisom_inv(GEN S,GEN Tp, GEN p); GEN FpXV_FpC_mul(GEN V, GEN W, GEN p); 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_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); GEN Fq_mulu(GEN x, ulong y, /*unused*/GEN T, GEN p); GEN Fq_neg(GEN x, GEN T, GEN p); GEN Fq_neg_inv(GEN x, GEN T, GEN p); GEN Fq_pow(GEN x, GEN n, GEN T, GEN p); GEN Fq_powu(GEN x, ulong n, GEN pol, GEN p); GEN Fq_sub(GEN x, GEN y, GEN T/*unused*/, GEN p); GEN Fq_sqr(GEN x, GEN T, GEN p); GEN Fq_sqrt(GEN x, GEN T, GEN p); GEN Fq_sqrtn(GEN x, GEN n, GEN T, GEN p, GEN *zeta); GEN FqC_add(GEN x, GEN y, GEN T, GEN p); GEN FqC_sub(GEN x, GEN y, GEN T, GEN p); GEN FqC_Fq_mul(GEN x, GEN y, GEN T, GEN p); GEN FqC_to_FlxC(GEN v, GEN T, GEN pp); GEN FqM_to_FlxM(GEN x, GEN T, GEN pp); GEN FqV_roots_to_pol(GEN V, GEN T, GEN p, long v); GEN FqV_red(GEN z, GEN T, GEN p); GEN FqV_to_FlxV(GEN v, GEN T, GEN pp); GEN FqX_Fq_add(GEN y, GEN x, GEN T, GEN p); GEN FqX_Fq_mul_to_monic(GEN P, GEN U, GEN T, GEN p); GEN FqX_eval(GEN x, GEN y, GEN T, GEN p); GEN FqX_normalize(GEN z, GEN T, GEN p); GEN FqX_translate(GEN P, GEN c, GEN T, GEN p); GEN FqXQ_powers(GEN x, long l, GEN S, GEN T, GEN p); GEN FqXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p); GEN FqXY_eval(GEN Q, GEN y, GEN x, GEN T, GEN p); GEN FqXY_evalx(GEN Q, GEN x, GEN T, GEN p); GEN QX_disc(GEN x); GEN QX_gcd(GEN a,GEN b); GEN QX_resultant(GEN A, GEN B); GEN QXQ_intnorm(GEN A, GEN B); GEN QXQ_inv(GEN A, GEN B); GEN QXQ_norm(GEN A, GEN B); int Rg_is_Fp(GEN x, GEN *p); int Rg_is_FpXQ(GEN x, GEN *pT, GEN *pp); GEN Rg_to_Fp(GEN x, GEN p); GEN Rg_to_FpXQ(GEN x, GEN T, GEN p); GEN RgC_to_Flc(GEN x, ulong p); GEN RgC_to_FpC(GEN x, GEN p); int RgM_is_FpM(GEN x, GEN *p); GEN RgM_to_Flm(GEN x, ulong p); GEN RgM_to_FpM(GEN x, GEN p); int RgV_is_FpV(GEN x, GEN *p); GEN RgV_to_FpV(GEN x, GEN p); int RgX_is_FpX(GEN x, GEN *p); GEN RgX_to_FpX(GEN x, GEN p); int RgX_is_FpXQX(GEN x, GEN *pT, GEN *pp); GEN RgX_to_FpXQX(GEN x, GEN T, GEN p); GEN RgX_to_FqX(GEN x, GEN T, GEN p); GEN ZX_ZXY_rnfequation(GEN A, GEN B, long *lambda); GEN ZXQ_charpoly(GEN A, GEN T, long v); GEN ZX_disc(GEN x); int ZX_is_squarefree(GEN x); GEN ZX_gcd(GEN A, GEN B); GEN ZX_gcd_all(GEN A, GEN B, GEN *Anew); GEN ZX_resultant(GEN A, GEN B); int Z_incremental_CRT(GEN *H, ulong Hp, GEN *q, ulong p); GEN Z_init_CRT(ulong Hp, ulong p); int ZM_incremental_CRT(GEN *H, GEN Hp, GEN *q, ulong p); GEN ZM_init_CRT(GEN Hp, ulong p); int ZX_incremental_CRT(GEN *ptH, GEN Hp, GEN *q, ulong p); GEN ZX_init_CRT(GEN Hp, ulong p, long v); GEN characteristic(GEN x); GEN ffinit(GEN p, long n, long v); GEN ffnbirred(GEN p, long n); GEN ffnbirred0(GEN p, long n, long flag); GEN ffsumnbirred(GEN p, long n); const struct bb_field *get_Fq_field(void **E, GEN T, GEN p); GEN init_Fq(GEN p, long n, long v); GEN pol_x_powers(long N, long v); GEN residual_characteristic(GEN x); /* prime.c */ long BPSW_isprime(GEN x); long BPSW_psp(GEN N); GEN addprimes(GEN primes); GEN gisprime(GEN x, long flag); GEN gispseudoprime(GEN x, long flag); GEN gprimepi_upper_bound(GEN x); GEN gprimepi_lower_bound(GEN x); long isprime(GEN x); long ispseudoprime(GEN x, long flag); long millerrabin(GEN n, long k); GEN prime(long n); GEN primepi(GEN x); double primepi_upper_bound(double x); double primepi_lower_bound(double x); GEN primes(long n); GEN primes_interval(GEN a, GEN b); GEN primes_interval_zv(ulong a, ulong b); GEN primes_upto_zv(ulong b); GEN primes0(GEN n); GEN primes_zv(long m); GEN randomprime(GEN N); GEN removeprimes(GEN primes); int uislucaspsp(ulong n); int uisprime(ulong n); ulong uprime(long n); ulong uprimepi(ulong n); /* qfisom.c */ GEN qfauto(GEN g, GEN flags); GEN qfauto0(GEN g, GEN flags); GEN qfautoexport(GEN g, long flag); GEN qfisom(GEN g, GEN h, GEN flags); GEN qfisom0(GEN g, GEN h, GEN flags); GEN qfisominit(GEN g, GEN flags); GEN qfisominit0(GEN g, GEN flags); /* random.c */ GEN genrand(GEN N); GEN getrand(void); ulong pari_rand(void); GEN randomi(GEN x); GEN randomr(long prec); ulong random_Fl(ulong n); void setrand(GEN seed); /* rootpol.c */ GEN QX_complex_roots(GEN p, long l); GEN ZX_graeffe(GEN p); GEN cleanroots(GEN x,long l); int isrealappr(GEN x, long l); GEN polgraeffe(GEN p); GEN polmod_to_embed(GEN x, long prec); GEN roots(GEN x,long l); /* subcyclo.c */ GEN factor_Aurifeuille(GEN p, long n); GEN factor_Aurifeuille_prime(GEN p, long n); GEN galoissubcyclo(GEN N, GEN sg, long flag, long v); GEN polsubcyclo(long n, long d, long v); /* subfield.c */ GEN nfsubfields(GEN nf, long d); /* subgroup.c */ GEN subgrouplist(GEN cyc, GEN bound); void forsubgroup(void *E, long fun(void*,GEN), GEN cyc, GEN B); /* stark.c */ GEN bnrL1(GEN bnr, GEN sbgrp, long flag, long prec); GEN bnrrootnumber(GEN bnr, GEN chi, long flag, long prec); GEN bnrstark(GEN bnr, GEN subgroup, long prec); /* sumiter.c */ GEN derivnum(void *E, GEN (*eval)(void *, GEN), GEN x, long prec); GEN derivfun(void *E, GEN (*eval)(void *, GEN), GEN x, long prec); GEN direuler(void *E, GEN (*eval)(void *, GEN), GEN ga, GEN gb, GEN c); int forcomposite_init(forcomposite_t *C, GEN a, GEN b); GEN forcomposite_next(forcomposite_t *C); GEN forprime_next(forprime_t *T); int forprime_init(forprime_t *T, GEN a, GEN b); int forvec_init(forvec_t *T, GEN x, long flag); GEN forvec_next(forvec_t *T); GEN polzag(long n, long m); GEN prodeuler(void *E, GEN (*eval)(void *, GEN), GEN ga, GEN gb, long prec); GEN prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN sumalt(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN sumpos2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); GEN suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec); ulong u_forprime_next(forprime_t *T); int u_forprime_init(forprime_t *T, ulong a, ulong b); void u_forprime_restrict(forprime_t *T, ulong c); int u_forprime_arith_init(forprime_t *T, ulong a, ulong b, ulong c, ulong q); GEN zbrent(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec); /* thue.c */ GEN bnfisintnorm(GEN x, GEN y); GEN bnfisintnormabs(GEN bnf, GEN a); GEN thue(GEN thueres, GEN rhs, GEN ne); GEN thueinit(GEN pol, long flag, long prec); /* trans1.c */ GEN Pi2n(long n, long prec); GEN PiI2(long prec); GEN PiI2n(long n, long prec); GEN Qp_exp(GEN x); GEN Qp_log(GEN x); GEN Qp_sqrt(GEN x); GEN Qp_sqrtn(GEN x, GEN n, GEN *zetan); long Zn_ispower(GEN a, GEN q, GEN K, GEN *pt); long Zn_issquare(GEN x, GEN n); GEN Zn_sqrt(GEN x, GEN n); GEN Zp_teichmuller(GEN x, GEN p, long n, GEN q); GEN agm(GEN x, GEN y, long prec); GEN constcatalan(long prec); GEN consteuler(long prec); GEN constlog2(long prec); GEN constpi(long prec); GEN cxexpm1(GEN z, long prec); GEN expIr(GEN x); GEN exp1r_abs(GEN x); GEN gcos(GEN x, long prec); GEN gcotan(GEN x, long prec); 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 gpowgs(GEN x, long n); GEN gsin(GEN x, long prec); void gsincos(GEN x, GEN *s, GEN *c, long prec); GEN gsqrt(GEN x, long prec); GEN gsqrtn(GEN x, GEN n, GEN *zetan, long prec); GEN gtan(GEN x, long prec); GEN logr_abs(GEN x); GEN mpcos(GEN x); GEN mpeuler(long prec); GEN mpcatalan(long prec); void mpsincosm1(GEN x, GEN *s, GEN *c); GEN mpexp(GEN x); GEN mpexpm1(GEN x); GEN mplog(GEN x); GEN mplog2(long prec); GEN mppi(long prec); GEN mpsin(GEN x); void mpsincos(GEN x, GEN *s, GEN *c); GEN powis(GEN x, long n); GEN powiu(GEN p, ulong k); GEN powrfrac(GEN x, long n, long d); GEN powrs(GEN x, long n); GEN powrshalf(GEN x, long s); GEN powru(GEN x, ulong n); GEN powruhalf(GEN x, ulong s); GEN powuu(ulong p, ulong k); GEN powgi(GEN x, GEN n); GEN serchop0(GEN s); GEN sqrtnint(GEN a, long n); GEN teich(GEN x); GEN trans_eval(const char *fun, GEN (*f) (GEN, long), GEN x, long prec); ulong upowuu(ulong p, ulong k); ulong usqrtn(ulong a, ulong n); ulong usqrt(ulong a); /* trans2.c */ GEN Qp_gamma(GEN x); GEN bernfrac(long n); GEN bernpol(long k, long v); GEN bernreal(long n, long prec); GEN gacosh(GEN x, long prec); GEN gacos(GEN x, long prec); GEN garg(GEN x, long prec); GEN gasinh(GEN x, long prec); GEN gasin(GEN x, long prec); GEN gatan(GEN x, long prec); GEN gatanh(GEN x, long prec); GEN gcosh(GEN x, long prec); GEN ggammah(GEN x, long prec); GEN ggamma(GEN x, long prec); GEN glngamma(GEN x, long prec); GEN gpsi(GEN x, long prec); GEN gsinh(GEN x, long prec); GEN gtanh(GEN x, long prec); void mpbern(long nomb, long prec); GEN mpfactr(long n, long prec); GEN sumformal(GEN T, long v); /* trans3.c */ GEN dilog(GEN x, long prec); 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 gpolylog(long m, GEN x, long prec); GEN gzeta(GEN x, long prec); GEN hyperu(GEN a, GEN b, GEN gx, 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 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 szeta(long x, long prec); GEN theta(GEN q, GEN z, long prec); GEN thetanullk(GEN q, long k, long prec); GEN trueeta(GEN x, long prec); GEN u_sumdedekind_coprime(long h, long k); GEN veceint1(GEN nmax, GEN C, long prec); GEN vecthetanullk(GEN q, long k, long prec); GEN vecthetanullk_tau(GEN tau, long k, long prec); 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); /* level1.h */ 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_mul(ulong a, ulong b, ulong p); INLINE ulong Fl_neg(ulong x, ulong p); INLINE ulong Fl_sqr(ulong a, ulong p); INLINE ulong Fl_sub(ulong a, ulong b, ulong p); INLINE ulong Fl_triple(ulong a, ulong p); INLINE GEN absi(GEN x); INLINE GEN absi_shallow(GEN x); INLINE GEN absr(GEN x); INLINE int absrnz_equal1(GEN x); INLINE int absrnz_equal2n(GEN x); INLINE GEN addii(GEN x, GEN y); INLINE void addiiz(GEN x, GEN y, GEN z); INLINE GEN addir(GEN x, GEN y); INLINE void addirz(GEN x, GEN y, GEN z); INLINE GEN addis(GEN x, long s); INLINE GEN addri(GEN x, GEN y); INLINE void addriz(GEN x, GEN y, GEN z); INLINE GEN addrr(GEN x, GEN y); INLINE void addrrz(GEN x, GEN y, GEN z); INLINE GEN addrs(GEN x, long s); INLINE GEN addsi(long x, GEN y); INLINE void addsiz(long s, GEN y, GEN z); INLINE void addsrz(long s, GEN y, GEN z); INLINE GEN addss(long x, long y); INLINE void addssz(long s, long y, GEN z); INLINE GEN adduu(ulong x, ulong y); INLINE void affgr(GEN x, GEN y); INLINE void affii(GEN x, GEN y); INLINE void affiz(GEN x, GEN y); INLINE void affrr_fixlg(GEN y, GEN z); INLINE void affsi(long s, GEN x); INLINE void affsr(long s, GEN x); INLINE void affsz(long x, GEN y); INLINE void affui(ulong s, GEN x); INLINE void affur(ulong s, GEN x); INLINE GEN cgetg(long x, long y); INLINE GEN cgetg_block(long x, long y); INLINE GEN cgetg_copy(GEN x, long *plx); INLINE GEN cgeti(long x); INLINE GEN cgetineg(long x); INLINE GEN cgetipos(long x); INLINE GEN cgetr(long x); INLINE GEN cgetr_block(long prec); INLINE int cmpir(GEN x, GEN y); INLINE int cmpis(GEN x, long y); INLINE int cmpiu(GEN x, ulong y); INLINE int cmpri(GEN x, GEN y); INLINE int cmprs(GEN x, long y); INLINE int cmpsi(long x, GEN y); INLINE int cmpsr(long x, GEN y); INLINE int cmpui(ulong x, GEN y); INLINE GEN cxtofp(GEN x, long prec); INLINE GEN divii(GEN a, GEN b); INLINE void diviiz(GEN x, GEN y, GEN z); INLINE void divirz(GEN x, GEN y, GEN z); INLINE void divisz(GEN x, long s, GEN z); INLINE void divriz(GEN x, GEN y, GEN z); INLINE void divrrz(GEN x, GEN y, GEN z); INLINE void divrsz(GEN y, long s, GEN z); INLINE GEN divsi_rem(long x, GEN y, long *rem); INLINE void divsiz(long x, GEN y, GEN z); INLINE void divsrz(long s, GEN y, GEN z); INLINE GEN divss(long x, long y); INLINE GEN divss_rem(long x, long y, long *rem); INLINE void divssz(long x, long y, GEN z); INLINE int dvdii(GEN x, GEN y); INLINE int dvdiiz(GEN x, GEN y, GEN z); INLINE int dvdis(GEN x, long y); INLINE int dvdisz(GEN x, long y, GEN z); INLINE int dvdiu(GEN x, ulong y); INLINE int dvdiuz(GEN x, ulong y, GEN z); INLINE int dvdsi(long x, GEN y); INLINE int dvdui(ulong x, GEN y); INLINE void dvmdiiz(GEN x, GEN y, GEN z, GEN t); INLINE GEN dvmdis(GEN x, long y, GEN *z); INLINE void dvmdisz(GEN x, long y, GEN z, GEN t); INLINE long dvmdsBIL(long n, long *r); INLINE GEN dvmdsi(long x, GEN y, GEN *z); INLINE void dvmdsiz(long x, GEN y, GEN z, GEN t); INLINE GEN dvmdss(long x, long y, GEN *z); INLINE void dvmdssz(long x, long y, GEN z, GEN t); INLINE ulong dvmduBIL(ulong n, ulong *r); INLINE int equalis(GEN x, long y); INLINE int equaliu(GEN x, ulong y); INLINE int equalsi(long x, GEN y); INLINE int equalui(ulong x, GEN y); INLINE long evalexpo(long x); INLINE long evallg(long x); INLINE long evalprecp(long x); INLINE long evalvalp(long x); INLINE long expi(GEN x); INLINE long expu(ulong x); INLINE void fixlg(GEN z, long ly); INLINE GEN fractor(GEN x, long prec); INLINE GEN icopy(GEN x); INLINE GEN icopyspec(GEN x, long nx); INLINE GEN icopy_avma(GEN x, pari_sp av); INLINE ulong int_bit(GEN x, long n); INLINE GEN itor(GEN x, long prec); INLINE long itos(GEN x); INLINE long itos_or_0(GEN x); INLINE ulong itou(GEN x); INLINE ulong itou_or_0(GEN x); INLINE GEN leafcopy(GEN x); INLINE GEN leafcopy_avma(GEN x, pari_sp av); INLINE double maxdd(double x, double y); INLINE long maxss(long x, long y); INLINE long maxuu(ulong x, ulong y); INLINE double mindd(double x, double y); INLINE long minss(long x, long y); INLINE long minuu(ulong x, ulong y); INLINE long mod16(GEN x); INLINE long mod2(GEN x); INLINE ulong mod2BIL(GEN x); INLINE long mod32(GEN x); INLINE long mod4(GEN x); INLINE long mod64(GEN x); INLINE long mod8(GEN x); INLINE GEN modis(GEN x, long y); INLINE void modisz(GEN y, long s, GEN z); INLINE GEN modsi(long x, GEN y); INLINE void modsiz(long s, GEN y, GEN z); INLINE GEN modss(long x, long y); INLINE void modssz(long s, long y, GEN z); INLINE GEN mpabs(GEN x); INLINE GEN mpabs_shallow(GEN x); INLINE GEN mpadd(GEN x, GEN y); INLINE void mpaddz(GEN x, GEN y, GEN z); INLINE void mpaff(GEN x, GEN y); INLINE GEN mpceil(GEN x); INLINE int mpcmp(GEN x, GEN y); INLINE GEN mpcopy(GEN x); INLINE GEN mpdiv(GEN x, GEN y); INLINE long mpexpo(GEN x); INLINE GEN mpfloor(GEN x); INLINE GEN mpmul(GEN x, GEN y); INLINE void mpmulz(GEN x, GEN y, GEN z); INLINE GEN mpneg(GEN x); INLINE int mpodd(GEN x); INLINE GEN mpround(GEN x); INLINE GEN mpshift(GEN x,long s); INLINE GEN mpsqr(GEN x); INLINE GEN mpsub(GEN x, GEN y); INLINE void mpsubz(GEN x, GEN y, GEN z); INLINE GEN mptrunc(GEN x); INLINE void muliiz(GEN x, GEN y, GEN z); INLINE void mulirz(GEN x, GEN y, GEN z); INLINE GEN mulis(GEN x, long s); INLINE GEN muliu(GEN x, ulong s); INLINE GEN mulri(GEN x, GEN s); INLINE void mulriz(GEN x, GEN y, GEN z); INLINE void mulrrz(GEN x, GEN y, GEN z); INLINE GEN mulrs(GEN x, long s); INLINE GEN mulru(GEN x, ulong s); INLINE void mulsiz(long s, GEN y, GEN z); INLINE void mulsrz(long s, GEN y, GEN z); INLINE void mulssz(long s, long y, GEN z); INLINE GEN negi(GEN x); INLINE GEN negr(GEN x); INLINE GEN new_chunk(size_t x); INLINE GEN rcopy(GEN x); INLINE GEN rdivii(GEN x, GEN y, long prec); INLINE void rdiviiz(GEN x, GEN y, GEN z); INLINE GEN rdivis(GEN x, long y, long prec); INLINE GEN rdivsi(long x, GEN y, long prec); INLINE GEN rdivss(long x, long y, long prec); INLINE GEN real2n(long n, long prec); INLINE GEN real_m2n(long n, long prec); INLINE GEN real_0(long prec); INLINE GEN real_0_bit(long bitprec); INLINE GEN real_1(long prec); INLINE GEN real_m1(long prec); 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 GEN remsi(long x, GEN y); INLINE void remsiz(long s, GEN y, GEN z); INLINE GEN remss(long x, long y); INLINE void remssz(long s, long y, GEN z); INLINE GEN rtor(GEN x, long prec); INLINE long sdivsi(long x, GEN y); INLINE long sdivsi_rem(long x, GEN y, long *rem); INLINE long sdivss_rem(long x, long y, long *rem); INLINE ulong udiviu_rem(GEN n, ulong d, ulong *r); INLINE ulong udivuu_rem(ulong x, ulong y, ulong *r); INLINE void setabssign(GEN x); INLINE void shift_left(GEN z2, GEN z1, long min, long M, ulong f, ulong sh); INLINE void shift_right(GEN z2, GEN z1, long min, long M, ulong f, ulong sh); INLINE ulong shiftl(ulong x, ulong y); INLINE ulong shiftlr(ulong x, ulong y); INLINE GEN shiftr(GEN x, long n); INLINE void shiftr_inplace(GEN z, long d); INLINE long smodis(GEN x, long y); INLINE long smodss(long x, long y); INLINE void stackdummy(pari_sp av, pari_sp ltop); INLINE char *stack_malloc(size_t N); INLINE char *stack_calloc(size_t N); INLINE GEN stoi(long x); INLINE GEN stor(long x, long prec); INLINE GEN subii(GEN x, GEN y); INLINE void subiiz(GEN x, GEN y, GEN z); INLINE GEN subir(GEN x, GEN y); INLINE void subirz(GEN x, GEN y, GEN z); INLINE GEN subis(GEN x, long y); INLINE void subisz(GEN y, long s, GEN z); INLINE GEN subri(GEN x, GEN y); INLINE void subriz(GEN x, GEN y, GEN z); INLINE GEN subrr(GEN x, GEN y); INLINE void subrrz(GEN x, GEN y, GEN z); INLINE GEN subrs(GEN x, long y); INLINE void subrsz(GEN y, long s, GEN z); INLINE GEN subsi(long x, GEN y); INLINE void subsiz(long s, GEN y, GEN z); INLINE void subsrz(long s, GEN y, GEN z); INLINE GEN subss(long x, long y); INLINE void subssz(long x, long y, GEN z); INLINE GEN subuu(ulong x, ulong y); INLINE void togglesign(GEN x); INLINE void togglesign_safe(GEN *px); INLINE void affectsign(GEN x, GEN y); INLINE void affectsign_safe(GEN x, GEN *py); 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 umodui(ulong x, GEN y); INLINE GEN utoi(ulong x); INLINE GEN utoineg(ulong x); INLINE GEN utoipos(ulong x); 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); /* pariinl.h */ INLINE GEN abgrp_get_cyc(GEN x); INLINE GEN abgrp_get_gen(GEN x); INLINE GEN abgrp_get_no(GEN x); INLINE GEN bid_get_arch(GEN bid); INLINE GEN bid_get_cyc(GEN bid); INLINE GEN bid_get_gen(GEN bid); INLINE GEN bid_get_gen_nocheck(GEN bid); INLINE GEN bid_get_grp(GEN bid); INLINE GEN bid_get_ideal(GEN bid); INLINE GEN bid_get_mod(GEN bid); INLINE GEN bid_get_no(GEN bid); INLINE GEN bnf_get_clgp(GEN bnf); INLINE GEN bnf_get_cyc(GEN bnf); INLINE GEN bnf_get_fu(GEN bnf); INLINE GEN bnf_get_fu_nocheck(GEN bnf); INLINE GEN bnf_get_gen(GEN bnf); INLINE GEN bnf_get_logfu(GEN bnf); INLINE GEN bnf_get_nf(GEN bnf); INLINE GEN bnf_get_no(GEN bnf); INLINE GEN bnf_get_reg(GEN bnf); INLINE GEN bnf_get_tuU(GEN bnf); INLINE long bnf_get_tuN(GEN bnf); INLINE GEN bnr_get_bnf(GEN bnr); INLINE GEN bnr_get_clgp(GEN bnr); INLINE GEN bnr_get_cyc(GEN bnr); INLINE GEN bnr_get_gen(GEN bnr); INLINE GEN bnr_get_gen_nocheck(GEN bnr); INLINE GEN bnr_get_no(GEN bnr); INLINE GEN bnr_get_bid(GEN bnr); INLINE GEN bnr_get_mod(GEN bnr); INLINE GEN bnr_get_nf(GEN bnr); INLINE GEN ell_get_a1(GEN e); INLINE GEN ell_get_a2(GEN e); INLINE GEN ell_get_a3(GEN e); INLINE GEN ell_get_a4(GEN e); INLINE GEN ell_get_a6(GEN e); INLINE GEN ell_get_b2(GEN e); INLINE GEN ell_get_b4(GEN e); INLINE GEN ell_get_b6(GEN e); INLINE GEN ell_get_b8(GEN e); INLINE GEN ell_get_c4(GEN e); INLINE GEN ell_get_c6(GEN e); INLINE GEN ell_get_disc(GEN e); INLINE GEN ell_get_j(GEN e); INLINE long ell_get_type(GEN e); 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 ellQp_get_p(GEN E); INLINE long ellQp_get_prec(GEN E); INLINE GEN ellQp_get_zero(GEN x); INLINE long ellR_get_prec(GEN x); INLINE long ellR_get_sign(GEN x); INLINE GEN gal_get_pol(GEN gal); INLINE GEN gal_get_p(GEN gal); INLINE GEN gal_get_e(GEN gal); INLINE GEN gal_get_mod(GEN gal); INLINE GEN gal_get_roots(GEN gal); INLINE GEN gal_get_invvdm(GEN gal); INLINE GEN gal_get_den(GEN gal); INLINE GEN gal_get_group(GEN gal); INLINE GEN gal_get_gen(GEN gal); INLINE GEN gal_get_orders(GEN gal); 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 nf_get_M(GEN nf); INLINE GEN nf_get_G(GEN nf); INLINE GEN nf_get_Tr(GEN nf); INLINE GEN nf_get_diff(GEN nf); INLINE long nf_get_degree(GEN nf); INLINE GEN nf_get_disc(GEN nf); INLINE GEN nf_get_index(GEN nf); 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_roots(GEN nf); INLINE GEN nf_get_roundG(GEN nf); INLINE void nf_get_sign(GEN nf, long *r1, long *r2); INLINE long nf_get_varn(GEN nf); INLINE GEN nf_get_zk(GEN nf); INLINE long pr_get_e(GEN pr); INLINE long pr_get_f(GEN pr); INLINE GEN pr_get_gen(GEN pr); 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 long rnf_get_absdegree(GEN rnf); INLINE long rnf_get_degree(GEN rnf); INLINE GEN rnf_get_invzk(GEN rnf); INLINE GEN rnf_get_map(GEN rnf); INLINE GEN rnf_get_nf(GEN rnf); INLINE long rnf_get_nfdegree(GEN rnf); INLINE GEN rnf_get_nfpol(GEN rnf); INLINE long rnf_get_nfvarn(GEN rnf); INLINE GEN rnf_get_pol(GEN rnf); INLINE GEN rnf_get_polabs(GEN rnf); INLINE GEN rnf_get_zk(GEN nf); INLINE void rnf_get_nfzk(GEN rnf, GEN *b, GEN *cb); INLINE long rnf_get_varn(GEN rnf); INLINE long closure_arity(GEN C); INLINE const char * closure_codestr(GEN C); INLINE GEN closure_get_code(GEN C); INLINE GEN closure_get_oper(GEN C); 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 GEN addmuliu(GEN x, GEN y, ulong u); INLINE GEN addmuliu_inplace(GEN x, GEN y, ulong u); INLINE GEN lincombii(GEN u, GEN v, GEN x, GEN y); INLINE GEN mulsubii(GEN y, GEN z, GEN x); INLINE GEN submulii(GEN x, GEN y, GEN z); INLINE GEN submuliu(GEN x, GEN y, ulong u); INLINE GEN submuliu_inplace(GEN x, GEN y, ulong u); INLINE GEN FpXQ_add(GEN x,GEN y,GEN T,GEN p); INLINE GEN FpXQ_sub(GEN x,GEN y,GEN T,GEN p); INLINE GEN Flxq_add(GEN x,GEN y,GEN T,ulong p); INLINE GEN Flxq_sub(GEN x,GEN y,GEN T,ulong p); INLINE GEN FpXQX_div(GEN x, GEN y, GEN T, GEN p); 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 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_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_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); INLINE GEN FqX_sub(GEN x,GEN y,GEN T,GEN p); INLINE GEN FqXQ_add(GEN x, GEN y, GEN S, GEN T, GEN p); INLINE GEN FqXQ_div(GEN x, GEN y, GEN S, GEN T, GEN p); INLINE GEN FqXQ_inv(GEN x, GEN S, GEN T, GEN p); INLINE GEN FqXQ_invsafe(GEN x, GEN S, GEN T, GEN p); INLINE GEN FqXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p); INLINE GEN FqXQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p); INLINE GEN FqXQ_sqr(GEN x, GEN S, GEN T, GEN p); INLINE GEN FqXQ_sub(GEN x, GEN y, GEN S, GEN T, GEN p); INLINE ulong F2m_coeff(GEN x, long a, long b); INLINE void F2m_clear(GEN x, long a, long b); INLINE void F2m_flip(GEN x, long a, long b); INLINE void F2m_set(GEN x, long a, long b); INLINE void F2v_clear(GEN x,long v); INLINE ulong F2v_coeff(GEN x,long v); INLINE void F2v_flip(GEN x,long v); INLINE GEN F2v_to_F2x(GEN x, long sv); INLINE void F2v_set(GEN x,long v); INLINE void F2x_clear(GEN x,long v); INLINE ulong F2x_coeff(GEN x,long v); INLINE void F2x_flip(GEN x,long v); INLINE void F2x_set(GEN x,long v); INLINE int F2x_equal1(GEN x); INLINE int F2x_equal(GEN V, GEN W); INLINE GEN F2x_div(GEN x, GEN y); INLINE GEN F2x_renormalize(GEN x, long lx); INLINE GEN F2m_copy(GEN x); INLINE GEN F2v_copy(GEN x); INLINE GEN F2v_ei(long n, long i); INLINE GEN Flm_copy(GEN x); INLINE GEN Flv_copy(GEN x); INLINE int Flx_equal1(GEN x); INLINE GEN Flx_copy(GEN x); INLINE GEN Flx_div(GEN x, GEN y, ulong p); INLINE ulong Flx_lead(GEN x); INLINE GEN Flx_mulu(GEN x, ulong a, ulong p); INLINE GEN FpV_FpC_mul(GEN x, GEN y, GEN p); INLINE GEN FpXQX_renormalize(GEN x, long lx); INLINE GEN FpXX_renormalize(GEN x, long lx); INLINE GEN FpX_div(GEN x, GEN y, GEN p); INLINE GEN FpX_renormalize(GEN x, long lx); 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_inv(GEN a, GEN m); INLINE GEN Fp_invsafe(GEN a, GEN m); INLINE GEN Fp_mul(GEN a, GEN b, GEN m); INLINE GEN Fp_muls(GEN a, long b, GEN m); INLINE GEN Fp_mulu(GEN a, ulong b, GEN m); INLINE GEN Fp_neg(GEN b, GEN m); INLINE GEN Fp_red(GEN x, GEN p); INLINE GEN Fp_sqr(GEN a, GEN m); INLINE GEN Fp_sub(GEN a, GEN b, GEN m); INLINE GEN GENbinbase(GENbin *p); INLINE GEN Q_abs(GEN x); INLINE GEN Q_abs_shallow(GEN x); INLINE int QV_isscalar(GEN x); INLINE GEN RgC_fpnorml2(GEN x, long prec); INLINE GEN RgC_gtofp(GEN x, long prec); INLINE GEN RgC_gtomp(GEN x, long prec); INLINE void RgM_dimensions(GEN x, long *m, long *n); INLINE GEN RgM_fpnorml2(GEN x, long prec); INLINE GEN RgM_gtofp(GEN x, long prec); INLINE GEN RgM_gtomp(GEN x, long prec); INLINE GEN RgM_inv(GEN a); INLINE GEN RgM_minor(GEN a, long i, long j); INLINE GEN RgM_shallowcopy(GEN x); INLINE int RgV_isscalar(GEN x); INLINE int RgV_is_ZV(GEN x); INLINE int RgV_is_QV(GEN x); INLINE long RgX_equal_var(GEN x, GEN y); INLINE int RgX_is_monomial(GEN x); INLINE int RgX_is_rational(GEN x); INLINE int RgX_is_QX(GEN x); INLINE int RgX_is_ZX(GEN x); INLINE int RgX_isscalar(GEN x); INLINE GEN RgX_shift_inplace(GEN x, long v); INLINE void RgX_shift_inplace_init(long v); 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_copy(GEN x); INLINE GEN RgX_div(GEN x, GEN y); INLINE GEN RgX_fpnorml2(GEN x, long prec); INLINE GEN RgX_gtofp(GEN x, long prec); INLINE GEN RgX_rem(GEN x, GEN y); INLINE GEN RgX_renormalize(GEN x); INLINE GEN Rg_col_ei(GEN x, long n, long i); INLINE GEN ZC_hnfrem(GEN x, GEN y); INLINE GEN ZM_hnfrem(GEN x, GEN y); INLINE GEN ZM_lll(GEN x, double D, long f); INLINE int ZV_dvd(GEN x, GEN y); INLINE int ZV_isscalar(GEN x); INLINE GEN ZV_to_zv(GEN x); INLINE GEN ZX_ZXY_resultant(GEN a, GEN b); INLINE int ZX_equal1(GEN x); INLINE GEN ZX_renormalize(GEN x, long lx); INLINE GEN ZXQ_mul(GEN x,GEN y,GEN T); INLINE GEN ZXQ_sqr(GEN x,GEN T); INLINE long Z_ispower(GEN x, ulong k); INLINE long Z_issquare(GEN x); INLINE GEN absfrac(GEN x); INLINE GEN absfrac_shallow(GEN x); INLINE GEN affc_fixlg(GEN x, GEN res); INLINE GEN bin_copy(GENbin *p); 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 cgetc(long x); INLINE GEN cgetalloc(long t, size_t l); INLINE GEN cxcompotor(GEN z, long prec); INLINE void cgiv(GEN x); INLINE GEN col_ei(long n, long i); INLINE GEN const_col(long n, GEN x); INLINE GEN const_vec(long n, GEN x); INLINE GEN const_vecsmall(long n, long c); INLINE GEN constant_term(GEN x); INLINE GEN cxnorm(GEN x); INLINE GEN cyclic_perm(long l, long d); INLINE double dbllog2r(GEN x); INLINE long degpol(GEN x); INLINE long divsBIL(long n); INLINE void gabsz(GEN x, long prec, GEN z); INLINE GEN gaddgs(GEN y, long s); INLINE void gaddz(GEN x, GEN y, GEN z); INLINE int gcmpgs(GEN y, long s); INLINE void gdiventz(GEN x, GEN y, GEN z); INLINE GEN gdivsg(long s, GEN y); INLINE void gdivz(GEN x, GEN y, GEN z); INLINE GEN gen_I(void); INLINE void gerepileall(pari_sp av, int n, ...); INLINE void gerepilecoeffs(pari_sp av, GEN x, int n); INLINE GEN gerepilecopy(pari_sp av, GEN x); INLINE void gerepilemany(pari_sp av, GEN* g[], int n); INLINE int gequalgs(GEN y, long s); INLINE GEN gerepileupto(pari_sp av, GEN q); INLINE GEN gerepileuptoint(pari_sp av, GEN q); INLINE GEN gerepileuptoleaf(pari_sp av, GEN q); INLINE GEN gmaxsg(long s, GEN y); INLINE GEN gminsg(long s, GEN y); INLINE void gmodz(GEN x, GEN y, GEN z); INLINE void gmul2nz(GEN x, long s, GEN z); INLINE GEN gmulgs(GEN y, long s); INLINE void gmulz(GEN x, GEN y, GEN z); INLINE void gnegz(GEN x, GEN z); INLINE void gshiftz(GEN x, long s, GEN z); INLINE GEN gsubgs(GEN y, long s); INLINE void gsubz(GEN x, GEN y, GEN z); INLINE double gtodouble(GEN x); INLINE GEN gtofp(GEN z, long prec); INLINE GEN gtomp(GEN z, long prec); INLINE long gtos(GEN x); INLINE long gval(GEN x, long v); INLINE GEN identity_perm(long l); INLINE int equali1(GEN n); INLINE int equalim1(GEN n); INLINE int is_bigint(GEN n); INLINE int is_const_t(long t); INLINE int is_extscalar_t(long t); INLINE int is_intreal_t(long t); INLINE int is_matvec_t(long t); INLINE int is_noncalc_t(long tx); INLINE int is_pm1(GEN n); INLINE int is_rational_t(long t); INLINE int is_recursive_t(long t); INLINE int is_scalar_t(long t); INLINE int is_universal_constant(GEN x); INLINE int is_vec_t(long t); INLINE int isint1(GEN x); INLINE int isintm1(GEN x); INLINE int isintzero(GEN x); INLINE int ismpzero(GEN x); INLINE int isonstack(GEN x); INLINE void killblock(GEN x); INLINE GEN leading_term(GEN x); INLINE long lgcols(GEN x); INLINE long lgpol(GEN x); INLINE GEN matpascal(long n); INLINE GEN mkcol(GEN x); INLINE GEN mkcol2(GEN x, GEN y); INLINE GEN mkcol2s(long x, long y); INLINE GEN mkcol3(GEN x, GEN y, GEN z); 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 mkcolcopy(GEN x); INLINE GEN mkcols(long x); INLINE GEN mkcomplex(GEN x, GEN y); INLINE GEN mkerr(long n); INLINE GEN mkfrac(GEN x, GEN y); INLINE GEN mkfraccopy(GEN x, GEN y); INLINE GEN mkintmod(GEN x, GEN y); INLINE GEN mkintmodu(ulong x, ulong y); INLINE GEN mkmat(GEN x); INLINE GEN mkmat2(GEN x, GEN y); INLINE GEN mkmat3(GEN x, GEN y, GEN z); INLINE GEN mkmat4(GEN x, GEN y, GEN z, GEN t); INLINE GEN mkmat5(GEN x, GEN y, GEN z, GEN t, GEN u); INLINE GEN mkmatcopy(GEN x); INLINE GEN mkpolmod(GEN x, GEN y); INLINE GEN mkqfi(GEN x, GEN y, GEN z); INLINE GEN mkquad(GEN n, GEN x, GEN y); INLINE GEN mkrfrac(GEN x, GEN y); INLINE GEN mkrfraccopy(GEN x, GEN y); INLINE GEN mkvec(GEN x); INLINE GEN mkvec2(GEN x, GEN y); INLINE GEN mkvec2copy(GEN x, GEN y); INLINE GEN mkvec2s(long x, long y); INLINE GEN mkvec3(GEN x, GEN y, GEN z); INLINE GEN mkvec3s(long x, long y, long z); INLINE GEN mkvec4(GEN x, GEN y, GEN z, GEN t); INLINE GEN mkvec4s(long x, long y, long z, long t); INLINE GEN mkvec5(GEN x, GEN y, GEN z, GEN t, GEN u); INLINE GEN mkveccopy(GEN x); INLINE GEN mkvecs(long x); INLINE GEN mkvecsmall(long x); INLINE GEN mkvecsmall2(long x,long y); INLINE GEN mkvecsmall3(long x,long y,long z); INLINE GEN mkvecsmall4(long x,long y,long z,long t); INLINE void mpcosz(GEN x, GEN z); INLINE void mpexpz(GEN x, GEN z); INLINE void mplogz(GEN x, GEN z); INLINE void mpsinz(GEN x, GEN z); INLINE GEN mul_content(GEN cx, GEN cy); INLINE GEN mul_denom(GEN cx, GEN cy); INLINE long nbits2nlong(long x); INLINE long nbits2extraprec(long x); INLINE long nbits2prec(long x); INLINE long nbits2lg(long x); INLINE long nbrows(GEN x); INLINE long nchar2nlong(long x); INLINE long ndec2nlong(long x); INLINE long ndec2prec(long x); INLINE void normalize_frac(GEN z); INLINE int odd(long x); INLINE void pari_free(void *pointer); INLINE void* pari_calloc(size_t size); INLINE void* pari_malloc(size_t bytes); INLINE void* pari_realloc(void *pointer,size_t size); INLINE GEN perm_conj(GEN s, GEN t); INLINE GEN perm_inv(GEN x); INLINE GEN perm_mul(GEN s, GEN t); INLINE GEN pol_0(long v); INLINE GEN pol_1(long v); INLINE GEN pol_x(long v); INLINE GEN pol0_F2x(long sv); INLINE GEN pol1_F2x(long sv); INLINE GEN polx_F2x(long sv); INLINE GEN pol0_Flx(long sv); INLINE GEN pol1_Flx(long sv); INLINE GEN polx_Flx(long sv); INLINE GEN polx_zx(long sv); INLINE GEN powii(GEN x, GEN n); INLINE GEN powIs(long n); INLINE long prec2nbits(long x); INLINE double prec2nbits_mul(long x, double y); INLINE long prec2ndec(long x); INLINE long precdbl(long x); 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); INLINE GEN row_Flm(GEN A, long x0); INLINE GEN row_i(GEN A, long x0, long x1, long x2); INLINE GEN row_zm(GEN x, long i); 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 GEN shallowcopy(GEN x); INLINE GEN sqrfrac(GEN x); INLINE GEN sqrti(GEN x); INLINE GEN sqrtnr(GEN x, long n); INLINE GEN sqrtr(GEN x); INLINE void pari_stack_alloc(pari_stack *s, long nb); INLINE void** pari_stack_base(pari_stack *s); INLINE void pari_stack_delete(pari_stack *s); INLINE void pari_stack_init(pari_stack *s, size_t size, void **data); INLINE long pari_stack_new(pari_stack *s); INLINE void pari_stack_pushp(pari_stack *s, void *u); 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_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 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); INLINE GEN vecsmall_append(GEN V, long s); INLINE long vecsmall_coincidence(GEN u, GEN v); INLINE GEN vecsmall_concat(GEN u, GEN v); INLINE GEN vecsmall_copy(GEN x); INLINE GEN vecsmall_ei(long n, long i); INLINE long vecsmall_indexmax(GEN x); INLINE long vecsmall_indexmin(GEN x); INLINE long vecsmall_isin(GEN v, long x); INLINE GEN vecsmall_lengthen(GEN v, long n); INLINE int vecsmall_lexcmp(GEN x, GEN y); INLINE long vecsmall_max(GEN v); INLINE long vecsmall_min(GEN v); INLINE long vecsmall_pack(GEN V, long base, long mod); INLINE int vecsmall_prefixcmp(GEN x, GEN y); INLINE GEN vecsmall_prepend(GEN V, long s); INLINE GEN vecsmall_shorten(GEN v, long n); INLINE GEN vecsmall_to_col(GEN z); INLINE GEN vecsmall_to_vec(GEN z); INLINE void vecsmalltrunc_append(GEN x, long t); INLINE GEN vecsmalltrunc_init(long l); INLINE void vectrunc_append(GEN x, GEN t); INLINE void vectrunc_append_batch(GEN x, GEN y); INLINE GEN vectrunc_init(long l); INLINE GEN zc_to_ZC(GEN x); INLINE GEN zero_F2m(long n, long m); INLINE GEN zero_F2m_copy(long n, long m); INLINE GEN zero_F2v(long m); INLINE GEN zero_F2x(long sv); INLINE GEN zero_Flm(long m, long n); INLINE GEN zero_Flm_copy(long m, long n); INLINE GEN zero_Flv(long n); INLINE GEN zero_Flx(long sv); INLINE GEN zero_zm(long x, long y); INLINE GEN zero_zv(long x); INLINE GEN zero_zx(long sv); INLINE GEN zerocol(long n); INLINE GEN zeromat(long m, long n); INLINE GEN zeromatcopy(long m, long n); INLINE GEN zeropadic(GEN p, long e); INLINE GEN zeropadic_shallow(GEN p, long e); INLINE GEN zeropol(long v); INLINE GEN zeroser(long v, long e); INLINE GEN zerovec(long n); INLINE GEN zm_copy(GEN x); INLINE GEN zm_to_zxV(GEN x, long sv); INLINE GEN zm_transpose(GEN x); INLINE GEN zv_copy(GEN x); INLINE GEN zv_to_ZV(GEN x); INLINE GEN zv_to_zx(GEN x, long sv); INLINE GEN zx_renormalize(GEN x, long l); INLINE GEN zx_shift(GEN x, long n); INLINE GEN zx_to_zv(GEN x, long N); INLINE GEN err_get_compo(GEN e, long i); INLINE long err_get_num(GEN e); INLINE void pari_err_BUG(const char *f); INLINE void pari_err_COMPONENT(const char *f, const char *op, GEN l, GEN x); INLINE void pari_err_CONSTPOL(const char *f); INLINE void pari_err_COPRIME(const char *f, GEN x, GEN y); INLINE void pari_err_DIM(const char *f); INLINE void pari_err_DOMAIN(const char *f, const char *v, const char *op, GEN l, GEN x); INLINE void pari_err_FILE(const char *f, const char *g); INLINE void pari_err_FLAG(const char *f); INLINE void pari_err_IMPL(const char *f); INLINE void pari_err_INV(const char *f, GEN x); INLINE void pari_err_IRREDPOL(const char *f, GEN x); INLINE void pari_err_MAXPRIME(ulong c); INLINE void pari_err_MODULUS(const char *f, GEN x, GEN y); INLINE void pari_err_OP(const char *f, GEN x, GEN y); INLINE void pari_err_OVERFLOW(const char *f); INLINE void pari_err_PACKAGE(const char *f); INLINE void pari_err_PREC(const char *f); INLINE void pari_err_PRIME(const char *f, GEN x); INLINE void pari_err_PRIORITY(const char *f, GEN x, const char *op, long v); INLINE void pari_err_SQRTN(const char *f, GEN x); INLINE void pari_err_TYPE(const char *f, GEN x); INLINE void pari_err_TYPE2(const char *f, GEN x, GEN y); INLINE void pari_err_VAR(const char *f, GEN x, GEN y); INLINE void pari_err_ROOTS0(const char *f); pari-2.7.5/src/headers/parigen.h0000644000175000017500000001326112574311434015115 0ustar billbill/* 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. */ /* This file defines the parameters of the GEN type */ #ifdef _WIN64 typedef unsigned long long pari_ulong; #define long long long #define labs llabs #else typedef unsigned long pari_ulong; #endif #define ulong pari_ulong typedef long *GEN; #undef ULONG_MAX #undef LONG_MAX #ifdef LONG_IS_64BIT # define BITS_IN_LONG 64 # define TWOPOTBITS_IN_LONG 6 # define LONG_MAX (9223372036854775807L) /* 2^63-1 */ # define SMALL_ULONG(p) ((ulong)p <= 3037000493UL) #else # define BITS_IN_LONG 32 # define TWOPOTBITS_IN_LONG 5 # define LONG_MAX (2147483647L) /* 2^31-1 */ # define SMALL_ULONG(p) ((ulong)p <= 46337UL) /* 2p^2 < 2^BITS_IN_LONG */ #endif #define ULONG_MAX (~0x0UL) #define DEFAULTPREC (2 + (long)(8/sizeof(long))) #define MEDDEFAULTPREC (2 + (long)(16/sizeof(long))) #define BIGDEFAULTPREC (2 + (long)(24/sizeof(long))) #define LOWDEFAULTPREC 3 #define EXTRAPRECWORD 1 #define HIGHBIT (1UL << (BITS_IN_LONG-1)) #define BITS_IN_HALFULONG (BITS_IN_LONG>>1) #define LOWMASK ((1UL<> BITS_IN_HALFULONG) #define LOWWORD(a) ((a) & LOWMASK) /* Order of bits in codewords: * x[0] TYPBITS, CLONEBIT, LGBITS * x[1].real SIGNBITS, EXPOBITS * int SIGNBITS, LGBITS * pol SIGNBITS, VARNBITS * ser SIGNBITS, VARNBITS, VALPBITS * padic VALPBITS, PRECPBITS */ #define TYPnumBITS 7 #define SIGNnumBITS 2 #ifdef LONG_IS_64BIT # define VARNnumBITS 16 /* otherwise MAXVARN too large */ #else # define VARNnumBITS 14 #endif /* no user serviceable parts below :-) */ #define LGnumBITS (BITS_IN_LONG - 1 - TYPnumBITS) #define VALPnumBITS (BITS_IN_LONG - SIGNnumBITS - VARNnumBITS) #define EXPOnumBITS (BITS_IN_LONG - SIGNnumBITS) #define PRECPSHIFT VALPnumBITS #define VARNSHIFT VALPnumBITS #define TYPSHIFT (BITS_IN_LONG - TYPnumBITS) #define SIGNSHIFT (BITS_IN_LONG - SIGNnumBITS) #define EXPOBITS ((1UL< MAXVARN */ #define HIGHEXPOBIT (1UL<<(EXPOnumBITS-1)) #define HIGHVALPBIT (1UL<<(VALPnumBITS-1)) #define CLONEBIT (1UL<> TYPSHIFT)) #define settyp(x,s) (((ulong*)(x))[0]=\ (((ulong*)(x))[0]&(~TYPBITS)) | evaltyp(s)) #define isclone(x) (((ulong*) (x))[0] & CLONEBIT) #define setisclone(x) (((ulong*) (x))[0] |= CLONEBIT) #define unsetisclone(x) (((ulong*) (x))[0] &= (~CLONEBIT)) #define lg(x) ((long)(((ulong)((x)[0])) & LGBITS)) #define setlg(x,s) (((ulong*)(x))[0]=\ (((ulong*)(x))[0]&(~LGBITS)) | evallg(s)) #define signe(x) (((long)((x)[1])) >> SIGNSHIFT) #define setsigne(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~SIGNBITS)) | (ulong)evalsigne(s)) #define lgefint(x) ((long)(((ulong)((x)[1])) & LGBITS)) #define setlgefint(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~LGBITS)) | (ulong)evallgefint(s)) #define realprec(x) ((long)(((ulong)((x)[0])) & LGBITS)) #define setprec(x,s) (((ulong*)(x))[0]=\ (((ulong*)(x))[0]&(~LGBITS)) | evallg(s)) #define incrprec(x) ((x)++) #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 setvalp(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~VALPBITS)) | (ulong)evalvalp(s)) #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 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_data(x) ((GEN*)x)[2] /* DO NOT REORDER THESE * actual values can be changed. Adapt lontyp in gen2.c */ enum { t_INT = 1, t_REAL = 2, t_INTMOD = 3, t_FRAC = 4, t_FFELT = 5, t_COMPLEX= 6, t_PADIC = 7, t_QUAD = 8, t_POLMOD = 9, t_POL = 10, t_SER = 11, t_RFRAC = 13, t_QFR = 15, t_QFI = 16, t_VEC = 17, t_COL = 18, t_MAT = 19, t_LIST = 20, t_STR = 21, t_VECSMALL= 22, t_CLOSURE = 23, t_ERROR = 24 }; pari-2.7.5/src/headers/parisys.h0000644000175000017500000000402012405547147015160 0ustar billbill/* 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. */ /* This files contains macros depending on system and compiler */ #ifndef LITTLE_ENDIAN_64 # define LITTLE_ENDIAN_64 12345678 #endif #ifndef BIG_ENDIAN_64 # define BIG_ENDIAN_64 87654321 #endif #ifndef LITTLE_ENDIAN # define LITTLE_ENDIAN 1234 #endif #ifndef BIG_ENDIAN # define BIG_ENDIAN 4321 #endif #ifndef PDP_ENDIAN # define PDP_ENDIAN 3412 #endif #ifdef __cplusplus # define ANYARG ... # define BEGINEXTERN extern "C" { # define ENDEXTERN } #else # define ANYARG # define BEGINEXTERN # define ENDEXTERN #endif #ifdef DISABLE_INLINE # undef ASMINLINE #else # ifdef __cplusplus # define INLINE inline static # elif defined(__GNUC__) # define INLINE __inline__ static # endif #endif #ifndef DISABLE_VOLATILE # ifdef __GNUC__ # define VOLATILE volatile # endif #endif #ifndef VOLATILE # define VOLATILE #endif #ifndef INLINE # define INLINE static #endif #ifdef ENABLE_TLS # define THREAD __thread #else # define THREAD #endif #if defined(_WIN32) || defined(__CYGWIN32__) /* ANSI C does not allow to longjmp() out of a signal handler, in particular, * the SIGINT handler. On Win32, the handler is executed in another thread, and * 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; void dowin32ctrlc(void); ENDEXTERN #define CHECK_CTRLC if (win32ctrlc) dowin32ctrlc(); #else #define CHECK_CTRLC #endif pari-2.7.5/src/functions/0000755000175000017500000000000012613365633013715 5ustar billbillpari-2.7.5/src/functions/operators/0000755000175000017500000000000012613365633015733 5ustar billbillpari-2.7.5/src/functions/operators/sign0000644000175000017500000000044311636712103016607 0ustar billbillFunction: sign Section: operators C-Name: gsigne Prototype: iG Help: sign(x): sign of x, of type integer, real or fraction Description: (mp):small signe($1) (gen):small gsigne($1) Doc: \idx{sign} ($0$, $1$ or $-1$) of $x$, which must be of type integer, real or fraction. pari-2.7.5/src/functions/operators/vecmax0000644000175000017500000000154112314242551017131 0ustar billbillFunction: vecmax Section: operators C-Name: vecmax0 Prototype: GD& Help: 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). Description: (gen):gen vecmax($1) (gen, &gen):gen vecmax0($1, &$2) Doc: if $x$ is a vector or a matrix, returns the largest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. If $v$ is given, set it to the index of a largest entry (indirect maximum), when $x$ is a vector. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a largest entry. This flag is ignored if $x$ is not a vector or matrix. \bprog ? vecmax([10, 20, -30, 40]) %1 = 40 ? vecmax([10, 20, -30, 40], &v); v %2 = 4 ? vecmax([10, 20; -30, 40], &v); v %3 = [2, 2] @eprog Variant: Also available is \fun{GEN}{vecmax}{GEN x}. pari-2.7.5/src/functions/operators/min0000644000175000017500000000104411636712103016430 0ustar billbillFunction: min Section: operators C-Name: gmin Prototype: GG Help: min(x,y): minimum of x and y Description: (small, small):small minss($1, $2) (small, int):int gminsg($1, $2) (int, small):int gmings($1, $2) (int, int):int gmin($1, $2) (small, mp):mp gminsg($1, $2) (mp, small):mp gmings($1, $2) (mp, mp):mp gmin($1, $2) (small, gen):gen gminsg($1, $2) (gen, small):gen gmings($1, $2) (gen, gen):gen gmin($1, $2) Doc: creates the minimum of $x$ and $y$ when they can be compared. pari-2.7.5/src/functions/operators/divrem0000644000175000017500000000214011636712103017131 0ustar billbillFunction: divrem Section: operators C-Name: divrem Prototype: GGDn Help: 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) Doc: creates a column vector with two components, the first being the Euclidean quotient (\kbd{$x$ \bs\ $y$}), the second the Euclidean remainder (\kbd{$x$ - ($x$\bs$y$)*$y$}), of the division of $x$ by $y$. This avoids the need to do two divisions if one needs both the quotient and the remainder. If $v$ is present, and $x$, $y$ are multivariate polynomials, divide with respect to the variable $v$. Beware that \kbd{divrem($x$,$y$)[2]} is in general not the same as \kbd{$x$ \% $y$}; no GP operator corresponds to it: \bprog ? divrem(1/2, 3)[2] %1 = 1/2 ? (1/2) % 3 %2 = 2 ? divrem(Mod(2,9), 3)[2] *** at top-level: divrem(Mod(2,9),3)[2 *** ^-------------------- *** forbidden division t_INTMOD \ t_INT. ? Mod(2,9) % 6 %3 = Mod(2,3) @eprog Variant: Also available is \fun{GEN}{gdiventres}{GEN x, GEN y} when $v$ is not needed. pari-2.7.5/src/functions/operators/max0000644000175000017500000000104411636712103016432 0ustar billbillFunction: max Section: operators C-Name: gmax Prototype: GG Help: max(x,y): maximum of x and y Description: (small, small):small maxss($1, $2) (small, int):int gmaxsg($1, $2) (int, small):int gmaxgs($1, $2) (int, int):int gmax($1, $2) (small, mp):mp gmaxsg($1, $2) (mp, small):mp gmaxgs($1, $2) (mp, mp):mp gmax($1, $2) (small, gen):gen gmaxsg($1, $2) (gen, small):gen gmaxgs($1, $2) (gen, gen):gen gmax($1, $2) Doc: creates the maximum of $x$ and $y$ when they can be compared. pari-2.7.5/src/functions/operators/cmp0000644000175000017500000000222312413013143016414 0ustar billbillFunction: cmp Section: operators C-Name: cmp_universal Prototype: iGG Help: cmp(x,y): compare two arbitrary objects x and y (1 if x>y, 0 if x=y, -1 if x$ vector $>$ scalar. For example: \bprog ? cmp(1, 2) %1 = -1 ? cmp(2, 1) %2 = 1 ? cmp(1, 1.0) \\ note that 1 == 1.0, but (1===1.0) is false. %3 = -1 ? cmp(x + Pi, []) %4 = -1 @eprog\noindent This function is mostly useful to handle sorted lists or vectors of arbitrary objects. For instance, if $v$ is a vector, the construction \kbd{vecsort(v, cmp)} is equivalent to \kbd{Set(v)}. pari-2.7.5/src/functions/operators/shift0000644000175000017500000000104611636712103016764 0ustar billbillFunction: shift Section: operators C-Name: gshift Prototype: GL Help: shift(x,n): shift x left n bits if n>=0, right -n bits if n<0. Doc: 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)$. A left shift by $n$ corresponds to multiplication by $2^n$. A right shift of an integer $x$ by $|n|$ corresponds to a Euclidean division of $x$ by $2^{|n|}$ with a remainder of the same sign as $x$, hence is not the same (in general) as $x \kbd{\bs} 2^n$. pari-2.7.5/src/functions/operators/vecmin0000644000175000017500000000154312314242551017131 0ustar billbillFunction: vecmin Section: operators C-Name: vecmin0 Prototype: GD& Help: 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). Description: (gen):gen vecmin($1) (gen, &gen):gen vecmin0($1, &$2) Doc: if $x$ is a vector or a matrix, returns the smallest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. If $v$ is given, set it to the index of a smallest entry (indirect minimum), when $x$ is a vector. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a smallest entry. This is ignored if $x$ is not a vector or matrix. \bprog ? vecmin([10, 20, -30, 40]) %1 = -30 ? vecmin([10, 20, -30, 40], &v); v %2 = 3 ? vecmin([10, 20; -30, 40], &v); v %3 = [2, 1] @eprog Variant: Also available is \fun{GEN}{vecmin}{GEN x}. pari-2.7.5/src/functions/operators/lex0000644000175000017500000000155311636712103016442 0ustar billbillFunction: lex Section: operators C-Name: lexcmp Prototype: iGG Help: lex(x,y): compare x and y lexicographically (1 if x>y, 0 if x=y, -1 if x$ vector $>$ scalar. For example: \bprog ? lex([1,3], [1,2,5]) %1 = 1 ? lex([1,3], [1,3,-1]) %2 = -1 ? lex([1], [[1]]) %3 = -1 ? lex([1], [1]~) %4 = 0 @eprog pari-2.7.5/src/functions/operators/shiftmul0000644000175000017500000000065011636712103017502 0ustar billbillFunction: shiftmul Section: operators C-Name: gmul2n Prototype: GL Help: shiftmul(x,n): multiply x by 2^n (n>=0 or n<0) Doc: multiplies $x$ by $2^n$. The difference with \kbd{shift} is that when $n<0$, ordinary division takes place, hence for example if $x$ is an integer the result may be a fraction, while for shifts Euclidean division takes place when $n<0$ hence if $x$ is an integer the result is still an integer. pari-2.7.5/src/functions/elliptic_curves/0000755000175000017500000000000012613365633017111 5ustar billbillpari-2.7.5/src/functions/elliptic_curves/ellbil0000644000175000017500000000103012413013142020250 0ustar billbillFunction: 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. pari-2.7.5/src/functions/elliptic_curves/ellmul0000644000175000017500000000203612314242551020316 0ustar billbillFunction: ellmul Section: elliptic_curves C-Name: ellmul Prototype: GGG Help: ellmul(E,z,n): n times the point z on elliptic curve E (n in Z). Doc: computes $[n]z$, where $z$ is a point on the elliptic curve $E$. The exponent $n$ is in $\Z$, or may be a complex quadratic integer if the curve $E$ has complex multiplication by $n$ (if not, an error message is issued). \bprog ? Ei = ellinit([1,0]); z = [0,0]; ? ellmul(Ei, z, 10) %2 = [0] \\ unsurprising: z has order 2 ? ellmul(Ei, z, I) %3 = [0, 0] \\ Ei has complex multiplication by Z[i] ? ellmul(Ei, z, quadgen(-4)) %4 = [0, 0] \\ an alternative syntax for the same query ? Ej = ellinit([0,1]); z = [-1,0]; ? ellmul(Ej, z, I) *** at top-level: ellmul(Ej,z,I) *** ^-------------- *** ellmul: not a complex multiplication in ellmul. ? ellmul(Ej, z, 1+quadgen(-3)) %6 = [1 - w, 0] @eprog The simple-minded algorithm for the CM case assumes that we are in characteristic $0$, and that the quadratic order to which $n$ belongs has small discriminant. pari-2.7.5/src/functions/elliptic_curves/ellgenerators0000644000175000017500000000154612314242551021677 0ustar billbillFunction: ellgenerators Section: elliptic_curves C-Name: ellgenerators Prototype: G Help: 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). Doc: If $E$ is an elliptic curve over the rationals, return a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to $E$. This relies on the \tet{elldata} database being installed and referencing the curve, and so is only available for curves over $\Z$ of small conductors. If $E$ is an elliptic curve over a finite field $\F_q$ as output by \tet{ellinit}, return a minimal set of generators for the group $E(\F_q)$. pari-2.7.5/src/functions/elliptic_curves/elltors0000644000175000017500000000252212366172547020526 0ustar billbillFunction: 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. 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$. \bprog ? E = ellinit([-1,0]); ? elltors(E) %1 = [4, [2, 2], [[0, 0], [1, 0]]] @eprog 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)}. pari-2.7.5/src/functions/elliptic_curves/ellpow0000644000175000017500000000024212314242551020323 0ustar billbillFunction: ellpow Section: elliptic_curves C-Name: ellmul Prototype: GGG Help: ellpow(E,z,n): deprecated alias for ellmul. Doc: deprecated alias for \kbd{ellmul}. pari-2.7.5/src/functions/elliptic_curves/elldivpol0000644000175000017500000000156512314242551021024 0ustar billbillFunction: elldivpol Section: elliptic_curves C-Name: elldivpol Prototype: GLDn Help: elldivpol(E,n,{v='x}): n-division polynomial f_n for the curve E in the variable v. Doc: $n$-division polynomial $f_n$ for the curve $E$ in the variable $v$. In standard notation, for any affine point $P = (X,Y)$ on the curve, 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][X,Y]$. We have $f_n(X) = \psi_n(X)$ for $n$ odd, and $f_n(X) = \psi_n(X,Y) (2Y + a_1X+a_3)$ for $n$ even. We have $$ f_1 = 1,\quad f_2 = 4X^3 + b_2X^2 + 2b_4 X + b_6, \quad f_3 = 3 X^4 + b_2 X^3 + 3b_4 X^2 + 3 b_6 X + b8, $$ $$ f_4 = f_2(2X^6 + b_2 X^5 + 5b_4 X^4 + 10 b_6 X^3 + 10 b_8 X^2 + (b_2b_8-b_4b_6)X + (b_8b_4 - b_6^2)), \dots $$ For $n \geq 2$, the roots of $f_n$ are the $X$-coordinates of points in $E[n]$. pari-2.7.5/src/functions/elliptic_curves/ellanalyticrank0000644000175000017500000000214611636712103022204 0ustar billbillFunction: ellanalyticrank Section: elliptic_curves C-Name: ellanalyticrank Prototype: GDGp Help: 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. Doc: 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 \kbd{eps} is zero. If no value of \kbd{eps} is given, a value of half the current precision is used. \bprog ? e = ellinit("11a1"); \\ rank 0 ? ellanalyticrank(e) %2 = [0, 0.2538418608559106843377589233] ? e = ellinit("37a1"); \\ rank 1 ? ellanalyticrank(e) %4 = [1, 0.3059997738340523018204836835] ? e = ellinit("389a1"); \\ rank 2 ? ellanalyticrank(e) %6 = [2, 1.518633000576853540460385214] ? e = ellinit("5077a1"); \\ rank 3 ? ellanalyticrank(e) %8 = [3, 10.39109940071580413875185035] @eprog pari-2.7.5/src/functions/elliptic_curves/ellneg0000644000175000017500000000027612314242551020276 0ustar billbillFunction: ellneg Section: elliptic_curves C-Name: ellneg Prototype: GG Help: ellneg(E,z): opposite of the point z on elliptic curve E. Doc: Opposite of the point $z$ on elliptic curve $E$. pari-2.7.5/src/functions/elliptic_curves/ellisoncurve0000644000175000017500000000113211636712103021533 0ustar billbillFunction: ellisoncurve Section: elliptic_curves C-Name: ellisoncurve Prototype: GG Help: ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if not. Doc: 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 take this into account, i.e.~an imprecise equality is checked, not a precise one. It is allowed for $z$ to be a vector of points in which case a vector (of the same type) is returned. Variant: Also available is \fun{int}{oncurve}{GEN E, GEN z} which does not accept vectors of points. pari-2.7.5/src/functions/elliptic_curves/ellsigma0000644000175000017500000000216412366172547020641 0ustar billbillFunction: ellsigma Section: elliptic_curves C-Name: ellsigma Prototype: GDGD0,L,p Help: ellsigma(L,{z='x},{flag=0}): computes the value at z of the Weierstrass sigma function attached to the lattice w, as given by ellperiods(,1). If flag = 1, returns an arbitrary determination of the logarithm of sigma. Doc: Computes the value at $z$ of the Weierstrass $\sigma$ function attached to the lattice $L$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \sigma(z, L) = z \prod_{\omega\in L^*} \left(1 - \dfrac{z}{\omega}\right)e^{\dfrac{z}{\omega} + \dfrac{z^2}{2\omega^2}}.$$ It is also possible to directly input $L = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($L = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I], 1); ? ellsigma(w, 1/2) %2 = 0.47494937998792065033250463632798296855 ? E = ellinit([1,0]); ? ellsigma(E) \\ at 'x, implicitly at default seriesprecision %4 = x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17) @eprog If $\fl=1$, computes an arbitrary determination of $\log(\sigma(z))$. pari-2.7.5/src/functions/elliptic_curves/elltatepairing0000644000175000017500000000055211636712103022032 0ustar billbillFunction: elltatepairing Section: elliptic_curves C-Name: elltatepairing Prototype: GGGG Help: 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. Doc: Computes the Tate pairing of the two points $P$ and $Q$ on the elliptic curve $E$. The point $P$ must be of $m$-torsion. pari-2.7.5/src/functions/elliptic_curves/ellsearch0000644000175000017500000000342112413013143020756 0ustar billbillFunction: ellsearch Section: elliptic_curves C-Name: ellsearch Prototype: G Help: ellsearch(N): returns all curves in the elldata database matching constraint N: given name (N = "11a1" or [11,0,1]), given isogeny class (N = "11a" or [11,0]), or given conductor (N = 11, "11", or [11]). Doc: This function finds all curves in the \tet{elldata} database satisfying the constraint defined by the argument $N$: \item if $N$ is a character string, it selects a given curve, e.g. \kbd{"11a1"}, or curves in the given isogeny class, e.g. \kbd{"11a"}, or curves with given conductor, e.g. \kbd{"11"}; \item if $N$ is a vector of integers, it encodes the same constraints as the character string above, according to the \tet{ellconvertname} correspondance, e.g. \kbd{[11,0,1]} for \kbd{"11a1"}, \kbd{[11,0]} for \kbd{"11a"} and \kbd{[11]} for \kbd{"11"}; \item if $N$ is an integer, curves with conductor $N$ are selected. If $N$ is a full curve name, e.g. \kbd{"11a1"} or \kbd{[11,0,1]}, the output format is $[N, [a_1,a_2,a_3,a_4,a_6], G]$ where $[a_1,a_2,a_3,a_4,a_6]$ are the coefficients of the Weierstrass equation of the curve and $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to the curve. \bprog ? ellsearch("11a3") %1 = ["11a3", [0, -1, 1, 0, 0], []] ? ellsearch([11,0,3]) %2 = ["11a3", [0, -1, 1, 0, 0], []] @eprog\noindent If $N$ is not a full curve name, then the output is a vector of all matching curves in the above format: \bprog ? ellsearch("11a") %1 = [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], []], ["11a3", [0, -1, 1, 0, 0], []]] ? ellsearch("11b") %2 = [] @eprog Variant: Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only accepts complete curve names (as \typ{STR}). pari-2.7.5/src/functions/elliptic_curves/ellorder0000644000175000017500000000337212366172547020656 0ustar billbillFunction: 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. 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. \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 ? E = ellinit(ellfromj(ffgen(5^10))); ? ellcard(E) %5 = 9762580 ? P = random(E); ellorder(E, P) %6 = 4881290 ? p = 2^160+7; E = ellinit([1,2], p); ? N = ellcard(E) %8 = 1461501637330902918203686560289225285992592471152 ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E))) time = 260 ms. @eprog The parameter $o$, is now mostly useless, and kept for backward compatibility. If present, it represents a non-zero multiple of the order of $z$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the cardinality of the curve. It is no longer needed since PARI is now able to compute it over large finite fields (was restricted to small prime fields at the time this feature was introduced), \emph{and} caches the result in $E$ so that it is computed and factored only once. Modifying the last example, we see that including this extra parameter provides no improvement: \bprog ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E),o)) time = 260 ms. @eprog Variant: The obsolete form \fun{GEN}{orderell}{GEN e, GEN z} should no longer be used. pari-2.7.5/src/functions/elliptic_curves/ellconvertname0000644000175000017500000000115411636712103022043 0ustar billbillFunction: ellconvertname Section: elliptic_curves C-Name: ellconvertname Prototype: G Help: ellconvertname(name): convert an elliptic curve name (as found in the elldata database) from a string to a triplet [conductor, isogeny class, index]. It will also convert a triplet back to a curve name. Doc: converts an elliptic curve name, as found in the \tet{elldata} database, from a string to a triplet $[\var{conductor}, \var{isogeny class}, \var{index}]$. It will also convert a triplet back to a curve name. Examples: \bprog ? ellconvertname("123b1") %1 = [123, 1, 1] ? ellconvertname(%) %2 = "123b1" @eprog pari-2.7.5/src/functions/elliptic_curves/ellweilpairing0000644000175000017500000000047611636712103022042 0ustar billbillFunction: ellweilpairing Section: elliptic_curves C-Name: ellweilpairing Prototype: GGGG Help: ellweilpairing(E, P, Q, m): Computes the Weil pairing of the two points of m-torsion P and Q on the elliptic curve E. Doc: Computes the Weil pairing of the two points of $m$-torsion $P$ and $Q$ on the elliptic curve $E$. pari-2.7.5/src/functions/elliptic_curves/ellsub0000644000175000017500000000036112314242551020311 0ustar billbillFunction: ellsub Section: elliptic_curves C-Name: ellsub Prototype: GGG Help: ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E. Doc: difference of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. pari-2.7.5/src/functions/elliptic_curves/ellmodulareqn0000644000175000017500000000446612314242551021701 0ustar billbillFunction: ellmodulareqn Section: elliptic_curves C-Name: ellmodulareqn Prototype: LDnDn Help: 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) Doc: return a vector [\kbd{eqn},$t$] where \kbd{eqn} is a modular equation of level $N$, i.e.~a bivariate polynomial with integer coefficients; $t$ indicates the type of this equation: either \emph{canonical} ($t = 0$) or \emph{Atkin} ($t = 1$). This function currently requires the package \kbd{seadata} to be installed and is limited to $N<500$, $N$ prime. Let $j$ be the $j$-invariant function. The polynomial \kbd{eqn} satisfies the following functional equation, which allows to compute the values of the classical modular polynomial $\Phi_N$ of prime level $N$, such that $\Phi_N(j(\tau), j(N\tau)) = 0$, while being much smaller than the latter: \item for canonical type: $P(f(\tau),j(\tau)) = P(N^s/f(\tau),j(N\*\tau)) = 0$, where $s = 12/\gcd(12,N-1)$; \item for Atkin type: $P(f(\tau),j(\tau)) = P(f(\tau),j(N\*\tau)) = 0$. \noindent In both cases, $f$ is a suitable modular function (see below). The following GP function returns values of the classical modular polynomial by eliminating $f(\tau)$ in the above two equations, for $N\leq 31$ or $N\in\{41,47,59,71\}$. \bprog classicaleqn(N, X='X, Y='Y)= { my(E=ellmodulareqn(N), P=E[1], t=E[2], Q, d); if(poldegree(P,'y)>2,error("level unavailable in classicaleqn")); if (t == 0, my(s = 12/gcd(12,N-1)); Q = 'x^(N+1) * substvec(P,['x,'y],[N^s/'x,Y]); d = N^(s*(2*N+1)) * (-1)^(N+1); , Q = subst(P,'y,Y); d = (X-Y)^(N+1)); polresultant(subst(P,'y,X), Q) / d; } @eprog More precisely, let $W_N(\tau)={{-1}\over{N\*\tau}}$ be the Atkin-Lehner involution; we have $j(W_N(\tau)) = j(N\*\tau)$ and the function $f$ also satisfies: \item for canonical type: $f(W_N(\tau)) = N^s/f(\tau)$; \item for Atkin type: $f(W_N(\tau)) = f(\tau)$. \noindent Furthermore, for an equation of canonical type, $f$ is the standard $\eta$-quotient $$f(\tau) = N^s \* \big(\eta(N\*\tau) / \eta(\tau) \big)^{2\*s},$$ where $\eta$ is Dedekind's eta function, which is invariant under $\Gamma_0(N)$. pari-2.7.5/src/functions/elliptic_curves/ellheight0000644000175000017500000000221612413013143020762 0ustar billbillFunction: 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$). pari-2.7.5/src/functions/elliptic_curves/elllseries0000644000175000017500000000122512314242551021166 0ustar billbillFunction: elllseries Section: elliptic_curves C-Name: elllseries Prototype: GGDGp Help: elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A a cut-off point close to 1. Doc: $E$ being an elliptic curve, given by an arbitrary model over $\Q$ as output by \kbd{ellinit}, this function computes the value of the $L$-series of $E$ at the (complex) point $s$. This function uses an $O(N^{1/2})$ algorithm, where $N$ is the conductor. The optional parameter $A$ fixes a cutoff point for the integral and is best left omitted; the result must be independent of $A$, up to \kbd{realprecision}, so this allows to check the function's accuracy. pari-2.7.5/src/functions/elliptic_curves/ellminimalmodel0000644000175000017500000000141611636712103022172 0ustar billbillFunction: ellminimalmodel Section: elliptic_curves C-Name: ellminimalmodel Prototype: GD& Help: ellminimalmodel(E,{&v}): return the standard minimal integral model of the rational elliptic curve E. Sets v to the corresponding change of variables. Doc: return the standard minimal integral model of the rational elliptic curve $E$. If present, sets $v$ to the corresponding change of variables, which is a vector $[u,r,s,t]$ with rational components. The return value is identical to that of \kbd{ellchangecurve(E, v)}. The resulting model has integral coefficients, is everywhere minimal, $a_1$ is 0 or 1, $a_2$ is 0, 1 or $-1$ and $a_3$ is 0 or 1. Such a model is unique, and the vector $v$ is unique if we specify that $u$ is positive, which we do. \sidx{minimal model} pari-2.7.5/src/functions/elliptic_curves/ellchangepointinv0000644000175000017500000000132712314242551022537 0ustar billbillFunction: ellchangepointinv Section: elliptic_curves C-Name: ellchangepointinv Prototype: GG Help: ellchangepointinv(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t], inverse of ellchangepoint. Doc: changes the coordinates of the point or vector of points $x$ using the inverse of the isomorphism associated to \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the old coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$ (inverse of \kbd{ellchangepoint}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] \\ we get back P0 @eprog pari-2.7.5/src/functions/elliptic_curves/ellrootno0000644000175000017500000000137312314242551021044 0ustar billbillFunction: ellrootno Section: elliptic_curves C-Name: ellrootno Prototype: lGDG Help: ellrootno(E,{p}): root number for the L-function of the elliptic curve E/Q at a prime p (including 0, for the infinite place); global root number if p is omitted. Doc: $E$ being an \var{ell} structure over $\Q$ as output by \kbd{ellinit}, this function computes the local root number of its $L$-series at the place $p$ (at the infinite place if $p = 0$). If $p$ is omitted, return the global root number. Note that the global root number is the sign of the functional equation and conjecturally is the parity of the rank of the \idx{Mordell-Weil group}. The equation for $E$ needs not be minimal at $p$, but if the model is already minimal the function will run faster. pari-2.7.5/src/functions/elliptic_curves/elltaniyama0000644000175000017500000000207512314242551021327 0ustar billbillFunction: elltaniyama Section: elliptic_curves C-Name: elltaniyama Prototype: GDP Help: elltaniyama(E, {d = seriesprecision}): modular parametrization of elliptic curve E/Q. Doc: computes the modular parametrization of the elliptic curve $E/\Q$, where $E$ is an \var{ell} structure as output by \kbd{ellinit}. This returns a two-component vector $[u,v]$ of power series, given to $d$ significant terms (\tet{seriesprecision} by default), characterized by the following two properties. First the point $(u,v)$ satisfies the equation of the elliptic curve. Second, let $N$ be the conductor of $E$ and $\Phi: X_0(N)\to E$ be a modular parametrization; the pullback by $\Phi$ of the N\'eron differential $du/(2v+a_1u+a_3)$ is equal to $2i\pi f(z)dz$, a holomorphic differential form. The variable used in the power series for $u$ and $v$ is $x$, which is implicitly understood to be equal to $\exp(2i\pi z)$. The algorithm assumes that $E$ is a \emph{strong} \idx{Weil curve} and that the Manin constant is equal to 1: in fact, $f(x) = \sum_{n > 0} \kbd{ellan}(E, n) x^n$. pari-2.7.5/src/functions/elliptic_curves/ellwp0000644000175000017500000000246612366172547020174 0ustar billbillFunction: ellwp Section: elliptic_curves C-Name: ellwp0 Prototype: GDGD0,L,p Help: 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)]. Doc: Computes the value at $z$ of the Weierstrass $\wp$ function attached to the lattice $w$ as given by \tet{ellperiods}. It is also possible to directly input $w = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I]); ? ellwp(w, 1/2) %2 = 6.8751858180203728274900957798105571978 ? E = ellinit([1,1]); ? ellwp(E, 1/2) %4 = 3.9413112427016474646048282462709151389 @eprog\noindent One can also compute the series expansion around $z = 0$: \bprog ? E = ellinit([1,0]); ? ellwp(E) \\ 'x implicitly at default seriesprecision %5 = x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14) ? ellwp(E, x + O(x^12)) \\ explicit precision %6 = x^-2 - 1/5*x^2 + 1/75*x^6 + O(x^9) @eprog Optional \fl\ means 0 (default): compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. Variant: For $\fl = 0$, we also have \fun{GEN}{ellwp}{GEN w, GEN z, long prec}, and \fun{GEN}{ellwpseries}{GEN E, long v, long precdl} for the power series in variable $v$. pari-2.7.5/src/functions/elliptic_curves/genus2red0000644000175000017500000001266112405547147020741 0ustar billbillFunction: genus2red Section: elliptic_curves C-Name: genus2red Prototype: GGDG Help: 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.) Doc: Let $Q,P$ be polynomials 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 special fiber $X_p$ of the minimal regular model $X$ of $C$ over $\Z$.) 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/}. \misctitle{CAVEAT} The function interface may change: for the time being, it returns $[N,\var{FaN}, T, V]$ where $N$ is either the local conductor at $p$ or the global conductor, \var{FaN} is its factorization, $y^2 = T$ defines a minimal model over $\Z[1/2]$ and $V$ describes the reduction type at the various considered~$p$. Unfortunately, the program is not complete for $p = 2$, and we may return the odd part of the conductor only: this is the case if the factorization includes the (impossible) term $2^{-1}$; if the factorization contains another power of $2$, then this is the exact local conductor at $2$ and $N$ is the global conductor. \bprog ? default(debuglevel, 1); ? genus2red(0,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, []], ["[III{9}] page 184", [3, 3]]]] ? [N, FaN, T, V] = genus2red(x^3-x^2-1, x^2-x); \\ X_1(13), global reduction p = 13 (potential) stable reduction: [5, [Mod(0, 13), Mod(0, 13)]] reduction at p: [I{0}-II-0] page 159, [], f = 2 ? N %3 = 169 ? FaN %4 = Mat([13, 2]) \\ in particular, good reduction at 2 ! ? T %5 = x^6 + 58*x^5 + 1401*x^4 + 18038*x^3 + 130546*x^2 + 503516*x + 808561 ? V %6 = [[13, [5, [Mod(0, 13), Mod(0, 13)]], ["[I{0}-II-0] page 159", []]]] @eprog\noindent We now first describe the format of the vector $V = V_p$ in the case where $p$ was specified (local reduction at~$p$): it is a triple $[p, \var{stable}, \var{red}]$. The component $\var{stable} = [\var{type}, \var{vecj}]$ contains information about the stable reduction after a field extension; depending on \var{type}s, the stable reduction is \item 1: smooth (i.e. the curve has potentially good reduction). The Jacobian $J(C)$ has potentially good reduction. \item 2: an elliptic curve $E$ with an ordinary double point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 3: a projective line with two ordinary double points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 4: the union of two projective lines crossing transversally at three points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 5: the union of two elliptic curves $E_1$ and $E_2$ intersecting transversally at one point; \var{vecj} contains their modular invariants $j_1$ and $j_2$, which may live in a quadratic extension of $\F_p$ are need not be distinct. The Jacobian $J(C)$ has potentially good reduction, isomorphic to the product of the reductions of $E_1$ and $E_2$. \item 6: the union of an elliptic curve $E$ and a projective line which has an ordinary double point, and these two components intersect transversally at one point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 7: as in type 6, but the two components are both singular. The Jacobian $J(C)$ has potentially multiplicative reduction. The component $\var{red} = [\var{NUtype}, \var{neron}]$ contains two data concerning the reduction at $p$ without any ramified field extension. The \var{NUtype} is a \typ{STR} describing the reduction at $p$ of $C$, following Namikawa-Ueno, \emph{The complete classification of fibers in pencils of curves of genus two}, Manuscripta Math., vol. 9, (1973), pages 143-186. The reduction symbol is followed by the corresponding page number in this article. The second datum \var{neron} is the group of connected components (over an algebraic closure of $\F_p$) of the N\'eron model of $J(C)$, given as a finite abelian group (vector of elementary divisors). \smallskip If $p = 2$, the \var{red} component may be omitted altogether (and replaced by \kbd{[]}, in the case where the program could not compute it. When $p$ was not specified, $V$ is the vector of all $V_p$, for all considered $p$. \misctitle{Notes about Namikawa-Ueno types} \item A lower index is denoted between braces: for instance, \kbd{[I\obr 2\cbr-II-5]} means \kbd{[I\_2-II-5]}. \item If $K$ and $K'$ are Kodaira symbols for singular fibers of elliptic curves, \kbd{[$K$-$K'$-m]} and \kbd{[$K'$-$K$-m]} are the same. \item \kbd{[$K$-$K'$-$-1$]} is \kbd{[$K'$-$K$-$\alpha$]} in the notation of Namikawa-Ueno. \item The figure \kbd{[2I\_0-m]} in Namikawa-Ueno, page 159, must be denoted by \kbd{[2I\_0-(m+1)]}. pari-2.7.5/src/functions/elliptic_curves/ellperiods0000644000175000017500000000222412314242551021165 0ustar billbillFunction: ellperiods Section: elliptic_curves C-Name: ellperiods Prototype: GD0,L,p Help: 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. Doc: Let $w$ describe a complex period lattice ($w = [w_1,w_2]$ or an ellinit structure). Returns normalized periods $[W_1,W_2]$ generating the same lattice such that $\tau := W_1/W_2$ has positive imaginary part and lies in the standard fundamental domain for $\text{SL}_2(\Z)$. If $\fl = 1$, the function returns $[[W_1,W_2], [\eta_1,\eta_2]]$, where $\eta_1$ and $\eta_2$ are the quasi-periods associated to $[W_1,W_2]$, satisfying $\eta_1 W_2 - \eta_2 W_1 = 2 i \pi$. The output of this function is meant to be used as the first argument given to ellwp, ellzeta, ellsigma or elleisnum. Quasi-periods are needed by ellzeta and ellsigma only. pari-2.7.5/src/functions/elliptic_curves/ellidentify0000644000175000017500000000130112314242551021326 0ustar billbillFunction: ellidentify Section: elliptic_curves C-Name: ellidentify Prototype: G Help: 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). Doc: look up the elliptic curve $E$, defined by an arbitrary model over $\Q$, in the \tet{elldata} database. Return \kbd{[[N, M, G], C]} where $N$ is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} $E(\Q)$ and $C$ is the change of coordinates change, suitable for \kbd{ellchangecurve}. pari-2.7.5/src/functions/elliptic_curves/elllocalred0000644000175000017500000000233212405547147021317 0ustar billbillFunction: elllocalred Section: elliptic_curves C-Name: elllocalred Prototype: GG Help: 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. 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$. 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: 1 means good reduction (type I$_0$), 2, 3 and 4 mean types II, III and IV respectively, $4+\nu$ with $\nu>0$ means type I$_\nu$; finally the opposite values $-1$, $-2$, etc.~refer to the starred types I$_0^*$, II$^*$, etc. The third component $v$ is itself a vector $[u,r,s,t]$ 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$. pari-2.7.5/src/functions/elliptic_curves/ellap0000644000175000017500000000435012405547147020134 0ustar billbillFunction: ellap Section: elliptic_curves C-Name: ellap Prototype: GDG Help: ellap(E,{p}): computes the trace of Frobenius a_p for the elliptic curve E, defined over Q or a finite field. Doc: Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. This function computes the trace of Frobenius $t$ for the elliptic curve $E$, defined by the equation $\#E(\F_q) = q+1 - t$. If the curve is defined over $\Q$, $p$ must be explicitly given and the function computes the trace of the reduction over $\F_p$. The trace of Frobenius is also the $a_p$ coefficient in the curve $L$-series $L(E,s) = \sum_n a_n n^{-s}$, whence the function name. The equation must be integral at $p$ but need not be minimal at $p$; of course, a minimal model will be more efficient. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellap(E, 7) \\ 7 necessary here %2 = -4 \\ #E(F_7) = 7+1-(-4) = 12 ? ellcard(E, 7) %3 = 12 \\ OK ? E = ellinit([0,1], 11); \\ defined over F_11 ? ellap(E) \\ no need to repeat 11 %4 = 0 ? ellap(E, 11) \\ ... but it also works %5 = 0 ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellap(E,13) *** ^----------- *** ellap: inconsistent moduli in Rg_to_Fp: 11 13 ? Fq = ffgen(ffinit(11,3), 'a); \\ defines F_q := F_{11^3} ? E = ellinit([a+1,a], Fq); \\ y^2 = x^3 + (a+1)x + a, defined over F_q ? ellap(E) %8 = -3 @eprog \misctitle{Algorithms used} If $E/\F_q$ has CM by a principal imaginary 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. pari-2.7.5/src/functions/elliptic_curves/ellinit0000644000175000017500000001024512405547147020477 0ustar billbillFunction: ellinit Section: elliptic_curves C-Name: ellinit Prototype: GDGp Help: 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). Description: (gen, gen, small):ell:prec ellinit($1, $2, prec) Doc: initialize an \tet{ell} structure, associated to the elliptic curve $E$. $E$ is either \item a $5$-component vector $[a_1,a_2,a_3,a_4,a_6]$ defining the elliptic curve with Weierstrass equation $$ Y^2 + a_1 XY + a_3 Y = X^3 + a_2 X^2 + a_4 X + a_6, $$ \item a $2$-component vector $[a_4,a_6]$ defining the elliptic curve with short Weierstrass equation $$ Y^2 = X^3 + a_4 X + a_6, $$ \item a character string in Cremona's notation, e.g. \kbd{"11a1"}, in which case the curve is retrieved from the \tet{elldata} database if available. The optional argument $D$ describes the domain over which the curve is defined: \item the \typ{INT} $1$ (default): the field of rational numbers $\Q$. \item a \typ{INT} $p$, where $p$ is a prime number: the prime finite field $\F_p$. \item an \typ{INTMOD} \kbd{Mod(a, p)}, where $p$ is a prime number: the prime finite field $\F_p$. \item a \typ{FFELT}, as returned by \tet{ffgen}: the corresponding finite field $\F_q$. \item a \typ{PADIC}, $O(p^n)$: the field $\Q_p$, where $p$-adic quantities will be computed to a relative accuracy of $n$ digits. We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model, at the given accuracy. \item a \typ{REAL} $x$: the field $\C$ of complex numbers, where floating 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. 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 raised: \bprog ? ellinit([1 + O(5), 1], O(7)); *** at top-level: ellinit([1+O(5),1],O *** ^-------------------- *** ellinit: inconsistent moduli in ellinit: 7 != 5 @eprog\noindent If the curve coefficients are too general to fit any of the above domain categories, only basic operations, such as point addition, will be supported later. If the curve (seen over the domain $D$) is singular, fail and return an empty vector $[]$. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1, over Q ? E = ellinit([0,1]); \\ the same curve, short form ? E = ellinit("36a1"); \\ sill the same curve, Cremona's notations ? E = ellinit([0,1], 2) \\ over F2: singular curve %4 = [] ? E = ellinit(['a4,'a6] * Mod(1,5)); \\ over F_5[a4,a6], basic support ! @eprog\noindent The result of \tet{ellinit} is an \tev{ell} structure. It contains at least the following information in its components: % $$ a_1,a_2,a_3,a_4,a_6,b_2,b_4,b_6,b_8,c_4,c_6,\Delta,j.$$ % All are accessible via member functions. In particular, the discriminant is \kbd{$E$.disc}, and the $j$-invariant is \kbd{$E$.j}. \bprog ? E = ellinit([a4, a6]); ? E.disc %2 = -64*a4^3 - 432*a6^2 ? E.j %3 = -6912*a4^3/(-4*a4^3 - 27*a6^2) @eprog Further components contain domain-specific data, which are in general dynamic: only computed when needed, and then cached in the structure. \bprog ? E = ellinit([2,3], 10^60+7); \\ E over F_p, p large ? ellap(E) time = 4,440 ms. %2 = -1376268269510579884904540406082 ? ellcard(E); \\ now instantaneous ! time = 0 ms. ? ellgenerators(E); time = 5,965 ms. ? ellgenerators(E); \\ second time instantaneous time = 0 ms. @eprog See the description of member functions related to elliptic curves at the beginning of this section. pari-2.7.5/src/functions/elliptic_curves/elleisnum0000644000175000017500000000236612314242551021027 0ustar billbillFunction: elleisnum Section: elliptic_curves C-Name: elleisnum Prototype: GLD0,L,p Help: 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. Doc: $k$ being an even positive integer, computes the numerical value of the Eisenstein series of weight $k$ at the lattice $w$, as given by \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), $$ 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 = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit}. \bprog ? w = ellperiods([1,I]); ? elleisnum(w, 4) %2 = 2268.8726415508062275167367584190557607 ? elleisnum(w, 6) %3 = -3.977978632282564763 E-33 ? E = ellinit([1, 0]); ? elleisnum(E, 4, 1) %5 = -47.999999999999999999999999999999999998 @eprog When \fl\ is non-zero and $k=4$ or 6, returns the elliptic invariants $g_2$ or $g_3$, such that $$y^2 = 4x^3 - g_2 x - g_3$$ is a Weierstrass equation for $E$. pari-2.7.5/src/functions/elliptic_curves/ellglobalred0000644000175000017500000000234112366172547021471 0ustar billbillFunction: ellglobalred Section: elliptic_curves C-Name: ellglobalred Prototype: G Help: 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]). Description: (gen):gen ellglobalred($1) Doc: calculates the arithmetic conductor, the global minimal model of $E$ and the global \idx{Tamagawa number} $c$. $E$ must be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$. The result is a vector $[N,v,c,F,L]$, where \item $N$ is the arithmetic conductor of the curve, \item $v$ gives the coordinate change for $E$ over $\Q$ to the minimal integral model (see \tet{ellminimalmodel}), \item $c$ is the product of the local Tamagawa numbers $c_p$, a quantity which enters in the \idx{Birch and Swinnerton-Dyer conjecture},\sidx{minimal model} \item $F$ is the factorization of $N$ over $\Z$. \item $L$ is a vector, whose $i$-th entry contains the local data at the $i$-th prime divisor of $N$, i.e. \kbd{L[i] = elllocalred(E,F[i,1])}, where the local coordinate change has been deleted, and replaced by a $0$. pari-2.7.5/src/functions/elliptic_curves/elladd0000644000175000017500000000034312314242551020250 0ustar billbillFunction: elladd Section: elliptic_curves C-Name: elladd Prototype: GGG Help: elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E. Doc: sum of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. pari-2.7.5/src/functions/elliptic_curves/ellchangepoint0000644000175000017500000000135112366172547022035 0ustar billbillFunction: ellchangepoint Section: elliptic_curves C-Name: ellchangepoint Prototype: GG Help: ellchangepoint(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t]. Doc: changes the coordinates of the point or vector of points $x$ using the vector \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the new coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$ (see also \kbd{ellchangecurve}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] @eprog Variant: The reciprocal function \fun{GEN}{ellchangepointinv}{GEN x, GEN ch} inverts the coordinate change. pari-2.7.5/src/functions/elliptic_curves/ellordinate0000644000175000017500000000046311636712103021331 0ustar billbillFunction: ellordinate Section: elliptic_curves C-Name: ellordinate Prototype: GGp Help: ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E. Doc: gives a 0, 1 or 2-component vector containing the $y$-coordinates of the points of the curve $E$ having $x$ as $x$-coordinate. pari-2.7.5/src/functions/elliptic_curves/ellzeta0000644000175000017500000000271012366172547020501 0ustar billbillFunction: ellzeta Section: elliptic_curves C-Name: ellzeta Prototype: GDGp Help: ellzeta(w,{z='x}): computes the value at z of the Weierstrass Zeta function attached to the lattice w, as given by ellperiods(,1). Doc: Computes the value at $z$ of the Weierstrass $\zeta$ function attached to the lattice $w$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \zeta(z, L) = \dfrac{1}{z} + z^2\sum_{\omega\in L^*} \dfrac{1}{\omega^2(z-\omega)}.$$ It is also possible to directly input $w = [\omega_1,\omega_2]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). The quasi-periods of $\zeta$, such that $$\zeta(z + a\omega_1 + b\omega_2) = \zeta(z) + a\eta_1 + b\eta_2 $$ for integers $a$ and $b$ are obtained as $\eta_i = 2\zeta(\omega_i/2)$. Or using directly \tet{elleta}. \bprog ? w = ellperiods([1,I],1); ? ellzeta(w, 1/2) %2 = 1.5707963267948966192313216916397514421 ? E = ellinit([1,0]); ? ellzeta(E, E.omega[1]/2) %4 = 0.84721308479397908660649912348219163647 @eprog\noindent One can also compute the series expansion around $z = 0$ (the quasi-periods are useless in this case): \bprog ? E = ellinit([0,1]); ? ellzeta(E) \\ at 'x, implicitly at default seriesprecision %4 = x^-1 + 1/35*x^5 - 1/7007*x^11 + O(x^15) ? ellzeta(E, x + O(x^20)) \\ explicit precision %5 = x^-1 + 1/35*x^5 - 1/7007*x^11 + 1/1440257*x^17 + O(x^18) @eprog\noindent pari-2.7.5/src/functions/elliptic_curves/ellL10000644000175000017500000000262712515251402020001 0ustar billbillFunction: 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. 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.) \bprog ? e = ellinit("11a1"); \\ order of vanishing is 0 ? ellL1(e, 0) %2 = 0.2538418608559106843377589233 ? e = ellinit("389a1"); \\ order of vanishing is 2 ? ellL1(e, 0) %4 = -5.384067311837218089235032414 E-29 ? ellL1(e, 1) %5 = 0 ? ellL1(e, 2) %6 = 1.518633000576853540460385214 @eprog\noindent The main use of this function, after computing at \emph{low} accuracy the order of vanishing using \tet{ellanalyticrank}, is to compute the leading term at \emph{high} accuracy to check (or use) the Birch and Swinnerton-Dyer conjecture: \bprog ? \p18 realprecision = 18 significant digits ? ellanalyticrank(ellinit([0, 0, 1, -7, 6])) time = 32 ms. %1 = [3, 10.3910994007158041] ? \p200 realprecision = 202 significant digits (200 digits displayed) ? ellL1(e, 3) time = 23,113 ms. %3 = 10.3910994007158041387518505103609170697263563756570092797@com$[\dots]$ @eprog pari-2.7.5/src/functions/elliptic_curves/ellfromj0000644000175000017500000000043712314242551020641 0ustar billbillFunction: ellfromj Section: elliptic_curves C-Name: ellfromj Prototype: G Help: ellfromj(j): returns the coefficients [a1,a2,a3,a4,a6] of a fixed elliptic curve with j-invariant j. Doc: returns the coefficients $[a_1,a_2,a_3,a_4,a_6]$ of a fixed elliptic curve with $j$-invariant $j$. pari-2.7.5/src/functions/elliptic_curves/ellgroup0000644000175000017500000000535112366172547020676 0ustar billbillFunction: ellgroup Section: elliptic_curves C-Name: ellgroup0 Prototype: GDGD0,L, Help: ellgroup(E,{p},{flag}): computes the structure of the group E(Fp) If flag is 1, return also generators. Doc: Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. This function computes the structure of the group $E(\F_q) \sim \Z/d_1\Z \times \Z/d_2\Z$, with $d_2\mid d_1$. If the curve is defined over $\Q$, $p$ must be explicitly given and the function computes the structure 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 structure of the (cyclic) group of non-singular points in this case. If the flag is $0$ (default), return $[d_1]$ or $[d_1, d_2]$, if $d_2>1$. If the flag is $1$, return a triple $[h,\var{cyc},\var{gen}]$, where $h$ is the curve cardinality, \var{cyc} gives the group structure as a product of cyclic groups (as per $\fl = 0$). More precisely, if $d_2 > 1$, the output is $[d_1d_2, [d_1,d_2],[P,Q]]$ where $P$ is of order $d_1$ and $[P,Q]$ generates the curve. \misctitle{Caution} It is not guaranteed that $Q$ has order $d_2$, which in the worst case requires an expensive discrete log computation. Only that \kbd{ellweilpairing(E, P, Q, d1)} has order $d_2$. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellgroup(E, 7) %2 = [6, 2] \\ Z/6 x Z/2, non-cyclic ? E = ellinit([0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %4 = [12] ? ellgroup(E, 11) \\ ... but it also works %5 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11 13 ? ellgroup(E, 7, 1) %6 = [12, [6, 2], [[Mod(2, 7), Mod(4, 7)], [Mod(4, 7), Mod(4, 7)]]] @eprog\noindent If $E$ is defined over $\Q$, we allow singular reduction and in this case we return the structure of the group of non-singular points, satisfying $\#E_{ns}(\F_p) = p - a_p$. \bprog ? E = ellinit([0,5]); ? ellgroup(E, 5, 1) %2 = [5, [5], [[Mod(4, 5), Mod(2, 5)]]] ? ellap(E, 5) %3 = 0 \\ additive reduction at 5 ? E = ellinit([0,-1,0,35,0]); ? ellgroup(E, 5, 1) %5 = [4, [4], [[Mod(2, 5), Mod(2, 5)]]] ? ellap(E, 5) %6 = 1 \\ split multiplicative reduction at 5 ? ellgroup(E, 7, 1) %7 = [8, [8], [[Mod(3, 7), Mod(5, 7)]]] ? ellap(E, 7) %8 = -1 \\ non-split multiplicative reduction at 7 @eprog Variant: Also available is \fun{GEN}{ellgroup}{GEN E, GEN p}, corresponding to \fl = 0. pari-2.7.5/src/functions/elliptic_curves/ellj0000644000175000017500000000043111636712103017750 0ustar billbillFunction: ellj Section: elliptic_curves C-Name: jell Prototype: Gp Help: ellj(x): elliptic j invariant of x. Doc: elliptic $j$-invariant. $x$ must be a complex number with positive imaginary part, or convertible into a power series or a $p$-adic number with positive valuation. pari-2.7.5/src/functions/elliptic_curves/ellpointtoz0000644000175000017500000000415112366172547021425 0ustar billbillFunction: ellpointtoz Section: elliptic_curves C-Name: zell Prototype: GGp Help: ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic curve E. Doc: if $E/\C \simeq \C/\Lambda$ is a complex elliptic curve ($\Lambda = \kbd{E.omega}$), computes a complex number $z$, well-defined modulo the lattice $\Lambda$, corresponding to the point $P$; i.e.~such that $P = [\wp_\Lambda(z),\wp'_\Lambda(z)]$ satisfies the equation $$y^2 = 4x^3 - g_2 x - g_3,$$ where $g_2$, $g_3$ are the elliptic invariants. If $E$ is defined over $\R$ and $P\in E(\R)$, we have more precisely, $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$, where $(w1,w2)$ are the real and complex periods of $E$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [6.372367644529809109 E-58, 7.646841173435770930 E-57] ? ellpointtoz(E, [0]) \\ the point at infinity %5 = 0 @eprog If $E/\Q_p$ has multiplicative reduction, then $E/\bar{\Q_p}$ is analytically isomorphic to $\bar{\Q}_p^*/q^\Z$ (Tate curve) for some $p$-adic integer $q$. The behaviour is then as follows: \item If the reduction is split ($E.\kbd{tate[2]}$ is a \typ{PADIC}), we have an isomorphism $\phi: E(\Q_p) \simeq \Q_p^*/q^\Z$ and the function returns $\phi(P)\in \Q_p$. \item If the reduction is \emph{not} split ($E.\kbd{tate[2]}$ is a \typ{POLMOD}), we only have an isomorphism $\phi: E(K) \simeq K^*/q^\Z$ over the unramified quadratic extension $K/\Q_p$. In this case, the output $\phi(P)\in K$ is a \typ{POLMOD}. \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); P = [0,0]; ? [u2,u,q] = E.tate; type(u) \\ split multiplicative reduction %2 = "t_PADIC" ? ellmul(E, P, 5) \\ P has order 5 %3 = [0] ? z = ellpointtoz(E, [0,0]) %4 = 3 + 11^2 + 2*11^3 + 3*11^4 + O(11^5) ? z^5 %5 = 1 + O(11^5) ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ t_POLMOD of t_POL with t_PADIC coeffs ? liftint(z) \\ lift all p-adics %8 = Mod(8*u + 7, u^2 + 437) @eprog pari-2.7.5/src/functions/elliptic_curves/ellheegner0000644000175000017500000000207212314242551021136 0ustar billbillFunction: ellheegner Section: elliptic_curves C-Name: ellheegner Prototype: G Help: ellheegner(E): return a rational non-torsion point on the elliptic curve E assumed to be of rank 1 Doc: Let $E$ be an elliptic curve over the rationals, assumed to be of (analytic) rank $1$. This returns a non-torsion rational point on the curve, whose canonical height is equal to the product of the elliptic regulator by the analytic Sha. This uses the Heegner point method, described in Cohen GTM 239; the complexity is proportional to the product of the square root of the conductor and the height of the point (thus, it is preferable to apply it to strong Weil curves). \bprog ? E = ellinit([-157^2,0]); ? u = ellheegner(E); print(u[1], "\n", u[2]) 69648970982596494254458225/166136231668185267540804 538962435089604615078004307258785218335/67716816556077455999228495435742408 ? ellheegner(ellinit([0,1])) \\ E has rank 0 ! *** at top-level: ellheegner(E=ellinit *** ^-------------------- *** ellheegner: The curve has even analytic rank. @eprog pari-2.7.5/src/functions/elliptic_curves/ellak0000644000175000017500000000240312314242551020112 0ustar billbillFunction: ellak Section: elliptic_curves C-Name: akell Prototype: GG Help: ellak(E,n): computes the n-th Fourier coefficient of the L-function of the elliptic curve E (assumed E is an integral model). Doc: computes the coefficient $a_n$ of the $L$-function of the elliptic curve $E/\Q$, i.e.~coefficients of a newform of weight 2 by the modularity theorem (\idx{Taniyama-Shimura-Weil conjecture}). $E$ must be an \var{ell} structure over $\Q$ as output by \kbd{ellinit}. $E$ must be given by an integral model, not necessarily minimal, although a minimal model will make the function faster. \bprog ? E = ellinit([0,1]); ? ellak(E, 10) %2 = 0 ? e = ellinit([5^4,5^6]); \\ not minimal at 5 ? ellak(e, 5) \\ wasteful but works %3 = -3 ? E = ellminimalmodel(e); \\ now minimal ? ellak(E, 5) %5 = -3 @eprog\noindent If the model is not minimal at a number of bad primes, then the function will be slower on those $n$ divisible by the bad primes. The speed should be comparable for other $n$: \bprog ? for(i=1,10^6, ellak(E,5)) time = 820 ms. ? for(i=1,10^6, ellak(e,5)) \\ 5 is bad, markedly slower time = 1,249 ms. ? for(i=1,10^5,ellak(E,5*i)) time = 977 ms. ? for(i=1,10^5,ellak(e,5*i)) \\ still slower but not so much on average time = 1,008 ms. @eprog pari-2.7.5/src/functions/elliptic_curves/ellchangecurve0000644000175000017500000000112712314242551022013 0ustar billbillFunction: ellchangecurve Section: elliptic_curves C-Name: ellchangecurve Prototype: GG Help: ellchangecurve(E,v): change data on elliptic curve according to v=[u,r,s,t]. Description: (gen, gen):ell ellchangecurve($1, $2) Doc: changes the data for the elliptic curve $E$ by changing the coordinates using the vector \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the new coordinates, then $x=u^2x'+r$, $y=u^3y'+su^2x'+t$. $E$ must be an \var{ell} structure as output by \kbd{ellinit}. The special case $v = 1$ is also used instead of $[1,0,0,0]$ to denote the trivial coordinate change. pari-2.7.5/src/functions/elliptic_curves/elleta0000644000175000017500000000113112314242551020265 0ustar billbillFunction: elleta Section: elliptic_curves C-Name: elleta Prototype: Gp Help: elleta(w): w=[w1,w2], returns the vector [eta1,eta2] of quasi-periods associated to [w1,w2]. Doc: returns the quasi-periods $[\eta_1,\eta_2]$ associated to the lattice basis $\var{w} = [\omega_1, \omega_2]$. Alternatively, \var{w} can be an elliptic curve $E$ as output by \kbd{ellinit}, in which case, the quasi periods associated to the period lattice basis \kbd{$E$.omega} (namely, \kbd{$E$.eta}) are returned. \bprog ? elleta([1, I]) %1 = [3.141592653589793238462643383, 9.424777960769379715387930149*I] @eprog pari-2.7.5/src/functions/elliptic_curves/ellztopoint0000644000175000017500000000136612366172547021432 0ustar billbillFunction: ellztopoint Section: elliptic_curves C-Name: pointell Prototype: GGp Help: ellztopoint(E,z): coordinates of point P on the curve E corresponding to the complex number z. Doc: $E$ being an \var{ell} as output by \kbd{ellinit}, computes the coordinates $[x,y]$ on the curve $E$ corresponding to the complex number $z$. Hence this is the inverse function of \kbd{ellpointtoz}. In other words, if the curve is put in Weierstrass form $y^2 = 4x^3 - g_2x - g_3$, $[x,y]$ represents the Weierstrass $\wp$-function\sidx{Weierstrass $\wp$-function} and its derivative. More precisely, we have $$x = \wp(z) - b_2/12,\quad y = \wp'(z) - (a_1 x + a_3)/2.$$ If $z$ is in the lattice defining $E$ over $\C$, the result is the point at infinity $[0]$. pari-2.7.5/src/functions/elliptic_curves/elllog0000644000175000017500000000221612366172547020320 0ustar billbillFunction: elllog Section: elliptic_curves C-Name: elllog Prototype: GGGDG Help: 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. Doc: given two points $P$ and $G$ on the elliptic curve $E/\F_q$, returns the discrete logarithm of $P$ in base $G$, i.e. the smallest non-negative integer $n$ such that $P = [n]G$. See \tet{znlog} for the limitations of the underlying discrete log algorithms. If present, $o$ represents the order of $G$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where $N$ is the order of $G$. If no $o$ is given, assume that $G$ generates the curve. The function also assumes that $P$ is a multiple of $G$. \bprog ? a = ffgen(ffinit(2,8),'a); ? E = ellinit([a,1,0,0,1]); \\ over F_{2^8} ? x = a^3; y = ellordinate(E,x)[1]; ? P = [x,y]; G = ellmul(E, P, 113); ? ord = [242, factor(242)]; \\ P generates a group of order 242. Initialize. ? ellorder(E, G, ord) %4 = 242 ? e = elllog(E, P, G, ord) %5 = 15 ? ellmul(E,G,e) == P %6 = 1 @eprog pari-2.7.5/src/functions/elliptic_curves/ellheightmatrix0000644000175000017500000000144512413013143022212 0ustar billbillFunction: ellheightmatrix Section: elliptic_curves C-Name: mathell Prototype: GGp Help: ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E. Doc: $x$ being a vector of points, this function outputs the Gram matrix of $x$ with respect to the N\'eron-Tate height, in other words, the $(i,j)$ component of the matrix is equal to \kbd{ellbil($E$,x[$i$],x[$j$])}. The rank of this matrix, at least in some approximate sense, gives the rank of the set of points, and if $x$ is a basis of the \idx{Mordell-Weil group} of $E$, its determinant is equal to 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. pari-2.7.5/src/functions/elliptic_curves/ellan0000644000175000017500000000110512366172547020131 0ustar billbillFunction: ellan Section: elliptic_curves C-Name: anell Prototype: GL Help: 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). Doc: computes the vector of the first $n$ Fourier coefficients $a_k$ corresponding to the elliptic curve $E$. The curve must be given by an integral model, not necessarily minimal, although a minimal model will make the function faster. Variant: Also available is \fun{GEN}{anellsmall}{GEN e, long n}, which returns a \typ{VECSMALL} instead of a \typ{VEC}, saving on memory. pari-2.7.5/src/functions/elliptic_curves/ellcard0000644000175000017500000000167612314242551020443 0ustar billbillFunction: ellcard Section: elliptic_curves C-Name: ellcard Prototype: GDG Help: ellcard(E,{p}): computes the order of the group E(Fp) for the elliptic curve E, defined over Q or a finite field. Doc: Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over $\Q$ or a finite field $\F_q$. The argument $p$ is best left omitted if the curve is defined over a finite field, and must be a prime number otherwise. 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 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. Variant: Also available is \fun{GEN}{ellcard}{GEN E, GEN p} where $p$ is not \kbd{NULL}. pari-2.7.5/src/functions/number_fields/0000755000175000017500000000000012613365633016533 5ustar billbillpari-2.7.5/src/functions/number_fields/idealfrobenius0000644000175000017500000000200011636712103021431 0ustar billbillFunction: idealfrobenius Section: number_fields C-Name: idealfrobenius Prototype: GGG Help: 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. Doc: Let $K$ be the number field defined by $nf$ and assume $K/\Q$ be a Galois extension with Galois group given \kbd{gal=galoisinit(nf)}, and that $pr$ is the prime ideal $\goth{P}$ in prid format, and that $\goth{P}$ is unramified. This function returns a permutation of \kbd{gal.group} which defines the automorphism $\sigma=\left(\goth{P}\over K/\Q \right)$, i.e the Frobenius element associated to $\goth{P}$. If $p$ is the unique prime number in $\goth{P}$, then $\sigma(x)\equiv x^p\mod\P$ for all $x\in\Z_K$. \bprog ? nf = nfinit(polcyclo(31)); ? gal = galoisinit(nf); ? pr = idealprimedec(nf,101)[1]; ? g = idealfrobenius(nf,gal,pr); ? galoispermtopol(gal,g) %5 = x^8 @eprog\noindent This is correct since $101\equiv 8\mod{31}$. pari-2.7.5/src/functions/number_fields/nfalgtobasis0000644000175000017500000000110411636712103021116 0ustar billbillFunction: nfalgtobasis Section: number_fields C-Name: algtobasis Prototype: GG Help: nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on the integral basis nf.zk. Doc: Given an algebraic number $x$ in the number field $\var{nf}$, transforms it to a column vector on the integral basis \kbd{\var{nf}.zk}. \bprog ? nf = nfinit(y^2 + 4); ? nf.zk %2 = [1, 1/2*y] ? nfalgtobasis(nf, [1,1]~) %3 = [1, 1]~ ? nfalgtobasis(nf, y) %4 = [0, 2]~ ? nfalgtobasis(nf, Mod(y, y^2+4)) %4 = [0, 2]~ @eprog This is the inverse function of \kbd{nfbasistoalg}. pari-2.7.5/src/functions/number_fields/idealadd0000644000175000017500000000246212314242551020200 0ustar billbillFunction: idealadd Section: number_fields C-Name: idealadd Prototype: GGG Help: idealadd(nf,x,y): sum of two ideals x and y in the number field defined by nf. Doc: sum of the two ideals $x$ and $y$ in the number field $\var{nf}$. The result is given in HNF. \bprog ? K = nfinit(x^2 + 1); ? a = idealadd(K, 2, x + 1) \\ ideal generated by 2 and 1+I %2 = [2 1] [0 1] ? pr = idealprimedec(K, 5)[1]; \\ a prime ideal above 5 ? idealadd(K, a, pr) \\ coprime, as expected %4 = [1 0] [0 1] @eprog\noindent This function cannot be used to add arbitrary $\Z$-modules, since it assumes that its arguments are ideals: \bprog ? b = Mat([1,0]~); ? idealadd(K, b, b) \\ only square t_MATs represent ideals *** idealadd: non-square t_MAT in idealtyp. ? c = [2, 0; 2, 0]; idealadd(K, c, c) \\ non-sense %6 = [2 0] [0 2] ? d = [1, 0; 0, 2]; idealadd(K, d, d) \\ non-sense %7 = [1 0] [0 1] @eprog\noindent In the last two examples, we get wrong results since the matrices $c$ and $d$ do not correspond to an ideal: the $\Z$-span of their columns (as usual interpreted as coordinates with respect to the integer basis \kbd{K.zk}) is not an $O_K$-module. To add arbitrary $\Z$-modules generated by the columns of matrices $A$ and $B$, use \kbd{mathnf(concat(A,B))}. pari-2.7.5/src/functions/number_fields/nfsolvemodpr0000644000175000017500000000150712366172547021204 0ustar billbillFunction: nfsolvemodpr Section: number_fields C-Name: nfsolvemodpr Prototype: GGGG Help: 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). Doc: let $P$ be a prime ideal in \key{modpr} format (see \kbd{nfmodprinit}), let $a$ be a matrix, invertible over the residue field, and let $b$ be a column vector or matrix. This function returns a solution of $a\cdot x = b$; the coefficients of $x$ are lifted to \var{nf} elements. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? P = nfmodprinit(K, P); ? a = [y+1, y; y, 0]; b = [1, y]~ ? nfsolvemodpr(K, a,b, P) %5 = [1, 2]~ @eprog Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nfM\_to\_FqM}, then work there. pari-2.7.5/src/functions/number_fields/bnrisconductor0000644000175000017500000000104511636712103021504 0ustar billbillFunction: bnrisconductor Section: number_fields C-Name: bnrisconductor0 Prototype: lGDGDG Help: 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. Doc: $A$, $B$, $C$ represent an extension of the base field, given by class field theory (see~\secref{se:CFT}). Outputs 1 if this modulus is the conductor, and 0 otherwise. This is slightly faster than \kbd{bnrconductor}. pari-2.7.5/src/functions/number_fields/nffactor0000644000175000017500000000303612314242551020251 0ustar billbillFunction: nffactor Section: number_fields C-Name: nffactor Prototype: GG Help: nffactor(nf,T): factor polynomial T in number field nf. Doc: factorization of the univariate polynomial $T$ over the number field $\var{nf}$ given by \kbd{nfinit}; $T$ has coefficients in $\var{nf}$ (i.e.~either scalar, polmod, polynomial or column vector). The factors are sorted by increasing degree. The main variable of $\var{nf}$ must be of \emph{lower} priority than that of $T$, see \secref{se:priority}. However if the polynomial defining the number field occurs explicitly in the coefficients of $T$ as modulus of a \typ{POLMOD} or as a \typ{POL} coefficient, its main variable must be \emph{the same} as the main variable of $T$. For example, \bprog ? nf = nfinit(y^2 + 1); ? nffactor(nf, x^2 + y); \\@com OK ? nffactor(nf, x^2 + Mod(y, y^2+1)); \\ @com OK ? nffactor(nf, x^2 + Mod(z, z^2+1)); \\ @com WRONG @eprog It is possible to input a defining polynomial for \var{nf} instead, but this is in general less efficient since parts of an \kbd{nf} structure will then be computed internally. This is useful in two situations: when you do not need the \kbd{nf} elsewhere, or when you cannot compute the field discriminant due to integer factorization difficulties. In the latter case, if you must use a partial discriminant factorization (as allowed by both \tet{nfdisc} or \tet{nfbasis}) to build a partially correct \var{nf} structure, always input \kbd{nf.pol} to \kbd{nffactor}, and not your makeshift \var{nf}: otherwise factors could be missed. pari-2.7.5/src/functions/number_fields/rnfidealhnf0000644000175000017500000000072712366172547020751 0ustar billbillFunction: rnfidealhnf Section: number_fields C-Name: rnfidealhnf Prototype: GG Help: rnfidealhnf(rnf,x): relative version of idealhnf, where rnf is a relative numberfield. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being a relative ideal (which can be, as in the absolute case, of many different types, including of course elements), computes the HNF pseudo-matrix associated to $x$, viewed as a $\Z_K$-module. pari-2.7.5/src/functions/number_fields/rnfeltabstorel0000644000175000017500000000156212366172547021515 0ustar billbillFunction: rnfeltabstorel Section: number_fields C-Name: rnfeltabstorel Prototype: GG Help: rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}, computes $x$ as an element of the relative extension $L/K$ as a polmod with polmod coefficients. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltabstorel(L, Mod(x, L.pol)) %3 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltabstorel(L, Mod(2, L.pol)) %4 = 2 ? rnfeltabstorel(L, Mod(x, x^2-y)) *** at top-level: rnfeltabstorel(L,Mod *** ^-------------------- *** rnfeltabstorel: inconsistent moduli in rnfeltabstorel: x^2-y != x^4+1 @eprog pari-2.7.5/src/functions/number_fields/bnfisunit0000644000175000017500000000306311636712103020451 0ustar billbillFunction: bnfisunit Section: number_fields C-Name: bnfisunit Prototype: GG Help: 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. Doc: \var{bnf} being the number field data output by \kbd{bnfinit} and $x$ being an algebraic number (type integer, rational or polmod), this outputs the decomposition of $x$ on the fundamental units and the roots of unity if $x$ is a unit, the empty vector otherwise. More precisely, if $u_1$,\dots,$u_r$ are the fundamental units, and $\zeta$ is the generator of the group of roots of unity (\kbd{bnf.tu}), the output is a vector $[x_1,\dots,x_r,x_{r+1}]$ such that $x=u_1^{x_1}\cdots u_r^{x_r}\cdot\zeta^{x_{r+1}}$. The $x_i$ are integers for $i\le r$ and is an integer modulo the order of $\zeta$ for $i=r+1$. Note that \var{bnf} need not contain the fundamental unit explicitly: \bprog ? setrand(1); bnf = bnfinit(x^2-x-100000); ? bnf.fu *** at top-level: bnf.fu *** ^-- *** _.fu: missing units in .fu. ? u = [119836165644250789990462835950022871665178127611316131167, \ 379554884019013781006303254896369154068336082609238336]~; ? bnfisunit(bnf, u) %3 = [-1, Mod(0, 2)]~ @eprog\noindent The given $u$ is the inverse of the fundamental unit implicitly stored in \var{bnf}. In this case, the fundamental unit was not computed and stored in algebraic form since the default accuracy was too low. (Re-run the command at \bs g1 or higher to see such diagnostics.) pari-2.7.5/src/functions/number_fields/galoissubcyclo0000644000175000017500000000501511636712103021471 0ustar billbillFunction: galoissubcyclo Section: number_fields C-Name: galoissubcyclo Prototype: GDGD0,L,Dn Help: 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 the conductor. Doc: computes the subextension of $\Q(\zeta_n)$ fixed by the subgroup $H \subset (\Z/n\Z)^*$. By the Kronecker-Weber theorem, all abelian number fields can be generated in this way (uniquely if $n$ is taken to be minimal). \noindent The pair $(n, H)$ is deduced from the parameters $(N, H)$ as follows \item $N$ an integer: then $n = N$; $H$ is a generator, i.e. an integer or an integer modulo $n$; or a vector of generators. \item $N$ the output of \kbd{znstar($n$)}. $H$ as in the first case above, or a matrix, taken to be a HNF left divisor of the SNF for $(\Z/n\Z)^*$ (of type \kbd{$N$.cyc}), giving the generators of $H$ in terms of \kbd{$N$.gen}. \item $N$ the output of \kbd{bnrinit(bnfinit(y), $m$, 1)} where $m$ is a module. $H$ as in the first case, or a matrix taken to be a HNF left divisor of the SNF for the ray class group modulo $m$ (of type \kbd{$N$.cyc}), giving the generators of $H$ in terms of \kbd{$N$.gen}. In this last case, beware that $H$ is understood relatively to $N$; in particular, if the infinite place does not divide the module, e.g if $m$ is an integer, then it is not a subgroup of $(\Z/n\Z)^*$, but of its quotient by $\{\pm 1\}$. If $fl=0$, compute a polynomial (in the variable \var{v}) defining the the subfield of $\Q(\zeta_n)$ fixed by the subgroup \var{H} of $(\Z/n\Z)^*$. If $fl=1$, compute only the conductor of the abelian extension, as a module. If $fl=2$, output $[pol, N]$, where $pol$ is the polynomial as output when $fl=0$ and $N$ the conductor as output when $fl=1$. The following function can be used to compute all subfields of $\Q(\zeta_n)$ (of exact degree \kbd{d}, if \kbd{d} is set): \bprog polsubcyclo(n, d = -1)= { my(bnr,L,IndexBound); IndexBound = if (d < 0, n, [d]); bnr = bnrinit(bnfinit(y), [n,[1]], 1); L = subgrouplist(bnr, IndexBound, 1); vector(#L,i, galoissubcyclo(bnr,L[i])); } @eprog\noindent Setting \kbd{L = subgrouplist(bnr, IndexBound)} would produce subfields of exact conductor $n\infty$. pari-2.7.5/src/functions/number_fields/idealfactorback0000644000175000017500000000344711636712103021554 0ustar billbillFunction: idealfactorback Section: number_fields C-Name: idealfactorback Prototype: GGDGD0,L, Help: 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. Doc: gives back the ideal corresponding to a factorization. The integer $1$ corresponds to the empty factorization. If $e$ is present, $e$ and $f$ must be vectors of the same length ($e$ being integral), and the corresponding factorization is the product of the $f[i]^{e[i]}$. If not, and $f$ is vector, it is understood as in the preceding case with $e$ a vector of 1s: we return the product of the $f[i]$. Finally, $f$ can be a regular factorization, as produced by \kbd{idealfactor}. \bprog ? nf = nfinit(y^2+1); idealfactor(nf, 4 + 2*y) %1 = [[2, [1, 1]~, 2, 1, [1, 1]~] 2] [[5, [2, 1]~, 1, 1, [-2, 1]~] 1] ? idealfactorback(nf, %) %2 = [10 4] [0 2] ? f = %1[,1]; e = %1[,2]; idealfactorback(nf, f, e) %3 = [10 4] [0 2] ? % == idealhnf(nf, 4 + 2*y) %4 = 1 @eprog If \kbd{flag} is non-zero, perform ideal reductions (\tet{idealred}) along the way. This is most useful if the ideals involved are all \emph{extended} ideals (for instance with trivial principal part), so that the principal parts extracted by \kbd{idealred} are not lost. Here is an example: \bprog ? f = vector(#f, i, [f[i], [;]]); \\ transform to extended ideals ? idealfactorback(nf, f, e, 1) %6 = [[1, 0; 0, 1], [2, 1; [2, 1]~, 1]] ? nffactorback(nf, %[2]) %7 = [4, 2]~ @eprog The extended ideal returned in \kbd{\%6} is the trivial ideal $1$, extended with a principal generator given in factored form. We use \tet{nffactorback} to recover it in standard form. pari-2.7.5/src/functions/number_fields/nfelttrace0000644000175000017500000000022611636712103020575 0ustar billbillFunction: nfelttrace Section: number_fields C-Name: nftrace Prototype: GG Help: nfelttrace(nf,x): trace of x. Doc: returns the absolute trace of $x$. pari-2.7.5/src/functions/number_fields/idealintersect0000644000175000017500000000136112314242551021445 0ustar billbillFunction: idealintersect Section: number_fields C-Name: idealintersect Prototype: GGG Help: idealintersect(nf,A,B): intersection of two ideals A and B in the number field defined by nf. Doc: intersection of the two ideals $A$ and $B$ in the number field $\var{nf}$. The result is given in HNF. \bprog ? nf = nfinit(x^2+1); ? idealintersect(nf, 2, x+1) %2 = [2 0] [0 2] @eprog This function does not apply to general $\Z$-modules, e.g.~orders, since its arguments are replaced by the ideals they generate. The following script intersects $\Z$-modules $A$ and $B$ given by matrices of compatible dimensions with integer coefficients: \bprog ZM_intersect(A,B) = { my(Ker = matkerint(concat(A,B))); mathnf( A * Ker[1..#A,] ) } @eprog pari-2.7.5/src/functions/number_fields/galoisfixedfield0000644000175000017500000000357711636712103021764 0ustar billbillFunction: galoisfixedfield Section: number_fields C-Name: galoisfixedfield Prototype: GGD0,L,Dn Help: 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.pol over the field defined by P, where the variable v stands for a root of P. Description: (gen, gen, ?small, ?var):vec galoisfixedfield($1, $2, $3, $4) Doc: \var{gal} being be a Galois group as output by \tet{galoisinit} and \var{perm} an element of $\var{gal}.group$, a vector of such elements or a subgroup of \var{gal} as returned by galoissubgroups, computes the fixed field of \var{gal} by the automorphism defined by the permutations \var{perm} of the roots $\var{gal}.roots$. $P$ is guaranteed to be squarefree modulo $\var{gal}.p$. If no flags or $\fl=0$, output format is the same as for \tet{nfsubfield}, returning $[P,x]$ such that $P$ is a polynomial defining the fixed field, and $x$ is a root of $P$ expressed as a polmod in $\var{gal}.pol$. If $\fl=1$ return only the polynomial $P$. If $\fl=2$ return $[P,x,F]$ where $P$ and $x$ are as above and $F$ is the factorization of $\var{gal}.pol$ over the field defined by $P$, where variable $v$ ($y$ by default) stands for a root of $P$. The priority of $v$ must be less than the priority of the variable of $\var{gal}.pol$ (see \secref{se:priority}). Example: \bprog ? G = galoisinit(x^4+1); ? galoisfixedfield(G,G.group[2],2) %2 = [x^2 + 2, Mod(x^3 + x, x^4 + 1), [x^2 - y*x - 1, x^2 + y*x - 1]] @eprog\noindent computes the factorization $x^4+1=(x^2-\sqrt{-2}x-1)(x^2+\sqrt{-2}x-1)$ pari-2.7.5/src/functions/number_fields/matalgtobasis0000644000175000017500000000051211636712103021276 0ustar billbillFunction: matalgtobasis Section: number_fields C-Name: matalgtobasis Prototype: GG Help: matalgtobasis(nf,x): nfalgtobasis applied to every element of the vector or matrix x. Doc: $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a (row or column) vector or matrix, apply \tet{nfalgtobasis} to each entry of $x$. pari-2.7.5/src/functions/number_fields/polredabs0000644000175000017500000000764312366172547020450 0ustar billbillFunction: polredabs Section: number_fields C-Name: polredabs0 Prototype: GD0,L, Help: 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)). Doc: returns a canonical defining polynomial $P$ for the number field $\Q[X]/(T)$ defined by $T$, such that the sum of the squares of the modulus of the roots (i.e.~the $T_2$-norm) is minimal. Different $T$ defining isomorphic number fields will yield the same $P$. All $T$ accepted by \tet{nfinit} are also allowed here, e.g. non-monic polynomials, or pairs \kbd{[T, listP]} specifying that a non-maximal order may be used. \misctitle{Warning 1} Using a \typ{POL} $T$ requires fully factoring the discriminant of $T$, which may be very hard. The format \kbd{[T, listP]} computes only a suborder of the maximal order and replaces this part of the algorithm by a polynomial time computation. In that case the polynomial $P$ is a priori no longer canonical, and it may happen that it does not have minimal $T_2$ norm. The routine attempts to certify the result independently of this order computation (as per \tet{nfcertify}: we try to prove that the order is maximal); if it fails, the routine returns $0$ instead of $P$. In order to force an output in that case as well, you may either use \tet{polredbest}, or \kbd{polredabs(,16)}, or \bprog polredabs([T, nfbasis([T, listP])]) @eprog\noindent (In all three cases, the result is no longer canonical.) \misctitle{Warning 2} Apart from the factorization of the discriminant of $T$, this routine runs in polynomial time for a \emph{fixed} degree. But the complexity is exponential in the degree: this routine may be exceedingly slow when the number field has many subfields, hence a lot of elements of small $T_2$-norm. If you do not need a canonical polynomial, the function \tet{polredbest} is in general much faster (it runs in polynomial time), and tends to return polynomials with smaller discriminants. The binary digits of $\fl$ mean 1: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{Mod(a, P)} is a root of the original $T$. 4: gives \emph{all} polynomials of minimal $T_2$ norm; of the two polynomials $P(x)$ and $\pm P(-x)$, only one is given. 16: Possibly use a suborder of the maximal order, \emph{without} attempting to certify the result as in Warning 1: we always return a polynomial and never $0$. The result is a priori not canonical. \bprog ? T = x^16 - 136*x^14 + 6476*x^12 - 141912*x^10 + 1513334*x^8 \ - 7453176*x^6 + 13950764*x^4 - 5596840*x^2 + 46225 ? T1 = polredabs(T); T2 = polredbest(T); ? [ norml2(polroots(T1)), norml2(polroots(T2)) ] %3 = [88.0000000, 120.000000] ? [ sizedigit(poldisc(T1)), sizedigit(poldisc(T2)) ] %4 = [75, 67] @eprog Variant: Instead of the above hardcoded numerical flags, one should use an or-ed combination of \item \tet{nf_PARTIALFACT}: possibly use a suborder of the maximal order, \emph{without} attempting to certify the result. \item \tet{nf_ORIG}: return $[P, a]$, where \kbd{Mod(a, P)} is a root of $T$. \item \tet{nf_RAW}: return $[P, b]$, where \kbd{Mod(b, T)} is a root of $P$. The algebraic integer $b$ is the raw result produced by the small vectors enumeration in the maximal order; $P$ was computed as the characteristic polynomial of \kbd{Mod(b, T)}. \kbd{Mod(a, P)} as in \tet{nf_ORIG} is obtained with \tet{modreverse}. \item \tet{nf_ADDZK}: if $r$ is the result produced with some of the above flags (of the form $P$ or $[P,c]$), return \kbd{[r,zk]}, where \kbd{zk} is a $\Z$-basis for the maximal order of $\Q[X]/(P)$. \item \tet{nf_ALL}: return a vector of results of the above form, for all polynomials of minimal $T_2$-norm. pari-2.7.5/src/functions/number_fields/nfhnfmod0000644000175000017500000000103311636712103020242 0ustar billbillFunction: nfhnfmod Section: number_fields C-Name: nfhnfmod Prototype: GGG Help: 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. Doc: given a pseudo-matrix $(A,I)$ and an ideal \var{detx} which is contained in (read integral multiple of) the determinant of $(A,I)$, finds a pseudo-basis in \idx{Hermite normal form} of the module generated by $(A,I)$. This avoids coefficient explosion. \var{detx} can be computed using the function \kbd{nfdetint}. pari-2.7.5/src/functions/number_fields/nfeltreduce0000644000175000017500000000054711636712103020754 0ustar billbillFunction: nfeltreduce Section: number_fields C-Name: nfreduce Prototype: GGG Help: nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small. Doc: given an ideal \var{id} in Hermite normal form and an element $a$ of the number field $\var{nf}$, finds an element $r$ in $\var{nf}$ such that $a-r$ belongs to the ideal and $r$ is small. pari-2.7.5/src/functions/number_fields/rnflllgram0000644000175000017500000000121011636712103020600 0ustar billbillFunction: rnflllgram Section: number_fields C-Name: rnflllgram Prototype: GGGp Help: 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. Doc: given a polynomial \var{pol} with coefficients in \var{nf} defining a relative extension $L$ and a suborder \var{order} of $L$ (of maximal rank), as output by \kbd{rnfpseudobasis}$(\var{nf},\var{pol})$ or similar, gives $[[\var{neworder}],U]$, where \var{neworder} is a reduced order and $U$ is the unimodular transformation matrix. pari-2.7.5/src/functions/number_fields/nfeltdiveuc0000644000175000017500000000062311636712103020757 0ustar billbillFunction: nfeltdiveuc Section: number_fields C-Name: nfdiveuc Prototype: GGG Help: nfdiveuc(nf,x,y): gives algebraic integer q such that x-by is small. Doc: given two elements $x$ and $y$ in \var{nf}, computes an algebraic integer $q$ in the number field $\var{nf}$ such that the components of $x-qy$ are reasonably small. In fact, this is functionally identical to \kbd{round(nfdiv(\var{nf},x,y))}. pari-2.7.5/src/functions/number_fields/zetakinit0000644000175000017500000000256212314242551020454 0ustar billbillFunction: zetakinit Section: number_fields C-Name: initzeta Prototype: Gp Help: zetakinit(bnf): compute number field information necessary to use zetak. bnf may also be an irreducible polynomial. Doc: computes a number of initialization data concerning the number field associated to \kbd{bnf} so as to be able to compute the \idx{Dedekind} zeta and lambda functions, respectively $\kbd{zetak}(x)$ and $\kbd{zetak}(x,1)$, at the current real precision. If you do not need the \kbd{bnfinit} data somewhere else, you may call it with an irreducible polynomial instead of a \var{bnf}: it will call \kbd{bnfinit} itself. The result is a 9-component vector $v$ whose components are very technical and cannot really be used except through the \kbd{zetak} function. This function is very inefficient and should be rewritten. It needs to computes millions of coefficients of the corresponding Dirichlet series if the precision is big. Unless the discriminant is small it will not be able to handle more than 9 digits of relative precision. For instance, \kbd{zetakinit(x\pow 8 - 2)} needs 440MB of memory at default precision. This function will fail with the message \bprog *** bnrL1: overflow in zeta_get_N0 [need too many primes]. @eprog\noindent if the approximate functional equation requires us to sum too many terms (if the discriminant of the number field is too large). pari-2.7.5/src/functions/number_fields/rnfdet0000644000175000017500000000035311636712103017731 0ustar billbillFunction: rnfdet Section: number_fields C-Name: rnfdet Prototype: GG Help: rnfdet(nf,M): given a pseudo-matrix M, compute its determinant. Doc: given a pseudo-matrix $M$ over the maximal order of $\var{nf}$, computes its determinant. pari-2.7.5/src/functions/number_fields/rnfhnfbasis0000644000175000017500000000106211636712103020750 0ustar billbillFunction: rnfhnfbasis Section: number_fields C-Name: rnfhnfbasis Prototype: GG Help: 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. Doc: given $\var{bnf}$ as output by \kbd{bnfinit}, and either a polynomial $x$ with coefficients in $\var{bnf}$ defining a relative extension $L$ of $\var{bnf}$, or a pseudo-basis $x$ of such an extension, gives either a true $\var{bnf}$-basis of $L$ in upper triangular Hermite normal form, if it exists, and returns $0$ otherwise. pari-2.7.5/src/functions/number_fields/nfeltnorm0000644000175000017500000000022111636712103020445 0ustar billbillFunction: nfeltnorm Section: number_fields C-Name: nfnorm Prototype: GG Help: nfeltnorm(nf,x): norm of x. Doc: returns the absolute norm of $x$. pari-2.7.5/src/functions/number_fields/nfhnf0000644000175000017500000000077311636712103017554 0ustar billbillFunction: 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 Doc: given a pseudo-matrix $(A,I)$, finds a pseudo-basis in \idx{Hermite normal form} of the module it generates. Variant: Also available: \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. pari-2.7.5/src/functions/number_fields/rnfpseudobasis0000644000175000017500000000153211636712103021476 0ustar billbillFunction: rnfpseudobasis Section: number_fields C-Name: rnfpseudobasis Prototype: GG Help: 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. Doc: given a number field $\var{nf}$ as output by \kbd{nfinit} and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes a pseudo-basis $(A,I)$ for the maximal order $\Z_L$ viewed as a $\Z_K$-module, and the relative discriminant of $L$. This is output as a four-element row vector $[A,I,D,d]$, where $D$ is the relative ideal discriminant and $d$ is the relative discriminant considered as an element of $\var{nf}^*/{\var{nf}^*}^2$. pari-2.7.5/src/functions/number_fields/nfeltval0000644000175000017500000000071412413013143020253 0ustar billbillFunction: 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. 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{idealval(\var{nf},x,\var{pr})}, since $x$ is then converted to a principal ideal. pari-2.7.5/src/functions/number_fields/galoissubgroups0000644000175000017500000000145211636712103021700 0ustar billbillFunction: galoissubgroups Section: number_fields C-Name: galoissubgroups Prototype: G Help: galoissubgroups(G):Output all the subgroups of G. 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 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}. To get the subfield fixed by a subgroup \var{sub} of \var{gal}, use \bprog galoisfixedfield(gal,sub[1]) @eprog pari-2.7.5/src/functions/number_fields/nfisisom0000644000175000017500000000042411636712103020275 0ustar billbillFunction: nfisisom Section: number_fields C-Name: nfisisom Prototype: GG Help: nfisisom(x,y): as nfisincl but tests whether x is isomorphic to y. Doc: as \tet{nfisincl}, but tests for isomorphism. If either $x$ or $y$ is a number field, a much faster algorithm will be used. pari-2.7.5/src/functions/number_fields/galoisidentify0000644000175000017500000000212111636712103021454 0ustar billbillFunction: galoisidentify Section: number_fields C-Name: galoisidentify Prototype: G Help: 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. Doc: \var{gal} being be a Galois group as output by \tet{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, by Hans Ulrich Besche, Bettina Eick and Eamonn O'Brien. This command also accepts subgroups returned by \kbd{galoissubgroups}. The current implementation is limited to degree less or equal to $127$. Some larger ``easy'' orders are also supported. The output is similar to the output of the function \kbd{IdGroup} in GAP4. Note that GAP4 \kbd{IdGroup} handles all groups of order less than $2000$ except $1024$, so you can use \tet{galoisexport} and GAP4 to identify large Galois groups. pari-2.7.5/src/functions/number_fields/bnfisintnorm0000644000175000017500000000157712314242551021167 0ustar billbillFunction: bnfisintnorm Section: number_fields C-Name: bnfisintnorm Prototype: GG Help: 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). Doc: computes a complete system of solutions (modulo units of positive norm) of the absolute norm equation $\Norm(a)=x$, where $a$ is an integer in $\var{bnf}$. If $\var{bnf}$ has not been certified, the correctness of the result depends on the validity of \idx{GRH}. See also \tet{bnfisnorm}. Variant: The function \fun{GEN}{bnfisintnormabs}{GEN bnf, GEN a} returns a complete system of solutions modulo units of the absolute norm equation $|\Norm(x)| = |a|$. As fast as \kbd{bnfisintnorm}, but solves the two equations $\Norm(x) = \pm a$ simultaneously. pari-2.7.5/src/functions/number_fields/idealnumden0000644000175000017500000000061012314242551020727 0ustar billbillFunction: idealnumden Section: number_fields C-Name: idealnumden Prototype: GG Help: idealnumden(nf,x): returns [A,B], where A,B are coprime integer ideals such that x = A/B Doc: returns $[A,B]$, where $A,B$ are coprime integer ideals such that $x = A/B$, in the number field $\var{nf}$. \bprog ? nf = nfinit(x^2+1); ? idealnumden(nf, (x+1)/2) %2 = [[1, 0; 0, 1], [2, 1; 0, 1]] @eprog pari-2.7.5/src/functions/number_fields/rnfidealreltoabs0000644000175000017500000000174112366172547022006 0ustar billbillFunction: rnfidealreltoabs Section: number_fields C-Name: rnfidealreltoabs Prototype: GG Help: rnfidealreltoabs(rnf,x): transforms the ideal x from relative to absolute representation. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal, given as a $\Z_K$-module by a pseudo matrix $[A,I]$. This function returns the ideal $x$ as an absolute ideal of $L/\Q$ in the form of a $\Z$-basis, given by a vector of polynomials (modulo \kbd{rnf.pol}). The reason why we do not return the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, then \bprog xabs = rnfidealreltoabs(L, x); xLabs = mathnf(matalgtobasis(Labs, xabs)); @eprog\noindent computes a traditional HNF \kbd{xLabs} for $x$ in terms of the fixed $\Z$-basis \kbd{Labs.zk}. pari-2.7.5/src/functions/number_fields/polgalois0000644000175000017500000001025212314242551020436 0ustar billbillFunction: polgalois Section: number_fields C-Name: polgalois Prototype: Gp Help: 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. Doc: \idx{Galois} group of the non-constant polynomial $T\in\Q[X]$. In the present version \vers, $T$ must be irreducible and the degree $d$ of $T$ must be less than or equal to 7. If the \tet{galdata} package has been installed, degrees 8, 9, 10 and 11 are also implemented. By definition, if $K = \Q[x]/(T)$, this computes the action of the Galois group of the Galois closure of $K$ on the $d$ distinct roots of $T$, up to conjugacy (corresponding to different root orderings). The output is a 4-component vector $[n,s,k,name]$ with the following meaning: $n$ is the cardinality of the group, $s$ is its signature ($s=1$ if the group is a subgroup of the alternating group $A_d$, $s=-1$ otherwise) and name is a character string containing name of the transitive group according to the GAP 4 transitive groups library by Alexander Hulpke. $k$ is more arbitrary and the choice made up to version~2.2.3 of PARI is rather unfortunate: for $d > 7$, $k$ is the numbering of the group among all transitive subgroups of $S_d$, as given in ``The transitive groups of degree up to eleven'', G.~Butler and J.~McKay, \emph{Communications in Algebra}, vol.~11, 1983, pp.~863--911 (group $k$ is denoted $T_k$ there). And for $d \leq 7$, it was ad hoc, so as to ensure that a given triple would denote a unique group. Specifically, for polynomials of degree $d\leq 7$, the groups are coded as follows, using standard notations \smallskip In degree 1: $S_1=[1,1,1]$. \smallskip In degree 2: $S_2=[2,-1,1]$. \smallskip In degree 3: $A_3=C_3=[3,1,1]$, $S_3=[6,-1,1]$. \smallskip In degree 4: $C_4=[4,-1,1]$, $V_4=[4,1,1]$, $D_4=[8,-1,1]$, $A_4=[12,1,1]$, $S_4=[24,-1,1]$. \smallskip In degree 5: $C_5=[5,1,1]$, $D_5=[10,1,1]$, $M_{20}=[20,-1,1]$, $A_5=[60,1,1]$, $S_5=[120,-1,1]$. \smallskip In degree 6: $C_6=[6,-1,1]$, $S_3=[6,-1,2]$, $D_6=[12,-1,1]$, $A_4=[12,1,1]$, $G_{18}=[18,-1,1]$, $S_4^-=[24,-1,1]$, $A_4\times C_2=[24,-1,2]$, $S_4^+=[24,1,1]$, $G_{36}^-=[36,-1,1]$, $G_{36}^+=[36,1,1]$, $S_4\times C_2=[48,-1,1]$, $A_5=PSL_2(5)=[60,1,1]$, $G_{72}=[72,-1,1]$, $S_5=PGL_2(5)=[120,-1,1]$, $A_6=[360,1,1]$, $S_6=[720,-1,1]$. \smallskip In degree 7: $C_7=[7,1,1]$, $D_7=[14,-1,1]$, $M_{21}=[21,1,1]$, $M_{42}=[42,-1,1]$, $PSL_2(7)=PSL_3(2)=[168,1,1]$, $A_7=[2520,1,1]$, $S_7=[5040,-1,1]$. \smallskip This is deprecated and obsolete, but for reasons of backward compatibility, we cannot change this behavior yet. So you can use the default \tet{new_galois_format} to switch to a consistent naming scheme, namely $k$ is always the standard numbering of the group among all transitive subgroups of $S_n$. If this default is in effect, the above groups will be coded as: \smallskip In degree 1: $S_1=[1,1,1]$. \smallskip In degree 2: $S_2=[2,-1,1]$. \smallskip In degree 3: $A_3=C_3=[3,1,1]$, $S_3=[6,-1,2]$. \smallskip In degree 4: $C_4=[4,-1,1]$, $V_4=[4,1,2]$, $D_4=[8,-1,3]$, $A_4=[12,1,4]$, $S_4=[24,-1,5]$. \smallskip In degree 5: $C_5=[5,1,1]$, $D_5=[10,1,2]$, $M_{20}=[20,-1,3]$, $A_5=[60,1,4]$, $S_5=[120,-1,5]$. \smallskip In degree 6: $C_6=[6,-1,1]$, $S_3=[6,-1,2]$, $D_6=[12,-1,3]$, $A_4=[12,1,4]$, $G_{18}=[18,-1,5]$, $A_4\times C_2=[24,-1,6]$, $S_4^+=[24,1,7]$, $S_4^-=[24,-1,8]$, $G_{36}^-=[36,-1,9]$, $G_{36}^+=[36,1,10]$, $S_4\times C_2=[48,-1,11]$, $A_5=PSL_2(5)=[60,1,12]$, $G_{72}=[72,-1,13]$, $S_5=PGL_2(5)=[120,-1,14]$, $A_6=[360,1,15]$, $S_6=[720,-1,16]$. \smallskip In degree 7: $C_7=[7,1,1]$, $D_7=[14,-1,2]$, $M_{21}=[21,1,3]$, $M_{42}=[42,-1,4]$, $PSL_2(7)=PSL_3(2)=[168,1,5]$, $A_7=[2520,1,6]$, $S_7=[5040,-1,7]$. \smallskip \misctitle{Warning} The method used is that of resolvent polynomials and is sensitive to the current precision. The precision is updated internally but, in very rare cases, a wrong result may be returned if the initial precision was not sufficient. Variant: To enable the new format in library mode, set the global variable \tet{new_galois_format} to $1$. pari-2.7.5/src/functions/number_fields/rnfbasistoalg0000644000175000017500000000064611636712103021312 0ustar billbillFunction: rnfbasistoalg Section: number_fields C-Name: rnfbasistoalg Prototype: GG Help: rnfbasistoalg(rnf,x): relative version of nfbasistoalg, where rnf is a relative numberfield. Doc: computes the representation of $x$ as a polmod with polmods coefficients. Here, $\var{rnf}$ is a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an element of $L$ expressed on the relative integral basis. pari-2.7.5/src/functions/number_fields/galoissubfields0000644000175000017500000000066011636712103021627 0ustar billbillFunction: galoissubfields Section: number_fields C-Name: galoissubfields Prototype: GD0,L,Dn Help: galoissubfields(G,{flags=0},{v}):Output all the subfields of G. flags have the same meaning as for galoisfixedfield. Doc: outputs all the subfields of the Galois group \var{G}, as a vector. This works by applying \kbd{galoisfixedfield} to all subgroups. The meaning of the flag \var{fl} is the same as for \kbd{galoisfixedfield}. pari-2.7.5/src/functions/number_fields/nfeltpow0000644000175000017500000000054211636712103020305 0ustar billbillFunction: nfeltpow Section: number_fields C-Name: nfpow Prototype: GGG Help: nfeltpow(nf,x,k): element x^k in nf. Doc: given an element $x$ in \var{nf}, and a positive or negative integer $k$, computes $x^k$ in the number field $\var{nf}$. Variant: \fun{GEN}{nfinv}{GEN nf, GEN x} correspond to $k = -1$, and \fun{GEN}{nfsqr}{GEN nf,GEN x} to $k = 2$. pari-2.7.5/src/functions/number_fields/idealcoprime0000644000175000017500000000057011636712103021105 0ustar billbillFunction: idealcoprime Section: number_fields C-Name: idealcoprime Prototype: GGG Help: idealcoprime(nf,x,y): gives an element b in nf such that b. x is an integral ideal coprime to the integral ideal y. Doc: given two integral ideals $x$ and $y$ in the number field $\var{nf}$, returns a $\beta$ in the field, such that $\beta\cdot x$ is an integral ideal coprime to $y$. pari-2.7.5/src/functions/number_fields/galoisexport0000644000175000017500000000246712314242551021176 0ustar billbillFunction: galoisexport Section: number_fields C-Name: galoisexport Prototype: GD0,L, Help: 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). Doc: \var{gal} being be a Galois group as output by \tet{galoisinit}, export the underlying permutation group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example compute the index of the underlying abstract group in the GAP library: \bprog ? G = galoisinit(x^6+108); ? s = galoisexport(G) %2 = "Group((1, 2, 3)(4, 5, 6), (1, 4)(2, 6)(3, 5))" ? extern("echo \"IdGroup("s");\" | gap -q") %3 = [6, 1] ? galoisidentify(G) %4 = [6, 1] @eprog\noindent This command also accepts subgroups returned by \kbd{galoissubgroups}. To \emph{import} a GAP permutation into gp (for \tet{galoissubfields} for instance), the following GAP function may be useful: \bprog PermToGP := function(p, n) return Permuted([1..n],p); end; gap> p:= (1,26)(2,5)(3,17)(4,32)(6,9)(7,11)(8,24)(10,13)(12,15)(14,27) (16,22)(18,28)(19,20)(21,29)(23,31)(25,30) gap> PermToGP(p,32); [ 26, 5, 17, 32, 2, 9, 11, 24, 6, 13, 7, 15, 10, 27, 12, 22, 3, 28, 20, 19, 29, 16, 31, 8, 30, 1, 14, 18, 21, 25, 23, 4 ] @eprog pari-2.7.5/src/functions/number_fields/modreverse0000644000175000017500000000300712314242551020620 0ustar billbillFunction: modreverse Section: number_fields C-Name: modreverse Prototype: G Help: modreverse(z): reverse polmod of the polmod z, if it exists. Doc: let $z = \kbd{Mod(A, T)}$ be a polmod, and $Q$ be its minimal polynomial, which must satisfy $\text{deg}(Q) = \text{deg}(T)$. Returns a ``reverse polmod'' \kbd{Mod(B, Q)}, which is a root of $T$. This is quite useful when one changes the generating element in algebraic extensions: \bprog ? u = Mod(x, x^3 - x -1); v = u^5; ? w = modreverse(v) %2 = Mod(x^2 - 4*x + 1, x^3 - 5*x^2 + 4*x - 1) @eprog\noindent which means that $x^3 - 5x^2 + 4x -1$ is another defining polynomial for the cubic field $$\Q(u) = \Q[x]/(x^3 - x - 1) = \Q[x]/(x^3 - 5x^2 + 4x - 1) = \Q(v),$$ and that $u \to v^2 - 4v + 1$ gives an explicit isomorphism. From this, it is easy to convert elements between the $A(u)\in \Q(u)$ and $B(v)\in \Q(v)$ representations: \bprog ? A = u^2 + 2*u + 3; subst(lift(A), 'x, w) %3 = Mod(x^2 - 3*x + 3, x^3 - 5*x^2 + 4*x - 1) ? B = v^2 + v + 1; subst(lift(B), 'x, v) %4 = Mod(26*x^2 + 31*x + 26, x^3 - x - 1) @eprog If the minimal polynomial of $z$ has lower degree than expected, the routine fails \bprog ? u = Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1) ? modreverse(u) *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4 *** Break loop: type 'break' to go back to GP prompt break> Vec( dbg_err() ) \\ ask for more info ["e_DOMAIN", "modreverse", "deg(minpoly(z))", "<", 4, Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1)] break> minpoly(u) x^2 - 8 @eprog pari-2.7.5/src/functions/number_fields/ideallog0000644000175000017500000000205211636712103020225 0ustar billbillFunction: ideallog Section: number_fields C-Name: ideallog Prototype: GGG Help: 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). Doc: $\var{nf}$ is a number field, \var{bid} is as output by \kbd{idealstar(nf, D, \dots)} and $x$ a non-necessarily integral element of \var{nf} which must have valuation equal to 0 at all prime ideals in the support of $\kbd{D}$. This function computes the discrete logarithm of $x$ on the generators given in \kbd{\var{bid}.gen}. In other words, if $g_i$ are these generators, of orders $d_i$ respectively, the result is a column vector of integers $(x_i)$ such that $0\le x_i B && !setsearch(addprimes(), lastp), warning("nf may be incorrect!")) @eprog\noindent This is a sufficient but not a necessary condition, hence the warning, instead of an error. N.B. \kbd{lastp} is the last entry in the first column of the \kbd{check} matrix, i.e. the largest prime dividing \kbd{nf.disc} if $\leq B$ or if it belongs to the prime table. The function \tet{nfcertify} speeds up and automates the above process: \bprog ? B = 10^5; ? nf = nfinit([T, B]); ? nfcertify(nf) %3 = [] \\ nf is unconditionally correct ? basis = nf.zk; ? disc = nf.disc; @eprog \synt{nfbasis}{GEN T, GEN *d, GEN listP = NULL}, which returns the order basis, and where \kbd{*d} receives the order discriminant. pari-2.7.5/src/functions/number_fields/nfeltmod0000644000175000017500000000064711636712103020265 0ustar billbillFunction: nfeltmod Section: number_fields C-Name: nfmod Prototype: GGG Help: nfeltmod(nf,x,y): gives r such that r=x-by is small with q algebraic integer. Doc: given two elements $x$ and $y$ in \var{nf}, computes an element $r$ of $\var{nf}$ of the form $r=x-qy$ with $q$ and algebraic integer, and such that $r$ is small. This is functionally identical to $$\kbd{x - nfmul(\var{nf},round(nfdiv(\var{nf},x,y)),y)}.$$ pari-2.7.5/src/functions/number_fields/rnfidealtwoelt0000644000175000017500000000071711636712103021476 0ustar billbillFunction: rnfidealtwoelt Section: number_fields C-Name: rnfidealtwoelement Prototype: GG Help: rnfidealtwoelt(rnf,x): relative version of idealtwoelt, where rnf is a relative numberfield. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an ideal of the relative extension $L/K$ given by a pseudo-matrix, gives a vector of two generators of $x$ over $\Z_L$ expressed as polmods with polmod coefficients. pari-2.7.5/src/functions/number_fields/polcompositum0000644000175000017500000000626612314242551021371 0ustar billbillFunction: polcompositum 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. 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))$. The factors are given by a list of polynomials $R$ in $\Z[X]$, associated to the number field $\Q(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 disjoint. Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it is in general much faster to proceed as follows \bprog nf = nfinit(P); L = nffactor(nf, Q)[,1]; vector(#L, i, rnfequation(nf, L[i])) @eprog\noindent 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$ 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$. 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})$: \bprog ? L = polcompositum(x^5 - 5, 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$) ? R \\@com defines the compositum %3 = x^20 + 5*x^19 + 15*x^18 + 35*x^17 + 70*x^16 + 141*x^15 + 260*x^14\ + 355*x^13 + 95*x^12 - 1460*x^11 - 3279*x^10 - 3660*x^9 - 2005*x^8 \ + 705*x^7 + 9210*x^6 + 13506*x^5 + 7145*x^4 - 2740*x^3 + 1040*x^2 \ - 320*x + 256 ? a^5 - 5 \\@com a fifth root of $5$ %4 = 0 ? [T, X] = polredbest(R, 1); ? T \\@com simpler defining polynomial for $\Q[x]/(R)$ %6 = x^20 + 25*x^10 + 5 ? X \\ @com root of $R$ in $\Q[y]/(T(y))$ %7 = Mod(-1/11*x^15 - 1/11*x^14 + 1/22*x^10 - 47/22*x^5 - 29/11*x^4 + 7/22,\ x^20 + 25*x^10 + 5) ? a = subst(a.pol, 'x, X) \\@com \kbd{a} in the new coordinates %8 = Mod(1/11*x^14 + 29/11*x^4, x^20 + 25*x^10 + 5) ? a^5 - 5 %9 = 0 @eprog Variant: Also available are \fun{GEN}{compositum}{GEN P, GEN Q} ($\fl = 0$) and \fun{GEN}{compositum2}{GEN P, GEN Q} ($\fl = 1$). pari-2.7.5/src/functions/number_fields/idealaddtoone0000644000175000017500000000154411636712103021246 0ustar billbillFunction: idealaddtoone Section: number_fields C-Name: idealaddtoone0 Prototype: GGDG Help: 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. Doc: $x$ and $y$ being two co-prime integral ideals (given in any form), this gives a two-component row vector $[a,b]$ such that $a\in x$, $b\in y$ and $a+b=1$. The alternative syntax $\kbd{idealaddtoone}(\var{nf},v)$, is supported, where $v$ is a $k$-component vector of ideals (given in any form) which sum to $\Z_K$. This outputs a $k$-component vector $e$ such that $e[i]\in x[i]$ for $1\le i\le k$ and $\sum_{1\le i\le k}e[i]=1$. pari-2.7.5/src/functions/number_fields/nfsubfields0000644000175000017500000000171411636712103020755 0ustar billbillFunction: nfsubfields Section: number_fields C-Name: nfsubfields Prototype: GD0,L, Help: 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. Doc: finds all subfields of degree $d$ of the number field defined by the (monic, integral) polynomial \var{pol} (all subfields if $d$ is null or omitted). The 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 $\var{nf}$. This routine uses J.~Kl\"uners's algorithm in the general case, and B.~Allombert's \tet{galoissubfields} when \var{nf} is Galois (with weakly supersolvable Galois group).\sidx{Galois}\sidx{subfield} pari-2.7.5/src/functions/number_fields/rnfpolredbest0000644000175000017500000000366512366172547021346 0ustar billbillFunction: rnfpolredbest Section: number_fields C-Name: rnfpolredbest Prototype: GGD0,L, Help: 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. Doc: relative version of \kbd{polredbest}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a simpler relative polynomial $P$ defining the same field. As opposed to \tet{rnfpolredabs} this function does not return a \emph{smallest} (canonical) polynomial with respect to some measure, but it does run in polynomial time. The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. Same as but faster than \bprog rnfequation(nf, rnfpolredbest(nf,pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. \bprog ? K = nfinit(y^3-2); pol = x^2 +x*y + y^2; ? [P, a] = rnfpolredbest(K,pol,1); ? P %3 = x^2 - x + Mod(y - 1, y^3 - 2) ? a %4 = Mod(Mod(2*y^2+3*y+4,y^3-2)*x + Mod(-y^2-2*y-2,y^3-2), x^2 - x + Mod(y-1,y^3-2)) ? subst(K.pol,y,a) %5 = 0 ? [Pabs, a, b] = rnfpolredbest(K,pol,3); ? Pabs %7 = x^6 - 3*x^5 + 5*x^3 - 3*x + 1 ? a %8 = Mod(-x^2+x+1, x^6-3*x^5+5*x^3-3*x+1) ? b %9 = Mod(2*x^5-5*x^4-3*x^3+10*x^2+5*x-5, x^6-3*x^5+5*x^3-3*x+1) ? subst(K.pol,y,a) %10 = 0 ? substvec(pol,[x,y],[a,b]) %11 = 0 @eprog pari-2.7.5/src/functions/number_fields/rnfeltnorm0000644000175000017500000000103112366172547020644 0ustar billbillFunction: rnfeltnorm Section: number_fields C-Name: rnfeltnorm Prototype: GG Help: rnfeltnorm(rnf,x): returns the relative norm N_{L/K}(x), as an element of K Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative norm $N_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfeltnorm(L, Mod(x, L.pol)) %2 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltnorm(L, 2) %3 = 4 ? rnfeltnorm(L, Mod(x, x^2-y)) @eprog pari-2.7.5/src/functions/number_fields/rnfsteinitz0000644000175000017500000000172511636712103021032 0ustar billbillFunction: rnfsteinitz Section: number_fields C-Name: rnfsteinitz Prototype: GG Help: 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. Doc: given a number field $\var{nf}$ as output by \kbd{nfinit} and either a polynomial $x$ with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, or a pseudo-basis $x$ of such an extension as output for example by \kbd{rnfpseudobasis}, computes another pseudo-basis $(A,I)$ (not in HNF in general) such that all the ideals of $I$ except perhaps the last one are equal to the ring of integers of $\var{nf}$, and outputs the four-component row vector $[A,I,D,d]$ as in \kbd{rnfpseudobasis}. The name of this function comes from the fact that the ideal class of the last ideal of $I$, which is well defined, is the \idx{Steinitz class} of the $\Z_K$-module $\Z_L$ (its image in $SK_0(\Z_K)$). pari-2.7.5/src/functions/number_fields/rnfidealdown0000644000175000017500000000074212366172547021142 0ustar billbillFunction: rnfidealdown Section: number_fields C-Name: rnfidealdown Prototype: GG Help: rnfidealdown(rnf,x): finds the intersection of the ideal x with the base field. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an ideal of $L$, given either in relative form or by a $\Z$-basis of elements of $L$ (see \secref{se:rnfidealabstorel}). This function returns the ideal of $K$ below $x$, i.e.~the intersection of $x$ with $K$. pari-2.7.5/src/functions/number_fields/bnrdisc0000644000175000017500000000266011636712103020076 0ustar billbillFunction: bnrdisc Section: number_fields C-Name: bnrdisc0 Prototype: GDGDGD0,L, Help: 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. Doc: $A$, $B$, $C$ defining a class field $L$ over a ground field $K$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, \kbd{[\var{bnf}, \var{modulus}]} or \kbd{[\var{bnf}, \var{modulus}, \var{subgroup}]}, \secref{se:CFT}), outputs data $[N,r_1,D]$ giving the discriminant and signature of $L$, depending on the binary digits of \fl: \item 1: if this bit is unset, output absolute data related to $L/\Q$: $N$ is the absolute degree $[L:\Q]$, $r_1$ the number of real places of $L$, and $D$ the discriminant of $L/\Q$. Otherwise, output relative data for $L/K$: $N$ is the relative degree $[L:K]$, $r_1$ is the number of real places of $K$ unramified in $L$ (so that the number of real places of $L$ is equal to $r_1$ times $N$), and $D$ is the relative discriminant ideal of $L/K$. \item 2: if this bit is set and if the modulus is not the conductor of $L$, only return 0. pari-2.7.5/src/functions/number_fields/nfisincl0000644000175000017500000000172411636712103020257 0ustar billbillFunction: nfisincl Section: number_fields C-Name: nfisincl Prototype: GG Help: 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. Doc: tests whether the number field $K$ defined by the polynomial $x$ is conjugate to a subfield of the field $L$ defined by $y$ (where $x$ and $y$ must be in $\Q[X]$). If they are not, the output is the number 0. If they are, the output is a vector of polynomials, each polynomial $a$ representing an embedding of $K$ into $L$, i.e.~being such that $y\mid x\circ a$. If $y$ is a number field (\var{nf}), a much faster algorithm is used (factoring $x$ over $y$ using \tet{nffactor}). Before version 2.0.14, this wasn't guaranteed to return all the embeddings, hence was triggered by a special flag. This is no more the case. pari-2.7.5/src/functions/number_fields/nfeltdiv0000644000175000017500000000033711636712103020264 0ustar billbillFunction: nfeltdiv Section: number_fields C-Name: nfdiv Prototype: GGG Help: nfdiv(nf,x,y): element x/y in nf. Doc: given two elements $x$ and $y$ in \var{nf}, computes their quotient $x/y$ in the number field $\var{nf}$. pari-2.7.5/src/functions/number_fields/factornf0000644000175000017500000000245111636712103020252 0ustar billbillFunction: factornf Section: number_fields C-Name: polfnf Prototype: GG Help: factornf(x,t): factorization of the polynomial x over the number field defined by the polynomial t. Doc: factorization of the univariate polynomial $x$ over the number field defined by the (univariate) polynomial $t$. $x$ may have coefficients in $\Q$ or in the number field. The algorithm reduces to factorization over $\Q$ (\idx{Trager}'s trick). The direct approach of \tet{nffactor}, which uses \idx{van Hoeij}'s method in a relative setting, is in general faster. The main variable of $t$ must be of \emph{lower} priority than that of $x$ (see \secref{se:priority}). However if non-rational number field elements occur (as polmods or polynomials) as coefficients of $x$, the variable of these polmods \emph{must} be the same as the main variable of $t$. For example \bprog ? factornf(x^2 + Mod(y, y^2+1), y^2+1); ? factornf(x^2 + y, y^2+1); \\@com these two are OK ? factornf(x^2 + Mod(z,z^2+1), y^2+1) *** at top-level: factornf(x^2+Mod(z,z *** ^-------------------- *** factornf: inconsistent data in rnf function. ? factornf(x^2 + z, y^2+1) *** at top-level: factornf(x^2+z,y^2+1 *** ^-------------------- *** factornf: incorrect variable in rnf function. @eprog pari-2.7.5/src/functions/number_fields/idealhnf0000644000175000017500000000403712314242551020223 0ustar billbillFunction: idealhnf Section: number_fields C-Name: idealhnf0 Prototype: GGDG Help: 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. Doc: gives the \idx{Hermite normal form} of the ideal $u\Z_K+v\Z_K$, where $u$ and $v$ are elements of the number field $K$ defined by \kbd{nf}. \bprog ? nf = nfinit(y^3 - 2); ? idealhnf(nf, 2, y+1) %2 = [1 0 0] [0 1 0] [0 0 1] ? idealhnf(nf, y/2, [0,0,1/3]~) %3 = [1/3 0 0] [0 1/6 0] [0 0 1/6] @eprog If $b$ is omitted, returns the HNF of the ideal defined by $u$: $u$ may be an algebraic number (defining a principal ideal), a maximal ideal (as given by \kbd{idealprimedec} or \kbd{idealfactor}), or a matrix whose columns give generators for the ideal. This last format is a little complicated, but useful to reduce general modules to the canonical form once in a while: \item if strictly less than $N = [K:\Q]$ generators are given, $u$ is the $\Z_K$-module they generate, \item if $N$ or more are given, it is \emph{assumed} that they form a $\Z$-basis of the ideal, in particular that the matrix has maximal rank $N$. This acts as \kbd{mathnf} since the $\Z_K$-module structure is (taken for granted hence) not taken into account in this case. \bprog ? idealhnf(nf, idealprimedec(nf,2)[1]) %4 = [2 0 0] [0 1 0] [0 0 1] ? idealhnf(nf, [1,2;2,3;3,4]) %5 = [1 0 0] [0 1 0] [0 0 1] @eprog\noindent Finally, when $K$ is quadratic with discriminant $D_K$, we allow $u =$ \kbd{Qfb(a,b,c)}, provided $b^2 - 4ac = D_K$. As usual, this represents the ideal $a \Z + (1/2)(-b + \sqrt{D_K}) \Z$. \bprog ? K = nfinit(x^2 - 60); K.disc %1 = 60 ? idealhnf(K, qfbprimeform(60,2)) %2 = [2 1] [0 1] ? idealhnf(K, Qfb(1,2,3)) *** at top-level: idealhnf(K,Qfb(1,2,3 *** ^-------------------- *** idealhnf: Qfb(1, 2, 3) has discriminant != 60 in idealhnf. @eprog Variant: Also available is \fun{GEN}{idealhnf}{GEN nf, GEN a}. pari-2.7.5/src/functions/number_fields/galoispermtopol0000644000175000017500000000154511636712103021673 0ustar billbillFunction: galoispermtopol Section: number_fields C-Name: galoispermtopol Prototype: GG Help: 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. Doc: \var{gal} being a Galois group as output by \kbd{galoisinit} and \var{perm} a element of $\var{gal}.group$, return the polynomial defining the Galois automorphism, as output by \kbd{nfgaloisconj}, associated with the permutation \var{perm} of the roots $\var{gal}.roots$. \var{perm} can also be a vector or matrix, in this case, \kbd{galoispermtopol} is applied to all components recursively. \noindent Note that \bprog G = galoisinit(pol); galoispermtopol(G, G[6])~ @eprog\noindent is equivalent to \kbd{nfgaloisconj(pol)}, if degree of \var{pol} is greater or equal to $2$. pari-2.7.5/src/functions/number_fields/rnfdisc0000644000175000017500000000141311636712103020075 0ustar billbillFunction: rnfdisc Section: number_fields C-Name: rnfdiscf Prototype: GG Help: 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. Doc: given a number field $\var{nf}$ as output by \kbd{nfinit} and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes the relative discriminant of $L$. This is a two-element row vector $[D,d]$, where $D$ is the relative ideal discriminant and $d$ is the relative discriminant considered as an element of $\var{nf}^*/{\var{nf}^*}^2$. The main variable of $\var{nf}$ \emph{must} be of lower priority than that of \var{pol}, see \secref{se:priority}. pari-2.7.5/src/functions/number_fields/nfeltmulmodpr0000644000175000017500000000101111636712103021327 0ustar billbillFunction: nfeltmulmodpr Section: number_fields C-Name: nfmulmodpr Prototype: GGGG Help: nfeltmulmodpr(nf,x,y,pr): element x.y modulo pr in nf, where pr is in modpr format (see nfmodprinit). Doc: given two elements $x$ and $y$ in \var{nf} and \var{pr} a prime ideal in \kbd{modpr} format (see \tet{nfmodprinit}), computes their product $x*y$ modulo the prime ideal \var{pr}. Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. pari-2.7.5/src/functions/number_fields/nfeltpowmodpr0000644000175000017500000000100011636712103021335 0ustar billbillFunction: nfeltpowmodpr Section: number_fields C-Name: nfpowmodpr Prototype: GGGG Help: nfeltpowmodpr(nf,x,k,pr): element x^k modulo pr in nf, where pr is in modpr format (see nfmodprinit). Doc: given an element $x$ in \var{nf}, an integer $k$ and a prime ideal \var{pr} in \kbd{modpr} format (see \tet{nfmodprinit}), computes $x^k$ modulo the prime ideal \var{pr}. Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. pari-2.7.5/src/functions/number_fields/idealfactor0000644000175000017500000000070611636712103020726 0ustar billbillFunction: idealfactor Section: number_fields C-Name: idealfactor Prototype: GG Help: idealfactor(nf,x): factorization of the ideal x given in HNF into prime ideals in the number field nf. Doc: factors into prime ideal powers the ideal $x$ in the number field $\var{nf}$. The output format is similar to the \kbd{factor} function, and the prime ideals are represented in the form output by the \kbd{idealprimedec} function, i.e.~as 5-element vectors. pari-2.7.5/src/functions/number_fields/rnfconductor0000644000175000017500000000210112314242551021145 0ustar billbillFunction: rnfconductor Section: number_fields C-Name: rnfconductor Prototype: GG Help: 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]. Doc: given $\var{bnf}$ as output by \kbd{bnfinit}, and \var{pol} a relative polynomial defining an \idx{Abelian extension}, computes the class field theory conductor of this Abelian extension. The result is a 3-component vector $[\var{conductor},\var{rayclgp},\var{subgroup}]$, where \var{conductor} is the conductor of the extension given as a 2-component row vector $[f_0,f_\infty]$, \var{rayclgp} is the full ray class group corresponding to the conductor given as a 3-component vector [h,cyc,gen] as usual for a group, and \var{subgroup} is a matrix in HNF defining the subgroup of the ray class group on the given generators gen. pari-2.7.5/src/functions/number_fields/galoisgetpol0000644000175000017500000000275612366172547021166 0ustar billbillFunction: galoisgetpol Section: number_fields C-Name: galoisgetpol Prototype: LD0,L,D1,L, Description: (small):int galoisnbpol($1) (small,):int galoisnbpol($1) (small,,):int galoisnbpol($1) (small,small,small):vec galoisgetpol($1, $2 ,$3) Help: 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. Doc: 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 [\kbd{pol}, \kbd{den}] where \item \kbd{pol} is the polynomial of degree $a$ \item \kbd{den} is the denominator of \kbd{nfgaloisconj(pol)}. Pass it as an optional argument to \tet{galoisinit} or \tet{nfgaloisconj} to speed them up: \bprog ? [pol,den] = galoisgetpol(64,4,1); ? G = galoisinit(pol); time = 352ms ? galoisinit(pol, den); \\ passing 'den' speeds up the computation time = 264ms ? % == %` %4 = 1 \\ same answer @eprog If $b$ and $s$ are omitted, return the number of isomorphism classes of groups of order $a$. Variant: Also available is \fun{GEN}{galoisnbpol}{long a} when $b$ and $s$ are omitted. pari-2.7.5/src/functions/number_fields/ideallist0000644000175000017500000000413011636712103020416 0ustar billbillFunction: ideallist Section: number_fields C-Name: ideallist0 Prototype: GLD4,L, Help: 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. Doc: computes the list of all ideals of norm less or equal to \var{bound} in the number field \var{nf}. The result is a row vector with exactly \var{bound} components. Each component is itself a row vector containing the information about ideals of a given norm, in no specific order, depending on the value of $\fl$: The possible values of $\fl$ are: \quad 0: give the \var{bid} associated to the ideals, without generators. \quad 1: as 0, but include the generators in the \var{bid}. \quad 2: in this case, \var{nf} must be a \var{bnf} with units. Each component is of the form $[\var{bid},U]$, where \var{bid} is as case 0 and $U$ is a vector of discrete logarithms of the units. More precisely, it gives the \kbd{ideallog}s with respect to \var{bid} of \kbd{bnf.tufu}. This structure is technical, and only meant to be used in conjunction with \tet{bnrclassnolist} or \tet{bnrdisclist}. \quad 3: as 2, but include the generators in the \var{bid}. \quad 4: give only the HNF of the ideal. \bprog ? nf = nfinit(x^2+1); ? L = ideallist(nf, 100); ? L[1] %3 = [[1, 0; 0, 1]] \\@com A single ideal of norm 1 ? #L[65] %4 = 4 \\@com There are 4 ideals of norm 4 in $\Z[i]$ @eprog If one wants more information, one could do instead: \bprog ? nf = nfinit(x^2+1); ? L = ideallist(nf, 100, 0); ? l = L[25]; vector(#l, i, l[i].clgp) %3 = [[20, [20]], [16, [4, 4]], [20, [20]]] ? l[1].mod %4 = [[25, 18; 0, 1], []] ? l[2].mod %5 = [[5, 0; 0, 5], []] ? l[3].mod %6 = [[25, 7; 0, 1], []] @eprog\noindent where we ask for the structures of the $(\Z[i]/I)^*$ for all three ideals of norm $25$. In fact, for all moduli with finite part of norm $25$ and trivial Archimedean part, as the last 3 commands show. See \tet{ideallistarch} to treat general moduli. pari-2.7.5/src/functions/number_fields/idealpow0000644000175000017500000000160411636712103020253 0ustar billbillFunction: idealpow Section: number_fields C-Name: idealpow0 Prototype: GGGD0,L, Help: 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. Doc: computes the $k$-th power of the ideal $x$ in the number field $\var{nf}$; $k\in\Z$. If $x$ is an extended ideal\sidx{ideal (extended)}, its principal part is suitably updated: i.e. raising $[I,t]$ to the $k$-th power, yields $[I^k, t^k]$. If $\fl$ is non-zero, reduce the result using \kbd{idealred}, \emph{throughout the (binary) powering process}; in particular, this is \emph{not} the same as as $\kbd{idealpow}(\var{nf},x,k)$ followed by reduction. Variant: \noindent See also \fun{GEN}{idealpow}{GEN nf, GEN x, GEN k} and \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}. pari-2.7.5/src/functions/number_fields/nfdisc0000644000175000017500000000301212405547147017721 0ustar billbillFunction: nfdisc Section: number_fields C-Name: nfdisc_gp Prototype: GDGDG 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. Doc: \idx{field discriminant} of the number field defined by the integral, preferably monic, irreducible polynomial $T(X)$. Returns the discriminant of the number field $\Q[X]/(T)$, using the Round $4$ algorithm. \misctitle{Local discriminants, valuations at certain primes} As in \kbd{nfbasis}, the argument $T$ can be replaced by $[T,\var{listP}]$, where \kbd{listP} is as in \kbd{nfbasis}: a vector of pairwise coprime integers (usually distinct primes), a factorization matrix, or a single integer. In that case, the function returns the discriminant of an order whose basis is given by \kbd{nfbasis(T,listP)}, which need not be the maximal order, and whose valuation at a prime entry in \kbd{listP} is the same as the valuation of the field discriminant. In particular, if \kbd{listP} is $[p]$ for a prime $p$, we can return the $p$-adic discriminant of the maximal order of $\Z_p[X]/(T)$, as a power of $p$, as follows: \bprog ? padicdisc(T,p) = p^valuation(nfdisc(T,[p]), p); ? nfdisc(x^2 + 6) %1 = -24 ? padicdisc(x^2 + 6, 2) %2 = 8 ? padicdisc(x^2 + 6, 3) %3 = 3 @eprog \synt{nfdisc}{GEN T} (\kbd{listP = NULL}). Also available is \fun{GEN}{nfbasis}{GEN T, GEN *d, GEN listP = NULL}, which returns the order basis, and where \kbd{*d} receives the order discriminant. pari-2.7.5/src/functions/number_fields/idealstar0000644000175000017500000000422612366172547020437 0ustar billbillFunction: idealstar Section: number_fields C-Name: idealstar0 Prototype: GGD1,L, Help: 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. Doc: outputs a \var{bid} structure, necessary for computing in the finite abelian group $G = (\Z_K/I)^*$. Here, \var{nf} is a number field and $I$ is a \var{modulus}: either an ideal in any form, or a row vector whose first component is an ideal and whose second component is a row vector of $r_1$ 0 or 1. Ideals can also be given by a factorization into prime ideals, as produced by \tet{idealfactor}. This \var{bid} is used in \tet{ideallog} to compute discrete logarithms. It also contains useful information which can be conveniently retrieved as \kbd{\var{bid}.mod} (the modulus), \kbd{\var{bid}.clgp} ($G$ as a finite abelian group), \kbd{\var{bid}.no} (the cardinality of $G$), \kbd{\var{bid}.cyc} (elementary divisors) and \kbd{\var{bid}.gen} (generators). If $\fl=1$ (default), the result is a \var{bid} structure without generators. If $\fl=2$, as $\fl=1$, but including generators, which wastes some time. If $\fl=0$, only outputs $(\Z_K/I)^*$ as an abelian group, i.e as a 3-component vector $[h,d,g]$: $h$ is the order, $d$ is the vector of SNF\sidx{Smith normal form} cyclic components and $g$ the corresponding generators. Variant: Instead the above hardcoded numerical flags, one should rather use \fun{GEN}{Idealstar}{GEN nf, GEN ideal, long flag}, where \kbd{flag} is an or-ed combination of \tet{nf_GEN} (include generators) and \tet{nf_INIT} (return a full \kbd{bid}, not a group), possibly $0$. This offers one more combination: gen, but no init. pari-2.7.5/src/functions/number_fields/nfbasistoalg0000644000175000017500000000107111636712103021121 0ustar billbillFunction: nfbasistoalg Section: number_fields C-Name: basistoalg Prototype: GG Help: nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number. Doc: Given an algebraic number $x$ in the number field \kbd{nf}, transforms it into \typ{POLMOD} form. \bprog ? nf = nfinit(y^2 + 4); ? nf.zk %2 = [1, 1/2*y] ? nfbasistoalg(nf, [1,1]~) %3 = Mod(1/2*y + 1, y^2 + 4) ? nfbasistoalg(nf, y) %4 = Mod(y, y^2 + 4) ? nfbasistoalg(nf, Mod(y, y^2+4)) %4 = Mod(y, y^2 + 4) @eprog This is the inverse function of \kbd{nfalgtobasis}. pari-2.7.5/src/functions/number_fields/bnfisnorm0000644000175000017500000000276012314242551020447 0ustar billbillFunction: bnfisnorm Section: number_fields C-Name: bnfisnorm Prototype: GGD1,L, Help: 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 flag if flag>0. The answer is guaranteed (i.e x norm iff b=1) under GRH, if S contains all primes less than 12.log(disc(Bnf))^2, where Bnf is the Galois closure of bnf. Doc: tries to tell whether the rational number $x$ is the norm of some element y in $\var{bnf}$. Returns a vector $[a,b]$ where $x=Norm(a)*b$. Looks for a solution which is an $S$-unit, with $S$ a certain set of prime ideals containing (among others) all primes dividing $x$. If $\var{bnf}$ is known to be \idx{Galois}, set $\fl=0$ (in this case, $x$ is a norm iff $b=1$). If $\fl$ is non zero the program adds to $S$ the following prime ideals, depending on the sign of $\fl$. If $\fl>0$, the ideals of norm less than $\fl$. And if $\fl<0$ the ideals dividing $\fl$. Assuming \idx{GRH}, the answer is guaranteed (i.e.~$x$ is a norm iff $b=1$), if $S$ contains all primes less than $12\log(\disc(\var{Bnf}))^2$, where $\var{Bnf}$ is the Galois closure of $\var{bnf}$. See also \tet{bnfisintnorm}. pari-2.7.5/src/functions/number_fields/rnfbasis0000644000175000017500000000141211636712103020253 0ustar billbillFunction: rnfbasis Section: number_fields C-Name: rnfbasis Prototype: GG Help: 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. Doc: let $K$ the field represented by \var{bnf}, as output by \kbd{bnfinit}. $M$ is a projective $\Z_K$-module of rank $n$ ($M\otimes K$ is an $n$-dimensional $K$-vector space), given by a pseudo-basis of size $n$. The routine returns either a true $\Z_K$-basis of $M$ (of size $n$) if it exists, or an $n+1$-element generating set of $M$ if not. It is allowed to use an irreducible polynomial $P$ in $K[X]$ instead of $M$, in which case, $M$ is defined as the ring of integers of $K[X]/(P)$, viewed as a $\Z_K$-module. pari-2.7.5/src/functions/number_fields/bnfisprincipal0000644000175000017500000000527511636712103021462 0ustar billbillFunction: bnfisprincipal Section: number_fields C-Name: bnfisprincipal0 Prototype: GGD1,L, Help: 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). Doc: $\var{bnf}$ being the \sidx{principal ideal} number field data output by \kbd{bnfinit}, and $x$ being an ideal, this function tests whether the ideal is principal or not. The result is more complete than a simple true/false answer and solves general discrete logarithm problem. Assume the class group is $\oplus (\Z/d_i\Z)g_i$ (where the generators $g_i$ and their orders $d_i$ are respectively given by \kbd{bnf.gen} and \kbd{bnf.cyc}). The routine returns a row vector $[e,t]$, where $e$ is a vector of exponents $0 \leq e_i < d_i$, and $t$ is a number field element such that $$ x = (t) \prod_i g_i^{e_i}.$$ For \emph{given} $g_i$ (i.e. for a given \kbd{bnf}), the $e_i$ are unique, and $t$ is unique modulo units. In particular, $x$ is principal if and only if $e$ is the zero vector. Note that the empty vector, which is returned when the class number is $1$, is considered to be a zero vector (of dimension $0$). \bprog ? K = bnfinit(y^2+23); ? K.cyc %2 = [3] ? K.gen %3 = [[2, 0; 0, 1]] \\ a prime ideal above 2 ? P = idealprimedec(K,3)[1]; \\ a prime ideal above 3 ? v = bnfisprincipal(K, P) %5 = [[2]~, [3/4, 1/4]~] ? idealmul(K, v[2], idealfactorback(K, K.gen, v[1])) %6 = [3 0] [0 1] ? % == idealhnf(K, P) %7 = 1 @eprog \noindent The binary digits of \fl mean: \item $1$: If set, outputs $[e,t]$ as explained above, otherwise returns only $e$, which is much easier to compute. The following idiom only tests whether an ideal is principal: \bprog is_principal(bnf, x) = !bnfisprincipal(bnf,x,0); @eprog \item $2$: It may not be possible to recover $t$, given the initial accuracy to which \kbd{bnf} was computed. In that case, a warning is printed and $t$ is set equal to the empty vector \kbd{[]\til}. If this bit is set, increase the precision and recompute needed quantities until $t$ can be computed. Warning: setting this may induce \emph{very} lengthy computations. Variant: Instead of the above hardcoded numerical flags, one should rather use an or-ed combination of the symbolic flags \tet{nf_GEN} (include generators, possibly a place holder if too difficult) and \tet{nf_FORCE} (insist on finding the generators). pari-2.7.5/src/functions/number_fields/ideallistarch0000644000175000017500000000332211636712103021256 0ustar billbillFunction: ideallistarch Section: number_fields C-Name: ideallistarch Prototype: GGG Help: 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. Doc: \var{list} is a vector of vectors of bid's, as output by \tet{ideallist} with flag $0$ to $3$. Return a vector of vectors with the same number of components as the original \var{list}. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now \var{arch} (it was originally trivial). The information contained is of the same kind as was present in the input; see \tet{ideallist}, in particular the meaning of \fl. \bprog ? bnf = bnfinit(x^2-2); ? bnf.sign %2 = [2, 0] \\@com two places at infinity ? L = ideallist(bnf, 100, 0); ? l = L[98]; vector(#l, i, l[i].clgp) %4 = [[42, [42]], [36, [6, 6]], [42, [42]]] ? La = ideallistarch(bnf, L, [1,1]); \\@com add them to the modulus ? l = La[98]; vector(#l, i, l[i].clgp) %6 = [[168, [42, 2, 2]], [144, [6, 6, 2, 2]], [168, [42, 2, 2]]] @eprog Of course, the results above are obvious: adding $t$ places at infinity will add $t$ copies of $\Z/2\Z$ to the ray class group. The following application is more typical: \bprog ? L = ideallist(bnf, 100, 2); \\@com units are required now ? La = ideallistarch(bnf, L, [1,1]); ? H = bnrclassnolist(bnf, La); ? H[98]; %6 = [2, 12, 2] @eprog pari-2.7.5/src/functions/number_fields/bnrL10000644000175000017500000000551212314242551017426 0ustar billbillFunction: bnrL1 Section: number_fields C-Name: bnrL1 Prototype: GDGD0,L,p Help: 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, or if 1 then compute the value at s = 1 (and in this case, only for non-trivial characters), 2: if 0 then compute the value of the primitive L-function associated to chi, if 1 then compute the value of the L-function L_S(s, chi) where S is the set of places dividing the modulus of bnr (and the infinite places), 3: return also the characters. Doc: let \var{bnr} be the number field data output by \kbd{bnrinit(,,1)} and \var{H} be a square matrix defining a congruence subgroup of the ray class group corresponding to \var{bnr} (the trivial congruence subgroup if omitted). This function returns, for each \idx{character} $\chi$ of the ray class group which is trivial on $H$, the value at $s = 1$ (or $s = 0$) of the abelian $L$-function associated to $\chi$. For the value at $s = 0$, the function returns in fact for each $\chi$ a vector $[r_\chi, c_\chi]$ where $$L(s, \chi) = c \cdot s^r + O(s^{r + 1})$$ \noindent near $0$. The argument \fl\ is optional, its binary digits mean 1: compute at $s = 0$ if unset or $s = 1$ if set, 2: compute the primitive $L$-function associated to $\chi$ if unset or the $L$-function with Euler factors at prime ideals dividing the modulus of \var{bnr} removed if set (that is $L_S(s, \chi)$, where $S$ is the set of infinite places of the number field together with the finite prime ideals dividing the modulus of \var{bnr}), 3: return also the character if set. \bprog K = bnfinit(x^2-229); bnr = bnrinit(K,1,1); bnrL1(bnr) @eprog\noindent returns the order and the first non-zero term of $L(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K = \Q(\sqrt{229})$. Then \bprog bnr2 = bnrinit(K,2,1); bnrL1(bnr2,,2) @eprog\noindent returns the order and the first non-zero terms of $L_S(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K$ and $S$ is the set of infinite places of $K$ together with the finite prime $2$. Note that the ray class group modulo $2$ is in fact the class group, so \kbd{bnrL1(bnr2,0)} returns the same answer as \kbd{bnrL1(bnr,0)}. This function will fail with the message \bprog *** bnrL1: overflow in zeta_get_N0 [need too many primes]. @eprog\noindent if the approximate functional equation requires us to sum too many terms (if the discriminant of $K$ is too large). pari-2.7.5/src/functions/number_fields/nfrootsof10000644000175000017500000000306311636712103020550 0ustar billbillFunction: nfrootsof1 Section: number_fields C-Name: rootsof1 Prototype: G Help: nfrootsof1(nf): number of roots of unity and primitive root of unity in the number field nf. Doc: Returns a two-component vector $[w,z]$ where $w$ is the number of roots of unity in the number field \var{nf}, and $z$ is a primitive $w$-th root of unity. \bprog ? K = nfinit(polcyclo(11)); ? nfrootsof1(K) %2 = [22, [0, 0, 0, 0, 0, -1, 0, 0, 0, 0]~] ? z = nfbasistoalg(K, %[2]) \\ in algebraic form %3 = Mod(-x^5, x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) ? [lift(z^11), lift(z^2)] \\ proves that the order of z is 22 %4 = [-1, -x^9 - x^8 - x^7 - x^6 - x^5 - x^4 - x^3 - x^2 - x - 1] @eprog This function guesses the number $w$ as the gcd of the $\#k(v)^*$ for unramified $v$ above odd primes, then computes the roots in \var{nf} of the $w$-th cyclotomic polynomial: the algorithm is polynomial time with respect to the field degree and the bitsize of the multiplication table in \var{nf} (both of them polynomially bounded in terms of the size of the discriminant). Fields of degree up to $100$ or so should require less than one minute. Variant: Also available is \fun{GEN}{rootsof1_kannan}{GEN nf}, that computes all algebraic integers of $T_2$ norm equal to the field degree (all roots of $1$, by Kronecker's theorem). This is in general a little 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. pari-2.7.5/src/functions/number_fields/rnfeltup0000644000175000017500000000123312366172547020321 0ustar billbillFunction: rnfeltup Section: number_fields C-Name: rnfeltup Prototype: GG Help: rnfeltup(rnf,x): expresses x (belonging to the base field) on the relative field. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $K$, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltup(L, Mod(y, K.pol)) %4 = Mod(x^2, x^4 + 1) ? rnfeltup(L, y) %5 = Mod(x^2, x^4 + 1) ? rnfeltup(L, [1,2]~) \\ in terms of K.zk %6 = Mod(2*x^2 + 1, x^4 + 1) @eprog pari-2.7.5/src/functions/number_fields/nfinit0000644000175000017500000001702612413013143017733 0ustar billbillFunction: nfinit Section: number_fields C-Name: nfinit0 Prototype: GD0,L,p Help: 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. Description: (gen, ?0):nf:prec nfinit0($1, 0, prec) (gen, 1):nf:prec nfinit0($1, 1, prec) (gen, 2):nf:prec nfinit0($1, 2, prec) (gen, 3):gen:prec nfinit0($1, 3, prec) (gen, 4):nf:prec nfinit0($1, 4, prec) (gen, 5):gen:prec nfinit0($1, 5, prec) (gen, #small):void $"incorrect flag in nfinit" (gen, small):gen:prec nfinit0($1, $2, prec) Doc: \var{pol} being a non-constant, preferably monic, irreducible polynomial in $\Z[X]$, initializes a \emph{number field} structure (\kbd{nf}) associated to the field $K$ defined by \var{pol}. As such, it's a technical object passed as the first argument to most \kbd{nf}\var{xxx} functions, but it contains some information which may be directly useful. Access to this information via \emph{member functions} is preferred since the specific data organization specified below may change in the future. Currently, \kbd{nf} is a row vector with 9 components: $\var{nf}[1]$ contains the polynomial \var{pol} (\kbd{\var{nf}.pol}). $\var{nf}[2]$ contains $[r1,r2]$ (\kbd{\var{nf}.sign}, \kbd{\var{nf}.r1}, \kbd{\var{nf}.r2}), the number of real and complex places of $K$. $\var{nf}[3]$ contains the discriminant $d(K)$ (\kbd{\var{nf}.disc}) of $K$. $\var{nf}[4]$ contains the index of $\var{nf}[1]$ (\kbd{\var{nf}.index}), i.e.~$[\Z_K : \Z[\theta]]$, where $\theta$ is any root of $\var{nf}[1]$. $\var{nf}[5]$ is a vector containing 7 matrices $M$, $G$, \var{roundG}, $T$, $MD$, $TI$, $MDI$ useful for certain computations in the number field $K$. \quad\item $M$ is the $(r1+r2)\times n$ matrix whose columns represent the numerical values of the conjugates of the elements of the integral basis. \quad\item $G$ is an $n\times n$ matrix such that $T2 = {}^t G G$, where $T2$ is the quadratic form $T_2(x) = \sum |\sigma(x)|^2$, $\sigma$ running over the embeddings of $K$ into $\C$. \quad\item \var{roundG} is a rescaled copy of $G$, rounded to nearest integers. \quad\item $T$ is the $n\times n$ matrix whose coefficients are $\text{Tr}(\omega_i\omega_j)$ where the $\omega_i$ are the elements of the integral basis. Note also that $\det(T)$ is equal to the discriminant of the field $K$. Also, when understood as an ideal, the matrix $T^{-1}$ generates the codifferent ideal. \quad\item The columns of $MD$ (\kbd{\var{nf}.diff}) express a $\Z$-basis of the different of $K$ on the integral basis. \quad\item $TI$ is equal to the primitive part of $T^{-1}$, which has integral coefficients. \quad\item Finally, $MDI$ is a two-element representation (for faster ideal product) of $d(K)$ times the codifferent ideal (\kbd{\var{nf}.disc$*$\var{nf}.codiff}, which is an integral ideal). $MDI$ is only used in \tet{idealinv}. $\var{nf}[6]$ is the vector containing the $r1+r2$ roots (\kbd{\var{nf}.roots}) of $\var{nf}[1]$ corresponding to the $r1+r2$ embeddings of the number field into $\C$ (the first $r1$ components are real, the next $r2$ have positive imaginary part). $\var{nf}[7]$ is an integral basis for $\Z_K$ (\kbd{\var{nf}.zk}) expressed on the powers of~$\theta$. Its first element is guaranteed to be $1$. This basis is LLL-reduced with respect to $T_2$ (strictly speaking, it is a permutation of such a basis, due to the condition that the first element be $1$). $\var{nf}[8]$ is the $n\times n$ integral matrix expressing the power basis in terms of the integral basis, and finally $\var{nf}[9]$ is the $n\times n^2$ matrix giving the multiplication table 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. \bprog ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12) ? nf.pol \\ defining polynomial %2 = x^3 - 12 ? nf.disc \\ field discriminant %3 = -972 ? nf.index \\ index of power basis order in maximal order %4 = 2 ? nf.zk \\ integer basis, lifted to Q[X] %5 = [1, x, 1/2*x^2] ? nf.sign \\ signature %6 = [1, 1] ? factor(abs(nf.disc )) \\ determines ramified primes %7 = [2 2] [3 5] ? idealfactor(nf, 2) %8 = [[2, [0, 0, -1]~, 3, 1, [0, 1, 0]~] 3] \\ @com $\goth{p}_2^3$ @eprog \misctitle{Huge discriminants, helping nfdisc} In case \var{pol} has a huge discriminant which is difficult to factor, it is hard to compute from scratch the maximal order. The special input format $[\var{pol}, B]$ is also accepted where \var{pol} is a polynomial as above and $B$ has one of the following forms \item an integer basis, as would be computed by \tet{nfbasis}: a vector of polynomials with first element $1$. This is useful if the maximal order is known in advance. \item an argument \kbd{listP} which specifies a list of primes (see \tet{nfbasis}). Instead of the maximal order, \kbd{nfinit} then computes an order which is maximal at these particular primes as well as the primes contained in the private prime table (see \tet{addprimes}). The result is unconditionaly correct when the discriminant \kbd{nf.disc} factors completely over this set of primes. The function \tet{nfcertify} automates this: \bprog ? pol = polcompositum(x^5 - 101, polcyclo(7))[1]; ? nf = nfinit( [pol, 10^3] ); ? nfcertify(nf) %3 = [] @eprog\noindent A priori, \kbd{nf.zk} defines an order which is only known to be maximal at all primes $\leq 10^3$ (no prime $\leq 10^3$ divides \kbd{nf.index}). The certification step proves the correctness of the computation. \medskip If $\fl=2$: \var{pol} is changed into another polynomial $P$ defining the same number field, which is as simple as can easily be found using the \tet{polredbest} algorithm, and all the subsequent computations are done using this new polynomial. In particular, the first component of the result is the modified polynomial. If $\fl=3$, apply \kbd{polredbest} as in case 2, but outputs $[\var{nf},\kbd{Mod}(a,P)]$, where $\var{nf}$ is as before and $\kbd{Mod}(a,P)=\kbd{Mod}(x,\var{pol})$ gives the change of variables. This is implicit when \var{pol} is not monic: first a linear change of variables is performed, to get a monic polynomial, then \kbd{polredbest}. Variant: Also available are \fun{GEN}{nfinit}{GEN x, long prec} ($\fl = 0$), \fun{GEN}{nfinitred}{GEN x, long prec} ($\fl = 2$), \fun{GEN}{nfinitred2}{GEN x, long prec} ($\fl = 3$). Instead of the above hardcoded numerical flags in \kbd{nfinit0}, one should rather use \fun{GEN}{nfinitall}{GEN x, long flag, long prec}, where \fl\ is an or-ed combination of \item \tet{nf_RED}: find a simpler defining polynomial, \item \tet{nf_ORIG}: if \tet{nf_RED} set, also return the change of variable, \item \tet{nf_ROUND2}: \emph{Deprecated}. Slow down the routine by using an obsolete normalization algorithm (do not use this one!), \item \tet{nf_PARTIALFACT}: \emph{Deprecated}. Lazy factorization of the polynomial discriminant. Result is conditional unless \kbd{nfcertify} can certify it. pari-2.7.5/src/functions/number_fields/matbasistoalg0000644000175000017500000000051211636712103021276 0ustar billbillFunction: matbasistoalg Section: number_fields C-Name: matbasistoalg Prototype: GG Help: matbasistoalg(nf,x): nfbasistoalg applied to every element of the matrix or vector x. Doc: $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a (row or column) vector or matrix, apply \tet{nfbasistoalg} to each entry of $x$. pari-2.7.5/src/functions/number_fields/subgrouplist0000644000175000017500000000374511636712103021221 0ustar billbillFunction: subgrouplist Section: number_fields C-Name: subgrouplist0 Prototype: GDGD0,L, Help: 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. Doc: \var{bnr} being as output by \kbd{bnrinit} or a list of cyclic components of a finite Abelian group $G$, outputs the list of subgroups of $G$. Subgroups are given as HNF left divisors of the SNF matrix corresponding to $G$. If $\fl=0$ (default) and \var{bnr} is as output by \kbd{bnrinit}, gives only the subgroups whose modulus is the conductor. Otherwise, the modulus is not taken into account. If \var{bound} is present, and is a positive integer, restrict the output to subgroups of index less than \var{bound}. If \var{bound} is a vector containing a single positive integer $B$, then only subgroups of index exactly equal to $B$ are computed. For instance \bprog ? subgrouplist([6,2]) %1 = [[6, 0; 0, 2], [2, 0; 0, 2], [6, 3; 0, 1], [2, 1; 0, 1], [3, 0; 0, 2], [1, 0; 0, 2], [6, 0; 0, 1], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]] ? subgrouplist([6,2],3) \\@com index less than 3 %2 = [[2, 1; 0, 1], [1, 0; 0, 2], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]] ? subgrouplist([6,2],[3]) \\@com index 3 %3 = [[3, 0; 0, 1]] ? bnr = bnrinit(bnfinit(x), [120,[1]], 1); ? L = subgrouplist(bnr, [8]); @eprog\noindent In the last example, $L$ corresponds to the 24 subfields of $\Q(\zeta_{120})$, of degree $8$ and conductor $120\infty$ (by setting \fl, we see there are a total of $43$ subgroups of degree $8$). \bprog ? vector(#L, i, galoissubcyclo(bnr, L[i])) @eprog\noindent will produce their equations. (For a general base field, you would have to rely on \tet{bnrstark}, or \tet{rnfkummer}.) pari-2.7.5/src/functions/number_fields/rnfisabelian0000644000175000017500000000067011636712103021106 0ustar billbillFunction: rnfisabelian Section: number_fields C-Name: rnfisabelian Prototype: lGG Help: rnfisabelian(nf,T): T being a relative polynomial with coefficients in nf, return 1 if it defines an abelian extension, and 0 otherwise. Doc: $T$ being a relative polynomial with coefficients in \var{nf}, return 1 if it defines an abelian extension, and 0 otherwise. \bprog ? K = nfinit(y^2 + 23); ? rnfisabelian(K, x^3 - 3*x - y) %2 = 1 @eprog pari-2.7.5/src/functions/number_fields/idealappr0000644000175000017500000000241211636712103020406 0ustar billbillFunction: idealappr Section: number_fields C-Name: idealappr0 Prototype: GGD0,L, Help: 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. Doc: if $x$ is a fractional ideal (given in any form), gives an element $\alpha$ in $\var{nf}$ such that for all prime ideals $\goth{p}$ such that the valuation of $x$ at $\goth{p}$ is non-zero, we have $v_{\goth{p}}(\alpha)=v_{\goth{p}}(x)$, and $v_{\goth{p}}(\alpha)\ge0$ for all other $\goth{p}$. If $\fl$ is non-zero, $x$ must be given as a prime ideal factorization, as output by \kbd{idealfactor}, but possibly with zero or negative exponents. This yields an element $\alpha$ such that for all prime ideals $\goth{p}$ occurring in $x$, $v_{\goth{p}}(\alpha)$ is equal to the exponent of $\goth{p}$ in $x$, and for all other prime ideals, $v_{\goth{p}}(\alpha)\ge0$. This generalizes $\kbd{idealappr}(\var{nf},x,0)$ since zero exponents are allowed. Note that the algorithm used is slightly different, so that \bprog idealappr(nf, idealfactor(nf,x)) @eprog\noindent may not be the same as \kbd{idealappr(nf,x,1)}. pari-2.7.5/src/functions/number_fields/poltschirnhaus0000644000175000017500000000072211636712103021515 0ustar billbillFunction: poltschirnhaus Section: number_fields C-Name: tschirnhaus Prototype: G Help: poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x. Doc: applies a random Tschirnhausen transformation to the polynomial $x$, which is assumed to be non-constant and separable, so as to obtain a new equation for the \'etale algebra defined by $x$. This is for instance useful when computing resolvents, hence is used by the \kbd{polgalois} function. pari-2.7.5/src/functions/number_fields/bnrinit0000644000175000017500000000424712366172547020137 0ustar billbillFunction: bnrinit Section: number_fields C-Name: bnrinit0 Prototype: GGD0,L, Help: 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. Description: (gen,gen,?small):bnr bnrinit0($1, $2, $3) Doc: $\var{bnf}$ is as output by \kbd{bnfinit}, $f$ is a modulus, initializes data linked to the ray class group structure corresponding to this module, a so-called \var{bnr} structure. One can input the associated \var{bid} with generators for $f$ instead of the module itself, saving some time. (As in \tet{idealstar}, the finite part of the conductor may be given by a factorization into prime ideals, as produced by \tet{idealfactor}.) The following member functions are available on the result: \kbd{.bnf} is the underlying \var{bnf}, \kbd{.mod} the modulus, \kbd{.bid} the \var{bid} structure associated to the modulus; finally, \kbd{.clgp}, \kbd{.no}, \kbd{.cyc}, \kbd{.gen} refer to the ray class group (as a finite abelian group), its cardinality, its elementary divisors, its generators (only computed if $\fl = 1$). The last group of functions are different from the members of the underlying \var{bnf}, which refer to the class group; use \kbd{\var{bnr}.bnf.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bnf.cyc} to get the cyclic decomposition of the class group. They are also different from the members of the underlying \var{bid}, which refer to $(\Z_K/f)^*$; use \kbd{\var{bnr}.bid.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bid.no} to get $\phi(f)$. If $\fl=0$ (default), the generators of the ray class group are not computed, which saves time. Hence \kbd{\var{bnr}.gen} would produce an error. If $\fl=1$, as the default, except that generators are computed. 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. pari-2.7.5/src/functions/number_fields/bnrisprincipal0000644000175000017500000000243211636712103021466 0ustar billbillFunction: bnrisprincipal Section: number_fields C-Name: bnrisprincipal Prototype: GGD1,L, Help: 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. Doc: \var{bnr} being the number field data which is output by \kbd{bnrinit}$(,,1)$ and $x$ being an ideal in any form, outputs the components of $x$ on the ray class group generators in a way similar to \kbd{bnfisprincipal}. That is a 2-component vector $v$ where $v[1]$ is the vector of components of $x$ on the ray class group generators, $v[2]$ gives on the integral basis an element $\alpha$ such that $x=\alpha\prod_ig_i^{x_i}$. If $\fl=0$, outputs only $v_1$. In that case, \var{bnr} need not contain the ray class group generators, i.e.~it may be created with \kbd{bnrinit}$(,,0)$ If $x$ is not coprime to the modulus of \var{bnr} the result is undefined. Variant: Instead of hardcoded numerical flags, one should rather use \fun{GEN}{isprincipalray}{GEN bnr, GEN x} for $\kbd{flag} = 0$, and if you want generators: \bprog bnrisprincipal(bnr, x, nf_GEN) @eprog pari-2.7.5/src/functions/number_fields/idealchinese0000644000175000017500000000125511636712103021066 0ustar billbillFunction: idealchinese Section: number_fields C-Name: idealchinese Prototype: GGG Help: 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. Doc: $x$ being a prime ideal factorization (i.e.~a 2 by 2 matrix whose first column contains prime ideals, and the second column integral exponents), $y$ a vector of elements in $\var{nf}$ indexed by the ideals in $x$, computes an element $b$ such that $v_{\goth{p}}(b - y_{\goth{p}}) \geq v_{\goth{p}}(x)$ for all prime ideals in $x$ and $v_{\goth{p}}(b)\geq 0$ for all other $\goth{p}$. pari-2.7.5/src/functions/number_fields/nfnewprec0000644000175000017500000000114411636712103020435 0ustar billbillFunction: nfnewprec Section: number_fields C-Name: nfnewprec Prototype: Gp Help: nfnewprec(nf): transform the number field data nf into new data using the current (usually larger) precision. Doc: transforms the number field $\var{nf}$ into the corresponding data using current (usually larger) precision. This function works as expected if $\var{nf}$ is in fact a $\var{bnf}$ (update $\var{bnf}$ to current precision) but may be quite slow (many generators of principal ideals have to be computed). Variant: See also \fun{GEN}{bnfnewprec}{GEN bnf, long prec} and \fun{GEN}{bnrnewprec}{GEN bnr, long prec}. pari-2.7.5/src/functions/number_fields/rnfidealup0000644000175000017500000000162312366172547020616 0ustar billbillFunction: rnfidealup Section: number_fields C-Name: rnfidealup Prototype: GG Help: rnfidealup(rnf,x): lifts the ideal x (of the base field) to the relative field. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be an ideal of $K$. This function returns the ideal $x\Z_L$ as an absolute ideal of $L/\Q$, in the form of a $\Z$-basis, given by a vector of polynomials (modulo \kbd{rnf.pol}). The reason why we do not return the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, then \bprog xabs = rnfidealup(L, x); xLabs = mathnf(matalgtobasis(Labs, xabs)); @eprog\noindent computes a traditional HNF \kbd{xLabs} for $x$ in terms of the fixed $\Z$-basis \kbd{Labs.zk}. pari-2.7.5/src/functions/number_fields/idealmul0000644000175000017500000000237312314242551020246 0ustar billbillFunction: idealmul Section: number_fields C-Name: idealmul0 Prototype: GGGD0,L, Help: 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. Description: (gen, gen, gen, ?0):gen idealmul($1, $2, $3) (gen, gen, gen, 1):gen idealmulred($1, $2, $3) (gen, gen, gen, #small):gen $"invalid flag in idealmul" (gen, gen, gen, small):gen idealmul0($1, $2, $3, $4) Doc: ideal multiplication of the ideals $x$ and $y$ in the number field \var{nf}; the result is the ideal product in HNF. If either $x$ or $y$ are extended ideals\sidx{ideal (extended)}, their principal part is suitably updated: i.e. multiplying $[I,t]$, $[J,u]$ yields $[IJ, tu]$; multiplying $I$ and $[J, u]$ yields $[IJ, u]$. \bprog ? nf = nfinit(x^2 + 1); ? idealmul(nf, 2, x+1) %2 = [4 2] [0 2] ? idealmul(nf, [2, x], x+1) \\ extended ideal * ideal %4 = [[4, 2; 0, 2], x] ? idealmul(nf, [2, x], [x+1, x]) \\ two extended ideals %5 = [[4, 2; 0, 2], [-1, 0]~] @eprog\noindent If $\fl$ is non-zero, reduce the result using \kbd{idealred}. Variant: \noindent See also \fun{GEN}{idealmul}{GEN nf, GEN x, GEN y} ($\fl=0$) and \fun{GEN}{idealmulred}{GEN nf, GEN x, GEN y} ($\fl\neq0$). pari-2.7.5/src/functions/number_fields/dirzetak0000644000175000017500000000053211636712103020263 0ustar billbillFunction: dirzetak Section: number_fields C-Name: dirzetak Prototype: GG Help: dirzetak(nf,b): Dirichlet series of the Dedekind zeta function of the number field nf up to the bound b-1. Doc: gives as a vector the first $b$ coefficients of the \idx{Dedekind} zeta function of the number field $\var{nf}$ considered as a \idx{Dirichlet series}. pari-2.7.5/src/functions/number_fields/polred0000644000175000017500000000331712314242551017736 0ustar billbillFunction: polred Section: number_fields C-Name: polred0 Prototype: GD0,L,DG Help: 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. Doc: This function is \emph{deprecated}, use \tet{polredbest} instead. Finds polynomials with reasonably small coefficients defining subfields of the number field defined by $T$. One of the polynomials always defines $\Q$ (hence is equal to $x-1$), and another always defines the same number field as $T$ if $T$ is irreducible. All $T$ accepted by \tet{nfinit} are also allowed here; in particular, the format \kbd{[T, listP]} is recommended, e.g. with $\kbd{listP} = 10^5$ or a vector containing all ramified primes. Otherwise, the maximal order of $\Q[x]/(T)$ must be computed. The following binary digits of $\fl$ are significant: 1: Possibly use a suborder of the maximal order. The primes dividing the index of the order chosen are larger than \tet{primelimit} or divide integers stored in the \tet{addprimes} table. This flag is \emph{deprecated}, the \kbd{[T, listP]} format is more flexible. 2: gives also elements. The result is a two-column matrix, the first column giving primitive elements defining these subfields, the second giving the corresponding minimal polynomials. \bprog ? M = polred(x^4 + 8, 2) %1 = [1 x - 1] [1/2*x^2 x^2 + 2] [1/4*x^3 x^4 + 2] [x x^4 + 8] ? minpoly(Mod(M[2,1], x^4+8)) %2 = x^2 + 2 @eprog \synt{polred}{GEN T} ($\fl = 0$). Also available is \fun{GEN}{polred2}{GEN T} ($\fl = 2$). The function \kbd{polred0} is deprecated, provided for backward compatibility. pari-2.7.5/src/functions/number_fields/nfkermodpr0000644000175000017500000000070011636712103020612 0ustar billbillFunction: nfkermodpr Section: number_fields C-Name: nfkermodpr Prototype: GGG Help: nfkermodpr(nf,x,pr): kernel of the matrix x in Z_K/pr, where pr is in modpr format (see nfmodprinit). Doc: kernel of the matrix $a$ in $\Z_K/\var{pr}$, where \var{pr} is in \key{modpr} format (see \kbd{nfmodprinit}). Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nfM\_to\_FqM}, then work there. pari-2.7.5/src/functions/number_fields/polredord0000644000175000017500000000100012366172547020444 0ustar billbillFunction: polredord Section: number_fields C-Name: polredord Prototype: G Help: polredord(x): reduction of the polynomial x, staying in the same order. Doc: finds polynomials with reasonably small coefficients and of the same degree as that of $x$ defining suborders of the order defined by $x$. One of the polynomials always defines $\Q$ (hence is equal to $(x-1)^n$, where $n$ is the degree), and another always defines the same order as $x$ if $x$ is irreducible. Useless function: try \kbd{polredbest}. pari-2.7.5/src/functions/number_fields/bnrconductor0000644000175000017500000000202411636712103021146 0ustar billbillFunction: bnrconductor Section: number_fields C-Name: bnrconductor0 Prototype: GDGDGD0,L, Help: 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]. Doc: conductor $f$ of the subfield of a ray class field as defined by $[A,B,C]$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, \kbd{[\var{bnf}, \var{modulus}]} or \kbd{[\var{bnf}, \var{modulus}, \var{subgroup}]}, \secref{se:CFT}) If $\fl = 0$, returns $f$. If $\fl = 1$, returns $[f, Cl_f, H]$, where $Cl_f$ is the ray class group modulo $f$, as a finite abelian group; finally $H$ is the subgroup of $Cl_f$ defining the extension. If $\fl = 2$, returns $[f, \var{bnr}(f), H]$, as above except $Cl_f$ is replaced by a \kbd{bnr} structure, as output by $\tet{bnrinit}(,f,1)$. Variant: Also available is \fun{GEN}{bnrconductor}{GEN bnr, GEN H, long flag} pari-2.7.5/src/functions/number_fields/nfgaloisconj0000644000175000017500000000507711636712103021133 0ustar billbillFunction: nfgaloisconj Section: number_fields C-Name: galoisconj0 Prototype: GD0,L,DGp Help: 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. Doc: $\var{nf}$ being a number field as output by \kbd{nfinit}, computes the conjugates of a root $r$ of the non-constant polynomial $x=\var{nf}[1]$ expressed as polynomials in $r$. This also makes sense when the number field is not \idx{Galois} since some conjugates may lie in the field. $\var{nf}$ can simply be a polynomial. If no flags or $\fl=0$, use a combination of flag $4$ and $1$ and the result is always complete. There is no point whatsoever in using the other flags. If $\fl=1$, use \kbd{nfroots}: a little slow, but guaranteed to work in polynomial time. If $\fl=2$ (OBSOLETE), use complex approximations to the roots and an integral \idx{LLL}. The result is not guaranteed to be complete: some conjugates may be missing (a warning is issued if the result is not proved complete), especially so if the corresponding polynomial has a huge index, and increasing the default precision may help. This variant is slow and unreliable: don't use it. If $\fl=4$, use \kbd{galoisinit}: very fast, but only applies to (most) Galois fields. If the field is Galois with weakly super-solvable Galois group (see \tet{galoisinit}), return the complete list of automorphisms, else only the identity element. If present, $d$ is assumed to be a multiple of the least common denominator of the conjugates expressed as polynomial in a root of \var{pol}. This routine can only compute $\Q$-automorphisms, but it may be used to get $K$-automorphism for any base field $K$ as follows: \bprog rnfgaloisconj(nfK, R) = \\ K-automorphisms of L = K[X] / (R) { my(polabs, N); R *= Mod(1, nfK.pol); \\ convert coeffs to polmod elts of K polabs = rnfequation(nfK, R); N = nfgaloisconj(polabs) % R; \\ Q-automorphisms of L \\ select the ones that fix K select(s->subst(R, variable(R), Mod(s,R)) == 0, N); } K = nfinit(y^2 + 7); rnfgaloisconj(K, x^4 - y*x^3 - 3*x^2 + y*x + 1) \\ K-automorphisms of L @eprog Variant: Use directly \fun{GEN}{galoisconj}{GEN nf, GEN d}, corresponding to $\fl = 0$, the others only have historical interest. pari-2.7.5/src/functions/number_fields/bnfsunit0000644000175000017500000000220211636712103020272 0ustar billbillFunction: bnfsunit Section: number_fields C-Name: bnfsunit Prototype: GGp Help: 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. Doc: computes the fundamental $S$-units of the number field $\var{bnf}$ (output by \kbd{bnfinit}), where $S$ is a list of prime ideals (output by \kbd{idealprimedec}). The output is a vector $v$ with 6 components. $v[1]$ gives a minimal system of (integral) generators of the $S$-unit group modulo the unit group. $v[2]$ contains technical data needed by \kbd{bnfissunit}. $v[3]$ is an empty vector (used to give the logarithmic embeddings of the generators in $v[1]$ in version 2.0.16). $v[4]$ is the $S$-regulator (this is the product of the regulator, the determinant of $v[2]$ and the natural logarithms of the norms of the ideals in $S$). $v[5]$ gives the $S$-class group structure, in the usual format (a row vector whose three components give in order the $S$-class number, the cyclic components and the generators). $v[6]$ is a copy of $S$. pari-2.7.5/src/functions/number_fields/rnfequation0000644000175000017500000000420412366172547021016 0ustar billbillFunction: rnfequation Section: number_fields C-Name: rnfequation0 Prototype: GGD0,L, Help: 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. Doc: given a number field $\var{nf}$ as output by \kbd{nfinit} (or simply a polynomial) and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes an absolute equation of $L$ over $\Q$. The main variable of $\var{nf}$ \emph{must} be of lower priority than that of \var{pol} (see \secref{se:priority}). Note that for efficiency, this does not check whether the relative equation is irreducible over $\var{nf}$, but only if it is squarefree. If it is reducible but squarefree, the result will be the absolute equation of the \'etale algebra defined by \var{pol}. If \var{pol} is not squarefree, raise an \kbd{e\_DOMAIN} exception. \bprog ? rnfequation(y^2+1, x^2 - y) %1 = x^4 + 1 ? T = y^3-2; rnfequation(nfinit(T), (x^3-2)/(x-Mod(y,T))) %2 = x^6 + 108 \\ Galois closure of Q(2^(1/3)) @eprog If $\fl$ is non-zero, outputs a 3-component row vector $[z,a,k]$, where \item $z$ is the absolute equation of $L$ over $\Q$, as in the default behavior, \item $a$ expresses as a \typ{POLMOD} modulo $z$ a root $\alpha$ of the polynomial defining the base field $\var{nf}$, \item $k$ is a small integer such that $\theta = \beta+k\alpha$ is a root of $z$, where $\beta$ is a root of $\var{pol}$. \bprog ? T = y^3-2; pol = x^2 +x*y + y^2; ? [z,a,k] = rnfequation(T, pol, 1); ? z %4 = x^6 + 108 ? subst(T, y, a) %5 = 0 ? alpha= Mod(y, T); ? beta = Mod(x*Mod(1,T), pol); ? subst(z, x, beta + k*alpha) %8 = 0 @eprog Variant: Also available are \fun{GEN}{rnfequation}{GEN nf, GEN pol} ($\fl = 0$) and \fun{GEN}{rnfequation2}{GEN nf, GEN pol} ($\fl = 1$). pari-2.7.5/src/functions/number_fields/rnfidealnormrel0000644000175000017500000000067512366172547021656 0ustar billbillFunction: rnfidealnormrel Section: number_fields C-Name: rnfidealnormrel Prototype: GG Help: rnfidealnormrel(rnf,x): relative norm of the ideal x. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the relative norm of $x$ as an ideal of $K$ in HNF. pari-2.7.5/src/functions/number_fields/nfgaloisapply0000644000175000017500000000425312413013143021312 0ustar billbillFunction: nfgaloisapply Section: number_fields C-Name: galoisapply Prototype: GGG Help: nfgaloisapply(nf,aut,x): Apply the Galois automorphism aut to the object x (element or ideal) in the number field nf. Doc: let $\var{nf}$ be a number field as output by \kbd{nfinit}, and let \var{aut} be a \idx{Galois} automorphism of $\var{nf}$ expressed by its image on the field generator (such automorphisms can be found using \kbd{nfgaloisconj}). The function computes the action of the automorphism \var{aut} on the object $x$ in the number field; $x$ can be a number field element, or an ideal (possibly extended). Because of possible confusion with elements and ideals, other vector or matrix arguments are forbidden. \bprog ? nf = nfinit(x^2+1); ? L = nfgaloisconj(nf) %2 = [-x, x]~ ? aut = L[1]; /* the non-trivial automorphism */ ? nfgaloisapply(nf, aut, x) %4 = Mod(-x, x^2 + 1) ? P = idealprimedec(nf,5); /* prime ideals above 5 */ ? nfgaloisapply(nf, aut, P[2]) == P[1] %7 = 0 \\ !!!! ? idealval(nf, nfgaloisapply(nf, aut, P[2]), P[1]) %8 = 1 @eprog\noindent The surprising failure of the equality test (\kbd{\%7}) is due to the fact that although the corresponding prime ideals are equal, their representations are not. (A prime ideal is specified by a uniformizer, and there is no guarantee that applying automorphisms yields the same elements as a direct \kbd{idealprimedec} call.) The automorphism can also be given as a column vector, representing the image of \kbd{Mod(x, nf.pol)} as an algebraic number. This last representation is more efficient and should be preferred if a given automorphism must be used in many such calls. \bprog ? nf = nfinit(x^3 - 37*x^2 + 74*x - 37); ? l = nfgaloisconj(nf); aut = l[2] \\ @com automorphisms in basistoalg form %2 = -31/11*x^2 + 1109/11*x - 925/11 ? L = matalgtobasis(nf, l); AUT = L[2] \\ @com same in algtobasis form %3 = [16, -6, 5]~ ? v = [1, 2, 3]~; nfgaloisapply(nf, aut, v) == nfgaloisapply(nf, AUT, v) %4 = 1 \\ @com same result... ? for (i=1,10^5, nfgaloisapply(nf, aut, v)) time = 1,451 ms. ? for (i=1,10^5, nfgaloisapply(nf, AUT, v)) time = 1,045 ms. \\ @com but the latter is faster @eprog pari-2.7.5/src/functions/number_fields/idealramgroups0000644000175000017500000000326312314242551021467 0ustar billbillFunction: idealramgroups Section: number_fields C-Name: idealramgroups Prototype: GGG Help: 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. Doc: Let $K$ be the number field defined by \var{nf} and assume that $K/\Q$ is Galois with Galois group $G$ given by \kbd{gal=galoisinit(nf)}. Let \var{pr} be the prime ideal $\goth{P}$ in prid format. This function returns a vector $g$ of subgroups of \kbd{gal} as follow: \item \kbd{g[1]} is the decomposition group of $\goth{P}$, \item \kbd{g[2]} is $G_0(\goth{P})$, the inertia group of $\goth{P}$, and for $i\geq 2$, \item \kbd{g[i]} is $G_{i-2}(\goth{P})$, the $i-2$-th \idx{ramification group} of $\goth{P}$. \noindent The length of $g$ is the number of non-trivial groups in the sequence, thus is $0$ if $e=1$ and $f=1$, and $1$ if $f>1$ and $e=1$. The following function computes the cardinality of a subgroup of $G$, as given by the components of $g$: \bprog card(H) =my(o=H[2]); prod(i=1,#o,o[i]); @eprog \bprog ? nf=nfinit(x^6+3); gal=galoisinit(nf); pr=idealprimedec(nf,3)[1]; ? g = idealramgroups(nf, gal, pr); ? apply(card,g) %4 = [6, 6, 3, 3, 3] \\ cardinalities of the G_i @eprog \bprog ? nf=nfinit(x^6+108); gal=galoisinit(nf); pr=idealprimedec(nf,2)[1]; ? iso=idealramgroups(nf,gal,pr)[2] %4 = [[Vecsmall([2, 3, 1, 5, 6, 4])], Vecsmall([3])] ? nfdisc(galoisfixedfield(gal,iso,1)) %5 = -3 @eprog\noindent The field fixed by the inertia group of $2$ is not ramified at $2$. pari-2.7.5/src/functions/number_fields/idealmin0000644000175000017500000000060111636712103020225 0ustar billbillFunction: idealmin Section: number_fields C-Name: idealmin Prototype: GGDG Help: idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in the number field nf. Doc: \emph{This function is useless and kept for backward compatibility only, use \kbd{idealred}}. Computes a pseudo-minimum of the ideal $x$ in the direction \var{vdir} in the number field \var{nf}. pari-2.7.5/src/functions/number_fields/nfcertify0000644000175000017500000000156712366172547020465 0ustar billbillFunction: nfcertify Section: number_fields C-Name: nfcertify Prototype: G Help: 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). Doc: $\var{nf}$ being as output by \kbd{nfinit}, checks whether the integer basis is known unconditionally. This is in particular useful when the argument to \kbd{nfinit} was of the form $[T, \kbd{listP}]$, specifying a finite list of primes when $p$-maximality had to be proven. The function returns a vector of composite integers. If this vector is empty, then \kbd{nf.zk} and \kbd{nf.disc} are correct. Otherwise, the result is dubious. In order to obtain a certified result, one must completely factor each of the given integers, then \kbd{addprime} each of them, then check whether \kbd{nfdisc(nf.pol)} is equal to \kbd{nf.disc}. pari-2.7.5/src/functions/number_fields/bnfissunit0000644000175000017500000000102211636712103020625 0ustar billbillFunction: bnfissunit Section: number_fields C-Name: bnfissunit Prototype: GGG Help: 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. Doc: $\var{bnf}$ being output by \kbd{bnfinit}, \var{sfu} by \kbd{bnfsunit}, gives the column vector of exponents of $x$ on the fundamental $S$-units and the roots of unity. If $x$ is not a unit, outputs an empty vector. pari-2.7.5/src/functions/number_fields/rnfisnorminit0000644000175000017500000000204411636712103021347 0ustar billbillFunction: rnfisnorminit Section: number_fields C-Name: rnfisnorminit Prototype: GGD2,L, Help: 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. Doc: let $K$ be defined by a root of \var{pol}, and $L/K$ the extension defined by the polynomial \var{polrel}. As usual, \var{pol} can in fact be an \var{nf}, or \var{bnf}, etc; if \var{pol} has degree $1$ (the base field is $\Q$), polrel is also allowed to be an \var{nf}, etc. Computes technical data needed by \tet{rnfisnorm} to solve norm equations $Nx = a$, for $x$ in $L$, and $a$ in $K$. If $\fl = 0$, do not care whether $L/K$ is Galois or not. If $\fl = 1$, $L/K$ is assumed to be Galois (unchecked), which speeds up \tet{rnfisnorm}. If $\fl = 2$, let the routine determine whether $L/K$ is Galois. pari-2.7.5/src/functions/number_fields/nffactorback0000644000175000017500000000146211636712103021074 0ustar billbillFunction: nffactorback Section: number_fields C-Name: nffactorback Prototype: GGDG Help: nffactorback(nf,f,{e}): given a factorisation f, returns the factored object back as an nf element. Doc: gives back the \kbd{nf} element corresponding to a factorization. The integer $1$ corresponds to the empty factorization. If $e$ is present, $e$ and $f$ must be vectors of the same length ($e$ being integral), and the corresponding factorization is the product of the $f[i]^{e[i]}$. If not, and $f$ is vector, it is understood as in the preceding case with $e$ a vector of 1s: we return the product of the $f[i]$. Finally, $f$ can be a regular factorization matrix. \bprog ? nf = nfinit(y^2+1); ? nffactorback(nf, [3, y+1, [1,2]~], [1, 2, 3]) %2 = [12, -66]~ ? 3 * (I+1)^2 * (1+2*I)^3 %3 = 12 - 66*I @eprog pari-2.7.5/src/functions/number_fields/rnfpolredabs0000644000175000017500000000353012366172547021145 0ustar billbillFunction: rnfpolredabs Section: number_fields C-Name: rnfpolredabs Prototype: GGD0,L, Help: 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. Doc: THIS FUNCTION IS OBSOLETE: use \tet{rnfpolredbest} instead. Relative version of \kbd{polredabs}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a simpler relative polynomial defining the same field. The binary digits of $\fl$ mean The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative, $16$: possibly use a suborder of the maximal order. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. Same as but faster than \bprog rnfequation(nf, rnfpolredabs(nf,pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. 16: possibly use a suborder of the maximal order. This is slower than the default when the relative discriminant is smooth, and much faster otherwise. See \secref{se:polredabs}. \misctitle{Warning} In the present implementation, \kbd{rnfpolredabs} produces smaller polynomials than \kbd{rnfpolred} and is usually faster, but its complexity is still exponential in the absolute degree. The function \tet{rnfpolredbest} runs in polynomial time, and tends to return polynomials with smaller discriminants. pari-2.7.5/src/functions/number_fields/rnfeltreltoabs0000644000175000017500000000136512366172547021516 0ustar billbillFunction: rnfeltreltoabs Section: number_fields C-Name: rnfeltreltoabs Prototype: GG Help: rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial or polmod with polmod coefficients, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltreltoabs(L, Mod(x, L.pol)) %3 = Mod(x, x^4 + 1) ? rnfeltreltoabs(L, Mod(y, x^2-y)) %4 = Mod(x^2, x^4 + 1) ? rnfeltreltoabs(L, Mod(y,K.pol)) %5 = Mod(x^2, x^4 + 1) @eprog pari-2.7.5/src/functions/number_fields/bnfinit0000644000175000017500000001212012314242551020072 0ustar billbillFunction: bnfinit Section: number_fields C-Name: bnfinit0 Prototype: GD0,L,DGp Help: 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. Description: (gen):bnf:prec Buchall($1, 0, prec) (gen, 0):bnf:prec Buchall($1, 0, prec) (gen, 1):bnf:prec Buchall($1, nf_FORCE, prec) (gen, ?small, ?gen):bnf:prec bnfinit0($1, $2, $3, prec) Doc: initializes a \var{bnf} structure. Used in programs such as \kbd{bnfisprincipal}, \kbd{bnfisunit} or \kbd{bnfnarrow}. By default, the results are conditional on the GRH, see \ref{se:GRHbnf}. The result is a 10-component vector \var{bnf}. This implements \idx{Buchmann}'s sub-exponential algorithm for computing the class group, the regulator and a system of \idx{fundamental units} of the general algebraic number field $K$ defined by the irreducible polynomial $P$ with integer coefficients. If the precision becomes insufficient, \kbd{gp} does not strive to compute the units by default ($\fl=0$). When $\fl=1$, we insist on finding the fundamental units exactly. Be warned that this can take a very long time when the coefficients of the fundamental units on the integral basis are very large. If the fundamental units are simply too large to be represented in this form, an error message is issued. They could be obtained using the so-called compact representation of algebraic numbers as a formal product of algebraic integers. The latter is implemented internally but not publicly accessible yet. $\var{tech}$ is a technical vector (empty by default, see \ref{se:GRHbnf}). Careful use of this parameter may speed up your computations, but it is mostly obsolete and you should leave it alone. \smallskip The components of a \var{bnf} or \var{sbnf} are technical and never used by the casual user. In fact: \emph{never access a component directly, always use a proper member function.} However, for the sake of completeness and internal documentation, their description is as follows. We use the notations explained in the book by H. Cohen, \emph{A Course in Computational Algebraic Number Theory}, Graduate Texts in Maths \key{138}, Springer-Verlag, 1993, Section 6.5, and subsection 6.5.5 in particular. $\var{bnf}[1]$ contains the matrix $W$, i.e.~the matrix in Hermite normal form giving relations for the class group on prime ideal generators $(\goth{p}_i)_{1\le i\le r}$. $\var{bnf}[2]$ contains the matrix $B$, i.e.~the matrix containing the expressions of the prime ideal factorbase in terms of the $\goth{p}_i$. It is an $r\times c$ matrix. $\var{bnf}[3]$ contains the complex logarithmic embeddings of the system of fundamental units which has been found. It is an $(r_1+r_2)\times(r_1+r_2-1)$ matrix. $\var{bnf}[4]$ contains the matrix $M''_C$ of Archimedean components of the relations of the matrix $(W|B)$. $\var{bnf}[5]$ contains the prime factor base, i.e.~the list of prime ideals used in finding the relations. $\var{bnf}[6]$ used to contain a permutation of the prime factor base, but has been obsoleted. It contains a dummy $0$. $\var{bnf}[7]$ or \kbd{\var{bnf}.nf} is equal to the number field data $\var{nf}$ as would be given by \kbd{nfinit}. $\var{bnf}[8]$ is a vector containing the classgroup \kbd{\var{bnf}.clgp} as a finite abelian group, the regulator \kbd{\var{bnf}.reg}, a $1$ (used to contain an obsolete ``check number''), the number of roots of unity and a generator \kbd{\var{bnf}.tu}, the fundamental units \kbd{\var{bnf}.fu}. $\var{bnf}[9]$ is a 3-element row vector used in \tet{bnfisprincipal} only and obtained as follows. Let $D = U W V$ obtained by applying the \idx{Smith normal form} algorithm to the matrix $W$ (= $\var{bnf}[1]$) and let $U_r$ be the reduction of $U$ modulo $D$. The first elements of the factorbase are given (in terms of \kbd{bnf.gen}) by the columns of $U_r$, with Archimedean component $g_a$; let also $GD_a$ be the Archimedean components of the generators of the (principal) ideals defined by the \kbd{bnf.gen[i]\pow bnf.cyc[i]}. Then $\var{bnf}[9]=[U_r, g_a, GD_a]$. $\var{bnf}[10]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available, which is rarely needed, hence would be too expensive to compute during the initial \kbd{bnfinit} call. For instance, the generators of the principal ideals \kbd{bnf.gen[i]\pow bnf.cyc[i]} (during a call to \tet{bnrisprincipal}), or those corresponding to the relations in $W$ and $B$ (when the \kbd{bnf} internal precision needs to be increased). Variant: Also available is \fun{GEN}{Buchall}{GEN P, long flag, long prec}, corresponding to \kbd{tech = NULL}, where \kbd{flag} is either $0$ (default) or \tet{nf_FORCE} (insist on finding fundamental units). The function \fun{GEN}{Buchall_param}{GEN P, double c1, double c2, long nrpid, long flag, long prec} gives direct access to the technical parameters. pari-2.7.5/src/functions/number_fields/bnrconductorofchar0000644000175000017500000000066211636712103022337 0ustar billbillFunction: bnrconductorofchar Section: number_fields C-Name: bnrconductorofchar Prototype: GG Help: bnrconductorofchar(bnr,chi): conductor of the character chi on the ray class group bnr. Doc: \var{bnr} being a big ray number field as output by \kbd{bnrinit}, and \var{chi} being a row vector representing a \idx{character} as expressed on the generators of the ray class group, gives the conductor of this character as a modulus. pari-2.7.5/src/functions/number_fields/rnfidealabstorel0000644000175000017500000000273512366172547022012 0ustar billbillFunction: rnfidealabstorel Section: number_fields C-Name: rnfidealabstorel Prototype: GG Help: rnfidealabstorel(rnf,x): transforms the ideal x from absolute to relative representation. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ be an ideal of the absolute extension $L/\Q$ given by a $\Z$-basis of elements of $L$. Returns the relative pseudo-matrix in HNF giving the ideal $x$ considered as an ideal of the relative extension $L/K$, i.e.~as a $\Z_K$-module. The reason why the input does not use the customary HNF in terms of a fixed $\Z$-basis for $\Z_L$ is precisely that no such basis has been explicitly specified. On the other hand, if you already computed an (absolute) \var{nf} structure \kbd{Labs} associated to $L$, and $m$ is in HNF, defining an (absolute) ideal with respect to the $\Z$-basis \kbd{Labs.zk}, then \kbd{Labs.zk * m} is a suitable $\Z$-basis for the ideal, and \bprog 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); ? 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 ? A = rnfidealreltoabs(L, B) %4 = [17, x^2 + 4, x + 8, x^3 + 8*x^2] \\ Z-basis for m in Q[x]/(L.pol) ? mathnf(matalgtobasis(Labs, A)) %5 = [17 8 4 2] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] ? % == m %6 = 1 @eprog pari-2.7.5/src/functions/number_fields/zetak0000644000175000017500000000376711636712103017601 0ustar billbillFunction: zetak Section: number_fields C-Name: gzetakall Prototype: GGD0,L,p Help: 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. Doc: \var{znf} being a number field initialized by \kbd{zetakinit} (\emph{not} by \kbd{nfinit}), computes the value of the \idx{Dedekind} zeta function of the number field at the complex number $x$. If $\fl=1$ computes Dedekind $\Lambda$ function instead (i.e.~the product of the Dedekind zeta function by its gamma and exponential factors). \misctitle{CAVEAT} This implementation is not satisfactory and must be rewritten. In particular \item The accuracy of the result depends in an essential way on the accuracy of both the \kbd{zetakinit} program and the current accuracy. Be wary in particular that $x$ of large imaginary part or, on the contrary, very close to an ordinary integer will suffer from precision loss, yielding fewer significant digits than expected. Computing with 28 digits of relative accuracy, we have \bprog ? zeta(3) %1 = 1.202056903159594285399738161 ? zeta(3-1e-20) %2 = 1.202056903159594285401719424 ? zetak(zetakinit(x), 3-1e-20) %3 = 1.2020569031595952919 \\ 5 digits are wrong ? zetak(zetakinit(x), 3-1e-28) %4 = -25.33411749 \\ junk @eprog \item As the precision increases, results become unexpectedly completely wrong: \bprog ? \p100 ? zetak(zetakinit(x^2-5), -1) - 1/30 %1 = 7.26691813 E-108 \\ perfect ? \p150 ? zetak(zetakinit(x^2-5), -1) - 1/30 %2 = -2.486113578 E-156 \\ perfect ? \p200 ? zetak(zetakinit(x^2-5), -1) - 1/30 %3 = 4.47... E-75 \\ more than half of the digits are wrong ? \p250 ? zetak(zetakinit(x^2-5), -1) - 1/30 %4 = 1.6 E43 \\ junk @eprog Variant: See also \fun{GEN}{glambdak}{GEN znf, GEN x, long prec} or \fun{GEN}{gzetak}{GEN znf, GEN x, long prec}. pari-2.7.5/src/functions/number_fields/bnfdecodemodule0000644000175000017500000000076212314242551021571 0ustar billbillFunction: bnfdecodemodule Section: number_fields C-Name: decodemodule Prototype: GG Help: bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true module. Doc: if $m$ is a module as output in the first component of an extension given by \kbd{bnrdisclist}, outputs the true module. \bprog ? K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[1][2] %1 = [[Mat([8, 1]), [[0, 0, 0]]], [Mat([9, 1]), [[0, 0, 0]]]] ? bnfdecodemodule(K, s[1][1]) %2 = [2 0] [0 1] @eprog pari-2.7.5/src/functions/number_fields/idealinv0000644000175000017500000000063611636712103020246 0ustar billbillFunction: idealinv Section: number_fields C-Name: idealinv Prototype: GG Help: idealinv(nf,x): inverse of the ideal x in the number field nf. Description: (gen, gen):gen idealinv($1, $2) Doc: inverse of the ideal $x$ in the number field $\var{nf}$, given in HNF. If $x$ is an extended ideal\sidx{ideal (extended)}, its principal part is suitably updated: i.e. inverting $[I,t]$, yields $[I^{-1}, 1/t]$. pari-2.7.5/src/functions/number_fields/bnrrootnumber0000644000175000017500000000266511636712103021355 0ustar billbillFunction: bnrrootnumber Section: number_fields C-Name: bnrrootnumber Prototype: GGD0,L,p Help: 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. Doc: if $\chi=\var{chi}$ is a \idx{character} over \var{bnr}, not necessarily primitive, let $L(s,\chi) = \sum_{id} \chi(id) N(id)^{-s}$ be the associated \idx{Artin L-function}. Returns the so-called \idx{Artin root number}, i.e.~the complex number $W(\chi)$ of modulus 1 such that % $$\Lambda(1-s,\chi) = W(\chi) \Lambda(s,\overline{\chi})$$ % \noindent where $\Lambda(s,\chi) = A(\chi)^{s/2}\gamma_\chi(s) L(s,\chi)$ is the enlarged L-function associated to $L$. The generators of the ray class group are needed, and you can set $\fl=1$ if the character is known to be primitive. Example: \bprog bnf = bnfinit(x^2 - x - 57); bnr = bnrinit(bnf, [7,[1,1]], 1); bnrrootnumber(bnr, [2,1]) @eprog\noindent returns the root number of the character $\chi$ of $\Cl_{7\infty_1\infty_2}(\Q(\sqrt{229}))$ defined by $\chi(g_1^ag_2^b) = \zeta_1^{2a}\zeta_2^b$. Here $g_1, g_2$ are the generators of the ray-class group given by \kbd{bnr.gen} and $\zeta_1 = e^{2i\pi/N_1}, \zeta_2 = e^{2i\pi/N_2}$ where $N_1, N_2$ are the orders of $g_1$ and $g_2$ respectively ($N_1=6$ and $N_2=3$ as \kbd{bnr.cyc} readily tells us). pari-2.7.5/src/functions/number_fields/galoisisabelian0000644000175000017500000000103611636712103021574 0ustar billbillFunction: galoisisabelian Section: number_fields C-Name: galoisisabelian Prototype: GD0,L, Help: 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. Doc: \var{gal} being as output by \kbd{galoisinit}, return $0$ if \var{gal} is not an abelian group, and the HNF matrix of \var{gal} over \kbd{gal.gen} if $fl=0$, $1$ if $fl=1$. This command also accepts subgroups returned by \kbd{galoissubgroups}. pari-2.7.5/src/functions/number_fields/rnfdedekind0000644000175000017500000000667011636712103020734 0ustar billbillFunction: rnfdedekind Section: number_fields C-Name: rnfdedekind Prototype: GGDGD0,L, Help: 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 the order discriminant. If flag is set, just return 1 if the order is maximal, and 0 if not. Doc: given a number field $K$ coded by $\var{nf}$ and a monic polynomial $P\in \Z_K[X]$, irreducible over $K$ and thus defining a relative extension $L$ of $K$, applies \idx{Dedekind}'s criterion to the order $\Z_K[X]/(P)$, at the prime ideal \var{pr}. It is possible to set \var{pr} to a vector of prime ideals (test maximality at all primes in the vector), or to omit altogether, in which case maximality at \emph{all} primes is tested; in this situation \fl\ is automatically set to $1$. The default historic behavior (\fl\ is 0 or omitted and \var{pr} is a single prime ideal) is not so useful since \kbd{rnfpseudobasis} gives more information and is generally not that much slower. It returns a 3-component vector $[\var{max}, \var{basis}, v]$: \item \var{basis} is a pseudo-basis of an enlarged order $O$ produced by Dedekind's criterion, containing the original order $\Z_K[X]/(P)$ with index a power of \var{pr}. Possibly equal to the original order. \item \var{max} is a flag equal to 1 if the enlarged order $O$ could be proven to be \var{pr}-maximal and to 0 otherwise; it may still be maximal in the latter case if \var{pr} is ramified in $L$, \item $v$ is the valuation at \var{pr} of the order discriminant. If \fl\ is non-zero, on the other hand, we just return $1$ if the order $\Z_K[X]/(P)$ is \var{pr}-maximal (resp.~maximal at all relevant primes, as described above), and $0$ if not. This is much faster than the default, since the enlarged order is not computed. \bprog ? nf = nfinit(y^2-3); P = x^3 - 2*y; ? pr3 = idealprimedec(nf,3)[1]; ? rnfdedekind(nf, P, pr3) %2 = [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8] ? rnfdedekind(nf, P, pr3, 1) %3 = 1 @eprog\noindent In this example, \kbd{pr3} is the ramified ideal above $3$, and the order generated by the cube roots of $y$ is already \kbd{pr3}-maximal. The order-discriminant has valuation $8$. On the other hand, the order is not maximal at the prime above 2: \bprog ? pr2 = idealprimedec(nf,2)[1]; ? rnfdedekind(nf, P, pr2, 1) %5 = 0 ? rnfdedekind(nf, P, pr2) %6 = [0, [[2, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0; 0, 1], [1, 0; 0, 1], [1, 1/2; 0, 1/2]]], 2] @eprog The enlarged order is not proven to be \kbd{pr2}-maximal yet. In fact, it is; it is in fact the maximal order: \bprog ? B = rnfpseudobasis(nf, P) %7 = [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, [1, 1/2; 0, 1/2]], [162, 0; 0, 162], -1] ? idealval(nf,B[3], pr2) %4 = 2 @eprog\noindent It is possible to use this routine with non-monic $P = \sum_{i\leq n} a_i X^i \in \Z_K[X]$ if $\fl = 1$; in this case, we test maximality of Dedekind's order generated by $$1, a_n \alpha, a_n\alpha^2 + a_{n-1}\alpha, \dots, a_n\alpha^{n-1} + a_{n-1}\alpha^{n-2} + \cdots + a_1\alpha.$$ The routine will fail if $P$ is $0$ on the projective line over the residue field $\Z_K/\kbd{pr}$ (FIXME). pari-2.7.5/src/functions/number_fields/bnrdisclist0000644000175000017500000000533311636712103020772 0ustar billbillFunction: bnrdisclist Section: number_fields C-Name: bnrdisclist0 Prototype: GGDG Help: 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). Doc: $\var{bnf}$ being as output by \kbd{bnfinit} (with units), computes a list of discriminants of Abelian extensions of the number field by increasing modulus norm up to bound \var{bound}. The ramified Archimedean places are given by \var{arch}; all possible values are taken if \var{arch} is omitted. The alternative syntax $\kbd{bnrdisclist}(\var{bnf},\var{list})$ is supported, where \var{list} is as output by \kbd{ideallist} or \kbd{ideallistarch} (with units), in which case \var{arch} is disregarded. The output $v$ is a vector of vectors, where $v[i][j]$ is understood to be in fact $V[2^{15}(i-1)+j]$ of a unique big vector $V$. (This awkward scheme allows for larger vectors than could be otherwise represented.) $V[k]$ is itself a vector $W$, whose length is the number of ideals of norm $k$. We consider first the case where \var{arch} was specified. Each component of $W$ corresponds to an ideal $m$ of norm $k$, and gives invariants associated to the ray class field $L$ of $\var{bnf}$ of conductor $[m, \var{arch}]$. Namely, each contains a vector $[m,d,r,D]$ with the following meaning: $m$ is the prime ideal factorization of the modulus, $d = [L:\Q]$ is the absolute degree of $L$, $r$ is the number of real places of $L$, and $D$ is the factorization of its absolute discriminant. We set $d = r = D = 0$ if $m$ is not the finite part of a conductor. If \var{arch} was omitted, all $t = 2^{r_1}$ possible values are taken and a component of $W$ has the form $[m, [[d_1,r_1,D_1], \dots, [d_t,r_t,D_t]]]$, where $m$ is the finite part of the conductor as above, and $[d_i,r_i,D_i]$ are the invariants of the ray class field of conductor $[m,v_i]$, where $v_i$ is the $i$-th Archimedean component, ordered by inverse lexicographic order; so $v_1 = [0,\dots,0]$, $v_2 = [1,0\dots,0]$, etc. Again, we set $d_i = r_i = D_i = 0$ if $[m,v_i]$ is not a conductor. Finally, each prime ideal $pr = [p,\alpha,e,f,\beta]$ in the prime factorization $m$ is coded as the integer $p\cdot n^2+(f-1)\cdot n+(j-1)$, where $n$ is the degree of the base field and $j$ is such that \kbd{pr = idealprimedec(\var{nf},p)[j]}. \noindent $m$ can be decoded using \tet{bnfdecodemodule}. Note that to compute such data for a single field, either \tet{bnrclassno} or \tet{bnrdisc} is more efficient. pari-2.7.5/src/functions/number_fields/rnfisfree0000644000175000017500000000077711636712103020444 0ustar billbillFunction: rnfisfree Section: number_fields C-Name: rnfisfree Prototype: lGG Help: 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. Doc: given $\var{bnf}$ as output by \kbd{bnfinit}, and either a polynomial $x$ with coefficients in $\var{bnf}$ defining a relative extension $L$ of $\var{bnf}$, or a pseudo-basis $x$ of such an extension, returns true (1) if $L/\var{bnf}$ is free, false (0) if not. pari-2.7.5/src/functions/number_fields/nffactormod0000644000175000017500000000202312366172547020762 0ustar billbillFunction: nffactormod Section: number_fields C-Name: nffactormod Prototype: GGG Help: nffactormod(nf,Q,pr): factor polynomial Q modulo prime ideal pr in number field nf. Doc: factors the univariate polynomial $Q$ modulo the prime ideal \var{pr} in the number field $\var{nf}$. The coefficients of $Q$ belong to the number field (scalar, polmod, polynomial, even column vector) and the main variable of $\var{nf}$ must be of lower priority than that of $Q$ (see \secref{se:priority}). The prime ideal \var{pr} is either in \tet{idealprimedec} or (preferred) \tet{modprinit} format. The coefficients of the polynomial factors are lifted to elements of \var{nf}: \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? nffactormod(K, x^2 + y*x + 18*y+1, P) %3 = [x + (2*y + 1) 1] [x + (2*y + 2) 1] ? P = nfmodprinit(K, P); \\ convert to nfmodprinit format ? nffactormod(K, x^2 + y*x + 18*y+1) [x + (2*y + 1) 1] [x + (2*y + 2) 1] @eprog\noindent Same result, of course, here about 10\% faster due to the precomputation. pari-2.7.5/src/functions/number_fields/bnfcompress0000644000175000017500000000340711636712103020773 0ustar billbillFunction: bnfcompress Section: number_fields C-Name: bnfcompress Prototype: G Help: bnfcompress(bnf): converts bnf to a much smaller sbnf, containing the same information. Use bnfinit(sbnf) to recover a true bnf. Doc: computes a compressed version of \var{bnf} (from \tet{bnfinit}), a ``small Buchmann's number field'' (or \var{sbnf} for short) which contains enough information to recover a full $\var{bnf}$ vector very rapidly, but which is much smaller and hence easy to store and print. Calling \kbd{bnfinit} on the result recovers a true \kbd{bnf}, in general different from the original. Note that an \tev{snbf} is useless for almost all purposes besides storage, and must be converted back to \tev{bnf} form before use; for instance, no \kbd{nf*}, \kbd{bnf*} or member function accepts them. An \var{sbnf} is a 12 component vector $v$, as follows. Let \kbd{bnf} be the result of a full \kbd{bnfinit}, complete with units. Then $v[1]$ is \kbd{bnf.pol}, $v[2]$ is the number of real embeddings \kbd{bnf.sign[1]}, $v[3]$ is \kbd{bnf.disc}, $v[4]$ is \kbd{bnf.zk}, $v[5]$ is the list of roots \kbd{bnf.roots}, $v[7]$ is the matrix $\kbd{W} = \kbd{bnf[1]}$, $v[8]$ is the matrix $\kbd{matalpha}=\kbd{bnf[2]}$, $v[9]$ is the prime ideal factor base \kbd{bnf[5]} coded in a compact way, and ordered according to the permutation \kbd{bnf[6]}, $v[10]$ is the 2-component vector giving the number of roots of unity and a generator, expressed on the integral basis, $v[11]$ is the list of fundamental units, expressed on the integral basis, $v[12]$ is a vector containing the algebraic numbers alpha corresponding to the columns of the matrix \kbd{matalpha}, expressed on the integral basis. All the components are exact (integral or rational), except for the roots in $v[5]$. pari-2.7.5/src/functions/number_fields/nfeltdivmodpr0000644000175000017500000000101411636712103021317 0ustar billbillFunction: nfeltdivmodpr Section: number_fields C-Name: nfdivmodpr Prototype: GGGG Help: nfeltdivmodpr(nf,x,y,pr): element x/y modulo pr in nf, where pr is in modpr format (see nfmodprinit). Doc: given two elements $x$ and $y$ in \var{nf} and \var{pr} a prime ideal in \kbd{modpr} format (see \tet{nfmodprinit}), computes their quotient $x / y$ modulo the prime ideal \var{pr}. Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nf\_to\_Fq}, then work there. pari-2.7.5/src/functions/number_fields/nfmodprinit0000644000175000017500000000066111636712103021002 0ustar billbillFunction: nfmodprinit Section: number_fields C-Name: nfmodprinit Prototype: GG Help: 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). Doc: transforms the prime ideal \var{pr} into \tet{modpr} format necessary for all operations modulo \var{pr} in the number field \var{nf}. pari-2.7.5/src/functions/number_fields/polredbest0000644000175000017500000000436312366172547020634 0ustar billbillFunction: polredbest Section: number_fields C-Name: polredbest Prototype: GD0,L, Help: polredbest(T,{flag=0}): reduction of the polynomial T (gives minimal polynomials only). If flag=1, gives also elements. Doc: finds a polynomial with reasonably small coefficients defining the same number field as $T$. All $T$ accepted by \tet{nfinit} are also allowed here (e.g. non-monic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[T,Z\_K\_basis]}). Contrary to \tet{polredabs}, this routine runs in polynomial time, but it offers no guarantee as to the minimality of its result. This routine computes an LLL-reduced basis for the ring of integers of $\Q[X]/(T)$, then examines small linear combinations of the basis vectors, computing their characteristic polynomials. It returns the \emph{separable} $P$ polynomial of smallest discriminant (the one with lexicographically smallest \kbd{abs(Vec(P))} in case of ties). This is a good candidate for subsequent number field computations, since it guarantees that the denominators of algebraic integers, when expressed in the power basis, are reasonably small. With no claim of minimality, though. It can happen that iterating this functions yields better and better polynomials, until it stabilizes: \bprog ? \p5 ? P = X^12+8*X^8-50*X^6+16*X^4-3069*X^2+625; ? poldisc(P)*1. %2 = 1.2622 E55 ? P = polredbest(P); ? poldisc(P)*1. %4 = 2.9012 E51 ? P = polredbest(P); ? poldisc(P)*1. %6 = 8.8704 E44 @eprog\noindent In this example, the initial polynomial $P$ is the one returned by \tet{polredabs}, and the last one is stable. If $\fl = 1$: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{Mod(a, P)} is a root of the original $T$. \bprog ? [P,a] = polredbest(x^4 + 8, 1) %1 = [x^4 + 2, Mod(x^3, x^4 + 2)] ? charpoly(a) %2 = x^4 + 8 @eprog\noindent In particular, the map $\Q[x]/(T) \to \Q[x]/(P)$, $x\mapsto \kbd{Mod(a,P)}$ defines an isomorphism of number fields, which can be computed as \bprog subst(lift(Q), 'x, a) @eprog\noindent if $Q$ is a \typ{POLMOD} modulo $T$; \kbd{b = modreverse(a)} returns a \typ{POLMOD} giving the inverse of the above map (which should be useless since $\Q[x]/(P)$ is a priori a better representation for the number field and its elements). pari-2.7.5/src/functions/number_fields/bnrstark0000644000175000017500000000432011636712103020273 0ustar billbillFunction: bnrstark Section: number_fields C-Name: bnrstark Prototype: GDGp Help: 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. Doc: \var{bnr} being as output by \kbd{bnrinit(,,1)}, finds a relative equation for the class field corresponding to the modulus in \var{bnr} and the given congruence subgroup (as usual, omit $\var{subgroup}$ if you want the whole ray class group). The main variable of \var{bnr} must not be $x$, and the ground field and the class field must be totally real. When the base field is $\Q$, the vastly simpler \tet{galoissubcyclo} is used instead. Here is an example: \bprog bnf = bnfinit(y^2 - 3); bnr = bnrinit(bnf, 5, 1); bnrstark(bnr) @eprog\noindent returns the ray class field of $\Q(\sqrt{3})$ modulo $5$. Usually, one wants to apply to the result one of \bprog rnfpolredabs(bnf, pol, 16) \\@com compute a reduced relative polynomial rnfpolredabs(bnf, pol, 16 + 2) \\@com compute a reduced absolute polynomial @eprog The routine uses \idx{Stark units} and needs to find a suitable auxiliary conductor, which may not exist when the class field is not cyclic over the base. In this case \kbd{bnrstark} is allowed to return a vector of polynomials defining \emph{independent} relative extensions, whose compositum is the requested class field. It was decided that it was more useful to keep the extra information thus made available, hence the user has to take the compositum herself. Even if it exists, the auxiliary conductor may be so large that later computations become unfeasible. (And of course, Stark's conjecture may simply be wrong.) In case of difficulties, try \tet{rnfkummer}: \bprog ? bnr = bnrinit(bnfinit(y^8-12*y^6+36*y^4-36*y^2+9,1), 2, 1); ? bnrstark(bnr) *** at top-level: bnrstark(bnr) *** ^------------- *** bnrstark: need 3919350809720744 coefficients in initzeta. *** Computation impossible. ? lift( rnfkummer(bnr) ) time = 24 ms. %2 = x^2 + (1/3*y^6 - 11/3*y^4 + 8*y^2 - 5) @eprog pari-2.7.5/src/functions/number_fields/idealnorm0000644000175000017500000000032611636712103020421 0ustar billbillFunction: idealnorm Section: number_fields C-Name: idealnorm Prototype: GG Help: idealnorm(nf,x): norm of the ideal x in the number field nf. Doc: computes the norm of the ideal~$x$ in the number field~$\var{nf}$. pari-2.7.5/src/functions/number_fields/nfeltadd0000644000175000017500000000033311636712103020226 0ustar billbillFunction: nfeltadd Section: number_fields C-Name: nfadd Prototype: GGG Help: nfadd(nf,x,y): element x+y in nf. Doc: given two elements $x$ and $y$ in \var{nf}, computes their sum $x+y$ in the number field $\var{nf}$. pari-2.7.5/src/functions/number_fields/rnfisnorm0000644000175000017500000000430711636712103020467 0ustar billbillFunction: rnfisnorm Section: number_fields C-Name: rnfisnorm Prototype: GGD0,L, Help: 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 <= flag (resp. p | flag) if flag > 0 (resp. flag < 0). The answer is guaranteed (i.e a is a norm iff q=1) if L/K is Galois or, under GRH, if S contains all primes less than 12.log(disc(M))^2, where M is the normal closure of L/K. Doc: similar to \kbd{bnfisnorm} but in the relative case. $T$ is as output by \tet{rnfisnorminit} applied to the extension $L/K$. This tries to decide whether the element $a$ in $K$ is the norm of some $x$ in the extension $L/K$. The output is a vector $[x,q]$, where $a = \Norm(x)*q$. The algorithm looks for a solution $x$ which is an $S$-integer, with $S$ a list of places of $K$ containing at least the ramified primes, the generators of the class group of $L$, as well as those primes dividing $a$. If $L/K$ is Galois, then this is enough; otherwise, $\fl$ is used to add more primes to $S$: all the places above the primes $p \leq \fl$ (resp.~$p|\fl$) if $\fl>0$ (resp.~$\fl<0$). The answer is guaranteed (i.e.~$a$ is a norm iff $q = 1$) if the field is Galois, or, under \idx{GRH}, if $S$ contains all primes less than $12\log^2\left|\disc(M)\right|$, where $M$ is the normal closure of $L/K$. If \tet{rnfisnorminit} has determined (or was told) that $L/K$ is \idx{Galois}, and $\fl \neq 0$, a Warning is issued (so that you can set $\fl = 1$ to check whether $L/K$ is known to be Galois, according to $T$). Example: \bprog bnf = bnfinit(y^3 + y^2 - 2*y - 1); p = x^2 + Mod(y^2 + 2*y + 1, bnf.pol); T = rnfisnorminit(bnf, p); rnfisnorm(T, 17) @eprog\noindent checks whether $17$ is a norm in the Galois extension $\Q(\beta) / \Q(\alpha)$, where $\alpha^3 + \alpha^2 - 2\alpha - 1 = 0$ and $\beta^2 + \alpha^2 + 2\alpha + 1 = 0$ (it is). pari-2.7.5/src/functions/number_fields/nfeltdivrem0000644000175000017500000000053111636712103020764 0ustar billbillFunction: nfeltdivrem Section: number_fields C-Name: nfdivrem Prototype: GGG Help: nfeltdivrem(nf,x,y): gives [q,r] such that r=x-by is small. Doc: given two elements $x$ and $y$ in \var{nf}, gives a two-element row vector $[q,r]$ such that $x=qy+r$, $q$ is an algebraic integer in $\var{nf}$, and the components of $r$ are reasonably small. pari-2.7.5/src/functions/number_fields/rnfpolred0000644000175000017500000000140512366172547020456 0ustar billbillFunction: rnfpolred Section: number_fields C-Name: rnfpolred Prototype: GGp Help: rnfpolred(nf,pol): given a pol with coefficients in nf, finds a list of relative polynomials defining some subfields, hopefully simpler. Doc: THIS FUNCTION IS OBSOLETE: use \tet{rnfpolredbest} instead. Relative version of \kbd{polred}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a list of relative polynomials defining some subfields, hopefully simpler and containing the original field. In the present version \vers, this is slower and less efficient than \kbd{rnfpolredbest}. \misctitle{Remark} this function is based on an incomplete reduction theory of lattices over number fields, implemented by \kbd{rnflllgram}, which deserves to be improved. pari-2.7.5/src/functions/number_fields/rnfinit0000644000175000017500000000740712413013143020117 0ustar billbillFunction: rnfinit Section: number_fields C-Name: rnfinit Prototype: GG Help: 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. Doc: $\var{nf}$ being a number field in \kbd{nfinit} format considered as base field, and \var{pol} a polynomial defining a relative extension over $\var{nf}$, this computes data to work in the relative extension. The main variable of \var{pol} must be of higher priority (see \secref{se:priority}) than that of $\var{nf}$, and the coefficients of \var{pol} must be in $\var{nf}$. The result is a row vector, whose components are technical. In the following description, we let $K$ be the base field defined by $\var{nf}$ and $L/K$ the large field associated to the \var{rnf}. Furthermore, we let $m = [K:\Q]$ the degree of the base field, $n = [L:K]$ the relative degree, $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. $\var{rnf}[1]$(\kbd{rnf.pol}) contains the relative polynomial \var{pol}. $\var{rnf}[2]$ contains the integer basis $[A,d]$ of $K$, as (integral) elements of $L/\Q$. More precisely, $A$ is a vector of polynomial with integer coefficients, $d$ is a denominator, and the integer basis is given by $A/d$. $\var{rnf}[3]$ (\kbd{rnf.disc}) is a two-component row vector $[\goth{d}(L/K),s]$ where $\goth{d}(L/K)$ is the relative ideal discriminant of $L/K$ and $s$ is the discriminant of $L/K$ viewed as an element of $K^*/(K^*)^2$, in other words it is the output of \kbd{rnfdisc}. $\var{rnf}[4]$(\kbd{rnf.index}) is the ideal index $\goth{f}$, i.e.~such that $d(pol)\Z_K=\goth{f}^2\goth{d}(L/K)$. $\var{rnf}[5]$ is currently unused. $\var{rnf}[6]$ is currently unused. $\var{rnf}[7]$ (\kbd{rnf.zk}) is the pseudo-basis $(A,I)$ for the maximal order $\Z_L$ as a $\Z_K$-module: $A$ is the relative integral pseudo basis expressed as polynomials (in the variable of $pol$) with polmod coefficients in $\var{nf}$, and the second component $I$ is the ideal list of the pseudobasis in HNF. $\var{rnf}[8]$ is the inverse matrix of the integral basis matrix, with coefficients polmods in $\var{nf}$. $\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 $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 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 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 working, but we advise to change the relative polynomial so that its root becomes $\beta + k \alpha$. Typical GP instructions would be \bprog [P,a,k] = rnfequation(K, pol, 1); if (k, pol = subst(pol, x, x - k*Mod(y, K.pol))); L = rnfinit(K, pol); @eprog $\var{rnf}[12]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available (which is rarely needed, hence would be too expensive to compute during the initial \kbd{rnfinit} call). pari-2.7.5/src/functions/number_fields/bnrclassnolist0000644000175000017500000000223712314242551021511 0ustar billbillFunction: bnrclassnolist Section: number_fields C-Name: bnrclassnolist Prototype: GG Help: bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives list of corresponding ray class numbers. Doc: $\var{bnf}$ being as output by \kbd{bnfinit}, and \var{list} being a list of moduli (with units) as output by \kbd{ideallist} or \kbd{ideallistarch}, outputs the list of the class numbers of the corresponding ray class groups. To compute a single class number, \tet{bnrclassno} is more efficient. \bprog ? bnf = bnfinit(x^2 - 2); ? L = ideallist(bnf, 100, 2); ? H = bnrclassnolist(bnf, L); ? H[98] %4 = [1, 3, 1] ? l = L[1][98]; ids = vector(#l, i, l[i].mod[1]) %5 = [[98, 88; 0, 1], [14, 0; 0, 7], [98, 10; 0, 1]] @eprog The weird \kbd{l[i].mod[1]}, is the first component of \kbd{l[i].mod}, i.e. the finite part of the conductor. (This is cosmetic: since by construction the Archimedean part is trivial, I do not want to see it). This tells us that the ray class groups modulo the ideals of norm 98 (printed as \kbd{\%5}) have respectively order $1$, $3$ and $1$. Indeed, we may check directly: \bprog ? bnrclassno(bnf, ids[2]) %6 = 3 @eprog pari-2.7.5/src/functions/number_fields/rnfkummer0000644000175000017500000000250211636712103020453 0ustar billbillFunction: rnfkummer Section: number_fields C-Name: rnfkummer Prototype: GDGD0,L,p Help: 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). Doc: \var{bnr} being as output by \kbd{bnrinit}, finds a relative equation for the class field corresponding to the module in \var{bnr} and the given congruence subgroup (the full ray class field if \var{subgp} is omitted). If $d$ is positive, outputs the list of all relative equations of degree $d$ contained in the ray class field defined by \var{bnr}, with the \emph{same} conductor as $(\var{bnr}, \var{subgp})$. \misctitle{Warning} This routine only works for subgroups of prime index. It uses Kummer theory, adjoining necessary roots of unity (it needs to compute a tough \kbd{bnfinit} here), and finds a generator via Hecke's characterization of ramification in Kummer extensions of prime degree. If your extension does not have prime degree, for the time being, you have to split it by hand as a tower / compositum of such extensions. pari-2.7.5/src/functions/number_fields/rnfidealnormabs0000644000175000017500000000107412366172547021633 0ustar billbillFunction: rnfidealnormabs Section: number_fields C-Name: rnfidealnormabs Prototype: GG Help: rnfidealnormabs(rnf,x): absolute norm of the ideal x. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the norm of the $x$ considered as an ideal of the absolute extension $L/\Q$. This is identical to \bprog idealnorm(rnf, rnfidealnormrel(rnf,x)) @eprog\noindent but faster. pari-2.7.5/src/functions/number_fields/rnfnormgroup0000644000175000017500000000211612405547147021215 0ustar billbillFunction: rnfnormgroup Section: number_fields C-Name: rnfnormgroup Prototype: GG Help: 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. Doc: \var{bnr} being a big ray class field as output by \kbd{bnrinit} and \var{pol} a relative polynomial defining an \idx{Abelian extension}, computes the norm group (alias Artin or Takagi group) corresponding to the Abelian extension of $\var{bnf}=$\kbd{bnr.bnf} defined by \var{pol}, where the module corresponding to \var{bnr} is assumed 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. pari-2.7.5/src/functions/number_fields/bnrclassno0000644000175000017500000000227712366172547020637 0ustar billbillFunction: bnrclassno Section: number_fields C-Name: bnrclassno0 Prototype: GDGDG Help: 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. Doc: let $A$, $B$, $C$ define a class field $L$ over a ground field $K$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, or \kbd{[\var{bnf}, \var{modulus}]}, or \kbd{[\var{bnf}, \var{modulus},\var{subgroup}]}, \secref{se:CFT}); this function returns the relative degree $[L:K]$. In particular if $A$ is a \var{bnf} (with units), and $B$ a modulus, this function returns the corresponding ray class number modulo $B$. One can input the associated \var{bid} (with generators if the subgroup $C$ is non trivial) for $B$ instead of the module itself, saving some time. This function is faster than \kbd{bnrinit} and should be used if only the ray class number is desired. See \tet{bnrclassnolist} if you need ray class numbers for all moduli less than some bound. Variant: Also available is \fun{GEN}{bnrclassno}{GEN bnf,GEN f} to compute the ray class number modulo~$f$. pari-2.7.5/src/functions/number_fields/nfroots0000644000175000017500000000261211636712103020141 0ustar billbillFunction: nfroots Section: number_fields C-Name: nfroots Prototype: DGG Help: nfroots({nf},x): roots of polynomial x belonging to nf (Q if omitted) without multiplicity. Doc: roots of the polynomial $x$ in the number field $\var{nf}$ given by \kbd{nfinit} without multiplicity (in $\Q$ if $\var{nf}$ is omitted). $x$ has coefficients in the number field (scalar, polmod, polynomial, column vector). The main variable of $\var{nf}$ must be of lower priority than that of $x$ (see \secref{se:priority}). However if the coefficients of the number field occur explicitly (as polmods) as coefficients of $x$, the variable of these polmods \emph{must} be the same as the main variable of $t$ (see \kbd{nffactor}). It is possible to input a defining polynomial for \var{nf} instead, but this is in general less efficient since parts of an \kbd{nf} structure will be computed internally. This is useful in two situations: when you don't need the \kbd{nf}, or when you can't compute its discriminant due to integer factorization difficulties. In the latter case, \tet{addprimes} is a possibility but a dangerous one: roots will probably be missed if the (true) field discriminant and an \kbd{addprimes} entry are strictly divisible by some prime. If you have such an unsafe \var{nf}, it is safer to input \kbd{nf.pol}. Variant: See also \fun{GEN}{nfrootsQ}{GEN x}, corresponding to $\kbd{nf} = \kbd{NULL}$. pari-2.7.5/src/functions/number_fields/rnfalgtobasis0000644000175000017500000000074111636712103021306 0ustar billbillFunction: rnfalgtobasis Section: number_fields C-Name: rnfalgtobasis Prototype: GG Help: rnfalgtobasis(rnf,x): relative version of nfalgtobasis, where rnf is a relative numberfield. Doc: expresses $x$ on the relative integral basis. Here, $\var{rnf}$ is a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an element of $L$ in absolute form, i.e. expressed as a polynomial or polmod with polmod coefficients, \emph{not} on the relative integral basis. pari-2.7.5/src/functions/number_fields/bnfsignunit0000644000175000017500000000167211636712103021002 0ustar billbillFunction: bnfsignunit Section: number_fields C-Name: signunits Prototype: G Help: bnfsignunit(bnf): matrix of signs of the real embeddings of the system of fundamental units found by bnfinit. Doc: $\var{bnf}$ being as output by \kbd{bnfinit}, this computes an $r_1\times(r_1+r_2-1)$ matrix having $\pm1$ components, giving the signs of the real embeddings of the fundamental units. The following functions compute generators for the totally positive units: \bprog /* exponents of totally positive units generators on bnf.tufu */ tpuexpo(bnf)= { my(S,d,K); S = bnfsignunit(bnf); d = matsize(S); S = matrix(d[1],d[2], i,j, if (S[i,j] < 0, 1,0)); S = concat(vectorv(d[1],i,1), S); \\ add sign(-1) K = lift(matker(S * Mod(1,2))); if (K, mathnfmodid(K, 2), 2*matid(d[1])) } /* totally positive units */ tpu(bnf)= { my(vu = bnf.tufu, ex = tpuexpo(bnf)); vector(#ex-1, i, factorback(vu, ex[,i+1])) \\ ex[,1] is 1 } @eprog pari-2.7.5/src/functions/number_fields/rnfcharpoly0000644000175000017500000000110112314242551020765 0ustar billbillFunction: rnfcharpoly Section: number_fields C-Name: rnfcharpoly Prototype: GGGDn Help: 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). Doc: characteristic polynomial of $a$ over $\var{nf}$, where $a$ belongs to the algebra defined by $T$ over $\var{nf}$, i.e.~$\var{nf}[X]/(T)$. Returns a polynomial in variable $v$ ($x$ by default). \bprog ? nf = nfinit(y^2+1); ? rnfcharpoly(nf, x^2+y*x+1, x+y) %2 = x^2 + Mod(-y, y^2 + 1)*x + 1 @eprog pari-2.7.5/src/functions/number_fields/nfeltmul0000644000175000017500000000033711636712103020277 0ustar billbillFunction: nfeltmul Section: number_fields C-Name: nfmul Prototype: GGG Help: nfmul(nf,x,y): element x.y in nf. Doc: given two elements $x$ and $y$ in \var{nf}, computes their product $x*y$ in the number field $\var{nf}$. pari-2.7.5/src/functions/number_fields/galoisinit0000644000175000017500000000743712314242551020622 0ustar billbillFunction: galoisinit Section: number_fields C-Name: galoisinit Prototype: GDG Help: 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). Description: (gen, ?int):gal galoisinit($1, $2) Doc: computes the Galois group and all necessary information for computing the fixed fields of the Galois extension $K/\Q$ where $K$ is the number field defined by $\var{pol}$ (monic irreducible polynomial in $\Z[X]$ or a number field as output by \tet{nfinit}). The extension $K/\Q$ must be Galois with Galois group ``weakly'' super-solvable, see below; returns 0 otherwise. Hence this permits to quickly check whether a polynomial of order strictly less than $36$ is Galois or not. The algorithm used is an improved version of the paper ``An efficient algorithm for the computation of Galois automorphisms'', Bill Allombert, Math.~Comp, vol.~73, 245, 2001, pp.~359--375. A group $G$ is said to be ``weakly'' super-solvable if there exists a normal series $\{1\} = H_0 \triangleleft H_1 \triangleleft \cdots \triangleleft H_{n-1} \triangleleft H_n$ such that each $H_i$ is normal in $G$ and for $i1$). 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)) %3 = 2 ? p1 = L[1]; p2 = L[2]; ? [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 %5 = [1, 2] ? p1.gen %6 = [5, [2, 1, 0]~] ? nfbasistoalg(K, %[2]) \\ a uniformizer for p1 %7 = Mod(x + 2, x^3 - 2) @eprog pari-2.7.5/src/functions/number_fields/rnfeltdown0000644000175000017500000000161512366172547020650 0ustar billbillFunction: rnfeltdown Section: number_fields C-Name: rnfeltdown Prototype: GG Help: rnfeltdown(rnf,x): expresses x on the base field if possible; returns an error otherwise. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial or polmod with polmod coefficients, computes $x$ as an element of $K$ as a polmod, assuming $x$ is in $K$ (otherwise a domain error occurs). \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltdown(L, Mod(x^2, L.pol)) %3 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(y, x^2-y)) %4 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(y,K.pol)) %5 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(x, L.pol)) *** at top-level: rnfeltdown(L,Mod(x,x *** ^-------------------- *** rnfeltdown: domain error in rnfeltdown: element not in the base field @eprog pari-2.7.5/src/functions/number_fields/galoisisnormal0000644000175000017500000000105711636712103021474 0ustar billbillFunction: galoisisnormal Section: number_fields C-Name: galoisisnormal Prototype: lGG Help: 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. Doc: \var{gal} being as output by \kbd{galoisinit}, and \var{subgrp} a subgroup of \var{gal} as output by \kbd{galoissubgroups},return $1$ if \var{subgrp} is a normal subgroup of \var{gal}, else return 0. This command also accepts subgroups returned by \kbd{galoissubgroups}. pari-2.7.5/src/functions/number_fields/idealtwoelt0000644000175000017500000000243212366172547021001 0ustar billbillFunction: idealtwoelt Section: number_fields C-Name: idealtwoelt0 Prototype: GGDG Help: 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. Doc: computes a two-element representation of the ideal $x$ in the number field $\var{nf}$, combining a random search and an approximation theorem; $x$ is an ideal in any form (possibly an extended ideal, whose principal part is ignored) \item When called as \kbd{idealtwoelt(nf,x)}, the result is a row vector $[a,\alpha]$ with two components such that $x=a\Z_K+\alpha\Z_K$ and $a$ is chosen to be the positive generator of $x\cap\Z$, unless $x$ was given as a principal ideal (in which case we may choose $a = 0$). The algorithm uses a fast lazy factorization of $x\cap \Z$ and runs in randomized polynomial time. \item When called as \kbd{idealtwoelt(nf,x,a)} with an explicit non-zero $a$ supplied as third argument, the function assumes that $a \in x$ and returns $\alpha\in x$ such that $x = a\Z_K + \alpha\Z_K$. Note that we must factor $a$ in this case, and the algorithm is generally much slower than the default variant. Variant: Also available are \fun{GEN}{idealtwoelt}{GEN nf, GEN x} and \fun{GEN}{idealtwoelt2}{GEN nf, GEN x, GEN a}. pari-2.7.5/src/functions/number_fields/idealdiv0000644000175000017500000000173611636712103020236 0ustar billbillFunction: idealdiv Section: number_fields C-Name: idealdiv0 Prototype: GGGD0,L, Help: 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). Description: (gen, gen, gen, ?0):gen idealdiv($1, $2, $3) (gen, gen, gen, 1):gen idealdivexact($1, $2, $3) (gen, gen, gen, #small):gen $"invalid flag in idealdiv" (gen, gen, gen, small):gen idealdiv0($1, $2, $3, $4) Doc: quotient $x\cdot y^{-1}$ of the two ideals $x$ and $y$ in the number field $\var{nf}$. The result is given in HNF. If $\fl$ is non-zero, the quotient $x \cdot y^{-1}$ is assumed to be an integral ideal. This can be much faster when the norm of the quotient is small even though the norms of $x$ and $y$ are large. Variant: Also available are \fun{GEN}{idealdiv}{GEN nf, GEN x, GEN y} ($\fl=0$) and \fun{GEN}{idealdivexact}{GEN nf, GEN x, GEN y} ($\fl=1$). pari-2.7.5/src/functions/number_fields/nfisideal0000644000175000017500000000036311636712103020406 0ustar billbillFunction: nfisideal Section: number_fields C-Name: isideal Prototype: lGG Help: nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not. Doc: returns 1 if $x$ is an ideal in the number field $\var{nf}$, 0 otherwise. pari-2.7.5/src/functions/number_fields/bnfcertify0000644000175000017500000000265312366172547020624 0ustar billbillFunction: bnfcertify Section: number_fields C-Name: bnfcertify0 Prototype: lGD0,L, Help: 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). Doc: $\var{bnf}$ being as output by \kbd{bnfinit}, checks whether the result is correct, i.e.~whether it is possible to remove the assumption of the Generalized Riemann Hypothesis\sidx{GRH}. It is correct if and only if the answer is 1. If it is incorrect, the program may output some error message, or loop indefinitely. You can check its progress by increasing the debug level. The \var{bnf} structure must contain the fundamental units: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K) *** at top-level: K=bnfinit(x^3+2^2^3+1);bnfcertify(K) *** ^------------- *** bnfcertify: missing units in bnf. ? K = bnfinit(x^3+2^2^3+1, 1); \\ include units ? bnfcertify(K) %3 = 1 @eprog If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general); likewise, the computed units may form a subgroup of the full unit group. In this variant, the units are no longer needed: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K, 1) %4 = 1 @eprog Variant: Also available is \fun{GEN}{bnfcertify}{GEN bnf} ($\fl=0$). pari-2.7.5/src/functions/number_fields/rnfelttrace0000644000175000017500000000100412366172547020767 0ustar billbillFunction: rnfelttrace Section: number_fields C-Name: rnfelttrace Prototype: GG Help: rnfelttrace(rnf,x): returns the relative trace N_{L/K}(x), as an element of K Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative trace $N_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfelttrace(L, Mod(x, L.pol)) %2 = 0 ? rnfelttrace(L, 2) %3 = 4 ? rnfelttrace(L, Mod(x, x^2-y)) @eprog pari-2.7.5/src/functions/number_fields/rnfidealmul0000644000175000017500000000063211636712103020751 0ustar billbillFunction: rnfidealmul Section: number_fields C-Name: rnfidealmul Prototype: GGG Help: rnfidealmul(rnf,x,y): relative version of idealmul, where rnf is a relative numberfield. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ and $y$ being ideals of the relative extension $L/K$ given by pseudo-matrices, outputs the ideal product, again as a relative ideal. pari-2.7.5/src/functions/number_fields/idealred0000644000175000017500000000553611636712103020230 0ustar billbillFunction: idealred Section: number_fields C-Name: idealred0 Prototype: GGDG Help: idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along direction v, in HNF. Doc: \idx{LLL} reduction of the ideal $I$ in the number field \var{nf}, along the direction $v$. The $v$ parameter is best left omitted, but if it is present, it must be an $\kbd{nf.r1} + \kbd{nf.r2}$-component vector of \emph{non-negative} integers. (What counts is the relative magnitude of the entries: if all entries are equal, the effect is the same as if the vector had been omitted.) This function finds a ``small'' $a$ in $I$ (see the end for technical details). The result is the Hermite normal form of the ``reduced'' ideal $J = r I/a$, where $r$ is the unique rational number such that $J$ is integral and primitive. (This is usually not a reduced ideal in the sense of \idx{Buchmann}.) \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K,5)[1]; ? idealred(K, P) %3 = [1 0] [0 1] @eprog\noindent More often than not, a \idx{principal ideal} yields the unit ideal as above. This is a quick and dirty way to check if ideals are principal, but it is not a necessary condition: a non-trivial result does not prove that the ideal is non-principal. For guaranteed results, see \kbd{bnfisprincipal}, which requires the computation of a full \kbd{bnf} structure. If the input is an extended ideal $[I,s]$, the output is $[J,sa/r]$; this way, one can keep track of the principal ideal part: \bprog ? idealred(K, [P, 1]) %5 = [[1, 0; 0, 1], [-2, 1]~] @eprog\noindent meaning that $P$ is generated by $[-2, 1]~$. The number field element in the extended part is an algebraic number in any form \emph{or} a factorization matrix (in terms of number field elements, not ideals!). In the latter case, elements stay in factored form, which is a convenient way to avoid coefficient explosion; see also \tet{idealpow}. \misctitle{Technical note} The routine computes an LLL-reduced basis for the lattice $I$ equipped with the quadratic form $$|| x ||_v^2 = \sum_{i=1}^{r_1+r_2} 2^{v_i}\varepsilon_i|\sigma_i(x)|^2,$$ where as usual the $\sigma_i$ are the (real and) complex embeddings and $\varepsilon_i = 1$, resp.~$2$, for a real, resp.~complex place. The element $a$ is simply the first vector in the LLL basis. The only reason you may want to try to change some directions and set some $v_i\neq 0$ is to randomize the elements found for a fixed ideal, which is heuristically useful in index calculus algorithms like \tet{bnfinit} and \tet{bnfisprincipal}. \misctitle{Even more technical note} In fact, the above is a white lie. We do not use $||\cdot||_v$ exactly but a rescaled rounded variant which gets us faster and simpler LLLs. There's no harm since we are not using any theoretical property of $a$ after all, except that it belongs to $I$ and is ``expected to be small''. pari-2.7.5/src/functions/number_theoretical/0000755000175000017500000000000012613365633017570 5ustar billbillpari-2.7.5/src/functions/number_theoretical/istotient0000644000175000017500000000067212314242551021531 0ustar billbillFunction: istotient Section: number_theoretical C-Name: istotient Prototype: lGD& Help: 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. Doc: true (1) if $x = \phi(n)$ for some integer $n$, false (0) if not. \bprog ? istotient(14) %1 = 0 ? istotient(100) %2 = 0 @eprog If $N$ is given, set $N = n$ as well. \bprog ? istotient(4, &n) %1 = 1 ? n %2 = 10 @eprog pari-2.7.5/src/functions/number_theoretical/quaddisc0000644000175000017500000000033111636712103021275 0ustar billbillFunction: quaddisc 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$. pari-2.7.5/src/functions/number_theoretical/bigomega0000644000175000017500000000056312314242551021260 0ustar billbillFunction: bigomega Section: number_theoretical C-Name: bigomega Prototype: lG Help: bigomega(x): number of prime divisors of x, counted with multiplicity. Doc: number of prime divisors of the integer $|x|$ counted with multiplicity: \bprog ? factor(392) %1 = [2 3] [7 2] ? bigomega(392) %2 = 5; \\ = 3+2 ? omega(392) %3 = 2; \\ without multiplicity @eprog pari-2.7.5/src/functions/number_theoretical/bestappr0000644000175000017500000000414312314242551021324 0ustar billbillFunction: bestappr Section: number_theoretical C-Name: bestappr Prototype: GDG Help: 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. Doc: using variants of the extended Euclidean algorithm, returns a rational approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, return the best approximation affordable given the input accuracy; if you are looking for true rational numbers, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a positive real scalar (impose $0 < b \leq B$). \item If $x$ is a \typ{REAL} or a \typ{FRAC}, this function uses continued fractions. \bprog ? bestappr(Pi, 100) %1 = 22/7 ? bestappr(0.1428571428571428571428571429) %2 = 1/7 ? bestappr([Pi, sqrt(2) + 'x], 10^3) %3 = [355/113, x + 1393/985] @eprog By definition, $a/b$ is the best rational approximation to $x$ if $|b x - a| < |v x - u|$ for all integers $(u,v)$ with $0 < v \leq B$. (Which implies that $n/d$ is a convergent of the continued fraction of $x$.) \item If $x$ is a \typ{INTMOD} modulo $N$ or a \typ{PADIC} of precision $N = p^k$, this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational number $a/b$ in coprime integers $|a| < N/2B$ and $b\leq B$ which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it of the order of $\sqrt{N/2}$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? bestappr(Mod(18526731858, 11^10)) %1 = 1/7 ? bestappr(Mod(18526731858, 11^20)) %2 = [] ? bestappr(3 + 5 + 3*5^2 + 5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7)) %2 = -1/3 @eprog\noindent In most concrete uses, $B$ is a prime power and we performed Hensel lifting to obtain $x$. The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, return $[]$. pari-2.7.5/src/functions/number_theoretical/bestapprPade0000644000175000017500000000360212314242551022115 0ustar billbillFunction: bestapprPade Section: number_theoretical C-Name: bestapprPade Prototype: GD-1,L, Help: 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. Doc: using variants of the extended Euclidean algorithm, returns a rational function approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, return the best approximation affordable given the input accuracy; if you are looking for true rational functions, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a non-negative real (impose $0 \leq \text{degree}(b) \leq B$). \item If $x$ is a \typ{RFRAC} or \typ{SER}, this function uses continued fractions. \bprog ? bestapprPade((1-x^11)/(1-x)+O(x^11)) %1 = 1/(-x + 1) ? bestapprPade([1/(1+x+O(x^10)), (x^3-2)/(x^3+1)], 1) %2 = [1/(x + 1), -2] @eprog \item If $x$ is a \typ{POLMOD} modulo $N$ or a \typ{SER} of precision $N = t^k$, this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational function $a/b$ in coprime polynomials, with $\text{degree}(b)\leq B$ which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it of the order of $N/2$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? bestapprPade(Mod(1+x+x^2+x^3+x^4, x^4-2)) %1 = (2*x - 1)/(x - 1) ? % * Mod(1,x^4-2) %2 = Mod(x^3 + x^2 + x + 3, x^4 - 2) ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^9)) %2 = [] ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^10)) %3 = (2*x^4 + x^3 - x - 1)/(-x^5 + x^3 + x^2 - 1) @eprog\noindent The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, return $[]$. pari-2.7.5/src/functions/number_theoretical/addprimes0000644000175000017500000000135511636712103021457 0ustar billbillFunction: addprimes Section: number_theoretical C-Name: addprimes Prototype: DG Help: 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! Doc: adds the integers contained in the vector $x$ (or the single integer $x$) to a special table of ``user-defined primes'', and returns that table. Whenever \kbd{factor} is subsequently called, it will trial divide by the elements in this table. If $x$ is empty or omitted, just returns the current list of extra primes. The entries in $x$ must be primes: there is no internal check, even if the \tet{factor_proven} default is set. To remove primes from the list use \kbd{removeprimes}. pari-2.7.5/src/functions/number_theoretical/qfbsolve0000644000175000017500000000162411636712103021327 0ustar billbillFunction: qfbsolve Section: number_theoretical C-Name: qfbsolve Prototype: GG Help: 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. Doc: Solve the equation $Q(x,y)=p$ over the integers, where $Q$ is a binary quadratic form and $p$ a prime number. Return $[x,y]$ as a two-components vector, or zero if there is no solution. Note that this function returns only one solution and not all the solutions. Let $D = \disc Q$. The algorithm used runs in probabilistic polynomial time in $p$ (through the computation of a square root of $D$ modulo $p$); it is polynomial time in $D$ if $Q$ is imaginary, but exponential time if $Q$ is real (through the computation of a full cycle of reduced forms). In the latter case, note that \tet{bnfisprincipal} provides a solution in heuristic subexponential time in $D$ assuming the GRH. pari-2.7.5/src/functions/number_theoretical/fibonacci0000644000175000017500000000026011636712103021416 0ustar billbillFunction: fibonacci Section: number_theoretical C-Name: fibo Prototype: L Help: fibonacci(x): fibonacci number of index x (x C-integer). Doc: $x^{\text{th}}$ Fibonacci number. pari-2.7.5/src/functions/number_theoretical/qfbnupow0000644000175000017500000000056011636712103021345 0ustar billbillFunction: qfbnupow Section: number_theoretical C-Name: nupow Prototype: GG Help: qfbnupow(x,n): n-th power of primitive positive definite quadratic form x using nucomp and nudupl. Doc: $n$-th power of the primitive positive definite binary quadratic form $x$ using \idx{Shanks}'s NUCOMP and NUDUPL algorithms (see \kbd{qfbnucomp}, in particular the final warning). pari-2.7.5/src/functions/number_theoretical/ffinit0000644000175000017500000000127712366172547021006 0ustar billbillFunction: ffinit Section: number_theoretical C-Name: ffinit Prototype: GLDn Help: ffinit(p,n,{v='x}): monic irreducible polynomial of degree n over F_p[v]. Description: (int, small, ?var):pol ffinit($1, $2, $3) Doc: computes a monic polynomial of degree $n$ which is irreducible over $\F_p$, where $p$ is assumed to be prime. This function uses a fast variant of Adleman and Lenstra's algorithm. It is useful in conjunction with \tet{ffgen}; for instance if \kbd{P = ffinit(3,2)}, you can represent elements in $\F_{3^2}$ in term of \kbd{g = ffgen(P,'t)}. This can be abbreviated as \kbd{g = ffgen(3\pow2, 't)}, where the defining polynomial $P$ can be later recovered as \kbd{g.mod}. pari-2.7.5/src/functions/number_theoretical/ispolygonal0000644000175000017500000000073712314242551022051 0ustar billbillFunction: ispolygonal Section: number_theoretical C-Name: ispolygonal Prototype: lGGD& Help: 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. Doc: true (1) if the integer $x$ is an s-gonal number, false (0) if not. The parameter $s > 2$ must be a \typ{INT}. If $N$ is given, set it to $n$ if $x$ is the $n$-th $s$-gonal number. \bprog ? ispolygonal(36, 3, &N) %1 = 1 ? N @eprog pari-2.7.5/src/functions/number_theoretical/znstar0000644000175000017500000000215512366172547021044 0ustar billbillFunction: znstar Section: number_theoretical C-Name: znstar Prototype: G Help: znstar(n): 3-component vector v, giving the structure of (Z/nZ)^*. v[1] is the order (i.e. eulerphi(n)), v[2] is a vector of cyclic components, and v[3] is a vector giving the corresponding generators. Doc: gives the structure of the multiplicative group $(\Z/n\Z)^*$ as a 3-component row vector $v$, where $v[1]=\phi(n)$ is the order of that group, $v[2]$ is a $k$-component row-vector $d$ of integers $d[i]$ such that $d[i]>1$ and $d[i]\mid d[i-1]$ for $i \ge 2$ and $(\Z/n\Z)^* \simeq \prod_{i=1}^k(\Z/d[i]\Z)$, and $v[3]$ is a $k$-component row vector giving generators of the image of the cyclic groups $\Z/d[i]\Z$. \bprog ? G = znstar(40) %1 = [16, [4, 2, 2], [Mod(17, 40), Mod(21, 40), Mod(11, 40)]] ? G.no \\ eulerphi(40) %2 = 16 ? G.cyc \\ cycle structure %3 = [4, 2, 2] ? G.gen \\ generators for the cyclic components %4 = [Mod(17, 40), Mod(21, 40), Mod(11, 40)] ? apply(znorder, G.gen) %5 = [4, 2, 2] @eprog\noindent According to the above definitions, \kbd{znstar(0)} is \kbd{[2, [2], [-1]]}, corresponding to $\Z^*$. pari-2.7.5/src/functions/number_theoretical/qfbpowraw0000644000175000017500000000052211636712103021512 0ustar billbillFunction: qfbpowraw Section: number_theoretical C-Name: qfbpowraw Prototype: GL Help: qfbpowraw(x,n): n-th power without reduction of the binary quadratic form x. Doc: $n$-th power of the binary quadratic form $x$, computed without doing any \idx{reduction} (i.e.~using \kbd{qfbcompraw}). Here $n$ must be non-negative and $n<2^{31}$. pari-2.7.5/src/functions/number_theoretical/primepi0000644000175000017500000000067212314242551021154 0ustar billbillFunction: primepi Section: number_theoretical C-Name: primepi Prototype: G Help: primepi(x): the prime counting function pi(x) = #{p <= x, p prime}. Description: (gen):int primepi($1) Doc: the prime counting function. Returns the number of primes $p$, $p \leq x$. \bprog ? primepi(10) %1 = 4; ? primes(5) %2 = [2, 3, 5, 7, 11] ? primepi(10^11) %3 = 4118054813 @eprog\noindent Uses checkpointing and a naive $O(x)$ algorithm. pari-2.7.5/src/functions/number_theoretical/sqrtint0000644000175000017500000000067112366172547021230 0ustar billbillFunction: sqrtint Section: number_theoretical C-Name: sqrtint Prototype: G Help: sqrtint(x): integer square root of x, where x is a non-negative integer. Description: (gen):int sqrtint($1) Doc: returns the integer square root of $x$, i.e. the largest integer $y$ such that $y^2 \leq x$, where $x$ a non-negative integer. \bprog ? N = 120938191237; sqrtint(N) %1 = 347761 ? sqrt(N) %2 = 347761.68741970412747602130964414095216 @eprog pari-2.7.5/src/functions/number_theoretical/qfbclassno0000644000175000017500000000477112405547147021660 0ustar billbillFunction: qfbclassno Section: number_theoretical 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}. \misctitle{Warning} Contrary to what its name implies, this routine does not compute the number of classes of binary primitive forms of discriminant $D$, which is equal to the \emph{narrow} class number. The two notions are the same when $D < 0$ or the fundamental unit $\varepsilon$ has negative norm; when $D > 0$ and $N\varepsilon > 0$, the number of classes of forms is twice the ordinary class number. This is a problem which we cannot fix for backward compatibility reasons. Use the following routine if you are only interested in the number of classes of forms: \bprog QFBclassno(D) = qfbclassno(D) * if (D < 0 || norm(quadunit(D)) < 0, 1, 2) @eprog\noindent Here are a few examples: \bprog ? qfbclassno(400000028) time = 3,140 ms. %1 = 1 ? quadclassunit(400000028).no time = 20 ms. \\@com{ much faster} %2 = 1 ? qfbclassno(-400000028) time = 0 ms. %3 = 7253 \\@com{ correct, and fast enough} ? quadclassunit(-400000028).no time = 0 ms. %4 = 7253 @eprog\noindent See also \kbd{qfbhclassno}. Variant: The following functions are also available: \fun{GEN}{classno}{GEN D} ($\fl = 0$) \fun{GEN}{classno2}{GEN D} ($\fl = 1$). \noindent Finally \fun{GEN}{hclassno}{GEN D} computes the class number of an imaginary quadratic field by counting reduced forms, an $O(|D|)$ algorithm. pari-2.7.5/src/functions/number_theoretical/dirmul0000644000175000017500000000126112366172547021014 0ustar billbillFunction: dirmul Section: number_theoretical C-Name: dirmul Prototype: GG Help: dirmul(x,y): multiplication of the Dirichlet series x by the Dirichlet series y. Doc: $x$ and $y$ being vectors of perhaps different lengths representing the \idx{Dirichlet series} $\sum_n x_n n^{-s}$ and $\sum_n y_n n^{-s}$, computes the product of $x$ by $y$, again as a vector. \bprog ? dirmul(vector(10,n,1), vector(10,n,moebius(n))) %1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] @eprog\noindent The product length is the minimum of $\kbd{\#}x\kbd{*}v(y)$ and $\kbd{\#}y\kbd{*}v(x)$, where $v(x)$ is the index of the first non-zero coefficient. \bprog ? dirmul([0,1], [0,1]); %2 = [0, 0, 0, 1] @eprog pari-2.7.5/src/functions/number_theoretical/factorcantor0000644000175000017500000000133111636712103022166 0ustar billbillFunction: factorcantor Section: number_theoretical C-Name: factcantor Prototype: GG Help: factorcantor(x,p): factorization mod p of the polynomial x using Cantor-Zassenhaus. Doc: factors the polynomial $x$ modulo the prime $p$, using distinct degree plus \idx{Cantor-Zassenhaus}\sidx{Zassenhaus}. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix, the first column being the irreducible polynomials dividing $x$, and the second the exponents. If you want only the \emph{degrees} of the irreducible polynomials (for example for computing an $L$-function), use $\kbd{factormod}(x,p,1)$. Note that the \kbd{factormod} algorithm is usually faster than \kbd{factorcantor}. pari-2.7.5/src/functions/number_theoretical/contfrac0000644000175000017500000000556411636712103021314 0ustar billbillFunction: contfrac Section: number_theoretical C-Name: contfrac0 Prototype: GDGD0,L, Help: 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. Doc: returns the row vector whose components are the partial quotients of the \idx{continued fraction} expansion of $x$. In other words, a result $[a_0,\dots,a_n]$ means that $x \approx a_0+1/(a_1+\dots+1/a_n)$. The output is normalized so that $a_n \neq 1$ (unless we also have $n = 0$). The number of partial quotients $n+1$ is limited by \kbd{nmax}. If \kbd{nmax} is omitted, the expansion stops at the last significant partial quotient. \bprog ? \p19 realprecision = 19 significant digits ? contfrac(Pi) %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2] ? contfrac(Pi,, 3) \\ n = 2 %2 = [3, 7, 15] @eprog\noindent $x$ can also be a rational function or a power series. If a vector $b$ is supplied, the numerators are equal to the coefficients of $b$, instead of all equal to $1$ as above; more precisely, $x \approx (1/b_0)(a_0+b_1/(a_1+\dots+b_n/a_n))$; for a numerical continued fraction ($x$ real), the $a_i$ are integers, as large as possible; if $x$ is a rational function, they are polynomials with $\deg a_i = \deg b_i + 1$. The length of the result is then equal to the length of $b$, unless the next partial quotient cannot be reliably computed, in which case the expansion stops. This happens when a partial remainder is equal to zero (or too small compared to the available significant digits for $x$ a \typ{REAL}). A direct implementation of the numerical continued fraction \kbd{contfrac(x,b)} described above would be \bprog \\ "greedy" generalized continued fraction cf(x, b) = { my( a= vector(#b), t ); x *= b[1]; for (i = 1, #b, a[i] = floor(x); t = x - a[i]; if (!t || i == #b, break); x = b[i+1] / t; ); a; } @eprog\noindent There is some degree of freedom when choosing the $a_i$; the program above can easily be modified to derive variants of the standard algorithm. In the same vein, although no builtin function implements the related \idx{Engel expansion} (a special kind of \idx{Egyptian fraction} decomposition: $x = 1/a_1 + 1/(a_1a_2) + \dots$ ), it can be obtained as follows: \bprog \\ n terms of the Engel expansion of x engel(x, n = 10) = { my( u = x, a = vector(n) ); for (k = 1, n, a[k] = ceil(1/u); u = u*a[k] - 1; if (!u, break); ); a } @eprog \misctitle{Obsolete hack} (don't use this): If $b$ is an integer, \var{nmax} is ignored and the command is understood as \kbd{contfrac($x,, b$)}. Variant: Also available are \fun{GEN}{gboundcf}{GEN x, long nmax}, \fun{GEN}{gcf}{GEN x} and \fun{GEN}{gcf2}{GEN b, GEN x}. pari-2.7.5/src/functions/number_theoretical/content0000644000175000017500000000200711636712103021154 0ustar billbillFunction: content Section: number_theoretical C-Name: content Prototype: G Help: content(x): gcd of all the components of x, when this makes sense. Doc: computes the gcd of all the coefficients of $x$, when this gcd makes sense. This is the natural definition if $x$ is a polynomial (and by extension a power series) or a vector/matrix. This is in general a weaker notion than the \emph{ideal} generated by the coefficients: \bprog ? content(2*x+y) %1 = 1 \\ = gcd(2,y) over Q[y] @eprog If $x$ is a scalar, this simply returns the absolute value of $x$ if $x$ is rational (\typ{INT} or \typ{FRAC}), and either $1$ (inexact input) or $x$ (exact input) otherwise; the result should be identical to \kbd{gcd(x, 0)}. The content of a rational function is the ratio of the contents of the numerator and the denominator. In recursive structures, if a matrix or vector \emph{coefficient} $x$ appears, the gcd is taken not with $x$, but with its content: \bprog ? content([ [2], 4*matid(3) ]) %1 = 2 @eprog pari-2.7.5/src/functions/number_theoretical/isprimepower0000644000175000017500000000073012314242551022227 0ustar billbillFunction: isprimepower Section: number_theoretical C-Name: isprimepower Prototype: lGD& Help: 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. Doc: if $x = p^k$ is a prime power ($p$ prime, $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$. pari-2.7.5/src/functions/number_theoretical/qfbprimeform0000644000175000017500000000117711636712103022202 0ustar billbillFunction: qfbprimeform Section: number_theoretical C-Name: primeform Prototype: GGp Help: qfbprimeform(x,p): returns the prime form of discriminant x, whose first coefficient is p. Doc: prime binary quadratic form of discriminant $x$ whose first coefficient is $p$, where $|p|$ is a prime number. By abuse of notation, $p = \pm 1$ is also valid and returns the unit form. Returns an error if $x$ is not a quadratic residue mod $p$, or if $x < 0$ and $p < 0$. (Negative definite \typ{QFI} are not implemented.) In the case where $x>0$, the ``distance'' component of the form is set equal to zero according to the current precision. pari-2.7.5/src/functions/number_theoretical/znprimroot0000644000175000017500000000126212366172547021744 0ustar billbillFunction: znprimroot Section: number_theoretical C-Name: znprimroot Prototype: G Help: znprimroot(n): returns a primitive root of n when it exists. Doc: returns a primitive root (generator) of $(\Z/n\Z)^*$, whenever this latter group is cyclic ($n = 4$ or $n = 2p^k$ or $n = p^k$, where $p$ is an odd prime and $k \geq 0$). If the group is not cyclic, the result is undefined. If $n$ is a prime power, then the smallest positive primitive root is returned. This may not be true for $n = 2p^k$, $p$ odd. Note that this function requires factoring $p-1$ for $p$ as above, in order to determine the exact order of elements in $(\Z/n\Z)^*$: this is likely to be costly if $p$ is large. pari-2.7.5/src/functions/number_theoretical/factor0000644000175000017500000001422712413013143020757 0ustar billbillFunction: factor Section: number_theoretical C-Name: gp_factor0 Prototype: GDG Help: 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. Description: (int, ?-1):vec Z_factor($1) (gen, ?-1):vec factor($1) (gen, small):vec factor0($1, $2) Doc: general factorization function, where $x$ is a rational (including integers), a complex number with rational real and imaginary parts, or a rational function (including polynomials). The result is a two-column matrix: the first contains the irreducibles dividing $x$ (rational or Gaussian primes, irreducible polynomials), and the second the exponents. By convention, $0$ is factored as $0^1$. \misctitle{$\Q$ and $\Q(i)$} See \tet{factorint} for more information about the algorithms used. The rational or Gaussian primes are in fact \var{pseudoprimes} (see \kbd{ispseudoprime}), a priori not rigorously proven primes. In fact, any factor which is $\leq 2^{64}$ (whose norm is $\leq 2^{64}$ for an irrational Gaussian prime) is a genuine prime. Use \kbd{isprime} to prove primality of other factors, as in \bprog ? fa = factor(2^2^7 + 1) %1 = [59649589127497217 1] [5704689200685129054721 1] ? isprime( fa[,1] ) %2 = [1, 1]~ \\ both entries are proven primes @eprog\noindent Another possibility is to set the global default \tet{factor_proven}, which will perform a rigorous primality proof for each pseudoprime factor. A \typ{INT} argument \var{lim} can be added, meaning that we look only for prime factors $p < \var{lim}$. The limit \var{lim} must be non-negative. In this case, all but the last factor are proven primes, but the remaining factor may actually be a proven composite! If the remaining factor is less than $\var{lim}^2$, then it is prime. \bprog ? factor(2^2^7 +1, 10^5) %3 = [340282366920938463463374607431768211457 1] @eprog\noindent \misctitle{Deprecated feature} Setting $\var{lim}=0$ is the same as setting it to $\kbd{primelimit} + 1$. Don't use this: it is unwise to rely on global variables when you can specify an explicit argument. \smallskip This routine uses trial division and perfect power tests, and should not be used for huge values of \var{lim} (at most $10^9$, say): \kbd{factorint(, 1 + 8)} will in general be faster. The latter does not guarantee that all small prime factors are found, but it also finds larger factors, and in a much more efficient way. \bprog ? F = (2^2^7 + 1) * 1009 * 100003; factor(F, 10^5) \\ fast, incomplete time = 0 ms. %4 = [1009 1] [34029257539194609161727850866999116450334371 1] ? factor(F, 10^9) \\ very slow time = 6,892 ms. %6 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F, 1+8) \\ much faster, all small primes were found time = 12 ms. %7 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factor(F) \\ complete factorisation time = 112 ms. %8 = [1009 1] [100003 1] [59649589127497217 1] [5704689200685129054721 1] @eprog\noindent Over $\Q$, the prime factors are sorted in increasing order. \misctitle{Rational functions} The polynomials or rational functions to be factored must have scalar coefficients. In particular PARI does not know how to factor \emph{multivariate} polynomials. The following domains are currently supported: $\Q$, $\R$, $\C$, $\Q_p$, finite fields and number fields. See \tet{factormod} and \tet{factorff} for the algorithms used over finite fields, \tet{factornf} for the algorithms over number fields. Over $\Q$, \idx{van Hoeij}'s method is used, which is able to cope with hundreds of modular factors. The routine guesses a sensible ring over which to factor: the smallest ring containing all coefficients, taking into account quotient structures induced by \typ{INTMOD}s and \typ{POLMOD}s (e.g.~if a coefficient in $\Z/n\Z$ is known, all rational numbers encountered are first mapped to $\Z/n\Z$; different moduli will produce an error). Factoring modulo a non-prime number is not supported; to factor in $\Q_p$, use \typ{PADIC} coefficients not \typ{INTMOD} modulo $p^n$. \bprog ? T = x^2+1; ? factor(T); \\ over Q ? factor(T*Mod(1,3)) \\ over F_3 ? factor(T*ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2} ? factor(T*Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again ? factor(T*(1 + O(3^6)) \\ over Q_3, precision 6 ? factor(T*1.) \\ over R, current precision ? factor(T*(1.+0.*I)) \\ over C ? factor(T*Mod(1, y^3-2)) \\ over Q(2^{1/3}) @eprog\noindent In most cases, it is clearer and simpler to call an explicit variant than to rely on the generic \kbd{factor} function and the above detection mechanism: \bprog ? factormod(T, 3) \\ over F_3 ? factorff(T, 3, t^2+t+2)) \\ over F_{3^2} ? factorpadic(T, 3,6) \\ over Q_3, precision 6 ? nffactor(y^3-2, T) \\ over Q(2^{1/3}) ? polroots(T) \\ over C @eprog Note that factorization of polynomials is done up to multiplication by a constant. In particular, the factors of rational polynomials will have integer coefficients, and the content of a polynomial or rational function is discarded and not included in the factorization. If needed, you can always ask for the content explicitly: \bprog ? factor(t^2 + 5/2*t + 1) %1 = [2*t + 1 1] [t + 2 1] ? content(t^2 + 5/2*t + 1) %2 = 1/2 @eprog\noindent The irreducible factors are sorted by increasing degree. See also \tet{nffactor}. Variant: This function should only be used by the \kbd{gp} interface. Use directly \fun{GEN}{factor}{GEN x} or \fun{GEN}{boundfact}{GEN x, ulong lim}. The obsolete function \fun{GEN}{factor0}{GEN x, long lim} is kept for backward compatibility. Function: _factor_Aurifeuille Section: programming/internals C-Name: factor_Aurifeuille Prototype: GL Help: _factor_Aurifeuille(a,d): return an algebraic factor of Phi_d(a), a != 0 Function: _factor_Aurifeuille_prime Section: programming/internals C-Name: factor_Aurifeuille_prime Prototype: GL Help: _factor_Aurifeuille_prime(p,d): return an algebraic factor of Phi_d(p), p prime pari-2.7.5/src/functions/number_theoretical/quadhilbert0000644000175000017500000000110111636712103022000 0ustar billbillFunction: quadhilbert Section: number_theoretical C-Name: quadhilbert Prototype: Gp Help: quadhilbert(D): relative equation for the Hilbert class field of the quadratic field of discriminant D (which can also be a bnf). Doc: relative equation defining the \idx{Hilbert class field} of the quadratic field of discriminant $D$. If $D < 0$, uses complex multiplication (\idx{Schertz}'s variant). If $D > 0$ \idx{Stark units} are used and (in rare cases) a vector of extensions may be returned whose compositum is the requested class field. See \kbd{bnrstark} for details. pari-2.7.5/src/functions/number_theoretical/contfracpnqn0000644000175000017500000000250312413013143022167 0ustar billbillFunction: contfracpnqn Section: number_theoretical C-Name: contfracpnqn Prototype: GD-1,L, Help: 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. Doc: when $x$ is a vector or a one-row matrix, $x$ is considered as the list of partial quotients $[a_0,a_1,\dots,a_n]$ of a rational number, and the result is the 2 by 2 matrix $[p_n,p_{n-1};q_n,q_{n-1}]$ in the standard notation of continued fractions, so $p_n/q_n=a_0+1/(a_1+\dots+1/a_n)$. If $x$ is a matrix with two rows $[b_0,b_1,\dots,b_n]$ and $[a_0,a_1,\dots,a_n]$, this is then considered as a generalized continued fraction and we have similarly $p_n/q_n=(1/b_0)(a_0+b_1/(a_1+\dots+b_n/a_n))$. Note that in this case one usually has $b_0=1$. If $n \geq 0$ is present, returns all convergents from $p_0/q_0$ up to $p_n/q_n$. (All convergents if $x$ is too small to compute the $n+1$ requested convergents.) \bprog ? a=contfrac(Pi,20) %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2] ? contfracpnqn(a,3) %2 = [3 22 333 355] [1 7 106 113] ? contfracpnqn(a,7) %3 = [3 22 333 355 103993 104348 208341 312689] [1 7 106 113 33102 33215 66317 99532] @eprog Variant: also available is \fun{GEN}{pnqn}{GEN x} for $n = -1$. pari-2.7.5/src/functions/number_theoretical/binomial0000644000175000017500000000101611636712103021273 0ustar billbillFunction: binomial Section: number_theoretical C-Name: binomial Prototype: GL Help: binomial(x,y): binomial coefficient x*(x-1)...*(x-y+1)/y! defined for y in Z and any x. Doc: \idx{binomial coefficient} $\binom{x}{y}$. Here $y$ must be an integer, but $x$ can be any PARI object. Variant: The function \fun{GEN}{binomialuu}{ulong n, ulong k} is also available, and so is \fun{GEN}{vecbinome}{long n}, which returns a vector $v$ with $n+1$ components such that $v[k+1] = \kbd{binomial}(n,k)$ for $k$ from $0$ up to $n$. pari-2.7.5/src/functions/number_theoretical/znlog0000644000175000017500000000431012366172547020647 0ustar billbillFunction: znlog Section: number_theoretical C-Name: znlog Prototype: GGDG Help: 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. Doc: discrete logarithm of $x$ in $(\Z/N\Z)^*$ in base $g$. The result is $[]$ when $x$ is not a power of $g$. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. This provides a definite speedup when the discrete log problem is simple: \bprog ? p = nextprime(10^4); g = znprimroot(p); o = [p-1, factor(p-1)]; ? for(i=1,10^4, znlog(i, g, o)) time = 205 ms. ? for(i=1,10^4, znlog(i, g)) time = 244 ms. \\ a little slower @eprog The result is undefined if $g$ is not invertible mod $N$ or if the supplied order is incorrect. This function uses \item a combination of generic discrete log algorithms (see below). \item in $(\Z/N\Z)^*$ when $N$ is prime: a linear sieve index calculus method, suitable for $N < 10^{50}$, say, is used for large prime divisors of the order. The generic discrete log algorithms are: \item Pohlig-Hellman algorithm, to reduce to groups of prime order $q$, where $q | p-1$ and $p$ is an odd prime divisor of $N$, \item Shanks baby-step/giant-step ($q < 2^{32}$ is small), \item Pollard rho method ($q > 2^{32}$). The latter two algorithms require $O(\sqrt{q})$ operations in the group on average, hence will not be able to treat cases where $q > 10^{30}$, say. In addition, Pollard rho is not able to handle the case where there are no solutions: it will enter an infinite loop. \bprog ? g = znprimroot(101) %1 = Mod(2,101) ? znlog(5, g) %2 = 24 ? g^24 %3 = Mod(5, 101) ? G = znprimroot(2 * 101^10) %4 = Mod(110462212541120451003, 220924425082240902002) ? znlog(5, G) %5 = 76210072736547066624 ? G^% == 5 %6 = 1 ? N = 2^4*3^2*5^3*7^4*11; g = Mod(13, N); znlog(g^110, g) %7 = 110 ? znlog(6, Mod(2,3)) \\ no solution %8 = [] @eprog\noindent For convenience, $g$ is also allowed to be a $p$-adic number: \bprog ? g = 3+O(5^10); znlog(2, g) %1 = 1015243 ? g^% %2 = 2 + O(5^10) @eprog pari-2.7.5/src/functions/number_theoretical/factorback0000644000175000017500000000235611636712103021610 0ustar billbillFunction: factorback Section: number_theoretical C-Name: factorback2 Prototype: GDG Description: (gen):gen factorback($1) (gen,):gen factorback($1) (gen,gen):gen factorback2($1, $2) Help: 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]. Doc: gives back the factored object corresponding to a factorization. The integer $1$ corresponds to the empty factorization. If $e$ is present, $e$ and $f$ must be vectors of the same length ($e$ being integral), and the corresponding factorization is the product of the $f[i]^{e[i]}$. If not, and $f$ is vector, it is understood as in the preceding case with $e$ a vector of 1s: we return the product of the $f[i]$. Finally, $f$ can be a regular factorization, as produced with any \kbd{factor} command. A few examples: \bprog ? factor(12) %1 = [2 2] [3 1] ? factorback(%) %2 = 12 ? factorback([2,3], [2,1]) \\ 2^3 * 3^1 %3 = 12 ? factorback([5,2,3]) %4 = 30 @eprog Variant: Also available is \fun{GEN}{factorback}{GEN f} (case $e = \kbd{NULL}$). pari-2.7.5/src/functions/number_theoretical/sigma0000644000175000017500000000072312314242551020604 0ustar billbillFunction: sigma Section: number_theoretical C-Name: sumdivk Prototype: GD1,L, Help: 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. Description: (gen, ?1):int sumdiv($1) (gen, 0):int numdiv($1) Doc: sum of the $k^{\text{th}}$ powers of the positive divisors of $|x|$. $x$ and $k$ must be of type integer. Variant: Also available is \fun{GEN}{sumdiv}{GEN n}, for $k = 1$. pari-2.7.5/src/functions/number_theoretical/chinese0000644000175000017500000000365712366172547021151 0ustar billbillFunction: chinese Section: number_theoretical C-Name: chinese Prototype: GDG Help: chinese(x,{y}): x,y being both intmods (or polmods) computes z in the same residue classes as x and y. Description: (gen):gen chinese1($1) (gen, gen):gen chinese($1, $2) Doc: if $x$ and $y$ are both intmods or both polmods, creates (with the same type) a $z$ in the same residue class as $x$ and in the same residue class as $y$, if it is possible. \bprog ? chinese(Mod(1,2), Mod(2,3)) %1 = Mod(5, 6) ? chinese(Mod(x,x^2-1), Mod(x+1,x^2+1)) %2 = Mod(-1/2*x^2 + x + 1/2, x^4 - 1) @eprog\noindent This function also allows vector and matrix arguments, in which case the operation is recursively applied to each component of the vector or matrix. \bprog ? chinese([Mod(1,2),Mod(1,3)], [Mod(1,5),Mod(2,7)]) %3 = [Mod(1, 10), Mod(16, 21)] @eprog\noindent For polynomial arguments in the same variable, the function is applied to each coefficient; if the polynomials have different degrees, the high degree terms are copied verbatim in the result, as if the missing high degree terms in the polynomial of lowest degree had been \kbd{Mod(0,1)}. Since the latter behavior is usually \emph{not} the desired one, we propose to convert the polynomials to vectors of the same length first: \bprog ? P = x+1; Q = x^2+2*x+1; ? chinese(P*Mod(1,2), Q*Mod(1,3)) %4 = Mod(1, 3)*x^2 + Mod(5, 6)*x + Mod(3, 6) ? chinese(Vec(P,3)*Mod(1,2), Vec(Q,3)*Mod(1,3)) %5 = [Mod(1, 6), Mod(5, 6), Mod(4, 6)] ? Pol(%) %6 = Mod(1, 6)*x^2 + Mod(5, 6)*x + Mod(4, 6) @eprog If $y$ is omitted, and $x$ is a vector, \kbd{chinese} is applied recursively to the components of $x$, yielding a residue belonging to the same class as all components of $x$. Finally $\kbd{chinese}(x,x) = x$ regardless of the type of $x$; this allows vector arguments to contain other data, so long as they are identical in both vectors. Variant: \fun{GEN}{chinese1}{GEN x} is also available. pari-2.7.5/src/functions/number_theoretical/issquarefree0000644000175000017500000000045512314242551022204 0ustar billbillFunction: issquarefree Section: number_theoretical C-Name: issquarefree Prototype: lG Help: issquarefree(x): true(1) if x is squarefree, false(0) if not. Description: (gen):bool issquarefree($1) Doc: true (1) if $x$ is squarefree, false (0) if not. Here $x$ can be an integer or a polynomial. pari-2.7.5/src/functions/number_theoretical/gcdext0000644000175000017500000000214312314242551020760 0ustar billbillFunction: gcdext Section: number_theoretical C-Name: gcdext0 Prototype: GG Help: gcdext(x,y): returns [u,v,d] such that d=gcd(x,y) and u*x+v*y=d. Doc: Returns $[u,v,d]$ such that $d$ is the gcd of $x,y$, $x*u+y*v=\gcd(x,y)$, and $u$ and $v$ minimal in a natural sense. The arguments must be integers or polynomials. \sidx{extended gcd} \sidx{Bezout relation} \bprog ? [u, v, d] = gcdext(32,102) %1 = [16, -5, 2] ? d %2 = 2 ? gcdext(x^2-x, x^2+x-2) %3 = [-1/2, 1/2, x - 1] @eprog If $x,y$ are polynomials in the same variable and \emph{inexact} coefficients, then compute $u,v,d$ such that $x*u+y*v = d$, where $d$ approximately divides both and $x$ and $y$; in particular, we do not obtain \kbd{gcd(x,y)} which is \emph{defined} to be a scalar in this case: \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? gcdext(a,a) %2 = [0, 1, x + 0.E-28] ? gcdext(x-Pi, 6*x^2-zeta(2)) %3 = [-6*x - 18.8495559, 1, 57.5726923] @eprog\noindent For inexact inputs, the output is thus not well defined mathematically, but you obtain explicit polynomials to check whether the approximation is close enough for your needs. pari-2.7.5/src/functions/number_theoretical/quadpoly0000644000175000017500000000064712314242551021347 0ustar billbillFunction: quadpoly Section: number_theoretical C-Name: quadpoly0 Prototype: GDn Help: quadpoly(D,{v='x}): quadratic polynomial corresponding to the discriminant D, in variable v. Doc: creates the ``canonical'' quadratic polynomial (in the variable $v$) corresponding to the discriminant $D$, i.e.~the minimal polynomial of $\kbd{quadgen}(D)$. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square. pari-2.7.5/src/functions/number_theoretical/logint0000644000175000017500000000171012366172547021013 0ustar billbillFunction: logint Section: number_theoretical C-Name: logint0 Prototype: lGGD& Help: 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. Description: (gen,2):small expi($1) (gen,gen,&int):small logint0($1, $2, &$3) Doc: Return the largest integer $e$ so that $b^e \leq x$, where the parameters $b > 1$ and $x > 0$ are both integers. If the parameter $z$ is present, set it to $b^e$. \bprog ? logint(1000, 2) %1 = 9 ? 2^9 %2 = 512 ? logint(1000, 2, &z) %3 = 9 ? z %4 = 512 @eprog\noindent The number of digits used to write $b$ in base $x$ is \kbd{1 + logint(x,b)}: \bprog ? #digits(1000!, 10) %5 = 2568 ? logint(1000!, 10) %6 = 2567 @eprog\noindent This function may conveniently replace \bprog floor( log(x) / log(b) ) @eprog\noindent which may not give the correct answer since PARI does not guarantee exact rounding. pari-2.7.5/src/functions/number_theoretical/factorial0000644000175000017500000000053311636712103021450 0ustar billbillFunction: factorial Section: number_theoretical C-Name: mpfactr Prototype: Lp Help: factorial(x): factorial of x, the result being given as a real number. Doc: factorial of $x$. The expression $x!$ gives a result which is an integer, while $\kbd{factorial}(x)$ gives a real number. Variant: \fun{GEN}{mpfact}{long x} returns $x!$ as a \typ{INT}. pari-2.7.5/src/functions/number_theoretical/ispseudoprime0000644000175000017500000000303212456454744022410 0ustar billbillFunction: ispseudoprime Section: number_theoretical C-Name: gispseudoprime Prototype: GD0,L, Help: 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. Description: (int,?0):bool BPSW_psp($1) (int,#small):bool millerrabin($1,$2) (int,small):bool ispseudoprime($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 that $x$ is a prime number. Use \tet{isprime} (which is of course much slower) to prove that $x$ is indeed prime. The function accepts vector/matrices arguments, and is then applied componentwise. If $\fl = 0$, checks whether $x$ is a Baillie-Pomerance-Selfridge-Wagstaff pseudo prime (strong Rabin-Miller pseudo prime for base $2$, followed by strong Lucas test for the sequence $(P,-1)$, $P$ smallest positive integer 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}). 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$). pari-2.7.5/src/functions/number_theoretical/sumdedekind0000644000175000017500000000051411636712103021777 0ustar billbillFunction: sumdedekind Section: number_theoretical C-Name: sumdedekind Prototype: GG Help: sumdedekind(h,k): Dedekind sum associated to h,k Doc: returns the \idx{Dedekind sum} associated to the integers $h$ and $k$, corresponding to a fast implementation of \bprog s(h,k) = sum(n = 1, k-1, (n/k)*(frac(h*n/k) - 1/2)) @eprog pari-2.7.5/src/functions/number_theoretical/quadregulator0000644000175000017500000000057011636712103022364 0ustar billbillFunction: quadregulator Section: number_theoretical C-Name: quadregulator Prototype: Gp Help: quadregulator(x): regulator of the real quadratic field of discriminant x. Doc: regulator of the quadratic field of positive discriminant $x$. Returns an error if $x$ is not a discriminant (fundamental or not) or if $x$ is a square. See also \kbd{quadclassunit} if $x$ is large. pari-2.7.5/src/functions/number_theoretical/qfbcompraw0000644000175000017500000000065712314242551021653 0ustar billbillFunction: qfbcompraw Section: number_theoretical C-Name: qfbcompraw Prototype: GG Help: qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic forms x and y. Doc: \idx{composition} of the binary quadratic forms $x$ and $y$, without \idx{reduction} of the result. This is useful e.g.~to compute a generating element of an ideal. The result is undefined if $x$ and $y$ do not have the same discriminant. pari-2.7.5/src/functions/number_theoretical/znorder0000644000175000017500000000140111636712103021162 0ustar billbillFunction: znorder Section: number_theoretical C-Name: znorder Prototype: GDG Help: znorder(x,{o}): order of the integermod x in (Z/nZ)*. Optional o represents a multiple of the order of the element. Description: (gen):int order($1) (gen,):int order($1) (gen,int):int znorder($1, $2) Doc: $x$ must be an integer mod $n$, and the result is the order of $x$ in the multiplicative group $(\Z/n\Z)^*$. Returns an error if $x$ is not invertible. The parameter o, if present, represents a non-zero multiple of the order of $x$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord = eulerphi(n)} is the cardinality of the group. Variant: Also available is \fun{GEN}{order}{GEN x}. pari-2.7.5/src/functions/number_theoretical/factorint0000644000175000017500000000404412366172547021513 0ustar billbillFunction: factorint Section: number_theoretical C-Name: factorint Prototype: GD0,L, Help: 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). Doc: factors the integer $n$ into a product of pseudoprimes (see \kbd{ispseudoprime}), using a combination of the \idx{Shanks SQUFOF} and \idx{Pollard Rho} method (with modifications due to Brent), \idx{Lenstra}'s \idx{ECM} (with modifications by Montgomery), and \idx{MPQS} (the latter adapted from the \idx{LiDIA} code with the kind permission of the LiDIA maintainers), as well as a search for pure powers. The output is a two-column matrix as for \kbd{factor}: the first column contains the ``prime'' divisors of $n$, the second one contains the (positive) exponents. By convention $0$ is factored as $0^1$, and $1$ as the empty factorization; also the divisors are by default not proven primes is they are larger than $2^{64}$, they only failed the BPSW compositeness test (see \tet{ispseudoprime}). Use \kbd{isprime} on the result if you want to guarantee primality or set the \tet{factor_proven} default to $1$. Entries of the private prime tables (see \tet{addprimes}) are also included as is. This gives direct access to the integer factoring engine called by most arithmetical functions. \fl\ is optional; its binary digits mean 1: avoid MPQS, 2: skip first stage ECM (we may still fall back to it later), 4: avoid Rho and SQUFOF, 8: don't run final ECM (as a result, a huge composite may be declared to be prime). Note that a (strong) probabilistic primality test is used; thus composites might not be detected, although no example is known. You are invited to play with the flag settings and watch the internals at work by using \kbd{gp}'s \tet{debug} default parameter (level 3 shows just the outline, 4 turns on time keeping, 5 and above show an increasing amount of internal details). pari-2.7.5/src/functions/number_theoretical/hilbert0000644000175000017500000000103011636712103021126 0ustar billbillFunction: hilbert Section: number_theoretical C-Name: hilbert Prototype: lGGDG Help: hilbert(x,y,{p}): Hilbert symbol at p of x,y. Doc: \idx{Hilbert symbol} of $x$ and $y$ modulo the prime $p$, $p=0$ meaning the place at infinity (the result is undefined if $p\neq 0$ is not prime). It is possible to omit $p$, in which case we take $p = 0$ if both $x$ and $y$ are rational, or one of them is a real number. And take $p = q$ if one of $x$, $y$ is a \typ{INTMOD} modulo $q$ or a $q$-adic. (Incompatible types will raise an error.) pari-2.7.5/src/functions/number_theoretical/bezout0000644000175000017500000000024112314242551021007 0ustar billbillFunction: bezout Section: number_theoretical C-Name: gcdext0 Prototype: GG Help: bezout(x,y): deprecated alias for gcdext Doc: deprecated alias for \kbd{gcdext} pari-2.7.5/src/functions/number_theoretical/ffprimroot0000644000175000017500000000214011636712103021667 0ustar billbillFunction: ffprimroot Section: number_theoretical C-Name: ffprimroot Prototype: GD& Help: 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). Doc: 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 a vector \kbd{[ord, fa]}, where \kbd{ord} is the order of the group and \kbd{fa} its factorisation \kbd{factor(ord)}. This last parameter is useful in \tet{fflog} and \tet{fforder}, see \secref{se:DLfun}. \bprog ? t = ffgen(ffinit(nextprime(10^7), 5)); ? g = ffprimroot(t, &o); ? o[1] %3 = 100000950003610006859006516052476098 ? o[2] %4 = [2 1] [7 2] [31 1] [41 1] [67 1] [1523 1] [10498781 1] [15992881 1] [46858913131 1] ? fflog(g^1000000, g, o) time = 1,312 ms. %5 = 1000000 @eprog pari-2.7.5/src/functions/number_theoretical/factorff0000644000175000017500000000304011636712103021272 0ustar billbillFunction: factorff Section: number_theoretical C-Name: factorff Prototype: GDGDG Help: factorff(x,{p},{a}): factorization of the polynomial x in the finite field F_p[X]/a(X)F_p[X]. Doc: factors the polynomial $x$ in the field $\F_q$ defined by the irreducible polynomial $a$ over $\F_p$. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix: the first column contains the irreducible factors of $x$, and the second their exponents. If all the coefficients of $x$ are in $\F_p$, a much faster algorithm is applied, using the computation of isomorphisms between finite fields. Either $a$ or $p$ can omitted (in which case both are ignored) if x has \typ{FFELT} coefficients; the function then becomes identical to \kbd{factor}: \bprog ? factorff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25 %1 = [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x + Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1] [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x + Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1] ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT ? factorff(x^2 + 1) \\ not enough information to determine the base field *** at top-level: factorff(x^2+1) *** ^--------------- *** factorff: incorrect type in factorff. ? factorff(x^2 + t^0) \\ make sure a coeff. is a t_FFELT %3 = [x + 2 1] [x + 3 1] ? factorff(x^2 + t + 1) %11 = [x + (2*t + 1) 1] [x + (3*t + 4) 1] @eprog\noindent Notice that the second syntax is easier to use and much more readable. pari-2.7.5/src/functions/number_theoretical/zncoppersmith0000644000175000017500000000432712541104173022414 0ustar billbillFunction: zncoppersmith Section: number_theoretical C-Name: zncoppersmith Prototype: GGGDG Help: 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)). Doc: $N$ being an integer and $P\in \Z[X]$, finds all integers $x$ with $|x| \leq X$ such that $$\gcd(N, P(x)) \geq B,$$ using \idx{Coppersmith}'s algorithm (a famous application of the \idx{LLL} algorithm). $X$ must be smaller than $\exp(\log^2 B / (\deg(P) \log N))$: for $B = N$, this means $X < N^{1/\deg(P)}$. Some $x$ larger than $X$ may be returned if you are very lucky. The smaller $B$ (or the larger $X$), the slower the routine will be. The strength of Coppersmith method is the ability to find roots modulo a general \emph{composite} $N$: if $N$ is a prime or a prime power, \tet{polrootsmod} or \tet{polrootspadic} will be much faster. We shall now present two simple applications. The first one is finding non-trivial factors of $N$, given some partial information on the factors; in that case $B$ must obviously be smaller than the largest non-trivial divisor of $N$. \bprog setrand(1); \\ to make the example reproducible 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 L = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) \\ result in 10ms. %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}$. The second application is an attack on RSA with low exponent, when the message $x$ is short and the padding $P$ is known to the attacker. We use the same RSA modulus $N$ as in the first example: \bprog setrand(1); P = random(N); \\ known padding e = 3; \\ small public encryption exponent X = floor(N^0.3); \\ N^(1/e - epsilon) x0 = random(X); \\ unknown short message C = lift( (Mod(x0,N) + P)^e ); \\ known ciphertext, with padding P zncoppersmith((P + x)^3 - C, N, X) \\ result in 244ms. %14 = [2679982004001230401] ? %[1] == x0 %4 = 1 @eprog\noindent We guessed an integer of the order of $10^{18}$, almost instantly. pari-2.7.5/src/functions/number_theoretical/qfbnucomp0000644000175000017500000000160611636712103021500 0ustar billbillFunction: qfbnucomp Section: number_theoretical C-Name: nucomp Prototype: GGG Help: 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. Doc: \idx{composition} of the primitive positive definite binary quadratic forms $x$ and $y$ (type \typ{QFI}) using the NUCOMP and NUDUPL algorithms of \idx{Shanks}, \`a la Atkin. $L$ is any positive constant, but for optimal speed, one should take $L=|D|^{1/4}$, where $D$ is the common discriminant of $x$ and $y$. When $x$ and $y$ do not have the same discriminant, the result is undefined. The current implementation is straightforward and in general \emph{slower} than the generic routine (since the latter takes advantage of asymptotically fast operations and careful optimizations). Variant: Also available is \fun{GEN}{nudupl}{GEN x, GEN L} when $x=y$. pari-2.7.5/src/functions/number_theoretical/eulerphi0000644000175000017500000000101512413013143021305 0ustar billbillFunction: eulerphi Section: number_theoretical C-Name: eulerphi Prototype: G Help: eulerphi(x): Euler's totient function of x. Description: (gen):int eulerphi($1) Doc: Euler's $\phi$ (totient)\sidx{Euler totient function} function of the integer $|x|$, in other words $|(\Z/x\Z)^*|$. \bprog ? eulerphi(40) %1 = 16 @eprog\noindent According to this definition we let $\phi(0) := 2$, since $\Z^* = \{-1,1\}$; this is consistent with \kbd{znstar(0)}: we have \kbd{znstar$(n)$.no = eulerphi(n)} for all $n\in\Z$. pari-2.7.5/src/functions/number_theoretical/direuler0000644000175000017500000000220612314242551021315 0ustar billbillFunction: direuler Section: number_theoretical C-Name: direuler0 Prototype: V=GGEDG Help: 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. Wrapper: (,,G) Description: (gen,gen,closure,?gen):gen direuler(${3 cookie}, ${3 wrapper}, $1, $2, $4) Doc: computes the \idx{Dirichlet series} associated to the \idx{Euler product} of expression \var{expr} as $p$ ranges through the primes from $a$ to $b$. \var{expr} must be a polynomial or rational function in another variable than $p$ (say $X$) and $\var{expr}(X)$ is understood as the local factor $\var{expr}(p^{-s})$. The series is output as a vector of coefficients. If $c$ is present, output only the first $c$ coefficients in the series. The following command computes the \teb{sigma} function, associated to $\zeta(s)\zeta(s-1)$: \bprog ? direuler(p=2, 10, 1/((1-X)*(1-p*X))) %1 = [1, 3, 4, 7, 6, 12, 8, 15, 13, 18] @eprog \synt{direuler}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b} pari-2.7.5/src/functions/number_theoretical/quadgen0000644000175000017500000000067511636712103021137 0ustar billbillFunction: quadgen Section: number_theoretical C-Name: quadgen Prototype: G Help: quadgen(D): standard generator of quadratic order of discriminant D. Doc: creates the quadratic number\sidx{omega} $\omega=(a+\sqrt{D})/2$ where $a=0$ if $D\equiv0\mod4$, $a=1$ if $D\equiv1\mod4$, so that $(1,\omega)$ is an integral basis for the quadratic order of discriminant $D$. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square. pari-2.7.5/src/functions/number_theoretical/quadray0000644000175000017500000000114411636712103021151 0ustar billbillFunction: quadray Section: number_theoretical C-Name: quadray Prototype: GGp Help: quadray(D,f): relative equation for the ray class field of conductor f for the quadratic field of discriminant D (which can also be a bnf). Doc: relative equation for the ray class field of conductor $f$ for the quadratic field of discriminant $D$ using analytic methods. A \kbd{bnf} for $x^2 - D$ is also accepted in place of $D$. For $D < 0$, uses the $\sigma$ function and Schertz's method. For $D>0$, uses Stark's conjecture, and a vector of relative equations may be returned. See \tet{bnrstark} for more details. pari-2.7.5/src/functions/number_theoretical/precprime0000644000175000017500000000076112314242551021474 0ustar billbillFunction: precprime Section: number_theoretical C-Name: precprime Prototype: G Help: precprime(x): largest pseudoprime <= x, 0 if x<=1. Description: (gen):int precprime($1) Doc: finds the largest pseudoprime (see \tet{ispseudoprime}) less than or equal to $x$. $x$ can be of any real type. Returns 0 if $x\le1$. Note that if $x$ is a prime, this function returns $x$ and not the largest prime strictly smaller than $x$. To rigorously prove that the result is prime, use \kbd{isprime}. pari-2.7.5/src/functions/number_theoretical/partitions0000644000175000017500000000410412366172547021713 0ustar billbillFunction: partitions Section: number_theoretical C-Name: partitions Prototype: LDGDG Help: 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). Doc: returns the vector of partitions of the integer $k$ as a sum of positive integers (parts); for $k < 0$, it returns the empty set \kbd{[]}, and for $k = 0$ the trivial partition (no parts). A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order: \bprog ? partitions(3) %1 = [Vecsmall([3]), Vecsmall([1, 2]), Vecsmall([1, 1, 1])] @eprog\noindent correspond to $3$, $1+2$ and $1+1+1$. The number of (unrestricted) partitions of $k$ is given by \tet{numbpart}: \bprog ? #partitions(50) %1 = 204226 ? numbpart(50) %2 = 204226 @eprog \noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). \bprog ? partitions(4, 2) \\ parts bounded by 2 %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])] ? partitions(4,, 2) \\ at most 2 parts %2 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])] ? partitions(4,[0,3], 2) \\ at most 2 parts %3 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])] @eprog\noindent By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case $nmin$ is ignored and $X$ is of constant length $\var{nmax}$: \bprog ? partitions(4, [0,3]) \\ parts between 0 and 3 %1 = [Vecsmall([0, 0, 1, 3]), Vecsmall([0, 0, 2, 2]),\ Vecsmall([0, 1, 1, 2]), Vecsmall([1, 1, 1, 1])] @eprog pari-2.7.5/src/functions/number_theoretical/gcd0000644000175000017500000000437712413013143020243 0ustar billbillFunction: gcd Section: number_theoretical C-Name: ggcd0 Prototype: GDG Help: gcd(x,{y}): greatest common divisor of x and y. Description: (small, small):small cgcd($1, $2) (int, int):int gcdii($1, $2) (gen):gen content($1) (gen, gen):gen ggcd($1, $2) Doc: creates the greatest common divisor of $x$ and $y$. If you also need the $u$ and $v$ such that $x*u + y*v = \gcd(x,y)$, use the \tet{bezout} function. $x$ and $y$ can have rather quite general types, for instance both rational numbers. If $y$ is omitted and $x$ is a vector, returns the $\text{gcd}$ of all components of $x$, i.e.~this is equivalent to \kbd{content(x)}. When $x$ and $y$ are both given and one of them is a vector/matrix type, the GCD is again taken recursively on each component, but in a different way. If $y$ is a vector, resp.~matrix, then the result has the same type as $y$, and components equal to \kbd{gcd(x, y[i])}, resp.~\kbd{gcd(x, y[,i])}. Else if $x$ is a vector/matrix the result has the same type as $x$ and an analogous definition. Note that for these types, \kbd{gcd} is not commutative. The algorithm used is a naive \idx{Euclid} except for the following inputs: \item integers: use modified right-shift binary (``plus-minus'' variant). \item univariate polynomials with coefficients in the same number field (in particular rational): use modular gcd algorithm. \item general polynomials: use the \idx{subresultant algorithm} if coefficient explosion is likely (non modular coefficients). If $u$ and $v$ are polynomials in the same variable with \emph{inexact} coefficients, their gcd is defined to be scalar, so that \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? b = y*x + O(y); gcd(b,b) %2 = y ? c = 4*x + O(2^3); gcd(c,c) %3 = 4 @eprog\noindent A good quantitative check to decide whether such a gcd ``should be'' non-trivial, is to use \tet{polresultant}: a value close to $0$ means that a small deformation of the inputs has non-trivial gcd. You may also use \tet{gcdext}, which does try to compute an approximate gcd $d$ and provides $u$, $v$ to check whether $u x + v y$ is close to $d$. Variant: Also available are \fun{GEN}{ggcd}{GEN x, GEN y}, if \kbd{y} is not \kbd{NULL}, and \fun{GEN}{content}{GEN x}, if $\kbd{y} = \kbd{NULL}$. pari-2.7.5/src/functions/number_theoretical/issquare0000644000175000017500000000275612531362535021356 0ustar billbillFunction: issquare Section: number_theoretical C-Name: issquareall Prototype: lGD& Help: 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. Description: (int):bool Z_issquare($1) (gen):bool issquare($1) (int, &int):bool Z_issquareall($1, &$2) (gen, &gen):bool issquareall($1, &$2) Doc: true (1) if $x$ is a square, false (0) if not. What ``being a square'' means depends on the type of $x$: all \typ{COMPLEX} are squares, as well as all non-negative \typ{REAL}; for exact types such as \typ{INT}, \typ{FRAC} and \typ{INTMOD}, squares are numbers of the form $s^2$ with $s$ in $\Z$, $\Q$ and $\Z/N\Z$ respectively. \bprog ? issquare(3) \\ as an integer %1 = 0 ? issquare(3.) \\ as a real number %2 = 1 ? issquare(Mod(7, 8)) \\ in Z/8Z %3 = 0 ? issquare( 5 + O(13^4) ) \\ in Q_13 %4 = 0 @eprog If $n$ is given, a square root of $x$ is put into $n$. \bprog ? issquare(4, &n) %1 = 1 ? n %2 = 2 @eprog For polynomials, either we detect that the characteristic is 2 (and check directly odd and even-power monomials) or we assume that $2$ is invertible and check whether squaring the truncated power series for the square root yields the original input. Variant: Also available is \fun{long}{issquare}{GEN x}. Deprecated GP-specific functions \fun{GEN}{gissquare}{GEN x} and \fun{GEN}{gissquareall}{GEN x, GEN *pt} return \kbd{gen\_0} and \kbd{gen\_1} instead of a boolean value. pari-2.7.5/src/functions/number_theoretical/sqrtnint0000644000175000017500000000077512366172547021413 0ustar billbillFunction: sqrtnint Section: number_theoretical C-Name: sqrtnint Prototype: GL Help: sqrtnint(x,n): integer n-th root of x, where x is non-negative integer. Description: (gen,small):int sqrtnint($1, $2) Doc: returns the integer $n$-th root of $x$, i.e. the largest integer $y$ such that $y^n \leq x$, where $x$ is a non-negative integer. \bprog ? N = 120938191237; sqrtnint(N, 5) %1 = 164 ? N^(1/5) %2 = 164.63140849829660842958614676939677391 @eprog\noindent The special case $n = 2$ is \tet{sqrtint} pari-2.7.5/src/functions/number_theoretical/fforder0000644000175000017500000000153412314242551021134 0ustar billbillFunction: fforder Section: number_theoretical C-Name: fforder Prototype: GDG Help: fforder(x,{o}): multiplicative order of the finite field element x. Optional o represents a multiple of the order of the element. Doc: multiplicative order of the finite field element $x$. If $o$ is present, it represents a multiple of the order of the element, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where \kbd{N} is the cardinality of the multiplicative group of the underlying finite field. \bprog ? t = ffgen(ffinit(nextprime(10^8), 5)); ? g = ffprimroot(t, &o); \\@com o will be useful! ? fforder(g^1000000, o) time = 0 ms. %5 = 5000001750000245000017150000600250008403 ? fforder(g^1000000) time = 16 ms. \\@com noticeably slower, same result of course %6 = 5000001750000245000017150000600250008403 @eprog pari-2.7.5/src/functions/number_theoretical/fflog0000644000175000017500000000253212366172547020617 0ustar billbillFunction: fflog Section: number_theoretical C-Name: fflog Prototype: GGDG Help: 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. Doc: discrete logarithm of the finite field element $x$ in base $g$, i.e.~ an $e$ in $\Z$ such that $g^e = o$. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. It may be set as a side effect of calling \tet{ffprimroot}. If no $o$ is given, assume that $g$ is a primitive root. The result is undefined if $e$ does not exist. This function uses \item a combination of generic discrete log algorithms (see \tet{znlog}) \item a cubic sieve index calculus algorithm for large fields of degree at least $5$. \item Coppersmith's algorithm for fields of characteristic at most $5$. \bprog ? t = ffgen(ffinit(7,5)); ? o = fforder(t) %2 = 5602 \\@com \emph{not} a primitive root. ? fflog(t^10,t) %3 = 10 ? fflog(t^10,t, o) %4 = 10 ? g = ffprimroot(t, &o); ? o \\ order is 16806, bundled with its factorization matrix %6 = [16806, [2, 1; 3, 1; 2801, 1]] ? fforder(g, o) %7 = 16806 ? fflog(g^10000, g, o) %8 = 10000 @eprog pari-2.7.5/src/functions/number_theoretical/stirling0000644000175000017500000000250212453240751021340 0ustar billbillFunction: stirling Section: number_theoretical C-Name: stirling Prototype: LLD1,L, Help: 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). Doc: \idx{Stirling number} of the first kind $s(n,k)$ ($\fl=1$, default) or of the second kind $S(n,k)$ (\fl=2), where $n$, $k$ are non-negative integers. The former is $(-1)^{n-k}$ times the number of permutations of $n$ symbols with exactly $k$ cycles; the latter is the number of ways of partitioning a set of $n$ elements into $k$ non-empty subsets. Note that if all $s(n,k)$ are needed, it is much faster to compute $$\sum_k s(n,k) x^k = x(x-1)\dots(x-n+1).$$ Similarly, if a large number of $S(n,k)$ are needed for the same $k$, one should use $$\sum_n S(n,k) x^n = \dfrac{x^k}{(1-x)\dots(1-kx)}.$$ (Should be implemented using a divide and conquer product.) Here are simple variants for $n$ fixed: \bprog /* list of s(n,k), k = 1..n */ 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]; simplify(t[2])); } @eprog Variant: Also available are \fun{GEN}{stirling1}{ulong n, ulong k} ($\fl=1$) and \fun{GEN}{stirling2}{ulong n, ulong k} ($\fl=2$). pari-2.7.5/src/functions/number_theoretical/isfundamental0000644000175000017500000000057112314242551022337 0ustar billbillFunction: isfundamental Section: number_theoretical C-Name: isfundamental Prototype: lG Help: isfundamental(x): true(1) if x is a fundamental discriminant (including 1), false(0) if not. Description: (int):bool Z_isfundamental($1) (gen):bool isfundamental($1) Doc: true (1) if $x$ is equal to 1 or to the discriminant of a quadratic field, false (0) otherwise. pari-2.7.5/src/functions/number_theoretical/numbpart0000644000175000017500000000101411636712103021327 0ustar billbillFunction: numbpart Section: number_theoretical C-Name: numbpart Prototype: G Help: numbpart(n): number of partitions of n. Doc: gives the number of unrestricted partitions of $n$, usually called $p(n)$ in the literature; in other words the number of nonnegative integer solutions to $a+2b+3c+\cdots=n$. $n$ must be of type integer and $n<10^{15}$ (with trivial values $p(n) = 0$ for $n < 0$ and $p(0) = 1$). The algorithm uses the Hardy-Ramanujan-Rademacher formula. To explicitly enumerate them, see \tet{partitions}. pari-2.7.5/src/functions/number_theoretical/randomprime0000644000175000017500000000101112366172547022026 0ustar billbillFunction: randomprime Section: number_theoretical C-Name: randomprime Prototype: DG Help: randomprime({N = 2^31}): returns a strong pseudo prime in [2, N-1]. Doc: returns a strong pseudo prime (see \tet{ispseudoprime}) in $[2,N-1]$. A \typ{VEC} $N = [a,b]$ is also allowed, with $a \leq b$ in which case a pseudo prime $a \leq p \leq b$ is returned; if no prime exists in the interval, the function will run into an infinite loop. If the upper bound is less than $2^{64}$ the pseudo prime returned is a proven prime. pari-2.7.5/src/functions/number_theoretical/quadunit0000644000175000017500000000107711636712103021342 0ustar billbillFunction: quadunit Section: number_theoretical C-Name: quadunit Prototype: G Help: quadunit(D): fundamental unit of the quadratic field of discriminant D where D must be positive. Doc: fundamental unit\sidx{fundamental units} of the real quadratic field $\Q(\sqrt D)$ where $D$ is the positive discriminant of the field. If $D$ is not a fundamental discriminant, this probably gives the fundamental unit of the corresponding order. $D$ must be an integer congruent to 0 or 1 modulo 4, which is not a square; the result is a quadratic number (see \secref{se:quadgen}). pari-2.7.5/src/functions/number_theoretical/ffnbirred0000644000175000017500000000121412413013143021432 0ustar billbillFunction: ffnbirred Section: number_theoretical C-Name: ffnbirred0 Prototype: GLD0,L, Help: ffnbirred(q,n{,fl=0}): number of monic irreducible polynomials over F_q, of degree n (fl=0, default) or at most n (fl=1). Description: (int, small, ?0):int ffnbirred($1, $2) (int, small, 1):int ffsumnbirred($1, $2) (int, small, ?small):int ffnbirred0($1, $2, $3) Doc: computes the number of monic irreducible polynomials over $\F_q$ of degree exactly $n$, ($\fl=0$ or omitted) or at most $n$ ($\fl=1$). Variant: Also available are \fun{GEN}{ffnbirred}{GEN q, long n} (for $\fl=0$) and \fun{GEN}{ffsumnbirred}{GEN q, long n} (for $\fl=1$). pari-2.7.5/src/functions/number_theoretical/prime0000644000175000017500000000041612314242551020617 0ustar billbillFunction: prime Section: number_theoretical C-Name: prime Prototype: L Help: prime(n): returns the n-th prime (n C-integer). Doc: the $n^{\text{th}}$ prime number \bprog ? prime(10^9) %1 = 22801763489 @eprog\noindent Uses checkpointing and a naive $O(n)$ algorithm. pari-2.7.5/src/functions/number_theoretical/lcm0000644000175000017500000000264611636712103020266 0ustar billbillFunction: 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). 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$ is a vector, returns the $\text{lcm}$ of all components of $x$. 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. If $y$ is a vector, resp.~matrix, then the result has the same type as $y$, and components equal to \kbd{lcm(x, y[i])}, resp.~\kbd{lcm(x, y[,i])}. Else if $x$ is a vector/matrix the result has the same type as $x$ and an analogous definition. Note that for these types, \kbd{lcm} is not commutative. Note that \kbd{lcm(v)} is quite different from \bprog l = v[1]; for (i = 1, #v, l = lcm(l, v[i])) @eprog\noindent Indeed, \kbd{lcm(v)} is a scalar, but \kbd{l} may not be (if one of 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); ? lcm(v); time = 323 ms. ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i])) time = 833 ms. @eprog pari-2.7.5/src/functions/number_theoretical/isprime0000644000175000017500000000500612531362535021161 0ustar billbillFunction: isprime Section: number_theoretical C-Name: gisprime Prototype: GD0,L, Help: 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. Description: (int, ?0):bool isprime($1) (gen, ?small):gen gisprime($1, $2) Doc: true (1) if $x$ is a prime number, false (0) otherwise. A prime number is a positive integer having exactly two distinct divisors among the natural numbers, namely 1 and itself. This routine proves or disproves rigorously that a number is prime, which can be very slow when $x$ is indeed prime and has more than $1000$ digits, say. Use \tet{ispseudoprime} to quickly check for compositeness. See also \kbd{factor}. It accepts vector/matrices arguments, and is then applied componentwise. If $\fl=0$, use a combination of Baillie-PSW pseudo primality test (see \tet{ispseudoprime}), Selfridge ``$p-1$'' test if $x-1$ is smooth enough, and Adleman-Pomerance-Rumely-Cohen-Lenstra (APRCL) for general $x$. If $\fl=1$, use Selfridge-Pocklington-Lehmer ``$p-1$'' test and output a primality certificate as follows: return \item 0 if $x$ is composite, \item 1 if $x$ is small enough that passing Baillie-PSW test guarantees its primality (currently $x < 2^{64}$, as checked by Jan Feitsma), \item $2$ if $x$ is a large prime whose primality could only sensibly be proven (given the algorithms implemented in PARI) using the APRCL test. \item Otherwise ($x$ is large and $x-1$ is smooth) output a three column matrix as a primality certificate. The first column contains prime divisors $p$ of $x-1$ (such that $\prod p^{v_p(x-1)} > x^{1/3}$), the second the corresponding elements $a_p$ as in Proposition~8.3.1 in GTM~138 , and the third the output of isprime(p,1). The algorithm fails if one of the pseudo-prime factors is not prime, which is exceedingly unlikely and well worth a bug report. Note that if you monitor \kbd{isprime} at a high enough debug level, you may see warnings about untested integers being declared primes. This is normal: we ask for partial factorisations (sufficient to prove primality if the unfactored part is not too large), and \kbd{factor} warns us that the cofactor hasn't been tested. It may or may not be tested later, and may or may not be prime. This does not affect the validity of the whole \kbd{isprime} procedure. If $\fl=2$, use APRCL. pari-2.7.5/src/functions/number_theoretical/ffgen0000644000175000017500000000345212366172547020611 0ustar billbillFunction: ffgen Section: number_theoretical C-Name: ffgen Prototype: GDn Help: 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. Doc: return a \typ{FFELT} generator for the finite field with $q$ elements; $q = p^f$ must be a prime power. This functions computes an irreducible monic polynomial $P\in\F_p[X]$ of degree~$f$ (via \tet{ffinit}) and returns $g = X \pmod{P(X)}$. If \kbd{v} is given, the variable name is used to display $g$, else the variable $x$ is used. \bprog ? g = ffgen(8, 't); ? g.mod %2 = t^3 + t^2 + 1 ? g.p %3 = 2 ? g.f %4 = 3 ? ffgen(6) *** 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} 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 $P$ is used. If $P$ is not irreducible, we create an invalid object and behaviour of functions dealing with the resulting \typ{FFELT} is undefined; in fact, it is much more costly to test $P$ for irreducibility than it would be to produce it via \kbd{ffinit}. Variant: To create a generator for a prime finite field, the function \fun{GEN}{p_to_GEN}{GEN p, long v} returns \kbd{1+ffgen(x*Mod(1,p),v)}. pari-2.7.5/src/functions/number_theoretical/quadclassunit0000644000175000017500000000557212314242551022373 0ustar billbillFunction: quadclassunit Section: number_theoretical C-Name: quadclassunit0 Prototype: GD0,L,DGp Help: 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. Doc: \idx{Buchmann-McCurley}'s sub-exponential algorithm for computing the class group of a quadratic order of discriminant $D$. This function should be used instead of \tet{qfbclassno} or \tet{quadregula} when $D<-10^{25}$, $D>10^{10}$, or when the \emph{structure} is wanted. It is a special case of \tet{bnfinit}, which is slower, but more robust. The result is a vector $v$ whose components should be accessed using member functions: \item \kbd{$v$.no}: the class number \item \kbd{$v$.cyc}: a vector giving the structure of the class group as a product of cyclic groups; \item \kbd{$v$.gen}: a vector giving generators of those cyclic groups (as binary quadratic forms). \item \kbd{$v$.reg}: the regulator, computed to an accuracy which is the maximum of an internal accuracy determined by the program and the current default (note that once the regulator is known to a small accuracy it is trivial to compute it to very high accuracy, see the tutorial). The $\fl$ is obsolete and should be left alone. In older versions, it supposedly computed the narrow class group when $D>0$, but this did not work at all; use the general function \tet{bnfnarrow}. Optional parameter \var{tech} is a row vector of the form $[c_1, c_2]$, where $c_1 \leq c_2$ are non-negative real numbers which control the execution time and the stack size, see \ref{se:GRHbnf}. The parameter is used as a threshold to balance the relation finding phase against the final linear algebra. Increasing the default $c_1$ means that relations are easier to find, but more relations are needed and the linear algebra will be harder. The default value for $c_1$ is $0$ and means that it is taken equal to $c_2$. The parameter $c_2$ is mostly obsolete and should not be changed, but we still document it for completeness: we compute a tentative class group by generators and relations using a factorbase of prime ideals $\leq c_1 (\log |D|)^2$, then prove that ideals of norm $\leq c_2 (\log |D|)^2$ do not generate a larger group. By default an optimal $c_2$ is chosen, so that the result is provably correct under the GRH --- a famous result of Bach states that $c_2 = 6$ is fine, but it is possible to improve on this algorithmically. You may provide a smaller $c_2$, it will be ignored (we use the provably correct one); you may provide a larger $c_2$ than the default value, which results in longer computing times for equally correct outputs (under GRH). Variant: If you really need to experiment with the \var{tech} parameter, it is usually more convenient to use \fun{GEN}{Buchquad}{GEN D, double c1, double c2, long prec} pari-2.7.5/src/functions/number_theoretical/sumdigits0000644000175000017500000000054512405547147021530 0ustar billbillFunction: 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$. \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}. pari-2.7.5/src/functions/number_theoretical/core0000644000175000017500000000122511636712103020433 0ustar billbillFunction: core Section: number_theoretical C-Name: core0 Prototype: GD0,L, Help: 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. Doc: if $n$ is an integer written as $n=df^2$ with $d$ squarefree, returns $d$. If $\fl$ is non-zero, returns the two-element row vector $[d,f]$. By convention, we write $0 = 0 \times 1^2$, so \kbd{core(0, 1)} returns $[0,1]$. Variant: Also available are \fun{GEN}{core}{GEN n} ($\fl = 0$) and \fun{GEN}{core2}{GEN n} ($\fl = 1$) pari-2.7.5/src/functions/number_theoretical/kronecker0000644000175000017500000000136612314242551021473 0ustar billbillFunction: kronecker Section: number_theoretical C-Name: kronecker Prototype: lGG Help: kronecker(x,y): kronecker symbol (x/y). Description: (small, small):small kross($1, $2) (int, small):small krois($1, $2) (small, int):small krosi($1, $2) (gen, gen):small kronecker($1, $2) Doc: \idx{Kronecker symbol} $(x|y)$, where $x$ and $y$ must be of type integer. By definition, this is the extension of \idx{Legendre symbol} to $\Z \times \Z$ by total multiplicativity in both arguments with the following special rules for $y = 0, -1$ or $2$: \item $(x|0) = 1$ if $|x| = 1$ and $0$ otherwise. \item $(x|-1) = 1$ if $x \geq 0$ and $-1$ otherwise. \item $(x|2) = 0$ if $x$ is even and $1$ if $x = 1,-1 \mod 8$ and $-1$ if $x=3,-3 \mod 8$. pari-2.7.5/src/functions/number_theoretical/factormod0000644000175000017500000000145511636712103021466 0ustar billbillFunction: factormod Section: number_theoretical C-Name: factormod0 Prototype: GGD0,L, Help: 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. Doc: factors the polynomial $x$ modulo the prime integer $p$, using \idx{Berlekamp}. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. The result is a two-column matrix, the first column being the irreducible polynomials dividing $x$, and the second the exponents. If $\fl$ is non-zero, outputs only the \emph{degrees} of the irreducible polynomials (for example, for computing an $L$-function). A different algorithm for computing the mod $p$ factorization is \kbd{factorcantor} which is sometimes faster. pari-2.7.5/src/functions/number_theoretical/polrootsff0000644000175000017500000000230311636712103021676 0ustar billbillFunction: polrootsff Section: number_theoretical C-Name: polrootsff Prototype: GDGDG Help: 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. Doc: returns the vector of distinct roots of the polynomial $x$ in the field $\F_q$ defined by the irreducible polynomial $a$ over $\F_p$. The coefficients of $x$ must be operation-compatible with $\Z/p\Z$. Either $a$ or $p$ can omitted (in which case both are ignored) if x has \typ{FFELT} coefficients: \bprog ? polrootsff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25 %1 = [Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)), Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5))] ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT ? polrootsff(x^2 + 1) \\ not enough information to determine the base field *** at top-level: polrootsff(x^2+1) *** ^----------------- *** polrootsff: incorrect type in factorff. ? polrootsff(x^2 + t^0) \\ make sure one coeff. is a t_FFELT %3 = [3, 2] ? polrootsff(x^2 + t + 1) %4 = [2*t + 1, 3*t + 4] @eprog\noindent Notice that the second syntax is easier to use and much more readable. pari-2.7.5/src/functions/number_theoretical/divisors0000644000175000017500000000116311636712103021346 0ustar billbillFunction: divisors Section: number_theoretical C-Name: divisors Prototype: G Help: divisors(x): gives a vector formed by the divisors of x in increasing order. Description: (gen):vec divisors($1) Doc: creates a row vector whose components are the divisors of $x$. The factorization of $x$ (as output by \tet{factor}) can be used instead. By definition, these divisors are the products of the irreducible factors of $n$, as produced by \kbd{factor(n)}, raised to appropriate powers (no negative exponent may occur in the factorization). If $n$ is an integer, they are the positive divisors, in increasing order. pari-2.7.5/src/functions/number_theoretical/primes0000644000175000017500000000115312366172547021017 0ustar billbillFunction: primes Section: number_theoretical C-Name: primes0 Prototype: G Help: primes(n): returns the vector of the first n primes (integer), or the primes in interval n = [a,b]. Doc: creates a row vector whose components are the first $n$ prime numbers. (Returns the empty vector for $n \leq 0$.) A \typ{VEC} $n = [a,b]$ is also allowed, in which case the primes in $[a,b]$ are returned \bprog ? primes(10) \\ the first 10 primes %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([0,29]) \\ the primes up to 29 %2 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([15,30]) %3 = [17, 19, 23, 29] @eprog pari-2.7.5/src/functions/number_theoretical/nextprime0000644000175000017500000000074112314242551021517 0ustar billbillFunction: nextprime Section: number_theoretical C-Name: nextprime Prototype: G Help: nextprime(x): smallest pseudoprime >= x. Description: (gen):int nextprime($1) Doc: finds the smallest pseudoprime (see \tet{ispseudoprime}) greater than or equal to $x$. $x$ can be of any real type. Note that if $x$ is a pseudoprime, this function returns $x$ and not the smallest pseudoprime strictly larger than $x$. To rigorously prove that the result is prime, use \kbd{isprime}. pari-2.7.5/src/functions/number_theoretical/dirdiv0000644000175000017500000000051611636712103020766 0ustar billbillFunction: dirdiv Section: number_theoretical C-Name: dirdiv Prototype: GG Help: dirdiv(x,y): division of the Dirichlet series x by the Dirichlet series y. Doc: $x$ and $y$ being vectors of perhaps different lengths but with $y[1]\neq 0$ considered as \idx{Dirichlet series}, computes the quotient of $x$ by $y$, again as a vector. pari-2.7.5/src/functions/number_theoretical/coredisc0000644000175000017500000000215111636712103021275 0ustar billbillFunction: coredisc Section: number_theoretical C-Name: coredisc0 Prototype: GD0,L, Help: 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. Doc: a \emph{fundamental discriminant} is an integer of the form $t\equiv 1 \mod 4$ or $4t \equiv 8,12 \mod 16$, with $t$ squarefree (i.e.~$1$ or the discriminant of a quadratic number field). Given a non-zero integer $n$, this routine returns the (unique) fundamental discriminant $d$ such that $n=df^2$, $f$ a positive rational number. If $\fl$ is non-zero, returns the two-element row vector $[d,f]$. If $n$ is congruent to 0 or 1 modulo 4, $f$ is an integer, and a half-integer otherwise. By convention, \kbd{coredisc(0, 1))} returns $[0,1]$. Note that \tet{quaddisc}$(n)$ returns the same value as \kbd{coredisc}$(n)$, and also works with rational inputs $n\in\Q^*$. Variant: Also available are \fun{GEN}{coredisc}{GEN n} ($\fl = 0$) and \fun{GEN}{coredisc2}{GEN n} ($\fl = 1$) pari-2.7.5/src/functions/number_theoretical/qfbred0000644000175000017500000000263211636712103020751 0ustar billbillFunction: qfbred Section: number_theoretical C-Name: qfbred0 Prototype: GD0,L,DGDGDG Help: 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. Doc: reduces the binary quadratic form $x$ (updating Shanks's distance function if $x$ is indefinite). The binary digits of $\fl$ are toggles meaning \quad 1: perform a single \idx{reduction} step \quad 2: don't update \idx{Shanks}'s distance The arguments $d$, \var{isd}, \var{sd}, if present, supply the values of the discriminant, $\floor{\sqrt{d}}$, and $\sqrt{d}$ respectively (no checking is done of these facts). If $d<0$ these values are useless, and all references to Shanks's distance are irrelevant. Variant: Also available are \fun{GEN}{redimag}{GEN x} (for definite $x$), \noindent and for indefinite forms: \fun{GEN}{redreal}{GEN x} \fun{GEN}{rhoreal}{GEN x} (= \kbd{qfbred(x,1)}), \fun{GEN}{redrealnod}{GEN x, GEN isd} (= \kbd{qfbred(x,2,,isd)}), \fun{GEN}{rhorealnod}{GEN x, GEN isd} (= \kbd{qfbred(x,3,,isd)}). pari-2.7.5/src/functions/number_theoretical/omega0000644000175000017500000000055212314242551020574 0ustar billbillFunction: omega Section: number_theoretical C-Name: omega Prototype: lG Help: omega(x): number of distinct prime divisors of x. Doc: number of distinct prime divisors of $|x|$. $x$ must be of type integer. \bprog ? factor(392) %1 = [2 3] [7 2] ? omega(392) %2 = 2; \\ without multiplicity ? bigomega(392) %3 = 5; \\ = 3+2, with multiplicity @eprog pari-2.7.5/src/functions/number_theoretical/ispowerful0000644000175000017500000000071412314242551021703 0ustar billbillFunction: ispowerful 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. 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. \bprog ? ispowerful(50) %1 = 0 ? ispowerful(100) %2 = 1 ? ispowerful(5^3*(10^1000+1)^2) %3 = 1 @eprog pari-2.7.5/src/functions/number_theoretical/ispower0000644000175000017500000000230511636712103021173 0ustar billbillFunction: ispower Section: number_theoretical C-Name: ispower Prototype: lGDGD& Help: 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. Description: (int):small Z_isanypower($1, NULL) (int, &int):small Z_isanypower($1, &$2) Doc: if $k$ is given, returns true (1) if $x$ is a $k$-th power, false (0) if not. If $k$ is omitted, only integers and fractions are allowed for $x$ and the function returns the maximal $k \geq 2$ such that $x = n^k$ is a perfect power, or 0 if no such $k$ exist; in particular \kbd{ispower(-1)}, \kbd{ispower(0)}, and \kbd{ispower(1)} all return $0$. If a third argument $\&n$ is given and $x$ is indeed a $k$-th power, sets $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) @eprog Variant: Also available is \fun{long}{gisanypower}{GEN x, GEN *pty} ($k$ omitted). pari-2.7.5/src/functions/number_theoretical/qfbhclassno0000644000175000017500000000052311636712103022006 0ustar billbillFunction: qfbhclassno Section: number_theoretical C-Name: hclassno Prototype: G Help: qfbhclassno(x): Hurwitz-Kronecker class number of x>0. Doc: \idx{Hurwitz class number} of $x$, where $x$ is non-negative and congruent to 0 or 3 modulo 4. For $x > 5\cdot 10^5$, we assume the GRH, and use \kbd{quadclassunit} with default parameters. pari-2.7.5/src/functions/number_theoretical/removeprimes0000644000175000017500000000073411636712103022224 0ustar billbillFunction: removeprimes Section: number_theoretical C-Name: removeprimes Prototype: DG Help: 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. Doc: removes the primes listed in $x$ from the prime number table. In particular \kbd{removeprimes(addprimes())} empties the extra prime table. $x$ can also be a single integer. List the current extra primes if $x$ is omitted. pari-2.7.5/src/functions/number_theoretical/moebius0000644000175000017500000000027612314242551021152 0ustar billbillFunction: moebius Section: number_theoretical C-Name: moebius Prototype: lG Help: moebius(x): Moebius function of x. Doc: \idx{Moebius} $\mu$-function of $|x|$. $x$ must be of type integer. pari-2.7.5/src/functions/number_theoretical/numdiv0000644000175000017500000000033512314242551021005 0ustar billbillFunction: numdiv Section: number_theoretical C-Name: numdiv Prototype: G Help: numdiv(x): number of divisors of x. Description: (gen):int numdiv($1) Doc: number of divisors of $|x|$. $x$ must be of type integer. pari-2.7.5/src/functions/gp2c/0000755000175000017500000000000012613365633014550 5ustar billbillpari-2.7.5/src/functions/gp2c/unclone0000644000175000017500000000015411636712103016126 0ustar billbillFunction: unclone Class: gp2c Description: (small):void (void)0 /*unclone*/ (gen):void gunclone($1) pari-2.7.5/src/functions/gp2c/clone0000644000175000017500000000102012452257625015566 0ustar billbillFunction: clone Class: gp2c Description: (small):small:parens $1 (int):int gclone($1) (real):real gclone($1) (mp):mp gclone($1) (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) pari-2.7.5/src/functions/gp2c/DEBUGLEVEL0000644000175000017500000000017312314242551016101 0ustar billbillFunction: DEBUGLEVEL C-Name: DEBUGLEVEL Prototype: v Class: gp2c Description: ():small DEBUGLEVEL pari-2.7.5/src/functions/gp2c/copy0000644000175000017500000000060111636712103015432 0ustar billbillFunction: copy Class: gp2c Description: (small):small:parens $1 (int):int icopy($1) (real):real gcopy($1) (mp):mp gcopy($1) (vecsmall):vecsmall gcopy($1) (vec):vec gcopy($1) (pol):pol gcopy($1) (gen):gen gcopy($1) pari-2.7.5/src/functions/graphic/0000755000175000017500000000000012613365633015332 5ustar billbillpari-2.7.5/src/functions/graphic/psdraw0000644000175000017500000000104311636712103016543 0ustar billbillFunction: psdraw Class: highlevel Section: graphic C-Name: postdraw_flag Prototype: vGD0,L, Help: 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. Doc: same as \kbd{plotdraw}, except that the output is a PostScript program appended to the \kbd{psfile}, and flag!=0 scales the plot from size of the current output device to the standard PostScript plotting size pari-2.7.5/src/functions/graphic/psplothraw0000644000175000017500000000052411636712103017451 0ustar billbillFunction: psplothraw Class: highlevel Section: graphic C-Name: postplothraw Prototype: GGD0,L, Help: psplothraw(listx,listy,{flag=0}): same as plothraw, except that the output is a postscript program in psfile (pari.ps by default). Doc: same as \kbd{plothraw}, except that the output is a PostScript program appended to the \kbd{psfile}. pari-2.7.5/src/functions/graphic/psploth0000644000175000017500000000052411636712103016737 0ustar billbillFunction: psploth Class: highlevel Section: graphic C-Name: postploth Prototype: V=GGEpD0,L,D0,L, Help: 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). Doc: same as \kbd{ploth}, except that the output is a PostScript program appended to the \kbd{psfile}. pari-2.7.5/src/functions/graphic/plothsizes0000644000175000017500000000137311636712103017455 0ustar billbillFunction: plothsizes Class: highlevel Section: graphic C-Name: plothsizes_flag Prototype: D0,L, Help: 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. Doc: return data corresponding to the output window in the form of a 6-component vector: window width and height, sizes for ticks in horizontal and vertical directions (this is intended for the \kbd{gnuplot} interface and is currently not significant), width and height of characters. If $\fl = 0$, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size pari-2.7.5/src/functions/graphic/plotcopy0000644000175000017500000000156311636712103017123 0ustar billbillFunction: plotcopy Class: highlevel Section: graphic C-Name: rectcopy_gen Prototype: vLLGGD0,L, Help: 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. Doc: copy the contents of rectwindow \var{sourcew} to rectwindow \var{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 pari-2.7.5/src/functions/graphic/plotrbox0000644000175000017500000000101711636712103017115 0ustar billbillFunction: plotrbox Class: highlevel Section: graphic C-Name: rectrbox Prototype: vLGG Help: 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). Doc: draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x1+dx,y1+dy)$ are opposite corners, where $(x1,y1)$ is the current position of the cursor. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. pari-2.7.5/src/functions/graphic/plotstring0000644000175000017500000000163011636712103017452 0ustar billbillFunction: plotstring Class: highlevel Section: graphic C-Name: rectstring3 Prototype: vLsD0,L, Help: 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. Doc: draw on the rectwindow $w$ the String $x$ (see \secref{se:strings}), at the current position of the cursor. \fl\ is used for justification: bits 1 and 2 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 small gap between point and string: horizontal if bit 16 is set, vertical if bit 32 is set (see the tutorial for an example). pari-2.7.5/src/functions/graphic/plotlines0000644000175000017500000000234111636712103017256 0ustar billbillFunction: plotlines Class: highlevel Section: graphic C-Name: rectlines Prototype: vLGGD0,L, Help: 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. Doc: draw on the rectwindow $w$ the polygon such that the (x,y)-coordinates of the vertices are in the vectors of equal length $X$ and $Y$. For simplicity, the whole polygon is drawn, not only the part of the polygon which is inside the rectwindow. If $\fl$ is non-zero, close the polygon. In any case, the virtual cursor does not move. $X$ and $Y$ are allowed to be scalars (in this case, both have to). There, a single segment will be drawn, between the virtual cursor current position and the point $(X,Y)$. And only the part thereof which actually lies within the boundary of $w$. Then \emph{move} the virtual cursor to $(X,Y)$, even if it is outside the window. If you want to draw a line from $(x1,y1)$ to $(x2,y2)$ where $(x1,y1)$ is not necessarily the position of the virtual cursor, use \kbd{plotmove(w,x1,y1)} before using this function. pari-2.7.5/src/functions/graphic/plotcursor0000644000175000017500000000042411636712103017461 0ustar billbillFunction: plotcursor Class: highlevel Section: graphic C-Name: rectcursor Prototype: L Help: plotcursor(w): current position of cursor in rectwindow w. Doc: give as a 2-component vector the current (scaled) position of the virtual cursor corresponding to the rectwindow $w$. pari-2.7.5/src/functions/graphic/plotpointtype0000644000175000017500000000105111636712103020174 0ustar billbillFunction: plotpointtype Class: highlevel Section: graphic C-Name: rectpointtype Prototype: vLL Help: 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. Doc: change the type of points subsequently plotted in rectwindow $w$. $\var{type} = -1$ corresponds to a dot, larger values may correspond to something else. $w = -1$ changes highlevel plotting. This is only taken into account by the \kbd{gnuplot} interface. pari-2.7.5/src/functions/graphic/plotpoints0000644000175000017500000000162011636712103017457 0ustar billbillFunction: plotpoints Class: highlevel Section: graphic C-Name: rectpoints Prototype: vLGG Help: 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). Doc: draw on the rectwindow $w$ the points whose $(x,y)$-coordinates are in the vectors of equal length $X$ and $Y$ and which are inside $w$. The virtual cursor does \emph{not} move. This is basically the same function as \kbd{plothraw}, but either with no scaling factor or with a scale chosen using the function \kbd{plotscale}. As was the case with the \kbd{plotlines} function, $X$ and $Y$ are allowed to be (simultaneously) scalar. In this case, draw the single point $(X,Y)$ on the rectwindow $w$ (if it is actually inside $w$), and in any case \emph{move} the virtual cursor to position $(x,y)$. pari-2.7.5/src/functions/graphic/plotkill0000644000175000017500000000065611636712103017106 0ustar billbillFunction: plotkill Class: highlevel Section: graphic C-Name: killrect Prototype: vL Help: plotkill(w): erase the rectwindow w. Doc: erase rectwindow $w$ and free the corresponding memory. Note that if you want to use the rectwindow $w$ again, you have to use \kbd{plotinit} first to specify the new size. So it's better in this case to use \kbd{plotinit} directly as this throws away any previous work in the given rectwindow. pari-2.7.5/src/functions/graphic/plotinit0000644000175000017500000000237311636712103017114 0ustar billbillFunction: plotinit Class: highlevel Section: graphic C-Name: initrect_gen Prototype: vLDGDGD0,L, Help: 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. Doc: initialize the rectwindow $w$, destroying any rect objects you may have already drawn in $w$. The virtual cursor is set to $(0,0)$. The rectwindow size is set to width $x$ and height $y$; omitting either $x$ or $y$ means we use the full size of the device in that direction. If $\fl=0$, $x$ and $y$ represent pixel units. Otherwise, $x$ and $y$ are understood as fractions of the size of the current output device (hence must be between $0$ and $1$) and internally converted to pixels. The plotting device imposes an upper bound for $x$ and $y$, for instance the number of pixels for screen output. These bounds are available through the \tet{plothsizes} function. The following sequence initializes in a portable way (i.e independent of the output device) a window of maximal size, accessed through coordinates in the $[0,1000] \times [0,1000]$ range: \bprog s = plothsizes(); plotinit(0, s[1]-1, s[2]-1); plotscale(0, 0,1000, 0,1000); @eprog pari-2.7.5/src/functions/graphic/plotlinetype0000644000175000017500000000107611636712103020001 0ustar billbillFunction: plotlinetype Class: highlevel Section: graphic C-Name: rectlinetype Prototype: vLL Help: 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. Doc: change the type of lines subsequently plotted in rectwindow $w$. \var{type} $-2$ corresponds to frames, $-1$ to axes, larger values may correspond to something else. $w = -1$ changes highlevel plotting. This is only taken into account by the \kbd{gnuplot} interface. pari-2.7.5/src/functions/graphic/plotpointsize0000644000175000017500000000055411636712103020174 0ustar billbillFunction: plotpointsize Class: highlevel Section: graphic C-Name: rectpointsize Prototype: vLG Help: plotpointsize(w,size): change the "size" of following points in rectwindow w. w=-1 changes global value. Doc: changes the ``size'' of following points in rectwindow $w$. If $w = -1$, change it in all rectwindows. This only works in the \kbd{gnuplot} interface. pari-2.7.5/src/functions/graphic/plotbox0000644000175000017500000000102311636712103016730 0ustar billbillFunction: plotbox Class: highlevel Section: graphic C-Name: rectbox Prototype: vLGG Help: 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). Doc: let $(x1,y1)$ be the current position of the virtual cursor. Draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x2,y2)$ are opposite corners. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. pari-2.7.5/src/functions/graphic/plotrline0000644000175000017500000000073711636712103017264 0ustar billbillFunction: plotrline Class: highlevel Section: graphic C-Name: rectrline Prototype: vLGG Help: 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. Doc: draw in the rectwindow $w$ the part of the segment $(x1,y1)-(x1+dx,y1+dy)$ which is inside $w$, where $(x1,y1)$ is the current position of the virtual cursor, and move the virtual cursor to $(x1+dx,y1+dy)$ (even if it is outside the window). pari-2.7.5/src/functions/graphic/plotrmove0000644000175000017500000000061611636712103017277 0ustar billbillFunction: plotrmove Class: highlevel Section: graphic C-Name: rectrmove Prototype: vLGG Help: plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w. Doc: move the virtual cursor of the rectwindow $w$ to position $(x1+dx,y1+dy)$, where $(x1,y1)$ is the initial position of the cursor (i.e.~to position $(dx,dy)$ relative to the initial cursor). pari-2.7.5/src/functions/graphic/ploth0000644000175000017500000001220012413013143016356 0ustar billbillFunction: ploth Class: highlevel Section: graphic C-Name: ploth Prototype: 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 Help: 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. Doc: high precision plot of the function $y=f(x)$ represented by the expression \var{expr}, $x$ going from $a$ to $b$. This opens a specific window (which is killed whenever you click on it), and returns a four-component vector giving the coordinates of the bounding box in the form $[\var{xmin},\var{xmax},\var{ymin},\var{ymax}]$. \misctitle{Important note} \kbd{ploth} may evaluate \kbd{expr} thousands of times; given the relatively low resolution of plotting devices, few significant digits of the result will be meaningful. Hence you should keep the current precision to a minimum (e.g.~9) before calling this function. $n$ specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values (1000 for general plot, 1500 for parametric plot, and 8 for recursive plot). If no $\fl$ is given, \var{expr} is either a scalar expression $f(X)$, in which case the plane curve $y=f(X)$ will be drawn, or a vector $[f_1(X),\dots,f_k(X)]$, and then all the curves $y=f_i(X)$ will be drawn in the same window. \noindent The binary digits of $\fl$ mean: \item $1 = \kbd{Parametric}$: \tev{parametric plot}. Here \var{expr} must be a vector with an even number of components. Successive pairs are then understood as the parametric coordinates of a plane curve. Each of these are then drawn. For instance: \bprog ploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") ploth(X=0,2*Pi,[sin(X),cos(X)]) ploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric") @eprog\noindent draw successively a circle, two entwined sinusoidal curves and a circle cut by the line $y=x$. \item $2 = \kbd{Recursive}$: \tev{recursive plot}. If this flag is set, only \emph{one} curve can be drawn at a time, i.e.~\var{expr} must be either a two-component vector (for a single parametric curve, and the parametric flag \emph{has} to be set), or a scalar function. The idea is to choose pairs of successive reference points, and if their middle point is not too far away from the segment joining them, draw this as a local approximation to the curve. Otherwise, add the middle point to the reference points. This is fast, and usually more precise than usual plot. Compare the results of \bprog ploth(X=-1,1, sin(1/X), "Recursive") ploth(X=-1,1, sin(1/X)) @eprog\noindent for instance. But beware that if you are extremely unlucky, or choose too few reference points, you may draw some nice polygon bearing little resemblance to the original curve. For instance you should \emph{never} plot recursively an odd function in a symmetric interval around 0. Try \bprog ploth(x = -20, 20, sin(x), "Recursive") @eprog\noindent to see why. Hence, it's usually a good idea to try and plot the same curve with slightly different parameters. The other values toggle various display options: \item $4 = \kbd{no\_Rescale}$: do not rescale plot according to the computed extrema. This is used in conjunction with \tet{plotscale} when graphing multiple functions on a rectwindow (as a \tet{plotrecth} call): \bprog s = plothsizes(); plotinit(0, s[2]-1, s[2]-1); plotscale(0, -1,1, -1,1); plotrecth(0, t=0,2*Pi, [cos(t),sin(t)], "Parametric|no_Rescale") plotdraw([0, -1,1]); @eprog\noindent This way we get a proper circle instead of the distorted ellipse produced by \bprog ploth(t=0,2*Pi, [cos(t),sin(t)], "Parametric") @eprog \item $8 = \kbd{no\_X\_axis}$: do not print the $x$-axis. \item $16 = \kbd{no\_Y\_axis}$: do not print the $y$-axis. \item $32 = \kbd{no\_Frame}$: do not print frame. \item $64 = \kbd{no\_Lines}$: only plot reference points, do not join them. \item $128 = \kbd{Points\_too}$: plot both lines and points. \item $256 = \kbd{Splines}$: use splines to interpolate the points. \item $512 = \kbd{no\_X\_ticks}$: plot no $x$-ticks. \item $1024 = \kbd{no\_Y\_ticks}$: plot no $y$-ticks. \item $2048 = \kbd{Same\_ticks}$: plot all ticks with the same length. \item $4096 = \kbd{Complex}$: is a parametric plot but where each member of \kbd{expr} is considered a complex number encoding the two coordinates of a point. For instance: \bprog ploth(X=0,2*Pi,exp(I*X), "Complex") ploth(X=0,2*Pi,[(1+I)*X,exp(I*X)], "Complex") @eprog\noindent will draw respectively a circle and a circle cut by the line $y=x$. pari-2.7.5/src/functions/graphic/plotmove0000644000175000017500000000034211636712103017111 0ustar billbillFunction: plotmove Class: highlevel Section: graphic C-Name: rectmove Prototype: vLGG Help: plotmove(w,x,y): move cursor to position x,y in rectwindow w. Doc: move the virtual cursor of the rectwindow $w$ to position $(x,y)$. pari-2.7.5/src/functions/graphic/plotscale0000644000175000017500000000134711636712103017240 0ustar billbillFunction: plotscale Class: highlevel Section: graphic C-Name: rectscale Prototype: vLGGGG Help: 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>=_ Section: symbolic_operators C-Name: gshiftre Prototype: &L Help: x>>=y: shortcut for x=x>>y. Description: (*small, small):small:parens $1 >>= $(2) (*int, small):int:parens $1 = shifti($1, -$(2)) (*mp, small):mp:parens $1 = mpshift($1, -$(2)) (*gen, small):mp:parens $1 = gshift($1, -$(2)) pari-2.7.5/src/functions/symbolic_operators/shiftr0000644000175000017500000000045411636712103021051 0ustar billbillFunction: _>>_ Section: symbolic_operators C-Name: gshift_right Prototype: GL Help: x>>y Description: (small, small):small:parens $(1)>>$(2) (int, small):int shifti($1, -$(2)) (mp, small):mp mpshift($1, -$(2)) (gen, small):mp gshift($1, -$(2)) pari-2.7.5/src/functions/symbolic_operators/deriv0000644000175000017500000000027511636712103020664 0ustar billbillFunction: _' Section: symbolic_operators C-Name: deriv Prototype: GDn Help: x': derivative of x with respect to the main variable. Description: (gen):gen deriv($1,-1) pari-2.7.5/src/functions/symbolic_operators/divrounde0000644000175000017500000000052111636712103021544 0ustar billbillFunction: _\/=_ Section: symbolic_operators C-Name: gdivrounde Prototype: &G Help: x\/=y: shortcut for x=x\/y. Description: (*int, int):int:parens $1 = gdivround($1, $2) (*pol, gen):gen:parens $1 = gdivround($1, $2) (*gen, gen):gen:parens $1 = gdivround($1, $2) pari-2.7.5/src/functions/symbolic_operators/ge0000644000175000017500000000142612314242551020144 0ustar billbillFunction: _>=_ Help: x>=y: return 1 if x is greater or equal to y, 0 otherwise. Section: symbolic_operators C-Name: gge Prototype: GG Description: (small, small):bool:parens $(1) >= $(2) (lg, lg):bool:parens $(1) >= $(2) (lg, small):bool:parens $(1) > $(2) (small, int):bool:parens cmpsi($1, $2) >= 0 (int, small):bool:parens cmpis($1, $2) >= 0 (int, int):bool:parens cmpii($1, $2) >= 0 (mp, mp):bool:parens mpcmp($1, $2) >= 0 (str, str):bool:parens strcmp($1, $2) >= 0 (small, gen):bool:parens gcmpsg($1, $2) >= 0 (gen, small):bool:parens gcmpgs($1, $2) >= 0 (gen, gen):bool:parens gcmp($1, $2) >= 0 pari-2.7.5/src/functions/symbolic_operators/le0000644000175000017500000000151612314242551020151 0ustar billbillFunction: _<=_ Help: x<=y: return 1 if x is less or equal to y, 0 otherwise. Section: symbolic_operators C-Name: gle Prototype: GG Description: (small, small):bool:parens $(1) <= $(2) (small, lg):bool:parens $(1) < $(2) (lg, lg):bool:parens $(1) <= $(2) (small, int):bool:parens cmpsi($1, $2) <= 0 (int, lg):bool:parens cmpis($1, $2) < 0 (int, small):bool:parens cmpis($1, $2) <= 0 (int, int):bool:parens cmpii($1, $2) <= 0 (mp, mp):bool:parens mpcmp($1, $2) <= 0 (str, str):bool:parens strcmp($1, $2) <= 0 (small, gen):bool:parens gcmpsg($1, $2) <= 0 (gen, small):bool:parens gcmpgs($1, $2) <= 0 (gen, gen):bool:parens gcmp($1, $2) <= 0 pari-2.7.5/src/functions/symbolic_operators/adde0000644000175000017500000000157411636712103020453 0ustar billbillFunction: _+=_ C-Name: gadde Prototype: &G Help: x+=y: shortcut for x=x+y. Section: symbolic_operators Description: (*small, small):small:parens $1 += $(2) (*lg, small):lg:parens $1 += $(2) (*int, small):int:parens $1 = addis($1, $2) (*int, int):int:parens $1 = addii($1, $2) (*real, small):real:parens $1 = addrs($1, $2) (*real, int):real:parens $1 = addir($2, $1) (*real, real):real:parens $1 = addrr($1, $2) (*mp, mp):mp:parens $1 = mpadd($1, $2) (*pol, small):gen:parens $1 = gaddgs($1, $2) (*pol, gen):gen:parens $1 = gadd($1, $2) (*vec, gen):gen:parens $1 = gadd($1, $2) (*gen, small):gen:parens $1 = gaddgs($1, $2) (*gen, gen):gen:parens $1 = gadd($1, $2) pari-2.7.5/src/functions/symbolic_operators/compr0000644000175000017500000000132012314242551020662 0ustar billbillFunction: [_|_<-_,_;_] Section: programming/internals C-Name: vecexpr1 Prototype: mGVDEDE Help: [a(x)|x<-b,c(x);...] Wrapper: (,,G,bG) Description: (gen,,closure):gen veccatapply(${3 cookie}, ${3 wrapper}, $1) (gen,,closure,closure):gen veccatselapply(${4 cookie}, ${4 wrapper}, ${3 cookie}, ${3 wrapper}, $1) Function: [_|_<-_,_] Section: programming/internals C-Name: vecexpr0 Prototype: GVDEDE Help: [a(x)|x<-b,c(x)] = apply(a,select(c,b)) Wrapper: (,,G,bG) Description: (gen,,closure):gen vecapply(${3 cookie}, ${3 wrapper}, $1) (gen,,,closure):gen vecselect(${4 cookie}, ${4 wrapper}, $1) (gen,,closure,closure):gen vecselapply(${4 cookie}, ${4 wrapper}, ${3 cookie}, ${3 wrapper}, $1) pari-2.7.5/src/functions/symbolic_operators/hist0000644000175000017500000000034712366172547020537 0ustar billbillFunction: % C-Name: pari_get_hist Prototype: D0,L, Section: symbolic_operators Help: last history item. Function: %# C-Name: pari_get_histtime Prototype: lD0,L, Section: symbolic_operators Help: time to compute last history item. pari-2.7.5/src/functions/symbolic_operators/not0000644000175000017500000000025311636712103020347 0ustar billbillFunction: !_ Help: !_ Section: symbolic_operators C-Name: gnot Prototype: G Description: (negbool):bool:parens $1 (bool):negbool:parens $1 pari-2.7.5/src/functions/symbolic_operators/mule0000644000175000017500000000150711636712103020514 0ustar billbillFunction: _*=_ Section: symbolic_operators C-Name: gmule Prototype: &G Help: x*=y: shortcut for x=x*y. Description: (*small, small):small:parens $1 *= $(2) (*int, small):int:parens $1 = mulis($1, $2) (*int, int):int:parens $1 = mulii($1, $2) (*real, small):real:parens $1 = mulrs($1, $2) (*real, int):real:parens $1 = mulri($1, $2) (*real, real):real:parens $1 = mulrr($1, $2) (*mp, mp):mp:parens $1 = mpmul($1, $2) (*pol, small):gen:parens $1 = gmulgs($1, $2) (*pol, gen):gen:parens $1 = gmul($1, $2) (*vec, gen):gen:parens $1 = gmul($1, $2) (*gen, small):gen:parens $1 = gmulgs($1, $2) (*gen, gen):gen:parens $1 = gmul($1, $2) pari-2.7.5/src/functions/symbolic_operators/mod0000644000175000017500000000071111636712103020325 0ustar billbillFunction: _%_ Section: symbolic_operators C-Name: gmod Prototype: GG Help: x%y: Euclidean remainder of x and y. Description: (small, small):small smodss($1, $2) (small, int):int modsi($1, $2) (int, small):small smodis($1, $2) (int, int):int modii($1, $2) (gen, small):gen gmodgs($1, $2) (small, gen):gen gmodsg($1, $2) (gen, gen):gen gmod($1, $2) pari-2.7.5/src/functions/symbolic_operators/sub0000644000175000017500000000140311636712103020336 0ustar billbillFunction: _-_ Section: symbolic_operators C-Name: gsub Prototype: GG Help: x-y: difference of x and y. Description: (small, small):small:parens $(1) - $(2) (lg, small):lg:parens $(1) - $(2) (int, small):int subis($1, $2) (small, int):int subsi($1, $2) (int, int):int subii($1, $2) (real, small):real subrs($1, $2) (small, real):real subsr($1, $2) (real, real):real subrr($1, $2) (mp, real):real mpsub($1, $2) (real, mp):real mpsub($1, $2) (mp, mp):mp mpsub($1, $2) (gen, small):gen gsubgs($1, $2) (small, gen):gen gsubsg($1, $2) (gen, gen):gen gsub($1, $2) pari-2.7.5/src/functions/symbolic_operators/slice0000644000175000017500000000067012314242551020650 0ustar billbillFunction: _[_.._] Section: symbolic_operators C-Name: vecslice0 Prototype: GD0,L,L Help: x[a..b] = [x[a],x[a+1],...,x[b]] Function: _[_.._,_.._] Section: symbolic_operators C-Name: matslice0 Prototype: GD0,L,D0,L,D0,L,D0,L, Help: 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]] pari-2.7.5/src/functions/symbolic_operators/lt0000644000175000017500000000141212314242551020163 0ustar billbillFunction: _<_ Help: x_ Help: x>y: return 1 if x is strictly greater than y, 0 otherwise. Section: symbolic_operators C-Name: ggt Prototype: GG Description: (small, small):bool:parens $(1) > $(2) (lg, lg):bool:parens $(1) > $(2) (small, lg):bool:parens $(1) >= $(2) (small, int):bool:parens cmpsi($1, $2) > 0 (int, small):bool:parens cmpis($1, $2) > 0 (int, int):bool:parens cmpii($1, $2) > 0 (mp, mp):bool:parens mpcmp($1, $2) > 0 (str, str):bool:parens strcmp($1, $2) > 0 (small, gen):bool:parens gcmpsg($1, $2) > 0 (gen, small):bool:parens gcmpgs($1, $2) > 0 (gen, gen):bool:parens gcmp($1, $2) > 0 pari-2.7.5/src/functions/symbolic_operators/divente0000644000175000017500000000060111636712103021202 0ustar billbillFunction: _\=_ Section: symbolic_operators C-Name: gdivente Prototype: &G Help: x\=y: shortcut for x=x\y. Description: (*small, small):small:parens $1 /= $(2) (*int, int):int:parens $1 = gdivent($1, $2) (*pol, gen):gen:parens $1 = gdivent($1, $2) (*gen, gen):gen:parens $1 = gdivent($1, $2) pari-2.7.5/src/functions/symbolic_operators/and0000644000175000017500000000022611636712103020311 0ustar billbillFunction: _&&_ C-Name: andpari Prototype: GE Help: _&&_ Section: symbolic_operators Description: (bool, bool):bool:parens $(1) && $(2) pari-2.7.5/src/functions/programming/0000755000175000017500000000000012613365633016237 5ustar billbillpari-2.7.5/src/functions/programming/parselect0000644000175000017500000000112012366172547020143 0ustar billbillFunction: parselect Section: programming/parallel C-Name: parselect Prototype: GGD0,L, Help: 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) Doc: selects elements of $A$ according to the selection function $f$, done in parallel. If \fl is $1$, return the indices of those elements (indirect selection) The function \kbd{f} must not access global variables or variables declared with local(), and must be free of side effects. pari-2.7.5/src/functions/programming/parforprime0000644000175000017500000000160012366172547020512 0ustar billbillFunction: parforprime Section: programming/parallel C-Name: parforprime Prototype: vV=GDGJDVDI 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). 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 for $j$ the value of \kbd{expr1} (dependent on $p$). If $b$ is omitted, the loop will not stop. It is allowed fo \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}, however in that case, \kbd{expr2} will still be evaluated for all remaining value of $p$ less than the current one, unless a subsequent \kbd{break}/\kbd{next}/\kbd{return} happens. %\syn{NO} pari-2.7.5/src/functions/programming/readstr0000644000175000017500000000061212366172547017632 0ustar billbillFunction: readstr Class: gp Section: programming/specific C-Name: readstr Prototype: D"",s, Help: readstr({filename}): returns the vector of GP strings containing the lines in filename. Doc: 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}. pari-2.7.5/src/functions/programming/break0000644000175000017500000000075211636712103017242 0ustar billbillFunction: break Section: programming/control C-Name: break0 Prototype: D1,L, Help: break({n=1}): interrupt execution of current instruction sequence, and exit from the n innermost enclosing loops. Doc: interrupts execution of current \var{seq}, and immediately exits from the $n$ innermost enclosing loops, within the current function call (or the top level loop); the integer $n$ must be positive. If $n$ is greater than the number of enclosing loops, all enclosing loops are exited. pari-2.7.5/src/functions/programming/system0000644000175000017500000000067712314242551017507 0ustar billbillFunction: system Class: gp Section: programming/specific C-Name: system0 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 logfile), and control returns to the PARI system. This simply calls the C \kbd{system} command. pari-2.7.5/src/functions/programming/getrand0000644000175000017500000000067211636712103017603 0ustar billbillFunction: getrand Section: programming/specific C-Name: getrand Prototype: Help: getrand(): current value of random number seed. Doc: returns the current value of the seed used by the pseudo-random number generator \tet{random}. Useful mainly for debugging purposes, to reproduce a specific chain of computations. The returned value is technical (reproduces an internal state array), and can only be used as an argument to \tet{setrand}. pari-2.7.5/src/functions/programming/write0000644000175000017500000000046111636712103017305 0ustar billbillFunction: write Section: programming/specific C-Name: write0 Prototype: vss* Help: write(filename,{str}*): appends the remaining arguments (same output as print) to filename. Doc: writes (appends) to \var{filename} the remaining arguments, and appends a newline (same output as \kbd{print}). %\syn{NO} pari-2.7.5/src/functions/programming/printsep10000644000175000017500000000063712314242551020104 0ustar billbillFunction: printsep1 Section: programming/specific C-Name: printsep1 Prototype: vss* Help: printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', without ending with a newline. Doc: outputs its (string) arguments in raw format, without ending with a newline. Successive entries are separated by \var{sep}: \bprog ? printsep1(":", 1,2,3,4);print("|") 1:2:3:4 @eprog %\syn{NO} pari-2.7.5/src/functions/programming/parsum0000644000175000017500000000127412366172547017502 0ustar billbillFunction: parsum Section: programming/parallel C-Name: parsum Prototype: V=GGJDG Description: (gen,gen,closure,?gen):gen parsum($1, $2, $3, $4) Help: 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) Doc: sum of expression \var{expr}, initialized at $x$, the formal parameter going from $a$ to $b$, evaluated in parallel in random order. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog parsum(i=1,1000,ispseudoprime(2^prime(i)-1)) @eprog returns the numbers of prime numbers among the first $1000$ Mersenne numbers. %\syn{NO} pari-2.7.5/src/functions/programming/setrand0000644000175000017500000000077011636712103017616 0ustar billbillFunction: setrand Section: programming/specific C-Name: setrand Prototype: vG Help: setrand(n): reset the seed of the random number generator to n. Doc: reseeds the random number generator using the seed $n$. No value is returned. The seed is either a technical array output by \kbd{getrand}, or a small positive integer, used to generate deterministically a suitable state array. For instance, running a randomized computation starting by \kbd{setrand(1)} twice will generate the exact same output. pari-2.7.5/src/functions/programming/version0000644000175000017500000000451512366172547017661 0ustar billbillFunction: version Section: programming/specific C-Name: pari_version Prototype: Help: version(): returns the PARI version as [major,minor,patch] or [major,minor,patch,VCSversion]. Doc: returns the current version number as a \typ{VEC} with three integer components (major version number, minor version number and patchlevel); if your sources were obtained through our version control system, this will be followed by further more precise arguments, including e.g.~a~\kbd{git} \emph{commit hash}. This function is present in all versions of PARI following releases 2.3.4 (stable) and 2.4.3 (testing). Unless you are working with multiple development versions, you probably only care about the 3 first numeric components. In any case, the \kbd{lex} function offers a clever way to check against a particular version number, since it will compare each successive vector entry, numerically or as strings, and will not mind if the vectors it compares have different lengths: \bprog if (lex(version(), [2,3,5]) >= 0, \\ code to be executed if we are running 2.3.5 or more recent. , \\ compatibility code ); @eprog\noindent On a number of different machines, \kbd{version()} could return either of \bprog %1 = [2, 3, 4] \\ released version, stable branch %1 = [2, 4, 3] \\ released version, testing branch %1 = [2, 6, 1, 15174, ""505ab9b"] \\ development @eprog In particular, if you are only working with released versions, the first line of the gp introductory message can be emulated by \bprog [M,m,p] = version(); printf("GP/PARI CALCULATOR Version %s.%s.%s", M,m,p); @eprog\noindent If you \emph{are} working with many development versions of PARI/GP, the 4th and/or 5th components can be profitably included in the name of your logfiles, for instance. \misctitle{Technical note} For development versions obtained via \kbd{git}, the 4th and 5th components are liable to change eventually, but we document their current meaning for completeness. The 4th component counts the number of reachable commits in the branch (analogous to \kbd{svn}'s revision number), and the 5th is the \kbd{git} commit hash. In particular, \kbd{lex} comparison still orders correctly development versions with respect to each others or to released versions (provided we stay within a given branch, e.g. \kbd{master})! pari-2.7.5/src/functions/programming/dbg_x0000644000175000017500000000072612314242551017241 0ustar billbillFunction: dbg_x Section: programming/control C-Name: dbgGEN Prototype: vGD-1,L, Help: dbg_x(A{,n}): print inner structure of A, complete if n is omitted, up to level n otherwise. Intended for debugging. Doc: Print the inner structure of \kbd{A}, complete if \kbd{n} is omitted, up to level \kbd{n} otherwise. This is useful for debugging. This is similar to \b{x} but does not require \kbd{A} to be an history entry. In particular, it can be used in the break loop. pari-2.7.5/src/functions/programming/externstr0000644000175000017500000000071211636712103020210 0ustar billbillFunction: externstr Class: gp Section: programming/specific C-Name: externstr Prototype: s Help: externstr(str): execute shell command str, and returns the result as a vector of GP strings, one component per output line. Doc: 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. pari-2.7.5/src/functions/programming/forcomposite0000644000175000017500000000272212314242551020665 0ustar billbillFunction: _forcomposite_init Class: gp2c_internal Help: Initialize forcomposite_t Description: (forcomposite,int):void forcomposite_init(&$1, $2, NULL) (forcomposite,int,int):void forcomposite_init(&$1, $2, $3) Function: _forcomposite_next Class: gp2c_internal Help: Compute the next composite Description: (forcomposite):int forcomposite_next(&$1) Function: forcomposite Section: programming/control C-Name: forcomposite Prototype: vV=GDGI Help: 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 Iterator: (gen,gen,?gen) (forcomposite, _forcomposite_init, _forcomposite_next) Doc: evaluates \var{seq}, where the formal variable $n$ ranges over the composite numbers between the non-negative real numbers $a$ to $b$, including $a$ and $b$ if they are composite. Nothing is done if $a>b$. \bprog ? forcomposite(n = 0, 10, print(n)) 4 6 8 9 10 @eprog\noindent Omitting $b$ means we will run through all composites $\geq a$, starting an infinite loop; it is expected that the user will break out of the loop himself at some point, using \kbd{break} or \kbd{return}. Note that the value of $n$ cannot be modified within \var{seq}: \bprog ? forcomposite(n = 2, 10, n = []) *** at top-level: forcomposite(n=2,10,n=[]) *** ^--- *** index read-only: was changed to []. @eprog pari-2.7.5/src/functions/programming/read0000644000175000017500000000150312405547147017075 0ustar billbillFunction: read Class: gp Section: programming/specific C-Name: read0 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. Description: (str):gen gp_read_file($1) Doc: reads in the file \var{filename} (subject to string expansion). If \var{filename} is omitted, re-reads the last file that was fed into \kbd{gp}. The return value is the result of the last expression evaluated. If a GP \tet{binary file} is read using this command (see \secref{se:writebin}), the file is loaded and the last object in the file is returned. 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. pari-2.7.5/src/functions/programming/alarm0000644000175000017500000000362012366172547017264 0ustar billbillFunction: alarm Class: gp Section: programming/specific C-Name: gp_alarm Prototype: D0,L,DE Help: 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. Doc: if \var{code} is omitted, trigger an \var{e\_ALARM} exception after $s$ seconds, cancelling any previously set alarm; stop a pending alarm if $s = 0$ or is omitted. Otherwise, if $s$ is positive, the function evaluates \var{code}, aborting after $s$ seconds. The return value is the value of \var{code} if it ran to completion before the alarm timeout, and a \typ{ERROR} object otherwise. \bprog ? p = nextprime(10^25); q = nextprime(10^26); N = p*q; ? E = alarm(1, factor(N)); ? type(E) %3 = "t_ERROR" ? print(E) %4 = error("alarm interrupt after 964 ms.") ? alarm(10, factor(N)); \\ enough time %5 = [ 10000000000000000000000013 1] [100000000000000000000000067 1] @eprog\noindent Here is a more involved example: the function \kbd{timefact(N,sec)} below tries to factor $N$ and gives up after \var{sec} seconds, returning a partial factorisation. \bprog \\ Time-bounded partial factorization default(factor_add_primes,1); timefact(N,sec)= { F = alarm(sec, factor(N)); if (type(F) == "t_ERROR", factor(N, 2^24), F); } @eprog\noindent We either return the factorization directly, or replace the \typ{ERROR} result by a simple bounded factorization \kbd{factor(N, 2\pow 24)}. Note the \tet{factor_add_primes} trick: any prime larger than $2^{24}$ discovered while attempting the initial factorization is stored and remembered. When the alarm rings, the subsequent bounded factorization finds 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. pari-2.7.5/src/functions/programming/forstep0000644000175000017500000000110711636712103017633 0ustar billbillFunction: forstep Section: programming/control C-Name: forstep Prototype: vV=GGGI Help: 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). Doc: evaluates \var{seq}, where the formal variable $X$ goes from $a$ to $b$, in increments of $s$. Nothing is done if $s>0$ and $a>b$ or if $s<0$ and $ab$. $a$ and $b$ must be in $\R$. pari-2.7.5/src/functions/programming/getabstime0000644000175000017500000000053312405547147020310 0ustar billbillFunction: getabstime 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}: \bprog my (t = getabstime()); ... print("Time: ", getabstime() - t); @eprog pari-2.7.5/src/functions/programming/parvector0000644000175000017500000000135012366172547020173 0ustar billbillFunction: parvector Section: programming/parallel C-Name: parvector Prototype: LVJ Description: (small,,closure):vec parvector($1, $3) Help: parvector(N,i,expr): as vector(N,i,expr) but the evaluations of expr are done in parallel. Doc: As \kbd{vector(N,i,expr)} but the evaluations of \kbd{expr} are done in parallel. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog parvector(10,i,quadclassunit(2^(100+i)+1).no) @eprog\noindent computes the class numbers in parallel. %\syn{NO} Function: _parvector_worker Section: programming/internals C-Name: parvector_worker Prototype: GG Help: _parvector_worker(i,C): evaluate the closure C on i. pari-2.7.5/src/functions/programming/global0000644000175000017500000000024511636712103017413 0ustar billbillFunction: global Section: programming/specific Help: global(list of variables): obsolete. Scheduled for deletion. Doc: obsolete. Scheduled for deletion. % \syn{NO} pari-2.7.5/src/functions/programming/write10000644000175000017500000000047111636712103017367 0ustar billbillFunction: write1 Section: programming/specific C-Name: write1 Prototype: vss* Help: write1(filename,{str}*): appends the remaining arguments (same output as print1) to filename. Doc: writes (appends) to \var{filename} the remaining arguments without a trailing newline (same output as \kbd{print1}). %\syn{NO} pari-2.7.5/src/functions/programming/forvec0000644000175000017500000000247312314242551017443 0ustar billbillFunction: _forvec_init Class: gp2c_internal Help: Initializes parameters for forvec. Description: (forvec, gen, ?small):void forvec_init(&$1, $2, $3) Function: _forvec_next Class: gp2c_internal Help: Initializes parameters for forvec. Description: (forvec):vec forvec_next(&$1) Function: forvec Section: programming/control C-Name: forvec Prototype: vV=GID0,L, Iterator: (gen,gen,?small) (forvec, _forvec_init, _forvec_next) Help: 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. Doc: Let $v$ be an $n$-component vector (where $n$ is arbitrary) of two-component vectors $[a_i,b_i]$ for $1\le i\le n$. This routine evaluates \var{seq}, where the formal variables $X[1],\dots, X[n]$ go from $a_1$ to $b_1$,\dots, from $a_n$ to $b_n$, i.e.~$X$ goes from $[a_1,\dots,a_n]$ to $[b_1,\dots,b_n]$ with respect to the lexicographic ordering. (The formal variable with the highest index moves the fastest.) If $\fl=1$, generate only nondecreasing vectors $X$, and if $\fl=2$, generate only strictly increasing vectors $X$. The type of $X$ is the same as the type of $v$: \typ{VEC} or \typ{COL}. pari-2.7.5/src/functions/programming/extern0000644000175000017500000000062011636712103017455 0ustar billbillFunction: extern Class: gp Section: programming/specific C-Name: extern0 Prototype: s Help: extern(str): execute shell command str, and feeds the result to GP (as if loading from file). Doc: 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. pari-2.7.5/src/functions/programming/readvec0000644000175000017500000000170711636712103017570 0ustar billbillFunction: readvec Section: programming/specific C-Name: gp_readvec_file Prototype: D"",s, Help: readvec({filename}): create a vector whose components are the evaluation of all the expressions found in the input file filename. Description: (str):gen gp_readvec_file($1) Doc: reads in the file \var{filename} (subject to string expansion). If \var{filename} is omitted, re-reads the last file that was fed into \kbd{gp}. The return value is a vector whose components are the evaluation of all sequences of instructions contained in the file. For instance, if \var{file} contains \bprog 1 2 3 @eprog\noindent then we will get: \bprog ? \r a %1 = 1 %2 = 2 %3 = 3 ? read(a) %4 = 3 ? readvec(a) %5 = [1, 2, 3] @eprog In general a sequence is just a single line, but as usual braces and \kbd{\bs} may be used to enter multiline sequences. Variant: The underlying library function \fun{GEN}{gp_readvec_stream}{FILE *f} is usually more flexible. pari-2.7.5/src/functions/programming/type0000644000175000017500000000114011636712103017127 0ustar billbillFunction: type Section: programming/specific C-Name: type0 Prototype: G Help: type(x): return the type of the GEN x. Description: (gen):typ typ($1) Doc: this is useful only under \kbd{gp}. Returns the internal type name of the PARI object $x$ as a string. Check out existing type names with the metacommand \b{t}. For example \kbd{type(1)} will return "\typ{INT}". Variant: The macro \kbd{typ} is usually simpler to use since it returns a \kbd{long} that can easily be matched with the symbols \typ{*}. The name \kbd{type} was avoided since it is a reserved identifier for some compilers. pari-2.7.5/src/functions/programming/select0000644000175000017500000000532012413013143017421 0ustar billbillFunction: select Section: programming/specific C-Name: select0 Prototype: GGD0,L, Help: 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) Wrapper: (bG) Description: (gen,gen):gen genselect(${1 cookie}, ${1 wrapper}, $2) (gen,gen,0):gen genselect(${1 cookie}, ${1 wrapper}, $2) (gen,gen,1):gen genindexselect(${1 cookie}, ${1 wrapper}, $2) Doc: We first describe the default behavior, when $\fl$ is 0 or omitted. Given a vector or list \kbd{A} and a \typ{CLOSURE} \kbd{f}, \kbd{select} returns the elements $x$ of \kbd{A} such that $f(x)$ is non-zero. In other words, \kbd{f} is seen as a selection function returning a boolean value. \bprog ? select(x->isprime(x), vector(50,i,i^2+1)) %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] ? select(x->(x<100), %) %2 = [2, 5, 17, 37] @eprog\noindent returns the primes of the form $i^2+1$ for some $i\leq 50$, then the elements less than 100 in the preceding result. The \kbd{select} function also applies to a matrix \kbd{A}, seen as a vector of columns, i.e. it selects columns instead of entries, and returns the matrix whose columns are the selected ones. \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? [ x | x <- vector(50,i,i^2+1), isprime(x) ] %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog \noindent If $\fl = 1$, this function returns instead the \emph{indices} of the selected elements, and not the elements themselves (indirect selection): \bprog ? V = vector(50,i,i^2+1); ? select(x->isprime(x), V, 1) %2 = Vecsmall([1, 2, 4, 6, 10, 14, 16, 20, 24, 26, 36, 40]) ? vecextract(V, %) %3 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog\noindent The following function lists the elements in $(\Z/N\Z)^*$: \bprog ? invertibles(N) = select(x->gcd(x,N) == 1, [1..N]) @eprog \noindent Finally \bprog ? select(x->x, M) @eprog\noindent selects the non-0 entries in \kbd{M}. If the latter is a \typ{MAT}, we extract the matrix of non-0 columns. Note that \emph{removing} entries instead of selecting them just involves replacing the selection function \kbd{f} with its negation: \bprog ? select(x->!isprime(x), vector(50,i,i^2+1)) @eprog \synt{genselect}{void *E, long (*fun)(void*,GEN), GEN a}. Also available is \fun{GEN}{genindexselect}{void *E, long (*fun)(void*, GEN), GEN a}, corresponding to $\fl = 1$. pari-2.7.5/src/functions/programming/writebin0000644000175000017500000000363312314242551020001 0ustar billbillFunction: writebin Section: programming/specific C-Name: gpwritebin Prototype: vsDG Help: writebin(filename,{x}): write x as a binary object to file filename. If x is omitted, write all session variables. Doc: writes (appends) to \var{filename} the object $x$ in binary format. This format is not human readable, but contains the exact internal structure of $x$, and is much faster to save/load than a string expression, as would be produced by \tet{write}. The binary file format includes a magic number, so that such a file can be recognized and correctly input by the regular \tet{read} or \b{r} function. If saved objects refer to (polynomial) variables that are not defined in the new session, they will be displayed in a funny way (see \secref{se:kill}). Installed functions and history objects can not be saved via this function. If $x$ is omitted, saves all user variables from the session, together with their names. Reading such a ``named object'' back in a \kbd{gp} session will set the corresponding user variable to the saved value. E.g after \bprog x = 1; writebin("log") @eprog\noindent reading \kbd{log} into a clean session will set \kbd{x} to $1$. The relative variables priorities (see \secref{se:priority}) of new variables set in this way remain the same (preset variables retain their former priority, but are set to the new value). In particular, reading such a session log into a clean session will restore all variables exactly as they were in the original one. Just as a regular input file, a binary file can be compressed using \tet{gzip}, provided the file name has the standard \kbd{.gz} extension.\sidx{binary file} In the present implementation, the binary files are architecture dependent and compatibility with future versions of \kbd{gp} is not guaranteed. Hence binary files should not be used for long term storage (also, they are larger and harder to compress than text files). pari-2.7.5/src/functions/programming/breakpoint0000644000175000017500000000125512314242551020312 0ustar billbillFunction: breakpoint Class: gp Section: programming/control C-Name: pari_breakpoint Prototype: v Help: breakpoint(): interrupt the program and enter the breakloop. The program continues when the breakloop is exited. Doc: Interrupt the program and enter the breakloop. The program continues when the breakloop is exited. \bprog ? f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); ? f(221,3) *** at top-level: f(221,3) *** ^-------- *** in function f: my(z=x^2+1);breakpoint();gcd(N,z *** ^-------------------- *** Break loop: type to continue; 'break' to go back to GP break> z 10 break> %2 = 13 @eprog pari-2.7.5/src/functions/programming/fordiv0000644000175000017500000000205311636712103017443 0ustar billbillFunction: fordiv Section: programming/control C-Name: fordiv Prototype: vGVI Help: fordiv(n,X,seq): the sequence is evaluated, X running over the divisors of n. Doc: evaluates \var{seq}, where the formal variable $X$ ranges through the divisors of $n$ (see \tet{divisors}, which is used as a subroutine). It is assumed that \kbd{factor} can handle $n$, without negative exponents. Instead of $n$, it is possible to input a factorization matrix, i.e. the output of \kbd{factor(n)}. This routine uses \kbd{divisors} as a subroutine, then loops over the divisors. In particular, if $n$ is an integer, divisors are sorted by increasing size. To avoid storing all divisors, possibly using a lot of memory, the following (much slower) routine loops over the divisors using essentially constant space: \bprog FORDIV(N)= { my(P, E); P = factor(N); E = P[,2]; P = P[,1]; forvec( v = vector(#E, i, [0,E[i]]), X = factorback(P, v) \\ ... ); } ? for(i=1,10^5, FORDIV(i)) time = 3,445 ms. ? for(i=1,10^5, fordiv(i, d, )) time = 490 ms. @eprog pari-2.7.5/src/functions/programming/errname0000644000175000017500000000036312314242551017604 0ustar billbillFunction: errname Section: programming/specific C-Name: errname Prototype: G Help: errname(E): returns the type of the error message E. Doc: returns the type of the error message \kbd{E} as a string. Description: (gen):errtyp err_get_num($1) pari-2.7.5/src/functions/programming/parfor0000644000175000017500000000207012366172547017457 0ustar billbillFunction: parfor Section: programming/parallel C-Name: parfor Prototype: vV=GDGJDVDI 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). If b is omitted, the loop will not stop. Doc: evaluates the sequence \kbd{expr2} (dependent on $i$ and $j$) for $i$ between $a$ and $b$, in random order, computed in parallel; in this sequence \kbd{expr2}, substitute the variable $j$ by the value of \kbd{expr1} (dependent on $i$). If $b$ is omitted, the loop will not stop. It is allowed for \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}; however in that case, \kbd{expr2} will still be evaluated for all remaining value of $i$ less than the current one, unless a subsequent \kbd{break}/\kbd{next}/\kbd{return} happens. %\syn{NO} Function: _parfor_worker Section: programming/internals C-Name: parfor_worker Prototype: GG Help: _parfor_worker(i,C): evaluate the closure C on i and return [i,C(i)] pari-2.7.5/src/functions/programming/next0000644000175000017500000000101111636712103017121 0ustar billbillFunction: next Section: programming/control C-Name: next0 Prototype: D1,L, Help: next({n=1}): interrupt execution of current instruction sequence, and start another iteration from the n-th innermost enclosing loops. Doc: interrupts execution of current $seq$, resume the next iteration of the innermost enclosing loop, within the current function call (or top level loop). If $n$ is specified, resume at the $n$-th enclosing loop. If $n$ is bigger than the number of enclosing loops, all enclosing loops are exited. pari-2.7.5/src/functions/programming/local0000644000175000017500000000017511636712103017247 0ustar billbillFunction: local Section: programming/specific Help: local(x,...,z): declare x,...,z as (dynamically scoped) local variables. pari-2.7.5/src/functions/programming/trap0000644000175000017500000000441512366172547017141 0ustar billbillFunction: trap Section: programming/specific C-Name: trap0 Prototype: DrDEDE Help: 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" Wrapper: (,_,_) Description: (?str,?closure,?closure):gen trap0($1, $2, $3) Doc: THIS FUNCTION IS OBSOLETE: use \tet{iferr}, which has a nicer and much more powerful interface. For compatibility's sake we now describe the \emph{obsolete} function \tet{trap}. This function tries to evaluate \var{seq}, trapping runtime error $e$, that is effectively preventing it from aborting computations in the usual way; the recovery sequence \var{rec} is executed if the error occurs and the evaluation of \var{rec} becomes the result of the command. If $e$ is omitted, all exceptions are trapped. See \secref{se:errorrec} for an introduction to error recovery under \kbd{gp}. \bprog ? \\@com trap division by 0 ? inv(x) = trap (e_INV, INFINITY, 1/x) ? inv(2) %1 = 1/2 ? inv(0) %2 = INFINITY @eprog\noindent Note that \var{seq} is effectively evaluated up to the point that produced the error, and the recovery sequence is evaluated starting from that same context, it does not "undo" whatever happened in the other branch (restore the evaluation context): \bprog ? x = 1; trap (, /* recover: */ x, /* try: */ x = 0; 1/x) %1 = 0 @eprog \misctitle{Note} The interface is currently not adequate for trapping individual exceptions. In the current version \vers, the following keywords are recognized, but the name list will be expanded and changed in the future (all library mode errors can be trapped: it's a matter of defining the keywords to \kbd{gp}): \kbd{e\_ALARM}: alarm time-out \kbd{e\_ARCH}: not available on this architecture or operating system \kbd{e\_STACK}: the PARI stack overflows \kbd{e\_INV}: impossible inverse \kbd{e\_IMPL}: not yet implemented \kbd{e\_OVERFLOW}: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle). \kbd{e\_SYNTAX}: syntax error \kbd{e\_MISC}: miscellaneous error \kbd{e\_TYPE}: wrong type \kbd{e\_USER}: user error (from the \kbd{error} function) pari-2.7.5/src/functions/programming/dbg_err0000644000175000017500000000127112314242551017556 0ustar billbillFunction: dbg_err Class: gp Section: programming/control C-Name: dbg_err Prototype: Help: dbg_err(): (break loop) return the error data of the current error, if any. Doc: In the break loop, return the error data of the current error, if any. See \tet{iferr} for details about error data. Compare: \bprog ? iferr(1/(Mod(2,12019)^(6!)-1),E,Vec(E)) %1 = ["e_INV", "Fp_inv", Mod(119, 12019)] ? 1/(Mod(2,12019)^(6!)-1) *** at top-level: 1/(Mod(2,12019)^(6!)- *** ^-------------------- *** _/_: impossible inverse in Fp_inv: Mod(119, 12019). *** Break loop: type 'break' to go back to GP prompt break> Vec(dbg_err()) ["e_INV", "Fp_inv", Mod(119, 12019)] @eprog pari-2.7.5/src/functions/programming/printsep0000644000175000017500000000060012314242551020011 0ustar billbillFunction: printsep Section: programming/specific C-Name: printsep Prototype: vss* Help: printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', ending with a newline. Doc: outputs its (string) arguments in raw format, ending with a newline. Successive entries are separated by \var{sep}: \bprog ? printsep(":", 1,2,3,4) 1:2:3:4 @eprog %\syn{NO} pari-2.7.5/src/functions/programming/warning0000644000175000017500000000077512314242551017627 0ustar billbillFunction: warning Section: programming/specific C-Name: warning0 Prototype: vs* Help: warning({str}*): display warning message str Description: (?gen,...):void pari_warn(warnuser, "${2 format_string}"${2 format_args}) Doc: outputs the message ``user warning'' and the argument list (each of them interpreted as a string). If colors are enabled, this warning will be in a different color, making it easy to distinguish. \bprog warning(n, " is very large, this might take a while.") @eprog % \syn{NO} pari-2.7.5/src/functions/programming/iferr0000644000175000017500000002434112314242551017264 0ustar billbillFunction: _iferr_CATCH Class: gp2c_internal Description: (0) pari_CATCH(CATCH_ALL) (small) pari_CATCH2(__iferr_old$1, CATCH_ALL) Function: _iferr_ENDCATCH Class: gp2c_internal Description: (0) pari_ENDCATCH (small) pari_ENDCATCH2(__iferr_old$1) Function: _iferr_CATCH_reset Class: gp2c_internal Description: (0):void pari_CATCH_reset() (small):void pari_CATCH2_reset(__iferr_old$1) Function: _iferr_error Class: gp2c_internal Description: ():error pari_err_last() Function: _iferr_rethrow Class: gp2c_internal Description: (error):void pari_err(0, $1) Function: iferr Section: programming/control C-Name: iferrpari Prototype: EVEDE Help: 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. Doc: evaluates the expression sequence \var{seq1}. If an error occurs, set the formal parameter \var{E} set to the error data. If \var{pred} is not present or evaluates to true, catch the error and evaluate \var{seq2}. Both \var{pred} and \var{seq2} can reference \var{E}. The error type is given by \kbd{errname(E)}, and other data can be accessed using the \tet{component} function. The code \var{seq2} should check whether the error is the one expected. In the negative the error can be rethrown using \tet{error(E)} (and possibly caught by an higher \kbd{iferr} instance). The following uses \kbd{iferr} to implement Lenstra's ECM factoring method \bprog ? ecm(N, B = 1000!, nb = 100)= { for(a = 1, nb, iferr(ellmul(ellinit([a,1]*Mod(1,N)), [0,1]*Mod(1,N), B), E, return(gcd(lift(component(E,2)),N)), errname(E)=="e_INV" && type(component(E,2)) == "t_INTMOD")) } ? ecm(2^101-1) %2 = 7432339208719 @eprog The return value of \kbd{iferr} itself is the value of \var{seq2} if an error occurs, and the value of \var{seq1} otherwise. We now describe the list of valid error types, and the associated error data \var{E}; in each case, we list in order the components of \var{E}, accessed via \kbd{component(E,1)}, \kbd{component(E,2)}, etc. \misctitle{Internal errors, ``system'' errors} \item \kbd{"e\_ARCH"}. A requested feature $s$ is not available on this architecture or operating system. \var{E} has one component (\typ{STR}): the missing feature name $s$. \item \kbd{"e\_BUG"}. A bug in the PARI library, in function $s$. \var{E} has one component (\typ{STR}): the function name $s$. \item \kbd{"e\_FILE"}. Error while trying to open a file. \var{E} has two components, 1 (\typ{STR}): the file type (input, output, etc.), 2 (\typ{STR}): the file name. \item \kbd{"e\_IMPL"}. A requested feature $s$ is not implemented. \var{E} has one component, 1 (\typ{STR}): the feature name $s$. \item \kbd{"e\_PACKAGE"}. Missing optional package $s$. \var{E} has one component, 1 (\typ{STR}): the package name $s$. \misctitle{Syntax errors, type errors} \item \kbd{"e\_DIM"}. The dimensions of arguments $x$ and $y$ submitted to function $s$ does not match up. E.g., multiplying matrices of inconsistent dimension, adding vectors of different lengths,\dots \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_FLAG"}. A flag argument is out of bounds in function $s$. \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_NOTFUNC"}. Generated by the PARI evaluator; tried to use a \kbd{GEN} $x$ which is not a \typ{CLOSURE} in a function call syntax (as in \kbd{f = 1; f(2);}). \var{E} has one component, 1: the offending \kbd{GEN} $x$. \item \kbd{"e\_OP"}. Impossible operation between two objects than cannot be typecast to a sensible common domain for deeper reasons than a type mismatch, usually for arithmetic reasons. As in \kbd{O(2) + O(3)}: it is valid to add two \typ{PADIC}s, provided the underlying prime is the same; so the addition is not forbidden a priori for type reasons, it only becomes so when inspecting the objects and trying to perform the operation. \var{E} has three components, 1 (\typ{STR}): the operator name \var{op}, 2: first argument, 3: second argument. \item \kbd{"e\_TYPE"}. An argument $x$ of function $s$ had an unexpected type. (As in \kbd{factor("blah")}.) \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the offending argument $x$. \item \kbd{"e\_TYPE2"}. Forbidden operation between two objects than cannot be typecast to a sensible common domain, because their types do not match up. (As in \kbd{Mod(1,2) + Pi}.) \var{E} has three components, 1 (\typ{STR}): the operator name \var{op}, 2: first argument, 3: second argument. \item \kbd{"e\_PRIORITY"}. Object $o$ in function $s$ contains variables whose priority is incompatible with the expected operation. E.g.~\kbd{Pol([x,1], 'y)}: this raises an error because it's not possible to create a polynomial whose coefficients involve variables with higher priority than the main variable. $E$ has four components: 1 (\typ{STR}): the function name $s$, 2: the offending argument $o$, 3 (\typ{STR}): an operator $\var{op}$ describing the priority error, 4 (\typ{POL}): the variable $v$ describing the priority error. The argument satisfies $\kbd{variable}(x)~\var{op} \kbd{variable}(v)$. \item \kbd{"e\_VAR"}. The variables of arguments $x$ and $y$ submitted to function $s$ does not match up. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(x\pow2+1)}. \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2 (\typ{POL}): the argument $x$, 3 (\typ{POL}): the argument $y$. \misctitle{Overflows} \item \kbd{"e\_COMPONENT"}. Trying to access an inexistent component in a vector/matrix/list in a function: the index is less than $1$ or greater than the allowed length. \var{E} has four components, 1 (\typ{STR}): the function name 2 (\typ{STR}): an operator $\var{op}$ ($<$ or $>$), 2 (\typ{GEN}): a numerical limit $l$ bounding the allowed range, 3 (\kbd{GEN}): the index $x$. It satisfies $x$ \var{op} $l$. \item \kbd{"e\_DOMAIN"}. An argument is not in the function's domain. \var{E} has five components, 1 (\typ{STR}): the function name, 2 (\typ{STR}): the mathematical name of the out-of-domain argument 3 (\typ{STR}): an operator $\var{op}$ describing the domain error, 4 (\typ{GEN}): the numerical limit $l$ describing the domain error, 5 (\kbd{GEN}): the out-of-domain argument $x$. The argument satisfies $x$ \var{op} $l$, which prevents it from belonging to the function's domain. \item \kbd{"e\_MAXPRIME"}. A function using the precomputed list of prime numbers ran out of primes. \var{E} has one component, 1 (\typ{INT}): the requested prime bound, which overflowed \kbd{primelimit} or $0$ (bound is unknown). \item \kbd{"e\_MEM"}. A call to \tet{pari_malloc} or \tet{pari_realloc} failed. \var{E} has no component. \item \kbd{"e\_OVERFLOW"}. An object in function $s$ becomes too large to be represented within PARI's hardcoded limits. (As in \kbd{2\pow2\pow2\pow10} or \kbd{exp(1e100)}, which overflow in \kbd{lg} and \kbd{expo}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_PREC"}. Function $s$ fails because input accuracy is too low. (As in \kbd{floor(1e100)} at default accuracy.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_STACK"}. The PARI stack overflows. \var{E} has no component. \misctitle{Errors triggered intentionally} \item \kbd{"e\_ALARM"}. A timeout, generated by the \tet{alarm} function. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_USER"}. A user error, as triggered by \tet{error}($g_1,\dots,g_n)$. \var{E} has one component, 1 (\typ{VEC}): the vector of $n$ arguments given to \kbd{error}. \misctitle{Mathematical errors} \item \kbd{"e\_CONSTPOL"}. An argument of function $s$ is a constant polynomial, which does not make sense. (As in \kbd{galoisinit(Pol(1))}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_COPRIME"}. Function $s$ expected coprime arguments, and did receive $x,y$, which were not. \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_INV"}. Tried to invert a non-invertible object $x$ in function $s$. \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the non-invertible $x$. If $x = \kbd{Mod}(a,b)$ is a \typ{INTMOD} and $a$ is not $0$ mod $b$, this allows to factor the modulus, as \kbd{gcd}$(a,b)$ is a non-trivial divisor of $b$. \item \kbd{"e\_IRREDPOL"}. Function $s$ expected an irreducible polynomial, and did receive $T$, which was not. (As in \kbd{nfinit(x\pow2-1)}.) \var{E} has two component, 1 (\typ{STR}): the function name $s$, 2 (\typ{POL}): the polynomial $x$. \item \kbd{"e\_MISC"}. Generic uncategorized error. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_MODULUS"}. moduli $x$ and $y$ submitted to function $s$ are inconsistent. As in \bprog nfalgtobasis(nfinit(t^3-2), Mod(t,t^2+1) @eprog\noindent \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$, 2: the argument $p$. \item \kbd{"e\_ROOTS0"}. An argument of function $s$ is a zero polynomial, and we need to consider its roots. (As in \kbd{polroots(0)}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_SQRTN"}. Trying to compute an $n$-th root of $x$, which does not exist, in function $s$. (As in \kbd{sqrt(Mod(-1,3))}.) \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the argument $x$. pari-2.7.5/src/functions/programming/while0000644000175000017500000000061311636712103017262 0ustar billbillFunction: while Section: programming/control C-Name: whilepari Prototype: vEI Help: while(a,seq): while a is nonzero evaluate the expression sequence seq. Otherwise 0. Doc: while $a$ is non-zero, evaluates the expression sequence \var{seq}. The test is made \emph{before} evaluating the $seq$, hence in particular if $a$ is initially equal to zero the \var{seq} will not be evaluated at all. pari-2.7.5/src/functions/programming/parapply0000644000175000017500000000143212366172547020017 0ustar billbillFunction: parapply Section: programming/parallel C-Name: parapply Prototype: GG Help: parapply(f, x): parallel evaluation of f on the elements of x. Doc: parallel evaluation of \kbd{f} on the elements of \kbd{x}. The function \kbd{f} must not access global variables or variables declared with local(), and must be free of side effects. \bprog parapply(factor,[2^256 + 1, 2^193 - 1]) @eprog factors $2^{256} + 1$ and $2^{193} - 1$ in parallel. \bprog { my(E = ellinit([1,3]), V = vector(12,i,randomprime(2^200))); parapply(p->ellcard(E,p), V) } @eprog computes the order of $E(\F_p)$ for $12$ random primes of $200$ bits. Function: _parapply_worker Section: programming/internals C-Name: parapply_worker Prototype: GG Help: _parapply_worker(d,C): evaluate the closure C on d. pari-2.7.5/src/functions/programming/getheap0000644000175000017500000000055111636712103017570 0ustar billbillFunction: getheap 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. 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. pari-2.7.5/src/functions/programming/forsubgroup0000644000175000017500000000401512366172547020544 0ustar billbillFunction: forsubgroup Section: programming/control C-Name: forsubgroup0 Prototype: vV=GDGI Help: 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. Wrapper: (,,vG) Description: (gen,?gen,closure):void forsubgroup(${3 cookie}, ${3 wrapper}, $1, $2) Doc: evaluates \var{seq} for each subgroup $H$ of the \emph{abelian} group $G$ (given in SNF\sidx{Smith normal form} form or as a vector of elementary divisors). If \var{bound} is present, and is a positive integer, restrict the output to subgroups of index less than \var{bound}. If \var{bound} is a vector containing a single positive integer $B$, then only subgroups of index exactly equal to $B$ are computed The subgroups are not ordered in any obvious way, unless $G$ is a $p$-group in which case Birkhoff's algorithm produces them by decreasing index. A \idx{subgroup} is given as a matrix whose columns give its generators on the implicit generators of $G$. For example, the following prints all subgroups of index less than 2 in $G = \Z/2\Z g_1 \times \Z/2\Z g_2$: \bprog ? G = [2,2]; forsubgroup(H=G, 2, print(H)) [1; 1] [1; 2] [2; 1] [1, 0; 1, 1] @eprog\noindent The last one, for instance is generated by $(g_1, g_1 + g_2)$. This routine is intended to treat huge groups, when \tet{subgrouplist} is not an option due to the sheer size of the output. For maximal speed the subgroups have been left as produced by the algorithm. To print them in canonical form (as left divisors of $G$ in HNF form), one can for instance use \bprog ? G = matdiagonal([2,2]); forsubgroup(H=G, 2, print(mathnf(concat(G,H)))) [2, 1; 0, 1] [1, 0; 0, 2] [2, 0; 0, 1] [1, 0; 0, 1] @eprog\noindent Note that in this last representation, the index $[G:H]$ is given by the determinant. See \tet{galoissubcyclo} and \tet{galoisfixedfield} for applications to \idx{Galois} theory. \synt{forsubgroup}{void *data, long (*call)(void*,GEN), GEN G, GEN bound}. pari-2.7.5/src/functions/programming/getstack0000644000175000017500000000043511636712103017761 0ustar billbillFunction: getstack Section: programming/specific C-Name: getstack Prototype: l Help: getstack(): current value of stack pointer avma. Doc: returns the current value of $\kbd{top}-\kbd{avma}$, i.e.~the number of bytes used up to now on the stack. Useful mainly for debugging purposes. pari-2.7.5/src/functions/programming/uninline0000644000175000017500000000027012366172547020007 0ustar billbillFunction: uninline Section: programming/specific Help: uninline(): forget all inline variables [EXPERIMENTAL] Doc: (Experimental) Exit the scope of all current \kbd{inline} variables. pari-2.7.5/src/functions/programming/whatnow0000644000175000017500000000066211636712103017645 0ustar billbillFunction: whatnow Class: gp Section: programming/specific C-Name: whatnow0 Prototype: vr Help: whatnow(key): if key was present in GP version 1.39.15 or lower, gives the new function name. Description: (str):void whatnow($1, 0) Doc: if keyword \var{key} is the name of a function that was present in GP version 1.39.15 or lower, outputs the new function name and syntax, if it changed at all ($387$ out of $560$ did). pari-2.7.5/src/functions/programming/gettime0000644000175000017500000000060112405547147017616 0ustar billbillFunction: gettime 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 \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}. pari-2.7.5/src/functions/programming/printtex0000644000175000017500000000113411636712103020026 0ustar billbillFunction: printtex Section: programming/specific C-Name: printtex Prototype: vs* Help: printtex({str}*): outputs its string arguments in TeX format. Doc: outputs its (string) arguments in \TeX\ format. This output can then be used in a \TeX\ manuscript. The printing is done on the standard output. If you want to print it to a file you should use \kbd{writetex} (see there). Another possibility is to enable the \tet{log} default (see~\secref{se:defaults}). You could for instance do:\sidx{logfile} % \bprog default(logfile, "new.tex"); default(log, 1); printtex(result); @eprog %\syn{NO} pari-2.7.5/src/functions/programming/alias0000644000175000017500000000346311636712103017251 0ustar billbillFunction: alias Section: programming/specific C-Name: alias0 Prototype: vrr Help: alias(newsym,sym): defines the symbol newsym as an alias for the symbol sym. Doc: defines the symbol \var{newsym} as an alias for the the symbol \var{sym}: \bprog ? alias("det", "matdet"); ? det([1,2;3,4]) %1 = -2 @eprog\noindent You are not restricted to ordinary functions, as in the above example: to alias (from/to) member functions, prefix them with `\kbd{\_.}'; to alias operators, use their internal name, obtained by writing \kbd{\_} in lieu of the operators argument: for instance, \kbd{\_!} and \kbd{!\_} are the internal names of the factorial and the logical negation, respectively. \bprog ? alias("mod", "_.mod"); ? alias("add", "_+_"); ? alias("_.sin", "sin"); ? mod(Mod(x,x^4+1)) %2 = x^4 + 1 ? add(4,6) %3 = 10 ? Pi.sin %4 = 0.E-37 @eprog Alias expansion is performed directly by the internal GP compiler. Note that since alias is performed at compilation-time, it does not require any run-time processing, however it only affects GP code compiled \emph{after} the alias command is evaluated. A slower but more flexible alternative is to use variables. Compare \bprog ? fun = sin; ? g(a,b) = intnum(t=a,b,fun(t)); ? g(0, Pi) %3 = 2.0000000000000000000000000000000000000 ? fun = cos; ? g(0, Pi) %5 = 1.8830410776607851098 E-39 @eprog\noindent with \bprog ? alias(fun, sin); ? g(a,b) = intnum(t=a,b,fun(t)); ? g(0,Pi) %2 = 2.0000000000000000000000000000000000000 ? alias(fun, cos); \\ Oops. Does not affect *previous* definition! ? g(0,Pi) %3 = 2.0000000000000000000000000000000000000 ? g(a,b) = intnum(t=a,b,fun(t)); \\ Redefine, taking new alias into account ? g(0,Pi) %5 = 1.8830410776607851098 E-39 @eprog A sample alias file \kbd{misc/gpalias} is provided with the standard distribution. pari-2.7.5/src/functions/programming/print10000644000175000017500000000066511636712103017376 0ustar billbillFunction: print1 Section: programming/specific C-Name: print1 Prototype: vs* Help: print1({str}*): outputs its string arguments (in raw format) without ending with newline. Description: (?gen,...):void pari_printf("${2 format_string}"${2 format_args}) Doc: outputs its (string) arguments in raw format, without ending with a newline. Note that you can still embed newlines within your strings, using the \b{n} notation~! %\syn{NO} pari-2.7.5/src/functions/programming/if0000644000175000017500000000453012314242551016551 0ustar billbillFunction: if Section: programming/control C-Name: ifpari Prototype: GDEDE Help: 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. Doc: evaluates the expression sequence \var{seq1} if $a$ is non-zero, otherwise the expression \var{seq2}. Of course, \var{seq1} or \var{seq2} may be empty: \kbd{if ($a$,\var{seq})} evaluates \var{seq} if $a$ is not equal to zero (you don't have to write the second comma), and does nothing otherwise, \kbd{if ($a$,,\var{seq})} evaluates \var{seq} if $a$ is equal to zero, and does nothing otherwise. You could get the same result using the \kbd{!} (\kbd{not}) operator: \kbd{if (!$a$,\var{seq})}. The value of an \kbd{if} statement is the value of the branch that gets evaluated: for instance \bprog x = if(n % 4 == 1, y, z); @eprog\noindent sets $x$ to $y$ if $n$ is $1$ modulo $4$, and to $z$ otherwise. Successive 'else' blocks can be abbreviated in a single compound \kbd{if} as follows: \bprog if (test1, seq1, test2, seq2, ... testn, seqn, seqdefault); @eprog\noindent is equivalent to \bprog if (test1, seq1 , if (test2, seq2 , ... if (testn, seqn, seqdefault)...)); @eprog For instance, this allows to write traditional switch / case constructions: \bprog if (x == 0, do0(), x == 1, do1(), x == 2, do2(), dodefault()); @eprog \misctitle{Remark} The boolean operators \kbd{\&\&} and \kbd{||} are evaluated according to operator precedence as explained in \secref{se:operators}, but, contrary to other operators, the evaluation of the arguments is stopped as soon as the final truth value has been determined. For instance \bprog if (x != 0 && f(1/x), ...) @eprog \noindent is a perfectly safe statement. \misctitle{Remark} Functions such as \kbd{break} and \kbd{next} operate on \emph{loops}, such as \kbd{for$xxx$}, \kbd{while}, \kbd{until}. The \kbd{if} statement is \emph{not} a loop. (Obviously!) Function: _void_if C-Name: ifpari_void Section: programming/internals Prototype: vGDIDI Help: internal variant of if() that does not return a value. Function: _multi_if C-Name: ifpari_multi Section: programming/internals Prototype: GE* Help: internal variant of if() that allows more than 3 arguments. pari-2.7.5/src/functions/programming/forprime0000644000175000017500000000446312314242551020003 0ustar billbillFunction: _diffptr Class: gp2c_internal Help: Table of difference of primes. Description: ():bptr diffptr Function: _forprime_next Class: gp2c_internal Help: Compute the next prime from the diffptr table. Description: (*small,*bptr):void NEXT_PRIME_VIADIFF($1, $2) Function: _forprime_init Class: gp2c_internal Help: Initialize forprime_t Description: (forprime,int,?int):void forprime_init(&$1, $2, $3); Function: _forprime_next_ Class: gp2c_internal Help: Compute the next prime Description: (forprime):int forprime_next(&$1) Function: _u_forprime_init Class: gp2c_internal Help: Initialize forprime_t (ulong version) Description: (forprime,small,):void u_forprime_init(&$1, $2, LONG_MAX); (forprime,small,small):void u_forprime_init(&$1, $2, $3); Function: _u_forprime_next Class: gp2c_internal Help: Compute the next prime (ulong version) Description: (forprime):small u_forprime_next(&$1) Function: forprime Section: programming/control C-Name: forprime Prototype: vV=GDGI Help: forprime(p=a,{b},seq): the sequence is evaluated, p running over the primes between a and b. Omitting b runs through primes >= a Iterator: (*notype,small,small) (forprime, _u_forprime_init, _u_forprime_next) (*small,gen,?gen) (forprime, _u_forprime_init, _u_forprime_next) (*int,gen,?gen) (forprime, _forprime_init, _forprime_next_) (gen,gen,?gen) (forprime, _forprime_init, _forprime_next_) Doc: evaluates \var{seq}, where the formal variable $p$ ranges over the prime numbers between the real numbers $a$ to $b$, including $a$ and $b$ if they are prime. More precisely, the value of $p$ is incremented to \kbd{nextprime($p$ + 1)}, the smallest prime strictly larger than $p$, at the end of each iteration. Nothing is done if $a>b$. \bprog ? forprime(p = 4, 10, print(p)) 5 7 @eprog\noindent Omitting $b$ means we will run through all primes $\geq a$, starting an infinite loop; it is expected that the user will break out of the loop himself at some point, using \kbd{break} or \kbd{return}. Note that the value of $p$ cannot be modified within \var{seq}: \bprog ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. @eprog pari-2.7.5/src/functions/programming/forpart0000644000175000017500000000454012413013143017622 0ustar billbillFunction: _forpart_init Class: gp2c_internal Help: Initialize forpart_t Description: (forpart,small,?gen,?gen):void forpart_init(&$1, $2, $3, $4) Function: _forpart_next Class: gp2c_internal Help: Compute the next part Description: (forpart):vecsmall forpart_next(&$1) Function: forpart Section: programming/control C-Name: forpart0 Prototype: vV=GIDGDG Iterator: (gen,small,?gen,?gen) (forpart, _forpart_init, _forpart_next) Wrapper: (,vG,,) Description: (small,closure,?gen,?gen):void forpart(${2 cookie}, ${2 wrapper}, $1, $3, $4) Help: 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). Doc: evaluate \var{seq} over the partitions $X=[x_1,\dots x_n]$ of the integer $k$, i.e.~increasing sequences $x_1\leq x_2\dots \leq x_n$ of sum $x_1+\dots + x_n=k$. By convention, $0$ admits only the empty partition and negative numbers have no partitions. A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order: \bprog ? forpart(X=3, print(X)) Vecsmall([3]) Vecsmall([1, 2]) Vecsmall([1, 1, 1]) @eprog\noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case $X$ is of constant length $\var{nmax}$. \bprog \\ at most 3 non-zero parts, all <= 4 ? forpart(v=5,print(Vec(v)),4,3) [1, 4] [2, 3] [1, 1, 3] [1, 2, 2] \\ between 2 and 4 parts less than 5, fill with zeros ? forpart(v=5,print(Vec(v)),[0,5],[2,4]) [0, 0, 1, 4] [0, 0, 2, 3] [0, 1, 1, 3] [0, 1, 2, 2] [1, 1, 1, 2] @eprog\noindent The behavior is unspecified if $X$ is modified inside the loop. \synt{forpart}{void *data, long (*call)(void*,GEN), long k, GEN a, GEN n}. pari-2.7.5/src/functions/programming/dbg_down0000644000175000017500000000042112314242551017731 0ustar billbillFunction: dbg_down Class: gp Section: programming/control C-Name: dbg_down Prototype: vD1,L, Help: dbg_down({n=1}): (break loop) go down n frames. Cancel a previous dbg_up. Doc: (In the break loop) go down n frames. This allows to cancel a previous call to \kbd{dbg\_up}. pari-2.7.5/src/functions/programming/error0000644000175000017500000000124212314242551017301 0ustar billbillFunction: _err_primes Class: gp2c_internal Description: ():void pari_err(e_MAXPRIME) Function: _err_type Class: gp2c_internal Description: (str,gen):void pari_err_TYPE($1,$2) Function: error Section: programming/specific C-Name: error0 Prototype: vs* Help: error({str}*): abort script with error message str. Description: (error):void pari_err(0, $1) (?gen,...):void pari_err(e_MISC, "${2 format_string}"${2 format_args}) Doc: outputs its argument list (each of them interpreted as a string), then interrupts the running \kbd{gp} program, returning to the input prompt. For instance \bprog error("n = ", n, " is not squarefree!") @eprog\noindent % \syn{NO} pari-2.7.5/src/functions/programming/printf0000644000175000017500000001717511636712103017467 0ustar billbillFunction: printf Section: programming/specific C-Name: printf0 Prototype: vss* Help: printf(fmt,{x}*): prints its arguments according to the format fmt. Doc: This function is based on the C library command of the same name. It prints its arguments according to the format \var{fmt}, which specifies how subsequent arguments are converted for output. The format is a character string composed of zero or more directives: \item ordinary characters (not \kbd{\%}), printed unchanged, \item conversions specifications (\kbd{\%} followed by some characters) which fetch one argument from the list and prints it according to the specification. More precisely, a conversion specification consists in a \kbd{\%}, one or more optional flags (among \kbd{\#}, \kbd{0}, \kbd{-}, \kbd{+}, ` '), an optional decimal digit string specifying a minimal field width, an optional precision in the form of a period (`\kbd{.}') followed by a decimal digit string, and the conversion specifier (among \kbd{d},\kbd{i}, \kbd{o}, \kbd{u}, \kbd{x},\kbd{X}, \kbd{p}, \kbd{e},\kbd{E}, \kbd{f}, \kbd{g},\kbd{G}, \kbd{s}). \misctitle{The flag characters} The character \kbd{\%} is followed by zero or more of the following flags: \item \kbd{\#}: The value is converted to an ``alternate form''. For \kbd{o} conversion (octal), a \kbd{0} is prefixed to the string. For \kbd{x} and \kbd{X} conversions (hexa), respectively \kbd{0x} and \kbd{0X} are prepended. For other conversions, the flag is ignored. \item \kbd{0}: The value should be zero padded. For \kbd{d}, \kbd{i}, \kbd{o}, \kbd{u}, \kbd{x}, \kbd{X} \kbd{e}, \kbd{E}, \kbd{f}, \kbd{F}, \kbd{g}, and \kbd{G} conversions, the value is padded on the left with zeros rather than blanks. (If the \kbd{0} and \kbd{-} flags both appear, the \kbd{0} flag is ignored.) \item \kbd{-}: The value is left adjusted on the field boundary. (The default is right justification.) The value is padded on the right with blanks, rather than on the left with blanks or zeros. A \kbd{-} overrides a \kbd{0} if both are given. \item \kbd{` '} (a space): A blank is left before a positive number produced by a signed conversion. \item \kbd{+}: A sign (+ or -) is placed before a number produced by a signed conversion. A \kbd{+} overrides a space if both are used. \misctitle{The field width} An optional decimal digit string (whose first digit is non-zero) specifying a \emph{minimum} field width. If the value has fewer characters than the field width, it is padded with spaces on the left (or right, if the left-adjustment flag has been given). In no case does a small field width cause truncation of a field; if the value is wider than the field width, the field is expanded to contain the conversion result. Instead of a decimal digit string, one may write \kbd{*} to specify that the field width is given in the next argument. \misctitle{The precision} An optional precision in the form of a period (`\kbd{.}') followed by a decimal digit string. This gives the number of digits to appear after the radix character for \kbd{e}, \kbd{E}, \kbd{f}, and \kbd{F} conversions, the maximum number of significant digits for \kbd{g} and \kbd{G} conversions, and the maximum number of characters to be printed from an \kbd{s} conversion. Instead of a decimal digit string, one may write \kbd{*} to specify that the field width is given in the next argument. \misctitle{The length modifier} This is ignored under \kbd{gp}, but necessary for \kbd{libpari} programming. Description given here for completeness: \item \kbd{l}: argument is a \kbd{long} integer. \item \kbd{P}: argument is a \kbd{GEN}. \misctitle{The conversion specifier} A character that specifies the type of conversion to be applied. \item \kbd{d}, \kbd{i}: A signed integer. \item \kbd{o}, \kbd{u}, \kbd{x}, \kbd{X}: An unsigned integer, converted to unsigned octal (\kbd{o}), decimal (\kbd{u}) or hexadecimal (\kbd{x} or \kbd{X}) notation. The letters \kbd{abcdef} are used for \kbd{x} conversions; the letters \kbd{ABCDEF} are used for \kbd{X} conversions. \item \kbd{e}, \kbd{E}: The (real) argument is converted in the style \kbd{[ -]d.ddd e[ -]dd}, where there is one digit before the decimal point, and the number of digits after it is equal to the precision; if the precision is missing, use the current \kbd{realprecision} for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. An \kbd{E} conversion uses the letter \kbd{E} rather than \kbd{e} to introduce the exponent. \item \kbd{f}, \kbd{F}: The (real) argument is converted in the style \kbd{[ -]ddd.ddd}, where the number of digits after the decimal point is equal to the precision; if the precision is missing, use the current \kbd{realprecision} for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. If a decimal point appears, at least one digit appears before it. \item \kbd{g}, \kbd{G}: The (real) argument is converted in style \kbd{e} or \kbd{f} (or \kbd{E} or \kbd{F} for \kbd{G} conversions) \kbd{[ -]ddd.ddd}, where the total number of digits printed is equal to the precision; if the precision is missing, use the current \kbd{realprecision}. If the precision is explicitly 0, it is treated as 1. Style \kbd{e} is used when the decimal exponent is $< -4$, to print \kbd{0.}, or when the integer part cannot be decided given the known significant digits, and the \kbd{f} format otherwise. \item \kbd{c}: The integer argument is converted to an unsigned char, and the resulting character is written. \item \kbd{s}: Convert to a character string. If a precision is given, no more than the specified number of characters are written. \item \kbd{p}: Print the address of the argument in hexadecimal (as if by \kbd{\%\#x}). \item \kbd{\%}: A \kbd{\%} is written. No argument is converted. The complete conversion specification is \kbd{\%\%}. \noindent Examples: \bprog ? printf("floor: %d, field width 3: %3d, with sign: %+3d\n", Pi, 1, 2); floor: 3, field width 3: 1, with sign: +2 ? printf("%.5g %.5g %.5g\n",123,123/456,123456789); 123.00 0.26974 1.2346 e8 ? printf("%-2.5s:%2.5s:%2.5s\n", "P", "PARI", "PARIGP"); P :PARI:PARIG \\ min field width and precision given by arguments ? x = 23; y=-1/x; printf("x=%+06.2f y=%+0*.*f\n", x, 6, 2, y); x=+23.00 y=-00.04 \\ minimum fields width 5, pad left with zeroes ? for (i = 2, 5, printf("%05d\n", 10^i)) 00100 01000 10000 100000 \\@com don't truncate fields whose length is larger than the minimum width ? printf("%.2f |%06.2f|", Pi,Pi) 3.14 | 3.14| @eprog\noindent All numerical conversions apply recursively to the entries of vectors and matrices: \bprog ? printf("%4d", [1,2,3]); [ 1, 2, 3] ? printf("%5.2f", mathilbert(3)); [ 1.00 0.50 0.33] [ 0.50 0.33 0.25] [ 0.33 0.25 0.20] @eprog \misctitle{Technical note} Our implementation of \tet{printf} deviates from the C89 and C99 standards in a few places: \item whenever a precision is missing, the current \kbd{realprecision} is used to determine the number of printed digits (C89: use 6 decimals after the radix character). \item in conversion style \kbd{e}, we do not impose that the exponent has at least two digits; we never write a \kbd{+} sign in the exponent; 0 is printed in a special way, always as \kbd{0.E\var{exp}}. \item in conversion style \kbd{f}, we switch to style \kbd{e} if the exponent is greater or equal to the precision. \item in conversion \kbd{g} and \kbd{G}, we do not remove trailing zeros from the fractional part of the result; nor a trailing decimal point; 0 is printed in a special way, always as \kbd{0.E\var{exp}}. %\syn{NO} pari-2.7.5/src/functions/programming/getenv0000644000175000017500000000037412314242551017445 0ustar billbillFunction: getenv Section: programming/specific C-Name: gp_getenv Prototype: s Help: getenv(s): value of the environment variable s, 0 if it is not defined. Doc: return the value of the environment variable \kbd{s} if it is defined, otherwise return 0. pari-2.7.5/src/functions/programming/forell0000644000175000017500000000162312366172547017454 0ustar billbillFunction: forell Section: programming/control C-Name: forell0 Prototype: vVLLI Help: forell(E,a,b,seq): execute seq for each elliptic curves E of conductor between a and b in the elldata database. Wrapper: (,,,vG) Description: (,small,small,closure):void forell(${4 cookie}, ${4 wrapper}, $2, $3) Doc: evaluates \var{seq}, where the formal variable $E = [\var{name}, M, G]$ ranges through all elliptic curves of conductors from $a$ to $b$. In this notation \var{name} is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the Mordell-Weil group $E(\Q)$. \bprog ? forell(E, 1, 500, my([name,M,G] = E); \ if (#G > 1, print(name))) 389a1 433a1 446d1 @eprog\noindent The \tet{elldata} database must be installed and contain data for the specified conductors. \synt{forell}{void *data, long (*call)(void*,GEN), long a, long b}. pari-2.7.5/src/functions/programming/_eval_mnemonic0000644000175000017500000000021011636712103021116 0ustar billbillFunction: _eval_mnemonic C-Name: eval_mnemonic Section: programming/internals Prototype: lGs Help: Convert a mnemonic string to a flag. pari-2.7.5/src/functions/programming/return0000644000175000017500000000043711636712103017475 0ustar billbillFunction: return Section: programming/control C-Name: return0 Prototype: DG Help: return({x=0}): return from current subroutine with result x. Doc: returns from current subroutine, with result $x$. If $x$ is omitted, return the \kbd{(void)} value (return no result, like \kbd{print}). pari-2.7.5/src/functions/programming/addhelp0000644000175000017500000000212612366172547017571 0ustar billbillFunction: addhelp Section: programming/specific C-Name: addhelp Prototype: vrs Help: addhelp(sym,str): add/change help message for the symbol sym. Doc: changes the help message for the symbol \kbd{sym}. The string \var{str} is expanded on the spot and stored as the online help for \kbd{sym}. It is recommended to document global variables and user functions in this way, although \kbd{gp} will not protest if you don't. You can attach a help text to an alias, but it will never be shown: aliases are expanded by the \kbd{?} help operator and we get the help of the symbol the alias points to. Nothing prevents you from modifying the help of built-in PARI functions. But if you do, we would like to hear why you needed it! Without \tet{addhelp}, the standard help for user functions consists of its name and definition. \bprog gp> f(x) = x^2; gp> ?f f = (x)->x^2 @eprog\noindent Once addhelp is applied to $f$, the function code is no longer included. It can still be consulted by typing the function name: \bprog gp> addhelp(f, "Square") gp> ?f Square gp> f %2 = (x)->x^2 @eprog pari-2.7.5/src/functions/programming/allocatemem0000644000175000017500000000437512405547147020457 0ustar billbillFunction: allocatemem Class: gp Section: programming/specific C-Name: allocatemem0 Prototype: vDG Help: allocatemem({s=0}): allocates a new stack of s bytes. doubles the stack if s is omitted. Doc: this special operation changes the stack size \emph{after} initialization. $x$ must be a non-negative integer. If $x > 0$, a new stack 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 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 larger expression sequence, e.g \bprog allocatemem(); x = 1; \\@com This will not set \kbd{x}! @eprog\noindent 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 user). In particular, we have the following possibly unexpected behavior: in \bprog read("file.gp"); x = 1 @eprog\noindent were \kbd{file.gp} contains an \kbd{allocatemem} statement, 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 pari-2.7.5/src/functions/programming/default0000644000175000017500000000340211636712103017575 0ustar billbillFunction: default Section: programming/specific C-Name: default0 Prototype: DrDs Help: 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. Description: ("realprecision"):small:prec getrealprecision() ("realprecision",small):small:prec setrealprecision($2, &prec) ("seriesprecision"):small precdl ("seriesprecision",small):small:parens precdl = $2 ("debug"):small DEBUGLEVEL ("debug",small):small:parens DEBUGLEVEL = $2 ("debugmem"):small DEBUGMEM ("debugmem",small):small:parens DEBUGMEM = $2 ("debugfiles"):small DEBUGFILES ("debugfiles",small):small:parens DEBUGFILES = $2 ("factor_add_primes"):small factor_add_primes ("factor_add_primes",small):small factor_add_primes = $2 ("factor_proven"):small factor_proven ("factor_proven",small):small factor_proven = $2 ("new_galois_format"):small new_galois_format ("new_galois_format",small):small new_galois_format = $2 Doc: returns the default corresponding to keyword \var{key}. If \var{val} is present, sets the default to \var{val} first (which is subject to string expansion first). Typing \kbd{default()} (or \b{d}) yields the complete default list as well as their current values. See \secref{se:defaults} for an introduction to GP defaults, \secref{se:gp_defaults} for a list of available defaults, and \secref{se:meta} for some shortcut alternatives. Note that the shortcuts are meant for interactive use and usually display more information than \kbd{default}. pari-2.7.5/src/functions/programming/quit0000644000175000017500000000067711636712103017146 0ustar billbillFunction: quit Class: gp Section: programming/specific C-Name: gp_quit Prototype: vD0,L, Help: quit({status = 0}): quit, return to the system with exit status 'status'. Doc: exits \kbd{gp} and return to the system with exit status \kbd{status}, a small integer. A non-zero exit status normally indicates abnormal termination. (Note: the system actually sees only \kbd{status} mod $256$, see your man pages for \kbd{exit(3)} or \kbd{wait(2)}). pari-2.7.5/src/functions/programming/until0000644000175000017500000000064511636712103017312 0ustar billbillFunction: until Section: programming/control C-Name: untilpari Prototype: vEI Help: until(a,seq): evaluate the expression sequence seq until a is nonzero. Doc: evaluates \var{seq} until $a$ is not equal to 0 (i.e.~until $a$ is true). If $a$ is initially not equal to 0, \var{seq} is evaluated once (more generally, the condition on $a$ is tested \emph{after} execution of the \var{seq}, not before as in \kbd{while}). pari-2.7.5/src/functions/programming/input0000644000175000017500000000136211636712103017313 0ustar billbillFunction: input Class: gp Section: programming/specific C-Name: input0 Prototype: Help: input(): read an expression from the input file or standard input. Doc: reads a string, interpreted as a GP expression, from the input file, usually standard input (i.e.~the keyboard). If a sequence of expressions is given, the result is the result of the last expression of the sequence. When using this instruction, it is useful to prompt for the string by using the \kbd{print1} function. Note that in the present version 2.19 of \kbd{pari.el}, when using \kbd{gp} under GNU Emacs (see \secref{se:emacs}) one \emph{must} prompt for the string, with a string which ends with the same prompt as any of the previous ones (a \kbd{"? "} will do for instance). pari-2.7.5/src/functions/programming/inline0000644000175000017500000000075612366172547017455 0ustar billbillFunction: inline Section: programming/specific Help: inline(x,...,z): declares x,...,z as inline variables [EXPERIMENTAL] Doc: (Experimental) declare $x,\ldots, z$ as inline variables. Such variables behave like lexically scoped variable (see my()) but with unlimited scope. It is however possible to exit the scope by using \kbd{uninline()}. When used in a GP script, it is recommended to call \kbd{uninline()} before the script's end to avoid inline variables leaking outside the script. pari-2.7.5/src/functions/programming/install0000644000175000017500000000655212366172547017645 0ustar billbillFunction: install Section: programming/specific C-Name: gpinstall Prototype: vrrD"",r,D"",s, Help: 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'. Doc: 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} \var{code} (see below). If \var{gpname} is omitted, uses \var{name}. If \var{lib} is omitted, all symbols known to \kbd{gp} are available: this includes the whole of \kbd{libpari.so} and possibly others (such as \kbd{libc.so}). Most importantly, \kbd{install} gives you access to all non-static functions defined in the PARI library. For instance, the function \kbd{GEN addii(GEN x, GEN y)} adds two PARI integers, and is not directly accessible under \kbd{gp} (it is eventually called by the \kbd{+} operator of course): \bprog ? install("addii", "GG") ? addii(1, 2) %1 = 3 @eprog\noindent It also allows to add external functions to the \kbd{gp} interpreter. For instance, it makes the function \tet{system} obsolete: \bprog ? install(system, vs, sys,/*omitted*/) ? sys("ls gp*") gp.c gp.h gp_rl.c @eprog\noindent This works because \kbd{system} is part of \kbd{libc.so}, which is linked to \kbd{gp}. It is also possible to compile a shared library yourself and provide it to gp in this way: use \kbd{gp2c}, or do it manually (see the \kbd{modules\_build} variable in \kbd{pari.cfg} for hints). Re-installing a function will print a warning and update the prototype code if needed. However, it will not reload a symbol from the library, even if the latter has been recompiled. \misctitle{Prototype} We only give a simplified description here, covering most functions, but there are many more possibilities. The full documentation is available in \kbd{libpari.dvi}, see \bprog ??prototype @eprog \item First character \kbd{i}, \kbd{l}, \kbd{v} : return type int / long / void. (Default: \kbd{GEN}) \item One letter for each mandatory argument, in the same order as they appear in the argument list: \kbd{G} (\kbd{GEN}), \kbd{\&} (\kbd{GEN*}), \kbd{L} (\kbd{long}), \kbd{s} (\kbd{char *}), \kbd{n} (variable). \item \kbd{p} to supply \kbd{realprecision} (usually \kbd{long prec} in the argument list), \kbd{P} to supply \kbd{seriesprecision} (usually \kbd{long precdl}). \noindent We also have special constructs for optional arguments and default values: \item \kbd{DG} (optional \kbd{GEN}, \kbd{NULL} if omitted), \item \kbd{D\&} (optional \kbd{GEN*}, \kbd{NULL} if omitted), \item \kbd{Dn} (optional variable, $-1$ if omitted), For instance the prototype corresponding to \bprog long issquareall(GEN x, GEN *n = NULL) @eprog\noindent is \kbd{lGD\&}. \misctitle{Caution} This function may not work on all systems, especially when \kbd{gp} has been compiled statically. In that case, the first use of an installed function will provoke a Segmentation Fault (this should never happen with a dynamically linked executable). If you intend to use this function, please check first on some harmless example such as the one above that it works properly on your machine. pari-2.7.5/src/functions/programming/print0000644000175000017500000000051511636712103017307 0ustar billbillFunction: print Section: programming/specific C-Name: print Prototype: vs* Help: print({str}*): outputs its string arguments (in raw format) ending with a newline. Description: (?gen,...):void pari_printf("${2 format_string}\n"${2 format_args}) Doc: outputs its (string) arguments in raw format, ending with a newline. %\syn{NO} pari-2.7.5/src/functions/programming/apply0000644000175000017500000000307412314242551017302 0ustar billbillFunction: apply Section: programming/specific C-Name: apply0 Prototype: GG Help: apply(f, A): apply function f to each entry in A. Wrapper: (G) Description: (closure,gen):gen genapply(${1 cookie}, ${1 wrapper}, $2) Doc: Apply the \typ{CLOSURE} \kbd{f} to the entries of \kbd{A}. If \kbd{A} is a scalar, return \kbd{f(A)}. If \kbd{A} is a polynomial or power series, apply \kbd{f} on all coefficients. If \kbd{A} is a vector or list, return the elements $f(x)$ where $x$ runs through \kbd{A}. If \kbd{A} is a matrix, return the matrix whose entries are the $f(\kbd{A[i,j]})$. \bprog ? apply(x->x^2, [1,2,3,4]) %1 = [1, 4, 9, 16] ? apply(x->x^2, [1,2;3,4]) %2 = [1 4] [9 16] ? apply(x->x^2, 4*x^2 + 3*x+ 2) %3 = 16*x^2 + 9*x + 4 @eprog\noindent Note that many functions already act componentwise on vectors or matrices, but they almost never act on lists; in this case, \kbd{apply} is a good solution: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? lift(L) *** at top-level: lift(L) *** ^------- *** lift: incorrect type in lift. ? apply(lift, L); %2 = List([1, 2]) @eprog \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? [ lift(x) | x<-L ] %2 = [1, 2] @eprog \synt{genapply}{void *E, GEN (*fun)(void*,GEN), GEN a}. pari-2.7.5/src/functions/programming/kill0000644000175000017500000000267511636712103017117 0ustar billbillFunction: kill Section: programming/specific C-Name: kill0 Prototype: vr Help: kill(sym): restores the symbol sym to its ``undefined'' status and kill associated help messages. Doc: restores the symbol \kbd{sym} to its ``undefined'' status, and deletes any help messages associated to \kbd{sym} using \kbd{addhelp}. Variable names remain known to the interpreter and keep their former priority: you cannot make a variable ``less important" by killing it! \bprog ? z = y = 1; y %1 = 1 ? kill(y) ? y \\ restored to ``undefined'' status %2 = y ? variable() %3 = [x, y, z] \\ but the variable name y is still known, with y > z ! @eprog\noindent For the same reason, killing a user function (which is an ordinary variable holding a \typ{CLOSURE}) does not remove its name from the list of variable names. If the symbol is associated to a variable --- user functions being an important special case ---, one may use the \idx{quote} operator \kbd{a = 'a} to reset variables to their starting values. However, this will not delete a help message associated to \kbd{a}, and is also slightly slower than \kbd{kill(a)}. \bprog ? x = 1; addhelp(x, "foo"); x %1 = 1 ? x = 'x; x \\ same as 'kill', except we don't delete help. %2 = x ? ?x foo @eprog\noindent On the other hand, \kbd{kill} is the only way to remove aliases and installed functions. \bprog ? alias(fun, sin); ? kill(fun); ? install(addii, GG); ? kill(addii); @eprog pari-2.7.5/src/functions/programming/dbg_up0000644000175000017500000000051112366172547017424 0ustar billbillFunction: dbg_up Class: gp Section: programming/control C-Name: dbg_up Prototype: vD1,L, Help: dbg_up({n=1}): (break loop) go up n frames. Allow to inspect data of the parent function. Doc: (In the break loop) go up n frames. This allows to inspect data of the parent function. To cancel a \tet{dbg_up} call, use \tet{dbg_down} pari-2.7.5/src/functions/programming/pareval0000644000175000017500000000103512366172547017620 0ustar billbillFunction: pareval Section: programming/parallel C-Name: pareval Prototype: G Help: pareval(x): parallel evaluation of the elements of the vector of closures x. Doc: parallel evaluation of the elements of \kbd{x}, where \kbd{x} is a vector of closures. The closures must be of arity $0$, must not access global variables or variables declared with \kbd{local} and must be free of side effects. Function: _pareval_worker Section: programming/internals C-Name: pareval_worker Prototype: G Help: _pareval_worker(C): evaluate the closure C. pari-2.7.5/src/functions/programming/my0000644000175000017500000000016311636712103016577 0ustar billbillFunction: my Section: programming/specific Help: my(x,...,z): declare x,...,z as lexically-scoped local variables. pari-2.7.5/src/functions/transcendental/0000755000175000017500000000000012613365633016722 5ustar billbillpari-2.7.5/src/functions/transcendental/I0000644000175000017500000000021711636712103017025 0ustar billbillFunction: I Section: transcendental C-Name: gen_I Prototype: Help: I=I(): square root of -1. Description: Doc: the complex number $\sqrt{-1}$. pari-2.7.5/src/functions/transcendental/atanh0000644000175000017500000000051712366172547017750 0ustar billbillFunction: atanh Section: transcendental C-Name: gatanh Prototype: Gp Help: atanh(x): inverse hyperbolic tangent of x. Doc: principal branch of $\text{tanh}^{-1}(x) = log ((1+x)/(1-x)) / 2$. In particular the imaginary part of $\text{atanh}(x)$ belongs to $[-\pi/2,\pi/2]$; if $x\in \R$ and $|x|>1$ then $\text{atanh}(x)$ is complex. pari-2.7.5/src/functions/transcendental/tan0000644000175000017500000000016211636712103017416 0ustar billbillFunction: tan Section: transcendental C-Name: gtan Prototype: Gp Help: tan(x): tangent of x. Doc: tangent of $x$. pari-2.7.5/src/functions/transcendental/cosh0000644000175000017500000000021112366172547017600 0ustar billbillFunction: cosh Section: transcendental C-Name: gcosh Prototype: Gp Help: cosh(x): hyperbolic cosine of x. Doc: hyperbolic cosine of $x$. pari-2.7.5/src/functions/transcendental/sqrtn0000644000175000017500000000276212314242551020012 0ustar billbillFunction: sqrtn Section: transcendental C-Name: gsqrtn Prototype: GGD&p Help: 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. Doc: principal branch of the $n$th root of $x$, i.e.~such that $\text{Arg}(\text{sqrt}(x))\in{} ]-\pi/n, \pi/n]$. Intmod a prime and $p$-adics are allowed as arguments. If $z$ is present, it is set to a suitable root of unity allowing to recover all the other roots. If it was not possible, z is set to zero. In the case this argument is present and no square root exist, $0$ is returned instead or raising an error. \bprog ? sqrtn(Mod(2,7), 2) %1 = Mod(4, 7) ? sqrtn(Mod(2,7), 2, &z); z %2 = Mod(6, 7) ? sqrtn(Mod(2,7), 3) *** at top-level: sqrtn(Mod(2,7),3) *** ^----------------- *** sqrtn: nth-root does not exist in gsqrtn. ? sqrtn(Mod(2,7), 3, &z) %2 = 0 ? z %3 = 0 @eprog The following script computes all roots in all possible cases: \bprog sqrtnall(x,n)= { my(V,r,z,r2); r = sqrtn(x,n, &z); if (!z, error("Impossible case in sqrtn")); if (type(x) == "t_INTMOD" || type(x)=="t_PADIC", r2 = r*z; n = 1; while (r2!=r, r2*=z;n++)); V = vector(n); V[1] = r; for(i=2, n, V[i] = V[i-1]*z); V } addhelp(sqrtnall,"sqrtnall(x,n):compute the vector of nth-roots of x"); @eprog\noindent Variant: If $x$ is a \typ{PADIC}, the function \fun{GEN}{Qp_sqrt}{GEN x, GEN n, GEN *z} is also available. pari-2.7.5/src/functions/transcendental/gamma0000644000175000017500000000145712314242551017725 0ustar billbillFunction: gamma Section: transcendental C-Name: ggamma Prototype: Gp Help: gamma(s): gamma function at s, a complex or p-adic number, or a series. Doc: For $s$ a complex number, evaluates Euler's gamma function \sidx{gamma-function} $$\Gamma(s)=\int_0^\infty t^{s-1}\exp(-t)\,dt.$$ Error if $s$ is a non-positive integer, where $\Gamma$ has a pole. For $s$ a \typ{PADIC}, evaluates the Morita gamma function at $s$, that is the unique continuous $p$-adic function on the $p$-adic integers extending $\Gamma_p(k)=(-1)^k \prod_{j0$ and even, and using modular forms for $s>0$ and odd. For $s$ a $p$-adic number, Kubota-Leopoldt zeta function at $s$, that is the unique continuous $p$-adic function on the $p$-adic integers that interpolates the values of $(1 - p^{-k}) \zeta(k)$ at negative integers $k$ such that $k \equiv 1 \pmod{p-1}$ (resp. $k$ is odd) if $p$ is odd (resp. $p = 2$). pari-2.7.5/src/functions/transcendental/sqrt0000644000175000017500000000146312314242551017631 0ustar billbillFunction: sqrt Section: transcendental C-Name: gsqrt Prototype: Gp Help: sqrt(x): square root of x. Description: (real):gen sqrtr($1) (gen):gen:prec gsqrt($1, prec) Doc: principal branch of the square root of $x$, defined as $\sqrt{x} = \exp(\log x / 2)$. In particular, we have $\text{Arg}(\text{sqrt}(x))\in{} ]-\pi/2, \pi/2]$, and if $x\in \R$ and $x<0$, then the result is complex with positive imaginary part. Intmod a prime $p$, \typ{PADIC} and \typ{FFELT} are allowed as arguments. In the first 2 cases (\typ{INTMOD}, \typ{PADIC}), the square root (if it exists) which is returned is the one whose first $p$-adic digit is in the interval $[0,p/2]$. For other arguments, the result is undefined. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_sqrt}{GEN x} is also available. pari-2.7.5/src/functions/transcendental/log0000644000175000017500000000210211636712103017411 0ustar billbillFunction: log Section: transcendental C-Name: glog Prototype: Gp Help: log(x): natural logarithm of x. Description: (gen):gen:prec glog($1, prec) Doc: principal branch of the natural logarithm of $x \in \C^*$, i.e.~such that $\text{Im(log}(x))\in{} ]-\pi,\pi]$. The branch cut lies along the negative real axis, continuous with quadrant 2, i.e.~such that $\lim_{b\to 0^+} \log (a+bi) = \log a$ for $a \in\R^*$. The result is complex (with imaginary part equal to $\pi$) if $x\in \R$ and $x < 0$. In general, the algorithm uses the formula $$\log(x) \approx {\pi\over 2\text{agm}(1, 4/s)} - m \log 2, $$ if $s = x 2^m$ is large enough. (The result is exact to $B$ bits provided $s > 2^{B/2}$.) At low accuracies, the series expansion near $1$ is used. $p$-adic arguments are also accepted for $x$, with the convention that $\log(p)=0$. Hence in particular $\exp(\log(x))/x$ is not in general equal to 1 but to a $(p-1)$-th root of unity (or $\pm1$ if $p=2$) times a power of $p$. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_log}{GEN x} is also available. pari-2.7.5/src/functions/transcendental/arg0000644000175000017500000000030611636712103017405 0ustar billbillFunction: arg Section: transcendental C-Name: garg Prototype: Gp Help: arg(x): argument of x,such that -pi1$ then $\text{asin}(x)$ is complex. The branch cut is in two pieces: $]-\infty,-1]$, continuous with quadrant II, and $[1,+\infty[$ continuous with quadrant IV. The function satisfies $i \text{asin}(x) = \text{asinh}(ix)$. pari-2.7.5/src/functions/transcendental/sinh0000644000175000017500000000020512366172547017610 0ustar billbillFunction: sinh Section: transcendental C-Name: gsinh Prototype: Gp Help: sinh(x): hyperbolic sine of x. Doc: hyperbolic sine of $x$. pari-2.7.5/src/functions/transcendental/teichmuller0000644000175000017500000000042611636712103021154 0ustar billbillFunction: teichmuller Section: transcendental C-Name: teich Prototype: G Help: teichmuller(x): teichmuller character of p-adic number x. Doc: Teichm\"uller character of the $p$-adic number $x$, i.e. the unique $(p-1)$-th root of unity congruent to $x / p^{v_p(x)}$ modulo $p$. pari-2.7.5/src/functions/transcendental/bernreal0000644000175000017500000000046011636712103020427 0ustar billbillFunction: bernreal Section: transcendental C-Name: bernreal Prototype: Lp Help: bernreal(x): Bernoulli number B_x, as a real number with the current precision. Doc: Bernoulli number\sidx{Bernoulli numbers} $B_x$, as \kbd{bernfrac}, but $B_x$ is returned as a real number (with the current precision). pari-2.7.5/src/functions/transcendental/bernfrac0000644000175000017500000000046711636712103020426 0ustar billbillFunction: bernfrac Section: transcendental C-Name: bernfrac Prototype: L Help: bernfrac(x): Bernoulli number B_x, as a rational number. Doc: Bernoulli number\sidx{Bernoulli numbers} $B_x$, where $B_0=1$, $B_1=-1/2$, $B_2=1/6$,\dots, expressed as a rational number. The argument $x$ should be of type integer. pari-2.7.5/src/functions/transcendental/asinh0000644000175000017500000000055612366172547017762 0ustar billbillFunction: asinh Section: transcendental C-Name: gasinh Prototype: Gp Help: asinh(x): inverse hyperbolic sine of x. Doc: principal branch of $\text{sinh}^{-1}(x) = \log(x + \sqrt{1+x^2})$. In particular $\text{Im(asinh}(x))\in [-\pi/2,\pi/2]$. The branch cut is in two pieces: [-i oo ,-i], continuous with quadrant III and [i,+i oo [ continuous with quadrant I. pari-2.7.5/src/functions/transcendental/acos0000644000175000017500000000074211636712103017565 0ustar billbillFunction: acos Section: transcendental C-Name: gacos Prototype: Gp Help: acos(x): arc cosine of x. Doc: principal branch of $\text{cos}^{-1}(x) = -i \log (x + i\sqrt{1-x^2})$. In particular, $\text{Re(acos}(x))\in [0,\pi]$ and if $x\in \R$ and $|x|>1$, then $\text{acos}(x)$ is complex. The branch cut is in two pieces: $]-\infty,-1]$ , continuous with quadrant II, and $[1,+\infty[$, continuous with quadrant IV. We have $\text{acos}(x) = \pi/2 - \text{asin}(x)$ for all $x$. pari-2.7.5/src/functions/transcendental/abs0000644000175000017500000000151111636712103017400 0ustar billbillFunction: abs Section: transcendental C-Name: gabs Prototype: Gp Help: abs(x): absolute value (or modulus) of x. Description: (small):small labs($1) (int):int mpabs($1) (real):real mpabs($1) (mp):mp mpabs($1) (gen):gen:prec gabs($1, prec) Doc: absolute value of $x$ (modulus if $x$ is complex). Rational functions are not allowed. Contrary to most transcendental functions, an exact argument is \emph{not} converted to a real number before applying \kbd{abs} and an exact result is returned if possible. \bprog ? abs(-1) %1 = 1 ? abs(3/7 + 4/7*I) %2 = 5/7 ? abs(1 + I) %3 = 1.414213562373095048801688724 @eprog\noindent If $x$ is a polynomial, returns $-x$ if the leading coefficient is real and negative else returns $x$. For a power series, the constant coefficient is considered instead. pari-2.7.5/src/functions/transcendental/eta0000644000175000017500000000212211636712103017403 0ustar billbillFunction: eta Section: transcendental C-Name: eta0 Prototype: GD0,L,p Help: 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. Doc: Variants of \idx{Dedekind}'s $\eta$ function. If $\fl = 0$, return $\prod_{n=1}^\infty(1-q^n)$, where $q$ depends on $x$ in the following way: \item $q = e^{2i\pi x}$ if $x$ is a \emph{complex number} (which must then have positive imaginary part); notice that the factor $q^{1/24}$ is missing! \item $q = x$ if $x$ is a \typ{PADIC}, or can be converted to a \emph{power series} (which must then have positive valuation). If $\fl$ is non-zero, $x$ is converted to a complex number and we return the true $\eta$ function, $q^{1/24}\prod_{n=1}^\infty(1-q^n)$, where $q = e^{2i\pi x}$. Variant: Also available is \fun{GEN}{trueeta}{GEN x, long prec} ($\fl=1$). pari-2.7.5/src/functions/transcendental/erfc0000644000175000017500000000053712314242551017560 0ustar billbillFunction: erfc Section: transcendental C-Name: gerfc Prototype: Gp Help: erfc(x): complementary error function. Doc: complementary error function, analytic continuation of $(2/\sqrt\pi)\int_x^\infty e^{-t^2}\,dt = \kbd{incgam}(1/2,x^2)/\sqrt\pi$, where the latter expression extends the function definition from real $x$ to all complex $x \neq 0$. pari-2.7.5/src/functions/transcendental/besselk0000644000175000017500000000031111636712103020260 0ustar billbillFunction: besselk Section: transcendental C-Name: kbessel Prototype: GGp Help: besselk(nu,x): K-bessel function of index nu and argument x. Doc: $K$-Bessel function of index \var{nu} and argument $x$. pari-2.7.5/src/functions/transcendental/incgamc0000644000175000017500000000063111636712103020236 0ustar billbillFunction: incgamc Section: transcendental C-Name: incgamc Prototype: GGp Help: incgamc(s,x): complementary incomplete gamma function. Doc: complementary incomplete gamma function. The arguments $x$ and $s$ are complex numbers such that $s$ is not a pole of $\Gamma$ and $|x|/(|s|+1)$ is not much larger than 1 (otherwise the convergence is very slow). The result returned is $\int_0^x e^{-t}t^{s-1}\,dt$. pari-2.7.5/src/functions/transcendental/theta0000644000175000017500000000034311636712103017742 0ustar billbillFunction: theta Section: transcendental C-Name: theta Prototype: GGp Help: theta(q,z): Jacobi sine theta-function. Doc: Jacobi sine theta-function $$ \theta_1(z, q) = 2q^{1/4} \sum_{n\geq 0} (-1)^n q^{n(n+1)} \sin((2n+1)z).$$ pari-2.7.5/src/functions/transcendental/lngamma0000644000175000017500000000200612314242551020246 0ustar billbillFunction: lngamma Section: transcendental C-Name: glngamma Prototype: Gp Help: lngamma(x): logarithm of the gamma function of x. Doc: principal branch of the logarithm of the gamma function of $x$. This function is analytic on the complex plane with non-positive integers removed, and can have much larger arguments than \kbd{gamma} itself. For $x$ a power series such that $x(0)$ is not a pole of \kbd{gamma}, compute the Taylor expansion. (PARI only knows about regular power series and can't include logarithmic terms.) \bprog ? lngamma(1+x+O(x^2)) %1 = -0.57721566490153286060651209008240243104*x + O(x^2) ? lngamma(x+O(x^2)) *** at top-level: lngamma(x+O(x^2)) *** ^----------------- *** lngamma: domain error in lngamma: valuation != 0 ? lngamma(-1+x+O(x^2)) *** lngamma: Warning: normalizing a series with 0 leading term. *** at top-level: lngamma(-1+x+O(x^2)) *** ^-------------------- *** lngamma: domain error in intformal: residue(series, pole) != 0 @eprog pari-2.7.5/src/functions/transcendental/bernvec0000644000175000017500000000133011636712103020256 0ustar billbillFunction: bernvec Section: transcendental C-Name: bernvec Prototype: L Help: bernvec(x): Vector of rational Bernoulli numbers B_0, B_2,...up to B_(2x). Doc: creates a vector containing, as rational numbers, the \idx{Bernoulli numbers} $B_0$, $B_2$,\dots, $B_{2x}$. This routine is obsolete. Use \kbd{bernfrac} instead each time you need a Bernoulli number in exact form. \misctitle{Note} This routine is implemented using repeated independent calls to \kbd{bernfrac}, which is faster than the standard recursion in exact arithmetic. It is only kept for backward compatibility: it is not faster than individual calls to \kbd{bernfrac}, its output uses a lot of memory space, and coping with the index shift is awkward. pari-2.7.5/src/functions/transcendental/besselh10000644000175000017500000000032011636712103020336 0ustar billbillFunction: besselh1 Section: transcendental C-Name: hbessel1 Prototype: GGp Help: besselh1(nu,x): H^1-bessel function of index nu and argument x. Doc: $H^1$-Bessel function of index \var{nu} and argument $x$. pari-2.7.5/src/functions/transcendental/dilog0000644000175000017500000000035011636712103017731 0ustar billbillFunction: dilog Section: transcendental C-Name: dilog Prototype: Gp Help: dilog(x): dilogarithm of x. Doc: principal branch of the dilogarithm of $x$, i.e.~analytic continuation of the power series $\log_2(x)=\sum_{n\ge1}x^n/n^2$. pari-2.7.5/src/functions/transcendental/gammah0000644000175000017500000000025312366172547020104 0ustar billbillFunction: gammah Section: transcendental C-Name: ggammah Prototype: Gp Help: gammah(x): gamma of x+1/2 (x integer). Doc: gamma function evaluated at the argument $x+1/2$. pari-2.7.5/src/functions/transcendental/sqr0000644000175000017500000000170311636712103017443 0ustar billbillFunction: sqr Section: transcendental C-Name: gsqr Prototype: G Help: sqr(x): square of x. NOT identical to x*x. Description: (int):int sqri($1) (mp):mp gsqr($1) (gen):gen gsqr($1) Doc: square of $x$. This operation is not completely straightforward, i.e.~identical to $x * x$, since it can usually be computed more efficiently (roughly one-half of the elementary multiplications can be saved). Also, squaring a $2$-adic number increases its precision. For example, \bprog ? (1 + O(2^4))^2 %1 = 1 + O(2^5) ? (1 + O(2^4)) * (1 + O(2^4)) %2 = 1 + O(2^4) @eprog\noindent Note that this function is also called whenever one multiplies two objects which are known to be \emph{identical}, e.g.~they are the value of the same variable, or we are computing a power. \bprog ? x = (1 + O(2^4)); x * x %3 = 1 + O(2^5) ? (1 + O(2^4))^4 %4 = 1 + O(2^6) @eprog\noindent (note the difference between \kbd{\%2} and \kbd{\%3} above). pari-2.7.5/src/functions/transcendental/expm10000644000175000017500000000200612413013143017655 0ustar billbillFunction: expm1 Section: transcendental C-Name: gexpm1 Prototype: Gp Help: expm1(x): exp(x)-1. Description: (real):real mpexpm1($1) Doc: return $\exp(x)-1$, computed in a way that is also accurate when the real part of $x$ is near $0$. Only accept real or complex arguments. A naive direct computation would suffer from catastrophic cancellation; PARI's direct computation of $\exp(x)$ alleviates this well known problem at the expense of computing $\exp(x)$ to a higher accuracy when $x$ is small. Using \kbd{expm1} is recommended instead: \bprog ? default(realprecision, 10000); x = 1e-100; ? a = expm1(x); time = 4 ms. ? b = exp(x)-1; time = 28 ms. ? default(realprecision, 10040); x = 1e-100; ? c = expm1(x); \\ reference point ? abs(a-c)/c \\ relative error in expm1(x) %7 = 0.E-10017 ? abs(b-c)/c \\ relative error in exp(x)-1 %8 = 1.7907031188259675794 E-9919 @eprog\noindent As the example above shows, when $x$ is near $0$, \kbd{expm1} is both faster and more accurate than \kbd{exp(x)-1}. pari-2.7.5/src/functions/transcendental/acosh0000644000175000017500000000056212366172547017752 0ustar billbillFunction: acosh Section: transcendental C-Name: gacosh Prototype: Gp Help: acosh(x): inverse hyperbolic cosine of x. Doc: principal branch of $\text{cosh}^{-1}(x) = 2 \log(\sqrt{(x+1)/2} + \sqrt{(x-1)/2})$. In particular, $\text{Re}(\text{acosh}(x))\geq 0$ and $\text{In}(\text{acosh}(x))\in ]-\pi,\pi]0$; if $x\in \R$ and $x<1$, then $\text{acosh}(x)$ is complex. pari-2.7.5/src/functions/transcendental/Catalan0000644000175000017500000000056212314242551020202 0ustar billbillFunction: Catalan Section: transcendental C-Name: mpcatalan Prototype: p Help: Catalan=Catalan(): Catalan's number with current precision. Description: ():real:prec mpcatalan(prec) Doc: Catalan's constant $G = \sum_{n>=0}\dfrac{(-1)^n}{(2n+1)^2}=0.91596\cdots$. Note that \kbd{Catalan} is one of the few reserved names which cannot be used for user variables. pari-2.7.5/src/functions/transcendental/thetanullk0000644000175000017500000000073412314242551021013 0ustar billbillFunction: thetanullk Section: transcendental C-Name: thetanullk Prototype: GLp Help: thetanullk(q,k): k-th derivative at z=0 of theta(q,z). Doc: $k$-th derivative at $z=0$ of $\kbd{theta}(q,z)$. Variant: \fun{GEN}{vecthetanullk}{GEN q, long k, long prec} returns the vector of all $\dfrac{d^i\theta}{dz^i}(q,0)$ for all odd $i = 1, 3, \dots, 2k-1$. \fun{GEN}{vecthetanullk_tau}{GEN tau, long k, long prec} returns \kbd{vecthetanullk\_tau} at $q = \exp(2i\pi \kbd{tau})$. pari-2.7.5/src/functions/transcendental/bernpol0000644000175000017500000000043312314242551020275 0ustar billbillFunction: bernpol Section: transcendental C-Name: bernpol Prototype: LDn Help: bernpol(n, {v = 'x}): Bernoulli polynomial B_n, in variable v. Doc: \idx{Bernoulli polynomial} $B_n$ in variable $v$. \bprog ? bernpol(1) %1 = x - 1/2 ? bernpol(3) %2 = x^3 - 3/2*x^2 + 1/2*x @eprog pari-2.7.5/src/functions/transcendental/besselj0000644000175000017500000000055411636712103020270 0ustar billbillFunction: besselj Section: transcendental C-Name: jbessel Prototype: GGp Help: besselj(nu,x): J-bessel function of index nu and argument x. Doc: $J$-Bessel function of index \var{nu} and argument $x$. If $x$ converts to a power series, the initial factor $(x/2)^\nu/\Gamma(\nu+1)$ is omitted (since it cannot be represented in PARI when $\nu$ is not integral). pari-2.7.5/src/functions/transcendental/exp0000644000175000017500000000060311636712103017430 0ustar billbillFunction: exp Section: transcendental C-Name: gexp Prototype: Gp Help: exp(x): exponential of x. Description: (real):real mpexp($1) (mp):mp:prec gexp($1, prec) (gen):gen:prec gexp($1, prec) Doc: exponential of $x$. $p$-adic arguments with positive valuation are accepted. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_exp}{GEN x} is also available. pari-2.7.5/src/functions/transcendental/weber0000644000175000017500000000205011636712103017736 0ustar billbillFunction: weber Section: transcendental C-Name: weber0 Prototype: GD0,L,p Help: 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. Doc: one of Weber's three $f$ functions. If $\fl=0$, returns $$f(x)=\exp(-i\pi/24)\cdot\eta((x+1)/2)\,/\,\eta(x) \quad\hbox{such that}\quad j=(f^{24}-16)^3/f^{24}\,,$$ where $j$ is the elliptic $j$-invariant (see the function \kbd{ellj}). If $\fl=1$, returns $$f_1(x)=\eta(x/2)\,/\,\eta(x)\quad\hbox{such that}\quad j=(f_1^{24}+16)^3/f_1^{24}\,.$$ Finally, if $\fl=2$, returns $$f_2(x)=\sqrt{2}\eta(2x)\,/\,\eta(x)\quad\hbox{such that}\quad j=(f_2^{24}+16)^3/f_2^{24}.$$ Note the identities $f^8=f_1^8+f_2^8$ and $ff_1f_2=\sqrt2$. Variant: Also available are \fun{GEN}{weberf}{GEN x, long prec}, \fun{GEN}{weberf1}{GEN x, long prec} and \fun{GEN}{weberf2}{GEN x, long prec}. pari-2.7.5/src/functions/transcendental/psi0000644000175000017500000000027412314242551017432 0ustar billbillFunction: psi Section: transcendental C-Name: gpsi Prototype: Gp Help: psi(x): psi-function at x. Doc: the $\psi$-function of $x$, i.e.~the logarithmic derivative $\Gamma'(x)/\Gamma(x)$. pari-2.7.5/src/functions/transcendental/Pi0000644000175000017500000000045512314242551017210 0ustar billbillFunction: Pi Section: transcendental C-Name: mppi Prototype: p Help: Pi=Pi(): the constant pi, with current precision. Description: ():real:prec mppi(prec) Doc: the constant $\pi$ ($3.14159\cdots$). Note that \kbd{Pi} is one of the few reserved names which cannot be used for user variables. pari-2.7.5/src/functions/transcendental/hyperu0000644000175000017500000000046211636712103020153 0ustar billbillFunction: hyperu Section: transcendental C-Name: hyperu Prototype: GGGp Help: hyperu(a,b,x): U-confluent hypergeometric function. Doc: $U$-confluent hypergeometric function with parameters $a$ and $b$. The parameters $a$ and $b$ can be complex but the present implementation requires $x$ to be positive. pari-2.7.5/src/functions/transcendental/agm0000644000175000017500000000101612314242551017376 0ustar billbillFunction: agm Section: transcendental C-Name: agm Prototype: GGp Help: agm(x,y): arithmetic-geometric mean of x and y. Doc: arithmetic-geometric mean of $x$ and $y$. In the case of complex or negative numbers, the optimal AGM is returned (the largest in absolute value over all choices of the signs of the square roots). $p$-adic or power series arguments are also allowed. Note that a $p$-adic agm exists only if $x/y$ is congruent to 1 modulo $p$ (modulo 16 for $p=2$). $x$ and $y$ cannot both be vectors or matrices. pari-2.7.5/src/functions/transcendental/eint10000644000175000017500000000231612366172547017674 0ustar billbillFunction: eint1 Section: transcendental C-Name: veceint1 Prototype: GDGp Help: 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) Doc: exponential integral $\int_x^\infty \dfrac{e^{-t}}{t}\,dt = \kbd{incgam}(0, x)$, where the latter expression extends the function definition from real $x > 0$ to all complex $x \neq 0$. If $n$ is present, we must have $x > 0$; the function returns the $n$-dimensional vector $[\kbd{eint1}(x),\dots,\kbd{eint1}(nx)]$. Contrary to other transcendental functions, and to the default case ($n$ omitted), the values are correct up to a bounded \emph{absolute}, rather than relative, error $10^-n$, where $n$ is \kbd{precision}$(x)$ if $x$ is a \typ{REAL} and defaults to \kbd{realprecision} otherwise. (In the most important application, to the computation of $L$-functions via approximate functional equations, those values appear as weights in long sums and small individual relative errors are less useful than controlling the absolute error.) This is faster than repeatedly calling \kbd{eint1($i$ * x)}, but less precise. Variant: Also available is \fun{GEN}{eint1}{GEN x, long prec}. pari-2.7.5/src/functions/transcendental/atan0000644000175000017500000000073111636712103017561 0ustar billbillFunction: atan Section: transcendental C-Name: gatan Prototype: Gp Help: atan(x): arc tangent of x. Doc: principal branch of $\text{tan}^{-1}(x) = \log ((1+ix)/(1-ix)) / 2i$. In particular the real part of $\text{atan}(x))$ belongs to $]-\pi/2,\pi/2[$. The branch cut is in two pieces: $]-i\infty,-i[$, continuous with quadrant IV, and $]i,+i \infty[$ continuous with quadrant II. The function satisfies $i \text{atan}(x) = -i\text{atanh}(ix)$ for all $x\neq \pm i$. pari-2.7.5/src/functions/transcendental/incgam0000644000175000017500000000116212314242551020072 0ustar billbillFunction: incgam Section: transcendental C-Name: incgam0 Prototype: GGDGp Help: incgam(s,x,{g}): incomplete gamma function. g is optional and is the precomputed value of gamma(s). Doc: incomplete gamma function $\int_x^\infty e^{-t}t^{s-1}\,dt$, extended by analytic continuation to all complex $x, s$ not both $0$. The relative error is bounded in terms of the precision of $s$ (the accuracy of $x$ is ignored when determining the output precision). When $g$ is given, assume that $g=\Gamma(s)$. For small $|x|$, this will speed up the computation. Variant: Also available is \fun{GEN}{incgam}{GEN s, GEN x, long prec}. pari-2.7.5/src/functions/transcendental/sin0000644000175000017500000000015411636712103017426 0ustar billbillFunction: sin Section: transcendental C-Name: gsin Prototype: Gp Help: sin(x): sine of x. Doc: sine of $x$. pari-2.7.5/src/functions/transcendental/tanh0000644000175000017500000000021312366172547017600 0ustar billbillFunction: tanh Section: transcendental C-Name: gtanh Prototype: Gp Help: tanh(x): hyperbolic tangent of x. Doc: hyperbolic tangent of $x$. pari-2.7.5/src/functions/transcendental/besseln0000644000175000017500000000031111636712103020263 0ustar billbillFunction: besseln Section: transcendental C-Name: nbessel Prototype: GGp Help: besseln(nu,x): N-bessel function of index nu and argument x. Doc: $N$-Bessel function of index \var{nu} and argument $x$. pari-2.7.5/src/functions/transcendental/polylog0000644000175000017500000000310011636712103020314 0ustar billbillFunction: polylog Section: transcendental C-Name: polylog0 Prototype: LGD0,L,p Help: 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. Doc: one of the different polylogarithms, depending on \fl: If $\fl=0$ or is omitted: $m^\text{th}$ polylogarithm of $x$, i.e.~analytic continuation of the power series $\text{Li}_m(x)=\sum_{n\ge1}x^n/n^m$ ($x < 1$). Uses the functional equation linking the values at $x$ and $1/x$ to restrict to the case $|x|\leq 1$, then the power series when $|x|^2\le1/2$, and the power series expansion in $\log(x)$ otherwise. Using $\fl$, computes a modified $m^\text{th}$ polylogarithm of $x$. We use Zagier's notations; let $\Re_m$ denote $\Re$ or $\Im$ depending on whether $m$ is odd or even: If $\fl=1$: compute $\tilde D_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1} \dfrac{(-\log|x|)^k}{k!}\text{Li}_{m-k}(x) +\dfrac{(-\log|x|)^{m-1}}{m!}\log|1-x|\right).$$ If $\fl=2$: compute $D_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1}\dfrac{(-\log|x|)^k}{k!}\text{Li}_{m-k}(x) -\dfrac{1}{2}\dfrac{(-\log|x|)^m}{m!}\right).$$ If $\fl=3$: compute $P_m(x)$, defined for $|x|\le1$ by $$\Re_m\left(\sum_{k=0}^{m-1}\dfrac{2^kB_k}{k!}(\log|x|)^k\text{Li}_{m-k}(x) -\dfrac{2^{m-1}B_m}{m!}(\log|x|)^m\right).$$ These three functions satisfy the functional equation $f_m(1/x) = (-1)^{m-1}f_m(x)$. Variant: Also available is \fun{GEN}{gpolylog}{long m, GEN x, long prec} (\fl = 0). pari-2.7.5/src/functions/transcendental/besseljh0000644000175000017500000000067611636712103020445 0ustar billbillFunction: besseljh Section: transcendental C-Name: jbesselh Prototype: GGp Help: besseljh(n,x): J-bessel function of index n+1/2 and argument x, where n is a non-negative integer. Doc: $J$-Bessel function of half integral index. More precisely, $\kbd{besseljh}(n,x)$ computes $J_{n+1/2}(x)$ where $n$ must be of type integer, and $x$ is any element of $\C$. In the present version \vers, this function is not very accurate when $x$ is small. pari-2.7.5/src/functions/transcendental/lambertw0000644000175000017500000000034112366172547020465 0ustar billbillFunction: lambertw Section: transcendental C-Name: glambertW Prototype: Gp Help: lambertw(y): solution of the implicit equation x*exp(x)=y. Doc: Lambert $W$ function, solution of the implicit equation $xe^x=y$, for $y > 0$. pari-2.7.5/src/functions/transcendental/Euler0000644000175000017500000000050312314242551017706 0ustar billbillFunction: Euler Section: transcendental C-Name: mpeuler Prototype: p Help: Euler=Euler(): Euler's constant with current precision. Description: ():real:prec mpeuler(prec) Doc: Euler's constant $\gamma=0.57721\cdots$. Note that \kbd{Euler} is one of the few reserved names which cannot be used for user variables. pari-2.7.5/src/functions/default/0000755000175000017500000000000012613365633015341 5ustar billbillpari-2.7.5/src/functions/default/timer0000644000175000017500000000164412314242551016400 0ustar billbillFunction: _def_timer Class: gp_default Section: default C-Name: sd_timer Prototype: Help: Doc: 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, to some accuracy depending on the hardware and operating system. When \tet{timer} is on, each such timing is printed immediately before the output as follows: \bprog ? factor(2^2^7+1) time = 108 ms. \\ this line omitted if 'timer' is 0 %1 = [ 59649589127497217 1] [5704689200685129054721 1] @eprog\noindent (See also \kbd{\#} and \kbd{\#\#}.) The time measured is the user \idx{CPU time}, \emph{not} including the time for printing the results. If the time is negligible ($< 1$ ms.), nothing is printed: in particular, no timing should be printed when defining a user function or an alias, or installing a symbol from the library. The default value is \kbd{0} (off). pari-2.7.5/src/functions/default/factor_proven0000644000175000017500000000124012413013142020107 0ustar billbillFunction: _def_factor_proven Class: default Section: default C-Name: sd_factor_proven Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). By default, the factors output by the integer factorization machinery are only pseudo-primes, not proven primes. If this toggle is set, a primality proof is done for each factor and all results depending on integer factorization are fully proven. This flag does not affect partial factorization when it is explicitly requested. It also does not affect the private table managed by \tet{addprimes}: its entries are included as is in factorizations, without being tested for primality. The default value is \kbd{0}. pari-2.7.5/src/functions/default/psfile0000644000175000017500000000047511636712103016544 0ustar billbillFunction: _def_psfile Class: gp_default Section: default C-Name: sd_psfile Prototype: Help: Doc: name of the default file where \kbd{gp} is to dump its PostScript drawings (these are appended, so that no previous data are lost). Environment and time expansion are performed. The default value is \kbd{"pari.ps"}. pari-2.7.5/src/functions/default/TeXstyle0000644000175000017500000000100411636712103017030 0ustar billbillFunction: _def_TeXstyle Class: default Section: default C-Name: sd_TeXstyle Prototype: Help: Doc: the bits of this default allow \kbd{gp} to use less rigid TeX formatting commands in the logfile. This default is only taken into account when $\kbd{log} = 3$. The bits of \kbd{TeXstyle} have the following meaning 2: insert \kbd{\bs right} / \kbd{\bs left} pairs where appropriate. 4: insert discretionary breaks in polynomials, to enhance the probability of a good line break. The default value is \kbd{0}. pari-2.7.5/src/functions/default/seriesprecision0000644000175000017500000000040111636712103020455 0ustar billbillFunction: _def_seriesprecision Class: default Section: default C-Name: sd_seriesprecision Prototype: Help: Doc: number of significant terms when converting a polynomial or rational function to a power series (see~\b{ps}). The default value is \kbd{16}. pari-2.7.5/src/functions/default/new_galois_format0000644000175000017500000000072412413013142020745 0ustar billbillFunction: _def_new_galois_format Class: default Section: default C-Name: sd_new_galois_format Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If on, the \tet{polgalois} command will use a different, more consistent, naming scheme for Galois groups. This default is provided to ensure that scripts can control this behavior and do not break unexpectedly. The default value is \kbd{0}. This value will change to $1$ (set) in the next major version. pari-2.7.5/src/functions/default/breakloop0000644000175000017500000000044311636712103017233 0ustar billbillFunction: _def_breakloop Class: gp_default Section: default C-Name: sd_breakloop Prototype: Help: Doc: if true, enables the ``break loop'' debugging mode, see \secref{se:break_loop}. The default value is \kbd{1} if we are running an interactive \kbd{gp} session, and \kbd{0} otherwise. pari-2.7.5/src/functions/default/strictargs0000644000175000017500000000150012413013142017424 0ustar billbillFunction: _def_strictargs Class: default Section: default C-Name: sd_strictargs Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If on, all arguments to \emph{new} user functions are mandatory unless the function supplies an explicit default value. Otherwise arguments have the default value $0$. In this example, \bprog fun(a,b=2)=a+b @eprog \kbd{a} is mandatory, while \kbd{b} is optional. If \kbd{strictargs} is on: \bprog ? fun() *** at top-level: fun() *** ^----- *** in function fun: a,b=2 *** ^----- *** missing mandatory argument 'a' in user function. @eprog This applies to functions defined while \kbd{strictargs} is on. Changing \kbd{strictargs} does not affect the behavior of previously defined functions. The default value is \kbd{0}. pari-2.7.5/src/functions/default/log0000644000175000017500000000140611636712103016036 0ustar billbillFunction: _def_log Class: default Section: default C-Name: sd_log Prototype: Help: Doc: this can be either 0 (off) or 1, 2, 3 (on, see below for the various modes). When logging mode is turned on, \kbd{gp} opens a log file, whose exact name is determined by the \kbd{logfile} default. Subsequently, all the commands and results will be written to that file (see \b{l}). In case a file with this precise name already existed, it will not be erased: your data will be \emph{appended} at the end. The specific positive values of \kbd{log} have the following meaning 1: plain logfile 2: emit color codes to the logfile (if \kbd{colors} is set). 3: write LaTeX output to the logfile (can be further customized using \tet{TeXstyle}). The default value is \kbd{0}. pari-2.7.5/src/functions/default/help0000644000175000017500000000060712366172547016224 0ustar billbillFunction: _def_help Class: gp_default Section: default C-Name: sd_help Prototype: Help: Doc: name of the external help program to use from within \kbd{gp} when extended help is invoked, usually through a \kbd{??} or \kbd{???} request (see \secref{se:exthelp}), or \kbd{M-H} under readline (see \secref{se:readline}). The default value is the path to the \kbd{gphelp} script we install. pari-2.7.5/src/functions/default/linewrap0000644000175000017500000000036012314242551017073 0ustar billbillFunction: _def_linewrap Class: gp_default Section: default C-Name: sd_linewrap Prototype: Help: Doc: if set to a positive value, \kbd{gp} wraps every single line after printing that many characters. The default value is \kbd{0} (unset). pari-2.7.5/src/functions/default/output0000644000175000017500000000257312366172547016640 0ustar billbillFunction: _def_output Class: default Section: default C-Name: sd_output Prototype: Help: Doc: there are three possible values: 0 (=~\var{raw}), 1 (=~\var{prettymatrix}), or 3 (=~\var{external} \var{prettyprint}). This means that, independently of the default \kbd{format} for reals which we explained above, you can print results in three ways: \item \tev{raw format}, i.e.~a format which is equivalent to what you input, including explicit multiplication signs, and everything typed on a line instead of two dimensional boxes. This can have several advantages, for instance it allows you to pick the result with a mouse or an editor, and to paste it somewhere else. \item \tev{prettymatrix format}: this is identical to raw format, except that matrices are printed as boxes instead of horizontally. This is prettier, but takes more space and cannot be used for input. Column vectors are still printed horizontally. \item \tev{external prettyprint}: pipes all \kbd{gp} output in TeX format to an external prettyprinter, according to the value of \tet{prettyprinter}. The default script (\tet{tex2mail}) converts its input to readable two-dimensional text. Independently of the setting of this default, an object can be printed in any of the three formats at any time using the commands \b{a} and \b{m} and \b{B} respectively. The default value is \kbd{1} (\var{prettymatrix}). pari-2.7.5/src/functions/default/readline0000644000175000017500000000066611636712103017047 0ustar billbillFunction: _def_readline Class: gp_default Section: default C-Name: sd_readline Prototype: Help: Doc: switches readline line-editing facilities on and off. This may be useful if you are running \kbd{gp} in a Sun \tet{cmdtool}, which interacts badly with readline. Of course, until readline is switched on again, advanced editing features like automatic completion and editing history are not available. The default value is \kbd{1}. pari-2.7.5/src/functions/default/debugfiles0000644000175000017500000000046311636712103017370 0ustar billbillFunction: _def_debugfiles Class: default Section: default C-Name: sd_debugfiles Prototype: Help: Doc: file usage debugging level. If it is non-zero, \kbd{gp} will print information on file descriptors in use, from PARI's point of view (see~\b{gf}). The default value is \kbd{0} (no debugging messages). pari-2.7.5/src/functions/default/realprecision0000644000175000017500000000243212314242551020113 0ustar billbillFunction: _def_realprecision Class: default Section: default C-Name: sd_realprecision Prototype: Help: Doc: the number of significant digits used to convert exact inputs given to transcendental functions (see \secref{se:trans}), or to create absolute floating point constants (input as \kbd{1.0} or \kbd{Pi} for instance). Unless you tamper with the \tet{format} default, this is also the number of significant digits used to print a \typ{REAL} number; \kbd{format} will override this latter behaviour, and allow you to have a large internal precision while outputting few digits for instance. Note that PARI's internal precision works on a word basis (by increments of 32 or 64 bits), hence may be a little larger than the number of decimal digits you expected. For instance to get 2 decimal digits you need one word of precision which, on a 64-bit machine, actually gives you 19 digits ($19 < \log_{10}(2^{64}) < 20$). The value returned when typing \kbd{default(realprecision)} is the internal number of significant digits, not the number of printed digits: \bprog ? default(realprecision, 2) realprecision = 19 significant digits (2 digits displayed) ? default(realprecision) %1 = 19 @eprog The default value is \kbd{38}, resp.~\kbd{28}, on a 64-bit, resp~.32-bit, machine. pari-2.7.5/src/functions/default/graphcolormap0000644000175000017500000000175612314242551020122 0ustar billbillFunction: _def_graphcolormap Class: gp_default Section: default C-Name: sd_graphcolormap Prototype: Help: Doc: a vector of colors, to be used by hi-res graphing routines. Its length is arbitrary, but it must contain at least 3 entries: the first 3 colors are used for background, frame/ticks and axes respectively. All colors in the colormap may be freely used in \tet{plotcolor} calls. A color is either given as in the default by character strings or by an RGB code. For valid character strings, see the standard \kbd{rgb.txt} file in X11 distributions, where we restrict to lowercase letters and remove all whitespace from color names. An RGB code is a vector with 3 integer entries between 0 and 255. For instance \kbd{[250, 235, 215]} and \kbd{"antiquewhite"} represent the same color. RGB codes are cryptic but often easier to generate. The default value is [\kbd{"white"}, \kbd{"black"}, \kbd{"blue"}, \kbd{"violetred"}, \kbd{"red"}, \kbd{"green"}, \kbd{"grey"}, \kbd{"gainsboro"}]. pari-2.7.5/src/functions/default/strictmatch0000644000175000017500000000073011636712103017601 0ustar billbillFunction: _def_strictmatch Class: default 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}. pari-2.7.5/src/functions/default/sopath0000644000175000017500000000147212314242551016555 0ustar billbillFunction: _def_sopath Class: default Section: default C-Name: sd_sopath Prototype: Help: Doc: this is a list of directories, separated by colons ':' (semicolons ';' in the DOS world, since colons are preempted for drive names). When asked to \tet{install} an external symbol from a shared library whose name is not given by an absolute path (does not start with \kbd{/}, \kbd{./} or \kbd{../}), \kbd{gp} will look for it in these directories, in the order they were written in \kbd{sopath}. Here, as usual, \kbd{.} means the current directory, and \kbd{..} its immediate parent. Environment expansion is performed. The default value is \kbd{""}, corresponding to an empty list of directories: \tet{install} will use the library name as input (and look in the current directory if the name is not an absolute path). pari-2.7.5/src/functions/default/colors0000644000175000017500000000420312366172547016571 0ustar billbillFunction: _def_colors Class: default Section: default C-Name: sd_colors Prototype: Help: Doc: this default is only usable if \kbd{gp} is running within certain color-capable terminals. For instance \kbd{rxvt}, \kbd{color\_xterm} and modern versions of \kbd{xterm} under X Windows, or standard Linux/DOS text consoles. It causes \kbd{gp} to use a small palette of colors for its output. With xterms, the colormap used corresponds to the resources \kbd{Xterm*color$n$} where $n$ ranges from $0$ to $15$ (see the file \kbd{misc/color.dft} for an example). Accepted values for this default are strings \kbd{"$a_1$,\dots,$a_k$"} where $k\le7$ and each $a_i$ is either \noindent\item the keyword \kbd{no} (use the default color, usually black on transparent background) \noindent\item an integer between 0 and 15 corresponding to the aforementioned colormap \noindent\item a triple $[c_0,c_1,c_2]$ where $c_0$ stands for foreground color, $c_1$ for background color, and $c_2$ for attributes (0 is default, 1 is bold, 4 is underline). The output objects thus affected are respectively error messages, history numbers, prompt, input line, output, help messages, timer (that's seven of them). If $k < 7$, the remaining $a_i$ are assumed to be $no$. For instance % \bprog default(colors, "9, 5, no, no, 4") @eprog \noindent typesets error messages in color $9$, history numbers in color $5$, output in color $4$, and does not affect the rest. A set of default colors for dark (reverse video or PC console) and light backgrounds respectively is activated when \kbd{colors} is set to \kbd{darkbg}, resp.~\kbd{lightbg} (or any proper prefix: \kbd{d} is recognized as an abbreviation for \kbd{darkbg}). A bold variant of \kbd{darkbg}, called \kbd{boldfg}, is provided if you find the former too pale. \emacs In the present version, this default is incompatible with PariEmacs. Changing it will just fail silently (the alternative would be to display escape sequences as is, since Emacs will refuse to interpret them). You must customize color highlighting from the PariEmacs side, see its documentation. The default value is \kbd{""} (no colors). pari-2.7.5/src/functions/default/format0000644000175000017500000000260211636712103016544 0ustar billbillFunction: _def_format Class: default Section: default C-Name: sd_format Prototype: Help: Doc: of the form x$.n$, where x (conversion style) is a letter in $\{\kbd{e},\kbd{f},\kbd{g}\}$, and $n$ (precision) is an integer; this affects the way real numbers are printed: \item If the conversion style is \kbd{e}, real numbers are printed in \idx{scientific format}, always with an explicit exponent, e.g.~\kbd{3.3 E-5}. \item In style \kbd{f}, real numbers are generally printed in \idx{fixed floating point format} without exponent, e.g.~\kbd{0.000033}. A large real number, whose integer part is not well defined (not enough significant digits), is printed in style~\kbd{e}. For instance \kbd{10.\pow 100} known to ten significant digits is always printed in style \kbd{e}. \item In style \kbd{g}, non-zero real numbers are printed in \kbd{f} format, except when their decimal exponent is $< -4$, in which case they are printed in \kbd{e} format. Real zeroes (of arbitrary exponent) are printed in \kbd{e} format. The precision $n$ is the number of significant digits printed for real numbers, except if $n<0$ where all the significant digits will be printed (initial default 28, or 38 for 64-bit machines). For more powerful formatting possibilities, see \tet{printf} and \tet{Strprintf}. The default value is \kbd{"g.28"} and \kbd{"g.38"} on 32-bit and 64-bit machines, respectively. pari-2.7.5/src/functions/default/recover0000644000175000017500000000047011636712103016722 0ustar billbillFunction: _def_recover Class: gp_default Section: default C-Name: sd_recover Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If you change this to $0$, any error becomes fatal and causes the gp interpreter to exit immediately. Can be useful in batch job scripts. The default value is \kbd{1}. pari-2.7.5/src/functions/default/prompt0000644000175000017500000000265411636712103016604 0ustar billbillFunction: _def_prompt Class: gp_default Section: default C-Name: sd_prompt Prototype: Help: Doc: a string that will be printed as prompt. Note that most usual escape sequences are available there: \b{e} for Esc, \b{n} for Newline, \dots, \kbd{\bs\bs} for \kbd{\bs}. Time expansion is performed. This string is sent through the library function \tet{strftime} (on a Unix system, you can try \kbd{man strftime} at your shell prompt). This means that \kbd{\%} constructs have a special meaning, usually related to the time and date. For instance, \kbd{\%H} = hour (24-hour clock) and \kbd{\%M} = minute [00,59] (use \kbd{\%\%} to get a real \kbd{\%}). If you use \kbd{readline}, escape sequences in your prompt will result in display bugs. If you have a relatively recent \kbd{readline} (see the comment at the end of \secref{se:def,colors}), you can brace them with special sequences (\kbd{\bs[} and \kbd{\bs]}), and you will be safe. If these just result in extra spaces in your prompt, then you'll have to get a more recent \kbd{readline}. See the file \kbd{misc/gprc.dft} for an example. \emacs {\bf Caution}: PariEmacs needs to know about the prompt pattern to separate your input from previous \kbd{gp} results, without ambiguity. It is not a trivial problem to adapt automatically this regular expression to an arbitrary prompt (which can be self-modifying!). See PariEmacs's documentation. The default value is \kbd{"? "}. pari-2.7.5/src/functions/default/logfile0000644000175000017500000000037111636712103016676 0ustar billbillFunction: _def_logfile Class: default Section: default C-Name: sd_logfile Prototype: Help: Doc: name of the log file to be used when the \kbd{log} toggle is on. Environment and time expansion are performed. The default value is \kbd{"pari.log"}. pari-2.7.5/src/functions/default/nbthreads0000644000175000017500000000074212366172547017246 0ustar billbillFunction: _def_nbthreads Class: default Section: default C-Name: sd_nbthreads Prototype: Help: Doc: Number of threads to use for parallel computing. The exact meaning an default depend on the \kbd{mt} engine used: \item \kbd{single}: not used (always one thread). \item \kbd{pthread}: number of threads (unlimited, default: number of core) \item \kbd{mpi}: number of MPI process to use (limited to the number allocated by \kbd{mpirun}, default: use all allocated process). pari-2.7.5/src/functions/default/lines0000644000175000017500000000105411636712103016366 0ustar billbillFunction: _def_lines Class: gp_default Section: default C-Name: sd_lines Prototype: Help: Doc: if set to a positive value, \kbd{gp} prints at most that many lines from each result, terminating the last line shown with \kbd{[+++]} if further material has been suppressed. The various \kbd{print} commands (see \secref{se:gp_program}) are unaffected, so you can always type \kbd{print(\%)} or \b{a} to view the full result. If the actual screen width cannot be determined, a ``line'' is assumed to be 80 characters long. The default value is \kbd{0}. pari-2.7.5/src/functions/default/secure0000644000175000017500000000071011636712103016540 0ustar billbillFunction: _def_secure Class: default Section: default C-Name: sd_secure Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If on, the \tet{system} and \tet{extern} command are disabled. These two commands are potentially dangerous when you execute foreign scripts since they let \kbd{gp} execute arbitrary UNIX commands. \kbd{gp} will ask for confirmation before letting you (or a script) unset this toggle. The default value is \kbd{0}. pari-2.7.5/src/functions/default/echo0000644000175000017500000000072411636712103016175 0ustar billbillFunction: _def_echo Class: gp_default Section: default C-Name: sd_echo Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). When \kbd{echo} mode is on, each command is reprinted before being executed. This can be useful when reading a file with the \b{r} or \kbd{read} commands. For example, it is turned on at the beginning of the test files used to check whether \kbd{gp} has been built correctly (see \b{e}). The default value is \kbd{0} (no echo). pari-2.7.5/src/functions/default/primelimit0000644000175000017500000000331212314242551017425 0ustar billbillFunction: _def_primelimit Class: default Section: default C-Name: sd_primelimit Prototype: Help: Doc: \kbd{gp} precomputes a list of all primes less than \kbd{primelimit} at initialization time, and can build fast sieves on demand to quickly iterate over primes up to the \emph{square} of \kbd{primelimit}. These are used by many arithmetic functions, usually for trial division purposes. The maximal value is $2^{32} - 2049$ (resp $2^{64} - 2049$) on a 32-bit (resp.~64-bit) machine, but values beyond $10^8$, allowing to iterate over primes up to $10^{16}$, do not seem useful. Since almost all arithmetic functions eventually require some table of prime numbers, PARI guarantees that the first 6547 primes, up to and including 65557, are precomputed, even if \kbd{primelimit} is $1$. This default is only used on startup: changing it will not recompute a new table. \misctitle{Deprecated feature} \kbd{primelimit} was used in some situations by algebraic number theory functions using the \tet{nf_PARTIALFACT} flag (\tet{nfbasis}, \tet{nfdisc}, \tet{nfinit}, \dots): this assumes that all primes $p > \kbd{primelimit}$ have a certain property (the equation order is $p$-maximal). This is never done by default, and must be explicitly set by the user of such functions. Nevertheless, these functions now provide a more flexible interface, and their use of the global default \kbd{primelimit} is deprecated. \misctitle{Deprecated feature} \kbd{factor(N, 0)} was used to partially factor integers by removing all prime factors $\leq$ \kbd{primelimit}. Don't use this, supply an explicit bound: \kbd{factor(N, bound)}, which avoids relying on an unpredictable global variable. The default value is \kbd{500k}. pari-2.7.5/src/functions/default/parisize0000644000175000017500000000131012405547147017106 0ustar billbillFunction: _def_parisize Class: default Section: default 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. The default value is 4M, resp.~8M on a 32-bit, resp.~64-bit machine. pari-2.7.5/src/functions/default/threadsize0000644000175000017500000000073512413013142017412 0ustar billbillFunction: _def_threadsize Class: default Section: default C-Name: sd_threadsize Prototype: Help: Doc: In parallel mode, each thread needs its own private \tev{stack} in which to do its computations, see \kbd{parisize}. This value determines the size in bytes of the stacks of each thread, so the total memory allocated will be $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. If set to $0$, the value used is the same as \kbd{parisize}. The default value is $0$. pari-2.7.5/src/functions/default/debugmem0000644000175000017500000000111711636712103017041 0ustar billbillFunction: _def_debugmem Class: default Section: default C-Name: sd_debugmem Prototype: Help: Doc: memory debugging level. If it is non-zero, \kbd{gp} will regularly print information on memory usage. If it's greater than 2, it will indicate any important garbage collecting and the function it is taking place in (see~\b{gm}). \noindent {\bf Important Note:} As it noticeably slows down the performance, the first functionality (memory usage) is disabled if you're not running a version compiled for debugging (see Appendix~A). The default value is \kbd{0} (no debugging messages). pari-2.7.5/src/functions/default/simplify0000644000175000017500000000154411636712103017114 0ustar billbillFunction: _def_simplify Class: default Section: default C-Name: sd_simplify Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). When the PARI library computes something, the type of the result is not always the simplest possible. The only type conversions which the PARI library does automatically are rational numbers to integers (when they are of type \typ{FRAC} and equal to integers), and similarly rational functions to polynomials (when they are of type \typ{RFRAC} and equal to polynomials). This feature is useful in many cases, and saves time, but can be annoying at times. Hence you can disable this and, whenever you feel like it, use the function \kbd{simplify} (see Chapter 3) which allows you to simplify objects to the simplest possible types recursively (see~\b{y}). \sidx{automatic simplification} The default value is \kbd{1}. pari-2.7.5/src/functions/default/prettyprinter0000644000175000017500000000061311636712103020207 0ustar billbillFunction: _def_prettyprinter Class: default Section: default C-Name: sd_prettyprinter Prototype: Help: Doc: the name of an external prettyprinter to use when \kbd{output} is~3 (alternate prettyprinter). Note that the default \tet{tex2mail} looks much nicer than the built-in ``beautified format'' ($\kbd{output} = 2$). The default value is \kbd{"tex2mail -TeX -noindent -ragged -by\_par"}. pari-2.7.5/src/functions/default/datadir0000644000175000017500000000057411636712103016672 0ustar billbillFunction: _def_datadir Class: default Section: default C-Name: sd_datadir Prototype: Help: Doc: the name of directory containing the optional data files. For now, this includes the \kbd{elldata}, \kbd{galdata}, \kbd{galpol}, \kbd{seadata} packages. The default value is \datadir (the location of installed precomputed data, can be specified via \kbd{Configure --datadir=}). pari-2.7.5/src/functions/default/histfile0000644000175000017500000000106211636712103017062 0ustar billbillFunction: _def_histfile Class: gp_default Section: default C-Name: sd_histfile Prototype: Help: Doc: name of a file where \kbd{gp} will keep a history of all \emph{input} commands (results are omitted). If this file exists when the value of \kbd{histfile} changes, it is read in and becomes part of the session history. Thus, setting this default in your gprc saves your readline history between sessions. Setting this default to the empty string \kbd{""} changes it to \kbd{$<$undefined$>$} The default value is \kbd{$<$undefined$>$} (no history file). pari-2.7.5/src/functions/default/compatible0000644000175000017500000000425312413013142017366 0ustar billbillFunction: _def_compatible Class: default 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}. pari-2.7.5/src/functions/default/graphcolors0000644000175000017500000000062311636712103017600 0ustar billbillFunction: _def_graphcolors Class: gp_default Section: default C-Name: sd_graphcolors Prototype: Help: Doc: entries in the \tet{graphcolormap} that will be used to plot multi-curves. The successive curves are drawn in colors \kbd{graphcolormap[graphcolors[1]]}, \kbd{graphcolormap[graphcolors[2]]}, \dots cycling when the \kbd{graphcolors} list is exhausted. The default value is \kbd{[4,5]}. pari-2.7.5/src/functions/default/histsize0000644000175000017500000000067311636712103017124 0ustar billbillFunction: _def_histsize Class: default Section: default C-Name: sd_histsize Prototype: Help: Doc: \kbd{gp} keeps a history of the last \kbd{histsize} results computed so far, which you can recover using the \kbd{\%} notation (see \secref{se:history}). When this number is exceeded, the oldest values are erased. Tampering with this default is the only way to get rid of the ones you do not need anymore. The default value is \kbd{5000}. pari-2.7.5/src/functions/default/factor_add_primes0000644000175000017500000000140612413013142020711 0ustar billbillFunction: _def_factor_add_primes Class: default Section: default C-Name: sd_factor_add_primes Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If on, the integer factorization machinery calls \tet{addprimes} on primes factor that were difficult to find (larger than $2^24$), so they are automatically tried first in other factorizations. If a routine is performing (or has performed) a factorization and is interrupted by an error or via Control-C, this lets you recover the prime factors already found. The downside is that a huge \kbd{addprimes} table unrelated to the current computations will slow down arithmetic functions relying on integer factorization; one should then empty the table using \tet{removeprimes}. The default value is \kbd{0}. pari-2.7.5/src/functions/default/path0000644000175000017500000000131011636712103016203 0ustar billbillFunction: _def_path Class: default Section: default C-Name: sd_path Prototype: Help: Doc: this is a list of directories, separated by colons ':' (semicolons ';' in the DOS world, since colons are preempted for drive names). When asked to read a file whose name is not given by an absolute path (does not start with \kbd{/}, \kbd{./} or \kbd{../}), \kbd{gp} will look for it in these directories, in the order they were written in \kbd{path}. Here, as usual, \kbd{.} means the current directory, and \kbd{..} its immediate parent. Environment expansion is performed. The default value is \kbd{".:\til:\til/gp"} on UNIX systems, \kbd{".;C:\bs;C:\bs GP"} on DOS, OS/2 and Windows, and \kbd{"."} otherwise. pari-2.7.5/src/functions/default/prompt_cont0000644000175000017500000000053612413013142017613 0ustar billbillFunction: _def_prompt_cont Class: gp_default Section: default C-Name: sd_prompt_cont Prototype: Help: Doc: a string that will be printed to prompt for continuation lines (e.g. in between braces, or after a line-terminating backslash). Everything that applies to \kbd{prompt} applies to \kbd{prompt\_cont} as well. The default value is \kbd{""}. pari-2.7.5/src/functions/default/debug0000644000175000017500000000041011636712103016335 0ustar billbillFunction: _def_debug Class: default Section: default C-Name: sd_debug Prototype: Help: Doc: debugging level. If it is non-zero, some extra messages may be printed, according to what is going on (see~\b{g}). The default value is \kbd{0} (no debugging messages). pari-2.7.5/src/functions/sums/0000755000175000017500000000000012613365633014704 5ustar billbillpari-2.7.5/src/functions/sums/intfouriersin0000644000175000017500000000153111636712103017517 0ustar billbillFunction: intfouriersin Section: sums C-Name: intfoursin0 Prototype: V=GGGEDGp Help: 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. Wrapper: (,,,G) Description: (gen,gen,gen,gen,?gen):gen:prec intfouriercos(${4 cookie}, ${4 wrapper}, $1, $2, $3, $5, prec) Doc: numerical integration of $\var{expr}(X)\sin(2\pi zX)$ from $a$ to $b$, in other words Fourier sine transform (from $a$ to $b$) of the function represented by \var{expr}. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfouriersin}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. pari-2.7.5/src/functions/sums/sumalt0000644000175000017500000000404511636712103016127 0ustar billbillFunction: sumalt Section: sums C-Name: sumalt0 Prototype: V=GED0,L,p Help: 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. Wrapper: (,G) 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). If $\fl=1$, use a variant with slightly different polynomials. Sometimes faster. 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 \secref{se:userfundef}.) If the series already converges geometrically, \tet{suminf} is often a better choice: \bprog ? \p28 ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 0 ms. %1 = -2.524354897 E-29 ? suminf(i = 1, -(-1)^i / i) \\@com Had to hit *** at top-level: suminf(i=1,-(-1)^i/i) *** ^------ *** suminf: user interrupt after 10min, 20,100 ms. ? \p1000 ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 90 ms. %2 = 4.459597722 E-1002 ? sumalt(i = 0, (-1)^i / i!) - exp(-1) time = 670 ms. %3 = -4.03698781490633483156497361352190615794353338591897830587 E-944 ? suminf(i = 0, (-1)^i / i!) - exp(-1) time = 110 ms. %4 = -8.39147638 E-1000 \\ @com faster and more accurate @eprog \synt{sumalt}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also available is \tet{sumalt2} with the same arguments ($\fl = 1$). pari-2.7.5/src/functions/sums/intlaplaceinv0000644000175000017500000000437411636712103017460 0ustar billbillFunction: intlaplaceinv Section: sums C-Name: intlaplaceinv0 Prototype: V=GGEDGp Help: 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. Wrapper: (,,G) Description: (gen,gen,gen,?gen):gen:prec intlaplaceinv(${3 cookie}, ${3 wrapper}, $1, $2, $4, prec) Doc: numerical integration of $(2i\pi)^{-1}\var{expr}(X)e^{Xz}$ with respect to $X$ on the line $\Re(X)=sig$. In other words, inverse Laplace transform of the function corresponding to \var{expr} at the value $z$. $sig$ is coded as follows. Either it is a real number $\sigma$, equal to the abscissa of integration, and then the integrand is assumed to be slowly decreasing when the imaginary part of the variable tends to $\pm\infty$. Or it is a two component vector $[\sigma,\alpha]$, where $\sigma$ is as before, and either $\alpha=0$ for slowly decreasing functions, or $\alpha>0$ for functions decreasing like $\exp(-\alpha t)$. Note that it is not necessary to choose the exact value of $\alpha$. \var{tab} is as in \kbd{intnum}. It is often a good idea to use this function with a value of $m$ one or two higher than the one chosen by default (which can be viewed thanks to the function \kbd{intnumstep}), or to increase the abscissa of integration $\sigma$. For example: \bprog ? \p 105 ? intlaplaceinv(x=2, 1, 1/x) - 1 time = 350 ms. %1 = 7.37... E-55 + 1.72... E-54*I \\@com not so good ? m = intnumstep() %2 = 7 ? intlaplaceinv(x=2, 1, 1/x, m+1) - 1 time = 700 ms. %3 = 3.95... E-97 + 4.76... E-98*I \\@com better ? intlaplaceinv(x=2, 1, 1/x, m+2) - 1 time = 1400 ms. %4 = 0.E-105 + 0.E-106*I \\@com perfect but slow. ? intlaplaceinv(x=5, 1, 1/x) - 1 time = 340 ms. %5 = -5.98... E-85 + 8.08... E-85*I \\@com better than \%1 ? intlaplaceinv(x=5, 1, 1/x, m+1) - 1 time = 680 ms. %6 = -1.09... E-106 + 0.E-104*I \\@com perfect, fast. ? intlaplaceinv(x=10, 1, 1/x) - 1 time = 340 ms. %7 = -4.36... E-106 + 0.E-102*I \\@com perfect, fastest, but why $sig=10$? ? intlaplaceinv(x=100, 1, 1/x) - 1 time = 330 ms. %7 = 1.07... E-72 + 3.2... E-72*I \\@com too far now... @eprog \synt{intlaplaceinv}{void *E, GEN (*eval)(void*,GEN), GEN sig,GEN z, GEN tab, long prec}. pari-2.7.5/src/functions/sums/intfuncinit0000644000175000017500000000302412314242551017147 0ustar billbillFunction: intfuncinit Section: sums C-Name: intfuncinit0 Prototype: V=GGED0,L,D0,L,p Help: 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 for coding of a and b, and m is as in intnuminit. If flag is nonzero, assumes that expr(-X)=conj(expr(X)), which is twice faster. Wrapper: (,,G) Description: (gen,gen,gen,?small,?small):gen:prec intfuncinit(${3 cookie}, ${3 wrapper}, $1, $2, $4, $5, prec) Doc: initialize tables for use with integral transforms such as \kbd{intmellininv}, etc., where $a$ and $b$ are coded as in \kbd{intnum}, $\var{expr}$ is the function $s(X)$ to which the integral transform is to be applied (which will multiply the weights of integration) and $m$ is as in \kbd{intnuminit}. If $\fl$ is nonzero, assumes that $s(-X)=\overline{s(X)}$, which makes the computation twice as fast. See \kbd{intmellininvshort} for examples of the use of this function, which is particularly useful when the function $s(X)$ is lengthy to compute, such as a gamma product. \synt{intfuncinit}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,long m, long flag, long prec}. Note that the order of $m$ and $\fl$ are reversed compared to the \kbd{GP} syntax. pari-2.7.5/src/functions/sums/prodinf0000644000175000017500000000160511636712103016262 0ustar billbillFunction: prodinf Section: sums C-Name: prodinf0 Prototype: V=GED0,L,p Help: 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. Wrapper: (,G) Description: (gen,gen,?small):gen:prec prodinf(${2 cookie}, ${2 wrapper}, $1, $3, prec) Doc: \idx{infinite product} of expression \var{expr}, the formal parameter $X$ starting at $a$. The evaluation stops when the relative error of the expression minus 1 is less than the default precision. In particular, non-convergent products result in infinite loops. The expressions must always evaluate to an element of $\C$. If $\fl=1$, do the product of the ($1+\var{expr}$) instead. \synt{prodinf}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec} ($\fl=0$), or \tet{prodinf1} with the same arguments ($\fl=1$). pari-2.7.5/src/functions/sums/intfourierexp0000644000175000017500000000161011636712103017520 0ustar billbillFunction: intfourierexp Section: sums C-Name: intfourexp0 Prototype: V=GGGEDGp Help: 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. Wrapper: (,,,G) Description: (gen,gen,gen,gen,?gen):gen:prec intfourierexp(${4 cookie}, ${4 wrapper}, $1, $2, $3, $5, prec) Doc: numerical integration of $\var{expr}(X)\exp(-2i\pi zX)$ from $a$ to $b$, in other words Fourier transform (from $a$ to $b$) of the function represented by \var{expr}. Note the minus sign. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfourierexp}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. pari-2.7.5/src/functions/sums/intmellininvshort0000644000175000017500000000403511636712103020411 0ustar billbillFunction: intmellininvshort Section: sums C-Name: intmellininvshort Prototype: GGGp Help: 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 precomputed using the command intfuncinit(t=[[-1],sig[2]],[[1],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 of $(2i\pi)^{-1}s(X)z^{-X}$ with respect to $X$ on the line $\Re(X)=sig$. In other words, inverse Mellin transform of $s(X)$ at the value $z$. Here $s(X)$ is implicitly contained in \var{tab} in \kbd{intfuncinit} format, typically \bprog tab = intfuncinit(T = [-1], [1], 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|)$ ? tab = intfuncinit(t=[-oo, 3*Pi/2],[oo, 3*Pi/2], gamma(2+I*t)^3, 1); time = 1,370 ms. ? intmellininvshort(2,4, tab) - A time = 50 ms. %4 = -1.26... - 3.25...E-109*I \\@com 50 times faster than \kbd{A} and perfect. ? tab2 = intfuncinit(t=-oo, oo, gamma(2+I*t)^3, 1); ? intmellininvshort(2,4, tab2) %6 = -1.2...E-42 - 3.2...E-109*I \\@com 63 digits lost @eprog\noindent In the computation of \var{tab}, it was not essential to include the \emph{exact} exponential decrease of $\Gamma(2+it)^3$. But as the last example shows, a rough indication \emph{must} be given, otherwise slow decrease is assumed, resulting in catastrophic loss of accuracy. pari-2.7.5/src/functions/sums/intnuminit0000644000175000017500000000362511636712103017023 0ustar billbillFunction: intnuminit Section: sums C-Name: intnuminit Prototype: GGD0,L,p Help: 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. Doc: initialize tables for integration from $a$ to $b$, where $a$ and $b$ are coded as in \kbd{intnum}. Only the 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 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. The result is technical, but in some cases it is useful to know the output. Let $x=\phi(t)$ be the change of variable which is used. \var{tab}[1] contains the integer $m$ as above, either given by the user or computed from the default precision, and can be recomputed directly using the function \kbd{intnumstep}. \var{tab}[2] and \var{tab}[3] contain respectively the abscissa and weight corresponding to $t=0$ ($\phi(0)$ and $\phi'(0)$). \var{tab}[4] and \var{tab}[5] contain the abscissas and weights corresponding to positive $t=nh$ for $1\le n\le N$ and $h=1/2^m$ ($\phi(nh)$ and $\phi'(nh)$). Finally \var{tab}[6] and \var{tab}[7] contain either the abscissas and weights corresponding to negative $t=nh$ for $-N\le n\le -1$, or may be empty (but not always) if $\phi(t)$ is an odd function (implicitly we would have $\var{tab}[6]=-\var{tab}[4]$ and $\var{tab}[7]=\var{tab}[5]$). pari-2.7.5/src/functions/sums/intcirc0000644000175000017500000000150411636712103016252 0ustar billbillFunction: intcirc Section: sums C-Name: intcirc0 Prototype: V=GGEDGp Help: 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. Wrapper: (,,G) Description: (gen,gen,gen,?gen):gen:prec intcirc(${3 cookie}, ${3 wrapper}, $1, $2, $4, prec) Doc: numerical integration of $(2i\pi)^{-1}\var{expr}$ with respect to $X$ on the circle $|X-a| = R$. In other words, when \var{expr} is a meromorphic function, sum of the residues in the corresponding disk. \var{tab} is as in \kbd{intnum}, except that if computed with \kbd{intnuminit} it should be with the endpoints \kbd{[-1, 1]}. \bprog ? \p105 ? intcirc(s=1, 0.5, zeta(s)) - 1 %1 = -2.398082982 E-104 - 7.94487211 E-107*I @eprog \synt{intcirc}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN R,GEN tab, long prec}. pari-2.7.5/src/functions/sums/sumdiv0000644000175000017500000000077712314242551016140 0ustar billbillFunction: sumdiv Section: sums C-Name: sumdivexpr Prototype: GVE Help: sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n. Doc: sum of expression \var{expr} over the positive divisors of $n$. This function is a trivial wrapper essentially equivalent to \bprog D = divisors(n); for (i = 1, #D, X = D[i]; eval(expr)) @eprog\noindent (except that \kbd{X} is lexically scoped to the \kbd{sumdiv} loop). If \var{expr} is a multiplicative function, use \tet{sumdivmult}. %\syn{NO} pari-2.7.5/src/functions/sums/suminf0000644000175000017500000000220011636712103016112 0ustar billbillFunction: suminf Section: sums C-Name: suminf0 Prototype: V=GEp Help: suminf(X=a,expr): infinite sum (X goes from a to infinity) of real or complex expression expr. Wrapper: (,G) Description: (gen,gen):gen:prec suminf(${2 cookie}, ${2 wrapper}, $1, prec) Doc: \idx{infinite sum} of expression \var{expr}, the formal parameter $X$ starting at $a$. The evaluation stops when the relative error of the expression is less than the default precision for 3 consecutive evaluations. The expressions must always evaluate to a complex number. If the series converges slowly, make sure \kbd{realprecision} is low (even 28 digits may be too much). In this case, if the series is alternating or the terms have a constant sign, \tet{sumalt} and \tet{sumpos} should be used instead. \bprog ? \p28 ? suminf(i = 1, -(-1)^i / i) \\@com Had to hit *** at top-level: suminf(i=1,-(-1)^i/i) *** ^------ *** suminf: user interrupt after 10min, 20,100 ms. ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 0 ms. %1 = -2.524354897 E-29 @eprog \synt{suminf}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec}. pari-2.7.5/src/functions/sums/sumpos0000644000175000017500000000260511636712103016150 0ustar billbillFunction: sumpos Section: sums C-Name: sumpos0 Prototype: V=GED0,L,p Help: 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. Wrapper: (,G) Description: (gen,gen,?0):gen:prec sumpos(${2 cookie}, ${2 wrapper}, $1, prec) (gen,gen,1):gen:prec sumpos2(${2 cookie}, ${2 wrapper}, $1, prec) Doc: numerical summation of the series \var{expr}, which must be a series of terms having the same sign, the formal variable $X$ starting at $a$. The algorithm used is Van Wijngaarden's trick for converting such a series into an alternating one, then we use \tet{sumalt}. For regular functions, the function \kbd{sumnum} is in general much faster once the initializations have been made using \kbd{sumnuminit}. The routine is heuristic and assumes that \var{expr} is more or less a decreasing function of $X$. In particular, the result will be completely wrong if \var{expr} is 0 too often. We do not check either that all terms 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. \synt{sumpos}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also available is \tet{sumpos2} with the same arguments ($\fl = 1$). pari-2.7.5/src/functions/sums/sumdivmult0000644000175000017500000000063512314242551017033 0ustar billbillFunction: sumdivmult Section: sums C-Name: sumdivmultexpr Prototype: GVE Help: sumdivmult(n,d,expr): sum of multiplicative function expr, d running over the divisors of n. Doc: sum of \emph{multiplicative} expression \var{expr} over the positive divisors $d$ of $n$. Assume that \var{expr} evaluates to $f(d)$ where $f$ is multiplicative: $f(1) = 1$ and $f(ab) = f(a)f(b)$ for coprime $a$ and $b$. %\syn{NO} pari-2.7.5/src/functions/sums/intnumstep0000644000175000017500000000052611636712103017030 0ustar billbillFunction: intnumstep Section: sums C-Name: intnumstep Prototype: lp Help: intnumstep(): gives the default value of m used by all intnum and sumnum routines, such that the integration step is 1/2^m. Doc: give the value of $m$ used in all the \kbd{intnum} and \kbd{sumnum} programs, hence such that the integration step is equal to $1/2^m$. pari-2.7.5/src/functions/sums/sumnum0000644000175000017500000001153111636712103016144 0ustar billbillFunction: sumnum Section: sums C-Name: sumnum0 Prototype: V=GGEDGD0,L,p Help: 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)). Wrapper: (,,G) Description: (gen,gen,gen,?gen,?small):gen:prec sumnum(${3 cookie}, ${3 wrapper}, $1, $2, $4, $5, prec) Doc: numerical summation of \var{expr}, the variable $X$ taking integer values from ceiling of $a$ to $+\infty$, where \var{expr} is assumed to be a holomorphic function $f(X)$ for $\Re(X)\ge \sigma$. The parameter $\sigma\in\R$ is coded in the argument \kbd{sig} as follows: it is either \item a real number $\sigma$. Then the function $f$ is assumed to decrease at least as $1/X^2$ at infinity, but not exponentially; \item a two-component vector $[\sigma,\alpha]$, where $\sigma$ is as before, $\alpha < -1$. The function $f$ is assumed to decrease like $X^{\alpha}$. In particular, $\alpha\le-2$ is equivalent to no $\alpha$ at all. \item a two-component vector $[\sigma,\alpha]$, where $\sigma$ is as before, $\alpha > 0$. The function $f$ is assumed to decrease like $\exp(-\alpha X)$. In this case it is essential that $\alpha$ be exactly the rate of exponential decrease, and it is usually a good idea to increase the default value of $m$ used for the integration step. In practice, if the function is exponentially decreasing \kbd{sumnum} is slower and less accurate than \kbd{sumpos} or \kbd{suminf}, so should not be used. The function uses the \tet{intnum} routines and integration on the line $\Re(s) = \sigma$. The optional argument \var{tab} is as in intnum, except it must be initialized with \kbd{sumnuminit} instead of \kbd{intnuminit}. When \var{tab} is not precomputed, \kbd{sumnum} can be slower than \kbd{sumpos}, when the latter is applicable. It is in general faster for slowly decreasing functions. Finally, if $\fl$ is nonzero, we assume that the function $f$ to be summed is of real type, i.e. satisfies $\overline{f(z)}=f(\overline{z})$, which speeds up the computation. \bprog ? \p 308 ? a = sumpos(n=1, 1/(n^3+n+1)); time = 1,410 ms. ? tab = sumnuminit(2); time = 1,620 ms. \\@com slower but done once and for all. ? b = sumnum(n=1, 2, 1/(n^3+n+1), tab); time = 460 ms. \\@com 3 times as fast as \kbd{sumpos} ? a - b %4 = -1.0... E-306 + 0.E-320*I \\@com perfect. ? sumnum(n=1, 2, 1/(n^3+n+1), tab, 1) - a; \\@com function of real type time = 240 ms. %2 = -1.0... E-306 \\@com twice as fast, no imaginary part. ? c = sumnum(n=1, 2, 1/(n^2+1), tab, 1); time = 170 ms. \\@com fast ? d = sumpos(n=1, 1 / (n^2+1)); time = 2,700 ms. \\@com slow. ? d - c time = 0 ms. %5 = 1.97... E-306 \\@com perfect. @eprog For slowly decreasing function, we must indicate singularities: \bprog ? \p 308 ? a = sumnum(n=1, 2, n^(-4/3)); time = 9,930 ms. \\@com slow because of the computation of $n^{-4/3}$. ? a - zeta(4/3) time = 110 ms. %1 = -2.42... E-107 \\@com lost 200 decimals because of singularity at $\infty$ ? b = sumnum(n=1, [2,-4/3], n^(-4/3), /*omitted*/, 1); \\@com of real type time = 12,210 ms. ? b - zeta(4/3) %3 = 1.05... E-300 \\@com better @eprog Since the \emph{complex} values of the function are used, beware of determination problems. For instance: \bprog ? \p 308 ? tab = sumnuminit([2,-3/2]); time = 1,870 ms. ? sumnum(n=1,[2,-3/2], 1/(n*sqrt(n)), tab,1) - zeta(3/2) time = 690 ms. %1 = -1.19... E-305 \\@com fast and correct ? sumnum(n=1,[2,-3/2], 1/sqrt(n^3), tab,1) - zeta(3/2) time = 730 ms. %2 = -1.55... \\@com nonsense. However ? sumnum(n=1,[2,-3/2], 1/n^(3/2), tab,1) - zeta(3/2) time = 8,990 ms. %3 = -1.19... E-305 \\@com perfect, as $1/(n*\sqrt{n})$ above but much slower @eprog For exponentially decreasing functions, \kbd{sumnum} is given for completeness, but one of \tet{suminf} or \tet{sumpos} should always be preferred. If you experiment with such functions and \kbd{sumnum} anyway, indicate the exact rate of decrease and increase $m$ by $1$ or $2$: \bprog ? suminf(n=1, 2^(-n)) - 1 time = 10 ms. %1 = -1.11... E-308 \\@com fast and perfect ? sumpos(n=1, 2^(-n)) - 1 time = 10 ms. %2 = -2.78... E-308 \\@com also fast and perfect ? sumnum(n=1,2, 2^(-n)) - 1 %3 = -1.321115060 E320 + 0.E311*I \\@com nonsense ? sumnum(n=1, [2,log(2)], 2^(-n), /*omitted*/, 1) - 1 \\@com of real type time = 5,860 ms. %4 = -1.5... E-236 \\@com slow and lost $70$ decimals ? m = intnumstep() %5 = 9 ? sumnum(n=1,[2,log(2)], 2^(-n), m+1, 1) - 1 time = 11,770 ms. %6 = -1.9... E-305 \\@com now perfect, but slow. @eprog \synt{sumnum}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN sig,GEN tab,long flag, long prec}. pari-2.7.5/src/functions/sums/intnum0000644000175000017500000002736112405547147016153 0ustar billbillFunction: intnum 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 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) Description: (gen,gen,gen,?gen):gen:prec intnum(${3 cookie}, ${3 wrapper}, $1, $2, $4, prec) Doc: numerical integration of \var{expr} on $]a,b[$ with respect to $X$. The integrand may have values belonging to a vector space over the real numbers; in particular, it can be complex-valued or vector-valued. But it is assumed that the function is regular on $]a,b[$. If the endpoints $a$ and $b$ are finite and the function is regular there, the situation is simple: \bprog ? intnum(x = 0,1, x^2) %1 = 0.3333333333333333333333333333 ? 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. \bprog ? oo = [1]; \\@com for clarity ? intnum(x = 1,+oo, 1/x^2) %2 = 1.000000000000000000000000000 @eprog\noindent In basic usage, it is assumed that the function does not decrease exponentially fast at infinity: \bprog ? intnum(x=0,+oo, exp(-x)) *** at top-level: intnum(x=0,+oo,exp(- *** ^-------------------- *** exp: exponent (expo) overflow @eprog\noindent We shall see in a moment how to avoid the last problem, after describing the last argument \var{tab}, which is both optional and technical. The routine uses weights, which are mostly independent of the function being integrated, evaluated at many sampling points. If \var{tab} is \item a positive integer $m$, we use $2^m$ sampling points, hopefully increasing accuracy. But note that the running time is roughly proportional to $2^m$. One may try consecutive values of $m$ until they give the same value up to an accepted error. If \var{tab} is omitted, the algorithm guesses a reasonable value for $m$ depending on the current precision only, which should be sufficient for regular functions. That value may be obtained from \tet{intnumstep}, and increased in case of difficulties. \item a set of integration tables as output by \tet{intnuminit}, they are used directly. This is useful if several integrations of the same type are performed (on the same kind of interval and functions, for a given accuracy), in particular for multivariate integrals, since we then skip 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$. 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 0$, we only assume the function is regular, which is the default assumption.) If a wrong singularity exponent is used, the result will lose a catastrophic number of decimals: \bprog ? intnum(x=0, 1, x^(-1/2)) \\@com assume $x^{-1/2}$ is regular at 0 %1 = 1.999999999999999999990291881 ? intnum(x=[0,-1/2], 1, x^(-1/2)) \\@com no, it's not %2 = 2.000000000000000000000000000 ? intnum(x=[0,-1/10], 1, x^(-1/2)) %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: \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$ 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(- *** ^-------------------- *** exp: exponent (expo) overflow ? intnum(x=0, [+oo, 2], exp(-2*x)) %1 = 0.5000000000000000000000000000 \\@com OK! ? intnum(x=0, [+oo, 4], exp(-2*x)) %2 = 0.4999999999999999999961990984 \\@com wrong exponent $\Rightarrow$ imprecise result ? intnum(x=0, [+oo, 20], exp(-2*x)) %2 = 0.4999524997739071283804510227 \\@com disaster @eprog \item $\alpha<-1$ assumes that the function tends to $0$ slowly, like $x^{\alpha}$. Here it is essential to give the correct $\alpha$, if possible, but on the other hand $\alpha\le -2$ is equivalent to $\alpha=0$, in other words to no $\alpha$ at all. \smallskip The last two codes are reserved for oscillating functions. Let $k > 0$ real, and $g(x)$ a non-oscillating function tending slowly to $0$ (e.g. like a negative power of $x$), then \item $\alpha=k * I$ assumes that the function behaves like $\cos(kx)g(x)$. \item $\alpha=-k* I$ assumes that the function behaves like $\sin(kx)g(x)$. \noindent Here it is critical to give the exact value of $k$. If the oscillating part is not a pure sine or cosine, one must expand it into a Fourier series, use the above codings, and sum the resulting contributions. Otherwise you will get nonsense. Note that $\cos(kx)$, and similarly $\sin(kx)$, means that very function, and not a translated version such as $\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 if the oscillations are much weaker than the exponential decrease, choose $[[\pm1],\alpha]$, otherwise choose $[[\pm1],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 choose the oscillating type of integral we perhaps obtain the best results, at the expense of having to recompute our functions for a different value of the variable $z$ giving the transform, preventing us to use a function such as \kbd{intmellininvshort}. On the other hand using the exponential type of integral, we obtain less accurate results, but we skip expensive recomputations. See \kbd{intmellininvshort} and \kbd{intfuncinit} for more explanations. \smallskip We shall now see many examples to get a feeling for what the various 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 by \var{expr} has no singularities, it may be important to define the function differently near special points. For instance, if $f(x) = 1 /(\exp(x)-1) - \exp(-x)/x$, then $\int_0^\infty f(x)\,dx=\gamma$, Euler's constant \kbd{Euler}. But \bprog ? f(x) = 1/(exp(x)-1) - exp(-x)/x ? intnum(x = 0, [oo,1], f(x)) - Euler %1 = 6.00... E-67 @eprog\noindent thus only correct to $67$ decimal digits. This is because close to $0$ the function $f$ is computed with an enormous loss of accuracy. A better solution is \bprog ? f(x) = 1/(exp(x)-1)-exp(-x)/x ? F = truncate( f(t + O(t^7)) ); \\@com expansion around t = 0 ? g(x) = if (x > 1e-18, f(x), subst(F,t,x)) \\@com note that $6 \cdot 18 > 105$ ? intnum(x = 0, [oo,1], g(x)) - Euler %2 = 0.E-106 \\@com perfect @eprog\noindent It is up to the user to determine constants such as the $10^{-18}$ and $7$ used above. \misctitle{True singularities} With true singularities the result is worse. For instance \bprog ? intnum(x = 0, 1, 1/sqrt(x)) - 2 %1 = -1.92... E-59 \\@com only $59$ correct decimals ? intnum(x = [0,-1/2], 1, 1/sqrt(x)) - 2 %2 = 0.E-105 \\@com better @eprog \misctitle{Oscillating functions} \bprog ? intnum(x = 0, oo, sin(x) / x) - Pi/2 %1 = 20.78.. \\@com nonsense ? intnum(x = 0, [oo,1], sin(x)/x) - Pi/2 %2 = 0.004.. \\@com bad ? intnum(x = 0, [oo,-I], sin(x)/x) - Pi/2 %3 = 0.E-105 \\@com perfect ? intnum(x = 0, [oo,-I], sin(2*x)/x) - Pi/2 \\@com oops, wrong $k$ %4 = 0.07... ? intnum(x = 0, [oo,-2*I], sin(2*x)/x) - Pi/2 %5 = 0.E-105 \\@com perfect ? intnum(x = 0, [oo,-I], sin(x)^3/x) - Pi/4 %6 = 0.0092... \\@com bad ? sin(x)^3 - (3*sin(x)-sin(3*x))/4 %7 = O(x^17) @eprog\noindent We may use the above linearization and compute two oscillating integrals with ``infinite endpoints'' \kbd{[oo, -I]} and \kbd{[oo, -3*I]} respectively, or notice the obvious change of variable, and reduce to the single integral ${1\over 2}\int_0^\infty \sin(x)/x\,dx$. We finish with some more complicated examples: \bprog ? intnum(x = 0, [oo,-I], (1-cos(x))/x^2) - Pi/2 %1 = -0.0004... \\@com bad ? 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) - Pi/2 %2 = -2.18... E-106 \\@com OK ? intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)) - 0.3 %3 = 5.45... E-107 \\@com OK ? intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)) - 0.3 %4 = -1.33... E-89 \\@com lost 16 decimals. Try higher $m$: ? m = intnumstep() %5 = 7 \\@com the value of $m$ actually used above. ? tab = intnuminit(0,[oo,-I], m+1); \\@com try $m$ one higher. ? intnum(x = 0, oo, sin(x)^3*exp(-x), tab) - 0.3 %6 = 5.45... E-107 \\@com OK this time. @eprog \misctitle{Warning} Like \tet{sumalt}, \kbd{intnum} often assigns a reasonable value to diverging integrals. Use these values at your own risk! For example: \bprog ? intnum(x = 0, [oo, -I], x^2*sin(x)) %1 = -2.0000000000... @eprog\noindent Note the formula $$ \int_0^\infty \sin(x)/x^s\,dx = \cos(\pi s/2) \Gamma(1-s)\;, $$ a priori valid only for $0 < \Re(s) < 2$, but the right hand side provides an analytic continuation which may be evaluated at $s = -2$\dots \misctitle{Multivariate integration} Using successive univariate integration with respect to different formal parameters, it is immediate to do naive multivariate integration. But it is important to use a suitable \kbd{intnuminit} to precompute data for the \emph{internal} integrations at least! For example, to compute the double integral on the unit disc $x^2+y^2\le1$ of the function $x^2+y^2$, we can write \bprog ? tab = intnuminit(-1,1); ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab) @eprog\noindent The first \var{tab} is essential, the second optional. Compare: \bprog ? tab = intnuminit(-1,1); time = 30 ms. ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2)); time = 54,410 ms. \\@com slow ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab); time = 7,210 ms. \\@com faster @eprog\noindent However, the \kbd{intnuminit} program is usually pessimistic when it comes to choosing the integration step $2^{-m}$. It is often possible to improve the speed by trial and error. Continuing the above example: \bprog ? test(M) = { tab = intnuminit(-1,1, M); intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2,tab), tab) - Pi/2 } ? m = intnumstep() \\@com what value of $m$ did it take? %1 = 7 ? test(m - 1) time = 1,790 ms. %2 = -2.05... E-104 \\@com $4 = 2^2$ times faster and still OK. ? test(m - 2) time = 430 ms. %3 = -1.11... E-104 \\@com $16 = 2^4$ times faster and still OK. ? test(m - 3) time = 120 ms. %3 = -7.23... E-60 \\@com $64 = 2^6$ times faster, lost $45$ decimals. @eprog \synt{intnum}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,GEN tab, long prec}, where an omitted \var{tab} is coded as \kbd{NULL}. pari-2.7.5/src/functions/sums/sumnuminit0000644000175000017500000000105711636712103017032 0ustar billbillFunction: sumnuminit Section: sums C-Name: sumnuminit Prototype: GD0,L,D1,L,p Help: 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. Doc: initialize tables for numerical summation using \kbd{sumnum} (with $\var{sgn}=1$) or \kbd{sumnumalt} (with $\var{sgn}=-1$), $sig$ is the abscissa of integration coded as in \kbd{sumnum}, and $m$ is as in \kbd{intnuminit}. pari-2.7.5/src/functions/sums/prodeuler0000644000175000017500000000076311636712103016626 0ustar billbillFunction: prodeuler Section: sums C-Name: prodeuler0 Prototype: V=GGEp Help: prodeuler(X=a,b,expr): Euler product (X runs over the primes between a and b) of real or complex expression. Doc: product of expression \var{expr}, initialized at 1. (i.e.~to a \emph{real} number equal to 1 to the current \kbd{realprecision}), the formal parameter $X$ ranging over the prime numbers between $a$ and $b$.\sidx{Euler product} \synt{prodeuler}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b, long prec}. pari-2.7.5/src/functions/sums/sumnumalt0000644000175000017500000000463711636712103016656 0ustar billbillFunction: sumnumalt Section: sums C-Name: sumnumalt0 Prototype: V=GGEDGD0,L,p Help: 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 up to twice faster. Wrapper: (,,G) Description: (gen,gen,gen,?gen,?small):gen:prec sumnumalt(${3 cookie}, ${3 wrapper}, $1, $2, $4, $5, prec) Doc: numerical summation of $(-1)^X\var{expr}(X)$, the variable $X$ taking integer values from ceiling of $a$ to $+\infty$, where \var{expr} is assumed to be a holomorphic function for $\Re(X)\ge sig$ (or $sig[1]$). \misctitle{Warning} This function uses the \kbd{intnum} routines and is orders of magnitude slower than \kbd{sumalt}. It is only given for completeness and should not be used in practice. \misctitle{Warning 2} The expression \var{expr} must \emph{not} include the $(-1)^X$ coefficient. Thus $\kbd{sumalt}(n=a,(-1)^nf(n))$ is (approximately) equal to $\kbd{sumnumalt}(n=a,sig,f(n))$. $sig$ is coded as in \kbd{sumnum}. However for slowly decreasing functions (where $sig$ is coded as $[\sigma,\alpha]$ with $\alpha<-1$), it is not really important to indicate $\alpha$. In fact, as for \kbd{sumalt}, the program will often give meaningful results (usually analytic continuations) even for divergent series. On the other hand the exponential decrease must be indicated. \var{tab} is as in \kbd{intnum}, but if used must be initialized with \kbd{sumnuminit}. If $\fl$ is nonzero, assumes that the function $f$ to be summed is of real type, i.e. satisfies $\overline{f(z)}=f(\overline{z})$, and then twice faster when \var{tab} is precomputed. \bprog ? \p 308 ? tab = sumnuminit(2, /*omitted*/, -1); \\@com abscissa $\sigma=2$, alternating sums. time = 1,620 ms. \\@com slow, but done once and for all. ? a = sumnumalt(n=1, 2, 1/(n^3+n+1), tab, 1); time = 230 ms. \\@com similar speed to \kbd{sumnum} ? b = sumalt(n=1, (-1)^n/(n^3+n+1)); time = 0 ms. \\@com infinitely faster! ? a - b time = 0 ms. %1 = -1.66... E-308 \\@com perfect @eprog \synt{sumnumalt}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN sig, GEN tab, long flag, long prec}. pari-2.7.5/src/functions/sums/intfouriercos0000644000175000017500000000153611636712103017517 0ustar billbillFunction: intfouriercos Section: sums C-Name: intfourcos0 Prototype: V=GGGEDGp Help: 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. Wrapper: (,,,G) Description: (gen,gen,gen,gen,?gen):gen:prec intfouriercos(${4 cookie}, ${4 wrapper}, $1, $2, $3, $5, prec) Doc: numerical integration of $\var{expr}(X)\cos(2\pi zX)$ from $a$ to $b$, in other words Fourier cosine transform (from $a$ to $b$) of the function represented by \var{expr}. Endpoints $a$ and $b$ are coded as in \kbd{intnum}, and are not necessarily at infinity, but if they are, oscillations (i.e. $[[\pm1],\alpha I]$) are forbidden. \synt{intfouriercos}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, GEN z, GEN tab, long prec}. pari-2.7.5/src/functions/sums/solve0000644000175000017500000000131011636712103015742 0ustar billbillFunction: solve Section: sums C-Name: zbrent0 Prototype: V=GGEp Help: solve(X=a,b,expr): real root of expression expr (X between a and b), where expr(a)*expr(b)<=0. Wrapper: (,,G) Description: (gen,gen,gen):gen:prec zbrent(${3 cookie}, ${3 wrapper}, $1, $2, prec) Doc: find a real root of expression \var{expr} between $a$ and $b$, under the condition $\var{expr}(X=a) * \var{expr}(X=b) \le 0$. (You will get an error message \kbd{roots must be bracketed in solve} if this does not hold.) This routine uses Brent's method and can fail miserably if \var{expr} is not defined in the whole of $[a,b]$ (try \kbd{solve(x=1, 2, tan(x))}). \synt{zbrent}{void *E,GEN (*eval)(void*,GEN),GEN a,GEN b,long prec}. pari-2.7.5/src/functions/sums/intmellininv0000644000175000017500000000402711636712103017332 0ustar billbillFunction: intmellininv Section: sums C-Name: intmellininv0 Prototype: V=GGEDGp Help: 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 intmellininvshort if several values must be computed. Wrapper: (,,G) Description: (gen,gen,gen,?gen):gen:prec intmellininv(${3 cookie}, ${3 wrapper}, $1, $2, $4, prec) Doc: numerical integration of $(2i\pi)^{-1}\var{expr}(X)z^{-X}$ with respect to $X$ on the line $\Re(X)=sig$, in other words, inverse Mellin transform of the function corresponding to \var{expr} at the value $z$. $sig$ is coded as follows. Either it is a real number $\sigma$, equal to the abscissa of integration, and then the integrated is assumed to decrease exponentially fast, of the order of $\exp(-t)$ when the imaginary part of the variable tends to $\pm\infty$. Or it is a two component vector $[\sigma,\alpha]$, where $\sigma$ is as before, and either $\alpha=0$ for slowly decreasing functions, or $\alpha>0$ for functions decreasing like $\exp(-\alpha t)$, such as gamma products. Note that it is not necessary to choose the exact value of $\alpha$, and that $\alpha=1$ (equivalent to $sig$ alone) is usually sufficient. \var{tab} is as in \kbd{intnum}. As all similar functions, this function is provided for the convenience of the user, who could use \kbd{intnum} directly. However it is in general better to use \kbd{intmellininvshort}. \bprog ? \p 105 ? intmellininv(s=2,4, gamma(s)^3); time = 1,190 ms. \\@com reasonable. ? \p 308 ? intmellininv(s=2,4, gamma(s)^3); time = 51,300 ms. \\@com slow because of $\Gamma(s)^3$. @eprog\noindent \synt{intmellininv}{void *E, GEN (*eval)(void*,GEN), GEN sig, GEN z, GEN tab, long prec}. pari-2.7.5/src/functions/sums/intnumromb0000644000175000017500000000532612366172547017034 0ustar billbillFunction: intnumromb Section: sums C-Name: intnumromb0 Prototype: V=GGED0,L,p Help: 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. Wrapper: (,,G) Description: (gen,gen,gen,?small):gen:prec intnumromb(${3 cookie}, ${3 wrapper}, $1, $2, $4, prec) Doc: numerical integration of \var{expr} (smooth in $]a,b[$), with respect to $X$. Suitable for low accuracy; if \var{expr} is very regular (e.g. analytic in a large region) and high accuracy is desired, try \tet{intnum} first. Set $\fl=0$ (or omit it altogether) when $a$ and $b$ are not too large, the function is smooth, and can be evaluated exactly everywhere on the interval $[a,b]$. If $\fl=1$, uses a general driver routine for doing numerical integration, making no particular assumption (slow). $\fl=2$ is tailored for being used when $a$ or $b$ are infinite. One \emph{must} have $ab>0$, and in fact if for example $b=+\infty$, then it is preferable to have $a$ as large as possible, at least $a\ge1$. If $\fl=3$, the function is allowed to be undefined (but continuous) at $a$ or $b$, for example the function $\sin(x)/x$ at $x=0$. The user should not require too much accuracy: 18 or 28 decimal digits is OK, but not much more. In addition, analytical cleanup of the integral must have been done: there must be no singularities in the interval or at the boundaries. In practice this can be accomplished with a simple change of variable. Furthermore, for improper integrals, where one or both of the limits of integration are plus or minus infinity, the function must decrease sufficiently rapidly at infinity. This can often be accomplished through integration by parts. Finally, the function to be integrated should not be very small (compared to the current precision) on the entire interval. This can of course be accomplished by just multiplying by an appropriate constant. Note that \idx{infinity} can be represented with essentially no loss of accuracy by an appropriate huge number. However beware of real underflow when dealing with rapidly decreasing functions. For example, in order to compute the $\int_0^\infty e^{-x^2}\,dx$ to 28 decimal digits, then one can set infinity equal to 10 for example, and certainly not to \kbd{1e1000}. \synt{intnumromb}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, long flag, long prec}, where $\kbd{eval}(x, E)$ returns the value of the function at $x$. You may store any additional information required by \kbd{eval} in $E$, or set it to \kbd{NULL}. pari-2.7.5/src/functions/sums/sum0000644000175000017500000000121011636712103015415 0ustar billbillFunction: sum Section: sums C-Name: somme Prototype: V=GGEDG Help: sum(X=a,b,expr,{x=0}): x plus the sum (X goes from a to b) of expression expr. Doc: sum of expression \var{expr}, initialized at $x$, the formal parameter going from $a$ to $b$. As for \kbd{prod}, the initialization parameter $x$ may be given to force the type of the operations being performed. \noindent As an extreme example, compare \bprog ? sum(i=1, 10^4, 1/i); \\@com rational number: denominator has $4345$ digits. time = 236 ms. ? sum(i=1, 5000, 1/i, 0.) time = 8 ms. %2 = 9.787606036044382264178477904 @eprog \synt{somme}{GEN a, GEN b, char *expr, GEN x}. pari-2.7.5/src/functions/sums/prod0000644000175000017500000000263011636712103015564 0ustar billbillFunction: prod Section: sums C-Name: produit Prototype: V=GGEDG Help: prod(X=a,b,expr,{x=1}): x times the product (X runs from a to b) of expression. Doc: product of expression \var{expr}, initialized at $x$, the formal parameter $X$ going from $a$ to $b$. As for \kbd{sum}, the main purpose of the initialization parameter $x$ is to force the type of the operations being performed. For example if it is set equal to the integer 1, operations will start being done exactly. If it is set equal to the real $1.$, they will be done using real numbers having the default precision. If it is set equal to the power series $1+O(X^k)$ for a certain $k$, they will be done using power series of precision at most $k$. These are the three most common initializations. \noindent As an extreme example, compare \bprog ? prod(i=1, 100, 1 - X^i); \\@com this has degree $5050$ !! time = 128 ms. ? prod(i=1, 100, 1 - X^i, 1 + O(X^101)) time = 8 ms. %2 = 1 - X - X^2 + X^5 + X^7 - X^12 - X^15 + X^22 + X^26 - X^35 - X^40 + \ X^51 + X^57 - X^70 - X^77 + X^92 + X^100 + O(X^101) @eprog\noindent Of course, in this specific case, it is faster to use \tet{eta}, which is computed using Euler's formula. \bprog ? prod(i=1, 1000, 1 - X^i, 1 + O(X^1001)); time = 589 ms. ? \ps1000 seriesprecision = 1000 significant terms ? eta(X) - % time = 8ms. %4 = O(X^1001) @eprog \synt{produit}{GEN a, GEN b, char *expr, GEN x}. pari-2.7.5/src/functions/sums/intnuminitgen0000644000175000017500000000171712366172547017532 0ustar billbillFunction: intnuminitgen Section: sums C-Name: intnuminitgen0 Prototype: VGGED0,L,D0,L,p Help: 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. Doc: 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 \fl = 1 or 2, multiply the reserved table length by $4^{\fl}$, to avoid corresponding error. \synt{intnuminitgen}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, long m, long flag, long prec} pari-2.7.5/src/functions/sums/derivnum0000644000175000017500000000177712314242551016463 0ustar billbillFunction: derivnum Section: sums C-Name: derivnum0 Prototype: V=GEp Help: derivnum(X=a,expr): numerical derivation of expr with respect to X at X = a. Wrapper: (,G) Description: (gen,gen):gen:prec derivnum(${2 cookie}, ${2 wrapper}, $1, prec) Doc: numerical derivation of \var{expr} with respect to $X$ at $X=a$. \bprog ? derivnum(x=0,sin(exp(x))) - cos(1) %1 = -1.262177448 E-29 @eprog A clumsier approach, which would not work in library mode, is \bprog ? f(x) = sin(exp(x)) ? f'(0) - cos(1) %1 = -1.262177448 E-29 @eprog When $a$ is a power series, compute \kbd{derivnum(t=a,f)} as $f'(a) = (f(a))'/a'$. \synt{derivnum}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec}. Also available is \fun{GEN}{derivfun}{void *E, GEN (*eval)(void *, GEN), GEN a, long prec}, which also allows power series for $a$. Function: _derivfun Section: programming/internals C-Name: derivfun0 Prototype: GGp Help: _derivfun(closure,[args]) numerical derivation of closure with respect to the first variable at (args). pari-2.7.5/src/functions/member_functions/0000755000175000017500000000000012613365633017254 5ustar billbillpari-2.7.5/src/functions/member_functions/fu0000644000175000017500000000034511636712103017603 0ustar billbillFunction: _.fu Help: _.fu Section: member_functions C-Name: member_fu Prototype: G Description: (bnr):void $"ray units not implemented" (bnf):gen:copy bnf_get_fu($1) (gen):gen member_fu($1) pari-2.7.5/src/functions/member_functions/j0000644000175000017500000000020411636712103017414 0ustar billbillFunction: _.j Section: member_functions C-Name: member_j Prototype: mG Help: _.j Description: (ell):gen:copy ell_get_j($1) pari-2.7.5/src/functions/member_functions/reg0000644000175000017500000000035411636712103017746 0ustar billbillFunction: _.reg Help: _.reg Section: member_functions C-Name: member_reg Prototype: mG Description: (bnr):real $"ray regulator not implemented" (bnf):real:copy bnf_get_reg($1) (gen):real:copy member_reg($1) pari-2.7.5/src/functions/member_functions/a20000644000175000017500000000021011636712103017462 0ustar billbillFunction: _.a2 Section: member_functions C-Name: member_a2 Prototype: mG Help: _.a2 Description: (ell):gen:copy ell_get_a2($1) pari-2.7.5/src/functions/member_functions/b60000644000175000017500000000021711636712103017476 0ustar billbillFunction: _.b6 Section: member_functions C-Name: member_b6 Prototype: mG Help: _.b6 Description: (ell):gen:copy ell_get_b6($1) pari-2.7.5/src/functions/member_functions/sign0000644000175000017500000000030211636712103020122 0ustar billbillFunction: _.sign Help: _.sign Section: member_functions C-Name: member_sign Prototype: mG Description: (nf):vec:copy gel($1, 2) (gen):vec:copy member_sign($1) pari-2.7.5/src/functions/member_functions/cyc0000644000175000017500000000043611636712103017750 0ustar billbillFunction: _.cyc Help: _.cyc Section: member_functions C-Name: member_cyc Prototype: mG Description: (bnr):vec:copy bnr_get_cyc($1) (bnf):vec:copy bnf_get_cyc($1) (clgp):vec:copy gel($1, 2) (gen):vec:copy member_cyc($1) pari-2.7.5/src/functions/member_functions/polabs0000644000175000017500000000014012366172547020457 0ustar billbillFunction: _.polabs Help: _.polabs Section: member_functions C-Name: member_polabs Prototype: mG pari-2.7.5/src/functions/member_functions/diff0000644000175000017500000000030711636712103020077 0ustar billbillFunction: _.diff Help: _.diff Section: member_functions C-Name: member_diff Prototype: mG Description: (nf):gen:copy nf_get_diff($1) (gen):gen:copy member_diff($1) pari-2.7.5/src/functions/member_functions/orders0000644000175000017500000000022711636712103020466 0ustar billbillFunction: _.orders Help: _.orders Section: member_functions C-Name: member_orders Prototype: mG Description: (gal):vecsmall:copy gal_get_orders($1) pari-2.7.5/src/functions/member_functions/a30000644000175000017500000000021011636712103017463 0ustar billbillFunction: _.a3 Section: member_functions C-Name: member_a3 Prototype: mG Help: _.a3 Description: (ell):gen:copy ell_get_a3($1) pari-2.7.5/src/functions/member_functions/pol0000644000175000017500000000036211636712103017762 0ustar billbillFunction: _.pol Help: _.pol Section: member_functions C-Name: member_pol Prototype: mG Description: (gal):gen:copy gal_get_pol($1) (nf):gen:copy nf_get_pol($1) (gen):gen:copy member_pol($1) pari-2.7.5/src/functions/member_functions/zkst0000644000175000017500000000021611636712103020161 0ustar billbillFunction: _.zkst Help: _.zkst Section: member_functions C-Name: member_zkst Prototype: mG Description: (bnr):gen:copy bnr_get_bid($1) pari-2.7.5/src/functions/member_functions/a10000644000175000017500000000021011636712103017461 0ustar billbillFunction: _.a1 Section: member_functions C-Name: member_a1 Prototype: mG Help: _.a1 Description: (ell):gen:copy ell_get_a1($1) pari-2.7.5/src/functions/member_functions/tate0000644000175000017500000000013211636712103020120 0ustar billbillFunction: _.tate Help: _.tate Section: member_functions C-Name: member_tate Prototype: mG pari-2.7.5/src/functions/member_functions/futu0000644000175000017500000000013211636712103020146 0ustar billbillFunction: _.futu Help: _.futu Section: member_functions C-Name: member_futu Prototype: mG pari-2.7.5/src/functions/member_functions/b20000644000175000017500000000021111636712103017464 0ustar billbillFunction: _.b2 Section: member_functions C-Name: member_b2 Prototype: mG Help: _.b2 Description: (ell):gen:copy ell_get_b2($1) pari-2.7.5/src/functions/member_functions/mod0000644000175000017500000000012711636712103017746 0ustar billbillFunction: _.mod Help: _.mod Section: member_functions C-Name: member_mod Prototype: mG pari-2.7.5/src/functions/member_functions/p0000644000175000017500000000034611636712103017431 0ustar billbillFunction: _.p Help: _.p Section: member_functions C-Name: member_p Prototype: mG Description: (gal):int:copy gal_get_p($1) (prid):int:copy pr_get_p($1) (gen):int:copy member_p($1) pari-2.7.5/src/functions/member_functions/roots0000644000175000017500000000037612314242551020342 0ustar billbillFunction: _.roots Section: member_functions C-Name: member_roots Prototype: mG Help: _.roots Description: (gal):vec:copy gal_get_roots($1) (nf):vec:copy nf_get_roots($1) (gen):vec:copy member_roots($1) pari-2.7.5/src/functions/member_functions/eta0000644000175000017500000000012711636712103017740 0ustar billbillFunction: _.eta Help: _.eta Section: member_functions C-Name: member_eta Prototype: mG pari-2.7.5/src/functions/member_functions/no0000644000175000017500000000043011636712103017600 0ustar billbillFunction: _.no Help: _.no Section: member_functions C-Name: member_no Prototype: mG Description: (bnr):int:copy bnr_get_no($1) (bnf):int:copy bnf_get_no($1) (clgp):int:copy gel($1, 1) (gen):int:copy member_no($1) pari-2.7.5/src/functions/member_functions/tufu0000644000175000017500000000013211636712103020146 0ustar billbillFunction: _.tufu Help: _.tufu Section: member_functions C-Name: member_tufu Prototype: mG pari-2.7.5/src/functions/member_functions/clgp0000644000175000017500000000041211636712103020111 0ustar billbillFunction: _.clgp Help: _.clgp Section: member_functions C-Name: member_clgp Prototype: mG Description: (bnf):clgp:copy:parens $clgp:1 (bnr):clgp:copy:parens $clgp:1 (clgp):clgp:parens $1 (gen):clgp:copy member_clgp($1) pari-2.7.5/src/functions/member_functions/a60000644000175000017500000000021111636712103017467 0ustar billbillFunction: _.a6 Section: member_functions C-Name: member_a6 Prototype: mG Help: _.a6 Description: (ell):gen:copy ell_get_a6($1) pari-2.7.5/src/functions/member_functions/r10000644000175000017500000000027511636712103017515 0ustar billbillFunction: _.r1 Section: member_functions C-Name: member_r1 Prototype: mG Help: _.r1 Description: (nf):small nf_get_r1($1) (gen):int:copy member_r1($1) pari-2.7.5/src/functions/member_functions/a40000644000175000017500000000021011636712103017464 0ustar billbillFunction: _.a4 Section: member_functions C-Name: member_a4 Prototype: mG Help: _.a4 Description: (ell):gen:copy ell_get_a4($1) pari-2.7.5/src/functions/member_functions/c60000644000175000017500000000021011636712103017470 0ustar billbillFunction: _.c6 Section: member_functions C-Name: member_c6 Prototype: mG Help: _.c6 Description: (ell):gen:copy ell_get_c6($1) pari-2.7.5/src/functions/member_functions/bnf0000644000175000017500000000033511636712103017735 0ustar billbillFunction: _.bnf Help: _.bnf Section: member_functions C-Name: member_bnf Prototype: mG Description: (bnf):bnf:parens $1 (bnr):bnf:copy:parens $bnf:1 (gen):bnf:copy member_bnf($1) pari-2.7.5/src/functions/member_functions/codiff0000644000175000017500000000014011636712103020414 0ustar billbillFunction: _.codiff Help: _.codiff Section: member_functions C-Name: member_codiff Prototype: mG pari-2.7.5/src/functions/member_functions/f0000644000175000017500000000017711636712103017421 0ustar billbillFunction: _.f Help: _.f Section: member_functions C-Name: member_f Prototype: mG Description: (prid):small pr_get_f($1) pari-2.7.5/src/functions/member_functions/e0000644000175000017500000000020011636712103017403 0ustar billbillFunction: _.e Help: _.e Section: member_functions C-Name: member_e Prototype: mG Description: (prid):small pr_get_e($1) pari-2.7.5/src/functions/member_functions/bid0000644000175000017500000000030311636712103017721 0ustar billbillFunction: _.bid Section: member_functions C-Name: member_bid Prototype: mG Help: _.bid Description: (bnr):gen:copy bnr_get_bid($1) (gen):gen:copy member_bid($1) pari-2.7.5/src/functions/member_functions/disc0000644000175000017500000000037111636712103020112 0ustar billbillFunction: _.disc Section: member_functions C-Name: member_disc Prototype: mG Help: _.disc Description: (nf):int:copy nf_get_disc($1) (ell):gen:copy ell_get_disc($1) (gen):gen:copy member_disc($1) pari-2.7.5/src/functions/member_functions/r20000644000175000017500000000027511636712103017516 0ustar billbillFunction: _.r2 Section: member_functions C-Name: member_r2 Prototype: mG Help: _.r2 Description: (nf):small nf_get_r2($1) (gen):int:copy member_r2($1) pari-2.7.5/src/functions/member_functions/zk0000644000175000017500000000025311636712103017613 0ustar billbillFunction: _.zk Help: _.zk Section: member_functions C-Name: member_zk Prototype: mG Description: (nf):vec:copy nf_get_zk($1) (gen):vec:copy member_zk($1) pari-2.7.5/src/functions/member_functions/tu0000644000175000017500000000020511636712103017614 0ustar billbillFunction: _.tu Help: _.tu Section: member_functions C-Name: member_tu Prototype: G Description: (gen):gen:copy member_tu($1) pari-2.7.5/src/functions/member_functions/area0000644000175000017500000000013212314242551020072 0ustar billbillFunction: _.area Help: _.area Section: member_functions C-Name: member_area Prototype: mG pari-2.7.5/src/functions/member_functions/t20000644000175000017500000000021611636712103017513 0ustar billbillFunction: _.t2 Help: _.t2 Section: member_functions C-Name: member_t2 Prototype: G Description: (gen):vec member_t2($1) pari-2.7.5/src/functions/member_functions/b80000644000175000017500000000021011636712103017471 0ustar billbillFunction: _.b8 Section: member_functions C-Name: member_b8 Prototype: mG Help: _.b8 Description: (ell):gen:copy ell_get_b8($1) pari-2.7.5/src/functions/member_functions/nf0000644000175000017500000000026011636712103017570 0ustar billbillFunction: _.nf Help: _.nf Section: member_functions C-Name: member_nf Prototype: mG Description: (nf):nf:parens $1 (gen):nf:copy member_nf($1) pari-2.7.5/src/functions/member_functions/gen0000644000175000017500000000050711636712103017742 0ustar billbillFunction: _.gen Help: _.gen Section: member_functions C-Name: member_gen Prototype: mG Description: (bnr):vec:copy bnr_get_gen($1) (bnf):vec:copy bnf_get_gen($1) (gal):vec:copy gal_get_gen($1) (clgp):vec:copy gel($1, 3) (prid):gen:copy pr_get_gen($1) (gen):gen:copy member_gen($1) pari-2.7.5/src/functions/member_functions/omega0000644000175000017500000000013511636712103020256 0ustar billbillFunction: _.omega Help: _.omega Section: member_functions C-Name: member_omega Prototype: mG pari-2.7.5/src/functions/member_functions/index0000644000175000017500000000031411636712103020274 0ustar billbillFunction: _.index Section: member_functions C-Name: member_index Prototype: mG Help: _.index Description: (nf):int:copy nf_get_index($1) (gen):int:copy member_index($1) pari-2.7.5/src/functions/member_functions/b40000644000175000017500000000021011636712103017465 0ustar billbillFunction: _.b4 Section: member_functions C-Name: member_b4 Prototype: mG Help: _.b4 Description: (ell):gen:copy ell_get_b4($1) pari-2.7.5/src/functions/member_functions/c40000644000175000017500000000021011636712103017466 0ustar billbillFunction: _.c4 Section: member_functions C-Name: member_c4 Prototype: mG Help: _.c4 Description: (ell):gen:copy ell_get_c4($1) pari-2.7.5/src/functions/member_functions/group0000644000175000017500000000027311636712103020325 0ustar billbillFunction: _.group Help: _.group Section: member_functions C-Name: member_group Prototype: mG Description: (gal):vec:copy gal_get_group($1) (gen):vec:copy member_group($1) pari-2.7.5/src/functions/polynomials/0000755000175000017500000000000012613365633016263 5ustar billbillpari-2.7.5/src/functions/polynomials/intformal0000644000175000017500000000256512366172547020216 0ustar billbillFunction: intformal Section: polynomials C-Name: integ Prototype: GDn Help: intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted. Doc: \idx{formal integration} of $x$ with respect to the variable $v$ (wrt. the main variable if $v$ is omitted). Since PARI cannot represent logarithmic or arctangent terms, any such term in the result will yield an error: \bprog ? intformal(x^2) %1 = 1/3*x^3 ? intformal(x^2, y) %2 = y*x^2 ? intformal(1/x) *** at top-level: intformal(1/x) *** ^-------------- *** intformal: domain error in intformal: residue(series, pole) != 0 @eprog The argument $x$ can be of any type. When $x$ is a rational function, we assume that the base ring is an integral domain of characteristic zero. By definition, the main variable of a \typ{POLMOD} is the main variable among the coefficients from its two polynomial components (representative and modulus); in other words, assuming a polmod represents an element of $R[X]/(T(X))$, the variable $X$ is a mute variable and the integral is taken with respect to the main variable used in the base ring $R$. In particular, it is meaningless to integrate with respect to the main variable of \kbd{x.mod}: \bprog ? intformal(Mod(1,x^2+1), 'x) *** intformal: incorrect priority in intformal: variable x = x @eprog pari-2.7.5/src/functions/polynomials/polchebyshev0000644000175000017500000000231212314242551020666 0ustar billbillFunction: polchebyshev Section: polynomials C-Name: polchebyshev_eval Prototype: LD1,L,DG Help: polchebyshev(n,{flag=1},{a='x}): Chebychev polynomial of the first (flag = 1) or second (flag = 2) kind, of degree n, evaluated at a. Description: (small,?1,?var):gen polchebyshev1($1,$3) (small,2,?var):gen polchebyshev2($1,$3) (small,small,?var):gen polchebyshev($1,$2,$3) Doc: returns the $n^{\text{th}}$ \idx{Chebyshev} polynomial of the first kind $T_n$ ($\fl=1$) or the second kind $U_n$ ($\fl=2$), evaluated at $a$ (\kbd{'x} by default). Both series of polynomials satisfy the 3-term relation $$ P_{n+1} = 2xP_n - P_{n-1}, $$ and are determined by the initial conditions $U_0 = T_0 = 1$, $T_1 = x$, $U_1 = 2x$. In fact $T_n' = n U_{n-1}$ and, for all complex numbers $z$, we have $T_n(\cos z) = \cos (nz)$ and $U_{n-1}(\cos z) = \sin(nz)/\sin z$. If $n \geq 0$, then these polynomials have degree $n$. For $n < 0$, $T_n$ is equal to $T_{-n}$ and $U_n$ is equal to $-U_{-2-n}$. In particular, $U_{-1} = 0$. Variant: Also available are \fun{GEN}{polchebyshev}{long n, long \fl, long v}, \fun{GEN}{polchebyshev1}{long n, long v} and \fun{GEN}{polchebyshev2}{long n, long v} for $T_n$ and $U_n$ respectively. pari-2.7.5/src/functions/polynomials/polinterpolate0000644000175000017500000000135511636712103021243 0ustar billbillFunction: polinterpolate Section: polynomials C-Name: polint Prototype: GDGDGD& Help: 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. Doc: given the data vectors $X$ and $Y$ of the same length $n$ ($X$ containing the $x$-coordinates, and $Y$ the corresponding $y$-coordinates), this function finds the \idx{interpolating polynomial} passing through these points and evaluates it at~$x$. If $Y$ is omitted, return the polynomial interpolating the $(i,X[i])$. If present, $e$ will contain an error estimate on the returned value. pari-2.7.5/src/functions/polynomials/polgraeffe0000644000175000017500000000037212314242551020311 0ustar billbillFunction: polgraeffe Section: polynomials C-Name: polgraeffe Prototype: G Help: polgraeffe(f): returns the Graeffe transform g of f, such that g(x^2) = f(x)f(-x) Doc: returns the \idx{Graeffe} transform $g$ of $f$, such that $g(x^2) = f(x) f(-x)$. pari-2.7.5/src/functions/polynomials/substpol0000644000175000017500000000211711636712103020052 0ustar billbillFunction: substpol Section: polynomials C-Name: gsubstpol Prototype: GGG Help: substpol(x,y,z): in expression x, replace the polynomial y by the expression z, using remainder decomposition of x. Doc: replace the ``variable'' $y$ by the argument $z$ in the ``polynomial'' expression $x$. Every type is allowed for $x$, but the same behavior as \kbd{subst} above apply. The difference with \kbd{subst} is that $y$ is allowed to be any polynomial here. The substitution is done moding out all components of $x$ (recursively) by $y - t$, where $t$ is a new free variable of lowest priority. Then substituting $t$ by $z$ in the resulting expression. For instance \bprog ? substpol(x^4 + x^2 + 1, x^2, y) %1 = y^2 + y + 1 ? substpol(x^4 + x^2 + 1, x^3, y) %2 = x^2 + y*x + 1 ? substpol(x^4 + x^2 + 1, (x+1)^2, y) %3 = (-4*y - 6)*x + (y^2 + 3*y - 3) @eprog Variant: Further, \fun{GEN}{gdeflate}{GEN T, long v, long d} attempts to write $T(x)$ in the form $t(x^d)$, where $x=$\kbd{pol\_x}$(v)$, and returns \kbd{NULL} if the substitution fails (for instance in the example \kbd{\%2} above). pari-2.7.5/src/functions/polynomials/pollead0000644000175000017500000000114111636712103017613 0ustar billbillFunction: pollead Section: polynomials C-Name: pollead Prototype: GDn Help: 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. Description: (pol):gen:copy leading_term($1) (gen):gen pollead($1, -1) (gen, var):gen pollead($1, $2) Doc: leading coefficient of the polynomial or power series $x$. This is computed with respect to the main variable of $x$ if $v$ is omitted, with respect to the variable $v$ otherwise. pari-2.7.5/src/functions/polynomials/factorpadic0000644000175000017500000000273212405547147020472 0ustar billbillFunction: factorpadic Section: polynomials C-Name: factorpadic0 Prototype: GGLD0,L, Help: factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r. Doc: $p$-adic factorization of the polynomial \var{pol} to precision $r$, the result being a two-column matrix as in \kbd{factor}. Note that this is not the same as a factorization over $\Z/p^r\Z$ (polynomials over that ring do not form a unique factorization domain, anyway), but approximations in $\Q/p^r\Z$ of the true factorization in $\Q_p[X]$. \bprog ? factorpadic(x^2 + 9, 3,5) %1 = [(1 + O(3^5))*x^2 + O(3^5)*x + (3^2 + O(3^5)) 1] ? factorpadic(x^2 + 1, 5,3) %2 = [ (1 + O(5^3))*x + (2 + 5 + 2*5^2 + O(5^3)) 1] [(1 + O(5^3))*x + (3 + 3*5 + 2*5^2 + O(5^3)) 1] @eprog\noindent The factors are normalized so that their leading coefficient is a power of $p$. The method used is a modified version of the \idx{round 4} algorithm of \idx{Zassenhaus}. If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence we actually factor exactly a polynomial which is only $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials with exact rational coefficients. \synt{factorpadic}{GEN f,GEN p, long r} . The function \kbd{factorpadic0} is deprecated, provided for backward compatibility. pari-2.7.5/src/functions/polynomials/diffop0000644000175000017500000000362611636712103017454 0ustar billbillFunction: diffop Section: polynomials C-Name: diffop0 Prototype: GGGD1,L, Description: (gen,gen,gen,?1):gen diffop($1, $2, $3) (gen,gen,gen,small):gen diffop0($1, $2, $3, $4) Help: 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. Doc: Let $v$ be a vector of variables, and $d$ a vector of the same length, return the image of $x$ by the $n$-power ($1$ if n is not given) of the differential operator $D$ that assumes the value \kbd{d[i]} on the variable \kbd{v[i]}. The value of $D$ on a scalar type is zero, and $D$ applies componentwise to a vector or matrix. When applied to a \typ{POLMOD}, if no value is provided for the variable of the modulus, such value is derived using the implicit function theorem. Some examples: This function can be used to differentiate formal expressions: If $E=\exp(X^2)$ then we have $E'=2*X*E$. We can derivate $X*exp(X^2)$ as follow: \bprog ? diffop(E*X,[X,E],[1,2*X*E]) %1 = (2*X^2 + 1)*E @eprog Let \kbd{Sin} and \kbd{Cos} be two function such that $\kbd{Sin}^2+\kbd{Cos}^2=1$ and $\kbd{Cos}'=-\kbd{Sin}$. We can differentiate $\kbd{Sin}/\kbd{Cos}$ as follow, PARI inferring the value of $\kbd{Sin}'$ from the equation: \bprog ? diffop(Mod('Sin/'Cos,'Sin^2+'Cos^2-1),['Cos],[-'Sin]) %1 = Mod(1/Cos^2, Sin^2 + (Cos^2 - 1)) @eprog Compute the Bell polynomials (both complete and partial) via the Faa di Bruno formula: \bprog Bell(k,n=-1)= { my(var(i)=eval(Str("X",i))); my(x,v,dv); v=vector(k,i,if(i==1,'E,var(i-1))); dv=vector(k,i,if(i==1,'X*var(1)*'E,var(i))); x=diffop('E,v,dv,k)/'E; if(n<0,subst(x,'X,1),polcoeff(x,n,'X)) } @eprog Variant: For $n=1$, the function \fun{GEN}{diffop}{GEN x, GEN v, GEN d} is also available. pari-2.7.5/src/functions/polynomials/taylor0000644000175000017500000000127611636712103017516 0ustar billbillFunction: taylor Section: polynomials C-Name: tayl Prototype: GnDP Help: taylor(x,t,{d=seriesprecision}): taylor expansion of x with respect to t, adding O(t^d) to all components of x. Doc: Taylor expansion around $0$ of $x$ with respect to the simple variable $t$. $x$ can be of any reasonable type, for example a rational function. Contrary to \tet{Ser}, which takes the valuation into account, this function adds $O(t^d)$ to all components of $x$. \bprog ? taylor(x/(1+y), y, 5) %1 = (y^4 - y^3 + y^2 - y + 1)*x + O(y^5) ? Ser(x/(1+y), y, 5) *** at top-level: Ser(x/(1+y),y,5) *** ^---------------- *** Ser: main variable must have higher priority in gtoser. @eprog pari-2.7.5/src/functions/polynomials/deriv0000644000175000017500000000152011636712103017305 0ustar billbillFunction: deriv Section: polynomials C-Name: deriv Prototype: GDn Help: deriv(x,{v}): derivative of x with respect to v, or to the main variable of x if v is omitted. Doc: derivative of $x$ with respect to the main variable if $v$ is omitted, and with respect to $v$ otherwise. The derivative of a scalar type is zero, and the derivative of a vector or matrix is done componentwise. One can use $x'$ as a shortcut if the derivative is with respect to the main variable of $x$. By definition, the main variable of a \typ{POLMOD} is the main variable among the coefficients from its two polynomial components (representative and modulus); in other words, assuming a polmod represents an element of $R[X]/(T(X))$, the variable $X$ is a mute variable and the derivative is taken with respect to the main variable used in the base ring $R$. pari-2.7.5/src/functions/polynomials/polhensellift0000644000175000017500000000215512366172547021066 0ustar billbillFunction: polhensellift Section: polynomials C-Name: polhensellift Prototype: GGGL Help: 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. Doc: given a prime $p$, an integral polynomial $A$ whose leading coefficient is a $p$-unit, a vector $B$ of integral polynomials that are monic and pairwise relatively prime modulo $p$, and whose product is congruent to $A/\text{lc}(A)$ modulo $p$, lift the elements of $B$ to polynomials whose product is congruent to $A$ modulo $p^e$. More generally, if $T$ is an integral polynomial irreducible mod $p$, and $B$ is a factorization of $A$ over the finite field $\F_p[t]/(T)$, you can lift it to $\Z_p[t]/(T, p^e)$ by replacing the $p$ argument with $[p,T]$: \bprog ? { T = t^3 - 2; p = 7; A = x^2 + t + 1; B = [x + (3*t^2 + t + 1), x + (4*t^2 + 6*t + 6)]; r = polhensellift(A, B, [p, T], 6) } %1 = [x + (20191*t^2 + 50604*t + 75783), x + (97458*t^2 + 67045*t + 41866)] ? liftall( r[1] * r[2] * Mod(Mod(1,p^6),T) ) %2 = x^2 + (t + 1) @eprog pari-2.7.5/src/functions/polynomials/O0000644000175000017500000000153711636712103016402 0ustar billbillFunction: O(_^_) Section: programming/internals C-Name: ggrando Prototype: GD1,L, Help: O(p^e): p-adic or power series zero with precision given by e. Description: (gen):gen ggrando($1, 1) (1,small):gen ggrando(gen_1, $2) (int,small):gen zeropadic($1, $2) (gen,small):gen ggrando($1, $2) (var,small):gen zeroser($1, $2) Function: O Section: polynomials C-Name: ggrando Prototype: Help: O(p^e): p-adic or power series zero with precision given by e Doc: if $p$ is an integer greater than $2$, returns a $p$-adic $0$ of precision $e$. In all other cases, returns a power series zero with precision given by $e v$, where $v$ is the $X$-adic valuation of $p$ with respect to its main variable. Variant: \fun{GEN}{zeropadic}{GEN p, long e} for a $p$-adic and \fun{GEN}{zeroser}{long v, long e} for a power series zero in variable $v$. pari-2.7.5/src/functions/polynomials/polrecip0000644000175000017500000000036011636712103020012 0ustar billbillFunction: polrecip Section: polynomials C-Name: polrecip Prototype: G Help: polrecip(pol): reciprocal polynomial of pol. Doc: reciprocal polynomial of \var{pol}, i.e.~the coefficients are in reverse order. \var{pol} must be a polynomial. pari-2.7.5/src/functions/polynomials/serreverse0000644000175000017500000000061612366172547020403 0ustar billbillFunction: serreverse Section: polynomials C-Name: serreverse Prototype: G Help: serreverse(s): reversion of the power series s. Doc: reverse power series of $s$, i.e. the series $t$ such that $t(s) = x$; $s$ must be a power series whose valuation is exactly equal to one. \bprog ? \ps 8 ? t = serreverse(tan(x)) %2 = x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + O(x^8) ? tan(t) %3 = x + O(x^8) @eprog pari-2.7.5/src/functions/polynomials/bezoutres0000644000175000017500000000030012314242551020210 0ustar billbillFunction: bezoutres Section: polynomials C-Name: polresultantext0 Prototype: GGDn Help: bezoutre(A,B,{v}): deprecated alias for polresultantext Doc: deprecated alias for \kbd{polresultantext} pari-2.7.5/src/functions/polynomials/polsubcyclo0000644000175000017500000000134512314242551020536 0ustar billbillFunction: polsubcyclo Section: polynomials C-Name: polsubcyclo Prototype: LLDn Help: 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. Doc: gives polynomials (in variable $v$) defining the sub-Abelian extensions of degree $d$ of the cyclotomic field $\Q(\zeta_n)$, where $d\mid \phi(n)$. If there is exactly one such extension the output is a polynomial, else it is a vector of polynomials, possibly empty. To get a vector in all cases, use \kbd{concat([], polsubcyclo(n,d))}. The function \tet{galoissubcyclo} allows to specify exactly which sub-Abelian extension should be computed. pari-2.7.5/src/functions/polynomials/polcoeff0000644000175000017500000000200312314242551017765 0ustar billbillFunction: polcoeff Section: polynomials C-Name: polcoeff0 Prototype: GLDn Help: 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. Description: (pol, 0):gen:copy constant_term($1) (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$ is greater than the degree, the result is zero. Naturally applies to scalars (polynomial of degree $0$), as well as to rational functions whose denominator is a monomial. It also applies to power series: if $n$ is less than the valuation, the result is zero. If it is greater than the largest significant degree, then an error message is issued. For greater flexibility, $x$ can be a vector or matrix type and the function then returns \kbd{component(x,n)}. pari-2.7.5/src/functions/polynomials/polisirreducible0000644000175000017500000000071412314242551021537 0ustar billbillFunction: polisirreducible Section: polynomials C-Name: isirreducible Prototype: lG Help: polisirreducible(pol): true(1) if pol is an irreducible non-constant polynomial, false(0) if pol is reducible or constant. Doc: \var{pol} being a polynomial (univariate in the present version \vers), returns 1 if \var{pol} is non-constant and irreducible, 0 otherwise. Irreducibility is checked over the smallest base field over which \var{pol} seems to be defined. pari-2.7.5/src/functions/polynomials/poliscycloprod0000644000175000017500000000076112314242551021246 0ustar billbillFunction: poliscycloprod Section: polynomials C-Name: poliscycloprod Prototype: lG Help: poliscycloprod(f): returns 1 if f is a product of cyclotomic polynonials, and 0 otherwise. Doc: returns 1 if $f$ is a product of cyclotomic polynomial, and $0$ otherwise. \bprog ? f = x^6+x^5-x^3+x+1; ? poliscycloprod(f) %2 = 1 ? factor(f) %3 = [ x^2 + x + 1 1] [x^4 - x^2 + 1 1] ? [ poliscyclo(T) | T <- %[,1] ] %4 = [3, 12] ? polcyclo(3) * polcyclo(12) %5 = x^6 + x^5 - x^3 + x + 1 @eprog pari-2.7.5/src/functions/polynomials/serconvol0000644000175000017500000000051511636712103020211 0ustar billbillFunction: serconvol Section: polynomials C-Name: convol Prototype: GG Help: serconvol(x,y): convolution (or Hadamard product) of two power series. Doc: convolution (or \idx{Hadamard product}) of the two power series $x$ and $y$; in other words if $x=\sum a_k*X^k$ and $y=\sum b_k*X^k$ then $\kbd{serconvol}(x,y)=\sum a_k*b_k*X^k$. pari-2.7.5/src/functions/polynomials/polrootspadic0000644000175000017500000000177012366172547021102 0ustar billbillFunction: polrootspadic Section: polynomials C-Name: rootpadic Prototype: GGL Help: polrootspadic(x,p,r): p-adic roots of the polynomial x to precision r. Doc: vector of $p$-adic roots of the polynomial \var{pol}, given to $p$-adic precision $r$ $p$ is assumed to be a prime. Multiple roots are \emph{not} repeated. Note that this is not the same as the roots in $\Z/p^r\Z$, rather it gives approximations in $\Z/p^r\Z$ of the true roots living in $\Q_p$. \bprog ? polrootspadic(x^3 - x^2 + 64, 2, 5) %1 = [2^3 + O(2^5), 2^3 + 2^4 + O(2^5), 1 + O(2^5)]~ @eprog If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence the roots given are approximations of the roots of an exact polynomial which is $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials with eact rational coefficients. pari-2.7.5/src/functions/polynomials/polresultantext0000644000175000017500000000147312314242551021457 0ustar billbillFunction: polresultantext Section: polynomials C-Name: polresultantext0 Prototype: GGDn Help: 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. Doc: finds polynomials $U$ and $V$ such that $A*U + B*V = R$, where $R$ is the resultant of $U$ and $V$ with respect to the main variables of $A$ and $B$ if $v$ is omitted, and with respect to $v$ otherwise. Returns the row vector $[U,V,R]$. The algorithm used (subresultant) assumes that the base ring is a domain. \bprog ? A = x*y; B = (x+y)^2; ? [U,V,R] = polresultantext(A, B) %2 = [-y*x - 2*y^2, y^2, y^4] ? A*U + B*V %3 = y^4 ? [U,V,R] = polresultantext(A, B, y) %4 = [-2*x^2 - y*x, x^2, x^4] ? A*U+B*V %5 = x^4 @eprog Variant: Also available is \fun{GEN}{polresultantext}{GEN x, GEN y}. pari-2.7.5/src/functions/polynomials/subst0000644000175000017500000000205611636712103017341 0ustar billbillFunction: subst Section: polynomials C-Name: gsubst Prototype: GnG Help: subst(x,y,z): in expression x, replace the variable y by the expression z. Doc: replace the simple variable $y$ by the argument $z$ in the ``polynomial'' expression $x$. Every type is allowed for $x$, but if it is not a genuine polynomial (or power series, or rational function), the substitution will be done as if the scalar components were polynomials of degree zero. In particular, beware that: \bprog ? subst(1, x, [1,2; 3,4]) %1 = [1 0] [0 1] ? subst(1, x, Mat([0,1])) *** at top-level: subst(1,x,Mat([0,1]) *** ^-------------------- *** subst: forbidden substitution by a non square matrix. @eprog\noindent If $x$ is a power series, $z$ must be either a polynomial, a power series, or a rational function. Finally, if $x$ is a vector, matrix or list, the substitution is applied to each individual entry. Use the function \kbd{substvec} to replace several variables at once, or the function \kbd{substpol} to replace a polynomial expression. pari-2.7.5/src/functions/polynomials/poltchebi0000644000175000017500000000027012314242551020145 0ustar billbillFunction: poltchebi Section: polynomials C-Name: polchebyshev1 Prototype: LDn Help: poltchebi(n,{v='x}): deprecated alias for polchebyshev Doc: deprecated alias for \kbd{polchebyshev} pari-2.7.5/src/functions/polynomials/polzagier0000644000175000017500000000131211636712103020167 0ustar billbillFunction: polzagier Section: polynomials 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. %@article {MR2001m:11222, % AUTHOR = {Cohen, Henri and Rodriguez Villegas, Fernando and Zagier, Don}, % TITLE = {Convergence acceleration of alternating series}, % JOURNAL = {Experiment. Math.}, % VOLUME = {9}, % YEAR = {2000}, % NUMBER = {1}, % PAGES = {3--12}, %} pari-2.7.5/src/functions/polynomials/polcyclofactors0000644000175000017500000000162012413013143021373 0ustar billbillFunction: polcyclofactors Section: polynomials C-Name: polcyclofactors Prototype: G Help: polcyclofactors(f): returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing f. Doc: returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing $f$. \bprog ? f = x^10+5*x^8-x^7+8*x^6-4*x^5+8*x^4-3*x^3+7*x^2+3; ? v = polcyclofactors(f) %2 = [x^2 + 1, x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] ? apply(poliscycloprod, v) %3 = [1, 1, 1] ? apply(poliscyclo, v) %4 = [4, 3, 10] @eprog\noindent In general, the polynomials are products of cyclotomic polynomials and not themselves irreducible: \bprog ? g = x^8+2*x^7+6*x^6+9*x^5+12*x^4+11*x^3+10*x^2+6*x+3; ? polcyclofactors(g) %2 = [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] ? factor(%[1]) %3 = [ x^2 + x + 1 1] [x^4 + x^3 + x^2 + x + 1 1] @eprog pari-2.7.5/src/functions/polynomials/poliscyclo0000644000175000017500000000066512314242551020364 0ustar billbillFunction: poliscyclo Section: polynomials C-Name: poliscyclo Prototype: lG Help: poliscyclo(f): returns 0 if f is not a cyclotomic polynomial, and n > 0 if f = Phi_n, the n-th cyclotomic polynomial. Doc: returns 0 if $f$ is not a cyclotomic polynomial, and $n > 0$ if $f = \Phi_n$, the $n$-th cyclotomic polynomial. \bprog ? poliscyclo(x^4-x^2+1) %1 = 12 ? polcyclo(12) %2 = x^4 - x^2 + 1 ? poliscyclo(x^4-x^2-1) %3 = 0 @eprog pari-2.7.5/src/functions/polynomials/eval0000644000175000017500000000271412314242551017130 0ustar billbillFunction: eval Section: polynomials C-Name: geval_gp Prototype: GC Help: eval(x): evaluation of x, replacing variables by their value. Description: (gen):gen geval($1) Doc: replaces in $x$ the formal variables by the values that have been assigned to them after the creation of $x$. This is mainly useful in GP, and not in library mode. Do not confuse this with substitution (see \kbd{subst}). If $x$ is a character string, \kbd{eval($x$)} executes $x$ as a GP command, as if directly input from the keyboard, and returns its output. \bprog ? x1 = "one"; x2 = "two"; ? n = 1; eval(Str("x", n)) %2 = "one" ? f = "exp"; v = 1; ? eval(Str(f, "(", v, ")")) %4 = 2.7182818284590452353602874713526624978 @eprog\noindent Note that the first construct could be implemented in a simpler way by using a vector \kbd{x = ["one","two"]; x[n]}, and the second by using a closure \kbd{f = exp; f(v)}. The final example is more interesting: \bprog ? genmat(u,v) = matrix(u,v,i,j, eval( Str("x",i,j) )); ? genmat(2,3) \\ generic 2 x 3 matrix %2 = [x11 x12 x13] [x21 x22 x23] @eprog A syntax error in the evaluation expression raises an \kbd{e\_SYNTAX} exception, which can be trapped as usual: \bprog ? 1a *** unused characters: 1a *** ^- ? E(expr) = { iferr(eval(expr), e, print("syntax error"), errname(e) == "e_SYNTAX"); } ? E("1+1") %1 = 2 ? E("1a") syntax error @eprog \synt{geval}{GEN x}. pari-2.7.5/src/functions/polynomials/polhermite0000644000175000017500000000102612141040641020336 0ustar billbillFunction: polhermite Section: polynomials C-Name: polhermite_eval Prototype: LDG Help: polhermite(n,{a='x}): Hermite polynomial H(n,v) of degree n, evaluated at a. Description: (small,?var):gen polhermite($1,$2) (small,gen):gen polhermite_eval($1,$2) Doc: $n^{\text{th}}$ \idx{Hermite} polynomial $H_n$ evaluated at $a$ (\kbd{'x} by default), i.e. $$ H_n(x) = (-1)^n\*e^{x^2} \dfrac{d^n}{dx^n}e^{-x^2}.$$ Variant: The variant \fun{GEN}{polhermite}{long n, long v} returns the $n$-th Hermite polynomial in variable $v$. pari-2.7.5/src/functions/polynomials/polrootsmod0000644000175000017500000000130212314242551020552 0ustar billbillFunction: polrootsmod Section: polynomials C-Name: rootmod0 Prototype: GGD0,L, Help: 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. Description: (pol, int, ?0):vec rootmod($1, $2) (pol, int, 1):vec rootmod2($1, $2) (pol, int, #small):vec $"Bad flag in polrootsmod" (pol, int, small):vec rootmod0($1, $2, $3) Doc: row vector of roots modulo $p$ of the polynomial \var{pol}. Multiple roots are \emph{not} repeated. \bprog ? polrootsmod(x^2-1,2) %1 = [Mod(1, 2)]~ @eprog\noindent If $p$ is very small, you may set $\fl=1$, which uses a naive search. pari-2.7.5/src/functions/polynomials/thue0000644000175000017500000000505712413013143017142 0ustar billbillFunction: thue Section: polynomials C-Name: thue Prototype: GGDG Help: 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). Doc: returns all solutions of the equation $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. 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 very wasteful if more than one value of $a$ is required. If \var{tnf} was computed without assuming GRH (flag $1$ in \tet{thueinit}), then the result is unconditional. Otherwise, it depends in principle of the truth of the GRH, but may still be unconditionally correct in some favorable cases. The result is conditional on the GRH if $a\neq \pm 1$ and, $P$ has a single irreducible rational factor, whose associated tentative class number $h$ and regulator $R$ (as computed assuming the GRH) satisfy \item $h > 1$, \item $R/0.2 > 1.5$. Here's how to solve the Thue equation $x^{13} - 5y^{13} = - 4$: \bprog ? tnf = thueinit(x^13 - 5); ? thue(tnf, -4) %1 = [[1, 1]] @eprog\noindent In this case, one checks that \kbd{bnfinit(x\pow13 -5).no} is $1$. Hence, the only solution is $(x,y) = (1,1)$, and the result is unconditional. On the other hand: \bprog ? P = x^3-2*x^2+3*x-17; tnf = thueinit(P); ? thue(tnf, -15) %2 = [[1, 1]] \\ a priori conditional on the GRH. ? K = bnfinit(P); K.no %3 = 3 ? K.reg %4 = 2.8682185139262873674706034475498755834 @eprog This time the result is conditional. All results computed using this particular \var{tnf} are likewise conditional, \emph{except} for a right-hand side of $\pm 1$. The above result is in fact correct, so we did not just disprove the GRH: \bprog ? tnf = thueinit(x^3-2*x^2+3*x-17, 1 /*unconditional*/); ? thue(tnf, -15) %4 = [[1, 1]] @eprog Note that reducible or non-monic polynomials are allowed: \bprog ? tnf = thueinit((2*x+1)^5 * (4*x^3-2*x^2+3*x-17), 1); ? thue(tnf, 128) %2 = [[-1, 0], [1, 0]] @eprog\noindent Reducible polynomials are in fact much easier to handle. pari-2.7.5/src/functions/polynomials/padicappr0000644000175000017500000000133212314242551020137 0ustar billbillFunction: padicappr Section: polynomials C-Name: padicappr Prototype: GG Help: padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p. Doc: vector of $p$-adic roots of the polynomial $pol$ congruent to the $p$-adic number $a$ modulo $p$, and with the same $p$-adic precision as $a$. The number $a$ can be an ordinary $p$-adic number (type \typ{PADIC}, i.e.~an element of $\Z_p$) or can be an integral element of a finite extension of $\Q_p$, given as a \typ{POLMOD} at least one of whose coefficients is a \typ{PADIC}. In this case, the result is the vector of roots belonging to the same extension of $\Q_p$ as $a$. Variant: Also available is \fun{GEN}{Zp_appr}{GEN f, GEN a} when $a$ is a \typ{PADIC}. pari-2.7.5/src/functions/polynomials/polroots0000644000175000017500000000137012413013143020050 0ustar billbillFunction: polroots Section: polynomials C-Name: roots Prototype: Gp Help: polroots(x): complex roots of the polynomial x using Schonhage's method, as modified by Gourdon. Doc: complex roots of the polynomial \var{x}, given as a column vector where each root is repeated according to its multiplicity. The precision is given as for transcendental functions: in GP it is kept in the variable \kbd{realprecision} and is transparent to the user, but it must be explicitly given as a second argument in library mode. The algorithm used is a modification of A.~Sch\"onhage\sidx{Sch\"onage}'s root-finding algorithm, due to and originally implemented by X.~Gourdon. Barring bugs, it is guaranteed to converge and to give the roots to the required accuracy. pari-2.7.5/src/functions/polynomials/serlaplace0000644000175000017500000000051211636712103020307 0ustar billbillFunction: serlaplace Section: polynomials C-Name: laplace 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$. pari-2.7.5/src/functions/polynomials/polsym0000644000175000017500000000043511636712103017523 0ustar billbillFunction: polsym Section: polynomials C-Name: polsym Prototype: GL Help: polsym(x,n): column vector of symmetric powers of the roots of x up to n. Doc: creates the column vector of the \idx{symmetric powers} of the roots of the polynomial $x$ up to power $n$, using Newton's formula. pari-2.7.5/src/functions/polynomials/padicfields0000644000175000017500000000346112314242551020450 0ustar billbillFunction: padicfields Section: polynomials C-Name: padicfields0 Prototype: GGD0,L, Help: 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 the number of extensions in a fixed algebraic closure. Doc: returns a vector of polynomials generating all the extensions of degree $N$ of the field $\Q_p$ of $p$-adic rational numbers; $N$ is allowed to be a 2-component vector $[n,d]$, in which case we return the extensions of degree $n$ and discriminant $p^d$. The list is minimal in the sense that two different polynomials generate non-isomorphic extensions; in particular, the number of polynomials is the number of classes of non-isomorphic extensions. If $P$ is a polynomial in this list, $\alpha$ is any root of $P$ and $K = \Q_p(\alpha)$, then $\alpha$ is the sum of a uniformizer and a (lift of a) generator of the residue field of $K$; in particular, the powers of $\alpha$ generate the ring of $p$-adic integers of $K$. If $\fl = 1$, replace each polynomial $P$ by a vector $[P, e, f, d, c]$ where $e$ is the ramification index, $f$ the residual degree, $d$ the valuation of the discriminant, and $c$ the number of conjugate fields. If $\fl = 2$, only return the \emph{number} of extensions in a fixed algebraic closure (Krasner's formula), which is much faster. Variant: Also available is \fun{GEN}{padicfields}{GEN p, long n, long d, long flag}, which computes extensions of $\Q_p$ of degree $n$ and discriminant $p^d$. pari-2.7.5/src/functions/polynomials/substvec0000644000175000017500000000122611636712103020035 0ustar billbillFunction: substvec Section: polynomials C-Name: gsubstvec Prototype: GGG Help: substvec(x,v,w): in expression x, make a best effort to replace the variables v1,...,vn by the expression w1,...,wn. Doc: $v$ being a vector of monomials of degree 1 (variables), $w$ a vector of expressions of the same length, replace in the expression $x$ all occurrences of $v_i$ by $w_i$. The substitutions are done simultaneously; more precisely, the $v_i$ are first replaced by new variables in $x$, then these are replaced by the $w_i$: \bprog ? substvec([x,y], [x,y], [y,x]) %1 = [y, x] ? substvec([x,y], [x,y], [y,x+y]) %2 = [y, x + y] \\ not [y, 2*y] @eprog pari-2.7.5/src/functions/polynomials/sumformal0000644000175000017500000000202012314242551020174 0ustar billbillFunction: sumformal Section: polynomials C-Name: sumformal Prototype: GDn Help: sumformal(f,{v}): formal sum of f with respect to v, or to the main variable of f if v is omitted. Doc: \idx{formal sum} of the polynomial expression $f$ with respect to the main variable if $v$ is omitted, with respect to the variable $v$ otherwise; it is assumed that the base ring has characteristic zero. In other words, considering $f$ as a polynomial function in the variable $v$, returns $F$, a polynomial in $v$ vanishing at $0$, such that $F(b) - F(a) = sum_{v = a+1}^b f(v)$: \bprog ? sumformal(n) \\ 1 + ... + n %1 = 1/2*n^2 + 1/2*n ? f(n) = n^3+n^2+1; ? F = sumformal(f(n)) \\ f(1) + ... + f(n) %3 = 1/4*n^4 + 5/6*n^3 + 3/4*n^2 + 7/6*n ? sum(n = 1, 2000, f(n)) == subst(F, n, 2000) %4 = 1 ? sum(n = 1001, 2000, f(n)) == subst(F, n, 2000) - subst(F, n, 1000) %5 = 1 ? sumformal(x^2 + x*y + y^2, y) %6 = y*x^2 + (1/2*y^2 + 1/2*y)*x + (1/3*y^3 + 1/2*y^2 + 1/6*y) ? x^2 * y + x * sumformal(y) + sumformal(y^2) == % %7 = 1 @eprog pari-2.7.5/src/functions/polynomials/polsturm0000644000175000017500000000101312405547147020067 0ustar billbillFunction: 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). pari-2.7.5/src/functions/polynomials/polresultant0000644000175000017500000000225012314242551020730 0ustar billbillFunction: polresultant Section: polynomials C-Name: polresultant0 Prototype: GGDnD0,L, Help: 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). Doc: resultant of the two polynomials $x$ and $y$ with exact entries, with respect to the main variables of $x$ and $y$ if $v$ is omitted, with respect to the variable $v$ otherwise. The algorithm assumes the base ring is a domain. If you also need the $u$ and $v$ such that $x*u + y*v = \text{Res}(x,y)$, use the \tet{polresultantext} function. If $\fl=0$ (default), uses the the algorithm best suited to the inputs, either the \idx{subresultant algorithm} (Lazard/Ducos variant, generic case), a modular algorithm (inputs in $\Q[X]$) or Sylvester's matrix (inexact inputs). If $\fl=1$, uses the determinant of Sylvester's matrix instead; this should always be slower than the default. pari-2.7.5/src/functions/polynomials/polcyclo0000644000175000017500000000160012366172547020034 0ustar billbillFunction: polcyclo Section: polynomials C-Name: polcyclo_eval Prototype: LDG Help: polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a. Description: (small,?var):gen polcyclo($1,$2) (small,gen):gen polcyclo_eval($1,$2) Doc: $n$-th cyclotomic polynomial, evaluated at $a$ (\kbd{'x} by default). The integer $n$ must be positive. Algorithm used: reduce to the case where $n$ is squarefree; to compute the cyclotomic polynomial, use $\Phi_{np}(x)=\Phi_n(x^p)/\Phi(x)$; to compute it evaluated, use $\Phi_n(x) = \prod_{d\mid n} (x^d-1)^{\mu(n/d)}$. In the evaluated case, the algorithm assumes that $a^d - 1$ is either $0$ or invertible, for all $d\mid n$. If this is not the case (the base ring has zero divisors), use \kbd{subst(polcyclo(n),x,a)}. Variant: The variant \fun{GEN}{polcyclo}{long n, long v} returns the $n$-th cyclotomic polynomial in variable $v$. pari-2.7.5/src/functions/polynomials/pollegendre0000644000175000017500000000071411636712103020500 0ustar billbillFunction: pollegendre Section: polynomials C-Name: pollegendre_eval Prototype: LDG Help: pollegendre(n,{a='x}): legendre polynomial of degree n evaluated at a. Description: (small,?var):gen pollegendre($1,$2) (small,gen):gen pollegendre_eval($1,$2) Doc: $n^{\text{th}}$ \idx{Legendre polynomial} evaluated at $a$ (\kbd{'x} by default). Variant: To obtain the $n$-th Legendre polynomial in variable $v$, use \fun{GEN}{pollegendre}{long n, long v}. pari-2.7.5/src/functions/polynomials/poldiscreduced0000644000175000017500000000102011636712103021160 0ustar billbillFunction: poldiscreduced Section: polynomials C-Name: reduceddiscsmith Prototype: G Help: poldiscreduced(f): vector of elementary divisors of Z[a]/f'(a)Z[a], where a is a root of the polynomial f. Doc: reduced discriminant vector of the (integral, monic) polynomial $f$. This is the vector of elementary divisors of $\Z[\alpha]/f'(\alpha)\Z[\alpha]$, where $\alpha$ is a root of the polynomial $f$. The components of the result are all positive, and their product is equal to the absolute value of the discriminant of~$f$. pari-2.7.5/src/functions/polynomials/poldegree0000644000175000017500000000143512405547147020160 0ustar billbillFunction: poldegree Section: polynomials C-Name: poldegree Prototype: lGDn 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) 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. pari-2.7.5/src/functions/polynomials/thueinit0000644000175000017500000000174012413013143020021 0ustar billbillFunction: thueinit Section: polynomials C-Name: thueinit Prototype: GD0,L,p 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. 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. pari-2.7.5/src/functions/polynomials/polsylvestermatrix0000644000175000017500000000122011636712103022171 0ustar billbillFunction: polsylvestermatrix Section: polynomials C-Name: sylvestermatrix Prototype: GG Help: 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. Doc: forms the Sylvester matrix corresponding to the two polynomials $x$ and $y$, where the coefficients of the polynomials are put in the columns of the matrix (which is the natural direction for solving equations afterwards). The use of this matrix can be essential when dealing with polynomials with inexact entries, since polynomial Euclidean division doesn't make much sense in this case. pari-2.7.5/src/functions/polynomials/poldisc0000644000175000017500000000140312605245104017630 0ustar billbillFunction: poldisc Section: polynomials C-Name: poldisc0 Prototype: GDn Help: poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main variable if v is omitted, with respect to v otherwise. Description: (gen):gen poldisc0($1, -1) (gen, var):gen poldisc0($1, $2) Doc: discriminant of the polynomial \var{pol} in the main variable if $v$ is omitted, in $v$ otherwise. Uses a modular algorithm over $\Z$ or $\Q$, and the \idx{subresultant algorithm} otherwise. \bprog ? T = x^4 + 2*x+1; ? poldisc(T) %2 = -176 ? poldisc(T^2) %3 = 0 @eprog For convenience, the function also applies to types \typ{QUAD} and \typ{QFI}/\typ{QFR}: \bprog ? z = 3*quadgen(8) + 4; ? poldisc(z) %2 = 8 ? q = Qfb(1,2,3); ? poldisc(q) %4 = -8 @eprog pari-2.7.5/src/functions/gp2c_internal/0000755000175000017500000000000012613365633016444 5ustar billbillpari-2.7.5/src/functions/gp2c_internal/_tovec0000644000175000017500000000157012443123360017637 0ustar billbillFunction: _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,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,gen,gen,gen):vec:prec mkvec5($1, $2, $3, $4, stoi(prec)) (gen,...):vec:prec mkvecn(${nbarg 1 add}, $2, stoi(prec)) pari-2.7.5/src/functions/gp2c_internal/_gerepileall0000644000175000017500000000030111636712103020775 0ustar billbillFunction: _gerepileall Class: gp2c_internal Description: (pari_sp,gen):void:parens $2 = gerepilecopy($1, $2) (pari_sp,gen,...):void gerepileall($1, ${nbarg 1 sub}, ${stdref 3 code}) pari-2.7.5/src/functions/gp2c_internal/_maxprime0000644000175000017500000000013211636712103020334 0ustar billbillFunction: _maxprime Class: gp2c_internal Description: ():small maxprime() pari-2.7.5/src/functions/gp2c_internal/_const0000644000175000017500000000073611636712103017652 0ustar billbillFunction: _const_smallreal Class: gp2c_internal Description: (0):real:prec real_0(prec) (1):real:prec real_1(prec) (-1):real:prec real_m1(prec) (small):real:prec stor($1, prec) Function: _const_quote Class: gp2c_internal Description: (str):var fetch_user_var($1) Function: _const_expr Class: gp2c_internal Description: (str):gen readseq($1) Function: _const_real Class: gp2c_internal Description: (str):real:prec strtor($1, prec) pari-2.7.5/src/functions/gp2c_internal/_cast0000644000175000017500000000560112405547147017463 0ustar billbillFunction: _type_preorder Class: gp2c_internal Help: List of chains of type preorder. Description: (empty, void, bool, small, int, mp, gen) (empty, real, mp) (empty, bptr, small) (empty, bool, lg, small) (empty, bool, small_int, small) (empty, void, negbool, bool) (empty, typ, str, genstr,gen) (empty, errtyp, str) (empty, vecsmall, gen) (empty, vec, gen) (empty, list, gen) (empty, closure, gen) (empty, error, gen) (empty, bnr, bnf, nf, vec) (empty, bnr, bnf, clgp, vec) (empty, ell, vec) (empty, prid, vec) (empty, gal, vec) (empty, var, pol, gen) Function: _cast Class: gp2c_internal Help: (type1):type2 : cast expression of type1 to type2 Description: (void):bool 0 (#negbool):bool ${1 value not} (negbool):bool !$(1) (small_int):bool (small):bool (lg):bool:parens $(1)!=1 (bptr):bool *$(1) (gen):bool !gequal0($1) (real):bool signe($1) (int):bool signe($1) (mp):bool signe($1) (pol):bool signe($1) (void):negbool 1 (#bool):negbool ${1 value not} (bool):negbool !$(1) (lg):negbool:parens $(1)==1 (bptr):negbool !*$(1) (gen):negbool gequal0($1) (int):negbool !signe($1) (real):negbool !signe($1) (mp):negbool !signe($1) (pol):negbool !signe($1) (bool):small_int (typ):small_int (small):small_int (bool):small (typ):small (small_int):small (bptr):small *$(1) (int):small itos($1) (#lg):small:parens ${1 value 1 sub} (lg):small:parens $(1)-1 (gen):small gtos($1) (void):int gen_0 (-2):int gen_m2 (-1):int gen_m1 (0):int gen_0 (1):int gen_1 (2):int gen_2 (bool):int stoi($1) (small):int stoi($1) (mp):int (gen):int (mp):real (gen):real (int):mp (real):mp (gen):mp (#bool):lg:parens ${1 1 value add} (bool):lg:parens $(1)+1 (#small):lg:parens ${1 1 value add} (small):lg:parens $(1)+1 (gen):error (gen):closure (gen):vecsmall (nf):vec (bnf):vec (bnr):vec (ell):vec (clgp):vec (prid):vec (gal):vec (gen):vec (gen):list (pol):var varn($1) (gen):var gvar($1) (var):pol pol_x($1) (gen):pol (int):gen (mp):gen (vecsmall):gen (vec):gen (list):gen (pol):gen (genstr):gen (error):gen (closure):gen (gen):genstr GENtoGENstr($1) (str):genstr strtoGENstr($1) (gen):str GENtostr_unquoted($1) (genstr):str GSTR($1) (typ):str type_name($1) (errtyp):str numerr_name($1) (#str):typ ${1 str_format} (#str):errtyp ${1 str_format} (bnf):nf bnf_get_nf($1) (gen):nf (bnr):bnf bnr_get_bnf($1) (gen):bnf (gen):bnr (bnf):clgp bnf_get_clgp($1) (bnr):clgp bnr_get_clgp($1) (gen):clgp (gen):ell (gen):gal (gen):prid pari-2.7.5/src/functions/gp2c_internal/_strtoclosure0000644000175000017500000000025311636712103021266 0ustar billbillFunction: _strtoclosure Class: gp2c_internal Description: (str):closure strtofunction($1) (str,gen,...):closure strtoclosure($1, ${nbarg 1 sub}, $3) pari-2.7.5/src/functions/gp2c_internal/_badtype0000644000175000017500000000136712366172547020172 0ustar billbillFunction: _badtype Class: gp2c_internal Help: Code to check types. If not void, will be used as if(...). Description: (int):bool:parens typ($1) != t_INT (real):bool:parens typ($1) != t_REAL (mp):negbool is_intreal_t(typ($1)) (vec):negbool is_matvec_t(typ($1)) (vecsmall):bool:parens typ($1) != t_VECSMALL (pol):bool:parens typ($1) != t_POL (*nf):void:parens $1 = checknf($1) (*bnf):void:parens $1 = checkbnf($1) (bnr):void checkbnr($1) (prid):void checkprid($1) (clgp):void checkabgrp($1) (ell):void checkell($1) (*gal):gal:parens $1 = checkgal($1) pari-2.7.5/src/functions/gp2c_internal/_avma0000644000175000017500000000012211636712103017435 0ustar billbillFunction: _avma Class: gp2c_internal Description: ():pari_sp avma pari-2.7.5/src/functions/gp2c_internal/_typedef0000644000175000017500000000407412405547147020174 0ustar billbillFunction: _decl_base Class: gp2c_internal Description: (C!void) void (C!long) long (C!int) int (C!GEN) GEN (C!char*) char (C!byteptr) byteptr (C!pari_sp) pari_sp (C!func_GG) GEN (C!forprime_t) forprime_t (C!forcomposite_t) forcomposite_t (C!forpart_t) forpart_t (C!forvec_t) forvec_t Function: _decl_ext Class: gp2c_internal Description: (C!char*) *$1 (C!func_GG) (*$1)(GEN, GEN) Function: _typedef Class: gp2c_internal Description: (empty) void (void) void (negbool) long (bool) long (small_int) int (small) long (int) GEN (real) GEN (mp) GEN (lg) long (vecsmall) GEN (vec) GEN (list) GEN (var) long (pol) GEN (gen) GEN (closure) GEN (error) GEN (genstr) GEN (str) char* (bptr) byteptr (forcomposite) forcomposite_t (forpart) forpart_t (forprime) forprime_t (forvec) forvec_t (func_GG) func_GG (pari_sp) pari_sp (typ) long (errtyp) long (nf) GEN (bnf) GEN (bnr) GEN (ell) GEN (clgp) GEN (prid) GEN (gal) GEN Function: _proto_ret Class: gp2c_internal Help: Code for return value of functions Description: (C!void) v (C!int) i (C!long) l (C!GEN) Function: _proto_max_args Class: gp2c_internal Help: Max number of arguments supported by install. Description: (20) Function: _proto_code Class: gp2c_internal Help: Code for argument of a function Description: (var) n (C!long) L (C!GEN) G (C!char*) s Function: _default_marker Class: gp2c_internal Help: Code for default value of GP function Description: (C!GEN) NULL (var) -1 (small) 0 (str) "" Function: _default_check Class: gp2c_internal Help: Code to check for the default marker Description: (C!GEN):bool !$(1) (var):bool $(1) == -1 pari-2.7.5/src/functions/gp2c_internal/_gerepileupto0000644000175000017500000000053011636712103021220 0ustar billbillFunction: _gerepileupto Class: gp2c_internal Description: (pari_sp, int):int gerepileuptoint($1, $2) (pari_sp, mp):mp gerepileuptoleaf($1, $2) (pari_sp, vecsmall):vecsmall gerepileuptoleaf($1, $2) (pari_sp, vec):vec gerepileupto($1, $2) (pari_sp, gen):gen gerepileupto($1, $2) pari-2.7.5/src/functions/gp2c_internal/_formatcode0000644000175000017500000000036411636712103020644 0ustar billbillFunction: _formatcode Class: gp2c_internal Description: (#small):void $1 (small):small %ld (#str):void $%1 (str):str %s (gen):gen %Ps pari-2.7.5/src/functions/gp2c_internal/_cgetg0000644000175000017500000000024011636712103017603 0ustar billbillFunction: _cgetg Class: gp2c_internal Description: (lg,#str):gen cgetg($1, ${2 str_raw}) (gen,lg,#str):gen $1 = cgetg($2, ${3 str_raw}) pari-2.7.5/src/functions/gp2c_internal/_stack_lim0000644000175000017500000000034311636712103020464 0ustar billbillFunction: _stack_lim Class: gp2c_internal Description: (pari_sp,small):pari_sp stack_lim($1, $2) Function: _low_stack_lim Class: gp2c_internal Description: (pari_sp,pari_sp):bool low_stack($1, stack_lim($2, 1)) pari-2.7.5/src/functions/gp2c_internal/_wrap0000644000175000017500000000047011636712103017470 0ustar billbillFunction: _wrap_G Class: gp2c_internal C-Name: gp_call Prototype: G Description: (gen):gen $1 Function: _wrap_vG Class: gp2c_internal C-Name: gp_callvoid Prototype: lG Description: (void):small 0 Function: _wrap_bG Class: gp2c_internal C-Name: gp_callbool Prototype: lG Description: (bool):bool $1 pari-2.7.5/src/functions/linear_algebra/0000755000175000017500000000000012613365633016644 5ustar billbillpari-2.7.5/src/functions/linear_algebra/vecsum0000644000175000017500000000027512366172547020102 0ustar billbillFunction: 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$ pari-2.7.5/src/functions/linear_algebra/matsolvemod0000644000175000017500000000264211636712103021115 0ustar billbillFunction: matsolvemod Section: linear_algebra C-Name: matsolvemod0 Prototype: GGGD0,L, Help: 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. Doc: $M$ being any integral matrix, $D$ a column vector of non-negative integer moduli, and $B$ an integral column vector, gives a small integer solution to the system of congruences $\sum_i m_{i,j}x_j\equiv b_i\pmod{d_i}$ if one exists, otherwise returns zero. Shorthand notation: $B$ (resp.~$D$) can be given as a single integer, in which case all the $b_i$ (resp.~$d_i$) above are taken to be equal to $B$ (resp.~$D$). \bprog ? M = [1,2;3,4]; ? matsolvemod(M, [3,4]~, [1,2]~) %2 = [-2, 0]~ ? matsolvemod(M, 3, 1) \\ M X = [1,1]~ over F_3 %3 = [-1, 1]~ ? matsolvemod(M, [3,0]~, [1,2]~) \\ x + 2y = 1 (mod 3), 3x + 4y = 2 (in Z) %4 = [6, -4]~ @eprog If $\fl=1$, all solutions are returned in the form of a two-component row vector $[x,u]$, where $x$ is a small integer solution to the system of congruences and $u$ is a matrix whose columns give a basis of the homogeneous system (so that all solutions can be obtained by adding $x$ to any linear combination of columns of $u$). If no solution exists, returns zero. Variant: Also available are \fun{GEN}{gaussmodulo}{GEN M, GEN D, GEN B} ($\fl=0$) and \fun{GEN}{gaussmodulo2}{GEN M, GEN D, GEN B} ($\fl=1$). pari-2.7.5/src/functions/linear_algebra/algdep0000644000175000017500000000447112314242551020020 0ustar billbillFunction: algdep Section: linear_algebra C-Name: algdep0 Prototype: GLD0,L, Help: algdep(x,k,{flag=0}): algebraic relations up to degree n of x, using lindep([1,x,...,x^(k-1)], flag). Doc: \sidx{algebraic dependence} $x$ being real/complex, or $p$-adic, finds a polynomial of degree at most $k$ with integer coefficients having $x$ as approximate root. Note that the polynomial which is obtained is not necessarily the ``correct'' one. In fact it is not even guaranteed to be irreducible. One can check the closeness either by a polynomial evaluation (use \tet{subst}), or by computing the roots of the polynomial given by \kbd{algdep} (use \tet{polroots}). Internally, \tet{lindep}$([1,x,\ldots,x^k], \fl)$ is used. A non-zero value of $\fl$ may improve on the default behavior if the input number is known to a \emph{huge} accuracy, and you suspect the last bits are incorrect (this truncates the number, throwing away the least significant bits), but default values are usually sufficient: \bprog ? \p200 ? algdep(2^(1/6)+3^(1/5), 30); \\ wrong in 0.8s ? algdep(2^(1/6)+3^(1/5), 30, 100); \\ wrong in 0.4s ? algdep(2^(1/6)+3^(1/5), 30, 170); \\ right in 0.8s ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ wrong in 1.0s ? \p250 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 1.0s ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ right in 1.0s ? \p500 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 2.9s ? \p1000 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 10.6s @eprog\noindent The changes in \kbd{defaultprecision} only affect the quality of the initial approximation to $2^{1/6} + 3^{1/5}$, \kbd{algdep} itself uses exact operations (the size of its operands depend on the accuracy of the input of course: more accurate input means slower operations). Proceeding by increments of 5 digits of accuracy, \kbd{algdep} with default flag produces its first correct result at 205 digits, and from then on a steady stream of correct results. The above example is the test case studied in a 2000 paper by Borwein and Lisonek: Applications of integer relation algorithms, \emph{Discrete Math.}, {\bf 217}, p.~65--82. The version of PARI tested there was 1.39, which succeeded reliably from precision 265 on, in about 200 as much time as the current version. Variant: Also available is \fun{GEN}{algdep}{GEN x, long k} ($\fl=0$). pari-2.7.5/src/functions/linear_algebra/lindep0000644000175000017500000000447712413013143020036 0ustar billbillFunction: lindep Section: linear_algebra C-Name: lindep0 Prototype: GD0,L, Help: 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. Doc: \sidx{linear dependence} finds a small non-trivial integral linear combination between components of $v$. If none can be found return an empty vector. If $v$ is a vector with real/complex entries we use a floating point (variable precision) LLL algorithm. If $\fl = 0$ the accuracy is chosen internally using a crude heuristic. If $\fl > 0$ the computation is done with an accuracy of $\fl$ decimal digits. To get meaningful results in the latter case, the parameter $\fl$ should be smaller than the number of correct decimal digits in the input. \bprog ? lindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)]) %1 = [-1, -1, 1]~ @eprog If $v$ is $p$-adic, $\fl$ is ignored and the algorithm LLL-reduces a suitable (dual) lattice. \bprog ? lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)]) %2 = [1, -2]~ @eprog If $v$ is a matrix, $\fl$ is ignored and the function returns a non trivial kernel vector (combination of the columns). \bprog ? lindep([1,2,3;4,5,6;7,8,9]) %3 = [1, -2, 1]~ @eprog If $v$ contains polynomials or power series over some base field, finds a linear relation with coefficients in the field. \bprog ? lindep([x*y, x^2 + y, x^2*y + x*y^2, 1]) %4 = [y, y, -1, -y^2]~ @eprog\noindent For better control, it is preferable to use \typ{POL} rather than \typ{SER} in the input, otherwise one gets a linear combination which is $t$-adically small, but not necessarily $0$. Indeed, power series are first converted to the minimal absolute accuracy occurring among the entries of $v$ (which can cause some coefficients to be ignored), then truncated to polynomials: \bprog ? v = [t^2+O(t^4), 1+O(t^2)]; L=lindep(v) %1 = [1, 0]~ ? v*L %2 = t^2+O(t^4) \\ small but not 0 @eprog Variant: Also available are \fun{GEN}{lindep}{GEN v} (real/complex entries, $\fl=0$), \fun{GEN}{lindep2}{GEN v, long flag} (real/complex entries) \fun{GEN}{padic_lindep}{GEN v} ($p$-adic entries) and \fun{GEN}{Xadic_lindep}{GEN v} (polynomial entries). Finally \fun{GEN}{deplin}{GEN v} returns a non-zero kernel vector for a \typ{MAT} input. pari-2.7.5/src/functions/linear_algebra/vecsearch0000644000175000017500000000276712314242551020535 0ustar billbillFunction: vecsearch Section: linear_algebra C-Name: vecsearch Prototype: lGGDG Help: 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). Doc: determines whether $x$ belongs to the sorted vector or list $v$: return 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). 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 encode comparison functions. \bprog ? v = [1,3,4,5,7]; ? vecsearch(v, 3) %2 = 2 ? vecsearch(v, 6) %3 = 0 \\ not in the list ? vecsearch([7,6,5], 5) \\ unsorted vector: result undefined %4 = 0 @eprog By abuse of notation, $x$ is also allowed to be a matrix, seen as a vector of its columns; again by abuse of notation, a \typ{VEC} is considered as part of the matrix, if its transpose is one of the matrix columns. \bprog ? v = vecsort([3,0,2; 1,0,2]) \\ sort matrix columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsearch(v, [3,1]~) %2 = 3 ? vecsearch(v, [3,1]) \\ can search for x or x~ %3 = 3 ? vecsearch(v, [1,2]) %4 = 0 \\ not in the list @eprog\noindent pari-2.7.5/src/functions/linear_algebra/mathnfmod0000644000175000017500000000143211636712103020534 0ustar billbillFunction: mathnfmod Section: linear_algebra C-Name: hnfmod Prototype: GG Help: 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. Doc: if $x$ is a (not necessarily square) matrix of maximal rank with integer entries, and $d$ is a multiple of the (non-zero) determinant of the lattice spanned by the columns of $x$, finds the \emph{upper triangular} \idx{Hermite normal form} of $x$. If the rank of $x$ is equal to its number of rows, the result is a square matrix. In general, the columns of the result form a basis of the lattice spanned by the columns of $x$. Even when $d$ is known, this is in general slower than \kbd{mathnf} but uses much less memory. pari-2.7.5/src/functions/linear_algebra/setsearch0000644000175000017500000000320712366172547020557 0ustar billbillFunction: setsearch Section: linear_algebra C-Name: setsearch Prototype: lGGD0,L, Help: 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. Doc: determines whether $x$ belongs to the set $S$ (see \kbd{setisset}). We first describe the default behaviour, when $\fl$ is zero or omitted. If $x$ belongs to the set $S$, returns the index $j$ such that $S[j]=x$, otherwise returns 0. \bprog ? T = [7,2,3,5]; S = Set(T); ? setsearch(S, 2) %2 = 1 ? setsearch(S, 4) \\ not found %3 = 0 ? setsearch(T, 7) \\ search in a randomly sorted vector %4 = 0 \\ WRONG ! @eprog\noindent If $S$ is not a set, we also allow sorted lists with respect to the \tet{cmp} sorting function, without repeated entries, as per \tet{listsort}$(L,1)$; otherwise the result is undefined. \bprog ? L = List([1,4,2,3,2]); setsearch(L, 4) %1 = 0 \\ WRONG ! ? listsort(L, 1); L \\ sort L first %2 = List([1, 2, 3, 4]) ? setsearch(L, 4) %3 = 4 \\ now correct @eprog\noindent If $\fl$ is non-zero, this function returns the index $j$ where $x$ should be inserted, and $0$ if it already belongs to $S$. This is meant to be used for dynamically growing (sorted) lists, in conjunction with \kbd{listinsert}. \bprog ? L = List([1,5,2,3,2]); listsort(L,1); L %1 = List([1,2,3,5]) ? j = setsearch(L, 4, 1) \\ 4 should have been inserted at index j %2 = 4 ? listinsert(L, 4, j); L %3 = List([1, 2, 3, 4, 5]) @eprog pari-2.7.5/src/functions/linear_algebra/qfauto0000644000175000017500000000201612413013143020045 0ustar billbillFunction: qfauto Section: linear_algebra C-Name: qfauto0 Prototype: GDG Help: qfauto(G,{fl}): automorphism group of the positive definite quadratic form G. Doc: $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the automorphism group of the associate lattice. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. $G$ can also be given by an \kbd{qfisominit} structure. See \kbd{qfisominit} for the meaning of \var{fl}. The output is a two-components vector $[o,g]$ where $o$ is the group order and $g$ is the list of generators (as a vector). For each generator $H$, the equality $G={^t}H\*G\*H$ holds. The interface of this function is experimental and will likely change in the future. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. Variant: Also available is \fun{GEN}{qfauto}{GEN G, GEN fl} where $G$ is a vector of \kbd{zm}. pari-2.7.5/src/functions/linear_algebra/setminus0000644000175000017500000000055612314242551020433 0ustar billbillFunction: setminus Section: linear_algebra C-Name: setminus Prototype: GG Help: setminus(x,y): set of elements of x not belonging to y. Description: (vec, vec):vec setminus($1, $2) Doc: difference of the two sets $x$ and $y$ (see \kbd{setisset}), i.e.~set of elements of $x$ which do not belong to $y$. If $x$ or $y$ is not a set, the result is undefined. pari-2.7.5/src/functions/linear_algebra/minpoly0000644000175000017500000000046612314242551020253 0ustar billbillFunction: minpoly Section: linear_algebra C-Name: minpoly Prototype: GDn Help: minpoly(A,{v='x}): minimal polynomial of the matrix or polmod A. Doc: \idx{minimal polynomial} of $A$ with respect to the variable $v$., i.e. the monic polynomial $P$ of minimal degree (in the variable $v$) such that $P(A) = 0$. pari-2.7.5/src/functions/linear_algebra/matdiagonal0000644000175000017500000000112212314242551021032 0ustar billbillFunction: matdiagonal Section: linear_algebra C-Name: diagonal Prototype: G Help: matdiagonal(x): creates the diagonal matrix whose diagonal entries are the entries of the vector x. Doc: $x$ being a vector, creates the diagonal matrix whose diagonal entries are those of $x$. \bprog ? matdiagonal([1,2,3]); %1 = [1 0 0] [0 2 0] [0 0 3] @eprog\noindent Block diagonal matrices are easily created using \tet{matconcat}: \bprog ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9]; ? matconcat(matdiagonal([U, V])) %1 = [1 2 0 0 0] [3 4 0 0 0] [0 0 1 2 3] [0 0 4 5 6] [0 0 7 8 9] @eprog pari-2.7.5/src/functions/linear_algebra/matid0000644000175000017500000000030411636712103017652 0ustar billbillFunction: matid Section: linear_algebra C-Name: matid Prototype: L Help: matid(n): identity matrix of order n. Description: (small):vec matid($1) Doc: creates the $n\times n$ identity matrix. pari-2.7.5/src/functions/linear_algebra/forqfvec0000644000175000017500000000162012314242551020370 0ustar billbillFunction: forqfvec Section: linear_algebra C-Name: forqfvec0 Prototype: vVGDGI Help: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. Doc: $q$ being a square and symmetric matrix representing a positive definite quadratic form, evaluate \kbd{expr} for all vector $v$ such that $q(v)\leq b$. The formal variable $v$ runs through all such vectors in turn. \bprog ? forqfvec(v, [3,2;2,3], 3, print(v)) [0, 1]~ [1, 0]~ [-1, 1]~ @eprog Variant: The following function is also available: \fun{void}{forqfvec}{void *E, long (*fun)(void *, GEN, double), GEN q, GEN b}: Evaluate \kbd{fun(E,v,m)} on all $v$ such that $q(v) [2, 3, 4] v = vector(n); for (i = 1, n, v[i] = i++) ----> [2, 0, 4] @eprog\noindent %\syn{NO} pari-2.7.5/src/functions/linear_algebra/matsize0000644000175000017500000000053511636712103020236 0ustar billbillFunction: matsize Section: linear_algebra C-Name: matsize Prototype: G Help: matsize(x): number of rows and columns of the vector/matrix x as a 2-vector. Doc: $x$ being a vector or matrix, returns a row vector with two components, the first being the number of rows (1 for a row vector), the second the number of columns (1 for a column vector). pari-2.7.5/src/functions/linear_algebra/matdet0000644000175000017500000000224012314242551020032 0ustar billbillFunction: matdet Section: linear_algebra C-Name: det0 Prototype: GD0,L, Help: 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). Description: (gen, ?0):gen det($1) (gen, 1):gen det2($1) (gen, #small):gen $"incorrect flag in matdet" (gen, small):gen det0($1, $2) Doc: determinant of the square matrix $x$. If $\fl=0$, uses an appropriate algorithm depending on the coefficients: \item integer entries: modular method due to Dixon, Pernet and Stein. \item real or $p$-adic entries: classical Gaussian elimination using maximal pivot. \item intmod entries: classical Gaussian elimination using first non-zero pivot. \item other cases: Gauss-Bareiss. If $\fl=1$, uses classical Gaussian elimination with appropriate pivoting strategy (maximal pivot for real or $p$-adic coefficients). This is usually worse than the default. Variant: Also available are \fun{GEN}{det}{GEN x} ($\fl=0$), \fun{GEN}{det2}{GEN x} ($\fl=1$) and \fun{GEN}{ZM_det}{GEN x} for integer entries. pari-2.7.5/src/functions/linear_algebra/matimagecompl0000644000175000017500000000104712314242551021377 0ustar billbillFunction: matimagecompl Section: linear_algebra C-Name: imagecompl Prototype: G Description: (gen):vecsmall imagecompl($1) Help: matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage. Doc: gives the vector of the column indices which are not extracted by the function \kbd{matimage}, as a permutation (\typ{VECSMALL}). Hence the number of components of \kbd{matimagecompl(x)} plus the number of columns of \kbd{matimage(x)} is equal to the number of columns of the matrix $x$. pari-2.7.5/src/functions/linear_algebra/matcompanion0000644000175000017500000000031212314242551021237 0ustar billbillFunction: matcompanion Section: linear_algebra C-Name: matcompanion Prototype: G Help: matcompanion(x): companion matrix to polynomial x. Doc: the left companion matrix to the non-zero polynomial $x$. pari-2.7.5/src/functions/linear_algebra/matimage0000644000175000017500000000131412314242551020341 0ustar billbillFunction: matimage Section: linear_algebra C-Name: matimage0 Prototype: GD0,L, Help: 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. Description: (gen, ?0):vec image($1) (gen, 1):vec image2($1) (gen, #small) $"incorrect flag in matimage" (gen, small):vec matimage0($1, $2) Doc: gives a basis for the image of the matrix $x$ as columns of a matrix. A priori the matrix can have entries of any type. If $\fl=0$, use standard Gauss pivot. If $\fl=1$, use \kbd{matsupplement} (much slower: keep the default flag!). Variant: Also available is \fun{GEN}{image}{GEN x} ($\fl=0$). pari-2.7.5/src/functions/linear_algebra/mattranspose0000644000175000017500000000031711636712103021300 0ustar billbillFunction: mattranspose Section: linear_algebra C-Name: gtrans Prototype: G Help: mattranspose(x): x~ = transpose of x. Doc: transpose of $x$ (also $x\til$). This has an effect only on vectors and matrices. pari-2.7.5/src/functions/linear_algebra/vecsort0000644000175000017500000001022612314242551020244 0ustar billbillFunction: vecsort Section: linear_algebra C-Name: vecsort0 Prototype: GDGD0,L, Help: 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. Description: (vecsmall,?gen):vecsmall vecsort0($1, $2, 0) (vecsmall,?gen,small):vecsmall vecsort0($1, $2, $3) (vec, , ?0):vec sort($1) (vec, , 1):vecsmall indexsort($1) (vec, , 2):vec lexsort($1) (vec, gen):vec vecsort0($1, $2, 0) (vec, ?gen, 1):vecsmall vecsort0($1, $2, 1) (vec, ?gen, 3):vecsmall vecsort0($1, $2, 3) (vec, ?gen, 5):vecsmall vecsort0($1, $2, 5) (vec, ?gen, 7):vecsmall vecsort0($1, $2, 7) (vec, ?gen, 9):vecsmall vecsort0($1, $2, 9) (vec, ?gen, 11):vecsmall vecsort0($1, $2, 11) (vec, ?gen, 13):vecsmall vecsort0($1, $2, 13) (vec, ?gen, 15):vecsmall vecsort0($1, $2, 15) (vec, ?gen, #small):vec vecsort0($1, $2, $3) (vec, ?gen, small):gen vecsort0($1, $2, $3) Doc: sorts the vector $x$ in ascending order, using a mergesort method. $x$ must be a list, vector or matrix (seen as a vector of its columns). Note that mergesort is stable, hence the initial ordering of ``equal'' entries (with respect to the sorting criterion) is not changed. If \kbd{cmpf} is omitted, we use the standard comparison function \kbd{lex}, thereby restricting the possible types for the elements of $x$ (integers, fractions or reals and vectors of those). If \kbd{cmpf} is present, it is understood as a comparison function and we sort according to it. The following possibilities exist: \item an integer $k$: sort according to the value of the $k$-th subcomponents of the components of~$x$. \item a vector: sort lexicographically according to the components listed in the vector. For example, if $\kbd{cmpf}=\kbd{[2,1,3]}$, sort with respect to the second component, and when these are equal, with respect to the first, and when these are equal, with respect to the third. \item a comparison function (\typ{CLOSURE}), with two arguments $x$ and $y$, and returning an integer which is $<0$, $>0$ or $=0$ if $xy$ or $x=y$ respectively. The \tet{sign} function is very useful in this context: \bprog ? vecsort([3,0,2; 1,0,2]) \\ sort columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsort(v, (x,y)->sign(y-x)) \\@com reverse sort ? vecsort(v, (x,y)->sign(abs(x)-abs(y))) \\@com sort by increasing absolute value ? cmpf(x,y) = my(dx = poldisc(x), dy = poldisc(y)); sign(abs(dx) - abs(dy)) ? vecsort([x^2+1, x^3-2, x^4+5*x+1], cmpf) @eprog\noindent The last example used the named \kbd{cmpf} instead of an anonymous function, and sorts polynomials with respect to the absolute value of their discriminant. A more efficient approach would use precomputations to ensure a given discriminant is computed only once: \bprog ? DISC = vector(#v, i, abs(poldisc(v[i]))); ? perm = vecsort(vector(#v,i,i), (x,y)->sign(DISC[x]-DISC[y])) ? vecextract(v, perm) @eprog\noindent Similar ideas apply whenever we sort according to the values of a function which is expensive to compute. \noindent The binary digits of \fl\ mean: \item 1: indirect sorting of the vector $x$, i.e.~if $x$ is an $n$-component vector, returns a permutation of $[1,2,\dots,n]$ which applied to the components of $x$ sorts $x$ in increasing order. For example, \kbd{vecextract(x, vecsort(x,,1))} is equivalent to \kbd{vecsort(x)}. \item 4: use descending instead of ascending order. \item 8: remove ``duplicate'' entries with respect to the sorting function (keep the first occurring entry). For example: \bprog ? vecsort([Pi,Mod(1,2),z], (x,y)->0, 8) \\@com make everything compare equal %1 = [3.141592653589793238462643383] ? vecsort([[2,3],[0,1],[0,3]], 2, 8) %2 = [[0, 1], [2, 3]] @eprog pari-2.7.5/src/functions/linear_algebra/listpop0000644000175000017500000000101612314242551020246 0ustar billbillFunction: listpop Section: linear_algebra C-Name: listpop Prototype: vWD0,L, Help: listpop(list,{n}): removes n-th element from list. If n is omitted or greater than the current list length, removes last element. Description: (list, small):void listpop($1, $2) Doc: removes the $n$-th element of the list \var{list} (which must be of type \typ{LIST}). If $n$ is omitted, or greater than the list current length, removes the last element. If the list is already empty, do nothing. This runs in time $O(\#L - n + 1)$. pari-2.7.5/src/functions/linear_algebra/matsnf0000644000175000017500000000304611636712103020052 0ustar billbillFunction: matsnf Section: linear_algebra C-Name: matsnf0 Prototype: GD0,L, Help: 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. Doc: if $X$ is a (singular or non-singular) matrix outputs the vector of \idx{elementary divisors} of $X$, i.e.~the diagonal of the \idx{Smith normal form} of $X$, normalized so that $d_n \mid d_{n-1} \mid \ldots \mid d_1$. The binary digits of \fl\ mean: 1 (complete output): if set, outputs $[U,V,D]$, where $U$ and $V$ are two unimodular matrices such that $UXV$ is the diagonal matrix $D$. Otherwise output only the diagonal of $D$. If $X$ is not a square matrix, then $D$ will be a square diagonal matrix padded with zeros on the left or the top. 2 (generic input): if set, allows polynomial entries, in which case the input matrix must be square. Otherwise, assume that $X$ has integer coefficients with arbitrary shape. 4 (cleanup): if set, cleans up the output. This means that elementary divisors equal to $1$ will be deleted, i.e.~outputs a shortened vector $D'$ instead of $D$. If complete output was required, returns $[U',V',D']$ so that $U'XV' = D'$ holds. If this flag is set, $X$ is allowed to be of the form `vector of elementary divisors' or $[U,V,D]$ as would normally be output with the cleanup flag unset. pari-2.7.5/src/functions/linear_algebra/listinsert0000644000175000017500000000073311636712103020762 0ustar billbillFunction: listinsert Section: linear_algebra C-Name: listinsert Prototype: WGL Help: listinsert(L,x,n): insert x at index n in list L, shifting the remaining elements to the right. Description: (list, gen, small):gen listinsert($1, $2, $3) Doc: inserts the object $x$ at position $n$ in $L$ (which must be of type \typ{LIST}). This has complexity $O(\#L - n + 1)$: all the remaining elements of \var{list} (from position $n+1$ onwards) are shifted to the right. pari-2.7.5/src/functions/linear_algebra/charpoly0000644000175000017500000000531612314242551020404 0ustar billbillFunction: charpoly Section: linear_algebra C-Name: charpoly0 Prototype: GDnD5,L, Help: 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. Doc: \idx{characteristic polynomial} of $A$ with respect to the variable $v$, i.e.~determinant of $v*I-A$ if $A$ is a square matrix. \bprog ? charpoly([1,2;3,4]); %1 = x^2 - 5*x - 2 ? charpoly([1,2;3,4],, 't) %2 = t^2 - 5*t - 2 @eprog\noindent If $A$ is not a square matrix, the function returns the characteristic polynomial of the map ``multiplication by $A$'' if $A$ is a scalar: \bprog ? charpoly(Mod(x+2, x^3-2)) %1 = x^3 - 6*x^2 + 12*x - 10 ? charpoly(I) %2 = x^2 + 1 ? charpoly(quadgen(5)) %3 = x^2 - x - 1 ? charpoly(ffgen(ffinit(2,4))) %4 = Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) @eprog The value of $\fl$ is only significant for matrices, and we advise to stick to the default value. Let $n$ be the dimension of $A$. If $\fl=0$, same method (Le Verrier's) as for computing the adjoint matrix, i.e.~using the traces of the powers of $A$. Assumes that $n!$ is invertible; uses $O(n^4)$ scalar operations. If $\fl=1$, uses Lagrange interpolation which is usually the slowest method. Assumes that $n!$ is invertible; uses $O(n^4)$ scalar operations. If $\fl=2$, uses the Hessenberg form. Assumes that the base ring is a field. Uses $O(n^3)$ scalar operations, but suffers from coefficient explosion unless the base field is finite or $\R$. If $\fl=3$, uses Berkowitz's division free algorithm, valid over any ring (commutative, with unit). Uses $O(n^4)$ scalar operations. If $\fl=4$, $x$ must be integral. Uses a modular algorithm: Hessenberg form for various small primes, then Chinese remainders. If $\fl=5$ (default), uses the ``best'' method given $x$. This means we use Berkowitz unless the base ring is $\Z$ (use $\fl=4$) or a field where coefficient explosion does not occur, e.g.~a finite field or the reals (use $\fl=2$). Variant: Also available are \fun{GEN}{charpoly}{GEN x, long v} ($\fl=5$), \fun{GEN}{caract}{GEN A, long v} ($\fl=1$), \fun{GEN}{carhess}{GEN A, long v} ($\fl=2$), \fun{GEN}{carberkowitz}{GEN A, long v} ($\fl=3$) and \fun{GEN}{caradj}{GEN A, long v, GEN *pt}. In this last case, if \var{pt} is not \kbd{NULL}, \kbd{*pt} receives the address of the adjoint matrix of $A$ (see \tet{matadjoint}), so both can be obtained at once. pari-2.7.5/src/functions/linear_algebra/listkill0000644000175000017500000000056011636712103020407 0ustar billbillFunction: listkill Section: linear_algebra C-Name: listkill Prototype: vG Help: listkill(L): obsolete, retained for backward compatibility. Doc: obsolete, retained for backward compatibility. Just use \kbd{L = List()} instead of \kbd{listkill(L)}. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns. pari-2.7.5/src/functions/linear_algebra/trace0000644000175000017500000000061511636712103017657 0ustar billbillFunction: trace Section: linear_algebra C-Name: gtrace Prototype: G Help: trace(x): trace of x. Doc: this applies to quite general $x$. If $x$ is not a matrix, it is equal to the sum of $x$ and its conjugate, except for polmods where it is the trace as an algebraic number. For $x$ a square matrix, it is the ordinary trace. If $x$ is a non-square matrix (but not a vector), an error occurs. pari-2.7.5/src/functions/linear_algebra/listsort0000644000175000017500000000141512314242551020442 0ustar billbillFunction: listsort Section: linear_algebra C-Name: listsort Prototype: vWD0,L, Help: 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. Doc: sorts the \typ{LIST} \var{list} in place, with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. In particular, the ordering is the same as for sets and \tet{setsearch} can be used on a sorted list. \bprog ? L = List([1,2,4,1,3,-1]); listsort(L); L %1 = List([-1, 1, 1, 2, 3, 4]) ? setsearch(L, 4) %2 = 6 ? setsearch(L, -2) %3 = 0 @eprog\noindent This is faster than the \kbd{vecsort} command since the list is sorted in place: no copy is made. No value returned. If $\fl$ is non-zero, suppresses all repeated coefficients. pari-2.7.5/src/functions/linear_algebra/mathnf0000644000175000017500000001040512366172547020051 0ustar billbillFunction: mathnf Section: linear_algebra C-Name: mathnf0 Prototype: GD0,L, Help: 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. Doc: let $R$ be a Euclidean ring, equal to $\Z$ or to $K[X]$ for some field $K$. If $M$ is a (not necessarily square) matrix with entries in $R$, this routine finds the \emph{upper triangular} \idx{Hermite normal form} of $M$. If the rank of $M$ is equal to its number of rows, this is a square matrix. In general, the columns of the result form a basis of the $R$-module spanned by the columns of $M$. The values $0,1,2,3$ of $\fl$ have a binary meaning, analogous to the one in \tet{matsnf}; in this case, binary digits of $\fl$ mean: \item 1 (complete output): if set, outputs $[H,U]$, where $H$ is the Hermite normal form of $M$, and $U$ is a transformation matrix such that $MU=[0|H]$. The matrix $U$ belongs to $\text{GL}(R)$. When $M$ has a large kernel, the entries of $U$ are in general huge. \item 2 (generic input): \emph{Deprecated}. If set, assume that $R = K[X]$ is a polynomial ring; otherwise, assume that $R = \Z$. This flag is now useless since the routine always checks whether the matrix has integral entries. \noindent For these 4 values, we use a naive algorithm, which behaves well in small dimension only. Larger values correspond to different algorithms, are restricted to \emph{integer} matrices, and all output the unimodular matrix $U$. From now on all matrices have integral entries. \item $\fl=4$, returns $[H,U]$ as in ``complete output'' above, using a variant of \idx{LLL} reduction along the way. The matrix $U$ is provably small in the $L_2$ sense, and in general close to optimal; but the reduction is in general slow, although provably polynomial-time. If $\fl=5$, uses Batut's algorithm and output $[H,U,P]$, such that $H$ and $U$ are as before and $P$ is a permutation of the rows such that $P$ applied to $MU$ gives $H$. This is in general faster than $\fl=4$ but the matrix $U$ is usually worse; it is heuristically smaller than with the default algorithm. When the matrix is dense and the dimension is large (bigger than 100, say), $\fl = 4$ will be fastest. When $M$ has maximal rank, then \bprog H = mathnfmod(M, matdetint(M)) @eprog\noindent will be even faster. You can then recover $U$ as $M^{-1}H$. \bprog ? M = matrix(3,4,i,j,random([-5,5])) %1 = [ 0 2 3 0] [-5 3 -5 -5] [ 4 3 -5 4] ? [H,U] = mathnf(M, 1); ? U %3 = [-1 0 -1 0] [ 0 5 3 2] [ 0 3 1 1] [ 1 0 0 0] ? H %5 = [19 9 7] [ 0 9 1] [ 0 0 1] ? M*U %6 = [0 19 9 7] [0 0 9 1] [0 0 0 1] @eprog For convenience, $M$ is allowed to be a \typ{VEC}, which is then automatically converted to a \typ{MAT}, as per the \tet{Mat} function. For instance to solve the generalized extended gcd problem, one may use \bprog ? v = [116085838, 181081878, 314252913,10346840]; ? [H,U] = mathnf(v, 1); ? U %2 = [ 103 -603 15 -88] [-146 13 -1208 352] [ 58 220 678 -167] [-362 -144 381 -101] ? v*U %3 = [0, 0, 0, 1] @eprog\noindent This also allows to input a matrix as a \typ{VEC} of \typ{COL}s of the same length (which \kbd{Mat} would concatenate to the \typ{MAT} having those columns): \bprog ? v = [[1,0,4]~, [3,3,4]~, [0,-4,-5]~]; mathnf(v) %1 = [47 32 12] [ 0 1 0] [ 0 0 1] @eprog Variant: Also available are \fun{GEN}{hnf}{GEN M} ($\fl=0$) and \fun{GEN}{hnfall}{GEN M} ($\fl=1$). To reduce \emph{huge} relation matrices (sparse with small entries, say dimension $400$ or more), you can use the pair \kbd{hnfspec} / \kbd{hnfadd}. Since this is quite technical and the calling interface may change, they are not documented yet. Look at the code in \kbd{basemath/hnf\_snf.c}. pari-2.7.5/src/functions/linear_algebra/qflllgram0000644000175000017500000000344111636712103020542 0ustar billbillFunction: qflllgram Section: linear_algebra C-Name: qflllgram0 Prototype: GD0,L, Help: 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. Doc: same as \kbd{qflll}, except that the matrix $G = \kbd{x\til * x}$ is the Gram matrix of some lattice vectors $x$, and not the coordinates of the vectors themselves. In particular, $G$ must now be a square symmetric real matrix, corresponding to a positive quadratic form (not necessarily definite: $x$ needs not have maximal rank). The result is a unimodular transformation matrix $T$ such that $x \cdot T$ is an LLL-reduced basis of the lattice generated by the column vectors of $x$. See \tet{qflll} for further details about the LLL implementation. If $\fl=0$ (default), assume that $G$ has either exact (integral or rational) or real floating point entries. The matrix is rescaled, converted to integers and the behavior is then as in $\fl = 1$. If $\fl=1$, assume that $G$ is integral. Computations involving Gram-Schmidt vectors are approximate, with precision varying as needed (Lehmer's trick, as generalized by Schnorr). Adapted from Nguyen and Stehl\'e's algorithm and Stehl\'e's code (\kbd{fplll-1.3}). $\fl=4$: $G$ has integer entries, gives the kernel and reduced image of $x$. $\fl=5$: same as $4$, but $G$ may have polynomial coefficients. Variant: Also available are \fun{GEN}{lllgram}{GEN G} ($\fl=0$), \fun{GEN}{lllgramint}{GEN G} ($\fl=1$), and \fun{GEN}{lllgramkerim}{GEN G} ($\fl=4$). pari-2.7.5/src/functions/linear_algebra/qfisom0000644000175000017500000000207012366172547020071 0ustar billbillFunction: qfisom Section: linear_algebra C-Name: qfisom0 Prototype: GGDG Help: 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. Doc: $G$, $H$ being square and symmetric matrices with integer entries representing positive definite quadratic forms, return an invertible matrix $S$ such that $G={^t}S\*H\*S$. This defines a isomorphism between the corresponding lattices. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. See \kbd{qfisominit} for the meaning of \var{fl}. $G$ can also be given by an \kbd{qfisominit} structure which is preferable if several forms $H$ need to be compared to $G$. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. Variant: Also available is \fun{GEN}{qfisom}{GEN G, GEN H, GEN fl} where $G$ is a vector of \kbd{zm}, and $H$ is a \kbd{zm}. pari-2.7.5/src/functions/linear_algebra/matsupplement0000644000175000017500000000154212314242551021456 0ustar billbillFunction: matsupplement Section: linear_algebra C-Name: suppl Prototype: G Help: matsupplement(x): supplement the columns of the matrix x to an invertible matrix. Doc: assuming that the columns of the matrix $x$ are linearly independent (if they are not, an error message is issued), finds a square invertible matrix whose first columns are the columns of $x$, i.e.~supplement the columns of $x$ to a basis of the whole space. \bprog ? matsupplement([1;2]) %1 = [1 0] [2 1] @eprog Raises an error if $x$ has 0 columns, since (due to a long standing design bug), the dimension of the ambient space (the number of rows) is unknown in this case: \bprog ? matsupplement(matrix(2,0)) *** at top-level: matsupplement(matrix *** ^-------------------- *** matsupplement: sorry, suppl [empty matrix] is not yet implemented. @eprog pari-2.7.5/src/functions/linear_algebra/matisdiagonal0000644000175000017500000000034611636712103021376 0ustar billbillFunction: matisdiagonal Section: linear_algebra C-Name: isdiagonal Prototype: iG Help: matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise. Doc: returns true (1) if $x$ is a diagonal matrix, false (0) if not. pari-2.7.5/src/functions/linear_algebra/matadjoint0000644000175000017500000000212012366172547020721 0ustar billbillFunction: matadjoint Section: linear_algebra C-Name: matadjoint0 Prototype: GD0,L, Help: matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, compute the characteristic polynomial independently first. Doc: \idx{adjoint matrix} of $M$, i.e.~a matrix $N$ of cofactors of $M$, satisfying $M*N=\det(M)*\Id$. $M$ must be a (non-necessarily invertible) square matrix of dimension $n$. If $\fl$ is 0 or omitted, we try to use Leverrier-Faddeev's algorithm, which assumes that $n!$ invertible. If it fails or $\fl = 1$, compute $T = \kbd{charpoly}(M)$ independently first and return $(-1)^{n-1} (T(x)-T(0))/x$ evaluated at $M$. \bprog ? a = [1,2,3;3,4,5;6,7,8] * Mod(1,4); %2 = [Mod(1, 4) Mod(2, 4) Mod(3, 4)] [Mod(3, 4) Mod(0, 4) Mod(1, 4)] [Mod(2, 4) Mod(3, 4) Mod(0, 4)] @eprog\noindent Both algorithms use $O(n^4)$ operations in the base ring, and are usually slower than computing the characteristic polynomial or the inverse of $M$ directly. Variant: Also available are \fun{GEN}{adj}{GEN x} (\fl=0) and \fun{GEN}{adjsafe}{GEN x} (\fl=1). pari-2.7.5/src/functions/linear_algebra/qfsign0000644000175000017500000000055011636712103020046 0ustar billbillFunction: qfsign Section: linear_algebra C-Name: qfsign Prototype: G Help: qfsign(x): signature of the symmetric matrix x. Doc: returns $[p,m]$ the signature of the quadratic form represented by the symmetric matrix $x$. Namely, $p$ (resp.~$m$) is the number of positive (resp.~negative) eigenvalues of $x$.The result is computed using Gaussian reduction. pari-2.7.5/src/functions/linear_algebra/mathouseholder0000644000175000017500000000051712314242551021604 0ustar billbillFunction: mathouseholder Section: linear_algebra C-Name: mathouseholder Prototype: GG Help: mathouseholder(Q,v): applies a sequence Q of Householder transforms to the vector or matrix v. Doc: \sidx{Householder transform}applies a sequence $Q$ of Householder transforms, as returned by \kbd{matqr}$(M,1)$ to the vector or matrix $v$. pari-2.7.5/src/functions/linear_algebra/matfrobenius0000644000175000017500000000130612314242551021254 0ustar billbillFunction: matfrobenius Section: linear_algebra C-Name: matfrobenius Prototype: GD0,L,Dn Help: 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. Doc: returns the Frobenius form of the square matrix \kbd{M}. If $\fl=1$, returns only the elementary divisors as a vector of polynomials in the variable \kbd{v}. If $\fl=2$, returns a two-components vector [F,B] where \kbd{F} is the Frobenius form and \kbd{B} is the basis change so that $M=B^{-1}FB$. pari-2.7.5/src/functions/linear_algebra/matmuldiagonal0000644000175000017500000000065011636712103021556 0ustar billbillFunction: matmuldiagonal Section: linear_algebra C-Name: matmuldiagonal Prototype: GG Help: 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). Doc: product of the matrix $x$ by the diagonal matrix whose diagonal entries are those of the vector $d$. Equivalent to, but much faster than $x*\kbd{matdiagonal}(d)$. pari-2.7.5/src/functions/linear_algebra/qfnorm0000644000175000017500000000210412366172547020073 0ustar billbillFunction: qfnorm Section: linear_algebra C-Name: qfnorm Prototype: GDG Help: qfnorm(x,{q}): evaluate the binary quadratic form q (symmetric matrix) at x; if q omitted, use the standard Euclidean form. Doc: evaluate the binary quadratic form $q$ (symmetric matrix) at the vector $x$. If $q$ omitted, use the standard Euclidean form, corresponding to the identity matrix. Equivalent to \kbd{x\til * q * x}, but about twice faster and more convenient (does not distinguish between column and row vectors): \bprog ? x = [1,2,3]~; qfnorm(x) %1 = 14 ? q = [1,2,3;2,2,-1;3,-1,0]; qfnorm(x, q) %2 = 23 ? for(i=1,10^6, qfnorm(x,q)) time = 384ms. ? for(i=1,10^6, x~*q*x) time = 729ms. @eprog\noindent We also allow \typ{MAT}s of compatible dimensions for $x$, and return \kbd{x\til * q * x} in this case as well: \bprog ? M = [1,2,3;4,5,6;7,8,9]; qfnorm(M) \\ Gram matrix %5 = [66 78 90] [78 93 108] [90 108 126] ? for(i=1,10^6, qfnorm(M,q)) time = 2,144 ms. ? for(i=1,10^6, M~*q*M) time = 2,793 ms. @eprog \noindent The polar form is also available, as \tet{qfbil}. pari-2.7.5/src/functions/linear_algebra/matrank0000644000175000017500000000021211636712103020207 0ustar billbillFunction: matrank Section: linear_algebra C-Name: rank Prototype: lG Help: matrank(x): rank of the matrix x. Doc: rank of the matrix $x$. pari-2.7.5/src/functions/linear_algebra/mateigen0000644000175000017500000000262312366172547020370 0ustar billbillFunction: mateigen Section: linear_algebra C-Name: mateigen Prototype: GD0,L,p Help: 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. Doc: returns the (complex) eigenvectors of $x$ as columns of a matrix. If $\fl=1$, return $[L,H]$, where $L$ contains the eigenvalues and $H$ the corresponding eigenvectors; multiple eigenvalues are repeated according to the eigenspace dimension (which may be less than the eigenvalue multiplicity in the characteristic polynomial). This function first computes the characteristic polynomial of $x$ and approximates its complex roots $(\lambda_i)$, then tries to compute the eigenspaces as kernels of the $x - \lambda_i$. This algorithm is ill-conditioned and is likely to miss kernel vectors if some roots of the characteristic polynomial are close, in particular if it has multiple roots. \bprog ? A = [13,2; 10,14]; mateigen(A) %1 = [-1/2 2/5] [ 1 1] ? [L,H] = mateigen(A, 1); ? L %3 = [9, 18] ? H %4 = [-1/2 2/5] [ 1 1] @eprog\noindent For symmetric matrices, use \tet{qfjacobi} instead; for Hermitian matrices, compute \bprog A = real(x); B = imag(x); y = matconcat([A, -B; B, A]); @eprog\noindent and apply \kbd{qfjacobi} to $y$. Variant: Also available is \fun{GEN}{eigen}{GEN x, long prec} ($\fl = 0$) pari-2.7.5/src/functions/linear_algebra/qfrep0000644000175000017500000000212612314242551017674 0ustar billbillFunction: qfrep Section: linear_algebra C-Name: qfrep0 Prototype: GGD0,L, Help: 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. Doc: $q$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, count the vectors representing successive integers. \item If $\fl = 0$, count all vectors. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors $v$ such that $q(v)=i$. \item If $\fl = 1$, count vectors of even norm. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors such that $q(v) = 2i$. \bprog ? q = [2, 1; 1, 3]; ? qfrep(q, 5) %2 = Vecsmall([0, 1, 2, 0, 0]) \\ 1 vector of norm 2, 2 of norm 3, etc. ? qfrep(q, 5, 1) %3 = Vecsmall([1, 0, 0, 1, 0]) \\ 1 vector of norm 2, 0 of norm 4, etc. @eprog\noindent This routine uses a naive algorithm based on \tet{qfminim}, and will fail if any entry becomes larger than $2^{31}$ (or $2^{63}$). pari-2.7.5/src/functions/linear_algebra/matinverseimage0000644000175000017500000000146411636712103021744 0ustar billbillFunction: matinverseimage Section: linear_algebra C-Name: inverseimage Prototype: GG Help: matinverseimage(x,y): an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise. Doc: given a matrix $x$ and a column vector or matrix $y$, returns a preimage $z$ of $y$ by $x$ if one exists (i.e such that $x z = y$), an empty vector or matrix otherwise. The complete inverse image is $z + \text{Ker} x$, where a basis of the kernel of $x$ may be obtained by \kbd{matker}. \bprog ? M = [1,2;2,4]; ? matinverseimage(M, [1,2]~) %2 = [1, 0]~ ? matinverseimage(M, [3,4]~) %3 = []~ \\@com no solution ? matinverseimage(M, [1,3,6;2,6,12]) %4 = [1 3 6] [0 0 0] ? matinverseimage(M, [1,2;3,4]) %5 = [;] \\@com no solution ? K = matker(M) %6 = [-2] [1] @eprog pari-2.7.5/src/functions/linear_algebra/matconcat0000644000175000017500000000406212314242551020531 0ustar billbillFunction: matconcat Section: linear_algebra C-Name: matconcat Prototype: G Help: matconcat(v): concatenate the entries of v and return the resulting matrix Doc: returns a \typ{MAT} built from the entries of $v$, which may be a \typ{VEC} (concatenate horizontally), a \typ{COL} (concatenate vertically), or a \typ{MAT} (concatenate vertically each column, and concatenate vertically the resulting matrices). The entries of $v$ are always considered as matrices: they can themselves be \typ{VEC} (seen as a row matrix), a \typ{COL} seen as a column matrix), a \typ{MAT}, or a scalar (seen as an $1 \times 1$ matrix). \bprog ? A=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9; ? matconcat([A, B]) \\ horizontal %1 = [1 2 5] [3 4 6] ? matconcat([A, C]~) \\ vertical %2 = [1 2] [3 4] [7 8] ? matconcat([A, B; C, D]) \\ block matrix %3 = [1 2 5] [3 4 6] [7 8 9] @eprog\noindent If the dimensions of the entries to concatenate do not match up, the above rules are extended as follows: \item each entry $v_{i,j}$ of $v$ has a natural length and height: $1 \times 1$ for a scalar, $1 \times n$ for a \typ{VEC} of length $n$, $n \times 1$ for a \typ{COL}, $m \times n$ for an $m\times n$ \typ{MAT} \item let $H_i$ be the maximum over $j$ of the lengths of the $v_{i,j}$, let $L_j$ be the maximum over $i$ of the heights of the $v_{i,j}$. The dimensions of the $(i,j)$-th block in the concatenated matrix are $H_i \times L_j$. \item a scalar $s = v_{i,j}$ is considered as $s$ times an identity matrix of the block dimension $\min (H_i,L_j)$ \item blocks are extended by 0 columns on the right and 0 rows at the bottom, as needed. \bprog ? matconcat([1, [2,3]~, [4,5,6]~]) \\ horizontal %4 = [1 2 4] [0 3 5] [0 0 6] ? matconcat([1, [2,3], [4,5,6]]~) \\ vertical %5 = [1 0 0] [2 3 0] [4 5 6] ? matconcat([B, C; A, D]) \\ block matrix %6 = [5 0 7 8] [6 0 0 0] [1 2 9 0] [3 4 0 9] ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9]; ? matconcat(matdiagonal([U, V])) \\ block diagonal %7 = [1 2 0 0 0] [3 4 0 0 0] [0 0 1 2 3] [0 0 4 5 6] [0 0 7 8 9] @eprog pari-2.7.5/src/functions/linear_algebra/setisset0000644000175000017500000000107612413013143020416 0ustar billbillFunction: setisset Section: linear_algebra C-Name: setisset Prototype: lG Help: setisset(x): true(1) if x is a set (row vector with strictly increasing entries), false(0) if not. Doc: returns true (1) if $x$ is a set, false (0) if not. In PARI, a set is a row vector whose entries are strictly increasing with respect to a (somewhat arbitrary) universal comparison function. To convert any object into a set (this is most useful for vectors, of course), use the function \kbd{Set}. \bprog ? a = [3, 1, 1, 2]; ? setisset(a) %2 = 0 ? Set(a) %3 = [1, 2, 3] @eprog pari-2.7.5/src/functions/linear_algebra/qfjacobi0000644000175000017500000000155612366172547020361 0ustar billbillFunction: qfjacobi Section: linear_algebra C-Name: jacobi Prototype: Gp Help: qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A. Doc: apply Jacobi's eigenvalue algorithm to the real symmetric matrix $A$. This returns $[L, V]$, where \item $L$ is the vector of (real) eigenvalues of $A$, sorted in increasing order, \item $V$ is the corresponding orthogonal matrix of eigenvectors of $A$. \bprog ? \p19 ? A = [1,2;2,1]; mateigen(A) %1 = [-1 1] [ 1 1] ? [L, H] = qfjacobi(A); ? L %3 = [-1.000000000000000000, 3.000000000000000000]~ ? H %4 = [ 0.7071067811865475245 0.7071067811865475244] [-0.7071067811865475244 0.7071067811865475245] ? norml2( (A-L[1])*H[,1] ) \\ approximate eigenvector %5 = 9.403954806578300064 E-38 ? norml2(H*H~ - 1) %6 = 2.350988701644575016 E-38 \\ close to orthogonal @eprog pari-2.7.5/src/functions/linear_algebra/setunion0000644000175000017500000000044212314242551020422 0ustar billbillFunction: setunion Section: linear_algebra C-Name: setunion Prototype: GG Help: setunion(x,y): union of the sets x and y. Description: (vec, vec):vec setunion($1, $2) Doc: union of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. pari-2.7.5/src/functions/linear_algebra/listput0000644000175000017500000000146211636712103020266 0ustar billbillFunction: listput Section: linear_algebra C-Name: listput Prototype: WGD0,L, Help: 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. Description: (list, gen, small):gen listput($1, $2, $3) Doc: sets the $n$-th element of the list \var{list} (which must be of type \typ{LIST}) equal to $x$. If $n$ is omitted, or greater than the list length, appends $x$. You may put an element into an occupied cell (not changing the list length), but it is easier to use the standard \kbd{list[n] = x} construct. This runs in time $O(\#L)$ in the worst case (when the list must be reallocated), but in time $O(1)$ on average: any number of successive \kbd{listput}s run in time $O(\#L)$, where $\#L$ denotes the list \emph{final} length. pari-2.7.5/src/functions/linear_algebra/setintersect0000644000175000017500000000050012314242551021265 0ustar billbillFunction: setintersect Section: linear_algebra C-Name: setintersect Prototype: GG Help: setintersect(x,y): intersection of the sets x and y. Description: (vec, vec):vec setintersect($1, $2) Doc: intersection of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. pari-2.7.5/src/functions/linear_algebra/normlp0000644000175000017500000000225612366172547020110 0ustar billbillFunction: normlp Section: linear_algebra C-Name: gnormlp Prototype: GDGp Help: normlp(x,{p}): Lp-norm of x; sup norm if p is omitted. Doc: $L^p$-norm of $x$; sup norm if $p$ is omitted. More precisely, if $x$ is a scalar, \kbd{normlp}$(x, p)$ is defined to be \kbd{abs}$(x)$. If $x$ is a polynomial, a (row or column) vector or a matrix: \item if $p$ is omitted, \kbd{normlp($x$)} is defined recursively as $\max_i \kbd{normlp}(x_i))$, where $(x_i)$ run through the components of~$x$. In particular, this yields the usual sup norm if $x$ is a polynomial or vector with complex components. \item otherwise, \kbd{normlp($x$, $p$)} is defined recursively as $(\sum_i \kbd{normlp}^p(x_i,p))^{1/p}$. In particular, this yields the usual $(\sum |x_i|^p)^{1/p}$ if $x$ is a polynomial or vector with complex components. \bprog ? v = [1,-2,3]; normlp(v) \\ vector %1 = 3 ? M = [1,-2;-3,4]; normlp(M) \\ matrix %2 = 4 ? T = (1+I) + I*x^2; normlp(T) %3 = 1.4142135623730950488016887242096980786 ? normlp([[1,2], [3,4], 5, 6]) \\ recursively defined %4 = 6 ? normlp(v, 1) %5 = 6 ? normlp(M, 1) %6 = 10 ? normlp(T, 1) %7 = 2.4142135623730950488016887242096980786 @eprog pari-2.7.5/src/functions/linear_algebra/matmultodiagonal0000644000175000017500000000066011636712103022122 0ustar billbillFunction: matmultodiagonal Section: linear_algebra C-Name: matmultodiagonal Prototype: GG Help: 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. Doc: product of the matrices $x$ and $y$ assuming that the result is a diagonal matrix. Much faster than $x*y$ in that case. The result is undefined if $x*y$ is not diagonal. pari-2.7.5/src/functions/linear_algebra/mathess0000644000175000017500000000036311636712103020225 0ustar billbillFunction: mathess Section: linear_algebra C-Name: hess Prototype: G Help: mathess(x): Hessenberg form of x. Doc: returns a matrix similar to the square matrix $x$, which is in upper Hessenberg form (zero entries below the first subdiagonal). pari-2.7.5/src/functions/linear_algebra/matintersect0000644000175000017500000000121011636712103021253 0ustar billbillFunction: matintersect Section: linear_algebra C-Name: intersect Prototype: GG Help: matintersect(x,y): intersection of the vector spaces whose bases are the columns of x and y. Doc: $x$ and $y$ being two matrices with the same number of rows each of whose columns are independent, finds a basis of the $\Q$-vector space equal to the intersection of the spaces spanned by the columns of $x$ and $y$ respectively. The faster function \tet{idealintersect} can be used to intersect fractional ideals (projective $\Z_K$ modules of rank $1$); the slower but much more general function \tet{nfhnf} can be used to intersect general $\Z_K$-modules. pari-2.7.5/src/functions/linear_algebra/qfminim0000644000175000017500000001270212366172547020236 0ustar billbillFunction: qfminim Section: linear_algebra C-Name: qfminim0 Prototype: GDGDGD0,L,p Help: 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. Doc: $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 behavior is undefined if $x$ is not positive definite (a ``precision too low'' error is most likely, although more precise error messages are possible). The precise behavior depends on $\fl$. If $\fl=0$ (default), seeks at most $2m$ vectors. The result is a three-component vector, the first component being the number of vectors found, the second being the maximum norm found, and the last vector is a matrix whose columns are the vectors found, only one being given for each pair $\pm v$ (at most $m$ such pairs, unless $m$ was omitted). The vectors are returned in no particular order. If $\fl=1$, ignores $m$ and returns $[N,v]$, where $v$ is a non-zero vector of length $N \leq b$, or $[]$ if no non-zero vector has length $\leq b$. If no explicit $b$ is provided, return a vector of smallish norm (smallest vector in an LLL-reduced basis). In these two cases, $x$ must have \emph{integral} entries. The implementation uses low precision floating point computations for maximal speed, which gives incorrect result when $x$ has large entries. (The condition is checked in the code and the routine raises an error if large rounding errors occur.) A more robust, but much slower, implementation is chosen if the following flag is used: If $\fl=2$, $x$ can have non integral real entries. In this case, if $b$ is omitted, the ``minimal'' vectors only have approximately the same norm. If $b$ is omitted, $m$ is an upper bound for the number of vectors that will be stored and returned, but all minimal vectors are nevertheless enumerated. If $m$ is omitted, all vectors found are stored and returned; note that this may be a huge vector! \bprog ? x = matid(2); ? qfminim(x) \\@com 4 minimal vectors of norm 1: $\pm[0,1]$, $\pm[1,0]$ %2 = [4, 1, [0, 1; 1, 0]] ? { x = [4, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1, 0,-1, 0, 0, 0,-2; 2, 4,-2,-2, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1, 0, 1,-1,-1; 0,-2, 4, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 0, 1,-1,-1, 0, 0; 0,-2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1,-1, 0, 1,-1, 1, 0; 0, 0,-2, 0, 4, 0, 0, 0, 1,-1, 0, 0, 1, 0, 0, 0,-2, 0, 0,-1, 1, 1, 0, 0; -2, -2,0, 0, 0, 4,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,-1, 1, 1; 0, 0, 0, 0, 0,-2, 4,-2, 0, 0, 0, 0, 0, 1, 0, 0, 0,-1, 0, 0, 0, 1,-1, 0; 0, 0, 0, 0, 0, 0,-2, 4, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1,-1,-1, 0, 1, 0; 0, 0, 0, 0, 1,-1, 0, 0, 4, 0,-2, 0, 1, 1, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 0, 0, 1, 1,-1, 1, 0, 0, 0, 1, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 4,-2, 0,-1, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 4,-1, 1, 0, 0,-1, 1, 0, 1, 1, 1,-1, 0; 1, 0,-1, 1, 1, 0, 0,-1, 1, 1, 0,-1, 4, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,-1; -1,-1, 1,-1, 0, 0, 1, 0, 1, 1,-1, 1, 0, 4, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 1, 1, 0, 0; 0, 0, 1, 0,-2, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 1, 1, 1, 0, 0, 1, 1; 1, 0, 0, 1, 0, 0,-1, 0, 1, 0,-1, 1, 1, 0, 0, 0, 1, 4, 0, 1, 1, 0, 1, 0; 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 4, 0, 1, 1, 0, 1; -1, -1,1, 0,-1, 1, 0,-1, 0, 1,-1, 1, 0, 1, 0, 0, 1, 1, 0, 4, 0, 0, 1, 1; 0, 0,-1, 1, 1, 0, 0,-1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 4, 1, 0, 1; 0, 1,-1,-1, 1,-1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 4, 0, 1; 0,-1, 0, 1, 0, 1,-1, 1, 0, 1, 0,-1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 4, 1; -2,-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 4]; } ? qfminim(x,,0) \\ the Leech lattice has 196560 minimal vectors of norm 4 time = 648 ms. %4 = [196560, 4, [;]] ? qfminim(x,,0,2); \\ safe algorithm. Slower and unnecessary here. time = 18,161 ms. %5 = [196560, 4.000061035156250000, [;]] @eprog\noindent\sidx{Leech lattice}\sidx{minimal vector} In the last example, we store 0 vectors to limit memory use. All minimal vectors are nevertheless enumerated. Provided \kbd{parisize} is about 50MB, \kbd{qfminim(x)} succeeds in 2.5 seconds. Variant: Also available are \fun{GEN}{minim}{GEN x, GEN b = NULL, GEN m = NULL} ($\fl=0$), \fun{GEN}{minim2}{GEN x, GEN b = NULL, GEN m = NULL} ($\fl=1$). \fun{GEN}{minim_raw}{GEN x, GEN b = NULL, GEN m = NULL} (do not perform LLL reduction on x). pari-2.7.5/src/functions/linear_algebra/concat0000644000175000017500000000452412314242551020032 0ustar billbillFunction: concat Section: linear_algebra C-Name: concat Prototype: GDG Help: 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. Description: (mp,mp):vec concat($1, $2) (vec,mp):vec concat($1, $2) (mp,vec):vec concat($1, $2) (vec,vec):vec concat($1, $2) (list,list):list concat($1, $2) (genstr,gen):genstr concat($1, $2) (gen,genstr):genstr concat($1, $2) (gen,?gen):gen concat($1, $2) Doc: concatenation of $x$ and $y$. If $x$ or $y$ is not a vector or matrix, it is considered as a one-dimensional vector. All types are allowed for $x$ and $y$, but the sizes must be compatible. Note that matrices are concatenated horizontally, i.e.~the number of rows stays the same. Using transpositions, one can concatenate them vertically, but it is often simpler to use \tet{matconcat}. \bprog ? x = matid(2); y = 2*matid(2); ? concat(x,y) %2 = [1 0 2 0] [0 1 0 2] ? concat(x~,y~)~ %3 = [1 0] [0 1] [2 0] [0 2] ? matconcat([x;y]) %4 = [1 0] [0 1] [2 0] [0 2] @eprog\noindent To concatenate vectors sideways (i.e.~to obtain a two-row or two-column matrix), use \tet{Mat} instead, or \tet{matconcat}: \bprog ? x = [1,2]; ? y = [3,4]; ? concat(x,y) %3 = [1, 2, 3, 4] ? Mat([x,y]~) %4 = [1 2] [3 4] ? matconcat([x;y]) %5 = [1 2] [3 4] @eprog Concatenating a row vector to a matrix having the same number of columns will add the row to the matrix (top row if the vector is $x$, i.e.~comes first, and bottom row otherwise). The empty matrix \kbd{[;]} is considered to have a number of rows compatible with any operation, in particular concatenation. (Note that this is \emph{not} the case for empty vectors \kbd{[~]} or \kbd{[~]\til}.) If $y$ is omitted, $x$ has to be a row vector or a list, in which case its elements are concatenated, from left to right, using the above rules. \bprog ? concat([1,2], [3,4]) %1 = [1, 2, 3, 4] ? a = [[1,2]~, [3,4]~]; concat(a) %2 = [1 3] [2 4] ? concat([1,2; 3,4], [5,6]~) %3 = [1 2 5] [3 4 6] ? concat([%, [7,8]~, [1,2,3,4]]) %5 = [1 2 5 7] [3 4 6 8] [1 2 3 4] @eprog Variant: \fun{GEN}{concat1}{GEN x} is a shortcut for \kbd{concat(x,NULL)}. pari-2.7.5/src/functions/linear_algebra/vectorsmall0000644000175000017500000000100611636712103021107 0ustar billbillFunction: vectorsmall Section: linear_algebra C-Name: vecteursmall Prototype: GDVDE Help: 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. Doc: creates a row vector of small integers (type \typ{VECSMALL}) with $n$ components whose components are the expression \var{expr} evaluated at the integer points between 1 and $n$. If one of the last two arguments is omitted, fill the vector with zeroes. %\syn{NO} pari-2.7.5/src/functions/linear_algebra/listcreate0000644000175000017500000000066611636712103020726 0ustar billbillFunction: listcreate Section: linear_algebra C-Name: listcreate Prototype: D0,L, Help: listcreate(): creates an empty list. Description: (?gen):list listcreate() Doc: creates an empty list. This routine used to have a mandatory argument, which is now ignored (for backward compatibility). In fact, this function has become redundant and obsolete; it will disappear in future versions of PARI: just use \kbd{List()} % \syn{NO} pari-2.7.5/src/functions/linear_algebra/matker0000644000175000017500000000140712314242551020043 0ustar billbillFunction: matker Section: linear_algebra C-Name: matker0 Prototype: GD0,L, Help: 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. Description: (gen, ?0):vec ker($1) (gen, 1):vec keri($1) (gen, #small) $"incorrect flag in matker" (gen, small):vec matker0($1, $2) Doc: gives a basis for the kernel of the matrix $x$ as columns of a matrix. The matrix can have entries of any type, provided they are compatible with the generic arithmetic operations ($+$, $\times$ and $/$). If $x$ is known to have integral entries, set $\fl=1$. Variant: Also available are \fun{GEN}{ker}{GEN x} ($\fl=0$), \fun{GEN}{keri}{GEN x} ($\fl=1$). pari-2.7.5/src/functions/linear_algebra/qflll0000644000175000017500000000611411636712103017673 0ustar billbillFunction: qflll Section: linear_algebra C-Name: qflll0 Prototype: GD0,L, Help: 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. Description: (vec, ?0):vec lll($1) (vec, 1):vec lllint($1) (vec, 2):vec lllintpartial($1) (vec, 4):vec lllkerim($1) (vec, 5):vec lllkerimgen($1) (vec, 8):vec lllgen($1) (vec, #small):vec $"Bad flag in qflll" (vec, small):vec qflll0($1, $2) Doc: \idx{LLL} algorithm applied to the \emph{columns} of the matrix $x$. The columns of $x$ may be linearly dependent. The result is a unimodular transformation matrix $T$ such that $x \cdot T$ is an LLL-reduced basis of the lattice generated by the column vectors of $x$. Note that if $x$ is not of maximal rank $T$ will not be square. The LLL parameters are $(0.51,0.99)$, meaning that the Gram-Schmidt coefficients for the final basis satisfy $\mu_{i,j} \leq |0.51|$, and the Lov\'{a}sz's constant is $0.99$. If $\fl=0$ (default), assume that $x$ has either exact (integral or rational) or real floating point entries. The matrix is rescaled, converted to integers and the behavior is then as in $\fl = 1$. If $\fl=1$, assume that $x$ is integral. Computations involving Gram-Schmidt vectors are approximate, with precision varying as needed (Lehmer's trick, as generalized by Schnorr). Adapted from Nguyen and Stehl\'e's algorithm and Stehl\'e's code (\kbd{fplll-1.3}). If $\fl=2$, $x$ should be an integer matrix whose columns are linearly independent. Returns a partially reduced basis for $x$, using an unpublished algorithm by Peter Montgomery: a basis is said to be \emph{partially reduced} if $|v_i \pm v_j| \geq |v_i|$ for any two distinct basis vectors $v_i, \, v_j$. This is faster than $\fl=1$, esp. when one row is huge compared to the other rows (knapsack-style), and should quickly produce relatively short vectors. The resulting basis is \emph{not} LLL-reduced in general. If LLL reduction is eventually desired, avoid this partial reduction: applying LLL to the partially reduced matrix is significantly \emph{slower} than starting from a knapsack-type lattice. If $\fl=4$, as $\fl=1$, returning a vector $[K, T]$ of matrices: the columns of $K$ represent a basis of the integer kernel of $x$ (not LLL-reduced in general) and $T$ is the transformation matrix such that $x\cdot T$ is an LLL-reduced $\Z$-basis of the image of the matrix $x$. If $\fl=5$, case as case $4$, but $x$ may have polynomial coefficients. If $\fl=8$, same as case $0$, but $x$ may have polynomial coefficients. Variant: Also available are \fun{GEN}{lll}{GEN x} ($\fl=0$), \fun{GEN}{lllint}{GEN x} ($\fl=1$), and \fun{GEN}{lllkerim}{GEN x} ($\fl=4$). pari-2.7.5/src/functions/linear_algebra/qfperfection0000644000175000017500000000116711636712103021251 0ustar billbillFunction: qfperfection Section: linear_algebra C-Name: perf Prototype: G Help: qfperfection(G): rank of matrix of xx~ for x minimal vectors of a gram matrix G. Doc: $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the perfection rank of the form. That is, gives the rank of the family of the $s$ symmetric matrices $v_iv_i^t$, where $s$ is half the number of minimal vectors and the $v_i$ ($1\le i\le s$) are the minimal vectors. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension of $x$ grows. pari-2.7.5/src/functions/linear_algebra/matpascal0000644000175000017500000000070512413013143020516 0ustar billbillFunction: matpascal Section: linear_algebra C-Name: matqpascal Prototype: LDG Help: matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise. Doc: creates as a matrix the lower triangular \idx{Pascal triangle} of order $x+1$ (i.e.~with binomial coefficients up to $x$). If $q$ is given, compute the $q$-Pascal triangle (i.e.~using $q$-binomial coefficients). Variant: Also available is \fun{GEN}{matpascal}{GEN x}. pari-2.7.5/src/functions/linear_algebra/matqr0000644000175000017500000000165512314242551017711 0ustar billbillFunction: matqr Section: linear_algebra C-Name: matqr Prototype: GD0,L,p Help: 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). Doc: returns $[Q,R]$, the \idx{QR-decomposition} of the square invertible matrix $M$ with real entries: $Q$ is orthogonal and $R$ upper triangular. If $\fl=1$, the orthogonal matrix is returned as a sequence of Householder transforms: applying such a sequence is stabler and faster than multiplication by the corresponding $Q$ matrix.\sidx{Householder transform} More precisely, if \bprog [Q,R] = matqr(M); [q,r] = matqr(M, 1); @eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is $R$; furthermore \bprog mathouseholder(q, matid(#M)) == Q~ @eprog\noindent the inverse of $Q$. This function raises an error if the precision is too low or $x$ is singular. pari-2.7.5/src/functions/linear_algebra/matrixqz0000644000175000017500000000274512314242551020445 0ustar billbillFunction: matrixqz Section: linear_algebra C-Name: matrixqz0 Prototype: GDG Help: 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. Doc: $A$ being an $m\times n$ matrix in $M_{m,n}(\Q)$, let $\text{Im}_\Q A$ (resp.~$\text{Im}_\Z A$) the $\Q$-vector space (resp.~the $\Z$-module) spanned by the columns of $A$. This function has varying behavior depending on the sign of $p$: If $p \geq 0$, $A$ is assumed to have maximal rank $n\leq m$. The function returns a matrix $B\in M_{m,n}(\Z)$, with $\text{Im}_\Q B = \text{Im}_\Q A$, such that the GCD of all its $n\times n$ minors is coprime to $p$; in particular, if $p = 0$ (default), this GCD is $1$. \bprog ? minors(x) = vector(#x[,1], i, matdet(x[^i,])); ? A = [3,1/7; 5,3/7; 7,5/7]; minors(A) %1 = [4/7, 8/7, 4/7] \\ determinants of all 2x2 minors ? B = matrixqz(A) %2 = [3 1] [5 2] [7 3] ? minors(%) %3 = [1, 2, 1] \\ B integral with coprime minors @eprog If $p=-1$, returns the HNF basis of the lattice $\Z^n \cap \text{Im}_\Z A$. If $p=-2$, returns the HNF basis of the lattice $\Z^n \cap \text{Im}_\Q A$. \bprog ? matrixqz(A,-1) %4 = [8 5] [4 3] [0 1] ? matrixqz(A,-2) %5 = [2 -1] [1 0] [0 1] @eprog pari-2.7.5/src/functions/linear_algebra/seralgdep0000644000175000017500000000146412366172547020547 0ustar billbillFunction: seralgdep Section: linear_algebra C-Name: seralgdep Prototype: GLL Help: seralgdep(s,p,r): find a linear relation between powers (1,s, ..., s^p) of the series s, with polynomial coefficients of degree <= r. Doc: \sidx{algebraic dependence} finds a linear relation between powers $(1,s, \dots, s^p)$ of the series $s$, with polynomial coefficients of degree $\leq r$. In case no relation is found, return $0$. \bprog ? s = 1 + 10*y - 46*y^2 + 460*y^3 - 5658*y^4 + 77740*y^5 + O(y^6); ? seralgdep(s, 2, 2) %2 = -x^2 + (8*y^2 + 20*y + 1) ? subst(%, x, s) %3 = O(y^6) ? seralgdep(s, 1, 3) %4 = (-77*y^2 - 20*y - 1)*x + (310*y^3 + 231*y^2 + 30*y + 1) ? seralgdep(s, 1, 2) %5 = 0 @eprog\noindent The series main variable must not be $x$, so as to be able to express the result as a polynomial in $x$. pari-2.7.5/src/functions/linear_algebra/mathnfmodid0000644000175000017500000000117412366172547021071 0ustar billbillFunction: mathnfmodid Section: linear_algebra C-Name: hnfmodid Prototype: GG Help: mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d) Doc: outputs the (upper triangular) \idx{Hermite normal form} of $x$ concatenated with the diagonal matrix with diagonal $d$. Assumes that $x$ has integer entries. Variant: if $d$ is an integer instead of a vector, concatenate $d$ times the identity matrix. \bprog ? m=[0,7;-1,0;-1,-1] %1 = [ 0 7] [-1 0] [-1 -1] ? mathnfmodid(m, [6,2,2]) %2 = [2 1 1] [0 1 0] [0 0 1] ? mathnfmodid(m, 10) %3 = [10 7 3] [ 0 1 0] [ 0 0 1] @eprog pari-2.7.5/src/functions/linear_algebra/qfbil0000644000175000017500000000171212366172547017672 0ustar billbillFunction: qfbil Section: linear_algebra C-Name: qfbil Prototype: GGDG Help: qfbil(x,y,{q}): evaluate the bilinear form q (symmetric matrix) at (x,y); if q omitted, use the standard Euclidean scalar product. Doc: evaluate the bilinear form $q$ (symmetric matrix) at the vectors $(x,y)$; if $q$ omitted, use the standard Euclidean scalar product, corresponding to the identity matrix. Roughly equivalent to \kbd{x\til * q * y}, but a little faster and more convenient (does not distinguish between column and row vectors): \bprog ? x = [1,2,3]~; y = [-1,0,1]~; qfbil(x,y) %1 = 2 ? q = [1,2,3;2,2,-1;3,-1,0]; qfbil(x,y, q) %2 = -13 ? for(i=1,10^6, qfbil(x,y,q)) %3 = 568ms ? for(i=1,10^6, x~*q*y) %4 = 717ms @eprog\noindent The associated quadratic form is also available, as \tet{qfnorm}, slightly faster: \bprog ? for(i=1,10^6, qfnorm(x,q)) time = 444ms ? for(i=1,10^6, qfnorm(x)) time = 176 ms. ? for(i=1,10^6, qfbil(x,y)) time = 208 ms. @eprog pari-2.7.5/src/functions/linear_algebra/norml20000644000175000017500000000153212366172547020006 0ustar billbillFunction: norml2 Section: linear_algebra C-Name: gnorml2 Prototype: G Help: norml2(x): square of the L2-norm of x. Doc: square of the $L^2$-norm of $x$. More precisely, if $x$ is a scalar, $\kbd{norml2}(x)$ is defined to be the square of the complex modulus of $x$ (real \typ{QUAD}s are not supported). If $x$ is a polynomial, a (row or column) vector or a matrix, \kbd{norml2($x$)} is defined recursively as $\sum_i \kbd{norml2}(x_i)$, where $(x_i)$ run through the components of $x$. In particular, this yields the usual $\sum |x_i|^2$ (resp.~$\sum |x_{i,j}|^2$) if $x$ is a polynomial or vector (resp.~matrix) with complex components. \bprog ? norml2( [ 1, 2, 3 ] ) \\ vector %1 = 14 ? norml2( [ 1, 2; 3, 4] ) \\ matrix %2 = 30 ? norml2( 2*I + x ) %3 = 5 ? norml2( [ [1,2], [3,4], 5, 6 ] ) \\ recursively defined %4 = 91 @eprog pari-2.7.5/src/functions/linear_algebra/setbinop0000644000175000017500000000117212314242551020402 0ustar billbillFunction: setbinop Section: linear_algebra C-Name: setbinop Prototype: GGDG Help: 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. Doc: the set whose elements are the f(x,y), where x,y run through X,Y. respectively. If $Y$ is omitted, assume that $X = Y$ and that $f$ is symmetric: $f(x,y) = f(y,x)$ for all $x,y$ in $X$. \bprog ? X = [1,2,3]; Y = [2,3,4]; ? setbinop((x,y)->x+y, X,Y) \\ set X + Y %2 = [3, 4, 5, 6, 7] ? setbinop((x,y)->x-y, X,Y) \\ set X - Y %3 = [-3, -2, -1, 0, 1] ? setbinop((x,y)->x+y, X) \\ set 2X = X + X %2 = [2, 3, 4, 5, 6] @eprog pari-2.7.5/src/functions/linear_algebra/vecextract0000644000175000017500000000541012314242551020726 0ustar billbillFunction: vecextract Section: linear_algebra C-Name: extract0 Prototype: GGDG Description: (vec,gen,?gen):vec extract0($1, $2, $3) Help: 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.). Doc: extraction of components of the vector or matrix $x$ according to $y$. In case $x$ is a matrix, its components are the \emph{columns} of $x$. The parameter $y$ is a component specifier, which is either an integer, a string describing a range, or a vector. If $y$ is an integer, it is considered as a mask: the binary bits of $y$ are read from right to left, but correspond to taking the components from left to right. For example, if $y=13=(1101)_2$ then the components 1,3 and 4 are extracted. If $y$ is a vector (\typ{VEC}, \typ{COL} or \typ{VECSMALL}), which must have integer entries, these entries correspond to the component numbers to be extracted, in the order specified. If $y$ is a string, it can be \item a single (non-zero) index giving a component number (a negative index means we start counting from the end). \item a range of the form \kbd{"$a$..$b$"}, where $a$ and $b$ are indexes as above. Any of $a$ and $b$ can be omitted; in this case, we take as default values $a = 1$ and $b = -1$, i.e.~ the first and last components respectively. We then extract all components in the interval $[a,b]$, in reverse order if $b < a$. In addition, if the first character in the string is \kbd{\pow}, the complement of the given set of indices is taken. If $z$ is not omitted, $x$ must be a matrix. $y$ is then the \emph{row} specifier, and $z$ the \emph{column} specifier, where the component specifier is as explained above. \bprog ? v = [a, b, c, d, e]; ? vecextract(v, 5) \\@com mask %1 = [a, c] ? vecextract(v, [4, 2, 1]) \\@com component list %2 = [d, b, a] ? vecextract(v, "2..4") \\@com interval %3 = [b, c, d] ? vecextract(v, "-1..-3") \\@com interval + reverse order %4 = [e, d, c] ? vecextract(v, "^2") \\@com complement %5 = [a, c, d, e] ? vecextract(matid(3), "2..", "..") %6 = [0 1 0] [0 0 1] @eprog The range notations \kbd{v[i..j]} and \kbd{v[\pow i]} (for \typ{VEC} or \typ{COL}) and \kbd{M[i..j, k..l]} and friends (for \typ{MAT}) implement a subset of the above, in a simpler and \emph{faster} way, hence should be preferred in most common situations. The following features are not implemented in the range notation: \item reverse order, \item omitting either $a$ or $b$ in \kbd{$a$..$b$}. pari-2.7.5/src/functions/linear_algebra/qfgaussred0000644000175000017500000000177611636712103020736 0ustar billbillFunction: qfgaussred Section: linear_algebra C-Name: qfgaussred Prototype: G Help: 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). Doc: \idx{decomposition into squares} of the quadratic form represented by the symmetric matrix $q$. The result is a matrix whose diagonal entries are the coefficients of the squares, and the off-diagonal entries on each line represent the bilinear forms. More precisely, if $(a_{ij})$ denotes the output, one has $$ q(x) = \sum_i a_{ii} (x_i + \sum_{j \neq i} a_{ij} x_j)^2 $$ \bprog ? qfgaussred([0,1;1,0]) %1 = [1/2 1] [-1 -1/2] @eprog\noindent This means that $2xy = (1/2)(x+y)^2 - (1/2)(x-y)^2$. Variant: \fun{GEN}{qfgaussred_positive}{GEN q} assumes that $q$ is positive definite and is a little faster; returns \kbd{NULL} if a vector with negative norm occurs (non positive matrix or too many rounding errors). pari-2.7.5/src/functions/linear_algebra/qfautoexport0000644000175000017500000000141712366172547021340 0ustar billbillFunction: qfautoexport Section: linear_algebra C-Name: qfautoexport Prototype: GD0,L, Help: 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). Doc: \var{qfa} being an automorphism group as output by \tet{qfauto}, export the underlying matrix group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example computes the size of the matrix group using GAP: \bprog ? G = qfauto([2,1;1,2]) %1 = [12, [[-1, 0; 0, -1], [0, -1; 1, 1], [1, 1; 0, -1]]] ? s = qfautoexport(G) %2 = "Group([[-1, 0], [0, -1]], [[0, -1], [1, 1]], [[1, 1], [0, -1]])" ? extern("echo \"Order("s");\" | gap -q") %3 = 12 @eprog pari-2.7.5/src/functions/linear_algebra/mathilbert0000644000175000017500000000040711636712103020713 0ustar billbillFunction: mathilbert Section: linear_algebra C-Name: mathilbert Prototype: L Help: mathilbert(n): Hilbert matrix of order n. Doc: $x$ being a \kbd{long}, creates the \idx{Hilbert matrix}of order $x$, i.e.~the matrix whose coefficient ($i$,$j$) is $1/ (i+j-1)$. pari-2.7.5/src/functions/linear_algebra/matdetint0000644000175000017500000000202412314242551020545 0ustar billbillFunction: matdetint Section: linear_algebra C-Name: detint Prototype: G Help: 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. Doc: Let $B$ be an $m\times n$ matrix with integer coefficients. The \emph{determinant} $D$ of the lattice generated by the columns of $B$ is the square root of $\det(B^T B)$ if $B$ has maximal rank $m$, and $0$ otherwise. This function uses the Gauss-Bareiss algorithm to compute a positive \emph{multiple} of $D$. When $B$ is square, the function actually returns $D = |\det B|$. This function is useful in conjunction with \kbd{mathnfmod}, which needs to know such a multiple. If the rank is maximal and the matrix non-square, you can obtain $D$ exactly using \bprog matdet( mathnfmod(B, matdetint(B)) ) @eprog\noindent Note that as soon as one of the dimensions gets large ($m$ or $n$ is larger than 20, say), it will often be much faster to use \kbd{mathnf(B, 1)} or \kbd{mathnf(B, 4)} directly. pari-2.7.5/src/functions/linear_algebra/matindexrank0000644000175000017500000000100711636712103021242 0ustar billbillFunction: matindexrank Section: linear_algebra C-Name: indexrank Prototype: G Help: matindexrank(x): gives two extraction vectors (rows and columns) for the matrix x such that the extracted matrix is square of maximal rank. Doc: $x$ being a matrix of rank $r$, returns a vector with two \typ{VECSMALL} components $y$ and $z$ of length $r$ giving a list of rows and columns respectively (starting from 1) such that the extracted matrix obtained from these two vectors using $\tet{vecextract}(x,y,z)$ is invertible. pari-2.7.5/src/functions/conversions/0000755000175000017500000000000012613365633016265 5ustar billbillpari-2.7.5/src/functions/conversions/length0000644000175000017500000000201311636712103017455 0ustar billbillFunction: length Section: conversions C-Name: glength Prototype: lG Help: length(x): number of non code words in x, number of characters for a string. Description: (vecsmall):lg lg($1) (vec):lg lg($1) (pol):small lgpol($1) (gen):small glength($1) Doc: length of $x$; \kbd{\#}$x$ is a shortcut for \kbd{length}$(x)$. This is mostly useful for \item vectors: dimension (0 for empty vectors), \item lists: number of entries (0 for empty lists), \item matrices: number of columns, \item character strings: number of actual characters (without trailing \kbd{\bs 0}, should you expect it from $C$ \kbd{char*}). \bprog ? #"a string" %1 = 8 ? #[3,2,1] %2 = 3 ? #[] %3 = 0 ? #matrix(2,5) %4 = 5 ? L = List([1,2,3,4]); #L %5 = 4 @eprog The routine is in fact defined for arbitrary GP types, but is awkward and useless in other cases: it returns the number of non-code words in $x$, e.g. the effective length minus 2 for integers since the \typ{INT} type has two code words. pari-2.7.5/src/functions/conversions/round0000644000175000017500000000302711636712103017331 0ustar billbillFunction: round Section: conversions C-Name: round0 Prototype: GD& Help: 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. Description: (small):small:parens $1 (int):int:copy:parens $1 (real):int roundr($1) (mp):int mpround($1) (mp, &small):int grndtoi($1, &$2) (mp, &int):int round0($1, &$2) (gen):gen ground($1) (gen, &small):gen grndtoi($1, &$2) (gen, &int):gen round0($1, &$2) Doc: If $x$ is in $\R$, rounds $x$ to the nearest integer (rounding to $+\infty$ in case of ties), then and sets $e$ to the number of error bits, that is the binary exponent of the difference between the original and the rounded value (the ``fractional part''). If the exponent of $x$ is too large compared to its precision (i.e.~$e>0$), the result is undefined and an error occurs if $e$ was not given. \misctitle{Important remark} Contrary to the other truncation functions, this function operates on every coefficient at every level of a PARI object. For example $$\text{truncate}\left(\dfrac{2.4*X^2-1.7}{X}\right)=2.4*X,$$ whereas $$\text{round}\left(\dfrac{2.4*X^2-1.7}{X}\right)=\dfrac{2*X^2-2}{X}.$$ An important use of \kbd{round} is to get exact results after an approximate computation, when theory tells you that the coefficients must be integers. Variant: Also available are \fun{GEN}{grndtoi}{GEN x, long *e} and \fun{GEN}{ground}{GEN x}. pari-2.7.5/src/functions/conversions/variable0000644000175000017500000000262112366172547020003 0ustar billbillFunction: variable Section: conversions C-Name: gpolvar Prototype: DG Help: 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. Description: (pol):var:parens:copy $var:1 (gen):gen gpolvar($1) Doc: gives the main variable of the object $x$ (the variable with the highest priority used in $x$), and $p$ if $x$ is a $p$-adic number. Return $0$ if $x$ has no variable associated to it. \bprog ? variable(x^2 + y) %1 = x ? variable(1 + O(5^2)) %2 = 5 ? variable([x,y,z,t]) %3 = x ? variable(1) %4 = 0 @eprog\noindent The construction \bprog if (!variable(x),...) @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.) Variant: However, in library mode, this function should not be used for $x$ non-\kbd{NULL}, since \tet{gvar} is more appropriate. Instead, for $x$ a $p$-adic (type \typ{PADIC}), $p$ is $gel(x,2)$; otherwise, use \fun{long}{gvar}{GEN x} which returns the variable number of $x$ if 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. pari-2.7.5/src/functions/conversions/Vecrev0000644000175000017500000000112312366172547017444 0ustar billbillFunction: Vecrev Section: conversions C-Name: gtovecrev0 Prototype: GD0,L, Help: 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. Description: (gen):vec gtovecrev($1) Doc: as $\kbd{Vec}(x, n)$, then reverse the result. In particular In this case, \kbd{Vecrev} is the reciprocal function of \kbd{Polrev}: the coefficients of the vector start with the constant coefficient of the polynomial and the others follow by increasing degree. Variant: \fun{GEN}{gtovecrev}{GEN x} is also available. pari-2.7.5/src/functions/conversions/bitneg0000644000175000017500000000114512314242551017450 0ustar billbillFunction: bitneg Section: conversions C-Name: gbitneg Prototype: GD-1,L, Help: bitneg(x,{n=-1}): bitwise negation of an integers x truncated to n bits. n=-1 means represent infinite sequences of bit 1 as negative numbers. Negative numbers behave as if modulo big power of 2. Doc: \idx{bitwise negation} of an integer $x$, truncated to $n$ bits, $n\geq 0$, that is the integer $$\sum_{i=0}^{n-1} \kbd{not}(x_i) 2^i.$$ The special case $n=-1$ means no truncation: an infinite sequence of leading $1$ is then represented as a negative number. See \secref{se:bitand} for the behavior for negative arguments. pari-2.7.5/src/functions/conversions/sizebyte0000644000175000017500000000052711636712103020042 0ustar billbillFunction: sizebyte Section: conversions C-Name: gsizebyte Prototype: lG Help: sizebyte(x): number of bytes occupied by the complete tree of the object x. Doc: outputs the total number of bytes occupied by the tree representing the PARI object $x$. Variant: Also available is \fun{long}{gsizeword}{GEN x} returning a number of \emph{words}. pari-2.7.5/src/functions/conversions/frac0000644000175000017500000000033411636712103017113 0ustar billbillFunction: frac Section: conversions C-Name: gfrac Prototype: G Help: frac(x): fractional part of x = x-floor(x). Doc: fractional part of $x$. Identical to $x-\text{floor}(x)$. If $x$ is real, the result is in $[0,1[$. pari-2.7.5/src/functions/conversions/Vec0000644000175000017500000000303012314242551016710 0ustar billbillFunction: Vec Section: conversions C-Name: gtovec0 Prototype: GD0,L, Help: Vec(x, {n}): transforms the object x into a vector of dimension n. Description: (gen):vec gtovec($1) Doc: transforms the object $x$ into a row vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form (in which case the resulting vector is simply the initial object considered as a row vector), \item a polynomial or a power series. In the case of a polynomial, the coefficients of the vector start with the leading coefficient of the polynomial, while for power series only the significant coefficients are taken into account, but this time by increasing order of degree. In this last case, \kbd{Vec} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively, \item a matrix: return the vector of columns comprising the matrix. \item a character string: return the vector of individual characters. \item an error context (\typ{ERROR}): return the error components, see \tet{iferr}. In the last three cases (matrix, character string, error), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. Variant: \fun{GEN}{gtovec}{GEN x} is also available. pari-2.7.5/src/functions/conversions/padicprec0000644000175000017500000000056111636712103020134 0ustar billbillFunction: padicprec Section: conversions C-Name: padicprec Prototype: lGG Help: padicprec(x,p): absolute p-adic precision of object x. Doc: absolute $p$-adic precision of the object $x$. This is the minimum precision of the components of $x$. 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. pari-2.7.5/src/functions/conversions/valuation0000644000175000017500000000167112405547147020220 0ustar billbillFunction: valuation Section: conversions C-Name: gvaluation Prototype: lGG Help: valuation(x,p): valuation of x with respect to p. Doc: computes the highest exponent of $p$ dividing $x$. If $p$ is of type integer, $x$ must be an integer, an intmod whose modulus is divisible by $p$, a fraction, a $q$-adic number with $q=p$, or a polynomial or power series in which case the valuation is the minimum of the valuation of the coefficients. If $p$ is of type polynomial, $x$ must be of type polynomial or rational 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 $p$-adic numbers or power series, the result is the exponent of the zero. Any other type combinations gives an error. pari-2.7.5/src/functions/conversions/real0000644000175000017500000000036411636712103017126 0ustar billbillFunction: real Section: conversions C-Name: greal Prototype: G Help: real(x): real part of x. Doc: real part of $x$. In the case where $x$ is a quadratic number, this is the coefficient of $1$ in the ``canonical'' integral basis $(1,\omega)$. pari-2.7.5/src/functions/conversions/Mat0000644000175000017500000000163411636712103016725 0ustar billbillFunction: Mat Section: conversions C-Name: gtomat Prototype: DG Help: Mat({x=[]}): transforms any GEN x into a matrix. Empty matrix if x is omitted. Doc: transforms the object $x$ into a matrix. If $x$ is already a matrix, a copy of $x$ is created. If $x$ is a row (resp. column) vector, this creates a 1-row (resp. 1-column) matrix, \emph{unless} all elements are column (resp.~row) vectors of the same length, in which case the vectors are concatenated sideways and the associated big matrix is returned. If $x$ is a binary quadratic form, creates the associated $2\times 2$ matrix. Otherwise, this creates a $1\times 1$ matrix containing $x$. \bprog ? Mat(x + 1) %1 = [x + 1] ? Vec( matid(3) ) %2 = [[1, 0, 0]~, [0, 1, 0]~, [0, 0, 1]~] ? Mat(%) %3 = [1 0 0] [0 1 0] [0 0 1] ? Col( [1,2; 3,4] ) %4 = [[1, 2], [3, 4]]~ ? Mat(%) %5 = [1 2] [3 4] ? Mat(Qfb(1,2,3)) %6 = [1 1] [1 3] @eprog pari-2.7.5/src/functions/conversions/floor0000644000175000017500000000100211636712103017312 0ustar billbillFunction: floor Section: conversions C-Name: gfloor Prototype: G Help: floor(x): floor of x = largest integer <= x. Description: (small):small:parens $1 (int):int:copy:parens $1 (real):int floorr($1) (mp):int mpfloor($1) (gen):gen gfloor($1) Doc: floor of $x$. When $x$ is in $\R$, the result is the largest integer smaller than or equal to $x$. Applied to a rational function, $\kbd{floor}(x)$ returns the Euclidean quotient of the numerator by the denominator. pari-2.7.5/src/functions/conversions/bitand0000644000175000017500000000156311636712103017446 0ustar billbillFunction: bitand Section: conversions C-Name: gbitand Prototype: GG Help: bitand(x,y): bitwise "and" of two integers x and y. Negative numbers behave as if modulo big power of 2. Description: (small, small):small:parens $(1)&$(2) (gen, gen):int gbitand($1, $2) Doc: bitwise \tet{and} \sidx{bitwise and}of two integers $x$ and $y$, that is the integer $$\sum_i (x_i~\kbd{and}~y_i) 2^i$$ Negative numbers behave $2$-adically, i.e.~the result is the $2$-adic limit of \kbd{bitand}$(x_n,y_n)$, where $x_n$ and $y_n$ are non-negative integers tending to $x$ and $y$ respectively. (The result is an ordinary integer, possibly negative.) \bprog ? bitand(5, 3) %1 = 1 ? bitand(-5, 3) %2 = 3 ? bitand(-5, -3) %3 = -7 @eprog Variant: Also available is \fun{GEN}{ibitand}{GEN x, GEN y}, which returns the bitwise \emph{and} of $|x|$ and $|y|$, two integers. pari-2.7.5/src/functions/conversions/numerator0000644000175000017500000000163211636712103020216 0ustar billbillFunction: numerator Section: conversions C-Name: numer Prototype: G Help: numerator(x): numerator of x. Doc: numerator of $x$. The meaning of this is clear when $x$ is a rational number or function. If $x$ is an integer or a polynomial, it is treated as a rational number or function, respectively, and the result is $x$ itself. For polynomials, you probably want to use \bprog numerator( content(x) ) @eprog\noindent instead. In other cases, \kbd{numerator(x)} is defined to be \kbd{denominator(x)*x}. This is the case when $x$ is a vector or a matrix, but also for \typ{COMPLEX} or \typ{QUAD}. In particular since a \typ{PADIC} or \typ{INTMOD} has denominator $1$, its numerator is itself. \misctitle{Warning} Multivariate objects are created according to variable priorities, with possibly surprising side effects ($x/y$ is a polynomial, but $y/x$ is a rational function). See \secref{se:priority}. pari-2.7.5/src/functions/conversions/liftint0000644000175000017500000000142112366172547017664 0ustar billbillFunction: liftint Section: conversions C-Name: liftint Prototype: G Help: liftint(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Description: (pol):pol liftint($1) (vec):vec liftint($1) (gen):gen liftint($1) Doc: recursively lift all components of $x$ from $\Z/n\Z$ to $\Z$ and from $\Q_p$ to $\Q$ (as \tet{truncate}). \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(liftint,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? liftint(x * (1 + O(3)) + Mod(2,3)) %1 = x + 2 ? liftint(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2)) %2 = Mod(y, y^2 + 1)*x + Mod(Mod(2*z, z^2), y^2 + 1) @eprog pari-2.7.5/src/functions/conversions/characteristic0000644000175000017500000000073512366172547021212 0ustar billbillFunction: characteristic Section: conversions C-Name: characteristic Prototype: mG Help: characteristic(x): characteristic of the base ring over which x is defined Doc: returns the characteristic of the base ring over which $x$ is defined (as defined by \typ{INTMOD} and \typ{FFELT} components). The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. \bprog ? characteristic(Mod(1,24)*x + Mod(1,18)*y) %1 = 6 @eprog pari-2.7.5/src/functions/conversions/bitnegimply0000644000175000017500000000130211636712103020517 0ustar billbillFunction: bitnegimply Section: conversions C-Name: gbitnegimply Prototype: GG Help: bitnegimply(x,y): bitwise "negated imply" of two integers x and y, in other words, x BITAND BITNEG(y). Negative numbers behave as if modulo big power of 2. Description: (small, small):small:parens $(1)&~$(2) (gen, gen):int gbitnegimply($1, $2) Doc: bitwise negated imply of two integers $x$ and $y$ (or \kbd{not} $(x \Rightarrow y)$), that is the integer $$\sum (x_i~\kbd{and not}(y_i)) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. Variant: Also available is \fun{GEN}{ibitnegimply}{GEN x, GEN y}, which returns the bitwise negated imply of $|x|$ and $|y|$, two integers. pari-2.7.5/src/functions/conversions/Pol0000644000175000017500000000335412314242551016736 0ustar billbillFunction: Pol Section: conversions C-Name: gtopoly Prototype: GDn Description: (gen,?var):pol gtopoly($1, $2) Help: Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient. Doc: transforms the object $t$ into a polynomial with main variable $v$. If $t$ is a scalar, this gives a constant polynomial. If $t$ is a power series with non-negative valuation or a rational function, the effect is similar to \kbd{truncate}, i.e.~we chop off the $O(X^k)$ or compute the Euclidean quotient of the numerator by the denominator, then change the main variable of the result to $v$. The main use of this function is when $t$ is a vector: it creates the polynomial whose coefficients are given by $t$, with $t[1]$ being the leading coefficient (which can be zero). It is much faster to evaluate \kbd{Pol} on a vector of coefficients in this way, than the corresponding formal expression $a_n X^n + \dots + a_0$, which is evaluated naively exactly as written (linear versus quadratic time in $n$). \tet{Polrev} can be used if one wants $x[1]$ to be the constant coefficient: \bprog ? Pol([1,2,3]) %1 = x^2 + 2*x + 3 ? Polrev([1,2,3]) %2 = 3*x^2 + 2*x + 1 @eprog\noindent The reciprocal function of \kbd{Pol} (resp.~\kbd{Polrev}) is \kbd{Vec} (resp.~ \kbd{Vecrev}). \bprog ? Vec(Pol([1,2,3])) %1 = [1, 2, 3] ? Vecrev( Polrev([1,2,3]) ) %2 = [1, 2, 3] @eprog\noindent \misctitle{Warning} This is \emph{not} a substitution function. It will not transform an object containing variables of higher priority than~$v$. \bprog ? Pol(x + y, y) *** at top-level: Pol(x+y,y) *** ^---------- *** Pol: variable must have higher priority in gtopoly. @eprog pari-2.7.5/src/functions/conversions/bittest0000644000175000017500000000163312314242551017660 0ustar billbillFunction: bittest Section: conversions C-Name: gbittest Prototype: GL Help: 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. Description: (small, small):bool:parens ($(1)>>$(2))&1 (int, small):bool bittest($1, $2) (gen, small):gen gbittest($1, $2) Doc: outputs the $n^{\text{th}}$ bit of $x$ starting from the right (i.e.~the coefficient of $2^n$ in the binary expansion of $x$). The result is 0 or 1. \bprog ? bittest(7, 3) %1 = 1 \\ the 3rd bit is 1 ? bittest(7, 4) %2 = 0 \\ the 4th bit is 0 @eprog\noindent See \secref{se:bitand} for the behavior at negative arguments. Variant: For a \typ{INT} $x$, the variant \fun{long}{bittest}{GEN x, long n} is generally easier to use, and if furthermore $n\ge 0$ the low-level function \fun{ulong}{int_bit}{GEN x, long n} returns \kbd{bittest(abs(x),n)}. pari-2.7.5/src/functions/conversions/sizedigit0000644000175000017500000000053611636712103020177 0ustar billbillFunction: sizedigit Section: conversions C-Name: sizedigit Prototype: lG Help: sizedigit(x): maximum number of decimal digits minus one of (the coefficients of) x. 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. pari-2.7.5/src/functions/conversions/binary0000644000175000017500000000056211636712103017467 0ustar billbillFunction: binary Section: conversions C-Name: binaire Prototype: G Help: binary(x): gives the vector formed by the binary digits of x (x integer). Doc: outputs the vector of the binary digits of $|x|$. Here $x$ can be an integer, a real number (in which case the result has two components, one for the integer part, one for the fractional part) or a vector/matrix. pari-2.7.5/src/functions/conversions/Qfb0000644000175000017500000000115411636712103016711 0ustar billbillFunction: Qfb Section: conversions C-Name: Qfb0 Prototype: GGGDGp Help: 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. Doc: creates the binary quadratic form\sidx{binary quadratic form} $ax^2+bxy+cy^2$. If $b^2-4ac>0$, initialize \idx{Shanks}' distance function to $D$. Negative definite forms are not implemented, use their positive definite counterpart instead. Variant: Also available are \fun{GEN}{qfi}{GEN a, GEN b, GEN c} (assumes $b^2-4ac<0$) and \fun{GEN}{qfr}{GEN a, GEN b, GEN c, GEN D} (assumes $b^2-4ac>0$). pari-2.7.5/src/functions/conversions/precision0000644000175000017500000000556112314242551020201 0ustar billbillFunction: precision Section: conversions C-Name: precision0 Prototype: GD0,L, Help: precision(x,{n}): if n is present, return x at precision n. If n is omitted, return real precision of object x. Description: (real):small prec2ndec(gprecision($1)) (gen):int precision0($1, 0) (real,0):small prec2ndec(gprecision($1)) (gen,0):int precision0($1, 0) (real,#small):real rtor($1, ndec2prec($2)) (gen,#small):gen gprec($1, $2) (real,small):real precision0($1, $2) (gen,small):gen precision0($1, $2) Doc: the function has two different behaviors according to whether $n$ is present or not. If $n$ is missing, the function returns the precision in decimal digits of the PARI object $x$. If $x$ is an exact object, the largest single precision integer is returned. \bprog ? precision(exp(1e-100)) %1 = 134 \\ 134 significant decimal digits ? precision(2 + x) %2 = 2147483647 \\ exact object ? precision(0.5 + O(x)) %3 = 28 \\ floating point accuracy, NOT series precision ? precision( [ exp(1e-100), 0.5 ] ) %4 = 28 \\ minimal accuracy among components @eprog\noindent The return value for exact objects is meaningless since it is not even the same on 32 and 64-bit machines. The proper way to test whether an object is exact is \bprog ? isexact(x) = precision(x) == precision(0) @eprog If $n$ is present, the function creates a new object equal to $x$ with a new ``precision'' $n$. (This never changes the type of the result. In particular it is not possible to use it to obtain a polynomial from a power series; for that, see \tet{truncate}.) Now the meaning of precision is different from the above (floating point accuracy), and depends on the type of $x$: For exact types, no change. For $x$ a vector or a matrix, the operation is done componentwise. For real $x$, $n$ is the number of desired significant \emph{decimal} digits. If $n$ is smaller than the precision of $x$, $x$ is truncated, otherwise $x$ is extended with zeros. For $x$ a $p$-adic or a power series, $n$ is the desired number of \emph{significant} $p$-adic or $X$-adic digits, where $X$ is the main variable of $x$. (Note: yes, this is inconsistent.) Note that the precision is a priori distinct from the exponent $k$ appearing in $O(*^k)$; it is indeed equal to $k$ if and only if $x$ is a $p$-adic or $X$-adic \emph{unit}. \bprog ? precision(1 + O(x), 10) %1 = 1 + O(x^10) ? precision(x^2 + O(x^10), 3) %2 = x^2 + O(x^5) ? precision(7^2 + O(7^10), 3) %3 = 7^2 + O(7^5) @eprog\noindent For the last two examples, note that $x^2 + O(x^5) = x^2(1 + O(x^3))$ indeed has 3 significant coefficients Variant: Also available are \fun{GEN}{gprec}{GEN x, long n} and \fun{long}{precision}{GEN x}. In both, the accuracy is expressed in \emph{words} (32-bit or 64-bit depending on the architecture). pari-2.7.5/src/functions/conversions/lift0000644000175000017500000000361612366172547017161 0ustar billbillFunction: lift Section: conversions C-Name: lift0 Prototype: GDn Help: 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. Description: (pol):pol lift($1) (vec):vec lift($1) (gen):gen lift($1) (pol, var):pol lift0($1, $2) (vec, var):vec lift0($1, $2) (gen, var):gen lift0($1, $2) Doc: if $v$ is omitted, lifts intmods from $\Z/n\Z$ in $\Z$, $p$-adics from $\Q_p$ to $\Q$ (as \tet{truncate}), and polmods to polynomials. Otherwise, lifts only polmods whose modulus has main variable~$v$. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(lift,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? lift(Mod(5,3)) %1 = 2 ? lift(3 + O(3^9)) %2 = 3 ? lift(Mod(x,x^2+1)) %3 = x ? lift(Mod(x,x^2+1)) %4 = x @eprog Lifts are performed recursively on an object components, but only by \emph{one level}: once a \typ{POLMOD} is lifted, the components of the result are \emph{not} lifted further. \bprog ? lift(x * Mod(1,3) + Mod(2,3)) %4 = x + 2 ? lift(x * Mod(y,y^2+1) + Mod(2,3)) %5 = y*x + Mod(2, 3) \\@com do you understand this one? ? lift(x * Mod(y,y^2+1) + Mod(2,3), 'x) %6 = Mod(y, y^2 + 1)*x + Mod(Mod(2, 3), y^2 + 1) ? lift(%, y) %7 = y*x + Mod(2, 3) @eprog\noindent To recursively lift all components not only by one level, but as long as possible, use \kbd{liftall}. To lift only \typ{INTMOD}s and \typ{PADIC}s components, use \tet{liftint}. To lift only \typ{POLMOD}s components, use \tet{liftpol}. Finally, \tet{centerlift} allows to lift \typ{INTMOD}s and \typ{PADIC}s using centered residues (lift of smallest absolute value). Variant: Also available is \fun{GEN}{lift}{GEN x} corresponding to \kbd{lift0(x,-1)}. pari-2.7.5/src/functions/conversions/Colrev0000644000175000017500000000062012366172547017445 0ustar billbillFunction: Colrev Section: conversions C-Name: gtocolrev0 Prototype: GD0,L, Help: 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. Description: (gen):vec gtocolrev($1) Doc: as $\kbd{Col}(x, n)$, then reverse the result. In particular Variant: \fun{GEN}{gtocolrev}{GEN x} is also available. pari-2.7.5/src/functions/conversions/Strexpand0000644000175000017500000000112011636712103020142 0ustar billbillFunction: Strexpand Section: conversions C-Name: Strexpand Prototype: s* Help: Strexpand({x}*): concatenates its (string) argument into a single string, performing tilde expansion. Doc: converts its argument list into a single character string (type \typ{STR}, the empty string if $x$ is omitted). Then perform \idx{environment expansion}, see \secref{se:envir}. This feature can be used to read \idx{environment variable} values. \bprog ? Strexpand("$HOME/doc") %1 = "/home/pari/doc" @eprog The individual arguments are read in string context, see \secref{se:strings}. %\syn{NO} pari-2.7.5/src/functions/conversions/liftall0000644000175000017500000000140512366172547017644 0ustar billbillFunction: liftall Section: conversions C-Name: liftall Prototype: G Help: liftall(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Description: (pol):pol liftall($1) (vec):vec liftall($1) (gen):gen liftall($1) Doc: recursively lift all components of $x$ from $\Z/n\Z$ to $\Z$, from $\Q_p$ to $\Q$ (as \tet{truncate}), and polmods to polynomials. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(liftall,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? liftall(x * (1 + O(3)) + Mod(2,3)) %1 = x + 2 ? liftall(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2)) %2 = y*x + 2*z @eprog pari-2.7.5/src/functions/conversions/truncate0000644000175000017500000000325511636712103020032 0ustar billbillFunction: truncate Section: conversions C-Name: trunc0 Prototype: GD& Help: 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. Description: (small):small:parens $1 (int):int:copy:parens $1 (real):int truncr($1) (mp):int mptrunc($1) (mp, &small):int gcvtoi($1, &$2) (mp, &int):int trunc0($1, &$2) (gen):gen gtrunc($1) (gen, &small):gen gcvtoi($1, &$2) (gen, &int):gen trunc0($1, &$2) Doc: truncates $x$ and sets $e$ to the number of error bits. When $x$ is in $\R$, this means that the part after the decimal point is chopped away, $e$ is the binary exponent of the difference between the original and the truncated value (the ``fractional part''). If the exponent of $x$ is too large compared to its precision (i.e.~$e>0$), the result is undefined and an error occurs if $e$ was not given. The function applies componentwise on vector / matrices; $e$ is then the maximal number of error bits. If $x$ is a rational function, the result is the ``integer part'' (Euclidean quotient of numerator by denominator) and $e$ is not set. Note a very special use of \kbd{truncate}: when applied to a power series, it transforms it into a polynomial or a rational function with denominator a power of $X$, by chopping away the $O(X^k)$. Similarly, when applied to a $p$-adic number, it transforms it into an integer or a rational number by chopping away the $O(p^k)$. Variant: The following functions are also available: \fun{GEN}{gtrunc}{GEN x} and \fun{GEN}{gcvtoi}{GEN x, long *e}. pari-2.7.5/src/functions/conversions/Set0000644000175000017500000000135112366172547016750 0ustar billbillFunction: Set Section: conversions C-Name: gtoset Prototype: DG Help: Set({x=[]}): convert x into a set, i.e. a row vector with strictly increasing coefficients. Empty set if x is omitted. Description: ():vec cgetg(1,t_VEC) (gen):vec gtoset($1) Doc: converts $x$ into a set, i.e.~into a row vector, with strictly increasing entries with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. Standard container types \typ{VEC}, \typ{COL}, \typ{LIST} and \typ{VECSMALL} are converted to the set with corresponding elements. All others are converted to a set with one element. \bprog ? Set([1,2,4,2,1,3]) %1 = [1, 2, 3, 4] ? Set(x) %2 = [x] ? Set(Vecsmall([1,3,2,1,3])) %3 = [1, 2, 3] @eprog pari-2.7.5/src/functions/conversions/Mod0000644000175000017500000000271712413013142016715 0ustar billbillFunction: Mod Section: conversions C-Name: gmodulo Prototype: GG Help: Mod(a,b): creates 'a modulo b'. Description: (small, small):gen gmodulss($1, $2) (small, gen):gen gmodulsg($1, $2) (gen, gen):gen gmodulo($1, $2) Doc: in its basic form, creates an intmod or a polmod $(a \mod b)$; $b$ must be an integer or a polynomial. We then obtain a \typ{INTMOD} and a \typ{POLMOD} respectively: \bprog ? t = Mod(2,17); t^8 %1 = Mod(1, 17) ? t = Mod(x,x^2+1); t^2 %2 = Mod(-1, x^2+1) @eprog\noindent If $a \% b$ makes sense and yields a result of the appropriate type (\typ{INT} or scalar/\typ{POL}), the operation succeeds as well: \bprog ? Mod(1/2, 5) %3 = Mod(3, 5) ? Mod(7 + O(3^6), 3) %4 = Mod(1, 3) ? Mod(Mod(1,12), 9) %5 = Mod(1, 3) ? Mod(1/x, x^2+1) %6 = Mod(-1, x^2+1) ? Mod(exp(x), x^4) %7 = Mod(1/6*x^3 + 1/2*x^2 + x + 1, x^4) @eprog If $a$ is a complex object, ``base change'' it to $\Z/b\Z$ or $K[x]/(b)$, which is equivalent to, but faster than, multiplying it by \kbd{Mod(1,b)}: \bprog ? Mod([1,2;3,4], 2) %8 = [Mod(1, 2) Mod(0, 2)] [Mod(1, 2) Mod(0, 2)] ? Mod(3*x+5, 2) %9 = Mod(1, 2)*x + Mod(1, 2) ? Mod(x^2 + y*x + y^3, y^2+1) %10 = Mod(1, y^2 + 1)*x^2 + Mod(y, y^2 + 1)*x + Mod(-y, y^2 + 1) @eprog This function is not the same as $x$ \kbd{\%} $y$, the result of which has no knowledge of the intended modulus $y$. Compare \bprog ? x = 4 % 5; x + 1 %1 = 5 ? x = Mod(4,5); x + 1 %2 = Mod(0,5) @eprog pari-2.7.5/src/functions/conversions/Strtex0000644000175000017500000000064711636712103017500 0ustar billbillFunction: Strtex Section: conversions C-Name: Strtex Prototype: s* Help: Strtex({x}*): translates its (string) arguments to TeX format and returns the resulting string. Doc: translates its arguments to TeX format, and concatenates the results into a single character string (type \typ{STR}, the empty string if $x$ is omitted). The individual arguments are read in string context, see \secref{se:strings}. %\syn{NO} pari-2.7.5/src/functions/conversions/permtonum0000644000175000017500000000055012314242551020225 0ustar billbillFunction: permtonum Section: conversions C-Name: permtonum Prototype: G Help: permtonum(x): ordinal (between 1 and n!) of permutation x. Doc: given a permutation $x$ on $n$ elements, gives the number $k$ such that $x=\kbd{numtoperm(n,k)}$, i.e.~inverse function of \tet{numtoperm}. The numbering used is the standard lexicographic ordering, starting at $0$. pari-2.7.5/src/functions/conversions/bitor0000644000175000017500000000115011636712103017314 0ustar billbillFunction: bitor Section: conversions C-Name: gbitor Prototype: GG Help: bitor(x,y): bitwise "or" of two integers x and y. Negative numbers behave as if modulo big power of 2. Description: (small, small):small:parens $(1)|$(2) (gen, gen):int gbitor($1, $2) Doc: \sidx{bitwise inclusive or}bitwise (inclusive) \tet{or} of two integers $x$ and $y$, that is the integer $$\sum (x_i~\kbd{or}~y_i) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. Variant: Also available is \fun{GEN}{ibitor}{GEN x, GEN y}, which returns the bitwise \emph{ir} of $|x|$ and $|y|$, two integers. pari-2.7.5/src/functions/conversions/bitxor0000644000175000017500000000117111636712103017507 0ustar billbillFunction: bitxor Section: conversions C-Name: gbitxor Prototype: GG Help: bitxor(x,y): bitwise "exclusive or" of two integers x and y. Negative numbers behave as if modulo big power of 2. Description: (small, small):small:parens $(1)^$(2) (gen, gen):int gbitxor($1, $2) Doc: bitwise (exclusive) \tet{or} \sidx{bitwise exclusive or}of two integers $x$ and $y$, that is the integer $$\sum (x_i~\kbd{xor}~y_i) 2^i$$ See \secref{se:bitand} for the behavior for negative arguments. Variant: Also available is \fun{GEN}{ibitxor}{GEN x, GEN y}, which returns the bitwise \emph{xor} of $|x|$ and $|y|$, two integers. pari-2.7.5/src/functions/conversions/hammingweight0000644000175000017500000000104612314242551021030 0ustar billbillFunction: hammingweight Section: conversions C-Name: hammingweight Prototype: lG Help: hammingweight(x): returns the Hamming weight of x. Doc: 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 \typ{MAT} and the function returns the number of non-zero coefficients of $x$. \bprog ? hammingweight(15) %1 = 4 ? hammingweight(x^100 + 2*x + 1) %2 = 3 ? hammingweight([Mod(1,2), 2, Mod(0,3)]) %3 = 2 ? hammingweight(matid(100)) %4 = 100 @eprog pari-2.7.5/src/functions/conversions/Vecsmall0000644000175000017500000000133112314242551017743 0ustar billbillFunction: Vecsmall Section: conversions C-Name: gtovecsmall0 Prototype: GD0,L, Help: Vecsmall(x, {n}): transforms the object x into a VECSMALL of dimension n. Description: (gen):vecsmall gtovecsmall($1) Doc: transforms the object $x$ into a row vector of type \typ{VECSMALL}. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. This acts as \kbd{Vec}$(x,n)$, but only on a limited set of objects: the result must be representable as a vector of small integers. If $x$ is a character string, a vector of individual characters in ASCII encoding is returned (\tet{Strchr} yields back the character string). Variant: \fun{GEN}{gtovecsmall}{GEN x} is also available. pari-2.7.5/src/functions/conversions/random0000644000175000017500000000650612531362535017474 0ustar billbillFunction: random Section: conversions C-Name: genrand Prototype: DG Help: 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). Description: (?int):int genrand($1) (gen):gen genrand($1) Doc: returns a random element in various natural sets depending on the argument $N$. \item \typ{INT}: returns an integer uniformly distributed between $0$ and $N-1$. Omitting the argument is equivalent to \kbd{random(2\pow31)}. \item \typ{REAL}: returns a real number in $[0,1[$ with the same accuracy as $N$ (whose mantissa has the same number of significant words). \item \typ{INTMOD}: returns a random intmod for the same modulus. \item \typ{FFELT}: returns a random element in the same finite field. \item \typ{VEC} of length $2$, $N = [a,b]$: returns an integer uniformly distributed between $a$ and $b$. \item \typ{VEC} generated by \kbd{ellinit} over a finite field $k$ (coefficients are \typ{INTMOD}s modulo a prime or \typ{FFELT}s): returns a ``random'' $k$-rational \emph{affine} point on the curve. More precisely if the curve has a single point (at infinity!) we return it; otherwise we return an affine point by drawing an abscissa uniformly at random until \tet{ellordinate} succeeds. Note that this is definitely not a uniform distribution over $E(k)$, but it should be good enough for applications. \item \typ{POL} return a random polynomial of degree at most the degree of $N$. The coefficients are drawn by applying \kbd{random} to the leading coefficient of $N$. \bprog ? random(10) %1 = 9 ? random(Mod(0,7)) %2 = Mod(1, 7) ? a = ffgen(ffinit(3,7), 'a); random(a) %3 = a^6 + 2*a^5 + a^4 + a^3 + a^2 + 2*a ? E = ellinit([3,7]*Mod(1,109)); random(E) %4 = [Mod(103, 109), Mod(10, 109)] ? E = ellinit([1,7]*a^0); random(E) %5 = [a^6 + a^5 + 2*a^4 + 2*a^2, 2*a^6 + 2*a^4 + 2*a^3 + a^2 + 2*a] ? random(Mod(1,7)*x^4) %6 = Mod(5, 7)*x^4 + Mod(6, 7)*x^3 + Mod(2, 7)*x^2 + Mod(2, 7)*x + Mod(5, 7) @eprog These variants all depend on a single internal generator, and are independent from your operating system's random number generators. A random seed may be obtained via \tet{getrand}, and reset using \tet{setrand}: from a given seed, and given sequence of \kbd{random}s, the exact same values will be generated. The same seed is used at each startup, reseed the generator yourself if this is a problem. Note that internal functions also call the random number generator; adding such a function call in the middle of your code will change the numbers produced. \misctitle{Technical note} Up to 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 $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 the entire sequence. Variant: Also available: \fun{GEN}{ellrandom}{GEN E} and \fun{GEN}{ffrandom}{GEN a}. pari-2.7.5/src/functions/conversions/conjvec0000644000175000017500000000150611636712103017631 0ustar billbillFunction: conjvec Section: conversions C-Name: conjvec Prototype: Gp Help: conjvec(z): conjugate vector of the algebraic number z. Doc: conjugate vector representation of $z$. If $z$ is a polmod, equal to \kbd{Mod}$(a,T)$, this gives a vector of length $\text{degree}(T)$ containing: \item the complex embeddings of $z$ if $T$ has rational coefficients, i.e.~the $a(r[i])$ where $r = \kbd{polroots}(T)$; \item the conjugates of $z$ if $T$ has some intmod coefficients; \noindent if $z$ is a finite field element, the result is the vector of conjugates $[z,z^p,z^{p^2},\ldots,z^{p^{n-1}}]$ where $n=\text{degree}(T)$. \noindent If $z$ is an integer or a rational number, the result is~$z$. If $z$ is a (row or column) vector, the result is a matrix whose columns are the conjugate vectors of the individual elements of $z$. pari-2.7.5/src/functions/conversions/Strchr0000644000175000017500000000061611636712103017450 0ustar billbillFunction: Strchr Section: conversions C-Name: Strchr Prototype: G Help: Strchr(x): converts x to a string, translating each integer into a character. Doc: converts $x$ to a string, translating each integer into a character. \bprog ? Strchr(97) %1 = "a" ? Vecsmall("hello world") %2 = Vecsmall([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]) ? Strchr(%) %3 = "hello world" @eprog pari-2.7.5/src/functions/conversions/conj0000644000175000017500000000062111636712103017130 0ustar billbillFunction: conj Section: conversions C-Name: gconj Prototype: G Help: conj(x): the algebraic conjugate of x. Doc: conjugate of $x$. The meaning of this is clear, except that for real quadratic numbers, it means conjugation in the real quadratic field. This function has no effect on integers, reals, intmods, fractions or $p$-adics. The only forbidden type is polmod (see \kbd{conjvec} for this). pari-2.7.5/src/functions/conversions/List0000644000175000017500000000125411636712103017115 0ustar billbillFunction: List Section: conversions C-Name: gtolist Prototype: DG Help: List({x=[]}): transforms the vector or list x into a list. Empty list if x is omitted. Description: ():list listcreate() (gen):list gtolist($1) Doc: transforms a (row or column) vector $x$ into a list, whose components are the entries of $x$. Similarly for a list, but rather useless in this case. For other types, creates a list with the single element $x$. Note that, except when $x$ is omitted, this function creates a small memory leak; so, either initialize all lists to the empty list, or use them sparingly. Variant: The variant \fun{GEN}{listcreate}{void} creates an empty list. pari-2.7.5/src/functions/conversions/ceil0000644000175000017500000000100111636712103017104 0ustar billbillFunction: ceil Section: conversions C-Name: gceil Prototype: G Help: ceil(x): ceiling of x = smallest integer >= x. Description: (small):small:parens $1 (int):int:copy:parens $1 (real):int ceilr($1) (mp):int mpceil($1) (gen):gen gceil($1) Doc: ceiling of $x$. When $x$ is in $\R$, the result is the smallest integer greater than or equal to $x$. Applied to a rational function, $\kbd{ceil}(x)$ returns the Euclidean quotient of the numerator by the denominator. pari-2.7.5/src/functions/conversions/Col0000644000175000017500000000302612314242551016715 0ustar billbillFunction: Col Section: conversions C-Name: gtocol0 Prototype: GD0,L, Help: Col(x, {n}): transforms the object x into a column vector of dimension n. Description: (gen):vec gtocol($1) Doc: transforms the object $x$ into a column vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form (in which case the resulting vector is simply the initial object considered as a row vector), \item a polynomial or a power series. In the case of a polynomial, the coefficients of the vector start with the leading coefficient of the polynomial, while for power series only the significant coefficients are taken into account, but this time by increasing order of degree. In this last case, \kbd{Vec} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively, \item a matrix (the column of row vector comprising the matrix is returned), \item a character string (a vector of individual characters is returned). In the last two cases (matrix and character string), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. Note that the function \kbd{Colrev} does not exist, use \kbd{Vecrev}. Variant: \fun{GEN}{gtocol}{GEN x} is also available. pari-2.7.5/src/functions/conversions/liftpol0000644000175000017500000000131512366172547017666 0ustar billbillFunction: liftpol Section: conversions C-Name: liftpol Prototype: G Help: liftpol(x): lifts every polmod component of x to polynomials Description: (pol):pol liftpol($1) (vec):vec liftpol($1) (gen):gen liftpol($1) Doc: recursively lift all components of $x$ which are polmods to polynomials. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(liftpol,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? liftpol(x * (1 + O(3)) + Mod(2,3)) %1 = (1 + O(3))*x + Mod(2, 3) ? liftpol(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2)) %2 = y*x + Mod(2, 3)*z @eprog pari-2.7.5/src/functions/conversions/simplify0000644000175000017500000000176211636712103020042 0ustar billbillFunction: simplify Section: conversions C-Name: simplify Prototype: G Help: simplify(x): simplify the object x as much as possible. Doc: this function simplifies $x$ as much as it can. Specifically, a complex or quadratic number whose imaginary part is the integer 0 (i.e.~not \kbd{Mod(0,2)} or \kbd{0.E-28}) is converted to its real part, and a polynomial of degree $0$ is converted to its constant term. Simplifications occur recursively. This function is especially useful before using arithmetic functions, which expect integer arguments: \bprog ? x = 2 + y - y %1 = 2 ? isprime(x) *** at top-level: isprime(x) *** ^---------- *** isprime: not an integer argument in an arithmetic function ? type(x) %2 = "t_POL" ? type(simplify(x)) %3 = "t_INT" @eprog Note that GP results are simplified as above before they are stored in the history. (Unless you disable automatic simplification with \b{y}, that is.) In particular \bprog ? type(%1) %4 = "t_INT" @eprog pari-2.7.5/src/functions/conversions/imag0000644000175000017500000000036611636712103017122 0ustar billbillFunction: imag Section: conversions C-Name: gimag Prototype: G Help: imag(x): imaginary part of x. Doc: imaginary part of $x$. When $x$ is a quadratic number, this is the coefficient of $\omega$ in the ``canonical'' integral basis $(1,\omega)$. pari-2.7.5/src/functions/conversions/Strprintf0000644000175000017500000000063511636712103020177 0ustar billbillFunction: Strprintf Section: programming/specific C-Name: Strprintf Prototype: ss* Help: Strprintf(fmt,{x}*): returns a string built from the remaining arguments according to the format fmt. Doc: returns a string built from the remaining arguments according to the format fmt. The format consists of ordinary characters (not \%), printed unchanged, and conversions specifications. See \kbd{printf}. %\syn{NO} pari-2.7.5/src/functions/conversions/denominator0000644000175000017500000000212111636712103020513 0ustar billbillFunction: denominator Section: conversions C-Name: denom Prototype: G Help: denominator(x): denominator of x (or lowest common denominator in case of an array). Doc: denominator of $x$. The meaning of this is clear when $x$ is a rational number or function. If $x$ is an integer or a polynomial, it is treated as a rational number or function, respectively, and the result is equal to $1$. For polynomials, you probably want to use \bprog denominator( content(x) ) @eprog\noindent instead. As for modular objects, \typ{INTMOD} and \typ{PADIC} have denominator $1$, and the denominator of a \typ{POLMOD} is the denominator of its (minimal degree) polynomial representative. If $x$ is a recursive structure, for instance a vector or matrix, the lcm of the denominators of its components (a common denominator) is computed. This also applies for \typ{COMPLEX}s and \typ{QUAD}s. \misctitle{Warning} Multivariate objects are created according to variable priorities, with possibly surprising side effects ($x/y$ is a polynomial, but $y/x$ is a rational function). See \secref{se:priority}. pari-2.7.5/src/functions/conversions/Polrev0000644000175000017500000000162212314242551017447 0ustar billbillFunction: Polrev Section: conversions C-Name: gtopolyrev Prototype: GDn Description: (gen,?var):pol gtopolyrev($1, $2) Help: Polrev(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the constant term. Doc: transform the object $t$ into a polynomial with main variable $v$. If $t$ is a scalar, this gives a constant polynomial. If $t$ is a power series, the effect is identical to \kbd{truncate}, i.e.~it chops off the $O(X^k)$. The main use of this function is when $t$ is a vector: it creates the polynomial whose coefficients are given by $t$, with $t[1]$ being the constant term. \tet{Pol} can be used if one wants $t[1]$ to be the leading coefficient: \bprog ? Polrev([1,2,3]) %1 = 3*x^2 + 2*x + 1 ? Pol([1,2,3]) %2 = x^2 + 2*x + 3 @eprog The reciprocal function of \kbd{Pol} (resp.~\kbd{Polrev}) is \kbd{Vec} (resp.~ \kbd{Vecrev}). pari-2.7.5/src/functions/conversions/digits0000644000175000017500000000040312314242551017457 0ustar billbillFunction: digits Section: conversions C-Name: digits Prototype: GDG Help: digits(x,{b=10}): gives the vector formed by the digits of x in base b (x and b integers). Doc: outputs the vector of the digits of $|x|$ in base $b$, where $x$ and $b$ are integers. pari-2.7.5/src/functions/conversions/numtoperm0000644000175000017500000000063312314242551020227 0ustar billbillFunction: numtoperm Section: conversions C-Name: numtoperm Prototype: LG Help: numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer). Doc: generates the $k$-th permutation (as a row vector of length $n$) of the numbers $1$ to $n$. The number $k$ is taken modulo $n!\,$, i.e.~inverse function of \tet{permtonum}. The numbering used is the standard lexicographic ordering, starting at $0$. pari-2.7.5/src/functions/conversions/norm0000644000175000017500000000066111636712103017156 0ustar billbillFunction: norm Section: conversions C-Name: gnorm Prototype: G Help: norm(x): norm of x. Doc: algebraic norm of $x$, i.e.~the product of $x$ with its conjugate (no square roots are taken), or conjugates for polmods. For vectors and matrices, the norm is taken componentwise and hence is not the $L^2$-norm (see \kbd{norml2}). Note that the norm of an element of $\R$ is its square, so as to be compatible with the complex norm. pari-2.7.5/src/functions/conversions/Ser0000644000175000017500000000344212405547147016745 0ustar billbillFunction: Ser Section: conversions C-Name: gtoser Prototype: GDnDP 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 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 ? Ser(1, 'y, 5) %1 = 1 + O(y^5) ? Ser(x^2,, 5) %2 = x^2 + O(x^7) ? T = polcyclo(100) %3 = x^40 - x^30 + x^20 - x^10 + 1 ? Ser(T, 'x, 11) %4 = 1 - x^10 + O(x^11) @eprog\noindent The function is more or less equivalent with multiplication by $1 + O(v^d)$ in theses cases, only faster. If $s$ is a vector, on the other hand, the coefficients of the vector are understood to be the coefficients of the power series starting from the constant term (as in \tet{Polrev}$(x)$), and the precision $d$ is ignored: in other words, in this case, we convert \typ{VEC} / \typ{COL} to the power series whose significant terms are exactly given by the vector entries. Finally, if $s$ is already a power series in $v$, we return it verbatim, ignoring $d$ again. If $d$ significant terms are desired in the last two cases, convert/truncate to \typ{POL} first. \bprog ? v = [1,2,3]; Ser(v, t, 7) %5 = 1 + 2*t + 3*t^2 + O(t^3) \\ 3 terms: 7 is ignored! ? Ser(Polrev(v,t), t, 7) %6 = 1 + 2*t + 3*t^2 + O(t^7) ? s = 1+x+O(x^2); Ser(s, x, 7) %7 = 1 + x + O(x^2) \\ 2 terms: 7 ignored ? Ser(truncate(s), x, 7) %8 = 1 + x + O(x^7) @eprog\noindent The warning given for \kbd{Pol} also applies here: this is not a substitution function. pari-2.7.5/src/functions/conversions/centerlift0000644000175000017500000000200612366172547020352 0ustar billbillFunction: centerlift Section: conversions C-Name: centerlift0 Prototype: GDn Help: centerlift(x,{v}): centered lift of x. Same as lift except for intmod and padic components. Description: (pol):pol centerlift($1) (vec):vec centerlift($1) (gen):gen centerlift($1) (pol, var):pol centerlift0($1, $2) (vec, var):vec centerlift0($1, $2) (gen, var):gen centerlift0($1, $2) Doc: Same as \tet{lift}, except that \typ{INTMOD} and \typ{PADIC} components are lifted using centered residues: \item for a \typ{INTMOD} $x\in \Z/n\Z$, the lift $y$ is such that $-n/2= sizeof(b)) pari_err(e_MISC,"id too long in a stringified flag"); if (!l) /* Garbage after whitespace? */ pari_err(e_MISC,"a stringified flag does not start with an id"); strncpy(b, arg, l); b[l] = 0; arg = e; e = inibuf = buf = b; while (('0' <= *e) && (*e <= '9')) e++; if (*e == 0) pari_err(e_MISC,"numeric id in a stringified flag"); negate = 0; negated = NULL; find: id = tmplate; while ((id = strstr(id, buf)) && id < etmplate) { if (IS_ID(id[l])) { /* We do not allow abbreviations yet */ id += l; /* False positive */ continue; } if ((id >= tmplate + 2) && (IS_ID(id[-1]))) { const char *s = id; if ( !negate && s >= tmplate+3 && ((id[-1] == '_') || (id[-1] == '-')) ) s--; /* Check whether we are preceeded by "no" */ if ( negate /* buf initially started with "no" */ || (s < tmplate+2) || (s[-1] != 'o') || (s[-2] != 'n') || (s >= tmplate+3 && IS_ID(s[-3]))) { id += l; /* False positive */ continue; } /* Found noID in the template! */ id += l; negated = id; continue; /* Try to find without 'no'. */ } /* Found as is */ id += l; break; } if ( !id && !negated && !negate && (l > 2) && buf[0] == 'n' && buf[1] == 'o' ) { /* Try to find the flag without the prefix "no". */ buf += 2; l -= 2; if ((buf[0] == '_') || (buf[0] == '-')) { buf++; l--; } negate = 1; if (buf[0]) goto find; } if (!id && negated) /* Negated and AS_IS forms, prefer AS_IS */ { id = negated; /* Otherwise, use negated form */ negate = 1; } if (!id) pari_err(e_MISC,"Unrecognized id '%s' in a stringified flag", inibuf); if (singleton && !first) pari_err(e_MISC,"Singleton id non-single in a stringified flag"); if (id[0] == '=') { if (negate) pari_err(e_MISC,"Cannot negate id=value in a stringified flag"); if (!first) pari_err(e_MISC,"Assign action should be first in a stringified flag"); action = A_ACTION_ASSIGN; id++; if (id[0] == '=') { singleton = 1; id++; } } else if (id[0] == '^') { if (id[1] != '~') pari_err(e_MISC, "Unrecognized action in a template"); id += 2; if (negate) action = A_ACTION_SET; else action = A_ACTION_UNSET; } else if (id[0] == '|') { id++; if (negate) action = A_ACTION_UNSET; else action = A_ACTION_SET; } e = id; while ((*e >= '0' && *e <= '9')) e++; while (isspace((int)*e)) e++; if (*e && (*e != ';') && (*e != ',')) pari_err(e_MISC, "Non-numeric argument of an action in a template"); numarg = atol(id); /* Now it is safe to get it... */ switch (action) { case A_ACTION_SET: retval |= numarg; break; case A_ACTION_UNSET: retval &= ~numarg; break; case A_ACTION_ASSIGN: retval = numarg; break; default: pari_err(e_MISC,"error in parse_option_string"); } first = 0; while (isspace((int)*arg)) arg++; if (*arg && !(ispunct((int)*arg) && *arg != '-')) pari_err(e_MISC,"Junk after an id in a stringified flag"); /* Skip punctuation */ if (*arg) arg++; } avma=av; return retval; } /*******************************************************************/ /* */ /* SYNTACTICAL ANALYZER FOR GP */ /* */ /*******************************************************************/ GEN readseq(char *t) { pari_sp av = avma; return gerepileupto(av, closure_evalres(pari_compile_str(t,0))); } /* filtered readseq = remove blanks and comments */ GEN gp_read_str(const char *s) { char *t = filtre(s, (compatible == OLDALL)); GEN x = readseq(t); pari_free(t); return x; } GEN compile_str(const char *s) { char *t = filtre(s, (compatible == OLDALL)); GEN x = pari_compile_str(t, 1); pari_free(t); return x; } static long check_proto(const char *code) { long arity = 0; const char *s = code, *old; if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm') s++; while (*s && *s != '\n') switch (*s++) { case '&': case 'C': case 'G': case 'I': case 'J': case 'L': case 'M': case 'P': case 'W': case 'f': case 'n': case 'p': case 'r': case 'x': arity++; break; case 'E': case 's': if (*s == '*') s++; arity++; break; case 'D': if (*s == 'G' || *s == '&' || *s == 'n' || *s == 'I' || *s == 'E' || *s == 'V' || *s == 'P' || *s == 's' || *s == 'r') { if (*s != 'V') arity++; s++; break; } old = s; while (*s && *s != ',') s++; if (*s != ',') pari_err(e_SYNTAX, "missing comma", old, code); break; case 'V': case '=': case ',': break; case '\n': break; /* Before the mnemonic */ case 'm': case 'l': case 'i': case 'v': pari_err(e_SYNTAX, "this code has to come first", s-1, code); default: pari_err(e_SYNTAX, "unknown parser code", s-1, 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) { 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; } entree * install(void *f, const char *name, const char *code) { long hash, arity; entree *ep = is_entry_intern(name, functions_hash, &hash); arity=check_proto(code); if (ep && ep->valence != EpNEW) { if (ep->valence != EpINSTALL) pari_err(e_MISC,"[install] identifier '%s' already in use", name); pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name); if (ep->code) pari_free((void*)ep->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->code = pari_strdup(code); ep->arity=arity; return ep; } /* 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; } void addhelp(const char *e, char *s) { entree *ep = fetch_entry(e, strlen(e)); if (ep->help && !EpSTATIC(ep)) pari_free((void*)ep->help); ep->help = pari_strdup(s); } GEN type0(GEN x) { const char *s = type_name(typ(x)); return strtoGENstr(s); } /*******************************************************************/ /* */ /* PARSER */ /* */ /*******************************************************************/ #ifdef LONG_IS_64BIT static const long MAX_DIGITS = 19; #else static const long MAX_DIGITS = 9; #endif static ulong number(int *n, const char **s) { ulong m = 0; for (*n = 0; *n < MAX_DIGITS && isdigit((int)**s); (*n)++,(*s)++) m = 10*m + (**s - '0'); return m; } ulong u_pow10(int n) { const ulong pw10[] = { 1UL ,10UL ,100UL ,1000UL ,10000UL ,100000UL ,1000000UL ,10000000UL ,100000000UL ,1000000000UL #ifdef LONG_IS_64BIT ,10000000000UL ,100000000000UL ,1000000000000UL ,10000000000000UL ,100000000000000UL ,1000000000000000UL ,10000000000000000UL ,100000000000000000UL ,1000000000000000000UL ,10000000000000000000UL #endif }; return pw10[n]; } static GEN int_read_more(GEN y, const char **ps) { pari_sp av = avma; int i = 0, nb; while (isdigit((int)**ps)) { ulong m = number(&nb, ps); if (avma != av && ++i > 4) { avma = av; i = 0; } /* HACK gerepile */ y = addumului(m, u_pow10(nb), y); } return y; } static long exponent(const char **pts) { const char *s = *pts; long n; int nb; switch(*++s) { case '-': s++; n = -(long)number(&nb, &s); break; case '+': s++; /* Fall through */ default: n = (long)number(&nb, &s); } *pts = s; return n; } static GEN real_0_digits(long n) { long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1); return real_0_bit(b); } static GEN real_read(pari_sp av, const char **s, GEN y, long prec) { long l, n = 0; switch(**s) { default: return y; /* integer */ case '.': { const char *old = ++*s; if (isalpha((int)**s) || **s=='.') { if (**s == 'E' || **s == 'e') { n = exponent(s); if (!signe(y)) { avma = av; return real_0_digits(n); } break; } --*s; return y; /* member */ } y = int_read_more(y, s); n = old - *s; if (**s != 'E' && **s != 'e') { if (!signe(y)) { avma = av; return real_0(prec); } break; } } /* Fall through */ case 'E': case 'e': n += exponent(s); if (!signe(y)) { avma = av; return real_0_digits(n); } } l = nbits2prec(bit_accuracy(lgefint(y))); if (l < prec) l = prec; else prec = l; if (!n) return itor(y, prec); incrprec(l); y = itor(y, l); if (n > 0) y = mulrr(y, rpowuu(10UL, (ulong)n, l)); else y = divrr(y, rpowuu(10UL, (ulong)-n, l)); return gerepileuptoleaf(av, rtor(y, prec)); } static GEN int_read(const char **s) { int nb; GEN y = utoi(number(&nb, s)); if (nb == MAX_DIGITS) y = int_read_more(y, s); return y; } GEN strtoi(const char *s) { return int_read(&s); } GEN strtor(const char *s, long prec) { pari_sp av = avma; GEN y = int_read(&s); y = real_read(av, &s, y, prec); if (typ(y) == t_REAL) return y; return gerepileuptoleaf(av, itor(y, prec)); } static void skipdigits(char **lex) { while (isdigit((int)**lex)) ++*lex; } static int skipexponent(char **lex) { char *old=*lex; if ((**lex=='e' || **lex=='E')) { ++*lex; if ( **lex=='+' || **lex=='-' ) ++*lex; if (!isdigit((int)**lex)) { *lex=old; return KINTEGER; } skipdigits(lex); return KREAL; } return KINTEGER; } static int skipconstante(char **lex) { skipdigits(lex); if (**lex=='.') { char *old = ++*lex; if (**lex == '.') { --*lex; return KINTEGER; } if (isalpha((int)**lex)) { skipexponent(lex); if (*lex == old) { --*lex; /* member */ return KINTEGER; } return KREAL; } skipdigits(lex); skipexponent(lex); return KREAL; } return skipexponent(lex); } static void skipstring(char **lex) { while (**lex) { while (**lex == '\\') *lex+=2; if (**lex == '"') { if ((*lex)[1] != '"') break; *lex += 2; continue; } (*lex)++; } } int pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex) { (void) yylval; yylloc->start=*lex; if (!**lex) { yylloc->end=*lex; return 0; } if (isalpha((int)**lex)) { while (is_keyword_char(**lex)) ++*lex; yylloc->end=*lex; return KENTRY; } if (**lex=='"') { ++*lex; skipstring(lex); if (!**lex) compile_err("run-away string",*lex-1); ++*lex; yylloc->end=*lex; return KSTRING; } if (**lex == '.') { int token; if ((*lex)[1]== '.') { *lex+=2; yylloc->end = *lex; return KDOTDOT; } token=skipconstante(lex); if (token==KREAL) { yylloc->end = *lex; return token; } ++*lex; yylloc->end=*lex; return '.'; } if (isdigit((int)**lex)) { int token=skipconstante(lex); yylloc->end = *lex; return token; } if ((*lex)[1]=='=') switch (**lex) { case '=': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KID; } else { *lex+=2; yylloc->end = *lex; return KEQ; } case '>': *lex+=2; yylloc->end = *lex; return KGE; case '<': *lex+=2; yylloc->end = *lex; return KLE; case '*': *lex+=2; yylloc->end = *lex; return KME; case '/': *lex+=2; yylloc->end = *lex; return KDE; case '%': if ((*lex)[2]=='=') break; *lex+=2; yylloc->end = *lex; return KMODE; case '!': if ((*lex)[2]=='=') break; *lex+=2; yylloc->end = *lex; return KNE; case '\\': *lex+=2; yylloc->end = *lex; return KEUCE; case '+': *lex+=2; yylloc->end = *lex; return KPE; case '-': *lex+=2; yylloc->end = *lex; return KSE; } if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>') { *lex+=3; yylloc->end = *lex; return KPARROW; } if (**lex=='-' && (*lex)[1]=='>') { *lex+=2; yylloc->end = *lex; return KARROW; } if (**lex=='<' && (*lex)[1]=='>') { *lex+=2; yylloc->end = *lex; return KNE; } if (**lex=='\\' && (*lex)[1]=='/') switch((*lex)[2]) { case '=': *lex+=3; yylloc->end = *lex; return KDRE; default: *lex+=2; yylloc->end = *lex; return KDR; } if ((*lex)[1]==**lex) switch (**lex) { case '&': *lex+=2; yylloc->end = *lex; return KAND; case '|': *lex+=2; yylloc->end = *lex; return KOR; case '+': *lex+=2; yylloc->end = *lex; return KPP; case '-': *lex+=2; yylloc->end = *lex; return KSS; case '>': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;} *lex+=2; yylloc->end = *lex; return KSR; case '<': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSLE; } *lex+=2; yylloc->end = *lex; return KSL; } yylloc->end = *lex+1; return (unsigned char) *(*lex)++; } /********************************************************************/ /** **/ /** STRINGS **/ /** **/ /********************************************************************/ /* return the first n0 chars of s as a GEN [s may not be 0-terminated] */ GEN strntoGENstr(const char *s, long n0) { long n = nchar2nlong(n0+1); GEN x = cgetg(n+1, t_STR); char *t = GSTR(x); strncpy(t, s, n0); t[n0] = 0; return x; } GEN strtoGENstr(const char *s) { return strntoGENstr(s, strlen(s)); } GEN chartoGENstr(char c) { GEN x = cgetg(2, t_STR); char *t = GSTR(x); t[0] = c; t[1] = 0; return x; } /********************************************************************/ /** **/ /** 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 % functions_tblsz; } static ulong hashvalue_raw(const char *s, long len, ulong n) { long i; for(i=0; inext) if (!strncmp(ep->name, name, len) && !(ep->name)[len]) return ep; return NULL; /* not found */ } entree * is_entry_intern(const char *s, entree **table, long *pthash) { long hash = hashvalue(s); if (pthash) *pthash = hash; return findentry(s, strlen(s), table[hash]); } entree * is_entry(const char *s) { return is_entry_intern(s,functions_hash,NULL); } entree * fetch_entry(const char *s, long len) { 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); } /* 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) { entree **funhash = functions_hash+hashvalue_raw(s-1, len+1, '_'); entree *ep; for (ep = *funhash; ep; ep = ep->next) { if (ep->name[0]!='_' || ep->name[1]!='.') continue; if (!strncmp(ep->name+2, s, len) && !(ep->name)[len+2]) break; } if (ep) return ep; ep=installep(s-2,len+2,funhash); ((char*)ep->name)[0]='_'; return ep; } /********************************************************************/ /* */ /* Formal variables management */ /* */ /********************************************************************/ static long max_avail; /* max variable not yet used */ static long nvar; /* first GP free variable */ void pari_var_init(void) { nvar = 0; max_avail = MAXVARN; (void)fetch_var(); (void)fetch_named_var("x"); } 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 pari_var_create(entree *ep) { GEN p = (GEN)initial_value(ep); long v; if (*p) return; if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); v = nvar++; /* set p = pol_x(v) */ p[0] = evaltyp(t_POL) | _evallg(4); p[1] = evalsigne(1) | evalvarn(v); gel(p,2) = gen_0; gel(p,3) = gen_1; varentries[v] = ep; } 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; } long fetch_var(void) { if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); 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 */ } entree * fetch_named_var(const char *s) { 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)) { case EpVAR: return ep; case EpNEW: break; default: pari_err(e_MISC, "%s already exists with incompatible valence", s); } pari_var_create(ep); ep->valence=EpVAR; ep->value=initial_value(ep); return ep; } long fetch_user_var(const char *s) { return varn((GEN)initial_value(fetch_named_var(s)) ); } GEN fetch_var_value(long vx, GEN t) { entree *ep = varentries[vx]; long vn; 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; } void name_var(long n, const char *s) { entree *ep; char *u; if (n < pari_var_next()) pari_err(e_MISC, "renaming a GP variable is forbidden"); if (n > (long)MAXVARN) pari_err_OVERFLOW("variable number"); ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1); u = (char *)initial_value(ep); 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; } 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; } if (typ(x)==t_PADIC) return gcopy( gel(x,2) ); v = gvar(x); if (v==NO_VARIABLE) return gen_0; return pol_x(v); } 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); ep->pvalue = NULL; } void pari_fill_hashtable(entree **table, entree *ep) { for ( ; ep->name; ep++) fill_hashtable_single(table, ep); } void pari_add_function(entree *ep) { fill_hashtable_single(functions_hash, ep); } /********************************************************************/ /** **/ /** SIMPLE GP FUNCTIONS **/ /** **/ /********************************************************************/ #define ALIAS(ep) (entree *) ((GEN)ep->value)[1] entree * do_alias(entree *ep) { while (ep->valence == EpALIAS) ep = ALIAS(ep); return ep; } void alias0(const char *s, const char *old) { entree *ep, *e; GEN x; ep = fetch_entry(old,strlen(old)); e = fetch_entry(s,strlen(s)); if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW) pari_err(e_MISC,"can't replace an existing symbol by an alias"); freeep(e); x = newblock(2); x[0] = evaltyp(t_STR)|_evallg(2); /* for getheap */ gel(x,1) = (GEN)ep; e->value=x; e->valence=EpALIAS; } GEN ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/) { if (gequal0(g)) /* false */ return b?closure_evalgen(b):gnil; else /* true */ return a?closure_evalgen(a):gnil; } void ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/) { if (gequal0(g)) /* false */ { if(b) closure_evalvoid(b); } else /* true */ { if(a) closure_evalvoid(a); } } GEN ifpari_multi(GEN g, GEN a/*closure*/) { long i, nb = lg(a)-1; if (!gequal0(g)) /* false */ return closure_evalgen(gel(a,1)); for(i=2;iname, ((entree*)f)->name); } void print_all_user_fun(int member) { pari_sp av = avma; long iL = 0, lL = 1024; GEN L = cgetg(lL+1, t_VECSMALL); entree *ep; int i; for (i = 0; i < functions_tblsz; i++) for (ep = functions_hash[i]; ep; ep = ep->next) { const char *f; int is_member; if (EpVALENCE(ep) != EpVAR || typ((GEN)ep->value)!=t_CLOSURE) continue; f = ep->name; is_member = (f[0] == '_' && f[1] == '.'); if (member != is_member) continue; if (iL >= lL) { GEN oL = L; long j; lL *= 2; L = cgetg(lL+1, t_VECSMALL); for (j = 1; j <= iL; j++) gel(L,j) = gel(oL,j); } L[++iL] = (long)ep; } if (iL) { setlg(L, iL+1); L = gen_sort(L, NULL, &cmp_epname); for (i = 1; i <= iL; i++) { ep = (entree*)L[i]; pari_printf("%s =\n %Ps\n\n", ep->name, ep->value); } } avma = av; } pari-2.7.5/src/language/paricfg.c0000644000175000017500000000162112366172547015254 0ustar billbill/* Copyright (C) 2010 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" const char *paricfg_datadir = GPDATADIR; const char *paricfg_version = PARIVERSION; const char *paricfg_buildinfo = PARIINFO; const long paricfg_version_code = PARI_VERSION_CODE; const char *paricfg_vcsversion = PARI_VCSVERSION; const char *paricfg_compiledate = __DATE__; const char *paricfg_mt_engine = PARI_MT_ENGINE; pari-2.7.5/src/language/compat.c0000644000175000017500000023370012413013143015104 0ustar billbill/* 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<=_",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 -pi0 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=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 */ }; pari-2.7.5/src/language/eval.c0000644000175000017500000015034612415507022014562 0ustar billbill/* Copyright (C) 2006 The PARI group. This file is part of the PARI 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" #include "opcode.h" /********************************************************************/ /* */ /* break/next/return handling */ /* */ /********************************************************************/ static THREAD long br_status, br_count; static THREAD GEN br_res; long loop_break(void) { switch(br_status) { case br_MULTINEXT : if (! --br_count) br_status = br_NEXT; return 1; case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */ case br_RETURN: return 1; case br_NEXT: br_status = br_NONE; /* fall through */ } return 0; } static void reset_break(void) { br_status = br_NONE; if (br_res) { gunclone_deep(br_res); br_res = NULL; } } GEN return0(GEN x) { GEN y = br_res; br_res = (x && x != gnil)? gcloneref(x): NULL; if (y) gunclone_deep(y); br_status = br_RETURN; return NULL; } GEN next0(long n) { if (n < 1) pari_err_DOMAIN("next", "n", "<", gen_1, stoi(n)); if (n == 1) br_status = br_NEXT; else { br_count = n-1; br_status = br_MULTINEXT; } return NULL; } GEN break0(long n) { if (n < 1) pari_err_DOMAIN("break", "n", "<", gen_1, stoi(n)); br_count = n; br_status = br_BREAK; return NULL; } /*******************************************************************/ /* */ /* VARIABLES */ /* */ /*******************************************************************/ /* As a rule, ep->value is a clone (COPY). push_val and pop_val are private * functions for use in sumiter: we want a temporary ep->value, which is NOT * a clone (PUSH), to avoid unnecessary copies. */ enum {PUSH_VAL = 0, COPY_VAL = 1, DEFAULT_VAL = 2}; /* ep->args is the stack of old values (INITIAL if initial value, from * installep) */ typedef struct var_cell { struct var_cell *prev; /* cell associated to previous value on stack */ GEN value; /* last value (not including current one, in ep->value) */ char flag; /* status of _current_ ep->value: PUSH or COPY ? */ long valence; /* valence of entree* associated to 'value', to be restored * by pop_val */ } var_cell; #define INITIAL NULL /* Push x on value stack associated to ep. */ static void new_val_cell(entree *ep, GEN x, char flag) { var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell)); v->value = (GEN)ep->value; v->prev = (var_cell*) ep->pvalue; v->flag = flag; v->valence= ep->valence; /* beware: f(p) = Nv = 0 * Nv = p; f(Nv) --> this call would destroy p [ isclone ] */ ep->value = (flag == COPY_VAL)? gclone(x): (x && isclone(x))? gcopy(x): x; /* Do this last. In case the clone is 'ed before completion ! */ ep->pvalue= (char*)v; ep->valence=EpVAR; } /* kill ep->value and replace by preceding one, poped from value stack */ static void pop_val(entree *ep) { var_cell *v = (var_cell*) ep->pvalue; if (v == INITIAL) return; if (v->flag == COPY_VAL) gunclone_deep((GEN)ep->value); ep->value = v->value; ep->pvalue = (char*) v->prev; ep->valence=v->valence; pari_free((void*)v); } void freeep(entree *ep) { if (EpSTATIC(ep)) return; /* gp function loaded at init time */ if (ep->help) {pari_free((void*)ep->help); ep->help=NULL;} if (ep->code) {pari_free((void*)ep->code); ep->code=NULL;} switch(EpVALENCE(ep)) { case EpVAR: while (ep->pvalue!=INITIAL) pop_val(ep); break; case EpALIAS: killblock((GEN)ep->value); ep->value=NULL; break; } } INLINE void pushvalue(entree *ep, GEN x) { new_val_cell(ep, x, COPY_VAL); } INLINE void zerovalue (entree *ep) { var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell)); v->value = (GEN)ep->value; v->prev = (var_cell*) ep->pvalue; v->flag = PUSH_VAL; v->valence= ep->valence; ep->value = gen_0; ep->pvalue= (char*)v; ep->valence=EpVAR; } /* as above IF ep->value was PUSHed, or was created after block number 'loc' return 0 if not deleted, 1 otherwise [for recover()] */ int pop_val_if_newer(entree *ep, long loc) { var_cell *v = (var_cell*) ep->pvalue; if (v == INITIAL) return 0; if (v->flag == COPY_VAL && !pop_entree_block(ep, loc)) return 0; ep->value = v->value; ep->pvalue= (char*) v->prev; ep->valence=v->valence; pari_free((void*)v); return 1; } /* set new value of ep directly to val (COPY), do not save last value unless * it's INITIAL. */ void changevalue(entree *ep, GEN x) { var_cell *v = (var_cell*) ep->pvalue; if (v == INITIAL) new_val_cell(ep, x, COPY_VAL); else { GEN old_val = (GEN) ep->value; /* beware: gunclone_deep may destroy old x */ ep->value = (void *) gclone(x); if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL; } } INLINE GEN copyvalue(entree *ep) { var_cell *v = (var_cell*) ep->pvalue; if (v && v->flag != COPY_VAL) { ep->value = (void*) gclone((GEN)ep->value); v->flag = COPY_VAL; } return (GEN) ep->value; } INLINE void err_var(GEN x) { pari_err_TYPE("evaluator [variable name expected]", x); } INLINE void checkvalue(entree *ep) { 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); } else if (ep->valence!=EpVAR) err_var(strtoGENstr(ep->name)); } /* make GP variables safe for avma = top */ static void lvar_make_safe(void) { long n; entree *ep; for (n = 0; n < functions_tblsz; n++) for (ep = functions_hash[n]; ep; ep = ep->next) if (EpVALENCE(ep) == EpVAR) { /* make sure ep->value is a COPY */ var_cell *v = (var_cell*)ep->pvalue; if (v && v->flag == PUSH_VAL) { GEN x = (GEN)ep->value; if (x) changevalue(ep, (GEN)ep->value); else pop_val(ep); } } } static void check_array_index(long c, long l) { if (c < 1) pari_err_COMPONENT("", "<", gen_1, stoi(c)); if (c >= l) pari_err_COMPONENT("", ">", stoi(l-1), stoi(c)); } GEN* safegel(GEN x, long l) { if (!is_matvec_t(typ(x))) pari_err_TYPE("safegel",x); check_array_index(l, lg(x)); return &(gel(x,l)); } GEN* safelistel(GEN x, long l) { GEN d; if (typ(x)!=t_LIST) pari_err_TYPE("safelistel",x); d = list_data(x); check_array_index(l, lg(d)); return &(gel(d,l)); } long* safeel(GEN x, long l) { if (typ(x)!=t_VECSMALL) pari_err_TYPE("safeel",x); check_array_index(l, lg(x)); return &(x[l]); } GEN* safegcoeff(GEN x, long a, long b) { if (typ(x)!=t_MAT) pari_err_TYPE("safegcoeff", x); check_array_index(b, lg(x)); check_array_index(a, lg(gel(x,b))); return &(gcoeff(x,a,b)); } typedef struct matcomp { GEN *ptcell; GEN parent; int full_col, full_row; } matcomp; typedef struct gp_pointer { matcomp c; GEN x, ox; entree *ep; long vn; long sp; } gp_pointer; /* assign res at *pt in "simple array object" p and return it, or a copy.*/ static void change_compo(matcomp *c, GEN res) { GEN p = c->parent, *pt = c->ptcell; long i, t; if (typ(p) == t_VECSMALL) { if (typ(res) != t_INT || is_bigint(res)) pari_err_TYPE("t_VECSMALL assignment", res); *pt = (GEN)itos(res); return; } t = typ(res); if (c->full_row) { if (t != t_VEC) pari_err_TYPE("matrix row assignment", res); if (lg(res) != lg(p)) pari_err_DIM("matrix row assignment"); for (i=1; ifull_row,i); if (isclone(p1)) gunclone_deep(p1); gcoeff(p,c->full_row,i) = gclone(gel(res,i)); } return; } if (c->full_col) { if (t != t_COL) pari_err_TYPE("matrix col assignment", res); if (lg(res) != lg(*pt)) pari_err_DIM("matrix col assignment"); } res = gclone(res); gunclone_deep(*pt); *pt = res; } /*************************************************************************** ** ** ** Byte-code evaluator ** ** ** ***************************************************************************/ struct var_lex { long flag; GEN value; }; struct trace { long pc; GEN closure; }; static THREAD long sp, rp, dbg_level; static THREAD long *st; 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 void changelex(long vn, GEN x) { struct var_lex *v=var+s_var.n+vn; GEN old_val = v->value; v->value = gclone(x); if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL; } INLINE GEN copylex(long vn) { struct var_lex *v = var+s_var.n+vn; if (v->flag!=COPY_VAL) { v->value = gclone(v->value); v->flag = COPY_VAL; } return v->value; } INLINE void pushlex(long vn, GEN x) { struct var_lex *v=var+s_var.n+vn; v->flag = PUSH_VAL; v->value = x; } INLINE void freelex(long vn) { struct var_lex *v=var+s_var.n+vn; if (v->flag == COPY_VAL) gunclone_deep(v->value); } INLINE void restore_vars(long nbmvar, long nblvar) { long j; for(j=1;j<=nbmvar;j++) freelex(-j); s_var.n-=nbmvar; for(j=1;j<=nblvar;j++) pop_val(lvars[s_lvars.n-j]); s_lvars.n-=nblvar; } INLINE void restore_trace(long nbtrace) { long j; for(j=1;j<=nbtrace;j++) { GEN C = trace[s_trace.n-j].closure; if (isclone(C)) gunclone(C); } s_trace.n-=nbtrace; } INLINE long trace_push(long pc, GEN C) { long tr; BLOCK_SIGINT_START tr = pari_stack_new(&s_trace); trace[tr].pc = pc; trace[tr].closure = C; BLOCK_SIGINT_END return tr; } void push_lex(GEN a, GEN C) { long vn=pari_stack_new(&s_var); struct var_lex *v=var+vn; v->flag = PUSH_VAL; v->value = a; if (C) (void) trace_push(-1, C); } GEN get_lex(long vn) { struct var_lex *v=var+s_var.n+vn; return v->value; } void set_lex(long vn, GEN x) { struct var_lex *v=var+s_var.n+vn; if (v->flag == COPY_VAL) { gunclone_deep(v->value); v->flag = PUSH_VAL; } v->value = x; } void pop_lex(long n) { long j; for(j=1; j<=n; j++) freelex(-j); s_var.n-=n; s_trace.n--; } static THREAD pari_stack s_relocs; static THREAD entree **relocs; void pari_init_evaluator(void) { sp=0; pari_stack_init(&s_st,sizeof(*st),(void**)&st); pari_stack_alloc(&s_st,32); s_st.n=s_st.alloc; rp=0; pari_stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs); pari_stack_alloc(&s_ptrs,16); s_ptrs.n=s_ptrs.alloc; pari_stack_init(&s_var,sizeof(*var),(void**)&var); pari_stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars); pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace); br_res = NULL; pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs); } void pari_close_evaluator(void) { pari_stack_delete(&s_st); pari_stack_delete(&s_ptrs); pari_stack_delete(&s_var); pari_stack_delete(&s_lvars); pari_stack_delete(&s_trace); pari_stack_delete(&s_relocs); } static gp_pointer * new_ptr(void) { if (rp==s_ptrs.n-1) { long i; gp_pointer *old = ptrs; (void)pari_stack_new(&s_ptrs); if (old != ptrs) for(i=0; isp >= 0) gel(st,g->sp) = (GEN) &(g->x); } } return &ptrs[rp++]; } INLINE GEN copyupto(GEN z, GEN t) { if (is_universal_constant(z) || (z>(GEN)bot && z<=t)) return z; else return gcopy(z); } static void closure_eval(GEN C); INLINE GEN closure_return(GEN C) { pari_sp ltop=avma; closure_eval(C); if (br_status) { GEN z; avma=ltop; z=br_res?gcopy(br_res):gnil; reset_break(); return z; } return gerepileupto(ltop,gel(st,--sp)); } /* for the break_loop debugger. Not memory clean */ GEN closure_evalbrk(GEN C, long *status) { closure_eval(C); *status = br_status; if (br_status) { GEN z = br_res? gcopy(br_res): gnil; reset_break(); return z; } return gel(st,--sp); } INLINE long closure_varn(GEN x) { if (!x) return -1; if (!gequalX(x)) err_var(x); return varn(x); } INLINE void closure_castgen(GEN z, long mode) { switch (mode) { case Ggen: gel(st,sp++)=z; break; case Gsmall: st[sp++]=gtos(z); break; case Gvar: st[sp++]=closure_varn(z); break; case Gvoid: break; default: pari_err_BUG("closure_castgen, type unknown"); } } INLINE void closure_castlong(long z, long mode) { switch (mode) { case Gsmall: st[sp++]=z; break; case Ggen: gel(st,sp++)=stoi(z); break; case Gvar: err_var(stoi(z)); default: pari_err_BUG("closure_castlong, type unknown"); } } const char * closure_func_err(void) { long fun=s_trace.n-1, pc; const char *code; GEN C, oper; if (fun < 0 || trace[fun].pc < 0) return NULL; pc = trace[fun].pc; C = trace[fun].closure; code = closure_codestr(C); oper = closure_get_oper(C); if (code[pc]==OCcallgen || code[pc]==OCcallgen2 || code[pc]==OCcallint || code[pc]==OCcalllong || code[pc]==OCcallvoid) return ((entree*)oper[pc])->name; return NULL; } /* return the next label for the call chain debugger closure_err(), * incorporating the name of the user of member function. Return NULL for an * anonymous (inline) closure. */ static char * get_next_label(const char *s, int member, char **next_fun) { const char *v, *t = s+1; char *u, *next_label; if (!is_keyword_char(*s)) return NULL; while (is_keyword_char(*t)) t++; /* e.g. (x->1/x)(0) instead of (x)->1/x */ if (t[0] == '-' && t[1] == '>') return NULL; next_label = (char*)pari_malloc(t - s + 32); sprintf(next_label, "in %sfunction ", member? "member ": ""); u = *next_fun = next_label + strlen(next_label); v = s; while (v < t) *u++ = *v++; *u++ = 0; return next_label; } static const char * get_arg_name(GEN C, long i) { GEN e = gmael(closure_get_dbg(C), 3, 1); return ((entree*)e[i])->name; } void closure_err(long level) { GEN base; const long lastfun = s_trace.n - 1 - level; char *next_label, *next_fun; long i = maxss(0, lastfun - 19); if (lastfun < 0) return; /*e.g. when called by gp_main_loop's simplify */ if (i > 0) while (lg(trace[i].closure)==6) i--; base = closure_get_text(trace[i].closure); /* gcc -Wall*/ next_label = pari_strdup(i == 0? "at top-level": "[...] at"); next_fun = next_label; for (; i <= lastfun; i++) { GEN C = trace[i].closure; if (lg(C) >= 7) base=closure_get_text(C); if ((i==lastfun || lg(trace[i+1].closure)>=7)) { GEN dbg = gel(closure_get_dbg(C),1); /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */ long pc = minss(lg(dbg)-1, trace[i].pc>=0 ? trace[i].pc: 1); long offset = pc? dbg[pc]: 0; int member; const char *s, *sbase; if (typ(base)!=t_VEC) sbase = GSTR(base); else if (offset>=0) sbase = GSTR(gel(base,2)); else { sbase = GSTR(gel(base,1)); offset += strlen(sbase); } s = sbase + offset; member = offset>0 && (s[-1] == '.'); /* avoid "in function foo: foo" */ if (!next_fun || strcmp(next_fun, s)) { print_errcontext(pariErr, next_label, s, sbase); out_putc(pariErr, '\n'); } pari_free(next_label); if (i == lastfun) break; next_label = get_next_label(s, member, &next_fun); if (!next_label) { next_label = pari_strdup("in anonymous function"); next_fun = NULL; } } } } long closure_context(long start, long level) { const long lastfun = s_trace.n - 1 - level; long i, fun = lastfun; if (fun<0) return lastfun; while (fun>start && lg(trace[fun].closure)==6) fun--; for (i=fun; i <= lastfun; i++) push_frame(trace[i].closure, trace[i].pc,0); for ( ; i < s_trace.n; i++) push_frame(trace[i].closure, trace[i].pc,1); return s_trace.n-level; } INLINE void st_alloc(long n) { if (sp+n>s_st.n) { pari_stack_alloc(&s_st,n+16); s_st.n=s_st.alloc; if (DEBUGMEM>=2) pari_warn(warner,"doubling evaluator stack"); } } INLINE void ptr_proplock(gp_pointer *g, GEN C) { g->x = C; if (isclone(g->x)) { clone_unlock(g->ox); g->ox = g->x; ++bl_refc(g->ox); } } static void closure_eval(GEN C) { const char *code=closure_codestr(C); GEN oper=closure_get_oper(C); GEN data=closure_get_data(C); long loper=lg(oper); long saved_sp=sp-closure_arity(C); long saved_rp=rp; long j, nbmvar=0, nblvar=0; long pc, t; clone_lock(C); t = trace_push(0, C); if (lg(C)==8) { GEN z=closure_get_frame(C); long l=lg(z)-1; pari_stack_alloc(&s_var,l); s_var.n+=l; nbmvar+=l; for(j=1;j<=l;j++) { var[s_var.n-j].flag=PUSH_VAL; var[s_var.n-j].value=gel(z,j); } } for(pc=1;pcvalue; break; } case OCpushlex: gel(st,sp++)=var[s_var.n+operand].value; break; case OCsimpleptrdyn: { gp_pointer *g = new_ptr(); g->vn=0; g->ep = (entree*) operand; checkvalue(g->ep); g->x = (GEN) g->ep->value; g->ox = g->x; clone_lock(g->ox); g->sp = sp; gel(st,sp++) = (GEN)&(g->x); break; } case OCsimpleptrlex: { gp_pointer *g = new_ptr(); g->vn=operand; g->ep=(entree *)0x1L; g->x = (GEN) var[s_var.n+operand].value; g->ox = g->x; clone_lock(g->ox); g->sp = sp; gel(st,sp++) = (GEN)&(g->x); break; } case OCnewptrdyn: { entree *ep = (entree *)operand; gp_pointer *g = new_ptr(); matcomp *C; checkvalue(ep); g->sp = -1; g->x = copyvalue(ep); g->ox = g->x; clone_lock(g->ox); g->vn=0; g->ep=NULL; C=&g->c; C->full_col = C->full_row = 0; C->parent = (GEN) g->x; C->ptcell = (GEN *) &g->x; break; } case OCnewptrlex: { gp_pointer *g = new_ptr(); matcomp *C; g->sp = -1; g->x = copylex(operand); g->ox = g->x; clone_lock(g->ox); g->vn=0; g->ep=NULL; C=&g->c; C->full_col = C->full_row = 0; C->parent = (GEN) g->x; C->ptcell = (GEN *) &(g->x); break; } case OCpushptr: { gp_pointer *g = &ptrs[rp-1]; g->sp = sp; gel(st,sp++) = (GEN)&(g->x); } break; case OCendptr: for(j=0;jep) { if (g->vn) changelex(g->vn, g->x); else changevalue(g->ep, g->x); } else change_compo(&(g->c), g->x); clone_unlock(g->ox); } break; case OCstoredyn: { entree *ep = (entree *)operand; checkvalue(ep); changevalue(ep, gel(st,--sp)); break; } case OCstorelex: changelex(operand,gel(st,--sp)); break; case OCstoreptr: { gp_pointer *g = &ptrs[--rp]; change_compo(&(g->c), gel(st,--sp)); clone_unlock(g->ox); break; } case OCstackgen: { GEN z = gerepileupto(st[sp-2],gel(st,sp-1)); gmael(st,sp-3,operand) = copyupto(z,gel(st,sp-2)); st[sp-2] = avma; sp--; break; } case OCprecreal: st[sp++]=precreal; break; case OCprecdl: st[sp++]=precdl; break; case OCavma: st[sp++]=avma; break; case OCcowvardyn: { entree *ep = (entree *)operand; checkvalue(ep); (void)copyvalue(ep); break; } case OCcowvarlex: (void)copylex(operand); break; case OCstoi: gel(st,sp-1)=stoi(st[sp-1]); break; case OCitos: st[sp+operand]=gtos(gel(st,sp+operand)); break; case OCtostr: { GEN z = gel(st,sp+operand); st[sp+operand] = (long)GENtostr_unquoted(z); break; } case OCvarn: st[sp+operand] = closure_varn(gel(st,sp+operand)); break; case OCcopy: gel(st,sp-1) = gcopy(gel(st,sp-1)); break; case OCgerepile: { pari_sp av; GEN x; sp--; av = st[sp-1]; x = gel(st,sp); if (isonstack(x)) { pari_sp av2 = (pari_sp)(x + lg(x)); if ((long) (av - av2) > 1000000L) { if (DEBUGMEM>=2) pari_warn(warnmem,"eval: recovering %ld bytes", av - av2); x = gerepileupto(av, x); } } else avma = av; gel(st,sp-1) = x; break; } case OCcopyifclone: if (isclone(gel(st,sp-1))) gel(st,sp-1) = gcopy(gel(st,sp-1)); break; case OCcompo1: { GEN p=gel(st,sp-2); long c=st[sp-1]; sp-=2; switch(typ(p)) { case t_VEC: case t_COL: check_array_index(c, lg(p)); closure_castgen(gel(p,c),operand); break; case t_LIST: { long lx; p = list_data(p); lx = p? lg(p): 1; check_array_index(c, lx); closure_castgen(gel(p,c),operand); break; } case t_VECSMALL: check_array_index(c,lg(p)); closure_castlong(p[c],operand); break; default: pari_err_TYPE("_[_] OCcompo1 [not a vector]", p); break; } break; } case OCcompo1ptr: { long c=st[sp-1]; long lx; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp--; switch(typ(p)) { case t_VEC: case t_COL: check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; ptr_proplock(g, *(C->ptcell)); break; case t_VECSMALL: check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; g->x = stoi(p[c]); break; case t_LIST: p = list_data(p); lx = p? lg(p): 1; check_array_index(c,lx); C->ptcell = (GEN *) p+c; ptr_proplock(g, *(C->ptcell)); break; default: pari_err_TYPE("&_[_] OCcompo1ptr [not a vector]", p); } C->parent = p; break; } case OCcompo2: { GEN p=gel(st,sp-3); long c=st[sp-2]; long d=st[sp-1]; if (typ(p)!=t_MAT) pari_err_TYPE("_[_,_] OCcompo2 [not a matrix]", p); check_array_index(d, lg(p)); check_array_index(c, lg(gel(p,d))); sp-=3; closure_castgen(gcoeff(p,c,d),operand); break; } case OCcompo2ptr: { long c=st[sp-2]; long d=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp-=2; if (typ(p)!=t_MAT) pari_err_TYPE("&_[_,_] OCcompo2ptr [not a matrix]", p); check_array_index(d, lg(p)); check_array_index(c, lg(gel(p,d))); C->ptcell = (GEN *) gel(p,d)+c; C->parent = p; ptr_proplock(g, *(C->ptcell)); break; } case OCcompoC: { GEN p=gel(st,sp-2); long c=st[sp-1]; if (typ(p)!=t_MAT) pari_err_TYPE("_[,_] OCcompoC [not a matrix]", p); check_array_index(c, lg(p)); sp--; gel(st,sp-1) = gel(p,c); break; } case OCcompoCptr: { long c=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("&_[,_] OCcompoCptr [not a matrix]", p); check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; C->full_col = c; C->parent = p; ptr_proplock(g, *(C->ptcell)); break; } case OCcompoL: { GEN p=gel(st,sp-2); long r=st[sp-1]; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("_[_,] OCcompoL [not a matrix]", p); check_array_index(r,lg(p) == 1? 1: lgcols(p)); gel(st,sp-1) = row(p,r); break; } case OCcompoLptr: { long r=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x, p2; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("&_[_,] OCcompoLptr [not a matrix]", p); check_array_index(r,lg(p) == 1? 1: lgcols(p)); p2 = rowcopy(p,r); C->full_row = r; /* record row number */ C->ptcell = &p2; C->parent = p; g->x = p2; break; } case OCdefaultarg: if (var[s_var.n+operand].flag==DEFAULT_VAL) { GEN z = gel(st,sp-1); pushlex(operand,typ(z)== t_CLOSURE? closure_evalnobrk(z): z); } sp--; break; case OClocalvar: { long n = pari_stack_new(&s_lvars); entree *ep = (entree *)operand; checkvalue(ep); lvars[n] = ep; nblvar++; pushvalue(ep,gel(st,--sp)); break; } case OClocalvar0: { long n = pari_stack_new(&s_lvars); entree *ep = (entree *)operand; checkvalue(ep); lvars[n] = ep; nblvar++; zerovalue(ep); break; } #define EVAL_f(f) \ switch (ep->arity) \ { \ case 0: f(); break; \ case 1: sp--; f(st[sp]); break; \ case 2: sp-=2; f(st[sp],st[sp+1]); break; \ case 3: sp-=3; f(st[sp],st[sp+1],st[sp+2]); break; \ case 4: sp-=4; f(st[sp],st[sp+1],st[sp+2],st[sp+3]); break; \ case 5: sp-=5; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4]); break; \ case 6: sp-=6; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5]); break; \ case 7: sp-=7; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6]); break; \ case 8: sp-=8; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7]); break; \ case 9: sp-=9; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8]); break; \ case 10: sp-=10; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9]); break; \ case 11: sp-=11; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10]); break; \ case 12: sp-=12; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11]); break; \ case 13: sp-=13; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12]); break; \ case 14: sp-=14; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13]); break; \ case 15: sp-=15; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14]); break; \ case 16: sp-=16; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15]); break; \ case 17: sp-=17; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16]); break; \ case 18: sp-=18; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17]); break; \ case 19: sp-=19; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18]); break; \ case 20: sp-=20; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18],st[sp+19]); break; \ default: \ pari_err_IMPL("functions with more than 20 parameters");\ goto endeval; /*not reached*/ \ } case OCcallgen: { entree *ep = (entree *)operand; GEN res; /* Macro Madness : evaluate function ep->value on arguments * st[sp-ep->arity .. sp]. Set res = result. */ EVAL_f(res = ((GEN (*)(ANYARG))ep->value)); if (br_status) goto endeval; gel(st,sp++)=res; break; } case OCcallgen2: /*same for ep->arity = 2. Is this optimization worth it ?*/ { entree *ep = (entree *)operand; GEN res; sp-=2; res = ((GEN (*)(GEN,GEN))ep->value)(gel(st,sp),gel(st,sp+1)); if (br_status) goto endeval; gel(st,sp++)=res; break; } case OCcalllong: { entree *ep = (entree *)operand; long res; EVAL_f(res = ((long (*)(ANYARG))ep->value)); if (br_status) goto endeval; st[sp++] = res; break; } case OCcallint: { entree *ep = (entree *)operand; long res; EVAL_f(res = ((int (*)(ANYARG))ep->value)); if (br_status) goto endeval; st[sp++] = res; break; } case OCcallvoid: { entree *ep = (entree *)operand; EVAL_f(((void (*)(ANYARG))ep->value)); if (br_status) goto endeval; break; } #undef EVAL_f case OCcalluser: { long n=operand; GEN fun = gel(st,sp-1-n); long arity; GEN z; if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun); arity = closure_arity(fun); if (n!=arity) { 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; } #ifdef STACK_CHECK if (PARI_stack_limit && (void*) &z <= PARI_stack_limit) pari_err(e_MISC, "deep recursion"); #endif z = closure_return(fun); if (br_status) goto endeval; gel(st, sp-1) = z; break; } case OCnewframe: if (operand>0) nbmvar+=operand; else operand=-operand; pari_stack_alloc(&s_var,operand); s_var.n+=operand; for(j=1;j<=operand;j++) { var[s_var.n-j].flag=PUSH_VAL; var[s_var.n-j].value=gen_0; } break; case OCsaveframe: { GEN cl = (operand?gcopy:shallowcopy)(gel(st,sp-1)); long l = lg(gel(cl,7)); GEN v = cgetg(l, t_VEC); for(j=1; j>=1UL,j--) if ((operand&1L) && gel(st,j)==NULL) pari_err(e_MISC,"missing mandatory argument"); break; case OCcheckargs0: for (j=sp-1;operand;operand>>=1UL,j--) if ((operand&1L) && gel(st,j)) pari_err(e_MISC,"argument type not implemented"); break; case OCdefaultlong: sp--; if (st[sp+operand]) st[sp+operand]=gtos(gel(st,sp+operand)); else st[sp+operand]=st[sp]; break; case OCdefaultgen: sp--; if (!st[sp+operand]) st[sp+operand]=st[sp]; break; case OCvec: gel(st,sp++)=cgetg(operand,t_VEC); st[sp++]=avma; break; case OCcol: gel(st,sp++)=cgetg(operand,t_COL); st[sp++]=avma; break; case OCmat: { GEN z; long l=st[sp-1]; z=cgetg(operand,t_MAT); for(j=1;jsaved_rp ; ) { gp_pointer *g = &ptrs[--rp]; clone_unlock(g->ox); } } s_trace.n--; restore_vars(nbmvar, nblvar); clone_unlock(C); } GEN closure_evalgen(GEN C) { pari_sp ltop=avma; closure_eval(C); if (br_status) { avma=ltop; return NULL; } return gerepileupto(ltop,gel(st,--sp)); } void evalstate_save(struct pari_evalstate *state) { state->avma = avma; state->sp = sp; state->rp = rp; state->var = s_var.n; state->lvars= s_lvars.n; state->trace= s_trace.n; compilestate_save(&state->comp); mtstate_save(&state->pending_threads); } void evalstate_restore(struct pari_evalstate *state) { avma = state->avma; mtstate_restore(&state->pending_threads); sp = state->sp; rp = state->rp; restore_vars(s_var.n-state->var,s_lvars.n-state->lvars); restore_trace(s_trace.n-state->trace); reset_break(); compilestate_restore(&state->comp); } GEN evalstate_restore_err(struct pari_evalstate *state) { GENbin* err = copy_bin(pari_err_last()); evalstate_restore(state); return bin_copy(err); } void evalstate_reset(void) { mtstate_reset(); sp = 0; rp = 0; dbg_level = 0; restore_vars(s_var.n, s_lvars.n); s_trace.n = 0; reset_break(); compilestate_reset(); parsestate_reset(); avma = top; } void evalstate_clone(void) { long i; for (i = 1; i<=s_var.n; i++) copylex(-i); lvar_make_safe(); for (i = 0; i< s_trace.n; i++) { GEN C = trace[i].closure; if (isonstack(C)) trace[i].closure = gclone(C); } } GEN closure_trapgen(GEN C, long numerr) { VOLATILE GEN x; struct pari_evalstate state; evalstate_save(&state); pari_CATCH(numerr) { x = (GEN)1L; } pari_TRY { x = closure_evalgen(C); } pari_ENDCATCH; if (x == (GEN)1L) evalstate_restore(&state); return x; } GEN closure_evalnobrk(GEN C) { pari_sp ltop=avma; closure_eval(C); if (br_status) pari_err(e_MISC, "break not allowed here"); return gerepileupto(ltop,gel(st,--sp)); } void closure_evalvoid(GEN C) { pari_sp ltop=avma; closure_eval(C); avma=ltop; } GEN closure_evalres(GEN C) { return closure_return(C); } INLINE GEN closure_returnupto(GEN C) { pari_sp av=avma; 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) { return closure_callgenall(C, 0); } GEN pareval(GEN C) { pari_sp av = avma; long l = lg(C), i, pending = 0, workid; struct pari_mt pt; GEN worker, V, done; if (!is_vec_t(typ(C))) pari_err_TYPE("pareval",C); for (i=1; i1) pari_warn(warnmem,"sum"); x = gerepileupto(av2,x); } } } mt_queue_end(&pt); return gerepilecopy(av, x); } void parfor(GEN a, GEN b, GEN code, GEN code2) { pari_sp av = avma, av2; long running, pending = 0; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN done, stop = NULL; struct pari_mt pt; if (typ(a) != t_INT) pari_err_TYPE("parfor",a); if (b && gcmp(b,a) < 0) return; mt_queue_start(&pt, worker); b = b ? gfloor(b): NULL; a = mkvec(setloop(a)); av2 = avma; while ((running = (!stop && (!b || cmpii(gel(a,1),b) <= 0))) || pending) { 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()) { status = br_status; br_status = br_NONE; stop = gerepileuptoint(av2, gel(done,1)); } } gel(a,1) = incloop(gel(a,1)); if (!stop) avma = av2; } avma = av2; mt_queue_end(&pt); br_status = status; avma = av; } void parforprime(GEN a, GEN b, GEN code, GEN code2) { pari_sp av = avma, av2; long running, pending = 0; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN done, stop = NULL; struct pari_mt pt; forprime_t T; if (!forprime_init(&T, a,b)) { avma = av; return; } mt_queue_start(&pt, worker); av2 = avma; while ((running = (!stop && forprime_next(&T))) || pending) { 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()) { status = br_status; br_status = br_NONE; stop = gerepileuptoint(av2, gel(done,1)); } } if (!stop) avma = av2; } avma = av2; mt_queue_end(&pt); br_status = status; avma = av; } GEN closure_callgen2(GEN C, GEN x, GEN y) { long i, ar = closure_arity(C); st_alloc(ar); gel(st,sp++) = x; gel(st,sp++) = y; for(i=3; i<=ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenvec(GEN C, GEN args) { long i, l = lg(args), ar = closure_arity(C); st_alloc(ar); for (i = 1; i < l; i++) gel(st,sp++) = gel(args,i); for( ; i <= ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenall(GEN C, long n, ...) { va_list ap; long i, ar = closure_arity(C); va_start(ap,n); st_alloc(ar); for (i = 1; i <=n; i++) gel(st,sp++) = va_arg(ap, GEN); for( ; i <=ar; i++) gel(st,sp++) = NULL; va_end(ap); return closure_returnupto(C); } GEN gp_eval(void *E, GEN x) { GEN code = (GEN)E; set_lex(-1,x); return closure_evalnobrk(code); } GEN gp_evalupto(void *E, GEN x) { pari_sp av = avma; return copyupto(gp_eval(E,x), (GEN)av); } long gp_evalbool(void *E, GEN x) { pari_sp av = avma; long res = !gequal0(gp_eval(E,x)); avma = av; return res; } long gp_evalvoid(void *E, GEN x) { GEN code = (GEN)E; set_lex(-1,x); closure_evalvoid(code); return loop_break(); } GEN gp_call(void *E, GEN x) { GEN code = (GEN)E; return closure_callgen1(code, x); } long gp_callbool(void *E, GEN x) { pari_sp av = avma; GEN code = (GEN)E; long res = !gequal0(closure_callgen1(code, x)); avma = av; return res; } long gp_callvoid(void *E, GEN x) { GEN code = (GEN)E; closure_callvoid1(code, x); return loop_break(); } INLINE const char * disassemble_cast(long mode) { switch (mode) { case Gsmall: return "small"; case Ggen: return "gen"; case Gvar: return "var"; case Gvoid: return "void"; default: return "unknown"; } } void closure_disassemble(GEN C) { const char * code; GEN oper; long i; if (typ(C)!=t_CLOSURE) pari_err_TYPE("disassemble",C); code=closure_codestr(C); oper=closure_get_oper(C); for(i=1;iname); break; } case OCpushdyn: { entree *ep = (entree *)operand; pari_printf("pushdyn\t\t%s\n",ep->name); break; } case OCpushlex: pari_printf("pushlex\t\t%ld\n",operand); break; case OCstoredyn: { entree *ep = (entree *)operand; pari_printf("storedyn\t%s\n",ep->name); break; } case OCstorelex: pari_printf("storelex\t%ld\n",operand); break; case OCstoreptr: pari_printf("storeptr\n"); break; case OCsimpleptrdyn: { entree *ep = (entree *)operand; pari_printf("simpleptrdyn\t%s\n",ep->name); break; } case OCsimpleptrlex: pari_printf("simpleptrlex\t%ld\n",operand); break; case OCnewptrdyn: { entree *ep = (entree *)operand; pari_printf("newptrdyn\t%s\n",ep->name); break; } case OCnewptrlex: pari_printf("newptrlex\t%ld\n",operand); break; case OCpushptr: pari_printf("pushptr\n"); break; case OCstackgen: pari_printf("stackgen\t%ld\n",operand); break; case OCendptr: pari_printf("endptr\t\t%ld\n",operand); break; case OCprecreal: pari_printf("precreal\n"); break; case OCprecdl: pari_printf("precdl\n"); break; case OCstoi: pari_printf("stoi\n"); break; case OCitos: pari_printf("itos\t\t%ld\n",operand); break; case OCtostr: pari_printf("tostr\t\t%ld\n",operand); break; case OCvarn: pari_printf("varn\t\t%ld\n",operand); break; case OCcopy: pari_printf("copy\n"); break; case OCcopyifclone: pari_printf("copyifclone\n"); break; case OCcompo1: pari_printf("compo1\t\t%s\n",disassemble_cast(operand)); break; case OCcompo1ptr: pari_printf("compo1ptr\n"); break; case OCcompo2: pari_printf("compo2\t\t%s\n",disassemble_cast(operand)); break; case OCcompo2ptr: pari_printf("compo2ptr\n"); break; case OCcompoC: pari_printf("compoC\n"); break; case OCcompoCptr: pari_printf("compoCptr\n"); break; case OCcompoL: pari_printf("compoL\n"); break; case OCcompoLptr: pari_printf("compoLptr\n"); break; case OCcheckargs: pari_printf("checkargs\t0x%lx\n",operand); break; case OCcheckargs0: pari_printf("checkargs0\t0x%lx\n",operand); break; case OCcheckuserargs: pari_printf("checkuserargs\t%ld\n",operand); break; case OCdefaultlong: pari_printf("defaultlong\t%ld\n",operand); break; case OCdefaultgen: pari_printf("defaultgen\t%ld\n",operand); break; case OCgetargs: pari_printf("getargs\t\t%ld\n",operand); break; case OCdefaultarg: pari_printf("defaultarg\t%ld\n",operand); break; case OClocalvar: { entree *ep = (entree *)operand; pari_printf("localvar\t%s\n",ep->name); break; } case OClocalvar0: { entree *ep = (entree *)operand; pari_printf("localvar0\t%s\n",ep->name); break; } case OCcallgen: { entree *ep = (entree *)operand; pari_printf("callgen\t\t%s\n",ep->name); break; } case OCcallgen2: { entree *ep = (entree *)operand; pari_printf("callgen2\t%s\n",ep->name); break; } case OCcalllong: { entree *ep = (entree *)operand; pari_printf("calllong\t%s\n",ep->name); break; } case OCcallint: { entree *ep = (entree *)operand; pari_printf("callint\t\t%s\n",ep->name); break; } case OCcallvoid: { entree *ep = (entree *)operand; pari_printf("callvoid\t%s\n",ep->name); break; } case OCcalluser: pari_printf("calluser\t%ld\n",operand); break; case OCvec: pari_printf("vec\t\t%ld\n",operand); break; case OCcol: pari_printf("col\t\t%ld\n",operand); break; case OCmat: pari_printf("mat\t\t%ld\n",operand); break; case OCnewframe: pari_printf("newframe\t%ld\n",operand); break; case OCsaveframe: pari_printf("saveframe\t%ld\n", operand); break; case OCpop: pari_printf("pop\t\t%ld\n",operand); break; case OCdup: pari_printf("dup\t\t%ld\n",operand); break; case OCavma: pari_printf("avma\n",operand); break; case OCgerepile: pari_printf("gerepile\n",operand); break; case OCcowvardyn: { entree *ep = (entree *)operand; pari_printf("cowvardyn\t%s\n",ep->name); break; } case OCcowvarlex: pari_printf("cowvarlex\t%ld\n",operand); break; } } } static int opcode_need_relink(op_code opcode) { switch(opcode) { case OCpushlong: case OCpushgen: case OCpushgnil: case OCpushreal: case OCpushstoi: case OCpushlex: case OCstorelex: case OCstoreptr: case OCsimpleptrlex: case OCnewptrlex: case OCpushptr: case OCstackgen: case OCendptr: case OCprecreal: case OCprecdl: case OCstoi: case OCitos: case OCtostr: case OCvarn: case OCcopy: case OCcopyifclone: case OCcompo1: case OCcompo1ptr: case OCcompo2: case OCcompo2ptr: case OCcompoC: case OCcompoCptr: case OCcompoL: case OCcompoLptr: case OCcheckargs: case OCcheckargs0: case OCcheckuserargs: case OCgetargs: case OCdefaultarg: case OCdefaultgen: case OCdefaultlong: case OCcalluser: case OCvec: case OCcol: case OCmat: case OCnewframe: case OCsaveframe: case OCdup: case OCpop: case OCavma: case OCgerepile: case OCcowvarlex: break; case OCpushvar: case OCpushdyn: case OCstoredyn: case OCsimpleptrdyn: case OCnewptrdyn: case OClocalvar: case OClocalvar0: case OCcallgen: case OCcallgen2: case OCcalllong: case OCcallint: case OCcallvoid: case OCcowvardyn: return 1; } return 0; } static void closure_relink(GEN C, hashtable *table) { const char *code = closure_codestr(C); GEN oper = closure_get_oper(C); GEN fram = gel(closure_get_dbg(C),3); long i, j; for(i=1;ival; for (i=1;ival; } void gen_relink(GEN x, hashtable *table) { long i, lx, tx = typ(x); switch(tx) { case t_CLOSURE: closure_relink(x, table); gen_relink(closure_get_data(x), table); if (lg(x)==8) gen_relink(closure_get_frame(x), table); break; case t_LIST: gen_relink(list_data(x), table); break; case t_VEC: case t_COL: case t_MAT: case t_ERROR: lx = lg(x); for (i=lontyp[tx]; ivalue) continue; gen_unlink((GEN)ep->value); } } n = s_relocs.n-nold; v = cgetg(n+1, t_VECSMALL); for(i=0; iname); } gel(res,1) = vecsmall_copy(w); gel(res,2) = V; 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) */ 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); 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))); } return h; } void bincopy_relink(GEN C, GEN V) { pari_sp av = avma; hashtable *table = hash_from_link(gel(V,1),gel(V,2),1); gen_relink(C, table); avma = av; } pari-2.7.5/src/language/anal.h0000644000175000017500000000424312366172547014564 0ustar billbill/* 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. */ /*************************************************************************/ /* */ /* Declarations specific to the analyzer */ /* */ /*************************************************************************/ BEGINEXTERN /* GP control structures */ #define EXPR_WRAP(code, call) \ { GEN z; GEN __E = code; \ push_lex(gen_0, __E); z = call; pop_lex(1); return z; } #define EXPR_ARG __E, &gp_eval #define EXPR_ARGUPTO __E, &gp_evalupto #define EXPR_ARGBOOL __E, &gp_evalbool /* functions */ void changevalue(entree *ep, GEN val); void freeep(entree *ep); void pari_fill_hashtable(entree **table, entree *ep); void compile_err(const char *msg, const char *str); void compile_varerr(const char *str); #ifdef STACK_CHECK extern THREAD void *PARI_stack_limit; #endif extern entree **varentries; struct node_loc { const char *start,*end; }; 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); void pari_close_parser(void); void pari_close_compiler(void); void pari_close_evaluator(void); void pari_init_parser(void); void pari_init_compiler(void); void pari_init_evaluator(void); void optimizenode(long n); void push_frame(GEN C, long lpc, long flag); const char * closure_func_err(void); GEN gp_closure(long n); long eval_mnemonic(GEN str, const char *tmplate); ENDEXTERN pari-2.7.5/src/language/hash.c0000644000175000017500000001446212405547147014567 0ustar billbill/* 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" /********************************************************************/ /* */ /* GENERAL HASHTABLES */ /* */ /********************************************************************/ /* http://planetmath.org/encyclopedia/GoodHashTablePrimes.html */ static const ulong hashprimes[] = { 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741 }; static const int hashprimes_len = sizeof(hashprimes) / sizeof(hashprimes[0]); INLINE void setlen(hashtable *h, ulong len) { h->maxnb = (ulong)ceil(len * 0.65); h->len = len; } static int get_prime_index(ulong len) { int i; for (i=0; i < hashprimes_len; i++) if (hashprimes[i] > len) return i; pari_err_OVERFLOW("hash table [too large]"); return -1; /* not reached */ } /* link hashentry e to hashtable h, setting e->hash / e->next */ INLINE void hash_link(hashtable *h, hashentry *e) { ulong index; e->hash = h->hash(e->key); index = e->hash % h->len; e->next = h->table[index]; h->table[index] = e; } hashtable * hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack) { int i = get_prime_index(minsize); ulong len = hashprimes[i]; hashtable *h; if (use_stack) { h = (hashtable*)stack_malloc(sizeof(hashtable)); h->table = (hashentry**)stack_calloc(len * sizeof(hashentry*)); h->use_stack = 1; } else { h = (hashtable*)pari_malloc(sizeof(hashtable)); h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*)); h->use_stack = 0; } h->pindex = i; h->nb = 0; h->hash = hash; h->eq = eq; setlen(h, len); return h; } void hash_insert(hashtable *h, void *k, void *v) { hashentry *e; ulong index; if (h->use_stack) e = (hashentry*) stack_malloc(sizeof(hashentry)); else e = (hashentry*) pari_malloc(sizeof(hashentry)); if (++(h->nb) > h->maxnb && h->pindex < hashprimes_len-1) { /* double table size */ ulong i, newlen = hashprimes[++(h->pindex)]; hashentry *E, **newtable; if (h->use_stack) newtable = (hashentry**)stack_calloc(newlen*sizeof(hashentry*)); else newtable = (hashentry**)pari_calloc(newlen*sizeof(hashentry*)); for (i = 0; i < h->len; i++) while ( (E = h->table[i]) ) { h->table[i] = E->next; index = E->hash % newlen; E->next = newtable[index]; newtable[index] = E; } if (!h->use_stack) pari_free(h->table); h->table = newtable; setlen(h, newlen); } e->key = k; e->val = v; hash_link(h, e); } /* 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 ]; while (e) { if (hash == e->hash && h->eq(k, e->key)) return e; e = e->next; } return NULL; /* not found */ } hashentry * hash_remove(hashtable *h, void *k) { 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)) { *pE = e->next; h->nb--; return e; } pE = &(e->next); e = e->next; } return NULL; } void hash_destroy(hashtable *h) { ulong i; if (h->use_stack) return; for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { hashentry *f = e; e = e->next; pari_free(f); } } pari_free(h->table); pari_free(h); } static int strequal(void *a, void *b) { return !strcmp((char*)a,(char*)b); } hashtable * hashstr_import_static(hashentry *e, ulong size) { hashtable *h = hash_create(size, (ulong (*)(void *))hash_str, strequal, 0); for ( ; e->key; e++) { hash_link(h, e); h->nb++; } return h; } void hashstr_dbg(hashtable *h) { ulong n, Total = 0, Max = 0; hashentry *e, **table = h->table; for (n=0; n < h->len; n++) { ulong m=0; for (e=table[n]; e; e=e->next) m++; Total += m; if (Max < m) Max = m; pari_printf("%4ld:%2ld ",n,m); if (n%9 == 8) pari_putc('\n'); } pari_printf("\nTotal = %ld, Max = %ld\n", Total, Max); } /********************************************************************/ /* */ /* HASH FUNCTIONS */ /* */ /********************************************************************/ INLINE ulong glue(ulong h, ulong a) { return (h << 5) + (h>>2) + a; } ulong hash_GEN(GEN x) { ulong h = x[0]; long tx = typ(x), lx, i; switch(tx) { /* non recursive types */ case t_INT: lx = lgefint(x); h &= TYPBITS; for (i = 1; i < lx; i++) h = glue(h, (ulong)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]); return h; /* one more special case */ case t_LIST: x = list_data(x); if (!x) return h; /* fall through */ default: if (lontyp[tx] == 2) { h = glue(h, x[1]); i = 2; } else i = 1; lx = lg(x); for (; i < lx; i++) h = glue(h, hash_GEN(gel(x,i))); return h; } } /* djb's hash */ ulong hash_str(const char *str) { ulong hash = 5381, c; while ( (c = (ulong)*str++) ) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash; } /* hashvalue's underlying hash function */ ulong hash_str2(const char *s) { ulong n = 0, c; while ( (c = (ulong)*s++) ) n = (n<<1) ^ c; return n; } pari-2.7.5/src/language/parsec.h0000644000175000017500000001303012366172547015120 0ustar billbill/* Copyright (C) 2006-2008 The PARI group. This file is part of the PARI 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" BEGINEXTERN #include "parse.h" ENDEXTERN #include "anal.h" #include "tree.h" static THREAD int pari_once; static THREAD long pari_discarded; static THREAD const char *pari_lex_start, *pari_unused_chars; static THREAD GEN pari_lasterror; static void pari_error(YYLTYPE *yylloc, char **lex, const char *s) { (void) yylloc; (void) lex; if (pari_lasterror) cgiv(pari_lasterror); pari_lasterror=strtoGENstr(s); } static THREAD pari_stack s_node; THREAD node *pari_tree; void pari_init_parser(void) { long i; const char *opname[]={"_||_", "_&&_", "_===_", "_==_", "_!=_", "_>=_", "_>_", "_<=_", "_<_", "_-_","_+_","_<<_", "_>>_", "_%_", "_\\/_", "_\\_", "_/_", "_*_","_^_","__","_--","_++","_-=_", "_+=_", "_<<=_", "_>>=_", "_%=_", "_\\/=_", "_\\=_", "_/=_", "_*=_","+_","-_","!_","_!","_'","_~","[_.._]","[_|_<-_,_]","[_|_<-_,_;_]","%","%#","#_",""}; pari_stack_init(&s_node,sizeof(*pari_tree),(void **)&pari_tree); pari_stack_alloc(&s_node,OPnboperator); parsestate_reset(); for (i=0;i 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) { pari_err(e_SYNTAX, msg, str, pari_lex_start); } void compile_varerr(const char *str) { pari_err(e_SYNTAX, "variable name expected", str, pari_lex_start); } void parsestate_reset(void) { s_node.n = OPnboperator; pari_lex_start = NULL; pari_unused_chars=NULL; pari_once=1; pari_discarded=0; pari_lasterror=NULL; } void 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; } void 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_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_unused_chars && !pari_discarded) unused_chars(pari_unused_chars,strict); else if (pari_lasterror) compile_err(GSTR(pari_lasterror),lex-1); else /* should not happen */ compile_err("syntax error",lex-1); } avma=ltop; optimizenode(s_node.n-1); code=gp_closure(s_node.n-1); parsestate_restore(&state); return code; } static long newnode(Ffunc f, long x, long y, struct node_loc *loc) { long n=pari_stack_new(&s_node); pari_tree[n].f=f; pari_tree[n].x=x; pari_tree[n].y=y; pari_tree[n].str=loc->start; pari_tree[n].len=loc->end-loc->start; pari_tree[n].flags=0; return n; } static long newconst(long x, struct node_loc *loc) { return newnode(Fconst,x,-1,loc); } static long newopcall(OPerator op, long x, long y, struct node_loc *loc) { if (y==-1) return newnode(Ffunction,op,x,loc); else return newnode(Ffunction,op,newnode(Flistarg,x,y,loc),loc); } static long newopcall3(OPerator op, long x, long y, long z, struct node_loc *loc) { return newopcall(op,newnode(Flistarg,x,y,loc),z,loc); } static long countarg(long n) { long i; for(i=1; pari_tree[n].f==Flistarg; i++) n = pari_tree[n].x; return i; } static long addcurrexpr(long n, long currexpr, struct node_loc *loc) { long y, m = n; while (pari_tree[m].x==OPcomprc) { y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x; m = pari_tree[y].y; } y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x; pari_tree[y].y = currexpr; pari_tree[n].str=loc->start; pari_tree[n].len=loc->end-loc->start; return n; } static long newintnode(struct node_loc *loc) { if (loc->end-loc->start<=(long)(1+LOG10_2*BITS_IN_LONG)) { pari_sp ltop=avma; GEN g=strtoi(loc->start); long s; avma=ltop; if (signe(g)==0) return newnode(Fsmall,0,-1,loc); if ((s=itos_or_0(g))) return newnode(Fsmall,s,-1,loc); } return newconst(CSTint,loc); } static long newfunc(CSTtype t, struct node_loc *func, long args, long code, struct node_loc *loc) { long name=newnode(Fentry,newconst(t,func),-1,func); return newnode(Fassign,name,newnode(Flambda,args,code,loc),loc); } pari-2.7.5/src/language/parse.y0000644000175000017500000002064712405547147015006 0ustar billbill%{ /* Copyright (C) 2006 The PARI group. This file is part of the PARI 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. */ #define YYSIZE_T size_t #define YYSTYPE union token_value #define YYLTYPE struct node_loc #define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).start = ((N)?(Rhs)[1].start:(Rhs)[0].end), \ (Current).end = (Rhs)[N].end) #include "parsec.h" #define NOARG(x) newnode(Fnoarg,-1,-1,&(x)) %} %error-verbose %name-prefix "pari_" %pure-parser %parse-param {char **lex} %lex-param {char **lex} %initial-action{ @$.start=@$.end=*lex; } %token KPARROW ")->" %token KARROW "->" %token KDOTDOT ".." %token KPE "+=" %token KSE "-=" %token KME "*=" %token KDE "/=" %token KDRE "\\/=" %token KEUCE "\\=" %token KMODE "%=" %token KAND "&&" %token KOR "||" %token KID "===" %token KEQ "==" %token KNE "!=" %token KGE ">=" %token KLE "<=" %token KSRE ">>=" %token KSLE "<<=" %token KSR ">>" %token KSL "<<" %token KDR "\\/" %token KPP "++" %token KSS "--" %token KINTEGER "integer" %token KREAL "real number" %token KENTRY "variable name" %token KSTRING "character string" %left SEQ DEFFUNC %left INT LVAL %right ")->" "->" %left ';' ',' ".." %right '=' "+=" "-=" "*=" "/=" "\\/=" "\\=" "%=" ">>=" "<<=" %left '&' "&&" "||" %left "===" "==" "!=" '>' ">=" '<' "<=" %left '+' '-' %left '%' "\\/" '\\' '/' '*' ">>" "<<" %left SIGN %right '^' %left '#' %left '!' '~' '[' '\'' %left '.' %left "++" "--" %left '(' %left ':' %type seq sequnused %type range matrix matrix_index expr %type lvalue %type matrixelts matrixlines arg listarg definition %type funcid memberid %type backticks history %type compr in inseq %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;} ; seq: /**/ %prec SEQ {$$=NOARG(@$);} | expr %prec SEQ {$$=$1;} | seq ';' {$$=$1; @$=@1;} | seq ';' expr {$$=newnode(Fseq,$1,$3,&@$);} ; range: /* */ { $$=newnode(Frange,NOARG(@$),NOARG(@$),&@$); } | expr { $$=newnode(Frange,$1,NOARG(@$),&@$); } | expr ".." expr { $$=newnode(Frange,$1,$3,&@$); } | '^' expr { $$=newnode(Frange,NOARG(@$),$2,&@$); } ; matrix_index: '[' range ',' range ']' {$$=newnode(Fmatrix,$2,$4,&@$);} | '[' range ']' {$$=newnode(Fmatrix,$2,-1,&@$);} ; backticks: '`' {$$=1;} | backticks '`' {$$=$1+1;} ; history: '%' {$$=newopcall(OPhist,-1,-1,&@$);} | '%' KINTEGER {$$=newopcall(OPhist,newintnode(&@2),-1,&@$);} | '%' backticks {$$=newopcall(OPhist,newnode(Fsmall,-$2,-1,&@$),-1,&@$);} | '%' '#' {$$=newopcall(OPhisttime,-1,-1,&@$);} | '%' '#' KINTEGER {$$=newopcall(OPhisttime,newintnode(&@3),-1,&@$);} | '%' '#' backticks{$$=newopcall(OPhisttime,newnode(Fsmall,-$3,-1,&@$),-1,&@$);} ; expr: KINTEGER %prec INT {$$=newintnode(&@1);} | KREAL {$$=newconst(CSTreal,&@$);} | '.' {$$=newconst(CSTreal,&@$);} | KINTEGER '.' KENTRY {$$=newnode(Ffunction,newconst(CSTmember,&@3), newintnode(&@1),&@$);} | KSTRING {$$=newconst(CSTstr,&@$);} | '\'' KENTRY {$$=newconst(CSTquote,&@$);} | history {$$=$1;} | expr '(' listarg ')' {$$=newnode(Fcall,$1,$3,&@$);} | funcid {$$=$1;} | lvalue %prec LVAL {$$=$1;} | matrix {$$=$1;} | compr {$$=$1;} | definition {$$=$1;} | matrix '=' expr {$$=newnode(Fassign,$1,$3,&@$);} | lvalue '=' expr {$$=newnode(Fassign,$1,$3,&@$);} | lvalue "++" {$$=newopcall(OPpp,$1,-1,&@$);} | lvalue "--" {$$=newopcall(OPss,$1,-1,&@$);} | lvalue "*=" expr {$$=newopcall(OPme,$1,$3,&@$);} | lvalue "/=" expr {$$=newopcall(OPde,$1,$3,&@$);} | lvalue "\\/=" expr {$$=newopcall(OPdre,$1,$3,&@$);} | lvalue "\\=" expr {$$=newopcall(OPeuce,$1,$3,&@$);} | lvalue "%=" expr {$$=newopcall(OPmode,$1,$3,&@$);} | lvalue "<<=" expr {$$=newopcall(OPsle,$1,$3,&@$);} | lvalue ">>=" expr {$$=newopcall(OPsre,$1,$3,&@$);} | lvalue "+=" expr {$$=newopcall(OPpe,$1,$3,&@$);} | lvalue "-=" expr {$$=newopcall(OPse,$1,$3,&@$);} | '!' expr {$$=newopcall(OPnb,$2,-1,&@$);} | '#' expr {$$=newopcall(OPlength,$2,-1,&@$);} | expr "||" expr {$$=newopcall(OPor,$1,$3,&@$);} | expr "&&" expr {$$=newopcall(OPand,$1,$3,&@$);} | expr '&' expr {$$=newopcall(OPand,$1,$3,&@$);} | expr "===" expr {$$=newopcall(OPid,$1,$3,&@$);} | expr "==" expr {$$=newopcall(OPeq,$1,$3,&@$);} | expr "!=" expr {$$=newopcall(OPne,$1,$3,&@$);} | expr ">=" expr {$$=newopcall(OPge,$1,$3,&@$);} | expr '>' expr {$$=newopcall(OPg,$1,$3,&@$);} | expr "<=" expr {$$=newopcall(OPle,$1,$3,&@$);} | expr '<' expr {$$=newopcall(OPl,$1,$3,&@$);} | expr '-' expr {$$=newopcall(OPs,$1,$3,&@$);} | expr '+' expr {$$=newopcall(OPp,$1,$3,&@$);} | expr "<<" expr {$$=newopcall(OPsl,$1,$3,&@$);} | expr ">>" expr {$$=newopcall(OPsr,$1,$3,&@$);} | expr '%' expr {$$=newopcall(OPmod,$1,$3,&@$);} | expr "\\/" expr {$$=newopcall(OPdr,$1,$3,&@$);} | expr '\\' expr {$$=newopcall(OPeuc,$1,$3,&@$);} | expr '/' expr {$$=newopcall(OPd,$1,$3,&@$);} | expr '*' expr {$$=newopcall(OPm,$1,$3,&@$);} | '+' expr %prec SIGN {$$=$2;} | '-' expr %prec SIGN {$$=newopcall(OPn,$2,-1,&@$);} | expr '^' expr {$$=newopcall(OPpow,$1,$3,&@$);} | expr '~' {$$=newopcall(OPtrans,$1,-1,&@$);} | expr '\'' {$$=newopcall(OPderiv,$1,-1,&@$);} | expr '!' {$$=newopcall(OPfact,$1,-1,&@$);} | expr matrix_index {$$=newnode(Fmatcoeff,$1,$2,&@$);} | memberid {$$=$1;} | expr ':' KENTRY {$$=newnode(Ftag,$1,0,&@$);} | '(' expr ')' {$$=$2;} ; lvalue: KENTRY %prec LVAL {$$=newnode(Fentry,newconst(CSTentry,&@1),-1,&@$);} | lvalue matrix_index {$$=newnode(Fmatcoeff,$1,$2,&@$);} | lvalue ':' KENTRY {$$=newnode(Ftag,$1,newconst(CSTentry,&@2),&@$);} ; matrixelts: expr {$$=$1;} | matrixelts ',' expr {$$=newnode(Fmatrixelts,$1,$3,&@$);} ; matrixlines: matrixelts ';' matrixelts {$$=newnode(Fmatrixlines,$1,$3,&@$);} | matrixlines ';' matrixelts {$$=newnode(Fmatrixlines,$1,$3,&@$);} ; matrix: '[' ']' {$$=newnode(Fvec,-1,-1,&@$);} | '[' expr ".." expr ']' {$$=newopcall(OPrange,$2,$4,&@$);} | '[' ';' ']' {$$=newnode(Fmat,-1,-1,&@$);} | '[' matrixelts ']' {$$=newnode(Fvec,$2,-1,&@$);} | '[' matrixlines ']' {$$=newnode(Fmat,$2,-1,&@$);} | '[' error ']' {$$=-1; YYABORT;} ; in: lvalue '<' '-' expr {$$=newnode(Flistarg,$4,$1,&@$);} ; inseq: in {$$=newopcall(OPcompr,$1,-2,&@$);} | in ',' expr {$$=newopcall3(OPcompr,$1,-2,$3,&@$);} | in ';' inseq {$$=newopcall(OPcomprc,$1,$3,&@$);} | in ',' expr ';' inseq {$$=newopcall3(OPcomprc,$1,$5,$3,&@$);} ; compr: '[' expr '|' inseq ']' {$$=addcurrexpr($4,$2,&@$);} ; arg: seq {$$=$1;} | '&' lvalue {$$=newnode(Frefarg,$2,-1,&@$);} | arg error {if (!pari_once) { yyerrok; } pari_once=1;} expr {pari_once=0; $$=newopcall(OPcat,$1,$4,&@$);} ; listarg: arg {$$=$1;} | listarg ',' arg {$$=newnode(Flistarg,$1,$3,&@$);} ; funcid: KENTRY '(' listarg ')' {$$=newnode(Ffunction,newconst(CSTentry,&@1),$3,&@$);} ; memberid: expr '.' KENTRY {$$=newnode(Ffunction,newconst(CSTmember,&@3),$1,&@$);} ; definition: KENTRY '(' listarg ')' '=' seq %prec DEFFUNC {$$=newfunc(CSTentry,&@1,$3,$6,&@$);} | expr '.' KENTRY '=' seq %prec DEFFUNC {$$=newfunc(CSTmember,&@3,$1,$5,&@$);} | lvalue "->" seq {$$=newnode(Flambda, $1,$3,&@$);} | '(' listarg ")->" seq {$$=newnode(Flambda, $2,$4,&@$);} ; %% pari-2.7.5/src/language/sumiter.c0000644000175000017500000013015412571633357015334 0ustar billbill/* 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" GEN iferrpari(GEN a, GEN b, GEN c) { GEN res; struct pari_evalstate state; evalstate_save(&state); pari_CATCH(CATCH_ALL) { GEN E; if (!b&&!c) return gnil; E = evalstate_restore_err(&state); if (c) { push_lex(E,c); res = closure_evalgen(c); pop_lex(1); if (gequal0(res)) pari_err(0, E); } if (!b) return gnil; push_lex(E,b); res = closure_evalgen(b); pop_lex(1); return res; } pari_TRY { res = closure_evalgen(a); } pari_ENDCATCH; return res; } /********************************************************************/ /** **/ /** ITERATIONS **/ /** **/ /********************************************************************/ static void forparii(GEN a, GEN b, GEN code) { pari_sp av, av0 = avma, lim; GEN aa; if (gcmp(b,a) < 0) return; b = gfloor(b); aa = a = setloop(a); av=avma; lim = stack_lim(av,1); push_lex(a,code); while (gcmp(a,b) <= 0) { closure_evalvoid(code); if (loop_break()) break; a = get_lex(-1); if (a == aa) { a = incloop(a); if (a != aa) { set_lex(-1,a); aa = a; } } else { /* 'code' modified a ! Be careful (and slow) from now on */ a = gaddgs(a,1); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"forparii"); a = gerepileupto(av,a); } set_lex(-1,a); } } pop_lex(1); avma = av0; } void forpari(GEN a, GEN b, GEN code) { pari_sp ltop=avma, av, lim; 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); 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 (DEBUGMEM>1) pari_warn(warnmem,"forpari"); a = gerepileupto(av,a); } set_lex(-1, a); } pop_lex(1); avma = ltop; } void whilepari(GEN a, GEN b) { pari_sp av = avma; for(;;) { GEN res = closure_evalnobrk(a); if (gequal0(res)) break; avma = av; closure_evalvoid(b); if (loop_break()) break; } avma = av; } void untilpari(GEN a, GEN b) { pari_sp av = avma; for(;;) { GEN res; closure_evalvoid(b); if (loop_break()) break; res = closure_evalnobrk(a); if (!gequal0(res)) break; avma = av; } avma = av; } static int negcmp(GEN x, GEN y) { return gcmp(y,x); } void forstep(GEN a, GEN b, GEN s, GEN code) { long ss, i; pari_sp av, av0 = avma, lim; GEN v = NULL; int (*cmp)(GEN,GEN); b = gcopy(b); av=avma; lim = stack_lim(av,1); push_lex(a,code); if (is_vec_t(typ(s))) { v = s; s = gen_0; for (i=lg(v)-1; i; i--) s = gadd(s,gel(v,i)); } ss = gsigne(s); if (!ss) pari_err_DOMAIN("forstep","step","=",gen_0,s); cmp = (ss > 0)? &gcmp: &negcmp; i = 0; while (cmp(a,b) <= 0) { closure_evalvoid(code); if (loop_break()) break; if (v) { if (++i >= lg(v)) i = 1; s = gel(v,i); } a = get_lex(-1); a = gadd(a,s); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"forstep"); a = gerepileupto(av,a); } set_lex(-1,a); } pop_lex(1); avma = av0; } /* return good chunk size for sieve, 16 | chunk + 2 */ static ulong optimize_chunk(ulong a, ulong b) { /* TODO: Optimize size (surely < 512k to stay in L1 cache, but not so large */ /* as to force recalculating too often). */ /* Guesstimate: greater of sqrt(n) * lg(n) or 1M */ ulong chunk = maxuu(0x100000, usqrt(b) * expu(b)); ulong tmp = (b - a) / chunk + 1; if (tmp == 1) chunk = b - a + 16; else chunk = (b - a) / tmp + 15; /* Don't take up more than 2/3 of the stack */ chunk = minuu(chunk, avma - stack_lim(avma, 2)); /* ensure 16 | chunk + 2 */ return (((chunk + 2)>>4)<<4) - 2; } static void sieve_init(forprime_t *T, ulong a, ulong b) { T->sieveb = b; T->chunk = optimize_chunk(a, b); T->sieve = (unsigned char*)stack_malloc(((T->chunk+2) >> 4) + 1); T->cache[0] = 0; /* >> 1 [only odds] + 3 [convert from bits to bytes] */ T->a = a; T->end = minuu(a + T->chunk, b); T->pos = T->maxpos = 0; } static void u_forprime_set_prime_table(forprime_t *T, ulong a) { T->strategy = 1; if (a < 3) { T->p = 0; T->d = diffptr; } else T->p = init_primepointer_lt(a, &T->d); } /* Set p so that p + q the smallest integer = c (mod q) and > original p. * Assume 0 < c < q. Set p = 0 on overflow */ static void arith_set(forprime_t *T) { ulong r = T->p % T->q; /* 0 <= r <= min(p, q-1) */ pari_sp av = avma; GEN d = adduu(T->p - r, T->c); if (T->c > r) d = subiu(d, T->q); /* d = c mod q, d = c > r? p-r+c-q: p-r+c, so that * d <= p and d+q = c>r? p-r+c : p-r+c+q > p */ T->p = itou_or_0(d); avma = av; /* d = 0 is impossible */ } /* run through primes in arithmetic progression = c (mod q). * Assume (c,q)=1, 0 <= c < q */ int u_forprime_arith_init(forprime_t *T, ulong a, ulong b, ulong c, ulong q) { ulong maxp, maxp2; if (a > b || b < 2) { T->strategy = 1; /* paranoia */ T->p = 0; /* empty */ T->b = 0; /* empty */ T->d = diffptr; return 0; } maxp = maxprime(); if (q != 1 && c != 2 && odd(q)) { /* only allow *odd* primes. If c = 2, then p = 2 must be included :-( */ if (!odd(c)) c += q; q <<= 1; } T->q = q; T->c = c; T->strategy = 0; /* unknown */ T->sieve = NULL; /* unused for now */ if (!odd(b) && b > 2) b--; T->b = b; if (maxp >= b) { /* [a,b] \subset prime table */ u_forprime_set_prime_table(T, a); return 1; } /* b > maxp */ if (a >= maxp) { if (T->q == 1) T->p = a - 1; else arith_set(T); } else u_forprime_set_prime_table(T, a); maxp2 = (maxp & HIGHMASK)? 0 : maxp*maxp; /* FIXME: should sieve as well if q != 1, adapt sieve code */ if (q != 1 || (maxp2 && maxp2 <= a) || T->b - maxuu(a,maxp) < maxp / expu(b)) { if (!T->strategy) T->strategy = 3; } else { /* worth sieving */ #ifdef LONG_IS_64BIT const ulong UPRIME_MAX = 18446744073709551557UL; #else const ulong UPRIME_MAX = 4294967291UL; #endif ulong sieveb; if (b > UPRIME_MAX) b = UPRIME_MAX; sieveb = b; if (maxp2 && maxp2 < b) sieveb = maxp2; if (!T->strategy) T->strategy = 2; sieve_init(T, maxuu(maxp+2, a), sieveb); } return 1; } /* will run through primes in [a,b] */ int u_forprime_init(forprime_t *T, ulong a, ulong b) { return u_forprime_arith_init(T, a,b, 0,1); } /* now only run through primes <= c; assume c <= b above */ void u_forprime_restrict(forprime_t *T, ulong c) { T->b = c; } /* b = NULL: loop forever */ int forprime_init(forprime_t *T, GEN a, GEN b) { long lb; a = gceil(a); if (typ(a) != t_INT) pari_err_TYPE("forprime_init",a); if (signe(a) <= 0) a = gen_1; if (b) { b = gfloor(b); if (typ(b) != t_INT) pari_err_TYPE("forprime_init",b); if (signe(b) < 0 || cmpii(a,b) > 0) { T->strategy = 4; /* paranoia */ T->bb = gen_0; T->pp = gen_0; return 0; } lb = lgefint(b); } else lb = lgefint(a) + 4; T->bb = 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); T->strategy = 4; affii(subiu(a,1), T->pp); return 1; } /* assume a <= b <= maxprime()^2, a,b odd, sieve[n] corresponds to * a+16*n, a+16*n+2, ..., a+16*n+14 (bits 0 to 7) * maxpos = index of last sieve cell. */ static void sieve_block(ulong a, ulong b, ulong maxpos, unsigned char* sieve) { ulong p = 2, lim = usqrt(b), sz = (b-a) >> 1; byteptr d = diffptr+1; (void)memset(sieve, 0, maxpos+1); for (;;) { /* p is odd */ ulong k, r; NEXT_PRIME_VIADIFF(p, d); /* starts at p = 3 */ if (p > lim) break; /* solve a + 2k = 0 (mod p) */ r = a % p; if (r == 0) k = 0; else { k = p - r; if (odd(k)) k += p; k >>= 1; } /* m = a + 2k is the smallest odd m >= a, p | m */ /* position n (corresponds to a+2n) is sieve[n>>3], bit n&7 */ while (k <= sz) { sieve[k>>3] |= 1 << (k&7); k += p; /* 2k += 2p */ } } } /* T->cache is a 0-terminated list of primes, return the first one and * remove it from list. Most of the time the list contains a single prime */ static ulong shift_cache(forprime_t *T) { long i; T->p = T->cache[0]; for (i = 1;; i++) /* remove one prime from cache */ if (! (T->cache[i-1] = T->cache[i]) ) break; return T->p; } ulong u_forprime_next(forprime_t *T) { if (T->strategy == 1) { for(;;) { if (!*(T->d)) { T->strategy = T->sieve? 2: 3; if (T->q != 1) { arith_set(T); if (!T->p) return 0; } /* T->p possibly not a prime if q != 1 */ break; } else { NEXT_PRIME_VIADIFF(T->p, T->d); if (T->p > T->b) return 0; if (T->q == 1 || T->p % T->q == T->c) return T->p; } } } if (T->strategy == 2) { ulong n; if (T->cache[0]) return shift_cache(T); NEXT_CHUNK: for (n = T->pos; n < T->maxpos; n++) if (T->sieve[n] != 0xFF) { unsigned char mask = T->sieve[n]; ulong p = T->a + (n<<4); long i = 0; T->pos = n; if (!(mask & 1)) T->cache[i++] = p; if (!(mask & 2)) T->cache[i++] = p+2; if (!(mask & 4)) T->cache[i++] = p+4; if (!(mask & 8)) T->cache[i++] = p+6; if (!(mask & 16)) T->cache[i++] = p+8; if (!(mask & 32)) T->cache[i++] = p+10; if (!(mask & 64)) T->cache[i++] = p+12; if (!(mask &128)) T->cache[i++] = p+14; T->cache[i] = 0; T->pos = n+1; return shift_cache(T); } /* n = T->maxpos, last cell: check p <= b */ if (T->maxpos && n == T->maxpos && T->sieve[n] != 0xFF) { unsigned char mask = T->sieve[n]; ulong p = T->a + (n<<4); long i = 0; T->pos = n; if (!(mask & 1) && p <= T->sieveb) T->cache[i++] = p; if (!(mask & 2) && p <= T->sieveb-2) T->cache[i++] = p+2; if (!(mask & 4) && p <= T->sieveb-4) T->cache[i++] = p+4; if (!(mask & 8) && p <= T->sieveb-6) T->cache[i++] = p+6; if (!(mask & 16) && p <= T->sieveb-8) T->cache[i++] = p+8; if (!(mask & 32) && p <= T->sieveb-10) T->cache[i++] = p+10; if (!(mask & 64) && p <= T->sieveb-12) T->cache[i++] = p+12; if (!(mask &128) && p <= T->sieveb-14) T->cache[i++] = p+14; if (i) { T->cache[i] = 0; T->pos = n+1; return shift_cache(T); } } if (T->maxpos && T->end >= T->sieveb) /* done with sieves ? */ { if (T->sieveb == T->b && T->b != ULONG_MAX) return 0; T->strategy = 3; } else { /* initialize next chunk */ if (T->maxpos == 0) T->a |= 1; /* first time; ensure odd */ else T->a = (T->end + 2) | 1; T->end = T->a + T->chunk; /* may overflow */ if (T->end < T->a || T->end > T->sieveb) T->end = T->sieveb; /* end and a are odd; sieve[k] contains the a + 8*2k + (0,2,...,14). * The largest k is (end-a) >> 4 */ T->pos = 0; T->maxpos = (T->end - T->a) >> 4; sieve_block(T->a, T->end, T->maxpos, T->sieve); goto NEXT_CHUNK; } } if (T->strategy == 3) { if (T->q == 1) T->p = unextprime(T->p + 1); else { do { T->p += T->q; if (T->p < T->q) return 0; /* overflow */ } while (!uisprime(T->p)); } if (!T->p) /* overflow ulong, switch to GEN */ T->strategy = 4; else { if (T->p > T->b) return 0; return T->p; } } return 0; /* overflow */ } GEN forprime_next(forprime_t *T) { pari_sp av; GEN p; if (T->strategy <= 3) { ulong q = u_forprime_next(T); if (q) { affui(q, T->pp); return T->pp; } /* failure */ if (T->strategy <= 3) return NULL; /* we're done */ /* overflow ulong, switch to GEN */ affui(ULONG_MAX, T->pp); /* initialize */ } av = avma; p = nextprime(addiu(T->pp, 1)); if (T->bb && absi_cmp(p, T->bb) > 0) { avma = av; return NULL; } affii(p, T->pp); avma = av; return T->pp; } void forprime(GEN a, GEN b, GEN code) { pari_sp av = avma; forprime_t T; if (!forprime_init(&T, a,b)) { avma = av; return; } push_lex(T.pp,code); while(forprime_next(&T)) { closure_evalvoid(code); if (loop_break()) break; /* p changed in 'code', complain */ if (get_lex(-1) != T.pp) pari_err(e_MISC,"prime index read-only: was changed to %Ps", get_lex(-1)); } pop_lex(1); avma = av; } int forcomposite_init(forcomposite_t *C, GEN a, GEN b) { pari_sp av = avma; a = gceil(a); if (typ(a)!=t_INT) pari_err_TYPE("forcomposite",a); if (b) { b = gfloor(b);if (typ(b)!=t_INT) pari_err_TYPE("forcomposite",b); } if (signe(a) < 0) pari_err_DOMAIN("forcomposite", "a", "<", gen_0, a); if (cmpiu(a, 4) < 0) a = utoipos(4); C->first = 1; if (!forprime_init(&C->T, a,b)) { C->n = gen_1; /* in case caller forgets to check the return value */ C->b = gen_0; avma = av; return 0; } C->n = setloop(a); C->b = b; C->p = NULL; return 1; } GEN forcomposite_next(forcomposite_t *C) { if (C->first) /* first call ever */ { C->first = 0; C->p = forprime_next(&C->T); } else C->n = incloop(C->n); if (C->p) { if (cmpii(C->n, C->p) < 0) return C->n; C->n = incloop(C->n); /* n = p+1 */ C->p = forprime_next(&C->T); /* nextprime(p) > n */ if (C->p) return C->n; } if (!C->b || cmpii(C->n, C->b) <= 0) return C->n; return NULL; } void forcomposite(GEN a, GEN b, GEN code) { pari_sp av = avma; forcomposite_t T; GEN n; if (!forcomposite_init(&T,a,b)) return; push_lex(T.n,code); while((n = forcomposite_next(&T))) { closure_evalvoid(code); if (loop_break()) break; /* n changed in 'code', complain */ if (get_lex(-1) != n) pari_err(e_MISC,"index read-only: was changed to %Ps", get_lex(-1)); } pop_lex(1); avma = av; } void fordiv(GEN a, GEN code) { long i, l; pari_sp av2, av = avma; GEN t = divisors(a); push_lex(gen_0,code); l=lg(t); av2 = avma; for (i=1; ia [over integers]*/ static GEN _next_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { if (cmpii(d->a[i], d->M[i]) < 0) { d->a[i] = incloop(d->a[i]); return (GEN)d->a; } d->a[i] = resetloop(d->a[i], d->m[i]); if (--i <= 0) return NULL; } } /* increment and return d->a [generic]*/ static GEN _next(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) return (GEN)d->a; d->a[i] = d->m[i]; if (--i <= 0) return NULL; } } /* non-decreasing order [over integers] */ static GEN _next_le_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { 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] */ 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] */ 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])*/ } return (GEN)d->a; } d->a[i] = resetloop(d->a[i], d->m[i]); if (--i <= 0) return NULL; } } /* non-decreasing order [generic] */ static GEN _next_le(forvec_t *d) { long i = d->n, imin = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) { while (i < d->n) { 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); } } 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] */ static GEN _next_lt_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { 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] */ while (i < d->n) { pari_sp av; GEN t; i++; if (cmpii(d->a[i-1], d->a[i]) < 0) continue; av = avma; /* a[i-1] <= M[i-1] < M[i] */ 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; } return (GEN)d->a; } d->a[i] = resetloop(d->a[i], d->m[i]); if (--i <= 0) return NULL; } } /* strictly increasing order [generic] */ static GEN _next_lt(forvec_t *d) { long i = d->n, imin = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) { while (i < d->n) { 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; } } return (GEN)d->a; } d->a[i] = d->m[i]; if (--i <= 0) return NULL; if (i < imin) imin = i; } } /* for forvec(v=[],) */ static GEN _next_void(forvec_t *d) { if (d->first) { d->first = 0; return (GEN)d->a; } return NULL; } /* Initialize minima (m) and maxima (M); guarantee * 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] */ int forvec_init(forvec_t *d, GEN x, long flag) { long i, tx = typ(x), l = lg(x), t = t_INT; if (!is_vec_t(tx)) pari_err_TYPE("forvec [not a vector]", x); d->first = 1; d->n = l - 1; d->a = (GEN*)cgetg(l,tx); d->m = (GEN*)cgetg(l,tx); d->M = (GEN*)cgetg(l,tx); if (l == 1) { d->next = &_next_void; return 1; } for (i = 1; i < l; i++) { GEN a, e = gel(x,i), m = gel(e,1), M = gel(e,2); tx = typ(e); if (! is_vec_t(tx) || lg(e)!=3) pari_err_TYPE("forvec [expected vector not of type [min,MAX]]",e); if (typ(m) != t_INT) t = t_REAL; if (i > 1) switch(flag) { case 1: /* a >= m[i-1] - m */ a = gceil(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); break; case 2: /* a > m[i-1] - m */ a = gfloor(gsub(d->m[i-1], m)); if (typ(a) != t_INT) pari_err_TYPE("forvec",a); a = addis(a, 1); if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m); break; default: m = gcopy(m); break; } 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--) { 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; } if (t == t_INT) { for (i = 1; i < l; i++) { d->a[i] = setloop(d->m[i]); if (typ(d->M[i]) != t_INT) d->M[i] = gfloor(d->M[i]); } } else { for (i = 1; i < l; i++) d->a[i] = d->m[i]; } switch(flag) { case 0: d->next = t==t_INT? &_next_i: &_next; break; case 1: d->next = t==t_INT? &_next_le_i: &_next_le; break; case 2: d->next = t==t_INT? &_next_lt_i: &_next_lt; break; default: pari_err_FLAG("forvec"); } return 1; } GEN forvec_next(forvec_t *d) { return d->next(d); } void forvec(GEN x, GEN code, long flag) { pari_sp av = avma; forvec_t T; GEN v; if (!forvec_init(&T, x, flag)) { avma = av; return; } push_lex((GEN)T.a, code); while ((v = forvec_next(&T))) { closure_evalvoid(code); if (loop_break()) break; } pop_lex(1); avma = av; } /********************************************************************/ /** **/ /** SUMS **/ /** **/ /********************************************************************/ GEN somme(GEN a, GEN b, GEN code, GEN x) { pari_sp av, av0 = avma, lim; GEN p1; if (typ(a) != t_INT) pari_err_TYPE("sum",a); if (!x) x = gen_0; if (gcmp(b,a) < 0) return gcopy(x); b = gfloor(b); a = setloop(a); av=avma; lim = stack_lim(av,1); 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 (DEBUGMEM>1) pari_warn(warnmem,"sum"); x = gerepileupto(av,x); } set_lex(-1,a); } pop_lex(1); return gerepileupto(av0,x); } GEN suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { long fl, G; pari_sp av0 = avma, av, lim; 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); fl=0; G = prec2nbits(prec) + 5; for(;;) { p1 = eval(E, a); x = gadd(x,p1); a = incloop(a); if (gequal0(p1) || gexpo(p1) <= gexpo(x)-G) { if (++fl==3) break; } else fl=0; if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"suminf"); x = gerepileupto(av,x); } } return gerepileupto(av0, gaddgs(x,-1)); } GEN suminf0(GEN a, GEN code, long prec) { EXPR_WRAP(code, suminf(EXPR_ARG, a, prec)); } GEN sumdivexpr(GEN num, GEN code) { pari_sp av = avma; GEN y = gen_0, t = divisors(num); long i, l = lg(t); push_lex(gen_0, code); for (i=1; i= 0) break; a = incloop(a); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"prod"); x = gerepileupto(av,x); } set_lex(-1,a); } pop_lex(1); return gerepileupto(av0,x); } GEN prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { pari_sp av0 = avma, av, lim; 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); fl=0; G = -prec2nbits(prec)-5; for(;;) { p1 = eval(E, a); if (gequal0(p1)) { x = p1; break; } 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 (DEBUGMEM>1) pari_warn(warnmem,"prodinf"); x = gerepileupto(av,x); } } return gerepilecopy(av0,x); } GEN prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { pari_sp av0 = avma, av, lim; 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); fl=0; G = -prec2nbits(prec)-5; for(;;) { p2 = eval(E, a); p1 = gaddgs(p2,1); 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 (DEBUGMEM>1) pari_warn(warnmem,"prodinf1"); x = gerepileupto(av,x); } } return gerepilecopy(av0,x); } GEN prodinf0(GEN a, GEN code, long flag, long prec) { switch(flag) { case 0: EXPR_WRAP(code, prodinf (EXPR_ARG, a, prec)); case 1: EXPR_WRAP(code, prodinf1(EXPR_ARG, a, prec)); } pari_err_FLAG("prodinf"); return NULL; /* not reached */ } GEN prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec) { pari_sp av, av0 = avma, lim; GEN x = real_1(prec), prime; forprime_t T; av = avma; 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 (DEBUGMEM>1) pari_warn(warnmem,"prodeuler"); x = gerepilecopy(av, x); } } return gerepilecopy(av0,x); } GEN prodeuler0(GEN a, GEN b, GEN code, long prec) { EXPR_WRAP(code, prodeuler(EXPR_ARG, a, b, prec)); } static void err_direuler(GEN x) { pari_err_DOMAIN("direuler","constant term","!=", gen_1,x); } 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); long j, tx, lx; GEN x, y, s, polnum, polden, prime; forprime_t T; if (c) { if (typ(c) != t_INT) { 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 (!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); } y = cgetg(n+1,t_VEC); av = avma; x = zerovec(n); gel(x,1) = gen_1; while ( (prime = forprime_next(&T)) ) { ulong p = prime[2]; s = eval(E, prime); polnum = numer(s); polden = denom(s); tx = typ(polnum); if (is_scalar_t(tx)) { if (!gequal1(polnum)) { if (!gequalm1(polnum)) err_direuler(polnum); polden = gneg(polden); } } else { ulong k1, q, qlim; if (tx != t_POL) pari_err_TYPE("direuler",polnum); lx = degpol(polnum); if (lx < 0) err_direuler(polnum); c = gel(polnum,2); if (!gequal1(c)) { if (!gequalm1(c)) err_direuler(polnum); polnum = gneg(polnum); polden = gneg(polden); } for (i=1; i<=n; i++) gel(y,i) = gel(x,i); q = p; qlim = n/p; for (j = 1; q<=n && j<=lx; j++) { c = gel(polnum,j+2); if (!gequal0(c)) for (k=1,k1=q; k1<=n; k1+=q,k++) gel(x,k1) = gadd(gel(x,k1), gmul(c,gel(y,k))); if (q > qlim) break; q *= p; } } tx = typ(polden); if (is_scalar_t(tx)) { if (!gequal1(polden)) pari_err_DOMAIN("direuler","constant term", "!=", gen_1,polden); } else { if (tx != t_POL) pari_err_TYPE("direuler",polden); c = gel(polden,2); if (!gequal1(c)) pari_err_DOMAIN("direuler","constant term", "!=", gen_1,polden); lx = degpol(polden); for (i=p; i<=n; i+=p) { s = gen_0; k = i; for (j = 1; !(k%p) && j<=lx; j++) { c = gel(polden,j+2); k /= p; if (!gequal0(c)) s = gadd(s, gmul(c,gel(x,k))); } gel(x,i) = gsub(gel(x,i),s); } } if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"direuler"); x = gerepilecopy(av, x); } } return gerepilecopy(av0,x); } GEN direuler0(GEN a, GEN b, GEN code, GEN c) { EXPR_WRAP(code, direuler(EXPR_ARG, a, b, c)); } /********************************************************************/ /** **/ /** VECTORS & MATRICES **/ /** **/ /********************************************************************/ INLINE GEN copyupto(GEN z, GEN t) { if (is_universal_constant(z) || (z>(GEN)bot && z<=t)) return z; else return gcopy(z); } GEN vecexpr0(GEN vec, GEN code, GEN pred) { switch(typ(vec)) { case t_LIST: { vec = list_data(vec); if (!vec) return cgetg(1, t_VEC); break; } case t_VEC: case t_COL: case t_MAT: break; default: pari_err_TYPE("[_|_<-_,_]",vec); } if (pred && code) EXPR_WRAP(code,vecselapply((void*)pred,&gp_evalbool,EXPR_ARGUPTO,vec)) else if (code) EXPR_WRAP(code,vecapply(EXPR_ARGUPTO,vec)) else EXPR_WRAP(pred,vecselect(EXPR_ARGBOOL,vec)) } GEN vecexpr1(GEN vec, GEN code, GEN pred) { GEN v = vecexpr0(vec, code, pred); return lg(v) == 1? v: shallowconcat1(v); } GEN vecteur(GEN nmax, GEN code) { GEN y,p1; long i,m; GEN c=utoipos(1); m = gtos(nmax); if (m < 0) pari_err_DOMAIN("vector", "dimension", "<", gen_0, stoi(m)); if (!code) return zerovec(m); y = cgetg(m+1,t_VEC); push_lex(c, code); for (i=1; i<=m; i++) { c[2] = i; p1 = closure_evalnobrk(code); gel(y,i) = copyupto(p1, y); set_lex(-1,c); } pop_lex(1); return y; } GEN vecteursmall(GEN nmax, GEN code) { GEN y; long i,m; GEN c=utoipos(1); m = gtos(nmax); if (m < 0) pari_err_DOMAIN("vectorsmall", "dimension", "<", gen_0, stoi(m)); if (!code) return zero_zv(m); y = cgetg(m+1,t_VECSMALL); push_lex(c,code); for (i=1; i<=m; i++) { c[2] = i; y[i] = gtos(closure_evalnobrk(code)); set_lex(-1,c); } pop_lex(1); return y; } GEN vvecteur(GEN nmax, GEN n) { GEN y = vecteur(nmax,n); settyp(y,t_COL); return y; } GEN matrice(GEN nlig, GEN ncol, GEN code) { GEN y, z, p1; long i, j, m, n; GEN c1 = utoipos(1), c2 = utoipos(1); m = gtos(ncol); n = gtos(nlig); if (m < 0) pari_err_DOMAIN("matrix", "nbcols", "<", gen_0, stoi(m)); if (n < 0) pari_err_DOMAIN("matrix", "nbrows", "<", gen_0, stoi(n)); if (!m) return cgetg(1,t_MAT); if (!code || !n) return zeromatcopy(n, m); push_lex(c1,code); push_lex(c2,NULL); y = cgetg(m+1,t_MAT); for (i=1; i<=m; i++) { c2[2] = i; z = cgetg(n+1,t_COL); gel(y,i) = z; for (j=1; j<=n; j++) { c1[2] = j; p1 = closure_evalnobrk(code); gel(z,j) = copyupto(p1, y); set_lex(-2,c1); set_lex(-1,c2); } } pop_lex(2); return y; } /********************************************************************/ /** **/ /** SUMMING SERIES **/ /** **/ /********************************************************************/ GEN polzag(long n, long m) { 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)); } #ifdef _MSC_VER /* Bill Daly: work around a MSVC bug */ #pragma optimize("g",off) #endif static GEN polzagreel(long n, long m, long prec) { const long d = n - m, d2 = d<<1, r = (m+1)>>1; long j, k, k2; 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++) { gel(v,d-k) = gen_1; for (j=1; j1) pari_warn(warnmem,"sumalt, k = %ld/%ld", k,N-1); gerepileall(av2, 3, &az,&c,&s); } } return gerepileupto(av, gdiv(s,d)); } GEN sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { long k, N; pari_sp av = avma, av2, lim; 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); a = setloop(a); N = degpol(pol); s = gen_0; av2 = avma; lim = stack_lim(av,4); for (k=0; k<=N; k++) { s = gadd(s, gmul(gel(pol,k+2), eval(E, a))); if (k == N) break; a = incloop(a); /* in place! */ if (low_stack(lim, stack_lim(av,4))) { if (DEBUGMEM>1) pari_warn(warnmem,"sumalt2, k = %ld/%ld", k,N-1); s = gerepileupto(av2, s); } } return gerepileupto(av, gdiv(s,dn)); } GEN sumalt0(GEN a, GEN code, long flag, long prec) { switch(flag) { case 0: EXPR_WRAP(code, sumalt (EXPR_ARG,a,prec)); case 1: EXPR_WRAP(code, sumalt2(EXPR_ARG,a,prec)); default: pari_err_FLAG("sumalt"); } return NULL; /* not reached */ } GEN sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { long k, kk, N, G; pari_sp av = avma; GEN r, reel, s, az, c, x, e1, d, *stock; 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); 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; for (k=0; k>1,prec+EXTRAPRECWORD); pol = RgX_div_by_X_x(pol, gen_1, &dn); for (k=1; k<=lg(pol)-2; k++) { GEN p1 = gmul(gel(pol,k+1),stock[k]); if (!odd(k)) p1 = gneg_i(p1); s = gadd(s,p1); } return gerepileupto(av, gdiv(s,dn)); } GEN sumpos0(GEN a, GEN code, long flag, long prec) { switch(flag) { case 0: EXPR_WRAP(code, sumpos (EXPR_ARG,a,prec)); case 1: EXPR_WRAP(code, sumpos2(EXPR_ARG,a,prec)); default: pari_err_FLAG("sumpos"); } return NULL; /* not reached */ } /********************************************************************/ /** **/ /** SEARCH FOR REAL ZEROS of an expression **/ /** **/ /********************************************************************/ /* Brent's method, [a,b] bracketing interval */ GEN zbrent(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec) { long sig, iter, itmax; pari_sp av = avma; GEN c, d, e, tol, fa, fb, fc; a = gtofp(a,prec); b = gtofp(b,prec); sig = cmprr(b,a); if (!sig) return gerepileupto(av, a); if (sig < 0) { c=a; a=b; b=c; } else c = b; fa = eval(E, a); fb = eval(E, b); if (gsigne(fa)*gsigne(fb) > 0) pari_err_DOMAIN("solve", "f(a)f(b)", ">", gen_0, mkvec2(fa,fb)); itmax = prec2nbits(prec) * 2 + 1; tol = real2n(5-prec2nbits(prec), LOWDEFAULTPREC); fc = fb; e = d = NULL; /* gcc -Wall */ for (iter=1; iter<=itmax; iter++) { GEN xm, tol1; if (gsigne(fb)*gsigne(fc) > 0) { c = a; fc = fa; e = d = subrr(b,a); } if (gcmp(gabs(fc,0),gabs(fb,0)) < 0) { a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; } tol1 = absr_cmp(tol, b) > 0? sqrr(tol): mulrr(tol, absr(b)); xm = shiftr(subrr(c,b),-1); if (absr_cmp(xm,tol1) <= 0 || gequal0(fb)) break; /* SUCCESS */ if (absr_cmp(e,tol1) >= 0 && gcmp(gabs(fa,0),gabs(fb,0)) > 0) { /* attempt interpolation */ GEN min1, min2, p, q, s = gdiv(fb,fa); if (cmprr(a,c)==0) { p = gmul2n(gmul(xm,s),1); q = gsubsg(1,s); } else { GEN r = gdiv(fb,fc); q = gdiv(fa,fc); p = gmul2n(gmul(gsub(q,r),gmul(xm,q)),1); p = gmul(s, gsub(p, gmul(gsub(b,a),gsubgs(r,1)))); q = gmul(gmul(gsubgs(q,1),gsubgs(r,1)),gsubgs(s,1)); } if (gsigne(p) > 0) q = gneg_i(q); else p = gneg_i(p); min1 = gsub(gmulsg(3,gmul(xm,q)), gabs(gmul(q,tol1),0)); min2 = gabs(gmul(e,q),0); if (gcmp(gmul2n(p,1), gmin(min1,min2)) < 0) { e = d; d = gdiv(p,q); } /* interpolation OK */ else { d = xm; e = d; } /* failed, use bisection */ } else { d = xm; e = d; } /* bound decreasing too slowly, use bisection */ a = b; fa = fb; if (gcmp(gabs(d,0),tol1) > 0) b = gadd(b,d); else if (gsigne(xm) > 0) b = addrr(b,tol1); else b = subrr(b,tol1); fb = eval(E, b); } if (iter > itmax) pari_err_IMPL("solve recovery [too many iterations]"); return gerepileuptoleaf(av, rcopy(b)); } GEN zbrent0(GEN a, GEN b, GEN code, long prec) { EXPR_WRAP(code, zbrent(EXPR_ARG, a,b, prec)); } /* x = solve_start(&D, a, b, prec) * while (x) { * y = ...(x); * x = solve_next(&D, y); * } * return D.res; */ /********************************************************************/ /** **/ /** Numerical derivation **/ /** **/ /********************************************************************/ /* 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 * prec(RHS) = 2e, equal when pr = 3e = 3/2 fpr (fpr = required final prec) * * For f'(x), x far from 0: prec(LHS) = pr - e - expo(x) * --> pr = 3/2 fpr + expo(x) */ GEN derivnum(void *E, GEN (*eval)(void *, GEN), GEN x, long prec) { GEN eps,a,b, y; long pr, l, e, ex; pari_sp av = avma; long p = precision(x); long fpr = p ? prec2nbits(p): prec2nbits(prec); ex = gexpo(x); if (ex < 0) ex = 0; /* near 0 */ pr = (long)ceil(fpr * 1.5 + ex); l = nbits2prec(pr); switch(typ(x)) { case t_REAL: case t_COMPLEX: x = gprec_w(x, l + nbits2extraprec(ex + BITS_IN_LONG)); } e = fpr/2; /* 1/2 required prec (in sig. bits) */ eps = real2n(-e, l); a = eval(E, gsub(x, eps)); b = eval(E, gadd(x, eps)); y = gmul2n(gsub(b,a), e-1); return gerepileupto(av, gprec_w(y, nbits2prec(fpr))); } GEN derivfun(void *E, GEN (*eval)(void *, GEN), GEN x, long prec) { pari_sp av = avma; long vx; switch(typ(x)) { case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX: return derivnum(E,eval, x, prec); case t_POL: x = RgX_to_ser(x, precdl+2+1); /* +1 because deriv reduce the precision by 1 */ case t_SER: /* FALL THROUGH */ vx = varn(x); return gerepileupto(av, gdiv(deriv(eval(E, x),vx), deriv(x,vx))); default: pari_err_TYPE("formal derivation",x); return NULL; /*NOT REACHED*/ } } GEN 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) { struct deriv_data E; E.code=code; E.args=args; return derivfun((void*)&E, deriv_eval, gel(args,1), prec); } pari-2.7.5/src/language/compile.c0000644000175000017500000015342512502252164015265 0ustar billbill/* Copyright (C) 2006 The PARI group. This file is part of the PARI 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" #include "tree.h" #include "opcode.h" #define tree pari_tree enum COflags {COsafelex=1, COsafedyn=2}; /*************************************************************************** ** ** ** String constant expansion ** ** ** ***************************************************************************/ static GEN strntoGENexp(const char *str, long len) { GEN z = cgetg(1+nchar2nlong(len-1), t_STR); char *s=GSTR(z); const char *t=str+1; while (t<=str+len) { 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) compile_err("unfinished string",str); } t++; s++; } if (*t == '"') { if (t[1] != '"') break; t += 2; continue; } *s++ = *t++; } *s = '\0'; return z; } /*************************************************************************** ** ** ** Byte-code compiler ** ** ** ***************************************************************************/ typedef enum {Llocal, Lmy} Ltype; struct vars_s { Ltype type; /*Only Llocal and Lmy are allowed */ int inl; entree *ep; }; struct frame_s { long pc; GEN frame; }; static THREAD pari_stack s_opcode, s_operand, s_data, s_lvar; static THREAD pari_stack s_dbginfo, s_frame; static THREAD char *opcode; static THREAD long *operand; static THREAD GEN *data; static THREAD long offset; static THREAD struct vars_s *localvars; static THREAD const char **dbginfo, *dbgstart; static THREAD struct frame_s *frames; void pari_init_compiler(void) { pari_stack_init(&s_opcode,sizeof(*opcode),(void **)&opcode); pari_stack_init(&s_operand,sizeof(*operand),(void **)&operand); pari_stack_init(&s_data,sizeof(*data),(void **)&data); pari_stack_init(&s_lvar,sizeof(*localvars),(void **)&localvars); pari_stack_init(&s_dbginfo,sizeof(*dbginfo),(void **)&dbginfo); pari_stack_init(&s_frame,sizeof(*frames),(void **)&frames); offset=-1; } void pari_close_compiler(void) { pari_stack_delete(&s_opcode); pari_stack_delete(&s_operand); pari_stack_delete(&s_data); pari_stack_delete(&s_lvar); } struct codepos { long opcode, data, localvars, frames; long offset; const char *dbgstart; }; static void getcodepos(struct codepos *pos) { pos->opcode=s_opcode.n; pos->data=s_data.n; pos->offset=offset; pos->localvars=s_lvar.n; pos->dbgstart=dbgstart; pos->frames=s_frame.n; offset=s_data.n-1; } void compilestate_reset(void) { s_opcode.n=0; s_operand.n=0; s_dbginfo.n=0; s_data.n=0; s_lvar.n=0; s_frame.n=0; offset=-1; dbgstart=NULL; } void compilestate_save(struct pari_compilestate *comp) { comp->opcode=s_opcode.n; comp->operand=s_operand.n; comp->data=s_data.n; comp->offset=offset; comp->localvars=s_lvar.n; comp->dbgstart=dbgstart; comp->dbginfo=s_dbginfo.n; comp->frames=s_frame.n; } void compilestate_restore(struct pari_compilestate *comp) { s_opcode.n=comp->opcode; s_operand.n=comp->operand; s_data.n=comp->data; offset=comp->offset; s_lvar.n=comp->localvars; dbgstart=comp->dbgstart; s_dbginfo.n=comp->dbginfo; s_frame.n=comp->frames; } static GEN getfunction(const struct codepos *pos, long arity, long nbmvar, GEN text, long gap) { long lop =s_opcode.n+1-pos->opcode; long ldat=s_data.n+1-pos->data; long lfram=s_frame.n+1-pos->frames; GEN cl=cgetg(nbmvar?8:(text?7:6),t_CLOSURE); GEN frpc, fram, dbg; char *s; long i; cl[1] = arity; gel(cl,2) = cgetg(nchar2nlong(lop)+1, t_STR); gel(cl,3) = cgetg(lop, t_VECSMALL); gel(cl,4) = cgetg(ldat, t_VEC); dbg = cgetg(lop, t_VECSMALL); frpc = cgetg(lfram, t_VECSMALL); fram = cgetg(lfram, t_VEC); gel(cl,5) = mkvec3(dbg, frpc, fram); if (text) gel(cl,6) = text; if (nbmvar) gel(cl,7) = zerovec(nbmvar); s=GSTR(gel(cl,2))-1; for(i=1;iopcode-1]; mael(cl, 3, i) = operand[i+pos->opcode-1]; dbg[i] = dbginfo[i+pos->opcode-1]-dbgstart; if (dbg[i]<0) dbg[i]+=gap; } s[i]=0; s_opcode.n=pos->opcode; s_operand.n=pos->opcode; s_dbginfo.n=pos->opcode; for(i=1;idata-1]) { gmael(cl, 4, i) = gcopy(data[i+pos->data-1]); gunclone(data[i+pos->data-1]); } s_data.n=pos->data; while (s_lvar.n>pos->localvars && !localvars[s_lvar.n-1].inl) s_lvar.n--; for(i=1;iframes-1; frpc[i] = frames[j].pc-pos->opcode+1; gel(fram, i) = gcopy(frames[j].frame); gunclone(frames[j].frame); } s_frame.n=pos->frames; offset=pos->offset; dbgstart=pos->dbgstart; return cl; } static GEN getclosure(struct codepos *pos) { return getfunction(pos,0,0,NULL,0); } static void op_push_loc(op_code o, long x, const char *loc) { long n=pari_stack_new(&s_opcode); long m=pari_stack_new(&s_operand); long d=pari_stack_new(&s_dbginfo); opcode[n]=o; operand[m]=x; dbginfo[d]=loc; } static void op_push(op_code o, long x, long n) { op_push_loc(o,x,tree[n].str); } static void op_insert_loc(long k, op_code o, long x, const char *loc) { long i; long n=pari_stack_new(&s_opcode); (void) pari_stack_new(&s_operand); (void) pari_stack_new(&s_dbginfo); for (i=n-1; i>=k; i--) { opcode[i+1] = opcode[i]; operand[i+1]= operand[i]; dbginfo[i+1]= dbginfo[i]; } opcode[k] = o; operand[k] = x; dbginfo[k] = loc; } static long data_push(GEN x) { long n=pari_stack_new(&s_data); data[n] = x?gclone(x):x; return n-offset; } static void var_push(entree *ep, Ltype type) { long n=pari_stack_new(&s_lvar); localvars[n].ep = ep; localvars[n].inl = 0; localvars[n].type = type; } static void frame_push(GEN x) { long n=pari_stack_new(&s_frame); frames[n].pc = s_opcode.n-1; frames[n].frame = gclone(x); } static GEN pack_localvars(void) { GEN pack=cgetg(3,t_VEC); long i,l=s_lvar.n; GEN t=cgetg(1+l,t_VECSMALL); GEN e=cgetg(1+l,t_VECSMALL); gel(pack,1)=t; gel(pack,2)=e; for(i=1;i<=l;i++) { t[i]=localvars[i-1].type; e[i]=(long)localvars[i-1].ep; } return pack; } void push_frame(GEN C, long lpc, long dummy) { const char *code=closure_codestr(C); GEN oper=closure_get_oper(C); GEN dbg=closure_get_dbg(C); GEN frpc=gel(dbg,2); GEN fram=gel(dbg,3); long pc, j=1, lfr = lg(frpc); if (lpc==-1) { long k; GEN e = gel(fram, 1); for(k=1; k0 && (code[pc]==OClocalvar || code[pc]==OClocalvar0)) var_push((entree*)oper[pc],Llocal); if (jname:"NULL")); } } GEN localvars_read_str(const char *x, GEN pack) { GEN code; long l=0; if (pack) { GEN t=gel(pack,1); GEN e=gel(pack,2); long i; l=lg(t)-1; for(i=1;i<=l;i++) var_push((entree*)e[i],(Ltype)t[i]); } code = compile_str(x); s_lvar.n -= l; return closure_evalres(code); } long localvars_find(GEN pack, entree *ep) { GEN t=gel(pack,1); GEN e=gel(pack,2); long i; long vn=0; for(i=lg(e)-1;i>=1;i--) { if(t[i]==Lmy) vn--; if(e[i]==(long)ep) return t[i]==Lmy?vn:0; } return 0; } /* Flags for copy optimisation: -- Freturn: The result will be returned. -- FLsurvive: The result must survive the closure. -- FLnocopy: The result will never be updated nor part of a user variable. -- FLnocopylex: The result will never be updated nor part of dynamic variable. */ enum FLflag {FLreturn=1, FLsurvive=2, FLnocopy=4, FLnocopylex=8}; static void copyifclone(long n, long mode, long flag, long mask) { if (mode==Ggen && !(flag&mask)) { op_push(OCcopyifclone,0,n); if (!(flag&FLsurvive) && DEBUGLEVEL) pari_warn(warner,"compiler generates copy for `%.*s'", tree[n].len,tree[n].str); } } static void compilenode(long n, int mode, long flag); typedef enum {PPend,PPstd,PPdefault,PPdefaultmulti,PPstar,PPauto} PPproto; static PPproto parseproto(char const **q, char *c, const char *str) { char const *p=*q; long i; switch(*p) { case 0: case '\n': return PPend; case 'D': switch(p[1]) { case 0: compile_err("function has incomplete prototype",str); case 'G': case '&': case 'W': case 'V': case 'I': case 'E': case 'J': case 'n': case 'P': case 'r': case 's': *c=p[1]; *q=p+2; return PPdefault; default: for(i=0;*p && i<2;p++) i+=*p==','; if (i<2) compile_err("function has incomplete prototype",str); *c=p[-2]; *q=p; return PPdefaultmulti; } break; case 'C': case 'p': case 'P': case 'f': *c=*p; *q=p+1; return PPauto; case '&': *c='*'; *q=p+1; return PPstd; case 'V': if (p[1]=='=') { if (p[2]!='G') compile_err("function prototype is not supported",str); *c='='; p+=2; } else *c=*p; *q=p+1; return PPstd; case 'E': case 's': if (p[1]=='*') { *c=*p++; *q=p+1; return PPstar; } /*fall through*/ } *c=*p; *q=p+1; return PPstd; } static long detag(long n) { while (tree[n].f==Ftag) n=tree[n].x; return n; } /* return type for GP functions */ static op_code 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 == 'm') { (*p)++; *flag = FLnocopy; } *t=Ggen; return arity==2?OCcallgen2:OCcallgen; } /*supported types: * type: Gsmall, Ggen, Gvoid, Gvec, Gclosure * mode: Gsmall, Ggen, Gvar, Gvoid */ static void compilecast_loc(int type, int mode, const char *loc) { if (type==mode) return; switch (mode) { 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); break; case Ggen: if (type==Gsmall) op_push_loc(OCstoi,0,loc); else if (type==Gvoid) op_push_loc(OCpushgnil,0,loc); break; case Gvoid: op_push_loc(OCpop, 1,loc); break; case Gvar: if (type==Ggen) op_push_loc(OCvarn,-1,loc); else compile_varerr(loc); break; default: pari_err_BUG("compilecast [unknown type]"); } } static void compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); } 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)); else return do_alias(fetch_entry(tree[x].str, tree[x].len)); } static entree * getentry(long n) { n = detag(n); if (tree[n].f!=Fentry) { if (tree[n].f==Fseq) compile_err("unexpected character: ';'", tree[tree[n].y].str-1); compile_varerr(tree[n].str); } return getfunc(n); } /* match Fentry that are not actually EpSTATIC functions called without parens*/ static entree * getvar(long n) { entree *ep = getentry(n); if (EpSTATIC(do_alias(ep))) compile_varerr(tree[n].str); return ep; } static long getmvar(entree *ep) { long i; long vn=0; for(i=s_lvar.n-1;i>=0;i--) { if(localvars[i].type==Lmy) vn--; if(localvars[i].ep==ep) return localvars[i].type==Lmy?vn:0; } return 0; } static long ctxmvar(void) { pari_sp av=avma; long i, n=0; GEN ctx; for(i=s_lvar.n-1;i>=0;i--) if(localvars[i].type==Lmy) n++; if (n==0) return 0; ctx = cgetg(n+1,t_VECSMALL); for(n=0, i=0; iname, s); } INLINE int is_node_zero(long n) { n = detag(n); return (tree[n].f==Fsmall && tree[n].x==0); } static void str_defproto(const char *p, const char *q, const char *loc) { long len = p-4-q; if (q[1]!='"' || q[len]!='"') compile_err("default argument must be a string",loc); op_push_loc(OCpushgen,data_push(strntoGENexp(q+1,len)),loc); } static long countlisttogen(long n, Ffunc f) { long x,i; if (n==-1 || tree[n].f==Fnoarg) return 0; for(x=n, i=0; tree[x].f==f ;x=tree[x].x, i++); return i+1; } static GEN listtogen(long n, Ffunc f) { long x,i,nb = countlisttogen(n, f); GEN z=cgetg(nb+1, t_VECSMALL); if (nb) { for (x=n, i = nb-1; i>0; z[i+1]=tree[x].y, x=tree[x].x, i--); z[1]=x; } return z; } static long first_safe_arg(GEN arg, long mask) { long lnc, l=lg(arg); for (lnc=l-1; lnc>0 && (tree[arg[lnc]].flags&mask)==mask; lnc--); return lnc; } static void checkdups(GEN arg, GEN vep) { long l=vecsmall_duplicate(vep); if (l!=0) compile_err("variable declared twice",tree[arg[l]].str); } enum {MAT_range,MAT_std,MAT_line,MAT_column,VEC_std}; static int matindex_type(long n) { long x = tree[n].x, y = tree[n].y; long fxx = tree[tree[x].x].f, fxy = tree[tree[x].y].f; if (y==-1) { if (fxy!=Fnoarg) return MAT_range; if (fxx==Fnoarg) compile_err("missing index",tree[n].str); return VEC_std; } else { long fyx = tree[tree[y].x].f, fyy = tree[tree[y].y].f; if (fxy!=Fnoarg || fyy!=Fnoarg) return MAT_range; if (fxx==Fnoarg && fyx==Fnoarg) compile_err("missing index",tree[n].str); if (fxx==Fnoarg) return MAT_column; if (fyx==Fnoarg) return MAT_line; return MAT_std; } } static entree * getlvalue(long n) { while ((tree[n].f==Fmatcoeff && matindex_type(tree[n].y)!=MAT_range) || tree[n].f==Ftag) n=tree[n].x; return getvar(n); } INLINE void compilestore(long vn, entree *ep, long n) { if (vn) op_push(OCstorelex,vn,n); else op_push(OCstoredyn,(long)ep,n); } INLINE void compilenewptr(long vn, entree *ep, long n) { if (vn) op_push(OCnewptrlex,vn,n); else op_push(OCnewptrdyn,(long)ep,n); } static void compilelvalue(long n) { n = detag(n); if (tree[n].f==Fentry) return; else { long x = tree[n].x, y = tree[n].y; long yx = tree[y].x, yy = tree[y].y; long m = matindex_type(y); if (m == MAT_range) compile_err("not an lvalue",tree[n].str); if (m == VEC_std && tree[x].f==Fmatcoeff) { int mx = matindex_type(tree[x].y); if (mx==MAT_line) { int xy = tree[x].y, xyx = tree[xy].x; compilelvalue(tree[x].x); compilenode(tree[xyx].x,Gsmall,0); compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo2ptr,0,y); return; } } compilelvalue(x); switch(m) { case VEC_std: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo1ptr,0,y); break; case MAT_std: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yy].x,Gsmall,0); op_push(OCcompo2ptr,0,y); break; case MAT_line: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompoLptr,0,y); break; case MAT_column: compilenode(tree[yy].x,Gsmall,0); op_push(OCcompoCptr,0,y); break; } } } static void compilematcoeff(long n, int mode) { long x=tree[n].x, y=tree[n].y; long yx=tree[y].x, yy=tree[y].y; long m=matindex_type(y); compilenode(x,Ggen,FLnocopy); switch(m) { case VEC_std: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo1,mode,y); return; case MAT_std: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yy].x,Gsmall,0); op_push(OCcompo2,mode,y); return; case MAT_line: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompoL,0,y); compilecast(n,Gvec,mode); return; case MAT_column: compilenode(tree[yy].x,Gsmall,0); op_push(OCcompoC,0,y); compilecast(n,Gvec,mode); return; case MAT_range: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yx].y,Gsmall,0); if (yy==-1) op_push(OCcallgen,(long)is_entry("_[_.._]"),n); else { compilenode(tree[yy].x,Gsmall,0); compilenode(tree[yy].y,Gsmall,0); op_push(OCcallgen,(long)is_entry("_[_.._,_.._]"),n); } return; default: pari_err_BUG("compilematcoeff"); } } static void compilesmall(long n, long x, long mode) { if (mode==Ggen) op_push(OCpushstoi, x, n); else { op_push(OCpushlong, x, n); compilecast(n,Gsmall,mode); } } static void compilevec(long n, long mode, op_code op) { pari_sp ltop=avma; long x=tree[n].x; long i; GEN arg=listtogen(x,Fmatrixelts); long l=lg(arg); op_push(op,l,n); for (i=1;i0;i--) { long y=tree[x].y; x=tree[y].x; stack[i+1]=tree[y].y; } stack[1]=x; return stack; } static GEN compilelambda(long n, long y, GEN vep, struct codepos *pos) { long nbmvar, lev = vep ? lg(vep)-1 : 0; GEN text=cgetg(3,t_VEC); gel(text,1)=strtoGENstr(lev? ((entree*) vep[1])->name: ""); gel(text,2)=strntoGENstr(tree[y].str,tree[y].len); nbmvar=ctxmvar()-lev; if (lev) op_push(OCgetargs,lev,n); compilenode(y,Ggen,FLsurvive|FLreturn); return getfunction(pos,lev,nbmvar,text,2); } static void compilecall(long n, int mode) { pari_sp ltop=avma; long j; long x=tree[n].x; long y=tree[n].y; GEN arg=listtogen(y,Flistarg); long nb=lg(arg)-1; long lnc=first_safe_arg(arg, COsafelex); 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); else op_push(OCpushlong,0,n); } op_push(OCcalluser,nb,x); compilecast(n,Ggen,mode); avma=ltop; } static void compileuserfunc(entree *ep, long n, int mode) { long vn=getmvar(ep); if (tree[n].x=0) n += countlisttogen(tree[x].x,Fmatrixelts)-1; } } return n; } static void compileuninline(GEN arg) { long j; if (lg(arg) > 1) compile_err("too many arguments",tree[arg[1]].str); for(j=0; j=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1; for (j=1; j<=nv; j++) { ver[++k] = vars[j]; vep[k] = (long)getvar(ver[k]); } continue; } else ver[++k] = x; } else ver[++k] = a; vep[k] = (long)getvar(ver[k]); } checkdups(ver,vep); for(i=1; i<=n; i++) var_push(NULL,Lmy); op_push_loc(OCnewframe,inl?-n:n,str); frame_push(vep); for (k=0, i=1; i=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1; compilenode(tree[a].y,Ggen,FLnocopy); op_push(OCdup,nv-1,x); for (j=1; j<=nv; j++) { long v = detag(vars[j]); op_push(OCpushlong,j,v); op_push(OCcompo1,Ggen,v); k++; op_push(OCstorelex,-n+k-1,a); localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k]; localvars[s_lvar.n-n+k-1].inl=inl; } continue; } else if (!is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); op_push(OCstorelex,-n+k,a); } } k++; localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k]; localvars[s_lvar.n-n+k-1].inl=inl; } } static long localpush(op_code op, long a) { entree *ep = getvar(a); long vep = (long) ep; op_push(op,vep,a); var_push(ep,Llocal); return vep; } static void compilelocal(GEN arg) { long i, j, k, l = lg(arg); long n = countvar(arg); GEN vep = cgetg(n+1,t_VECSMALL); GEN ver = cgetg(n+1,t_VECSMALL); for(k=0, i=1; i=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1; compilenode(tree[a].y,Ggen,FLnocopy); op_push(OCdup,nv-1,x); for (j=1; j<=nv; j++) { long v = detag(vars[j]); op_push(OCpushlong,j,v); op_push(OCcompo1,Ggen,v); vep[++k] = localpush(OClocalvar, v); ver[k] = v; } continue; } else if (!is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); ver[++k] = x; vep[k] = localpush(OClocalvar, ver[k]); continue; } else ver[++k] = x; } else ver[++k] = a; vep[k] = localpush(OClocalvar0, ver[k]); } checkdups(ver,vep); } static void compilefunc(entree *ep, long n, int mode, long flag) { pari_sp ltop=avma; long j; long x=tree[n].x, y=tree[n].y; op_code ret_op; long ret_flag; Gtype ret_typ; char const *p,*q; char c; const char *flags = NULL; const char *str; PPproto mod; GEN arg=listtogen(y,Flistarg); long lnc=first_safe_arg(arg, COsafelex|COsafedyn); long lnl=first_safe_arg(arg, COsafelex); long nbpointers=0, nbopcodes; long nb=lg(arg)-1, lev=0; long ev[20]; if (x>=OPnboperator) str=tree[x].str; else { if (nb==2) str=tree[arg[1]].str+tree[arg[1]].len; else if (nb==1) str=tree[arg[1]].str; else str=tree[n].str; while(*str==')') str++; } if (tree[n].f==Fassign) { nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y); } else if (is_func_named(ep,"if")) { if (nb>=4) ep=is_entry("_multi_if"); else if (mode==Gvoid) ep=is_entry("_void_if"); } else if (is_func_named(ep,"return") && (flag&FLreturn) && nb<=1) { if (nb==0) op_push(OCpushgnil,0,n); else compilenode(arg[1],Ggen,FLsurvive|FLreturn); avma=ltop; return; } else if (is_func_named(ep,"inline")) { compilemy(arg, str, 1); compilecast(n,Gvoid,mode); avma=ltop; return; } else if (is_func_named(ep,"uninline")) { compileuninline(arg); compilecast(n,Gvoid,mode); avma=ltop; return; } else if (is_func_named(ep,"my")) { compilemy(arg, str, 0); compilecast(n,Gvoid,mode); avma=ltop; return; } else if (is_func_named(ep,"local")) { compilelocal(arg); compilecast(n,Gvoid,mode); avma=ltop; return; } /*We generate dummy code for global() for compatibility with gp2c*/ else if (is_func_named(ep,"global")) { long i; for (i=1;i<=nb;i++) { long a=arg[i]; long en; if (tree[a].f==Fassign) { compilenode(tree[a].y,Ggen,0); a=tree[a].x; en=(long)getvar(a); op_push(OCstoredyn,en,a); } else { en=(long)getvar(a); op_push(OCpushdyn,en,a); op_push(OCpop,1,a); } } compilecast(n,Gvoid,mode); avma=ltop; return; } else if (is_func_named(ep,"O") || (compatible==OLDALL && is_func_named(ep,"o"))) { if (nb!=1) compile_err("wrong number of arguments", tree[n].str+tree[n].len-1); ep=is_entry("O(_^_)"); if (tree[arg[1]].f==Ffunction && tree[arg[1]].x==OPpow) { arg = listtogen(tree[arg[1]].y,Flistarg); nb = lg(arg)-1; lnc = first_safe_arg(arg,COsafelex|COsafedyn); lnl = first_safe_arg(arg,COsafelex); } } else if (x==OPn && tree[y].f==Fsmall) { avma=ltop; compilesmall(y, -tree[y].x, mode); return; } else if (x==OPtrans && tree[y].f==Fvec) { avma=ltop; compilevec(y, mode, OCcol); return; } else if (x==OPpow && nb==2 && tree[arg[2]].f==Fsmall) ep=is_entry("_^s"); else if (x==OPcat) compile_err("expected character: ',' or ')' instead of", tree[arg[1]].str+tree[arg[1]].len); p=ep->code; if (!ep->value) compile_err("unknown function",tree[n].str); nbopcodes = s_opcode.n; ret_op = get_ret_type(&p, ep->arity, &ret_typ, &ret_flag); j=1; if (*p) { q=p; while((mod=parseproto(&p,&c,tree[n].str))!=PPend) { if (j<=nb && tree[arg[j]].f!=Fnoarg && (mod==PPdefault || mod==PPdefaultmulti)) mod=PPstd; switch(mod) { case PPstd: if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1); if (c!='I' && c!='E' && c!='J') { long x = tree[arg[j]].x, f = tree[arg[j]].f; if (f==Fnoarg) compile_err("missing mandatory argument", tree[arg[j]].str); if (f==Fseq) compile_err("unexpected ';'", tree[x].str+tree[x].len); } switch(c) { case 'G': compilenode(arg[j],Ggen,j>=lnl?(j>=lnc?FLnocopy:FLnocopylex):0); j++; break; case 'W': { entree *ep = getlvalue(arg[j]); long vn = getmvar(ep); if (vn) op_push(OCcowvarlex,vn,n); else op_push(OCcowvardyn,(long)ep,n); compilenode(arg[j++],Ggen,FLnocopy); break; } case 'M': if (tree[arg[j]].f!=Fsmall) { if (!flags) flags = ep->code; flags = strchr(flags, '\n'); /* Skip to the following '\n' */ if (!flags) compile_err("missing flag in string function signature", tree[n].str); flags++; if (tree[arg[j]].f==Fconst && tree[arg[j]].x==CSTstr) { GEN str=strntoGENexp(tree[arg[j]].str,tree[arg[j]].len); op_push(OCpushlong, eval_mnemonic(str, flags),n); j++; } else { compilenode(arg[j++],Ggen,0); op_push(OCpushlong,(long)flags,n); op_push(OCcallgen2,(long)is_entry("_eval_mnemonic"),n); } break; } case 'P': case 'L': /*Fall through*/ compilenode(arg[j++],Gsmall,0); break; case 'n': compilenode(arg[j++],Gvar,0); break; case '&': case '*': { long vn, a=arg[j++]; entree *ep; if (c=='&') { if (tree[a].f!=Frefarg) compile_err("expected character: '&'", tree[a].str); a=tree[a].x; } a=detag(a); ep=getlvalue(a); vn=getmvar(ep); if (tree[a].f==Fentry) { if (vn) op_push(OCsimpleptrlex, vn,n); else op_push(OCsimpleptrdyn, (long)ep,n); } else { compilenewptr(vn,ep,n); compilelvalue(a); op_push(OCpushptr, 0,n); } nbpointers++; break; } case 'I': case 'E': case 'J': { long a = arg[j++]; GEN d = compilefuncinline(n, c, a, flag, is_func_named(ep,"if"), lev, ev); op_push(OCpushgen, data_push(d), a); if (lg(d)==8) op_push(OCsaveframe,FLsurvive,n); break; } case 'V': { long a = arg[j++]; (void)getvar(a); ev[lev++] = a; break; } case '=': { long a = arg[j++]; ev[lev++] = tree[a].x; compilenode(tree[a].y, Ggen, FLnocopy); } break; case 'r': { long a=arg[j++]; if (tree[a].f==Fentry) { op_push(OCpushgen, data_push(strntoGENstr(tree[tree[a].x].str, tree[tree[a].x].len)),n); op_push(OCtostr, -1,n); } else { compilenode(a,Ggen,FLnocopy); op_push(OCtostr, -1,n); } break; } case 's': { long a = arg[j++]; GEN g = cattovec(a, OPcat); long l, nb = lg(g)-1; if (nb==1) { compilenode(g[1], Ggen, FLnocopy); op_push(OCtostr, -1, a); } else { op_push(OCvec, nb+1, a); for(l=1; l<=nb; l++) { compilenode(g[l], Ggen, FLsurvive); op_push(OCstackgen,l, a); } op_push(OCpop, 1, a); op_push(OCcallgen,(long)is_entry("Str"), a); op_push(OCtostr, -1, a); } break; } default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPauto: switch(c) { case 'p': op_push(OCprecreal,0,n); break; case 'P': op_push(OCprecdl,0,n); break; case 'C': op_push(OCpushgen,data_push(pack_localvars()),n); break; case 'f': { static long foo; op_push(OCpushlong,(long)&foo,n); break; } } break; case PPdefault: j++; switch(c) { case 'G': case '&': case 'E': case 'I': case 'r': case 's': op_push(OCpushlong,0,n); break; case 'n': op_push(OCpushlong,-1,n); break; case 'V': ev[lev++] = -1; break; case 'P': op_push(OCprecdl,0,n); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPdefaultmulti: j++; switch(c) { case 'G': op_push(OCpushstoi,strtol(q+1,NULL,10),n); break; case 'L': case 'M': op_push(OCpushlong,strtol(q+1,NULL,10),n); break; case 'r': case 's': str_defproto(p, q, tree[n].str); op_push(OCtostr, -1, n); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPstar: switch(c) { case 'E': { long k, n=nb+1-j; GEN g=cgetg(n+1,t_VEC); int ismif = is_func_named(ep,"_multi_if"); for(k=1; k<=n; k++) gel(g, k) = compilefuncinline(n, c, arg[j+k-1], flag, ismif && (k==n || odd(k)), lev, ev); op_push(OCpushgen, data_push(g), arg[j]); j=nb+1; break; } case 's': { long n=nb+1-j; long k,l,l1,m; GEN g=cgetg(n+1,t_VEC); for(l1=0,k=1;k<=n;k++) { gel(g,k)=cattovec(arg[j+k-1],OPcat); l1+=lg(gel(g,k))-1; } op_push_loc(OCvec, l1+1, str); for(m=1,k=1;k<=n;k++) for(l=1;lnbopcodes+128) { op_insert_loc(nbopcodes,OCavma,0,str); op_push_loc(OCgerepile,0,str); } compilecast(n,ret_typ,mode); if (nbpointers) op_push_loc(OCendptr,nbpointers, str); avma=ltop; } static GEN genclosure(entree *ep, const char *loc, long nbdata, int check) { struct codepos pos; long i, nb=0; const char *code=ep->code,*p,*q; char c; long index=ep->arity; long arity=0, maskarg=0, maskarg0=0, stop=0; PPproto mod; Gtype ret_typ; long ret_flag; op_code ret_op=get_ret_type(&code,ep->arity,&ret_typ,&ret_flag); p=code; while ((mod=parseproto(&p,&c,NULL))!=PPend) { if (mod==PPauto) stop=1; else { if (stop) return NULL; if (c=='V') continue; maskarg<<=1; maskarg0<<=1; arity++; switch(mod) { case PPstd: maskarg|=1L; break; case PPdefault: switch(c) { case '&': case 'E': case 'I': maskarg0|=1L; break; } break; default: break; } } } if (check && EpSTATIC(ep) && maskarg==0) return gen_0; getcodepos(&pos); 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); arity -= nbdata; if (maskarg) op_push_loc(OCcheckargs,maskarg,loc); if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc); p=code; while ((mod=parseproto(&p,&c,NULL))!=PPend) { switch(mod) { case PPauto: switch(c) { case 'p': op_push_loc(OCprecreal,0,loc); break; case 'P': op_push_loc(OCprecdl,0,loc); break; case 'C': op_push_loc(OCpushgen,data_push(pack_localvars()),loc); break; case 'f': { static long foo; op_push_loc(OCpushlong,(long)&foo,loc); break; } } default: break; } } q = p = code; while ((mod=parseproto(&p,&c,NULL))!=PPend) { switch(mod) { case PPstd: switch(c) { case 'G': break; case 'M': case 'L': op_push_loc(OCitos,-index,loc); break; case 'n': op_push_loc(OCvarn,-index,loc); break; case '&': case '*': case 'I': case 'E': case 'V': case '=': return NULL; case 'r': case 's': op_push_loc(OCtostr,-index,loc); break; } break; case PPauto: break; case PPdefault: switch(c) { case 'G': case '&': case 'E': case 'I': case 'V': case 'r': case 's': break; case 'n': op_push_loc(OCvarn,-index,loc); break; case 'P': op_push_loc(OCprecdl,0,loc); op_push_loc(OCdefaultlong,-index,loc); break; default: pari_err(e_MISC,"Unknown prototype code `D%c' for `%s'",c,ep->name); } break; case PPdefaultmulti: switch(c) { case 'G': op_push_loc(OCpushstoi,strtol(q+1,NULL,10),loc); op_push_loc(OCdefaultgen,-index,loc); break; case 'L': case 'M': op_push_loc(OCpushlong,strtol(q+1,NULL,10),loc); op_push_loc(OCdefaultlong,-index,loc); break; case 'r': case 's': str_defproto(p, q, loc); op_push_loc(OCdefaultgen,-index,loc); op_push_loc(OCtostr,-index,loc); break; default: pari_err(e_MISC, "Unknown prototype code `D...,%c,' for `%s'",c,ep->name); } break; case PPstar: switch(c) { case 'E': case 's': return NULL; default: pari_err(e_MISC,"Unknown prototype code `%c*' for `%s'",c,ep->name); } break; default: return NULL; } index--; q = p; } 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); } GEN snm_closure(entree *ep, GEN data) { long i; 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); return C; } GEN 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); 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); C = genclosure(ep,ep->name,n,0); if (!C) pari_err(e_MISC,"function prototype unsupported: \"%s\"",s); else { va_list ap; long i; va_start(ap,n); for(i=1; i<=n; i++) gmael(C,4,i) = va_arg(ap, GEN); va_end(ap); } return gerepilecopy(av, C); } GEN strtofunction(const char *s) { return strtoclosure(s, 0); } static void closurefunc(entree *ep, long n, long mode) { pari_sp ltop=avma; GEN C; if (!ep->value) compile_err("unknown function",tree[n].str); C = genclosure(ep,tree[n].str,0,1); if (!C) compile_err("sorry, closure not implemented",tree[n].str); if (C==gen_0) { compilefunc(ep,n,mode,0); return; } op_push(OCpushgen, data_push(C), n); compilecast(n,Gclosure,mode); avma=ltop; } static void compileseq(long n, int mode, long flag) { pari_sp av = avma; GEN L = listtogen(n, Fseq); long i, l = lg(L)-1; for(i = 1; i < l; i++) compilenode(L[i],Gvoid,0); compilenode(L[l],mode,flag&(FLreturn|FLsurvive)); avma = av; } static void compilenode(long n, int mode, long flag) { long x,y; #ifdef STACK_CHECK if (PARI_stack_limit && (void*) &x <= PARI_stack_limit) pari_err(e_MISC, "expression nested too deeply"); #endif if (n<0) pari_err_BUG("compilenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: compileseq(n, mode, flag); return; case Fmatcoeff: compilematcoeff(n,mode); if (mode==Ggen && !(flag&FLnocopy)) op_push(OCcopy,0,n); return; case Fassign: x = detag(x); if (tree[x].f==Fvec && tree[x].x>=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long i, l = lg(vars)-1; compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive); op_push(OCdup,mode==Gvoid?l-1:l,x); for(i=1; i<=l; i++) { long a = detag(vars[i]); entree *ep=getlvalue(a); long vn=getmvar(ep); op_push(OCpushlong,i,a); op_push(OCcompo1,Ggen,a); if (tree[a].f==Fentry) compilestore(vn,ep,n); else { compilenewptr(vn,ep,n); compilelvalue(a); op_push(OCstoreptr,0,a); } } if (mode!=Gvoid) compilecast(n,Ggen,mode); } else { entree *ep=getlvalue(x); long vn=getmvar(ep); if (tree[x].f!=Fentry) { compilenewptr(vn,ep,n); compilelvalue(x); } compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive); if (mode!=Gvoid) op_push(OCdup,1,n); if (tree[x].f==Fentry) compilestore(vn,ep,n); else op_push(OCstoreptr,0,x); if (mode!=Gvoid) compilecast(n,Ggen,mode); } return; case Fconst: { pari_sp ltop=avma; if (tree[n].x!=CSTquote) { if (mode==Gvoid) return; if (mode==Gvar) compile_varerr(tree[n].str); } if (mode==Gsmall) compile_err("this should be a small integer", tree[n].str); switch(tree[n].x) { case CSTreal: op_push(OCpushreal, data_push(strntoGENstr(tree[n].str,tree[n].len)),n); break; case CSTint: op_push(OCpushgen, data_push(strtoi((char*)tree[n].str)),n); compilecast(n,Ggen, mode); break; case CSTstr: 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); if (EpSTATIC(ep)) compile_varerr(tree[n].str+1); op_push(OCpushvar, (long)ep,n); compilecast(n,Ggen, mode); break; } default: pari_err_BUG("compilenode, unsupported constant"); } avma=ltop; return; } case Fsmall: compilesmall(n, x, mode); return; case Fvec: compilevec(n, mode, OCvec); return; case Fmat: compilemat(n, mode); return; case Frefarg: compile_err("unexpected character '&':",tree[n].str); return; case Fentry: { entree *ep=getentry(n); long vn=getmvar(ep); if (vn) { op_push(OCpushlex,(long)vn,n); copyifclone(n,mode,flag,FLnocopy|FLnocopylex); compilecast(n,Ggen,mode); } else if (ep->valence==EpVAR || ep->valence==EpNEW) { if (DEBUGLEVEL && mode==Gvoid) pari_warn(warner,"statement with no effect: `%s'",ep->name); op_push(OCpushdyn,(long)ep,n); copyifclone(n,mode,flag,FLnocopy); compilecast(n,Ggen,mode); } else closurefunc(ep,n,mode); return; } case Ffunction: { entree *ep=getfunc(n); if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW) compileuserfunc(ep,n,mode); else compilefunc(ep,n,mode,flag); return; } case Fcall: compilenode(x,Ggen,0); compilecall(n,mode); return; case Flambda: { pari_sp ltop=avma; struct codepos pos; GEN arg=listtogen(x,Flistarg); long nb, lgarg, nbmvar, gap; long strict = GP_DATA->strictargs; GEN vep = cgetg_copy(arg, &lgarg); GEN text=cgetg(3,t_VEC); gel(text,1)=strntoGENstr(tree[x].str,tree[x].len); gel(text,2)=strntoGENstr(tree[y].str,tree[y].len); getcodepos(&pos); dbgstart=tree[x].str+tree[x].len; gap = tree[y].str-dbgstart; nbmvar=ctxmvar(); nb = lgarg-1; if (nb) { long i; for(i=1;i<=nb;i++) { long a=arg[i]; vep[i]=(long)getvar(tree[a].f==Fassign?tree[a].x:a); var_push(NULL,Lmy); } checkdups(arg,vep); op_push(OCgetargs,nb,x); frame_push(vep); for (i=1;i<=nb;i++) { long a=arg[i]; long y = tree[a].y; if (tree[a].f==Fassign && (strict || !is_node_zero(y))) { if (tree[y].f==Fsmall) compilenode(y, Ggen, 0); else { struct codepos lpos; getcodepos(&lpos); compilenode(y, Ggen, 0); op_push(OCpushgen, data_push(getclosure(&lpos)),a); } op_push(OCdefaultarg,-nb+i-1,a); } localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i]; } } if (strict) op_push(OCcheckuserargs,nb,x); dbgstart=tree[y].str; if (y>=0 && tree[y].f!=Fnoarg) compilenode(y,Ggen,FLsurvive|FLreturn); else compilecast(n,Gvoid,Ggen); op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n); if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n); compilecast(n, Gclosure, mode); avma=ltop; return; } case Ftag: compilenode(x, mode,flag); return; case Fnoarg: compilecast(n,Gvoid,mode); return; default: pari_err_BUG("compilenode"); } } GEN gp_closure(long n) { struct codepos pos; getcodepos(&pos); dbgstart=tree[n].str; compilenode(n,Ggen,FLsurvive|FLreturn); return getfunction(&pos,0,0,strntoGENstr(tree[n].str,tree[n].len),0); } GEN closure_deriv(GEN G) { pari_sp ltop=avma; long i; struct codepos pos; const char *code; GEN text; long arity=G[1]; if (typ(gel(G,6))==t_STR) { code = GSTR(gel(G,6)); text = cgetg(1+nchar2nlong(2+strlen(code)),t_STR); sprintf(GSTR(text),"%s'",code); } else { code = GSTR(GENtoGENstr(G)); text = cgetg(1+nchar2nlong(4+strlen(code)),t_STR); sprintf(GSTR(text),"(%s)'",code); } getcodepos(&pos); dbgstart=code; op_push_loc(OCgetargs, arity,code); op_push_loc(OCpushgen,data_push(G),code); op_push_loc(OCvec,arity+1,code); for (i=1;i<=arity;i++) { op_push_loc(OCpushlex,i-arity-1,code); op_push_loc(OCstackgen,i,code); } op_push_loc(OCpop,1,code); op_push_loc(OCprecreal,0,code); op_push_loc(OCcallgen,(long)is_entry("_derivfun"),code); return gerepilecopy(ltop, getfunction(&pos,arity,0,text,0)); } static long vec_optimize(GEN arg) { long fl = COsafelex|COsafedyn; long i; for (i=1; i=0) { optimizenode(yy); fl&=tree[yy].flags; } tree[n].flags=fl; } static void optimizefunc(entree *ep, long n) { pari_sp av=avma; long j; long x=tree[n].x; long y=tree[n].y; Gtype t; PPproto mod; long fl=COsafelex|COsafedyn; const char *p=ep->code; char c; GEN arg = listtogen(y,Flistarg); long nb=lg(arg)-1, ret_flag; if (!p) fl=0; else (void) get_ret_type(&p, 2, &t, &ret_flag); if (p && *p) { j=1; while((mod=parseproto(&p,&c,tree[n].str))!=PPend) { if (j<=nb && tree[arg[j]].f!=Fnoarg && (mod==PPdefault || mod==PPdefaultmulti)) mod=PPstd; switch(mod) { case PPstd: if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1); if (tree[arg[j]].f==Fnoarg && c!='I' && c!='E') compile_err("missing mandatory argument", tree[arg[j]].str); switch(c) { case 'G': case 'n': case 'M': case 'L': case 'P': optimizenode(arg[j]); fl&=tree[arg[j++]].flags; break; case 'I': case 'E': case 'J': optimizenode(arg[j]); fl&=tree[arg[j]].flags; tree[arg[j++]].flags=COsafelex|COsafedyn; break; case '&': case '*': { long a=arg[j]; if (c=='&') { if (tree[a].f!=Frefarg) compile_err("expected character: '&'", tree[a].str); a=tree[a].x; } optimizenode(a); tree[arg[j++]].flags=COsafelex|COsafedyn; fl=0; break; } case 'W': optimizenode(arg[j++]); fl=0; break; case 'V': case 'r': tree[arg[j++]].flags=COsafelex|COsafedyn; break; case '=': { long a=arg[j++], y=tree[a].y; if (tree[a].f!=Fassign) compile_err("expected character: '=' instead of", tree[a].str+tree[a].len); optimizenode(y); fl&=tree[y].flags; } break; case 's': fl &= vec_optimize(cattovec(arg[j++], OPcat)); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPauto: break; case PPdefault: case PPdefaultmulti: if (j<=nb) optimizenode(arg[j++]); break; case PPstar: switch(c) { case 'E': { long n=nb+1-j; long k; for(k=1;k<=n;k++) { optimizenode(arg[j+k-1]); fl &= tree[arg[j+k-1]].flags; } j=nb+1; break; } case 's': { long n=nb+1-j; long k; for(k=1;k<=n;k++) fl &= vec_optimize(cattovec(arg[j+k-1],OPcat)); j=nb+1; break; } default: pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c, tree[x].len, tree[x].str); } break; default: pari_err_BUG("optimizefun [unknown PPproto]"); } } } else (void)vec_optimize(arg); avma=av; tree[n].flags=fl; } static void optimizecall(long n) { pari_sp av=avma; long x=tree[n].x; long y=tree[n].y; GEN arg=listtogen(y,Flistarg); optimizenode(x); tree[n].flags = COsafelex&tree[x].flags&vec_optimize(arg); avma=av; } static void optimizeseq(long n) { pari_sp av = avma; GEN L = listtogen(n, Fseq); long i, l = lg(L)-1, flags=-1L; for(i = 1; i <= l; i++) { optimizenode(L[i]); flags &= tree[L[i]].flags; } avma = av; tree[n].flags = flags; } void optimizenode(long n) { long x,y; #ifdef STACK_CHECK if (PARI_stack_limit && (void*) &x <= PARI_stack_limit) pari_err(e_MISC, "expression nested too deeply"); #endif if (n<0) pari_err_BUG("optimizenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: optimizeseq(n); return; case Frange: optimizenode(x); optimizenode(y); tree[n].flags=tree[x].flags&tree[y].flags; break; case Fmatcoeff: optimizematcoeff(n); break; case Fassign: optimizenode(x); optimizenode(y); tree[n].flags=0; break; case Fnoarg: case Fsmall: case Fconst: case Fentry: tree[n].flags=COsafelex|COsafedyn; return; case Fvec: optimizevec(n); return; case Fmat: optimizemat(n); return; case Frefarg: compile_err("unexpected character '&'",tree[n].str); return; case Ffunction: { entree *ep=getfunc(n); if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW) optimizecall(n); else optimizefunc(ep,n); return; } case Fcall: optimizecall(n); return; case Flambda: optimizenode(y); tree[n].flags=COsafelex|COsafedyn; return; case Ftag: optimizenode(x); tree[n].flags=tree[x].flags; return; default: pari_err_BUG("optimizenode"); } } pari-2.7.5/src/language/es.c0000644000175000017500000036316412601623017014246 0ustar billbill/* 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. */ /*******************************************************************/ /** **/ /** INPUT/OUTPUT SUBROUTINES **/ /** **/ /*******************************************************************/ #ifdef _WIN32 #include #include /* for getpid */ #include "../systems/mingw/mingw.h" #endif #include "paricfg.h" #ifdef HAS_STAT #include #endif #ifdef HAS_OPENDIR #include #endif #include "pari.h" #include "paripriv.h" #include "anal.h" static const char esc = (0x1f & '['); /* C-[ = escape */ typedef struct outString { char *string; /* start of the output buffer */ char *end; /* end of the output buffer */ char *cur; /* current writing place in the output buffer */ size_t size; /* buffer size */ int use_stack; /* use stack_malloc instead of malloc ? */ } outString; typedef void (*OUT_FUN)(GEN, pariout_t *, outString *); static void bruti_sign(GEN g, pariout_t *T, outString *S, int addsign); static void matbruti(GEN g, pariout_t *T, outString *S); static void texi_sign(GEN g, pariout_t *T, outString *S, int addsign); static char *GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out); static void bruti(GEN g, pariout_t *T, outString *S) { bruti_sign(g,T,S,1); } static void texi(GEN g, pariout_t *T, outString *S) { texi_sign(g,T,S,1); } void pari_ask_confirm(const char *s) { if (!cb_pari_ask_confirm) pari_err(e_MISC,"Can't ask for confirmation. Please define cb_pari_ask_confirm()"); cb_pari_ask_confirm(s); } /********************************************************************/ /** **/ /** INPUT FILTER **/ /** **/ /********************************************************************/ #define ONE_LINE_COMMENT 2 #define MULTI_LINE_COMMENT 1 #define LBRACE '{' #define RBRACE '}' /* 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; if (!F->t) F->t = (char*)pari_malloc(strlen(s)+1); t = F->t; if (F->more_input == 1) F->more_input = 0; while ((c = *s++)) { if (F->in_string) { *t++ = c; /* copy verbatim */ switch(c) { case '\\': /* in strings, \ is the escape character */ if (*s) *t++ = *s++; break; case '"': F->in_string = 0; } continue; } if (F->in_comment) { /* look for comment's end */ if (F->in_comment == MULTI_LINE_COMMENT) { while (c != '*' || *s != '/') { if (!*s) { if (!F->more_input) F->more_input = 1; goto END; } c = *s++; } s++; } else while (c != '\n' && *s) c = *s++; F->in_comment = 0; continue; } /* 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; switch(c) { case '/': if (*s == '*') { t--; F->in_comment = MULTI_LINE_COMMENT; } break; case '\\': if (!*s) { if (*F->buf->buf == '?') 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; /* '?...\' */ t--; s++; if (!*s) { if (!F->more_input) F->more_input = 1; goto END; } } /* skip \ */ break; case '"': F->in_string = 1; break; case LBRACE: t--; if (F->wait_for_brace) pari_err_IMPL("embedded braces (in parser)"); F->more_input = 2; F->wait_for_brace = 1; break; case RBRACE: if (!F->wait_for_brace) pari_err(e_MISC,"unexpected closing brace"); F->more_input = 0; t--; F->wait_for_brace = 0; break; } } if (t != F->t) /* non empty input */ { c = t[-1]; /* last char */ if (c == '=') { if (*F->buf->buf != '?') 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--;} } END: F->end = t; *t = 0; return F->t; } #undef ONE_LINE_COMMENT #undef MULTI_LINE_COMMENT char * filtre(const char *s, int downcase) { filtre_t T; 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); } void init_filtre(filtre_t *F, Buffer *buf) { F->buf = buf; F->in_string = 0; F->in_comment = 0; F->downcase = 0; } /********************************************************************/ /** **/ /** INPUT METHODS **/ /** **/ /********************************************************************/ /* create */ Buffer * new_buffer(void) { Buffer *b = (Buffer*) pari_malloc(sizeof(Buffer)); b->len = 1024; b->buf = (char*)pari_malloc(b->len); return b; } /* delete */ void delete_buffer(Buffer *b) { if (!b) return; pari_free((void*)b->buf); pari_free((void*)b); } /* resize */ void fix_buffer(Buffer *b, long newlbuf) { b->len = newlbuf; b->buf = (char*)pari_realloc((void*)b->buf, b->len); } static int gp_read_stream_buf(FILE *fi, Buffer *b) { input_method IM; filtre_t F; init_filtre(&F, b); IM.file = fi; IM.fgets= &fgets; IM.getline= &file_input; IM.free = 0; return input_loop(&F,&IM); } GEN gp_read_stream(FILE *fi) { Buffer *b = new_buffer(); GEN x = gp_read_stream_buf(fi, b)? readseq(b->buf): gnil; delete_buffer(b); return x; } GEN gp_read_file(char *s) { GEN x = gnil; FILE *f = switchin(s); if (file_is_binary(f)) { int junk; x = readbin(s,f, &junk); } else { Buffer *b = new_buffer(); x = gnil; for (;;) { if (!gp_read_stream_buf(f, b)) break; if (*(b->buf)) x = readseq(b->buf); } delete_buffer(b); } popinfile(); return x; } GEN gp_readvec_stream(FILE *fi) { pari_sp ltop = avma; Buffer *b = new_buffer(); long i = 1, n = 16; GEN z = cgetg(n+1,t_VEC); for(;;) { if (!gp_read_stream_buf(fi, b)) break; if (!*(b->buf)) continue; if (i>n) { if (DEBUGLEVEL) err_printf("gp_readvec_stream: reaching %ld entries\n",n); n <<= 1; z = vec_lengthen(z,n); } gel(z,i++) = readseq(b->buf); } if (DEBUGLEVEL) err_printf("gp_readvec_stream: found %ld entries\n",i-1); setlg(z,i); delete_buffer(b); return gerepilecopy(ltop,z); } GEN gp_readvec_file(char *s) { GEN x = NULL; FILE *f = switchin(s); if (file_is_binary(f)) { int junk; x = readbin(s,f,&junk); } else x = gp_readvec_stream(f); popinfile(); return x; } char * file_getline(Buffer *b, char **s0, input_method *IM) { const ulong MAX = (1UL << 31) - 1; ulong used0, used; **s0 = 0; /* paranoia */ used0 = used = *s0 - b->buf; for(;;) { ulong left = b->len - used, l, read; char *s; /* If little space left, double the buffer size before next read. */ if (left < 512) { fix_buffer(b, b->len << 1); left = b->len - used; *s0 = b->buf + used0; } /* # of chars read by fgets is an int; be careful */ read = minuu(left, MAX); s = b->buf + used; if (! IM->fgets(s, (int)read, IM->file)) return **s0? *s0: NULL; /* EOF */ l = strlen(s); if (l+1 < read || s[l-1] == '\n') return *s0; /* \n */ used += l; } } /* Read from file (up to '\n' or EOF) and copy at s0 (points in b->buf) */ char * file_input(char **s0, int junk, input_method *IM, filtre_t *F) { (void)junk; return file_getline(F->buf, s0, IM); } /* Read a "complete line" and filter it. Return: 0 if EOF, 1 otherwise */ int input_loop(filtre_t *F, input_method *IM) { Buffer *b = (Buffer*)F->buf; char *to_read, *s = b->buf; /* read first line */ if (! (to_read = IM->getline(&s,1, IM, F)) ) { check_filtre(F); return 0; } /* buffer is not empty, init filter */ F->in_string = 0; F->more_input= 0; F->wait_for_brace = 0; for(;;) { F->s = to_read; F->t = s; (void)filtre0(F); /* pre-processing of line, read by previous call to IM->getline */ if (IM->free) pari_free(to_read); if (! F->more_input) break; /* read continuation line */ s = F->end; to_read = IM->getline(&s,0, IM, F); if (!to_read) break; } return 1; } /********************************************************************/ /** **/ /** GENERAL PURPOSE PRINTING **/ /** **/ /********************************************************************/ PariOUT *pariOut, *pariErr; static void _fputs(const char *s, FILE *f ) { #ifdef _WIN32 win32_ansi_fputs(s, f); #else fputs(s, f); #endif } static void _putc_log(char c) { if (pari_logfile) (void)putc(c, pari_logfile); } static void _puts_log(const char *s) { FILE *f = pari_logfile; const char *p; if (!f) return; if (logstyle != logstyle_color) while ( (p = strchr(s, esc)) ) { /* skip ANSI color escape sequence */ if ( p!=s ) fwrite(s, 1, p-s, f); s = strchr(p, 'm'); if (!s) return; s++; } fputs(s, f); } static void _flush_log(void) { (void)fflush(pari_logfile); } static void normalOutC(char c) { putc(c, pari_outfile); _putc_log(c); } static void normalOutS(const char *s) { _fputs(s, pari_outfile); _puts_log(s); } static void normalOutF(void) { fflush(pari_outfile); _flush_log(); } static PariOUT defaultOut = {normalOutC, normalOutS, normalOutF}; static void normalErrC(char c) { putc(c, pari_errfile); _putc_log(c); } static void normalErrS(const char *s) { _fputs(s, pari_errfile); _puts_log(s); } static void normalErrF(void) { fflush(pari_errfile); _flush_log(); } static PariOUT defaultErr = {normalErrC, normalErrS, normalErrF}; /** GENERIC PRINTING **/ void resetout(int initerr) { pariOut = &defaultOut; if (initerr) pariErr = &defaultErr; } void initout(int initerr) { pari_infile = stdin; pari_outfile = stdout; pari_errfile = stderr; resetout(initerr); } static int last_was_newline = 1; static void set_last_newline(char c) { last_was_newline = (c == '\n'); } void out_putc(PariOUT *out, char c) { set_last_newline(c); out->putch(c); } void pari_putc(char c) { out_putc(pariOut, c); } void out_puts(PariOUT *out, const char *s) { if (*s) { set_last_newline(s[strlen(s)-1]); out->puts(s); } } void pari_puts(const char *s) { out_puts(pariOut, s); } int pari_last_was_newline(void) { return last_was_newline; } void pari_set_last_newline(int last) { last_was_newline = last; } void pari_flush(void) { pariOut->flush(); } void err_flush(void) { pariErr->flush(); } static GEN log10_2(void) { return divrr(mplog2(LOWDEFAULTPREC), mplog(utor(10,LOWDEFAULTPREC))); } /* e binary exponent, return exponent in base ten */ static long ex10(long e) { pari_sp av; GEN z; if (e >= 0) { if (e < 1e15) return (long)(e*LOG10_2); av = avma; z = mulur(e, log10_2()); z = floorr(z); e = itos(z); } else /* e < 0 */ { if (e > -1e15) return (long)(-(-e*LOG10_2)-1); av = avma; z = mulsr(e, log10_2()); z = floorr(z); e = itos(z) - 1; } avma = av; return e; } static char * zeros(char *b, long nb) { while (nb-- > 0) *b++ = '0'; *b = 0; return b; } /* # of decimal digits, assume l > 0 */ static long numdig(ulong l) { if (l < 100000) { if (l < 100) return (l < 10)? 1: 2; if (l < 10000) return (l < 1000)? 3: 4; return 5; } if (l < 10000000) return (l < 1000000)? 6: 7; if (l < 1000000000) return (l < 100000000)? 8: 9; return 10; } /* let ndig <= 9, x < 10^ndig, write in p[-ndig..-1] the decimal digits of x */ static void utodec(char *p, ulong x, long ndig) { switch(ndig) { case 9: *--p = x % 10 + '0'; x = x/10; case 8: *--p = x % 10 + '0'; x = x/10; case 7: *--p = x % 10 + '0'; x = x/10; case 6: *--p = x % 10 + '0'; x = x/10; case 5: *--p = x % 10 + '0'; x = x/10; case 4: *--p = x % 10 + '0'; x = x/10; case 3: *--p = x % 10 + '0'; x = x/10; case 2: *--p = x % 10 + '0'; x = x/10; case 1: *--p = x % 10 + '0'; x = x/10; } } /* convert abs(x) != 0 to str. Prepend '-' if (sx < 0) */ static char * itostr_sign(GEN x, int sx, long *len) { long l, d; ulong *res = convi(x, &l); /* l 9-digits words (< 10^9) + (optional) sign + \0 */ char *s = (char*)new_chunk(nchar2nlong(l*9 + 1 + 1)), *t = s; if (sx < 0) *t++ = '-'; d = numdig(*--res); t += d; utodec(t, *res, d); while (--l > 0) { t += 9; utodec(t, *--res, 9); } *t = 0; *len = t - s; return s; } /********************************************************************/ /** **/ /** WRITE A REAL NUMBER **/ /** **/ /********************************************************************/ /* 19 digits (if 64 bits, at most 2^60-1) + 1 sign */ static const long MAX_EXPO_LEN = 20; /* write z to buf, inserting '.' at 'point', 0 < point < strlen(z) */ static void wr_dec(char *buf, char *z, long point) { char *s = buf + point; strncpy(buf, z, point); /* integer part */ *s++ = '.'; z += point; while ( (*s++ = *z++) ) /* empty */; } static char * zerotostr(void) { char *s = (char*)new_chunk(1); s[0] = '0'; s[1] = 0; return s; } /* write a real 0 of exponent ex in format f */ static char * real0tostr_width_frac(long width_frac) { char *buf, *s; if (width_frac == 0) return zerotostr(); buf = s = stack_malloc(width_frac + 3); *s++ = '0'; *s++ = '.'; (void)zeros(s, width_frac); return buf; } /* write a real 0 of exponent ex */ static char * real0tostr(long ex, char format, char exp_char, long wanted_dec) { char *buf, *buf0; if (format == 'f') { long width_frac = wanted_dec; if (width_frac < 0) width_frac = (ex >= 0)? 0: (long)(-ex * LOG10_2); return real0tostr_width_frac(width_frac); } else { buf0 = buf = stack_malloc(3 + MAX_EXPO_LEN + 1); *buf++ = '0'; *buf++ = '.'; *buf++ = exp_char; sprintf(buf, "%ld", ex10(ex) + 1); } return buf0; } /* format f, width_frac >= 0: number of digits in fractional part, */ static char * absrtostr_width_frac(GEN x, int width_frac) { long beta, ls, point, lx, sx = signe(x); char *s, *buf; GEN z; if (!sx) return real0tostr_width_frac(width_frac); /* x != 0 */ lx = realprec(x); beta = width_frac; if (beta) /* >= 0 */ { /* z = |x| 10^beta, 10^b = 5^b * 2^b, 2^b goes into exponent */ if (beta > 4e9) lx++; z = mulrr(x, rpowuu(5UL, (ulong)beta, lx+1)); setsigne(z, 1); shiftr_inplace(z, beta); } else z = mpabs(x); z = roundr_safe(z); if (!signe(z)) return real0tostr_width_frac(width_frac); s = itostr_sign(z, 1, &ls); /* ls > 0, number of digits in s */ point = ls - beta; /* position of . in s; <= ls, may be < 0 */ if (point > 0) /* write integer_part.fractional_part */ { /* '.', trailing \0 */ buf = stack_malloc( ls + 1+1 ); if (ls == point) strcpy(buf, s); /* no '.' */ else wr_dec(buf, s, point); } else { /* point <= 0, fractional part must be written */ char *t; /* '0', '.', zeroes, trailing \0 */ buf = t = stack_malloc( 1 + 1 - point + ls + 1 ); *t++ = '0'; *t++ = '.'; t = zeros(t, -point); strcpy(t, s); } return buf; } /* Return t_REAL |x| in floating point format. * Allocate freely, the caller must clean the stack. * FORMAT: E/e (exponential), F/f (floating point), G/g * wanted_dec: number of significant digits to print (all if < 0). */ static char * absrtostr(GEN x, int sp, char FORMAT, long wanted_dec) { const char format = (char)tolower((int)FORMAT), exp_char = (format == FORMAT)? 'e': 'E'; long beta, ls, point, lx, sx = signe(x), ex = expo(x); char *s, *buf, *buf0; GEN z; if (!sx) return real0tostr(ex, format, exp_char, wanted_dec); /* x != 0 */ lx = realprec(x); if (wanted_dec >= 0) { /* reduce precision if possible */ long w = ndec2prec(wanted_dec); /* digits -> pari precision in words */ if (lx > w) lx = w; /* truncature with guard, no rounding */ } beta = ex10(prec2nbits(lx) - ex); if (beta) { /* z = |x| 10^beta, 10^b = 5^b * 2^b, 2^b goes into exponent */ if (beta > 0) { if (beta > 18) { lx++; x = rtor(x, lx); } z = mulrr(x, rpowuu(5UL, (ulong)beta, lx+1)); } else { if (beta < -18) { lx++; x = rtor(x, lx); } z = divrr(x, rpowuu(5UL, (ulong)-beta, lx+1)); } setsigne(z, 1); shiftr_inplace(z, beta); } else z = x; z = roundr_safe(z); if (!signe(z)) return real0tostr(ex, format, exp_char, wanted_dec); s = itostr_sign(z, 1, &ls); /* ls > 0, number of digits in s */ if (wanted_dec < 0) wanted_dec = ls; else if (ls > wanted_dec) { beta -= ls - wanted_dec; ls = wanted_dec; if (s[ls] >= '5') /* round up */ { long i; for (i = ls-1; i >= 0; s[i--] = '0') if (++s[i] <= '9') break; if (i < 0) { s[0] = '1'; beta--; } } s[ls] = 0; } /* '.', " E", exponent, trailing \0 */ point = ls - beta; /* position of . in s; < 0 or > 0 */ if (beta <= 0 || format == 'e' || (format == 'g' && point-1 < -4)) { /* e format */ buf0 = buf = stack_malloc(ls+1+2+MAX_EXPO_LEN + 1); wr_dec(buf, s, 1); buf += ls + 1; if (sp) *buf++ = ' '; *buf++ = exp_char; sprintf(buf, "%ld", point-1); } else if (point > 0) /* f format, write integer_part.fractional_part */ { buf0 = buf = stack_malloc(ls+1 + 1); wr_dec(buf, s, point); /* point < ls since beta > 0 */ } else /* f format, point <= 0, write fractional part */ { buf0 = buf = stack_malloc(2-point+ls + 1); *buf++ = '0'; *buf++ = '.'; buf = zeros(buf, -point); strcpy(buf, s); } return buf0; } /* vsnprintf implementation rewritten from snprintf.c to be found at * * http://www.nersc.gov/~scottc/misc/docs/snort-2.1.1-RC1/snprintf_8c-source.html * The original code was * Copyright (C) 1998-2002 Martin Roesch * available under the terms of the GNU GPL version 2 or later. It * was itself adapted from an original version by Patrick Powell. */ /* Modifications for format %Ps: R.Butel IMB/CNRS 2007/12/03 */ /* l = old len, L = new len */ static void str_alloc0(outString *S, long l, long L) { char *s; if (S->use_stack) { s = stack_malloc(L); memcpy(s, S->string, l); } else s = (char*)pari_realloc((void*)S->string, L); S->string = s; S->cur = s + l; S->end = s + L; S->size = L; } /* make sure S is large enough to write l further words (<= l * 20 chars). * To avoid automatic extension in between av = avma / avma = av pairs * [ would destroy S->string if (S->use_stack) ] */ static void str_alloc(outString *S, long l) { l *= 20; if (S->end - S->cur <= l) str_alloc0(S, S->cur - S->string, S->size + maxss(S->size, l)); } static void str_putc(outString *S, char c) { *S->cur++ = c; if (S->cur == S->end) str_alloc0(S, S->size, S->size << 1); } static void str_init(outString *S, int use_stack) { char *s; S->size = 1024; S->use_stack = use_stack; if (S->use_stack) s = (char*)stack_malloc(S->size); else s = (char*)pari_malloc(S->size); S->string = S->cur = s; S->end = S->string + S->size; } static void str_puts(outString *S, const char *s) { while (*s) str_putc(S, *s++); } static void str_putscut(outString *S, const char *str, int cut) { if (cut < 0) str_puts(S, str); else { while (*str && cut-- > 0) str_putc(S, *str++); } } /* lbuf = strlen(buf), len < 0: unset */ static void outpad(outString *S, const char *buf, long lbuf, int sign, long ljust, long len, long zpad) { long padlen = len - lbuf; if (padlen < 0) padlen = 0; if (ljust) padlen = -padlen; if (padlen > 0) { if (zpad) { if (sign) { str_putc(S, sign); --padlen; } while (padlen > 0) { str_putc(S, '0'); --padlen; } } else { if (sign) --padlen; while (padlen > 0) { str_putc(S, ' '); --padlen; } if (sign) str_putc(S, sign); } } else if (sign) str_putc(S, sign); str_puts(S, buf); while (padlen < 0) { str_putc(S, ' '); ++padlen; } } /* len < 0 or maxwidth < 0: unset */ static void fmtstr(outString *S, const char *buf, int ljust, int len, int maxwidth) { int padlen, lbuf = strlen(buf); if (maxwidth >= 0 && lbuf > maxwidth) lbuf = maxwidth; padlen = len - lbuf; if (padlen < 0) padlen = 0; if (ljust) padlen = -padlen; while (padlen > 0) { str_putc(S, ' '); --padlen; } str_putscut(S, buf, maxwidth); while (padlen < 0) { str_putc(S, ' '); ++padlen; } } /* abs(base) is 8, 10, 16. If base < 0, some "alternate" form * -- print hex in uppercase * -- prefix octal with 0 * signvalue = -1: unsigned, otherwise ' ' or '+' */ static void fmtnum(outString *S, long lvalue, GEN gvalue, int base, int signvalue, int ljust, int len, int zpad) { int caps; char *buf0, *buf; long lbuf, mxl; GEN uvalue = NULL; ulong ulvalue = 0; pari_sp av = avma; /* Assume !S->use_stack */ if (gvalue) { long s, l; if (typ(gvalue) != t_INT) { long i, j, h; l = lg(gvalue); switch(typ(gvalue)) { case t_VEC: str_putc(S, '['); for (i = 1; i < l; i++) { fmtnum(S, 0, gel(gvalue,i), base, signvalue, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); return; case t_COL: str_putc(S, '['); for (i = 1; i < l; i++) { fmtnum(S, 0, gel(gvalue,i), base, signvalue, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); str_putc(S, '~'); return; case t_MAT: if (l == 1) str_puts(S, "[;]"); else { h = lgcols(gvalue); for (i=1; i 0) caps = 0; else { caps = 1; base = -base; } buf0 = buf = stack_malloc(mxl) + mxl; /* fill from the right */ *--buf = 0; /* trailing \0 */ if (gvalue) { if (base == 10) { long i, l, cnt; ulong *larray = convi(uvalue, &l); larray -= l; for (i = 0; i < l; i++) { cnt = 0; ulvalue = larray[i]; do { *--buf = '0' + ulvalue%10; ulvalue = ulvalue / 10; cnt++; } while (ulvalue); if (i + 1 < l) for (;cnt<9;cnt++) *--buf = '0'; } } else if (base == 16) { long i, l = lgefint(uvalue); GEN up = int_LSW(uvalue); for (i = 2; i < l; i++, up = int_nextW(up)) { ulong ucp = (ulong)*up; long j; for (j=0; j < BITS_IN_LONG/4; j++) { unsigned char cv = ucp & 0xF; *--buf = (caps? "0123456789ABCDEF":"0123456789abcdef")[cv]; ucp >>= 4; if (ucp == 0 && i+1 == l) break; } } /* loop on hex digits in word */ } else if (base == 8) { long i, l = lgefint(uvalue); GEN up = int_LSW(uvalue); ulong rem = 0; int shift = 0; int mask[3] = {0, 1, 3}; for (i = 2; i < l; i++, up = int_nextW(up)) { ulong ucp = (ulong)*up; long j, ldispo = BITS_IN_LONG; if (shift) { /* 0, 1 or 2 */ unsigned char cv = ((ucp & mask[shift]) <<(3-shift)) + rem; *--buf = "01234567"[cv]; ucp >>= shift; ldispo -= shift; }; shift = (shift + 3 - BITS_IN_LONG % 3) % 3; for (j=0; j < BITS_IN_LONG/3; j++) { unsigned char cv = ucp & 0x7; if (ucp == 0 && i+1 == l) { rem = 0; break; }; *--buf = "01234567"[cv]; ucp >>= 3; ldispo -= 3; rem = ucp; if (ldispo < 3) break; } } /* loop on hex digits in word */ if (rem) *--buf = "01234567"[rem]; } } else { /* not a gvalue, thus a standard integer */ do { *--buf = (caps? "0123456789ABCDEF":"0123456789abcdef")[ulvalue % (unsigned)base ]; ulvalue /= (unsigned)base; } while (ulvalue); } /* leading 0 if octal and alternate # form */ if (caps && base == 8) *--buf = '0'; lbuf = (buf0 - buf) - 1; END: outpad(S, buf, lbuf, signvalue, ljust, len, zpad); avma = av; } static GEN v_get_arg(GEN arg_vector, int *index, const char *save_fmt) { if (*index >= lg(arg_vector)) pari_err(e_MISC, "missing arg %d for printf format '%s'", *index, save_fmt); return gel(arg_vector, (*index)++); } static int dosign(int blank, int plus) { if (plus) return('+'); if (blank) return(' '); return 0; } /* x * 10 + 'digit whose char value is ch'. Do not check for overflow */ static int shift_add(int x, int ch) { if (x < 0) /* was unset */ x = ch - '0'; else x = x*10 + ch - '0'; return x; } static long get_sigd(GEN gvalue, char ch, int maxwidth) { long sigd, e; if (maxwidth < 0) return prec2ndec(precreal); switch(ch) { case 'E': case 'e': sigd = maxwidth+1; break; case 'F': case 'f': e = gexpo(gvalue); if (e == -(long)HIGHEXPOBIT) /* exact 0 */ sigd = 0; else sigd = ex10(e) + 1 + maxwidth; break; /* 'g', 'G' */ default : sigd = maxwidth? maxwidth: 1; break; } return sigd; } static void fmtreal(outString *S, GEN gvalue, int space, int signvalue, int FORMAT, int maxwidth, int ljust, int len, int zpad) { pari_sp av = avma; /* Assume !S->use_stack */ long sigd; char *buf; if (typ(gvalue) == t_REAL) sigd = get_sigd(gvalue, FORMAT, maxwidth); else { long i, j, h, l = lg(gvalue); switch(typ(gvalue)) { case t_VEC: str_putc(S, '['); for (i = 1; i < l; i++) { fmtreal(S, gel(gvalue,i), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); return; case t_COL: str_putc(S, '['); for (i = 1; i < l; i++) { fmtreal(S, gel(gvalue,i), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); str_putc(S, '~'); return; case t_MAT: if (l == 1) str_puts(S, "[;]"); else { h = lgcols(gvalue); for (i=1; i= 0) buf = absrtostr_width_frac(gvalue, maxwidth); else buf = absrtostr(gvalue, space, FORMAT, sigd); if (signe(gvalue) < 0) signvalue = '-'; outpad(S, buf, strlen(buf), signvalue, ljust, len, zpad); avma = av; } /* format handling "inspired" by the standard draft at -- http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf pages 274ff * fmt is a standard printf format, except 'P' is a "length modifier" * allowing GEN arguments. Use either the arg_vector or (if NULL) the va_list */ static char * sm_dopr(const char *fmt, GEN arg_vector, va_list args) { int GENflag = 0, longflag = 0, pointflag = 0; int print_plus, print_blank, with_sharp, ch, ljust, len, maxwidth, zpad; long lvalue; int index = 1; GEN gvalue; const char *save_fmt = fmt; outString __S, *S = &__S; str_init(S, 0); while ((ch = *fmt++) != '\0') { switch(ch) { case '%': ljust = zpad = 0; len = maxwidth = -1; GENflag = longflag = pointflag = 0; print_plus = print_blank = with_sharp = 0; nextch: ch = *fmt++; switch(ch) { case 0: pari_err(e_MISC, "printf: end of format"); /*------------------------------------------------------------------------ -- flags ------------------------------------------------------------------------*/ case '-': ljust = 1; goto nextch; case '+': print_plus = 1; goto nextch; case '#': with_sharp = 1; goto nextch; case ' ': print_blank = 1; goto nextch; case '0': /* appears as a flag: set zero padding */ if (len < 0 && !pointflag) { zpad = '0'; goto nextch; } /* else part of a field width or precision */ /* fall through */ /*------------------------------------------------------------------------ -- maxwidth or precision ------------------------------------------------------------------------*/ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (pointflag) maxwidth = shift_add(maxwidth, ch); else len = shift_add(len, ch); goto nextch; case '*': { int *t = pointflag? &maxwidth: &len; if (arg_vector) *t = (int)gtolong( v_get_arg(arg_vector, &index, save_fmt) ); else *t = va_arg(args, int); goto nextch; } case '.': if (pointflag) pari_err(e_MISC, "two '.' in conversion specification"); pointflag = 1; goto nextch; /*------------------------------------------------------------------------ -- length modifiers ------------------------------------------------------------------------*/ case 'l': if (GENflag) pari_err(e_MISC, "P/l length modifiers in the same conversion"); #if !defined(_WIN64) if (longflag) pari_err_IMPL( "ll length modifier in printf"); #endif longflag = 1; goto nextch; case 'P': if (longflag) pari_err(e_MISC, "P/l length modifiers in the same conversion"); if (GENflag) pari_err(e_MISC, "'P' length modifier appears twice"); GENflag = 1; goto nextch; case 'h': /* dummy: va_arg promotes short into int */ goto nextch; /*------------------------------------------------------------------------ -- conversions ------------------------------------------------------------------------*/ case 'u': /* not a signed conversion: print_(blank|plus) ignored */ #define get_num_arg() \ if (arg_vector) { \ lvalue = 0; \ gvalue = v_get_arg(arg_vector, &index, save_fmt); \ } else { \ if (GENflag) { \ lvalue = 0; \ gvalue = va_arg(args, GEN); \ } else { \ lvalue = longflag? va_arg(args, long): va_arg(args, int); \ gvalue = NULL; \ } \ } get_num_arg(); fmtnum(S, lvalue, gvalue, 10, -1, ljust, len, zpad); break; case 'o': /* not a signed conversion: print_(blank|plus) ignored */ get_num_arg(); fmtnum(S, lvalue, gvalue, with_sharp? -8: 8, -1, ljust, len, zpad); break; case 'd': case 'i': get_num_arg(); fmtnum(S, lvalue, gvalue, 10, dosign(print_blank, print_plus), ljust, len, zpad); break; case 'p': str_putc(S, '0'); str_putc(S, 'x'); if (arg_vector) lvalue = (long)v_get_arg(arg_vector, &index, save_fmt); else lvalue = (long)va_arg(args, void*); fmtnum(S, lvalue, NULL, 16, -1, ljust, len, zpad); break; case 'x': /* not a signed conversion: print_(blank|plus) ignored */ if (with_sharp) { str_putc(S, '0'); str_putc(S, 'x'); } get_num_arg(); fmtnum(S, lvalue, gvalue, 16, -1, ljust, len, zpad); break; case 'X': /* not a signed conversion: print_(blank|plus) ignored */ if (with_sharp) { str_putc(S, '0'); str_putc(S, 'X'); } get_num_arg(); fmtnum(S, lvalue, gvalue,-16, -1, ljust, len, zpad); break; case 's': { char *strvalue; int tofree = 0; if (arg_vector) { gvalue = v_get_arg(arg_vector, &index, save_fmt); strvalue = NULL; } else { if (GENflag) { gvalue = va_arg(args, GEN); strvalue = NULL; } else { gvalue = NULL; strvalue = va_arg(args, char *); } } if (gvalue) { if (typ(gvalue) == t_STR) strvalue = GSTR(gvalue); else { strvalue = GENtostr_fun(gvalue, GP_DATA->fmt, bruti); tofree = 1; } } fmtstr(S, strvalue, ljust, len, maxwidth); if (tofree) pari_free(strvalue); break; } case 'c': if (arg_vector) { gvalue = v_get_arg(arg_vector, &index, save_fmt); ch = (int)gtolong(gvalue); } else { if (GENflag) ch = (int)gtolong( va_arg(args,GEN) ); else ch = va_arg(args, int); } str_putc(S, ch); break; case '%': str_putc(S, ch); continue; case 'g': case 'G': case 'e': case 'E': case 'f': case 'F': { pari_sp av = avma; if (arg_vector) gvalue = simplify_shallow( v_get_arg(arg_vector, &index, save_fmt) ); else { if (GENflag) gvalue = simplify_shallow( va_arg(args, GEN) ); else gvalue = dbltor( va_arg(args, double) ); } fmtreal(S, gvalue, GP_DATA->fmt->sp, dosign(print_blank,print_plus), ch, maxwidth, ljust, len, zpad); avma = av; break; } default: pari_err(e_MISC, "invalid conversion or specification %c in format `%s'", ch, save_fmt); } /* second switch on ch */ break; default: str_putc(S, ch); break; } /* first switch on ch */ } /* while loop on ch */ *S->cur = 0; return S->string; } void decode_color(long n, long *c) { c[1] = n & 0xf; n >>= 4; /* foreground */ c[2] = n & 0xf; n >>= 4; /* background */ c[0] = n & 0xf; /* attribute */ } #define COLOR_LEN 16 /* start printing in "color" c */ /* terminal has to support ANSI color escape sequences */ void out_term_color(PariOUT *out, long c) { static char s[COLOR_LEN]; out->puts(term_get_color(s, c)); } void term_color(long c) { out_term_color(pariOut, c); } char * term_get_color(char *s, long n) { long c[3], a; if (!s) s = stack_malloc(COLOR_LEN); if (disable_color) { *s = 0; return s; } if (n == c_NONE || (a = gp_colors[n]) == c_NONE) sprintf(s, "%c[0m", esc); /* reset */ else { decode_color(a,c); if (c[1]<8) c[1] += 30; else c[1] += 82; if (a & (1L<<12)) /* transparent background */ sprintf(s, "%c[%ld;%ldm", esc, c[0], c[1]); else { if (c[2]<8) c[2] += 40; else c[2] += 92; sprintf(s, "%c[%ld;%ld;%ldm", esc, c[0], c[1], c[2]); } } return s; } static long strlen_real(const char *s) { const char *t = s; long len = 0; while (*t) { if (t[0] == esc && t[1] == '[') { /* skip ANSI escape sequence */ t += 2; while (*t && *t++ != 'm') /* empty */; continue; } t++; len++; } return len; } #undef COLOR_LEN /********************************************************************/ /** **/ /** PRINTING BASED ON SCREEN WIDTH **/ /** **/ /********************************************************************/ #undef larg /* problems with SCO Unix headers (ioctl_arg) */ #ifdef HAS_TIOCGWINSZ # ifdef __sun # include # endif # include #endif static int term_width_intern(void) { if (GP_DATA->flags & gpd_TEST) return 0; #ifdef _WIN32 return win32_terminal_width(); #endif #ifdef HAS_TIOCGWINSZ { struct winsize s; if (!(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) && !ioctl(0, TIOCGWINSZ, &s)) return s.ws_col; } #endif { char *str; if ((str = os_getenv("COLUMNS"))) return atoi(str); } #ifdef __EMX__ { int scrsize[2]; _scrsize(scrsize); return scrsize[0]; } #endif return 0; } static int term_height_intern(void) { if (GP_DATA->flags & gpd_TEST) return 0; #ifdef _WIN32 return win32_terminal_height(); #endif #ifdef HAS_TIOCGWINSZ { struct winsize s; if (!(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) && !ioctl(0, TIOCGWINSZ, &s)) return s.ws_row; } #endif { char *str; if ((str = os_getenv("LINES"))) return atoi(str); } #ifdef __EMX__ { int scrsize[2]; _scrsize(scrsize); return scrsize[1]; } #endif return 0; } #define DFT_TERM_WIDTH 80 #define DFT_TERM_HEIGHT 20 int term_width(void) { int n = term_width_intern(); return (n>1)? n: DFT_TERM_WIDTH; } int term_height(void) { int n = term_height_intern(); return (n>1)? n: DFT_TERM_HEIGHT; } static ulong col_index; /* output string wrapped after MAX_WIDTH characters (for gp -test) */ static void putc_lw(char c) { if (c == '\n') col_index = 0; else if (col_index >= GP_DATA->linewrap) { normalOutC('\n'); col_index = 1; } else col_index++; normalOutC(c); } static void puts_lw(const char *s) { while (*s) putc_lw(*s++); } static PariOUT pariOut_lw= {putc_lw, puts_lw, normalOutF}; void init_linewrap(long w) { col_index=0; GP_DATA->linewrap=w; pariOut=&pariOut_lw; } /* output stopped after max_line have been printed, for default(lines,). * n = length of prefix already printed (print up to max_lin lines) */ void lim_lines_output(char *s, long n, long max_lin) { long lin, col, width; char c; if (!*s) return; width = term_width(); lin = 1; col = n; if (lin > max_lin) return; while ( (c = *s++) ) { if (lin >= max_lin) if (c == '\n' || col >= width-5) { pari_sp av = avma; normalOutS(term_get_color(NULL, c_ERR)); avma = av; normalOutS("[+++]"); return; } if (c == '\n') { col = -1; lin++; } else if (col == width) { col = 0; lin++; } set_last_newline(c); col++; normalOutC(c); } } static void new_line(PariOUT *out, const char *prefix) { out_putc(out, '\n'); if (prefix) out_puts(out, prefix); } #define is_blank(c) ((c) == ' ' || (c) == '\n' || (c) == '\t') /* output: < s wrapped at EOL > * < ... > * ^--- (no \n at the end) * If str is NULL, omit the arrow, end the text with '\n'. * If prefix is NULL, use "" */ void print_prefixed_text(PariOUT *out, const char *s, const char *prefix, const char *str) { const long prelen = prefix? strlen_real(prefix): 0; const long W = term_width(), ls = strlen(s); long linelen = prelen; char *word = (char*)pari_malloc(ls + 3); if (prefix) out_puts(out, prefix); for(;;) { long len; int blank = 0; char *u = word; while (*s && !is_blank(*s)) *u++ = *s++; *u = 0; /* finish "word" */ len = strlen_real(word); linelen += len; if (linelen >= W) { new_line(out, prefix); linelen = prelen + len; } out_puts(out, word); while (is_blank(*s)) { switch (*s) { case ' ': break; case '\t': linelen = (linelen & ~7UL) + 8; out_putc(out, '\t'); blank = 1; break; case '\n': linelen = W; blank = 1; break; } if (linelen >= W) { new_line(out, prefix); linelen = prelen; } s++; } if (!*s) break; if (!blank) { out_putc(out, ' '); linelen++; } } if (!str) out_putc(out, '\n'); else { long i,len = strlen_real(str); int space = (*str == ' ' && str[1]); if (linelen + len >= W) { new_line(out, prefix); linelen = prelen; if (space) { str++; len--; space = 0; } } out_term_color(out, c_OUTPUT); out_puts(out, str); if (!len || str[len-1] != '\n') out_putc(out, '\n'); if (space) { linelen++; len--; } out_term_color(out, c_ERR); if (prefix) { out_puts(out, prefix); linelen -= prelen; } for (i=0; i MAX_PAST) { past = MAX_PAST; strcpy(t, "..."); t += 3; } term_get_color(t, c_OUTPUT); t += strlen(t); strncpy(t, s - past, past); t[past] = 0; } /* suffix (past arrow) */ t = str; if (!past) *t++ = ' '; strncpy(t, s, STR_LEN); t[STR_LEN] = 0; /* prefix '***' */ term_get_color(pre, c_ERR); strcat(pre, " *** "); /* now print */ print_prefixed_text(out, buf, pre, str); pari_free(buf); } /********************************************************************/ /** **/ /** GEN <---> CHARACTER STRINGS **/ /** **/ /********************************************************************/ static OUT_FUN get_fun(long flag) { switch(flag) { case f_RAW : return bruti; case f_TEX : return texi; default: return matbruti; } } char * stack_strdup(const char *s) { long n = strlen(s)+1; char *t = stack_malloc(n); memcpy(t,s,n); return t; } char * stack_strcat(const char *s, const char *t) { long ls = strlen(s), lt = strlen(t); long n = ls + lt + 1; char *u = stack_malloc(n); memcpy(u, s, ls); memcpy(u + ls,t, lt+1); return u; } char * pari_strdup(const char *s) { long n = strlen(s)+1; char *t = (char*)pari_malloc(n); memcpy(t,s,n); return t; } char * pari_strndup(const char *s, long n) { char *t = (char*)pari_malloc(n+1); memcpy(t,s,n); t[n] = 0; return t; } /* not stack clean */ static char * GENtostr_aux(GEN x, pariout_t *T, OUT_FUN out, int use_stack) { outString S; str_init(&S, use_stack); out(x, T, &S); *S.cur = 0; return S.string; } static char * GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out) { pari_sp av = avma; char *s = GENtostr_aux(x, T, out, 0); avma = av; return s; } /* returns a malloc-ed string, which should be freed after usage */ /* Returns pari_malloc()ed string */ char * GENtostr(GEN x) { pariout_t *T = GP_DATA->fmt; return GENtostr_fun(x, T, get_fun(T->prettyp)); } char * GENtoTeXstr(GEN x) { return GENtostr_fun(x, GP_DATA->fmt, &texi); } static char * GENtostr1(GEN x, OUT_FUN out) { return (typ(x) == t_STR)? pari_strdup(GSTR(x)) : GENtostr_fun(x, GP_DATA->fmt, out); } /* see print0(). Returns pari_malloc()ed string */ static char * RgV_to_str_fun(GEN g, OUT_FUN out) { pari_sp av = avma; char *t, *t2; long i, tlen = 0, l = lg(g); GEN Ls, Ll; /* frequent special case */ if (l == 2) return GENtostr1(gel(g,1), out); Ls = cgetg(l, t_VEC); Ll = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { char *s = GENtostr1(gel(g,i), out); gel(Ls,i) = (GEN)s; Ll[i] = strlen(s); tlen += Ll[i]; } t2 = t = (char*)pari_malloc(tlen + 1); *t = 0; for (i = 1; i < l; i++) { strcpy(t2, (char*)Ls[i]); t2 += Ll[i]; pari_free((void*)Ls[i]); } avma = av; return t; } char * RgV_to_str(GEN g, long flag) { return RgV_to_str_fun(g, get_fun(flag)); } static GEN Str_fun(GEN g, OUT_FUN out) { char *t = RgV_to_str_fun(g, out); GEN z = strtoGENstr(t); pari_free(t); return z; } GEN Str(GEN g) { return Str_fun(g, &bruti); } GEN Strtex(GEN g) { return Str_fun(g, &texi); } GEN Strexpand(GEN g) { char *s = RgV_to_str_fun(g, &bruti), *t = path_expand(s); GEN z = strtoGENstr(t); pari_free(t); pari_free(s); return z; } GEN GENtoGENstr(GEN x) { char *s = GENtostr_fun(x, GP_DATA->fmt, &bruti); GEN z = strtoGENstr(s); pari_free(s); return z; } GEN GENtoGENstr_nospace(GEN x) { pariout_t T = *(GP_DATA->fmt); char *s; GEN z; T.sp = 0; s = GENtostr_fun(x, &T, &bruti); z = strtoGENstr(s); pari_free(s); return z; } static char * GENtostr_fun_unquoted(GEN x, pariout_t *T, OUT_FUN f) { if (typ(x)==t_STR) return GSTR(x); /* text surrounded by "" otherwise */ return GENtostr_aux(x, T, f, 1); } char * GENtostr_unquoted(GEN x) { return GENtostr_fun_unquoted(x, GP_DATA->fmt, &bruti); } static char ltoc(long n) { if (n <= 0 || n > 255) pari_err(e_MISC, "out of range in integer -> character conversion (%ld)", n); return (char)n; } static char itoc(GEN x) { return ltoc(gtos(x)); } GEN Strchr(GEN g) { long i, l, len, t = typ(g); char *s; GEN x; if (is_vec_t(t)) { l = lg(g); len = nchar2nlong(l); x = cgetg(len+1, t_STR); s = GSTR(x); for (i=1; i0)? '+' : '-') #define putsigne(S, x) str_puts(S, (x>0)? " + " : " - ") #define sp_sign_sp(T,S, x) ((T)->sp? putsigne(S,x): putsigne_nosp(S,x)) #define comma_sp(T,S) ((T)->sp? str_puts(S, ", "): str_putc(S, ',')) /* print e to S (more efficient than sprintf) */ static void str_ulong(outString *S, ulong e) { if (e == 0) str_putc(S, '0'); else { char buf[21], *p = buf + sizeof(buf)/sizeof(*buf); *--p = 0; if (e > 9) { do *--p = "0123456789"[e % 10]; while ((e /= 10) > 9); } *--p = "0123456789"[e]; str_puts(S, p); } } static void str_long(outString *S, long e) { if (e >= 0) str_ulong(S, (ulong)e); else { str_putc(S, '-'); str_ulong(S, (ulong)(-e)); } } static void wr_vecsmall(pariout_t *T, outString *S, GEN g) { long i, l; str_puts(S, "Vecsmall(["); l = lg(g); for (i=1; i 0 assumed */ { switch (i%10) { case 1: if (i%100==11) return ordsuff[3]; /* xxx11-th */ return ordsuff[0]; /* xxx01-st, xxx21-st,... */ case 2: if (i%100==12) return ordsuff[3]; /* xxx12-th */ return ordsuff[1]; /* xxx02-nd, xxx22-nd,... */ case 3: if (i%100==13) return ordsuff[3]; /* xxx13-th */ return ordsuff[2]; /* xxx03-rd, xxx23-rd,... */ default: return ordsuff[3]; /* xxxx4-th,... */ } } const char * type_name(long t) { const char *s; switch(t) { case t_INT : s="t_INT"; break; case t_REAL : s="t_REAL"; break; case t_INTMOD : s="t_INTMOD"; break; case t_FRAC : s="t_FRAC"; break; case t_FFELT : s="t_FFELT"; break; case t_COMPLEX: s="t_COMPLEX"; break; case t_PADIC : s="t_PADIC"; break; case t_QUAD : s="t_QUAD"; break; case t_POLMOD : s="t_POLMOD"; break; case t_POL : s="t_POL"; break; case t_SER : s="t_SER"; break; case t_RFRAC : s="t_RFRAC"; break; case t_QFR : s="t_QFR"; break; case t_QFI : s="t_QFI"; break; case t_VEC : s="t_VEC"; break; case t_COL : s="t_COL"; break; case t_MAT : s="t_MAT"; break; case t_LIST : s="t_LIST"; break; case t_STR : s="t_STR"; break; case t_VECSMALL:s="t_VECSMALL";break; case t_CLOSURE: s="t_CLOSURE"; break; case t_ERROR: s="t_ERROR"; break; default: pari_err(e_MISC,"unknown type %ld",t); s = NULL; /* not reached */ } return s; } static char vsigne(GEN x) { long s = signe(x); if (!s) return '0'; return (s > 0) ? '+' : '-'; } static void blancs(long nb) { while (nb-- > 0) pari_putc(' '); } /* write an "address" */ static void str_addr(outString *S, ulong x) { char s[128]; sprintf(s,"%0*lx", BITS_IN_LONG/4, x); str_puts(S, s); } static void dbg_addr(ulong x) { pari_printf("[&=%0*lx] ", BITS_IN_LONG/4, x); } /* write a "word" */ static void dbg_word(ulong x) { pari_printf("%0*lx ", BITS_IN_LONG/4, x); } /* bl: indent level */ static void dbg(GEN x, long nb, long bl) { long tx,i,j,e,dx,lx; if (!x) { pari_puts("NULL\n"); return; } tx = typ(x); if (tx == t_INT && x == gen_0) { pari_puts("gen_0\n"); return; } dbg_addr((ulong)x); lx = lg(x); pari_printf("%s(lg=%ld%s):",type_name(tx)+2,lx,isclone(x)? ",CLONE" : ""); dbg_word(x[0]); if (! is_recursive_t(tx)) /* t_INT, t_REAL, t_STR, t_VECSMALL */ { if (tx == t_STR) pari_puts("chars:"); else if (tx == t_INT) { lx = lgefint(x); pari_printf("(%c,lgefint=%ld):", vsigne(x), lx); } else if (tx == t_REAL) pari_printf("(%c,expo=%ld):", vsigne(x), expo(x)); if (nb < 0) nb = lx; for (i=1; i < nb; i++) dbg_word(x[i]); pari_putc('\n'); return; } if (tx == t_PADIC) pari_printf("(precp=%ld,valp=%ld):", precp(x), valp(x)); else if (tx == t_POL) 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)); 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)); for (i=1; iname); dbg_addr((ulong)ep); pari_printf(":\n hash = %3ld, menu = %2ld, code = %-10s", hash, ep->menu, ep->code? ep->code: "NULL"); if (ep->next) { pari_printf("next = %s ",(ep->next)->name); dbg_addr((ulong)ep->next); } pari_puts("\n"); } /* s = digit n : list of entrees in functions_hash[n] (s = $: last entry) * = range m-n: functions_hash[m..n] * = identifier: entree for that identifier */ void print_functions_hash(const char *s) { long m, n, Max, Total; entree *ep; if (isdigit((int)*s) || *s == '$') { m = functions_tblsz-1; n = atol(s); if (*s=='$') n = m; if (mnext) print_entree(ep,n); } return; } if (is_keyword_char((int)*s)) { ep = is_entry_intern(s,functions_hash,&n); if (!ep) pari_err(e_MISC,"no such function"); print_entree(ep,n); return; } if (*s=='-') { for (n=0; nnext) m++; pari_printf("%3ld:%3ld ",n,m); if (n%9 == 8) pari_putc('\n'); } pari_putc('\n'); return; } Max = Total = 0; for (n=0; nnext) { print_entree(ep,n); cnt++; } Total += cnt; if (cnt > Max) Max = cnt; } pari_printf("Total: %ld, Max: %ld\n", Total, Max); } /********************************************************************/ /** **/ /** FORMATTED OUTPUT **/ /** **/ /********************************************************************/ 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; } static void do_append(char **sp, char c, char *last, int count) { if (*sp + count > last) pari_err(e_MISC, "TeX variable name too long"); while (count--) *(*sp)++ = c; } static char * get_texvar(long v, char *buf, unsigned int len) { entree *ep = varentries[v]; char *t = buf, *e = buf + len - 1; const char *s; if (!ep) pari_err(e_MISC, "this object uses debugging variables"); s = ep->name; if (strlen(s) >= len) pari_err(e_MISC, "TeX variable name too long"); while (isalpha((int)*s)) *t++ = *s++; *t = 0; if (isdigit((int)*s) || *s == '_') { int seen1 = 0, seen = 0; /* Skip until the first non-underscore */ while (*s == '_') s++, seen++; /* Special-case integers and empty subscript */ if (*s == 0 || isdigit((unsigned char)*s)) seen++; do_append(&t, '_', e, 1); do_append(&t, '{', e, 1); do_append(&t, '[', e, seen - 1); while (1) { if (*s == '_') seen1++, s++; else { if (seen1) { do_append(&t, ']', e, (seen >= seen1 ? seen1 : seen) - 1); do_append(&t, ',', e, 1); do_append(&t, '[', e, seen1 - 1); if (seen1 > seen) seen = seen1; seen1 = 0; } if (*s == 0) break; do_append(&t, *s++, e, 1); } } do_append(&t, ']', e, seen - 1); do_append(&t, '}', e, 1); *t = 0; } return buf; } void dbg_pari_heap(void) { long nu, l, u, s; pari_sp av = avma; GEN adr = getheap(); nu = (top-avma)/sizeof(long); l = (top-bot)/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", nu, nu/1024*sizeof(long)); pari_printf(" Available : %ld long words (%ld K)\n", (l-nu), (l-nu)/1024*sizeof(long)); pari_printf(" Occupation of the PARI stack : %6.2f percent\n", 100.0*nu/l); pari_printf(" %ld objects on heap occupy %ld long words\n\n", itos(gel(adr,1)), itos(gel(adr,2))); u = pari_var_next(); s = MAXVARN - pari_var_next_temp(); pari_printf(" %ld variable names used (%ld user + %ld private) out of %d\n\n", u+s, u, s, MAXVARN); 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) { long i; switch (typ(g)) { case t_INT: return !signe(g); case t_COMPLEX: return isnull(gel(g,1)) && isnull(gel(g,2)); case t_FFELT: return FF_equal0(g); case t_QUAD: 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; return 1; } return 0; } /* return 1 or -1 if g is 1 or -1, 0 otherwise*/ static long isone(GEN g) { long i; switch (typ(g)) { case t_INT: return (signe(g) && is_pm1(g))? signe(g): 0; case t_FFELT: return FF_equal1(g); case t_COMPLEX: return isnull(gel(g,2))? isone(gel(g,1)): 0; case t_QUAD: return isnull(gel(g,3))? isone(gel(g,2)): 0; case t_FRAC: case t_RFRAC: return isone(gel(g,1)) * isone(gel(g,2)); case t_POL: if (!signe(g)) return 0; for (i=lg(g)-1; i>2; i--) if (!isnull(gel(g,i))) return 0; return isone(gel(g,2)); } return 0; } /* if g is a "monomial", return its sign, 0 otherwise */ static long isfactor(GEN g) { long i,deja,sig; switch(typ(g)) { case t_INT: case t_REAL: return (signe(g)<0)? -1: 1; case t_FRAC: case t_RFRAC: return isfactor(gel(g,1)); case t_FFELT: return isfactor(FF_to_FpXQ_i(g)); case t_COMPLEX: if (isnull(gel(g,1))) return isfactor(gel(g,2)); if (isnull(gel(g,2))) return isfactor(gel(g,1)); return 0; case t_PADIC: return !signe(gel(g,4)); case t_QUAD: if (isnull(gel(g,2))) return isfactor(gel(g,3)); if (isnull(gel(g,3))) return isfactor(gel(g,2)); return 0; case t_POL: deja = 0; sig = 1; for (i=lg(g)-1; i>1; i--) if (!isnull_for_pol(gel(g,i))) { if (deja) return 0; sig=isfactor(gel(g,i)); deja=1; } return sig? sig: 1; case t_SER: for (i=lg(g)-1; i>1; i--) if (!isnull(gel(g,i))) return 0; } return 1; } /* return 1 if g is a "truc" (see anal.c) */ static long isdenom(GEN g) { long i,deja; switch(typ(g)) { case t_FRAC: case t_RFRAC: return 0; case t_COMPLEX: return isnull(gel(g,2)); case t_PADIC: return !signe(gel(g,4)); case t_QUAD: return isnull(gel(g,3)); case t_POL: deja = 0; for (i=lg(g)-1; i>1; i--) if (!isnull(gel(g,i))) { if (deja) return 0; if (i==2) return isdenom(gel(g,2)); if (!isone(gel(g,i))) return 0; deja=1; } return 1; case t_SER: for (i=lg(g)-1; i>1; i--) if (!isnull(gel(g,i))) return 0; } return 1; } /********************************************************************/ /** **/ /** RAW OUTPUT **/ /** **/ /********************************************************************/ /* ^e */ static void texexpo(outString *S, long e) { if (e != 1) { str_putc(S, '^'); if (e >= 0 && e < 10) { str_putc(S, '0' + e); } else { str_putc(S, '{'); str_long(S, e); str_putc(S, '}'); } } } static void wrexpo(outString *S, long e) { if (e != 1) { str_putc(S, '^'); str_long(S, e); } } /* v^e */ static void VpowE(outString *S, const char *v, long e) { str_puts(S, v); wrexpo(S,e); } static void texVpowE(outString *S, const char *v, long e) { str_puts(S, v); texexpo(S,e); } static void monome(outString *S, const char *v, long e) { if (e) VpowE(S, v, e); else str_putc(S, '1'); } static void texnome(outString *S, const char *v, long e) { if (e) texVpowE(S, v, e); else str_putc(S, '1'); } /* ( a ) */ static void paren(pariout_t *T, outString *S, GEN a) { str_putc(S, '('); bruti(a,T,S); str_putc(S, ')'); } static void texparen(pariout_t *T, outString *S, GEN a) { if (T->TeXstyle & TEXSTYLE_PAREN) str_puts(S, " ("); else str_puts(S, " \\left("); texi(a,T,S); if (T->TeXstyle & TEXSTYLE_PAREN) str_puts(S, ") "); else str_puts(S, "\\right) "); } /* * v^d */ 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); } } static void times_monome(outString *S, const char *v, long d) { if (d) { str_putc(S, '*'); monome(S,v,d); } } /* write a * v^d */ static void wr_monome(pariout_t *T, outString *S, GEN a, const char *v, long d) { long sig = isone(a); if (sig) { sp_sign_sp(T,S,sig); monome(S,v,d); } else { sig = isfactor(a); if (sig) { sp_sign_sp(T,S,sig); bruti_sign(a,T,S,0); } else { sp_sign_sp(T,S,1); paren(T,S, a); } times_monome(S, v, d); } } static void wr_texnome(pariout_t *T, outString *S, GEN a, const char *v, long d) { long sig = isone(a); str_putc(S, '\n'); /* Avoid TeX buffer overflow */ if (T->TeXstyle & TEXSTYLE_BREAK) str_puts(S, "\\PARIbreak "); if (sig) { putsigne(S,sig); texnome(S,v,d); } else { sig = isfactor(a); if (sig) { putsigne(S,sig); texi_sign(a,T,S,0); } else { str_puts(S, " +"); texparen(T,S, a); } times_texnome(S, v, d); } } static void wr_lead_monome(pariout_t *T, outString *S, GEN a,const char *v, long d, int addsign) { long sig = isone(a); if (sig) { if (addsign && sig<0) str_putc(S, '-'); monome(S,v,d); } else { if (isfactor(a)) bruti_sign(a,T,S,addsign); else paren(T,S, a); times_monome(S, v, d); } } static void wr_lead_texnome(pariout_t *T, outString *S, GEN a,const char *v, long d, int addsign) { long sig = isone(a); if (sig) { if (addsign && sig<0) str_putc(S, '-'); texnome(S,v,d); } else { if (isfactor(a)) texi_sign(a,T,S,addsign); else texparen(T,S, a); times_texnome(S, v, d); } } static void prints(GEN g, pariout_t *T, outString *S) { (void)T; str_long(S, (long)g); } static void quote_string(outString *S, char *s) { str_putc(S, '"'); while (*s) { char c=*s++; if (c=='\\' || c=='"' || c=='\033' || c=='\n' || c=='\t') { str_putc(S, '\\'); switch(c) { case '\\': case '"': break; case '\n': c='n'; break; case '\033': c='e'; break; case '\t': c='t'; break; } } str_putc(S, c); } str_putc(S, '"'); } static int print_0_or_pm1(GEN g, outString *S, int addsign) { long r; if (!g) { str_puts(S, "NULL"); return 1; } if (isnull(g)) { str_putc(S, '0'); return 1; } r = isone(g); if (r) { if (addsign && r<0) str_putc(S, '-'); str_putc(S, '1'); return 1; } return 0; } 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 v = gel(g,7), d = gmael3(g,5,3,1); long i, l = lg(v), n=0; for(i=1; iname); str_putc(S,'='); if (tex) texi(gel(v,l-i),T,S); else bruti(gel(v,l-i),T,S); if (--n) str_putc(S,','); } str_puts(S,");"); } } static void bruti_intern(GEN g, pariout_t *T, outString *S, int addsign) { long l,i,j,r, tg = typ(g); GEN a,b; const char *v; char buf[32]; switch(tg) { case t_INT: if (addsign && signe(g) < 0) str_putc(S, '-'); str_absint(S, g); break; case t_REAL: { pari_sp av; str_alloc(S, lg(g)); /* careful! */ av = avma; if (addsign && signe(g) < 0) str_putc(S, '-'); str_puts(S, absrtostr(g, T->sp, (char)toupper((int)T->format), T->sigd) ); avma = av; break; } case t_INTMOD: case t_POLMOD: str_puts(S, new_fun_set? "Mod(": "mod("); bruti(gel(g,2),T,S); comma_sp(T,S); bruti(gel(g,1),T,S); str_putc(S, ')'); break; case t_FFELT: bruti_sign(FF_to_FpXQ_i(g),T,S,addsign); break; case t_FRAC: case t_RFRAC: r = isfactor(gel(g,1)); if (!r) str_putc(S, '('); bruti_sign(gel(g,1),T,S,addsign); if (!r) str_putc(S, ')'); str_putc(S, '/'); r = isdenom(gel(g,2)); if (!r) str_putc(S, '('); bruti(gel(g,2),T,S); if (!r) str_putc(S, ')'); break; case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD); a = gel(g,r+1); b = gel(g,r+2); v = r? "w": "I"; if (isnull(a)) { wr_lead_monome(T,S,b,v,1,addsign); return; } bruti_sign(a,T,S,addsign); if (!isnull(b)) wr_monome(T,S,b,v,1); break; case t_POL: v = get_var(varn(g), buf); /* hack: we want g[i] = coeff of degree i. */ i = degpol(g); g += 2; while (isnull(gel(g,i))) i--; wr_lead_monome(T,S,gel(g,i),v,i,addsign); while (i--) { a = gel(g,i); if (!isnull_for_pol(a)) wr_monome(T,S,a,v,i); } break; case t_SER: v = get_var(varn(g), buf); i = valp(g); l = lgpol(g); if (l) { /* See normalize(): Mod(0,2)*x^i*(1+O(x)), has valp = i+1 */ if (l == 1 && !signe(g)) i--; /* hack: we want g[i] = coeff of degree i */ l += i; g -= i-2; wr_lead_monome(T,S,gel(g,i),v,i,addsign); while (++i < l) { a = gel(g,i); if (!isnull_for_pol(a)) wr_monome(T,S,a,v,i); } sp_sign_sp(T,S,1); } str_puts(S, "O("); VpowE(S, v, i); str_putc(S, ')'); break; case t_PADIC: { GEN p = gel(g,2); pari_sp av, av0; char *ev; str_alloc(S, (precp(g)+1) * lgefint(p)); /* careful! */ av0 = avma; ev = itostr(p); av = avma; i = valp(g); l = precp(g)+i; g = gel(g,4); for (; i=7) { GEN str = closure_get_text(g); if (typ(str)==t_STR) str_puts(S, GSTR(str)); else { str_putc(S,'('); str_puts(S,GSTR(gel(str,1))); str_puts(S,")->"); print_context(g, T, S, 0); str_puts(S,GSTR(gel(str,2))); } } else { str_puts(S,"{\""); str_puts(S,GSTR(closure_get_code(g))); str_puts(S,"\","); wr_vecsmall(T,S,closure_get_oper(g)); str_putc(S,','); bruti(gel(g,4),T,S); str_putc(S,','); bruti(gel(g,5),T,S); str_putc(S,'}'); } break; case t_MAT: { OUT_FUN print; r = lg(g); if (r==1) { str_puts(S, "[;]"); return; } l = lgcols(g); if (l==1) { str_puts(S, "matrix(0,"); str_long(S, r-1); if (new_fun_set) str_putc(S, ')'); else str_puts(S, ",j,k,0)"); return; } print = (typ(gel(g,1)) == t_VECSMALL)? prints: bruti; if (l==2) { str_puts(S, new_fun_set? "Mat(": "mat("); if (r == 2) { print(gcoeff(g,1,1),T,S); str_putc(S, ')'); return; } } str_putc(S, '['); for (i=1; isp) str_putc(S, ' '); } } str_putc(S, ']'); if (l==2) str_putc(S, ')'); break; } default: str_addr(S, *g); } } static void bruti_sign(GEN g, pariout_t *T, outString *S, int addsign) { if (!print_0_or_pm1(g, S, addsign)) bruti_intern(g, T, S, addsign); } static void matbruti(GEN g, pariout_t *T, outString *S) { long i, j, r, w, l, *pad = NULL; pari_sp av; OUT_FUN print; if (typ(g) != t_MAT) { bruti(g,T,S); return; } r=lg(g); if (r==1 || lgcols(g)==1) { str_puts(S, "[;]"); return; } l = lgcols(g); str_putc(S, '\n'); print = (typ(gel(g,1)) == t_VECSMALL)? prints: bruti; av = avma; w = term_width(); if (2*r < w) { long lgall = 2; /* opening [ and closing ] */ pari_sp av2; outString scratchstr; pad = cgetg(l*r+1, t_VECSMALL); /* left on stack if (S->use_stack)*/ av2 = avma; str_init(&scratchstr, 1); for (j=1; j w) { pad = NULL; break; } /* doesn't fit, abort padding */ } avma = av2; } for (i=1; i 0) str_putc(S, ' '); } print(gcoeff(g,i,j),T,S); if (juse_stack) avma = av; } /********************************************************************/ /** **/ /** TeX OUTPUT **/ /** **/ /********************************************************************/ /* this follows bruti_sign */ static void texi_sign(GEN g, pariout_t *T, outString *S, int addsign) { long tg,i,j,l,r; GEN a,b; const char *v; char buf[67]; if (print_0_or_pm1(g, S, addsign)) return; tg = typ(g); switch(tg) { case t_INT: case t_REAL: case t_QFR: case t_QFI: bruti_intern(g, T, S, addsign); break; case t_INTMOD: case t_POLMOD: texi(gel(g,2),T,S); str_puts(S, " mod "); texi(gel(g,1),T,S); break; case t_FRAC: if (addsign && isfactor(gel(g,1)) < 0) str_putc(S, '-'); str_puts(S, "\\frac{"); texi_sign(gel(g,1),T,S,0); str_puts(S, "}{"); texi_sign(gel(g,2),T,S,0); str_puts(S, "}"); break; case t_RFRAC: str_puts(S, "\\frac{"); texi(gel(g,1),T,S); /* too complicated otherwise */ str_puts(S, "}{"); texi(gel(g,2),T,S); str_puts(S, "}"); break; case t_FFELT: bruti_sign(FF_to_FpXQ_i(g),T,S,addsign); break; case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD); a = gel(g,r+1); b = gel(g,r+2); v = r? "w": "I"; if (isnull(a)) { wr_lead_texnome(T,S,b,v,1,addsign); break; } texi_sign(a,T,S,addsign); if (!isnull(b)) wr_texnome(T,S,b,v,1); break; case t_POL: v = get_texvar(varn(g), buf, sizeof(buf)); /* hack: we want g[i] = coeff of degree i. */ i = degpol(g); g += 2; while (isnull(gel(g,i))) i--; wr_lead_texnome(T,S,gel(g,i),v,i,addsign); while (i--) { a = gel(g,i); if (!isnull_for_pol(a)) wr_texnome(T,S,a,v,i); } break; case t_SER: v = get_texvar(varn(g), buf, sizeof(buf)); i = valp(g); if (lgpol(g)) { /* hack: we want g[i] = coeff of degree i. */ l = i + lgpol(g); g -= i-2; wr_lead_texnome(T,S,gel(g,i),v,i,addsign); while (++i < l) { a = gel(g,i); if (!isnull_for_pol(a)) wr_texnome(T,S,a,v,i); } str_puts(S, "+ "); } str_puts(S, "O("); texnome(S,v,i); str_putc(S, ')'); break; case t_PADIC: { GEN p = gel(g,2); pari_sp av; char *ev; str_alloc(S, (precp(g)+1) * lgefint(p)); /* careful! */ av = avma; i = valp(g); l = precp(g)+i; g = gel(g,4); ev = itostr(p); for (; i=6) { GEN str = closure_get_text(g); if (typ(str)==t_STR) str_puts(S, GSTR(str)); else { str_putc(S,'('); str_puts(S,GSTR(gel(str,1))); str_puts(S,")\\mapsto "); print_context(g, T, S ,1); str_puts(S,GSTR(gel(str,2))); } } else { str_puts(S,"\\{\""); str_puts(S,GSTR(closure_get_code(g))); str_puts(S,"\","); texi(gel(g,3),T,S); str_putc(S,','); texi(gel(g,4),T,S); str_putc(S,','); texi(gel(g,5),T,S); str_puts(S,"\\}"); } break; case t_MAT: { str_puts(S, "\\pmatrix{\n "); r = lg(g); if (r>1) { OUT_FUN print = (typ(gel(g,1)) == t_VECSMALL)? prints: texi; l = lgcols(g); for (i=1; iformat = f; T->sigd = sigd; T->sp = sp; } static void gen_output_fun(GEN x, pariout_t *T, OUT_FUN out) { char *s = GENtostr_fun(x, T, out); pari_puts(s); pari_free(s); } void fputGEN_pariout(GEN x, pariout_t *T, FILE *out) { char *s = GENtostr_fun(x, T, get_fun(T->prettyp)); if (*s) set_last_newline(s[strlen(s)-1]); fputs(s, out); pari_free(s); } void gen_output(GEN x, pariout_t *T) { if (!T) T = GP_DATA->fmt; gen_output_fun(x, T, get_fun(T->prettyp)); } void brute(GEN g, char f, long d) { pariout_t T; _initout(&T,f,d,0); gen_output_fun(g, &T, &bruti); } void matbrute(GEN g, char f, long d) { pariout_t T; _initout(&T,f,d,1); gen_output_fun(g, &T, &matbruti); } void texe(GEN g, char f, long d) { pariout_t T; _initout(&T,f,d,0); gen_output_fun(g, &T, &texi); } void output(GEN x) { brute(x,'g',-1); pari_putc('\n'); pari_flush(); } void outmat(GEN x) { matbrute(x,'g',-1); pari_putc('\n'); pari_flush(); } void err_printf(const char* fmt, ...) { va_list args; va_start(args, fmt); out_vprintf(pariErr,fmt,args); va_end(args); } /*******************************************************************/ /** FILES **/ /*******************************************************************/ /* to cache '~' expansion */ static char *homedir; /* last file read successfully from try_name() */ static THREAD char *last_filename; /* stack of temporary files (includes all infiles + some output) */ static THREAD pariFILE *last_tmp_file; /* stack of "permanent" (output) files */ static THREAD pariFILE *last_file; pariFILE * pari_last_tmp_file(void) { return last_tmp_file; } #if defined(UNIX) || defined(__EMX__) # include # include /* for open */ # ifdef __EMX__ # include # endif # define HAVE_PIPES #endif #if defined(_WIN32) # define HAVE_PIPES #endif #ifndef O_RDONLY # define O_RDONLY 0 #endif pariFILE * newfile(FILE *f, const char *name, int type) { pariFILE *file = (pariFILE*) pari_malloc(strlen(name) + 1 + sizeof(pariFILE)); file->type = type; file->name = strcpy((char*)(file+1), name); file->file = f; file->next = NULL; if (type & mf_PERM) { file->prev = last_file; last_file = file; } else { file->prev = last_tmp_file; last_tmp_file = file; } if (file->prev) (file->prev)->next = file; if (DEBUGFILES) err_printf("I/O: new pariFILE %s (code %d) \n",name,type); return file; } static void pari_kill_file(pariFILE *f) { if ((f->type & mf_PIPE) == 0) { if (f->file != stdin && fclose(f->file)) pari_warn(warnfile, "close", f->name); } #ifdef HAVE_PIPES else { if (f->type & mf_FALSE) { if (f->file != stdin && fclose(f->file)) pari_warn(warnfile, "close", f->name); if (unlink(f->name)) pari_warn(warnfile, "delete", f->name); } else if (pclose(f->file) < 0) pari_warn(warnfile, "close pipe", f->name); } #endif if (DEBUGFILES) err_printf("I/O: closing file %s (code %d) \n",f->name,f->type); pari_free(f); } void pari_fclose(pariFILE *f) { if (f->next) (f->next)->prev = f->prev; else if (f == last_tmp_file) last_tmp_file = f->prev; else if (f == last_file) last_file = f->prev; if (f->prev) (f->prev)->next = f->next; pari_kill_file(f); } static pariFILE * pari_open_file(FILE *f, const char *s, const char *mode) { if (!f) pari_err_FILE("requested file", s); if (DEBUGFILES) err_printf("I/O: opening file %s (mode %s)\n", s, mode); return newfile(f,s,0); } pariFILE * pari_fopen_or_fail(const char *s, const char *mode) { return pari_open_file(fopen(s, mode), s, mode); } pariFILE * pari_fopen(const char *s, const char *mode) { FILE *f = fopen(s, mode); return f? pari_open_file(f, s, mode): NULL; } void pari_fread_chars(void *b, size_t n, FILE *f) { if (fread(b, sizeof(char), n, f) < n) pari_err_FILE("input file [fread]", "FILE*"); } /* FIXME: HAS_FDOPEN & allow standard open() flags */ #ifdef UNIX /* open tmpfile s (a priori for writing) avoiding symlink attacks */ pariFILE * pari_safefopen(const char *s, const char *mode) { long fd = open(s, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); if (fd == -1) pari_err(e_MISC,"tempfile %s already exists",s); return pari_open_file(fdopen(fd, mode), s, mode); } #else pariFILE * pari_safefopen(const char *s, const char *mode) { return pari_fopen_or_fail(s, mode); } #endif void pari_unlink(const char *s) { if (unlink(s)) pari_warn(warner, "I/O: can\'t remove file %s", s); else if (DEBUGFILES) 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 * Check for leaked file handlers (temporary files) */ int popinfile(void) { pariFILE *f = last_tmp_file, *g; while (f) { if (f->type & mf_IN) break; pari_warn(warner, "I/O: leaked file descriptor (%d): %s", f->type, f->name); g = f; f = f->prev; pari_fclose(g); } last_tmp_file = f; if (!f) return -1; pari_fclose(last_tmp_file); for (f = last_tmp_file; f; f = f->prev) if (f->type & mf_IN) { pari_infile = f->file; return 0; } pari_infile = stdin; return 0; } /* delete all "temp" files open since last reference point F */ void filestate_restore(pariFILE *F) { pariFILE *f = pari_last_tmp_file(); if (DEBUGFILES>1) err_printf("gp_context_restore: deleting open files...\n"); while (f) { pariFILE *g = f->prev; if (f == F) break; pari_fclose(f); f = g; } for (; f; f = f->prev) { if (f->type & mf_IN) { pari_infile = f->file; if (DEBUGFILES>1) err_printf("restoring pari_infile to %s\n", f->name); break; } } if (!f) { pari_infile = stdin; if (DEBUGFILES>1) err_printf("gp_context_restore: restoring pari_infile to stdin\n"); } if (DEBUGFILES>1) err_printf("done\n"); } static void kill_file_stack(pariFILE **s) { pariFILE *f = *s; while (f) { pariFILE *t = f->prev; pari_kill_file(f); *s = f = t; /* have to update *s in case of ^C */ } } void killallfiles(void) { kill_file_stack(&last_tmp_file); pari_infile = stdin; } void pari_init_homedir(void) { homedir = NULL; } void pari_close_homedir(void) { if (homedir) pari_free(homedir); } void pari_init_files(void) { last_filename = NULL; last_tmp_file = NULL; last_file=NULL; } void pari_close_files(void) { popinfile(); /* look for leaks */ kill_file_stack(&last_file); if (last_filename) pari_free(last_filename); if (pari_logfile) { fclose(pari_logfile); pari_logfile = NULL; } killallfiles(); } static int ok_pipe(FILE *f) { if (DEBUGFILES) err_printf("I/O: checking output pipe...\n"); pari_CATCH(CATCH_ALL) { return 0; } pari_TRY { int i; fprintf(f,"\n\n"); fflush(f); for (i=1; i<1000; i++) fprintf(f," \n"); fprintf(f,"\n"); fflush(f); } pari_ENDCATCH; return 1; } pariFILE * try_pipe(const char *cmd, int fl) { #ifndef HAVE_PIPES pari_err(e_ARCH,"pipes"); return NULL; #else FILE *file; const char *f; VOLATILE int flag = fl; # ifdef __EMX__ if (_osmode == DOS_MODE) /* no pipes under DOS */ { pari_sp av = avma; char *s; if (flag & mf_OUT) pari_err(e_ARCH,"pipes"); f = pari_unique_filename("pipe"); s = stack_malloc(strlen(cmd)+strlen(f)+4); sprintf(s,"%s > %s",cmd,f); file = system(s)? NULL: fopen(f,"r"); flag |= mf_FALSE; pari_free(f); avma = av; } else # endif { file = (FILE *) popen(cmd, (flag & mf_OUT)? "w": "r"); if (flag & mf_OUT) { if (!ok_pipe(file)) return NULL; flag |= mf_PERM; } f = cmd; } if (!file) pari_err(e_MISC,"[pipe:] '%s' failed",cmd); return newfile(file, f, mf_PIPE|flag); #endif } typedef void (*pari_sighandler_t)(int); pari_sighandler_t os_signal(int sig, pari_sighandler_t f) { #ifdef HAS_SIGACTION struct sigaction sa, oldsa; sa.sa_handler = f; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; if (sigaction(sig, &sa, &oldsa)) return NULL; return oldsa.sa_handler; #elif defined(WINCE) return SIG_IGN; #else return signal(sig,f); #endif } #if 0 void os_close(long fd) { #ifdef WINCE CloseHandle((HANDLE)fd); #else close(fd); #endif } void os_read(long fd, char ch[], long s) { #ifdef WINCE DWORD chRead; ReadFile((HANDLE)fd, ch, s, &chRead, NULL); #else (void)read(fd,ch,s); #endif } long os_open(const char *s, int mode) { long fd; #ifdef WINCE HANDLE h; short ws[256]; if (mode != O_RDONLY) pari_err_IMPL("generic open for Windows"); MultiByteToWideChar(CP_ACP, 0, s, strlen(s)+1, ws, 256); h = CreateFile(ws,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); fd = (h == INVALID_HANDLE_VALUE)? (long)-1: (long)h; #else fd = open(s,mode); #endif return fd; } #endif char * os_getenv(const char *s) { #ifdef HAS_GETENV return getenv(s); #else (void) s; return NULL; #endif } GEN gp_getenv(const char *s) { char *t = os_getenv(s); return t?strtoGENstr(t):gen_0; } /* FIXME: HAS_GETPWUID */ #if defined(UNIX) || defined(__EMX__) #include #include /* user = "": use current uid */ char * pari_get_homedir(const char *user) { struct passwd *p; char *dir = NULL; if (!*user) { if (homedir) dir = homedir; else { p = getpwuid(geteuid()); if (p) { dir = p->pw_dir; homedir = pari_strdup(dir); /* cache result */ } } } else { p = getpwnam(user); if (p) dir = p->pw_dir; } /* warn, but don't kill session on startup (when expanding path) */ if (!dir) pari_warn(warner,"can't expand ~%s", user? user: ""); return dir; } #else char * pari_get_homedir(const char *user) { (void) user; return NULL; } #endif /*******************************************************************/ /** **/ /** GP STANDARD INPUT AND OUTPUT **/ /** **/ /*******************************************************************/ #ifdef HAS_OPENDIR /* slow, but more portable than stat + S_ISDIR */ static int is_dir_opendir(const char *name) { DIR *d = opendir(name); if (d) { (void)closedir(d); return 1; } return 0; } #endif #ifdef HAS_STAT static int is_dir_stat(const char *name) { struct stat buf; if (stat(name, &buf)) return 0; return S_ISDIR(buf.st_mode); } #endif /* Does name point to a directory? */ int pari_is_dir(const char *name) { #ifdef HAS_STAT return is_dir_stat(name); #else # ifdef HAS_OPENDIR return is_dir_opendir(name); # else (void) name; return 0; # endif #endif } /* Does name point to a regular file? */ /* If unknown, assume that it is indeed regular. */ int pari_is_file(const char *name) { #ifdef HAS_STAT struct stat buf; if (stat(name, &buf)) return 1; return S_ISREG(buf.st_mode); #else (void) name; return 1; #endif } int pari_stdin_isatty(void) { #ifdef HAS_ISATTY return isatty( fileno(stdin) ); #else return 1; #endif } /* expand tildes in filenames, return a malloc'ed buffer */ static char * _path_expand(const char *s) { const char *t; char *ret, *dir = NULL; if (*s != '~') return pari_strdup(s); s++; /* skip ~ */ t = s; while (*t && *t != '/') t++; if (t == s) dir = pari_get_homedir(""); else { size_t len = t - s; char *user = (char*)pari_malloc(len+1); (void)strncpy(user,s,len); user[len] = 0; dir = pari_get_homedir(user); pari_free(user); } if (!dir) return pari_strdup(s); ret = (char*)pari_malloc(strlen(dir) + strlen(t) + 1); sprintf(ret,"%s%s",dir,t); return ret; } /* expand environment variables in str, return a malloc'ed buffer * assume no \ remain and str can be freed */ static char * _expand_env(char *str) { long i, l, len = 0, xlen = 16, xnum = 0; char *s = str, *s0 = s, *env; char **x = (char **)pari_malloc(xlen * sizeof(char*)); while (*s) { if (*s != '$') { s++; continue; } l = s - s0; if (l) { s0 = strncpy((char*)pari_malloc(l+1), s0, l); s0[l] = 0; x[xnum++] = s0; len += l; } if (xnum > xlen - 3) /* need room for possibly two more elts */ { xlen <<= 1; x = (char **)pari_realloc((void*)x, xlen * sizeof(char*)); } s0 = ++s; /* skip $ */ while (is_keyword_char(*s)) s++; l = s - s0; env = strncpy((char*)pari_malloc(l+1), s0, l); env[l] = 0; s0 = os_getenv(env); if (!s0) { pari_warn(warner,"undefined environment variable: %s",env); s0 = (char*)""; } l = strlen(s0); if (l) { s0 = strncpy((char*)pari_malloc(l+1), s0, l); s0[l] = 0; x[xnum++] = s0; len += l; } pari_free(env); s0 = s; } l = s - s0; if (l) { s0 = strncpy((char*)pari_malloc(l+1), s0, l); s0[l] = 0; x[xnum++] = s0; len += l; } s = (char*)pari_malloc(len+1); *s = 0; for (i = 0; i < xnum; i++) { (void)strcat(s, x[i]); pari_free(x[i]); } pari_free(str); pari_free(x); return s; } char * path_expand(const char *s) { #ifdef _WIN32 char *ss, *p; ss = pari_strdup(s); for (p = ss; *p != 0; ++p) if (*p == '\\') *p = '/'; p = _expand_env(_path_expand(ss)); pari_free(ss); return p; #else return _expand_env(_path_expand(s)); #endif } #ifdef HAS_STRFTIME # include void strftime_expand(const char *s, char *buf, long max) { time_t t; BLOCK_SIGINT_START t = time(NULL); (void)strftime(buf,max,s,localtime(&t)); BLOCK_SIGINT_END } #else void strftime_expand(const char *s, char *buf, long max) { strcpy(buf,s); } #endif void delete_dirs(gp_path *p) { char **v = p->dirs, **dirs; if (v) { p->dirs = NULL; /* in case of error */ for (dirs = v; *dirs; dirs++) pari_free(*dirs); pari_free(v); } } #if defined(__EMX__) || defined(_WIN32) || defined(__CYGWIN32__) # define PATH_SEPARATOR ';' /* beware DOSish 'C:' disk drives */ #else # define PATH_SEPARATOR ':' #endif const char * pari_default_path(void) { #if PATH_SEPARATOR == ';' return ".;C:;C:/gp"; #elif defined(UNIX) return ".:~:~/gp"; #else return "."; #endif } void gp_expand_path(gp_path *p) { char **dirs, *s, *v = p->PATH; int i, n = 0; delete_dirs(p); v = pari_strdup(v); for (s=v; *s; s++) if (*s == PATH_SEPARATOR) { *s = 0; if (s == v || s[-1] != 0) n++; /* ignore empty path components */ } dirs = (char**) pari_malloc((n + 2)*sizeof(char *)); for (s=v, i=0; i<=n; i++) { char *end, *f; while (!*s) s++; /* skip empty path components */ f = end = s + strlen(s); while (f > s && *--f == '/') *f = 0; /* skip trailing '/' */ dirs[i] = path_expand(s); s = end + 1; /* next path component */ } pari_free((void*)v); dirs[i] = NULL; p->dirs = dirs; } /* name is a malloc'ed (existing) filename. Accept it as new pari_infile * (unzip if needed). */ static pariFILE * pari_get_infile(const char *name, FILE *file) { #ifdef ZCAT long l = strlen(name); const char *end = name + l-1; if (l > 2 && (!strncmp(end-1,".Z",2) #ifdef GNUZCAT || !strncmp(end-2,".gz",3) #endif )) { /* compressed file (compress or gzip) */ char *cmd = stack_malloc(strlen(ZCAT) + l + 4); sprintf(cmd,"%s \"%s\"",ZCAT,name); fclose(file); return try_pipe(cmd, mf_IN); } #endif return newfile(file, name, mf_IN); } pariFILE * pari_fopengz(const char *s) { pari_sp av = avma; char *name; long l; FILE *f = fopen(s, "r"); pariFILE *pf; if (f) return pari_get_infile(s, f); l = strlen(s); name = stack_malloc(l + 3 + 1); strcpy(name, s); (void)sprintf(name + l, ".gz"); f = fopen(name, "r"); pf = f ? pari_get_infile(name, f): NULL; avma = av; return pf; } static FILE* try_open(char *s) { if (!pari_is_dir(s)) return fopen(s, "r"); pari_warn(warner,"skipping directory %s",s); return NULL; } void forpath_init(forpath_t *T, gp_path *path, const char *s) { T->s = s; T->ls = strlen(s); T->dir = path->dirs; } char * forpath_next(forpath_t *T) { char *t, *dir = T->dir[0]; if (!dir) return NULL; /* done */ /* room for dir + '/' + s + '\0' */ t = (char*)pari_malloc(strlen(dir) + T->ls + 2); sprintf(t,"%s/%s", dir, T->s); T->dir++; return t; } /* If a file called "name" exists (possibly after appending ".gp") * record it in the file_stack (as a pipe if compressed). * name is malloc'ed, we free it before returning */ static FILE * try_name(char *name) { pari_sp av = avma; char *s = name; FILE *file = try_open(name); if (!file) { /* try appending ".gp" to name */ s = stack_malloc(strlen(name)+4); sprintf(s, "%s.gp", name); file = try_open(s); } if (file) { if (! last_tmp_file) { /* empty file stack, record this name */ if (last_filename) pari_free(last_filename); last_filename = pari_strdup(s); } file = pari_infile = pari_get_infile(s,file)->file; } pari_free(name); avma = av; return file; } static FILE * switchin_last(void) { char *s = last_filename; FILE *file; if (!s) pari_err(e_MISC,"You never gave me anything to read!"); file = try_open(s); if (!file) pari_err_FILE("input file",s); return pari_infile = pari_get_infile(s,file)->file; } /* return 1 if s starts by '/' or './' or '../' */ int path_is_absolute(char *s) { #ifdef _WIN32 if( (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') ) { return *(s+1) == ':'; } #endif if (*s == '/') return 1; if (*s++ != '.') return 0; if (*s == '/') return 1; if (*s++ != '.') return 0; return *s == '/'; } /* If name = "", re-read last file */ FILE * switchin(const char *name) { FILE *f; char *s; if (!*name) return switchin_last(); s = path_expand(name); /* if s is an absolute path, don't use dir_list */ if (path_is_absolute(s)) { if ((f = try_name(s))) return f; } else { char *t; forpath_t T; forpath_init(&T, GP_DATA->path, s); while ( (t = forpath_next(&T)) ) if ((f = try_name(t))) return f; } pari_err_FILE("input file",name); return NULL; /*not reached*/ } static int is_magic_ok(FILE *f); static FILE * switchout_get_FILE(const char *name) { FILE* f; /* only for ordinary files (to avoid blocking on pipes). */ if (pari_is_file(name)) { f = fopen(name, "r"); if (f) { int magic = is_magic_ok(f); fclose(f); if (magic) pari_err_FILE("binary output file [ use writebin ! ]", name); } } f = fopen(name, "a"); if (!f) pari_err_FILE("output file",name); return f; } void switchout(const char *name) { if (name) pari_outfile = switchout_get_FILE(name); else if (pari_outfile != stdout) { fclose(pari_outfile); pari_outfile = stdout; } } /*******************************************************************/ /** **/ /** I/O IN BINARY FORM **/ /** **/ /*******************************************************************/ static void pari_fread_longs(void *a, size_t c, FILE *d) { if (fread(a,sizeof(long),c,d) < c) pari_err_FILE("input file [fread]", "FILE*"); } static void _fwrite(const void *a, size_t b, size_t c, FILE *d) { if (fwrite(a,b,c,d) < c) pari_err_FILE("output file [fwrite]", "FILE*"); } static void _lfwrite(const void *a, size_t b, FILE *c) { _fwrite(a,sizeof(long),b,c); } static void _cfwrite(const void *a, size_t b, FILE *c) { _fwrite(a,sizeof(char),b,c); } enum { BIN_GEN, NAM_GEN, VAR_GEN, RELINK_TABLE }; static long rd_long(FILE *f) { long L; pari_fread_longs(&L, 1UL, f); return L; } static void wr_long(long L, FILE *f) { _lfwrite(&L, 1UL, f); } /* append x to file f */ static void wrGEN(GEN x, FILE *f) { GENbin *p = copy_bin_canon(x); size_t L = p->len; wr_long(L,f); if (L) { wr_long((long)p->x,f); wr_long((long)p->base,f); _lfwrite(GENbinbase(p), L,f); } pari_free((void*)p); } static void wrstr(const char *s, FILE *f) { size_t L = strlen(s)+1; wr_long(L,f); _cfwrite(s, L, f); } static char * rdstr(FILE *f) { size_t L = (size_t)rd_long(f); char *s; if (!L) return NULL; s = (char*)pari_malloc(L); pari_fread_chars(s, L, f); return s; } static void writeGEN(GEN x, FILE *f) { fputc(BIN_GEN,f); wrGEN(x, f); } static void writenamedGEN(GEN x, const char *s, FILE *f) { fputc(x ? NAM_GEN : VAR_GEN,f); wrstr(s, f); if (x) wrGEN(x, f); } /* read a GEN from file f */ static GEN rdGEN(FILE *f) { size_t L = (size_t)rd_long(f); GENbin *p; if (!L) return gen_0; p = (GENbin*)pari_malloc(sizeof(GENbin) + L*sizeof(long)); p->len = L; p->x = (GEN)rd_long(f); p->base = (GEN)rd_long(f); p->canon= 1; pari_fread_longs(GENbinbase(p), L,f); return bin_copy(p); } /* read a binary object in file f. Set *ptc to the object "type": * BIN_GEN: an anonymous GEN x; return x. * NAM_GEN: a named GEN x, with name v; set 'v to x (changevalue) and return x * VAR_GEN: a name v; create the (unassigned) variable v and return gnil * RELINK_TABLE: a relinking table for gen_relink(), to replace old adresses * in * the original session by new incarnations in the current session. * H is the current relinking table * */ static GEN readobj(FILE *f, int *ptc, hashtable *H) { int c = fgetc(f); GEN x = NULL; switch(c) { case BIN_GEN: x = rdGEN(f); if (H) gen_relink(x, H); break; case NAM_GEN: case VAR_GEN: { char *s = rdstr(f); if (!s) pari_err(e_MISC,"malformed binary file (no name)"); if (c == NAM_GEN) { x = rdGEN(f); if (H) gen_relink(x, H); err_printf("setting %s\n",s); changevalue(fetch_named_var(s), x); } else { pari_var_create(fetch_entry(s, strlen(s))); x = gnil; } break; } case RELINK_TABLE: x = rdGEN(f); break; case EOF: break; default: pari_err(e_MISC,"unknown code in readobj"); } *ptc = c; return x; } #define MAGIC "\020\001\022\011-\007\020" /* ^P^A^R^I-^G^P */ #ifdef LONG_IS_64BIT # define ENDIAN_CHECK 0x0102030405060708L #else # define ENDIAN_CHECK 0x01020304L #endif static const long BINARY_VERSION = 1; /* since 2.2.9 */ static int is_magic_ok(FILE *f) { pari_sp av = avma; size_t L = strlen(MAGIC); char *s = stack_malloc(L); int r = (fread(s,1,L, f) == L && strncmp(s,MAGIC,L) == 0); avma = av; return r; } static int is_sizeoflong_ok(FILE *f) { char c; return (fread(&c,1,1, f) == 1 && c == (char)sizeof(long)); } static int is_long_ok(FILE *f, long L) { long c; return (fread(&c,sizeof(long),1, f) == 1 && c == L); } /* return 1 if valid binary file */ static int check_magic(const char *name, FILE *f) { if (!is_magic_ok(f)) pari_warn(warner, "%s is not a GP binary file",name); else if (!is_sizeoflong_ok(f)) pari_warn(warner, "%s not written for a %ld bit architecture", name, sizeof(long)*8); else if (!is_long_ok(f, ENDIAN_CHECK)) pari_warn(warner, "unexpected endianness in %s",name); else if (!is_long_ok(f, BINARY_VERSION)) pari_warn(warner, "%s written by an incompatible version of GP",name); else return 1; return 0; } static void write_magic(FILE *f) { fprintf(f, MAGIC); fprintf(f, "%c", (char)sizeof(long)); wr_long(ENDIAN_CHECK, f); wr_long(BINARY_VERSION, f); } int file_is_binary(FILE *f) { int c = fgetc(f); ungetc(c,f); return (c != EOF && isprint(c) == 0 && isspace(c) == 0); } void writebin(const char *name, GEN x) { FILE *f = fopen(name,"r"); pari_sp av = avma; GEN V; int already = f? 1: 0; if (f) { int ok = check_magic(name,f); fclose(f); if (!ok) pari_err_FILE("binary output file",name); } f = fopen(name,"a"); if (!f) pari_err_FILE("binary output file",name); if (!already) write_magic(f); V = copybin_unlink(x); if (lg(gel(V,1)) > 1) { fputc(RELINK_TABLE,f); wrGEN(V, f); } if (x) writeGEN(x,f); else { long v, maxv = pari_var_next(); for (v=0; vvalue,ep->name,f); } } avma = av; fclose(f); } /* read all objects in f. If f contains BIN_GEN that would be silently ignored * [i.e f contains more than one objet, not all of them 'named GENs'], return * them all in a vector and set 'vector'. */ GEN readbin(const char *name, FILE *f, int *vector) { pari_sp av = avma; hashtable *H = NULL; pari_stack s_obj; GEN obj, x, y; int cy; if (vector) *vector = 0; if (!check_magic(name,f)) return NULL; pari_stack_init(&s_obj, sizeof(GEN), (void**)&obj); /* HACK: push codeword so as to be able to treat s_obj.data as a t_VEC */ pari_stack_pushp(&s_obj, (void*) (evaltyp(t_VEC)|evallg(1))); x = gnil; while ((y = readobj(f, &cy, H))) { x = y; switch(cy) { case BIN_GEN: pari_stack_pushp(&s_obj, (void*)y); break; case RELINK_TABLE: if (H) hash_destroy(H); H = hash_from_link(gel(y,1),gel(y,2), 0); } } if (H) hash_destroy(H); switch(s_obj.n) /* >= 1 */ { case 1: break; /* nothing but the codeword */ case 2: x = gel(obj,1); break; /* read a single BIN_GEN */ default: /* more than one BIN_GEN */ setlg(obj, s_obj.n); if (DEBUGLEVEL) pari_warn(warner,"%ld unnamed objects read. Returning then in a vector", s_obj.n - 1); x = gerepilecopy(av, obj); if (vector) *vector = 1; } pari_stack_delete(&s_obj); return x; } /*******************************************************************/ /** **/ /** GP I/O **/ /** **/ /*******************************************************************/ /* print a vector of GENs, in output context 'out', using 'sep' as a * separator between sucessive entries [ NULL = no separator ]*/ void out_print0(PariOUT *out, const char *sep, GEN g, long flag) { pari_sp av0 = avma; OUT_FUN f = get_fun(flag); long i, l = lg(g); for (i = 1; i < l; i++) { pari_sp av = avma; GEN x = gel(g,i); char *s = GENtostr_fun_unquoted(x, GP_DATA->fmt, f); out_puts(out, s); avma = av; if (sep && i+1 < l) out_puts(out, sep); } avma = av0; } static void str_print0(outString *S, GEN g, long flag) { OUT_FUN f = get_fun(flag); long i, l = lg(g); for (i = 1; i < l; i++) { GEN x = gel(g,i); if (typ(x)==t_STR) str_puts(S, GSTR(x)); /* text surrounded by "" otherwise */ else { char *s = GENtostr_fun(x, GP_DATA->fmt, f); str_puts(S, s); pari_free(s); } } } /*Display s, followed by the element of g */ char * pari_sprint0(const char *s, GEN g, long flag) { outString S; str_init(&S, 0); str_puts(&S, s); str_print0(&S, g, flag); *S.cur = 0; return S.string; } static void print0_file(FILE *out, GEN g, long flag) { pari_sp av = avma; outString S; str_init(&S, 1); str_print0(&S, g, flag); *S.cur = 0; fputs(S.string, out); avma = av; } void print0(GEN g, long flag) { out_print0(pariOut, NULL, g, flag); } void printsep(const char *s, GEN g, long flag) { (void) flag; out_print0(pariOut, s, g, f_RAW); pari_putc('\n'); pari_flush(); } void printsep1(const char *s, GEN g, long flag) { (void) flag; out_print0(pariOut, s, g, f_RAW); } /* dummy needed to pass a (empty!) va_list to sm_dopr */ static char * dopr_arg_vector(GEN arg_vector, const char* fmt, ...) { va_list ap; char *s; va_start(ap, fmt); s = sm_dopr(fmt, arg_vector, ap); va_end(ap); return s; } /* GP only */ void printf0(const char *fmt, GEN args) { char *s = dopr_arg_vector(args, fmt); pari_puts(s); pari_free(s); pari_flush(); } /* GP only */ GEN Strprintf(const char *fmt, GEN args) { char *s = dopr_arg_vector(args, fmt); GEN z = strtoGENstr(s); pari_free(s); return z; } void out_vprintf(PariOUT *out, const char *fmt, va_list ap) { char *s = sm_dopr(fmt, NULL, ap); out_puts(out, s); pari_free(s); } void pari_vprintf(const char *fmt, va_list ap) { out_vprintf(pariOut, fmt, ap); } /* variadic version of printf0 */ void out_printf(PariOUT *out, const char *fmt, ...) { va_list args; va_start(args,fmt); out_vprintf(out,fmt,args); va_end(args); } void pari_printf(const char *fmt, ...) /* variadic version of printf0 */ { va_list args; va_start(args,fmt); pari_vprintf(fmt,args); va_end(args); } char * pari_vsprintf(const char *fmt, va_list ap) { return sm_dopr(fmt, NULL, ap); } GEN gvsprintf(const char *fmt, va_list ap) { char *s = sm_dopr(fmt, NULL, ap); GEN z = strtoGENstr(s); pari_free(s); return z; } char * pari_sprintf(const char *fmt, ...) /* variadic version of Strprintf */ { char *s; va_list ap; va_start(ap, fmt); s = pari_vsprintf(fmt, ap); va_end(ap); return s; } char * stack_sprintf(const char *fmt, ...) { char *s, *t; va_list ap; va_start(ap, fmt); s = pari_vsprintf(fmt, ap); va_end(ap); t = stack_strdup(s); pari_free(s); return t; } GEN gsprintf(const char *fmt, ...) /* variadic version of gvsprintf */ { GEN s; va_list ap; va_start(ap, fmt); s = gvsprintf(fmt, ap); va_end(ap); return s; } /* variadic version of fprintf0. FIXME: fprintf0 not yet available */ void pari_vfprintf(FILE *file, const char *fmt, va_list ap) { char *s = sm_dopr(fmt, NULL, ap); fputs(s, file); pari_free(s); } void pari_fprintf(FILE *file, const char *fmt, ...) { va_list ap; va_start(ap, fmt); pari_vfprintf(file, fmt, ap); va_end(ap); } void print (GEN g) { print0(g, f_RAW); pari_putc('\n'); pari_flush(); } void printtex(GEN g) { print0(g, f_TEX); pari_putc('\n'); pari_flush(); } void print1 (GEN g) { print0(g, f_RAW); pari_flush(); } void error0(GEN g) { if (lg(g)==2 && typ(gel(g,1))==t_ERROR) pari_err(0, gel(g,1)); else pari_err(e_USER, g); } void warning0(GEN g) { pari_warn(warnuser, g); } static char * wr_check(const char *s) { char *t = path_expand(s); if (GP_DATA->secure) { char *msg = pari_sprintf("[secure mode]: about to write to '%s'",t); pari_ask_confirm(msg); pari_free(msg); } return t; } /* write to file s */ static void wr(const char *s, GEN g, long flag, int addnl) { char *t = wr_check(s); FILE *out = switchout_get_FILE(t); pari_free(t); print0_file(out, g, flag); if (addnl) fputc('\n', out); fflush(out); if (fclose(out)) pari_warn(warnfile, "close", t); } void write0 (const char *s, GEN g) { wr(s, g, f_RAW, 1); } void writetex(const char *s, GEN g) { wr(s, g, f_TEX, 1); } void write1 (const char *s, GEN g) { wr(s, g, f_RAW, 0); } void gpwritebin(const char *s, GEN x) { char *t=wr_check(s); writebin(t, x); pari_free(t);} /*******************************************************************/ /** **/ /** HISTORY HANDLING **/ /** **/ /*******************************************************************/ /* history management function: * 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) { 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 (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); } 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); } 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; } long pari_get_histtime(long p) { return history(GP_DATA->hist, p, NULL,NULL)->t; } void pari_add_hist(GEN x, long time) { gp_hist *H = GP_DATA->hist; ulong i = H->total % H->size; H->total++; if (H->v[i].z) gunclone(H->v[i].z); H->v[i].t = time; H->v[i].z = gclone(x); } ulong pari_nb_hist(void) { return GP_DATA->hist->total; } /*******************************************************************/ /** **/ /** TEMPORARY FILES **/ /** **/ /*******************************************************************/ #ifndef R_OK # define R_OK 4 # define W_OK 2 # define X_OK 1 # define F_OK 0 #endif #ifdef __EMX__ #include static int unix_shell(void) { char *base, *sh = getenv("EMXSHELL"); if (!sh) { sh = getenv("COMSPEC"); if (!sh) return 0; } base = _getname(sh); return (stricmp (base, "cmd.exe") && stricmp (base, "4os2.exe") && stricmp (base, "command.com") && stricmp (base, "4dos.com")); } #endif /* check if s has rwx permissions for us */ static int pari_is_rwx(const char *s) { /* FIXME: HAS_ACCESS */ #if defined(UNIX) || defined (__EMX__) return access(s, R_OK | W_OK | X_OK) == 0; #else (void) s; return 1; #endif } #if defined(UNIX) || defined (__EMX__) #include #include static int pari_file_exists(const char *s) { int id = open(s, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); return id < 0 || close(id); } static int pari_dir_exists(const char *s) { return mkdir(s, 0777); } #elif defined(_WIN32) static int pari_file_exists(const char *s) { return GetFileAttributesA(s) != ~0UL; } static int pari_dir_exists(const char *s) { return mkdir(s); } #else static int pari_file_exists(const char *s) { return 0; } static int pari_dir_exists(const char *s) { return 0; } #endif char * env_ok(const char *s) { char *t = os_getenv(s); if (t && !pari_is_rwx(t)) { pari_warn(warner,"%s is set (%s), but is not writable", s,t); t = NULL; } if (t && !pari_is_dir(t)) { pari_warn(warner,"%s is set (%s), but is not a directory", s,t); t = NULL; } return t; } static const char* pari_tmp_dir(void) { char *s; #ifdef WINCE s = env_ok("TEMP"); if (s) return s; return "\\temp"; #endif s = env_ok("GPTMPDIR"); if (s) return s; s = env_ok("TMPDIR"); if (s) return s; #if defined(_WIN32) || defined(__EMX__) s = env_ok("TMP"); if (s) return s; s = env_ok("TEMP"); if (s) return s; #endif #if defined(UNIX) || defined(__EMX__) if (pari_is_rwx("/tmp")) return "/tmp"; if (pari_is_rwx("/var/tmp")) return "/var/tmp"; #endif return "."; } /* loop through 26^2 variants [suffix 'aa' to 'zz'] */ static int get_file(char *buf, int test(const char *)) { char c, d, *end = buf + strlen(buf) - 1; for (d = 'a'; d <= 'z'; d++) { end[-1] = d; for (c = 'a'; c <= 'z'; c++) { *end = c; if (! test(buf)) return 1; if (DEBUGFILES) err_printf("I/O: file %s exists!\n", buf); } } return 0; } #if defined(__EMX__) || defined(WINCE) || defined(_WIN32) static void swap_slash(char *s) { #ifdef __EMX__ if (!unix_shell()) #endif { char *t; for (t=s; *t; t++) if (*t == '/') *t = '\\'; } } #endif static char * init_unique(const char *s) { const char *pre = pari_tmp_dir(); char *buf, suf[64]; size_t lpre, lsuf; #ifdef UNIX sprintf(suf,"-%ld-%ld", (long)getuid(), (long)getpid()); #else suf[0] = 0; #endif lsuf = strlen(suf); lpre = strlen(pre); /* room for prefix + '/' + s + suffix '\0' */ buf = (char*) pari_malloc(lpre + 1 + 8 + lsuf + 1); strcpy(buf, pre); if (buf[lpre-1] != '/') { (void)strcat(buf, "/"); lpre++; } #if defined(__EMX__) || defined(WINCE) || defined(_WIN32) swap_slash(buf); #endif sprintf(buf + lpre, "%.8s%s", s, suf); if (DEBUGFILES) err_printf("I/O: prefix for unique file/dir = %s\n", buf); return buf; } /* Return a "unique filename" built from the string s, possibly the user id * and the process pid (on Unix systems). A "temporary" directory name is * prepended. The name returned is pari_malloc'ed. It is DOS-safe * (s truncated to 8 chars) */ char* pari_unique_filename(const char *s) { char *buf = init_unique(s); if (pari_file_exists(buf) && !get_file(buf, pari_file_exists)) pari_err(e_MISC,"couldn't find a suitable name for a tempfile (%s)",s); return buf; } /* Create a "unique directory" and return its name built from the string * s, the user id and process pid (on Unix systems). A "temporary" * directory name is prepended. The name returned is pari_malloc'ed. * It is DOS-safe (truncated to 8 chars) */ char* pari_unique_dir(const char *s) { char *buf = init_unique(s); if (pari_dir_exists(buf) && !get_file(buf, pari_dir_exists)) pari_err(e_MISC,"couldn't find a suitable name for a tempdir (%s)",s); return buf; } /*******************************************************************/ /** **/ /** INSTALL **/ /** **/ /*******************************************************************/ #ifdef HAS_DLOPEN #include /* see try_name() */ static void * try_dlopen(const char *s, int flag) { void *h = dlopen(s, flag); pari_free((void*)s); return h; } /* like dlopen, but using default(sopath) */ static void * gp_dlopen(const char *name, int flag) { void *handle; char *s; if (!name) return dlopen(NULL, flag); s = path_expand(name); /* if sopath empty or path is absolute, use dlopen */ if (!GP_DATA || *(GP_DATA->sopath->PATH)==0 || path_is_absolute(s)) return try_dlopen(s, flag); else { forpath_t T; char *t; forpath_init(&T, GP_DATA->sopath, s); while ( (t = forpath_next(&T)) ) { if ( (handle = try_dlopen(t,flag)) ) return handle; (void)dlerror(); /* clear error message */ } } return NULL; } static void * install0(const char *name, const char *lib) { void *handle; #ifndef RTLD_GLOBAL /* OSF1 has dlopen but not RTLD_GLOBAL*/ # define RTLD_GLOBAL 0 #endif handle = gp_dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); if (!handle) { const char *s = dlerror(); if (s) err_printf("%s\n\n",s); if (lib) pari_err(e_MISC,"couldn't open dynamic library '%s'",lib); pari_err(e_MISC,"couldn't open dynamic symbol table of process"); } return dlsym(handle, name); } #else # ifdef _WIN32 static HMODULE try_LoadLibrary(const char *s) { void *h = LoadLibrary(s); pari_free((void*)s); return h; } /* like LoadLibrary, but using default(sopath) */ static HMODULE gp_LoadLibrary(const char *name) { HMODULE handle; char *s = path_expand(name); /* if sopath empty or path is absolute, use LoadLibrary */ if (!GP_DATA || *(GP_DATA->sopath->PATH)==0 || path_is_absolute(s)) return try_LoadLibrary(s); else { forpath_t T; char *t; forpath_init(&T, GP_DATA->sopath, s); while ( (t = forpath_next(&T)) ) if ( (handle = try_LoadLibrary(t)) ) return handle; } return NULL; } static void * install0(const char *name, const char *lib) { HMODULE handle; #ifdef WINCE short wlib[256], wname[256]; MultiByteToWideChar(CP_ACP, 0, lib, strlen(lib)+1, wlib, 256); MultiByteToWideChar(CP_ACP, 0, name, strlen(name)+1, wname, 256); lib = wlib; name = wname; #endif handle = gp_LoadLibrary(lib); if (!handle) { if (lib) pari_err(e_MISC,"couldn't open dynamic library '%s'",lib); pari_err(e_MISC,"couldn't open dynamic symbol table of process"); } return (void *) GetProcAddress(handle,name); } # else static void * install0(const char *name, const char *lib) { pari_err(e_ARCH,"install"); return NULL; } #endif #endif static char * dft_help(const char *gp, const char *s, const char *code) { return stack_sprintf("%s: installed function\nlibrary name: %s\nprototype: %s" , gp, s, code); } void gpinstall(const char *s, const char *code, const char *gpname, const char *lib) { pari_sp av = avma; const char *gp = *gpname? gpname: s; void *f; entree *ep; if (GP_DATA->secure) { char *msg = pari_sprintf("[secure mode]: about to install '%s'", s); pari_ask_confirm(msg); pari_free(msg); } ep = is_entry(gp); if (ep && ep->valence == EpINSTALL && strcmp(ep->code, code) && !strcmp(ep->help, dft_help(gp,s,ep->code))) { /* help is the default AND prototype changes: delete help */ pari_free((void*)ep->help); ep->help = NULL; } f = install0(s, *lib ?lib :pari_library_path); if (!f) { if (*lib) pari_err(e_MISC,"can't find symbol '%s' in library '%s'",s,lib); pari_err(e_MISC,"can't find symbol '%s' in dynamic symbol table of process",s); } ep = install(f,gp,code); if (ep && !ep->help) addhelp(gp, dft_help(gp,s,code)); mt_broadcast(strtoclosure("install",4,strtoGENstr(s),strtoGENstr(code), strtoGENstr(gp),strtoGENstr(lib))); avma = av; } pari-2.7.5/src/language/intnum.c0000644000175000017500000014724312405547147015162 0ustar billbill/* 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" /********************************************************************/ /** **/ /** NUMERICAL INTEGRATION (Romberg) **/ /** **/ /********************************************************************/ typedef struct { void *E; GEN (*f)(void *E, GEN); } invfun; /* 1/x^2 f(1/x) */ static GEN _invf(void *E, GEN x) { invfun *S = (invfun*)E; GEN y = ginv(x); return gmul(S->f(S->E, y), gsqr(y)); } static GEN interp(GEN h, GEN s, long j, long lim, long KLOC) { pari_sp av = avma; long e1,e2; GEN dss, ss = polint_i(h+j-KLOC,s+j-KLOC,gen_0,KLOC+1,&dss); e1 = gexpo(ss); e2 = gexpo(dss); if (e1-e2 <= lim && (j <= 10 || e1 >= -lim)) { avma = av; return NULL; } if (typ(ss) == t_COMPLEX && gequal0(gel(ss,2))) ss = gel(ss,1); return ss; } static GEN qrom3(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec) { const long JMAX = 25, KLOC = 4; GEN ss,s,h,p1,p2,qlint,del,x,sum; long j, j1, it, sig; a = gtofp(a,prec); b = gtofp(b,prec); qlint = subrr(b,a); sig = signe(qlint); if (!sig) return gen_0; if (sig < 0) { setabssign(qlint); swap(a,b); } s = new_chunk(JMAX+KLOC-1); h = new_chunk(JMAX+KLOC-1); gel(h,0) = real_1(prec); p1 = eval(E, a); if (p1 == a) p1 = rcopy(p1); p2 = eval(E, b); gel(s,0) = gmul2n(gmul(qlint,gadd(p1,p2)),-1); for (it=1,j=1; j3) err_printf("qrom3: iteration %ld: %Ps\n", j,s[j]); if (j >= KLOC && (ss = interp(h, s, j, prec2nbits(prec)-j-6, KLOC))) return gmulsg(sig,ss); } return NULL; } static GEN qrom2(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec) { const long JMAX = 16, KLOC = 4; GEN ss,s,h,p1,qlint,del,ddel,x,sum; long j, j1, it, sig; a = gtofp(a, prec); b = gtofp(b, prec); qlint = subrr(b,a); sig = signe(qlint); if (!sig) return gen_0; if (sig < 0) { setabssign(qlint); swap(a,b); } s = new_chunk(JMAX+KLOC-1); h = new_chunk(JMAX+KLOC-1); gel(h,0) = real_1(prec); p1 = shiftr(addrr(a,b),-1); gel(s,0) = gmul(qlint, eval(E, p1)); for (it=1, j=1; j3) err_printf("qrom2: iteration %ld: %Ps\n", j,s[j]); if (j >= KLOC && (ss = interp(h, s, j, prec2nbits(prec)-(3*j/2)-6, KLOC))) return gmulsg(sig, ss); } return NULL; } /* integrate after change of variables x --> 1/x */ static GEN qromi(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long prec) { GEN A = ginv(b), B = ginv(a); invfun S; S.f = eval; S.E = E; return qrom2(&S, &_invf, A, B, prec); } /* a < b, assume b "small" (< 100 say) */ 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); } static GEN rombint(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long prec) { long l = gcmp(b,a); GEN z; if (!l) return gen_0; if (l < 0) swap(a,b); if (gcmpgs(b,100) >= 0) { if (gcmpgs(a,1) >= 0) z = qromi(E,eval,a,b,prec); else /* split at 1 */ z = gadd(rom_bsmall(E,eval,a,gen_1,prec), qromi(E,eval,gen_1,b,prec)); } else z = rom_bsmall(E,eval,a,b,prec); if (l < 0) z = gneg(z); return z; } /********************************************************************/ /** **/ /** DOUBLE EXPONENTIAL INTEGRATION **/ /** **/ /********************************************************************/ /* The init functions have the following purposes: * 1) They fill the value tabx0 = phi(0) and arrays of abcissas * tabxp[] = phi(k/2^m) (positive x) and also of tabxm[] = phi(-k/2^m) * (negative x) unless the phi function is odd, in which case this is useless. * 2) They fill the corresponding arrays of weights tabw0 = phi'(0) and * tabwp[] = phi'(k/2^m) (and possibly also of tabwm[] = phi'(-k/2^m)). * 3) They set eps to the desired accuracy (depending on the GP default). * 4) They compute nt which says that the weights tabwp[k] and tabwm[k] are * negligible with respect to eps if k > nt. In particular the tabxx[] arrays * are indexed from 1 to nt+1. */ typedef struct _intdata { long m; /* integration step h = 1/2^m */ long eps; /* bit accuracy of current precision */ GEN tabx0; /* abcissa phi(0) for t = 0 */ GEN tabw0; /* weight phi'(0) for t = 0 */ GEN tabxp; /* table of abcissas phi(kh) for k > 0 */ GEN tabwp; /* table of weights phi'(kh) for k > 0 */ GEN tabxm; /* table of abcissas phi(kh) for k < 0 */ GEN tabwm; /* table of weights phi'(kh) for k < 0 */ } intdata; #define TABm(v) gel(v,1) #define TABx0(v) gel(v,2) #define TABw0(v) gel(v,3) #define TABxp(v) gel(v,4) #define TABwp(v) gel(v,5) #define TABxm(v) gel(v,6) #define TABwm(v) gel(v,7) static int isinR(GEN z) { long tz = typ(z); return (tz == t_INT || tz == t_REAL || tz == t_FRAC); } static int isinC(GEN z) { return (typ(z) == t_COMPLEX)? isinR(gel(z,1)) && isinR(gel(z,2)): isinR(z); } static int checktabsimp(GEN tab) { long L, LN, LW; if (!tab || typ(tab) != t_VEC) return 0; if (lg(tab) != 8) return 0; if (typ(TABm(tab))!= t_INT) return 0; if (typ(TABxp(tab)) != t_VEC) return 0; if (typ(TABwp(tab)) != t_VEC) return 0; if (typ(TABxm(tab)) != t_VEC) return 0; if (typ(TABwm(tab)) != t_VEC) return 0; L = lg(TABxp(tab)); if (lg(TABwp(tab)) != L) return 0; LN = lg(TABxm(tab)); if (LN != 1 && LN != L) return 0; LW = lg(TABwm(tab)); if (LW != 1 && LW != L) return 0; return 1; } static int checktabdoub(GEN tab) { long L; if (typ(tab) != t_VEC) return 0; if (lg(tab) != 8) return 0; if (typ(TABm(tab)) != t_INT) return 0; L = lg(TABxp(tab)); if (lg(TABwp(tab)) != L) return 0; if (lg(TABxm(tab)) != L) return 0; if (lg(TABwm(tab)) != L) return 0; return 1; } static int checktab(GEN tab) { if (typ(tab) != t_VEC) return 0; if (lg(tab) != 3) return checktabsimp(tab); return checktabsimp(gel(tab,1)) && checktabsimp(gel(tab,2)); } static long findmforinit(long m, 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; } } return m; } long intnumstep(long prec) { return findmforinit(0, prec); } static void intinit_start(intdata *D, long m0, long flext, long prec) { long m = findmforinit(m0, prec), lim = 20L< 0) lim = lim << (2*flext); D->m = m; D->eps = prec2nbits(prec); D->tabxp = cgetg(lim+1, t_VEC); D->tabwp = cgetg(lim+1, t_VEC); D->tabxm = cgetg(lim+1, t_VEC); D->tabwm = cgetg(lim+1, t_VEC); } static GEN intinit_end(intdata *D, long pnt, long mnt) { GEN v = cgetg(8, t_VEC); if (pnt < 0) pari_err_DOMAIN("intnuminit","table length","<",gen_0,stoi(pnt)); gel(v,1) = stoi(D->m); TABx0(v) = D->tabx0; TABw0(v) = D->tabw0; TABxp(v) = D->tabxp; setlg(D->tabxp, pnt+1); TABwp(v) = D->tabwp; setlg(D->tabwp, pnt+1); TABxm(v) = D->tabxm; setlg(D->tabxm, mnt+1); TABwm(v) = D->tabwm; setlg(D->tabwm, mnt+1); return v; } static const long EXTRAPREC = #ifdef LONG_IS_64BIT 1; #else 2; #endif /* divide by 2 in place */ static GEN divr2_ip(GEN x) { shiftr_inplace(x, -1); return x; } /* phi(t)=tanh((3/2)sinh(t)) : from -1 to 1, hence also from a to b compact * interval. */ static GEN inittanhsinh(long m, long prec) { pari_sp av, ltop = avma; GEN h, et, ct, st, ext, ex, xp, wp; long k, nt = -1, lim; intdata D; intinit_start(&D, m, 0, prec); lim = lg(D.tabxp) - 1; D.tabx0 = real_0(prec); D.tabw0 = divr2_ip(stor(3, prec)); h = real2n(-D.m, prec); et = ex = mpexp(h); for (k = 1; k <= lim; k++) { gel(D.tabxp,k) = cgetr(prec+EXTRAPREC); gel(D.tabwp,k) = cgetr(prec+EXTRAPREC); av = avma; ct = divr2_ip(addrr(et, invr(et))); st = subrr(et, ct); ext = invr( addrs(mpexp(mulur(3, st)), 1) ); shiftr_inplace(ext, 1); xp = subsr(1, ext); wp = divr2_ip(mulur(3, mulrr(ct, mulrr(ext, addsr(1, xp))))); if (expo(wp) < -D.eps) { nt = k-1; break; } 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)); } /* phi(t)=sinh(sinh(t)) : from -\infty to \infty, slowly decreasing, at least * as 1/x^2. */ static GEN initsinhsinh(long m, long prec) { pari_sp av, ltop = avma; GEN h, et, ct, st, ext, exu, ex, xp, wp; long k, nt = -1, lim; intdata D; intinit_start(&D, m, 0, prec); lim = lg(D.tabxp) - 1; D.tabx0 = real_0(prec); D.tabw0 = real_1(prec); h = real2n(-D.m, prec); et = ex = mpexp(h); for (k = 1; k <= lim; k++) { gel(D.tabxp,k) = cgetr(prec+EXTRAPREC); gel(D.tabwp,k) = cgetr(prec+EXTRAPREC); av = avma; ct = divr2_ip(addrr(et, invr(et))); st = subrr(et, ct); ext = mpexp(st); exu = invr(ext); xp = divr2_ip(subrr(ext, exu)); wp = divr2_ip(mulrr(ct, addrr(ext, exu))); if (expo(wp) - 2*expo(xp) < -D.eps) { nt = k-1; break; } 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)); } /* phi(t)=2sinh(t) : from -\infty to \infty, exponentially decreasing as * exp(-x). */ static GEN initsinh(long m, long prec) { pari_sp av, ltop = avma; GEN h, et, ex, eti, xp, wp; long k, nt = -1, lim; intdata D; intinit_start(&D, m, 0, prec); lim = lg(D.tabxp) - 1; D.tabx0 = real_0(prec); D.tabw0 = real2n(1, prec); h = real2n(-D.m, prec); et = ex = mpexp(h); for (k = 1; k <= lim; k++) { gel(D.tabxp,k) = cgetr(prec+EXTRAPREC); gel(D.tabwp,k) = cgetr(prec+EXTRAPREC); av = avma; eti = invr(et); xp = subrr(et, eti); wp = addrr(et, eti); if (cmprs(xp, (long)(LOG2*(expo(wp)+D.eps) + 1)) > 0) { nt = k-1; break; } 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)); } /* phi(t)=exp(2sinh(t)) : from 0 to \infty, slowly decreasing at least as * 1/x^2. */ 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); lim = lg(D.tabxp) - 1; D.tabx0 = real_1(prec); D.tabw0 = real2n(1, prec); h = real2n(-D.m, prec); ex = mpexp(h); et = real_1(prec); for (k = 1; k <= lim; k++) { GEN t; et = mulrr(et, ex); eti = invr(et); t = addrr(et, eti); xp = mpexp(subrr(et, eti)); gel(D.tabxp,k) = xp; gel(D.tabwp,k) = mulrr(xp, t); gel(D.tabxm,k) = invr(xp); 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)); } /* phi(t)=exp(t-exp(-t)) : from 0 to \infty, exponentially decreasing. */ static GEN initexpexp(long m, long prec) { pari_sp av, ltop = avma; GEN kh, h, et, eti, ex, xp, xm, wp, wm; long k, nt = -1, lim; intdata D; intinit_start(&D, m, 0, prec); lim = lg(D.tabxp) - 1; D.tabx0 = mpexp(real_m1(prec)); D.tabw0 = gmul2n(D.tabx0, 1); h = real2n(-D.m, prec); et = ex = mpexp(negr(h)); for (k = 1; k <= lim; k++) { gel(D.tabxp,k) = cgetr(prec+EXTRAPREC); gel(D.tabwp,k) = cgetr(prec+EXTRAPREC); gel(D.tabxm,k) = cgetr(prec+EXTRAPREC); gel(D.tabwm,k) = cgetr(prec+EXTRAPREC); av = avma; eti = invr(et); kh = mulur(k,h); xp = mpexp(subrr(kh, et)); xm = mpexp(negr(addrr(kh, eti))); wp = mulrr(xp, addsr(1, et)); wm = mulrr(xm, addsr(1, eti)); if (expo(xm) < -D.eps && cmprs(xp, (long)(LOG2*(expo(wp)+D.eps) + 1)) > 0) { nt = k-1; break; } affrr(xp, gel(D.tabxp,k)); affrr(wp, gel(D.tabwp,k)); 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)); } /* 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; 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; intdata D; intinit_start(&D, m, 0, prec); lim = lg(D.tabxp) - 1; D.tabx0 = gmul2n(pi, D.m); D.tabw0 = gmul2n(pi, D.m - 1); h = real2n(-D.m, prec); et = ex = mpexp(h); for (k = 1; k <= lim; k++) { gel(D.tabxp,k) = cgetr(prec+EXTRAPREC); gel(D.tabwp,k) = cgetr(prec+EXTRAPREC); gel(D.tabxm,k) = cgetr(prec+EXTRAPREC); gel(D.tabwm,k) = cgetr(prec+EXTRAPREC); av = avma; eti = invr(et); /* exp(-kh) */ ct = divr2_ip(addrr(et, eti)); st = divr2_ip(subrr(et, eti)); extp = mpexp(st); extp1 = subsr(1, extp); extp2 = invr(extp1); extm = invr(extp); extm1 = subsr(1, extm); extm2 = invr(extm1); kpi = mulur(k, pi); kct = mulur(k, ct); shiftr_inplace(extm1, D.m); shiftr_inplace(extp1, D.m); xp = mulrr(kpi, extm2); wp = mulrr(subrr(extm1, mulrr(kct, extm)), mulrr(pi, sqrr(extm2))); xm = mulrr(negr(kpi), extp2); wm = mulrr(addrr(extp1, mulrr(kct, extp)), mulrr(pi, sqrr(extp2))); if (expo(wm) < -D.eps && expo(extm) + D.m + expu(10 * k) < -D.eps) { nt = k-1; break; } affrr(xp, gel(D.tabxp,k)); affrr(wp, gel(D.tabwp,k)); 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)); } static GEN suminit_start(GEN sig) { GEN sig2; if (typ(sig) == t_VEC) { if (lg(sig) != 3) pari_err_TYPE("sumnum",sig); sig2 = gel(sig,2); sig = gel(sig,1); if (!isinR(sig2)) pari_err_TYPE("sumnum",sig2); if (gsigne(sig2) > 0) sig2 = mulcxmI(sig2); } else sig2 = gen_0; if (!isinR(sig)) pari_err_TYPE("sumnum",sig); return mkvec2(mkvec(gen_1), sig2); } /* phi(t) depending on sig[2] as in intnum, with weights phi'(t)tanh(Pi*phi(t)) * (sgn >= 0) or phi'(t)/cosh(Pi*phi(t)) (otherwise), for use in sumnumall. * integrations are done from 0 to +infty (flii is set to 0), except if slowly decreasing, from -infty to +infty (flii is set to 1). */ GEN sumnuminit(GEN sig, long m, long sgn, long prec) { pari_sp ltop = avma; GEN b, t, tab, tabxp, tabwp, tabxm, tabwm, pi = mppi(prec); long L, k, eps, flii; b = suminit_start(sig); flii = gequal0(gel(b,2)); if (flii) tab = intnuminit(mkvec(gen_m1), mkvec(gen_1), m, prec); else tab = intnuminit(gen_0, b, m, prec); eps = prec2nbits(prec); t = gmul(pi, TABx0(tab)); if (sgn < 0) TABw0(tab) = gdiv(TABw0(tab), gcosh(t, prec)); else TABw0(tab) = gmul(TABw0(tab), gtanh(t, prec)); tabxp = TABxp(tab); L = lg(tabxp); tabwp = TABwp(tab); tabxm = TABxm(tab); tabwm = TABwm(tab); for (k = 1; k < L; k++) { if (cmprs(gel(tabxp,k), eps) < 0) { t = mulrr(pi, gel(tabxp,k)); gel(tabwp,k) = (sgn < 0)? divrr(gel(tabwp,k), gcosh(t, prec)) : mulrr(gel(tabwp,k), gtanh(t, prec)); } else if (sgn < 0) gel(tabwp,k) = real_0_bit(-eps); if (!flii) { t = mulrr(pi, gel(tabxm,k)); gel(tabwm,k) = (sgn < 0)? divrr(gel(tabwm,k), gcosh(t, prec)) : mulrr(gel(tabwm,k), gtanh(t, prec)); } } return gerepilecopy(ltop, tab); } /* End of initialization functions. These functions can be executed once * and for all for a given accuracy, type of integral ([a,b], [a,\infty[ or * ]-\infty,a], ]-\infty,\infty[) and of integrand in the noncompact case * (slowly decreasing, exponentially decreasing, oscillating with a fixed * oscillating factor such as sin(x)). */ /* In the following integration functions the parameters are as follows: * 1) The parameter denoted by m is the most crucial and difficult to * determine in advance: h = 1/2^m is the integration step size. Usually * m = floor(log(D)/log(2)), where D is the number of decimal digits of accuracy * is plenty for very regulat functions, for instance m = 6 for 100D, and m = 9 * for 1000D, but values of m 1 or 2 less are often sufficient, while for * singular functions, 1 or 2 more may be necessary. The best test is to take 2 * or 3 consecutive values of m and look. Note that the number of function * evaluations, hence the time doubles when m increases by 1. */ /* All inner functions such as intn, etc... must be called with a * valid 'tab' table. The wrapper intnum provides a higher level interface */ /* compute $\int_a^b f(t)dt$ with [a,b] compact and f nonsingular. */ static GEN intn(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab) { GEN tabx0, tabw0, tabxp, tabwp; GEN bpa, bma, bmb, S, SP, SM; long m, k, L, i; pari_sp ltop = avma, av; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); if (!isinC(a)) pari_err_TYPE("intnum",a); if (!isinC(b)) pari_err_TYPE("intnum",b); m = itos(TABm(tab)); tabx0 = TABx0(tab); tabw0 = TABw0(tab); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); bpa = gmul2n(gadd(b, a), -1); /* (b+a)/2 */ bma = gsub(bpa, a); /* (b-a)/2 */ bmb = gmul(bma, tabx0); /* (b-a)/2 phi(0) */ av = avma; /* phi'(0) f( (b+a)/2 + (b-a)/2 * phi(0) ) */ S = gmul(tabw0, eval(E, gadd(bpa, bmb))); for (k = 1; k <= m; k++) { long pas = 1L<<(m-k); for (i = pas; i < L; i += pas) if (i & pas || k == 1) { bmb = gmul(bma, gel(tabxp,i)); SP = eval(E, gsub(bpa, bmb)); SM = eval(E, gadd(bpa, bmb)); S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM))); if ((i & 0x7f) == 1) S = gerepileupto(av, S); } } return gerepileupto(ltop, gmul(S, gmul2n(bma, -m))); } /* compute $\int_{a[1]}^{b} f(t)dt$ with [a,b] compact, possible * singularity with exponent a[2] at lower extremity, b regular. * Use tanh(sinh(t)). */ static GEN intnsing(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec) { GEN tabx0, tabw0, tabxp, tabwp, ea, ba, bm, bp, S, tra, SP, SM; long m, k, L, i; pari_sp ltop = avma, av; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); m = itos(TABm(tab)); tabx0 = TABx0(tab); tabw0 = TABw0(tab); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); tra = gel(a,1); ea = ginv(gaddsg(1, gel(a,2))); ba = gdiv(gsub(b, tra), gpow(gen_2, ea, prec)); av = avma; S = gmul(gmul(tabw0, ba), eval(E, gadd(gmul(ba, gaddsg(1, tabx0)), tra))); for (k = 1; k <= m; k++) { long pas = 1L<<(m-k); for (i = pas; i < L; i += pas) if (i & pas || k == 1) /* i = odd multiple of pas = 2^(m-k) */ { GEN p = addsr(1, gel(tabxp,i)); GEN m = subsr(1, gel(tabxp,i)); bp = gmul(ba, gpow(p, ea, prec)); bm = gmul(ba, gpow(m, ea, prec)); SP = gmul(gdiv(bp, p), eval(E, gadd(bp, tra))); SM = gmul(gdiv(bm, m), eval(E, gadd(bm, tra))); S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM))); if ((i & 0x7f) == 1) S = gerepileupto(av, S); } } return gerepileupto(ltop, gmul(gmul2n(S, -m), ea)); } /* compute $\int_a^\infty f(t)dt$ if $si=1$ or $\int_{-\infty}^a f(t)dt$ if $si=-1$. Use exp(2sinh(t)) for slowly decreasing functions, exp(1+t-exp(-t)) for exponentially decreasing functions, and (pi/h)t/(1-exp(-sinh(t))) for oscillating functions. */ static GEN intninfpm(void *E, GEN (*eval)(void*, GEN), GEN a, long si, GEN tab) { GEN tabx0, tabw0, tabxp, tabwp, tabxm, tabwm; GEN S, SP, SM; long m, L, k, h = 0, pas, i; pari_sp ltop = avma, av; if (!checktabdoub(tab)) pari_err_TYPE("intnum",tab); m = itos(TABm(tab)); tabx0 = TABx0(tab); tabw0 = TABw0(tab); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); tabxm = TABxm(tab); tabwm = TABwm(tab); if (si < 0) { tabxp = gneg(tabxp); tabxm = gneg(tabxm); } av = avma; S = gmul(tabw0, eval(E, gadd(a, gmulsg(si, tabx0)))); for (k = 1; k <= m; k++) { h++; pas = 1L<<(m-k); for (i = pas; i < L; i += pas) if (i & pas || k == 1) { SP = eval(E, gadd(a, gel(tabxp,i))); SM = eval(E, gadd(a, gel(tabxm,i))); S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM))); if ((i & 0x7f) == 1) S = gerepileupto(av, S); } } return gerepileupto(ltop, gmul2n(S, -h)); } /* compute $\int_{-\infty}^\infty f(t)dt$ * use sinh(sinh(t)) for slowly decreasing functions and sinh(t) for * exponentially decreasing functions. * HACK: in case TABwm(tab) contains something, assume function to be integrated * satisfies f(-x) = conj(f(x)). * Usually flag < 0, but flag > 0 is used in sumnumall. */ static GEN intninfinfintern(void *E, GEN (*eval)(void*, GEN), GEN tab, long flag) { GEN tabx0, tabw0, tabxp, tabwp, tabwm; GEN S, SP, SM; long m, L, k, i, spf; pari_sp ltop = avma; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); m = itos(TABm(tab)); tabx0 = TABx0(tab); tabw0 = TABw0(tab); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); tabwm = TABwm(tab); spf = (lg(tabwm) == lg(tabwp)); S = flag > 0 ? gen_0 : gmul(tabw0, eval(E, tabx0)); if (spf) S = gmul2n(real_i(S), -1); for (k = 1; k <= m; k++) { long pas = 1L<<(m-k); for (i = pas; i < L; i += pas) if (i & pas || k == 1) { SP = eval(E, gel(tabxp,i)); if (spf) S = gadd(S, real_i(gmul(gel(tabwp,i), SP))); else { SM = eval(E, negr(gel(tabxp,i))); if (flag > 0) SM = gneg(SM); S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM))); } if ((i & 0x7f) == 1) S = gerepileupto(ltop, S); } } if (spf) m--; return gerepileupto(ltop, gmul2n(S, -m)); } static GEN intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab) { return intninfinfintern(E, eval, tab, -1); } /* 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 exp(-a|t|) at +-\infty. (5) [[+-1], 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 and like sin(at) if a < 0 at +-\infty. */ /* FIXME: The numbers below can be changed, but NOT the ordering */ 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_YFAST = 4, /* +\infty, exponentially decreasing */ f_YOSCS = 5, /* +\infty, sine oscillating */ f_YOSCC = 6 /* +\infty, cosine oscillating */ }; /* is c finite */ static int is_fin_f(long c) { return c == f_REG || c == f_SING; } /* oscillating case: valid for +oo (c > 0) or -oo (c < 0) */ static int is_osc_f(long c) { c = labs(c); return c == f_YOSCS || c == f_YOSCC; } static GEN f_getycplx(GEN a, long prec) { long s; GEN tmp, a2R, a2I; if (lg(a) == 2 || gequal0(gel(a,2))) return gen_1; a2R = real_i(gel(a,2)); a2I = imag_i(gel(a,2)); s = gsigne(a2I); if (s < 0) a2I = gneg(a2I); tmp = s ? ginv(a2I) : ginv(a2R); if (gprecision(tmp) < prec) tmp = gprec_w(tmp, prec); return tmp; } static void err_code(GEN a, const char *name) { char *s = stack_sprintf("intnum [incorrect %s]", name); pari_err_TYPE(s, a); } /* a = [[+/-1], alpha]*/ static long code_aux(GEN a, const char *name) { GEN re, im, alpha = gel(a,2); long s; if (!isinC(alpha)) err_code(a, name); re = real_i(alpha); im = imag_i(alpha); s = gsigne(im); if (s) { if(!gequal0(re)) pari_warn(warner,"real(z)*imag(z)!=0 in endpoint code, real(z) ignored"); return s > 0 ? f_YOSCC : f_YOSCS; } if (gequal0(re) || gcmpgs(re, -2)<=0) return f_YSLOW; if (gsigne(re) > 0) return f_YFAST; if (gcmpgs(re, -1) >= 0) err_code(a, name); return f_YVSLO; } static long transcode(GEN a, const char *name) { GEN a1, a2; if (typ(a) != t_VEC) 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; default: err_code(a,name); } a1 = gel(a,1); a2 = gel(a,2); if (typ(a1) != t_VEC) { 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 */ static GEN homtab(GEN tab, GEN k) { GEN z; if (gequal0(k) || gequal(k, gen_1)) return tab; if (gsigne(k) < 0) k = gneg(k); z = cgetg(8, t_VEC); TABm(z) = icopy(TABm(tab)); TABx0(z) = gmul(TABx0(tab), k); TABw0(z) = gmul(TABw0(tab), k); TABxp(z) = gmul(TABxp(tab), k); TABwp(z) = gmul(TABwp(tab), k); TABxm(z) = gmul(TABxm(tab), k); TABwm(z) = gmul(TABwm(tab), k); return z; } static GEN expvec(GEN v, GEN ea, long prec) { long lv = lg(v), i; GEN z = cgetg(lv, t_VEC); for (i = 1; i < lv; i++) gel(z,i) = gpow(gel(v,i),ea,prec); return z; } static GEN expscalpr(GEN vnew, GEN xold, GEN wold, GEN ea) { pari_sp av = avma; return gerepileupto(av, gdiv(gmul(gmul(vnew, wold), ea), xold)); } static GEN expvecpr(GEN vnew, GEN xold, GEN wold, GEN ea) { long lv = lg(vnew), i; GEN z = cgetg(lv, t_VEC); for (i = 1; i < lv; i++) gel(z,i) = expscalpr(gel(vnew,i), gel(xold,i), gel(wold,i), ea); return z; } /* here k < -1 */ static GEN exptab(GEN tab, GEN k, long prec) { GEN v, ea; if (gcmpgs(k, -2) <= 0) return tab; ea = ginv(gsubsg(-1, k)); v = cgetg(8, t_VEC); TABm(v) = icopy(TABm(tab)); TABx0(v) = gpow(TABx0(tab), ea, prec); TABw0(v) = expscalpr(TABx0(v), TABx0(tab), TABw0(tab), ea); TABxp(v) = expvec(TABxp(tab), ea, prec); TABwp(v) = expvecpr(TABxp(v), TABxp(tab), TABwp(tab), ea); TABxm(v) = expvec(TABxm(tab), ea, prec); TABwm(v) = expvecpr(TABxm(v), TABxm(tab), TABwm(tab), ea); return v; } GEN intnuminit(GEN a, GEN b, long m, long prec) { long codea, codeb, l; GEN T, U, km, 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); 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; } } 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; } return T; } if (codea * codeb > 0) return gen_0; kma = f_getycplx(a, l); kmb = f_getycplx(b, l); codea = labs(codea); 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); 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_YVSLO: tmp = initexpsinh(m, l); gel(T,1) = 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_YOSCS: case f_YOSCC: gel(T,2) = homtab(initnumsine(m, l), kmb); return T; } case f_YFAST: tmp = initexpexp(m, l); gel(T,1) = homtab(tmp, kma); switch (codeb) { case f_YFAST: gel(T,2) = homtab(tmp, kmb); return T; 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); 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); return T; } return gen_0; /* not reached */ } GEN intnuminit0(GEN a, GEN b, GEN tab, long prec) { long m; if (!tab) m = 0; else if (typ(tab) != t_INT) { if (!checktab(tab)) pari_err_TYPE("intnuminit0",tab); return tab; } else m = itos(tab); return intnuminit(a, b, m, prec); } GEN sumnuminit0(GEN a, GEN tab, long sgn, long prec) { long m; if (!tab) m = 0; else if (typ(tab) != t_INT) { if (!checktab(tab)) pari_err_TYPE("sumnuminit0",tab); return tab; } else m = itos(tab); return sumnuminit(a, m, sgn, prec); } /* User-defined change of variable phi(t) = f(t), where t goes from -oo to +oo, * and a and b are as in intnuminit. If [a,b] compact, assume phi(t) odd. */ static int condfin(long code, GEN xw, long eps, long m, long k) { GEN x, w; eps -= 8; /* for safety. Lose 8 bits, but took 1 whole word extra. */ x = gel(xw,1); w = gel(xw,2); switch(labs(code)) { case f_REG: case f_SING: return gexpo(w) < -eps; case f_YSLOW: case f_YVSLO: return gexpo(w) - 2*gexpo(x) < -eps; case f_YFAST: return cmprs(x, (long)(LOG2 * (gexpo(w) + eps) + 1)) > 0; case f_YOSCS: case f_YOSCC: return gexpo(x) + m + expu(10 * k) < - eps; default: return 0; } } /* eps = 2^(-k). Return f'(a) ~ (f(a+eps) - f(a-eps)) / 2eps*/ static GEN myderiv_num(void *E, GEN (*eval)(void*, GEN), GEN a, GEN eps, long k, long prec) { GEN d = gmul2n(gsub(eval(E, gadd(a,eps)), eval(E, gsub(a,eps))), k-1); return gprec_w(d, prec); } /* zp = z to a higher accuracy (enough to evaluate numerical derivative) */ static GEN ffprime(void *E, GEN (*eval)(void*, GEN), GEN z, GEN zp, GEN eps, long h, long precl) { GEN f = eval(E, z), fp = myderiv_num(E, eval, zp, eps, h, precl); return mkvec2(f, fp); } /* v = [f(z), f'(z)]. Return h := z/(1-f(z)), h + h^2 zf'(z) */ static GEN ffmodify(GEN v, GEN z) { GEN f = gel(v,1), fp = gel(v,2), h = ginv(gsubsg(1, f)); return mkvec2(gmul(z, h), gadd(h, gmul(gsqr(h), gmul(z,fp)))); } GEN intnuminitgen(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long flext, long prec) { enum { f_COMP, /* [a,b] */ f_SEMI, /* [a,+-oo[, no oscillation */ f_OSC1, /* [a,+-oo[, oscillation */ f_INF , /* ]-oo,+oo[, no oscillation */ f_OSC2 /* ]-oo,+oo[, oscillation */ }; pari_sp ltop = avma; GEN hnpr, eps, v; long k, h, newprec, lim, precl = prec+EXTRAPREC; long flag, codea = transcode(a, "a"), codeb = transcode(b, "b"); int NOT_OSC, NOT_ODD; intdata D; intinit_start(&D, m, flext, precl); flag = f_SEMI; if (is_osc_f(codea) || is_osc_f(codeb)) flag = f_OSC1; if (is_fin_f(codea) && is_fin_f(codeb)) flag = f_COMP; else if (!is_fin_f(codea) && !is_fin_f(codeb)) { if (codea * codeb > 0) return gen_0; if (codea != -codeb) pari_err_TYPE("intnuminitgen [infinities of different types]", mkvec2(a,b)); flag = (flag == f_SEMI) ? f_INF : f_OSC2; } NOT_OSC = (flag == f_COMP || flag == f_SEMI || flag == f_INF); NOT_ODD = (flag == f_SEMI || flag == f_OSC1); newprec = (3*precl - 1)>>1; h = prec2nbits(precl)/2; eps = real2n(-h, newprec); if (NOT_OSC || !gequal1(eval(E, gen_0))) { GEN a0 = real_0(precl), a0n = real_0(newprec), xw, xwmod; xw = ffprime(E, eval, a0, a0n, eps, h, precl); xwmod = NOT_OSC? xw: ffmodify(xw, a0); D.tabx0 = gel(xwmod,1); D.tabw0 = gel(xwmod,2); } else { GEN xw = gdiv(pol_x(0), gsubsg(1, eval(E, gadd(pol_x(0), zeroser(0, 4))))); D.tabx0 = gprec_w(polcoeff0(xw, 0, 0), precl); D.tabw0 = gprec_w(polcoeff0(xw, 1, 0), precl); } /* precl <= newprec */ hnpr = real2n(-D.m, newprec); lim = lg(D.tabxp) - 1; for (k = 1; k <= lim; k++) { GEN akn = mulur(k, hnpr), ak = rtor(akn, precl), xw, xwmod; int finb; xw = ffprime(E, eval, ak, akn, eps, h, precl); xwmod = NOT_OSC? xw: ffmodify(xw, ak); gel(D.tabxp,k) = gel(xwmod,1); gel(D.tabwp,k) = gel(xwmod,2); finb = condfin(codeb, is_osc_f(codeb)? xw: xwmod, D.eps, D.m, k); if (NOT_ODD) { ak = negr(ak); akn = negr(akn); xw = ffprime(E, eval, ak, akn, eps, h, precl); xwmod = NOT_OSC? xw: ffmodify(xw, ak); gel(D.tabxm,k) = gel(xwmod,1); gel(D.tabwm,k) = gel(xwmod,2); if (finb && condfin(codea, is_osc_f(codeb)? xw: xwmod, D.eps, D.m, k)) break; } else if (finb) break; } v = intinit_end(&D, k-1, NOT_ODD? k-1: 0); if (!NOT_OSC) { GEN C = Pi2n(D.m, precl); TABx0(v) = gmul(TABx0(v), C); TABw0(v) = gmul(TABw0(v), C); TABxp(v) = RgV_Rg_mul(TABxp(v), C); TABwp(v) = RgV_Rg_mul(TABwp(v), C); TABxm(v) = RgV_Rg_mul(TABxm(v), C); TABwm(v) = RgV_Rg_mul(TABwm(v), C); } return gerepilecopy(ltop, v); } /* Assigns the values of the function weighted by w[k] at quadrature points x[k] * [replacing the weights]. Return the index of the last non-zero coeff */ static long weight(void *E, GEN (*eval)(void *, GEN), GEN x, GEN w) { long k, l = lg(x); for (k = 1; k < l; k++) gel(w,k) = gmul(gel(w,k), eval(E, gel(x,k))); k--; while (k >= 1) if (!gequal0(gel(w,k--))) break; return k; } /* compute the necessary tabs, weights multiplied by f(t). * If flag set, assumes that f(-t) = conj(f(t)). */ static GEN intfuncinitintern(void *E, GEN (*eval)(void*, GEN), GEN tab, long flag) { GEN tabxp = TABxp(tab), tabwp = TABwp(tab); GEN tabxm = TABxm(tab), tabwm = TABwm(tab); long L = weight(E, eval, tabxp, tabwp), L0 = lg(tabxp); TABw0(tab) = gmul(TABw0(tab), eval(E, TABx0(tab))); if (lg(tabxm) > 1) (void)weight(E, eval, tabxm, tabwm); else { tabxm = gneg(tabxp); if (flag) tabwm = gconj(tabwp); else { long L2; tabwm = leafcopy(tabwp); L2 = weight(E, eval, tabxm, tabwm); if (L > L2) L = L2; } TABxm(tab) = tabxm; TABwm(tab) = tabwm; } if (L < L0) { /* catch up functions whose growth at oo was not adequately described */ setlg(tabxp, L+1); setlg(tabwp, L+1); if (lg(tabxm) > 1) { setlg(tabxm, L+1); setlg(tabwm, L+1); } } return tab; } GEN intfuncinit(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long flag, long prec) { pari_sp ltop = avma; GEN T, tab = intnuminit(a, b, m, prec); if (lg(tab) != 3) T = intfuncinitintern(E, eval, tab, flag); else { T = cgetg(3, t_VEC); gel(T,1) = intfuncinitintern(E, eval, gel(tab,1), flag); gel(T,2) = intfuncinitintern(E, eval, gel(tab,2), flag); } return gerepilecopy(ltop, T); } 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"); 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; } /* now labs(codea) <= labs(codeb) */ if (codeb == f_SING) { if (codea == f_REG) 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); S = gsub(res1, res2); } return (sgns < 0) ? gneg(S) : S; } /* now b is infinite */ tmpi = 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; } 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); 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"); 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 ((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)); if (codea != f_YOSCC) SP = intninfpm(E, eval, coupeb, 1, 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)); 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))); } } S = gadd(SN, SP); } if (sgns < 0) S = gneg(S); return S; } GEN intnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec) { pari_sp ltop = avma; long l = prec+EXTRAPREC; GEN S; tab = intnuminit0(a, b, tab, prec); S = intnum_i(E, eval, gprec_w(a, l), gprec_w(b, l), tab, l); return gerepilecopy(ltop, gprec_wtrunc(S, prec)); } typedef struct auxint_s { GEN a, R, pi; GEN (*f)(void*, GEN); GEN (*w)(GEN, long); long prec; void *E; } auxint_t; static GEN auxcirc(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN s, c, z; mpsincos(mulrr(t, D->pi), &s, &c); z = mkcomplex(c,s); return gmul(z, D->f(D->E, gadd(D->a, gmul(D->R, z)))); } GEN intcirc(void *E, GEN (*eval)(void*, GEN), GEN a, GEN R, GEN tab, long prec) { auxint_t D; GEN z; D.a = a; D.R = R; D.pi = mppi(prec); D.f = eval; D.E = E; z = intnum(&D, &auxcirc, real_m1(prec), real_1(prec), tab, 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)); } /* w(Rt) f(a+it) */ static GEN auxinv(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN tmp = D->w(gmul(D->R, t), D->prec); return gmul(tmp, D->f(D->E, gadd(D->a, mulcxI(t)))); } 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; if (lg(sig) != 3 || !isinR(gel(sig,1)) || !isinR(gel(sig,2))) pari_err_TYPE("integral transform",sig); if (gsigne(gel(sig,2)) < 0) pari_err_OVERFLOW("integral transform [exponential increase]"); D.a = gel(sig,1); D.prec = prec; D.f = eval; D.E = E; if (gequal0(gel(sig,2))) { D.R = x; tmpP = gettmpP(mulcxI(gabs(x, prec))); tmpN = gettmpN(tmpP); tab = intnuminit0(tmpN, tmpP, tab, prec); D.w = gcos; zR = intnum_i(&D, &auxinv, tmpN, tmpP, tab, prec); gel(tmpP,2) = gneg(gel(tmpP,2)); D.w = gsin; zI = intnum_i(&D, &auxinv, gettmpN(tmpP), tmpP, tab, prec); z = gadd(zR, mulcxI(zI)); } else { D.R = mulcxI(x); tmpP = gettmpP(gel(sig,2)); D.w = gexp; z = intnum(&D, &auxinv, gettmpN(tmpP), tmpP, tab, prec); } return gdiv(gmul(gexp(gmul(gel(sig,1), x), prec), z), Pi2n(1, prec)); } /* If sig = [sigR, e]: if e = 0, slowly decreasing, if e > 0, exponentially * decreasing like exp(-e*t). If sig is real, identical to [sig, 1]. */ GEN intmellininv(void *E, GEN (*eval)(void*, GEN), GEN sig, GEN x, GEN tab, long prec) { if (typ(sig) != t_VEC) sig = mkvec2(sig, gen_1); return intinvintern(E, eval, sig, gneg(glog(x, prec)), tab, prec); } /* If sig = [sigR, e]: if e = 0, slowly decreasing, if e > 0, exponentially * decreasing like exp(-e*t). If sig is real, identical to [sig, 0]. */ GEN intlaplaceinv(void *E, GEN (*eval)(void*, GEN), GEN sig, GEN x, GEN tab, long prec) { if (typ(sig) != t_VEC) sig = mkvec2(sig, gen_0); return intinvintern(E, eval, sig, x, tab, prec); } /* assume tab computed with additional weights f(sig + I*T) */ typedef struct auxmel_s { GEN L; long prec; } auxmel_t; static GEN auxmelshort(void *E, GEN t) { auxmel_t *D = (auxmel_t*) E; return gexp(gmul(D->L, t), D->prec); } GEN intmellininvshort(GEN sig, GEN x, GEN tab, long prec) { auxmel_t D; GEN z, tmpP, 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))) pari_err_TYPE("intmellininvshort",sig); if (gsigne(gel(sig,2)) <= 0) 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); return gdiv(gmul(gexp(gmul(gel(sig,1), LX), prec), z), Pi2n(1, prec)); } /* a as in intnum. flag = 0 for sin, flag = 1 for cos. */ static GEN mytra(GEN a, GEN x, long flag, const char *name) { GEN b, xa; long s, codea = transcode(a, name); switch (labs(codea)) { case f_REG: case f_SING: case f_YFAST: return a; case f_YSLOW: case f_YVSLO: xa = real_i(x); s = gsigne(xa); 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)); return b; case f_YOSCS: case f_YOSCC: pari_err_IMPL("Fourier transform of oscillating functions"); } return NULL; } /* w(ta) f(t) */ static GEN auxfour(void *E, GEN t) { auxint_t *D = (auxint_t*) E; return gmul(D->w(gmul(t, D->a), D->prec), D->f(D->E, t)); } GEN intfouriersin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN x, GEN tab, long prec) { auxint_t D; GEN tmp; if (gequal0(x)) return gcopy(x); tmp = gmul(x, Pi2n(1, prec)); D.a = tmp; D.R = NULL; D.prec = prec; D.f = eval; D.E = E; a = mytra(a,tmp,0,"a"); b = mytra(b,tmp,0,"b"); D.w = gsin; return intnum(&D, &auxfour, a, b, tab, prec); } GEN intfouriercos(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN x, GEN tab, long prec) { auxint_t D; GEN tmp; if (gequal0(x)) return intnum(E, eval, a, b, tab, prec); tmp = gmul(x, Pi2n(1, prec)); D.a = tmp; D.R = NULL; D.prec = prec; D.f = eval; D.E = E; a = mytra(a,tmp,1,"a"); b = mytra(b,tmp,1,"b"); D.w = gcos; return intnum(&D, &auxfour, a, b, tab, prec); } GEN intfourierexp(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN x, GEN tab, long prec) { pari_sp ltop = avma; GEN R = intfouriercos(E, eval, a, b, x, tab, prec); GEN I = intfouriersin(E, eval, a, b, x, tab, prec); return gerepileupto(ltop, gadd(R, mulcxmI(I))); } GEN intnumromb(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long flag, long prec) { pari_sp av = avma; GEN z; switch(flag) { case 0: z = qrom3 (E, eval, a, b, prec); break; case 1: z = rombint(E, eval, a, b, prec); break; case 2: z = qromi (E, eval, a, b, prec); break; case 3: z = qrom2 (E, eval, a, b, prec); break; default: pari_err_FLAG("intnumromb"); return NULL; /* not reached */ } if (!z) pari_err_IMPL("intnumromb recovery [too many iterations]"); return gerepileupto(av, z); } GEN intnumromb0(GEN a, GEN b, GEN code, long flag, long prec) { EXPR_WRAP(code, intnumromb(EXPR_ARG, a, b, flag, prec)); } GEN intnum0(GEN a, GEN b, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intnum(EXPR_ARG, a, b, tab, prec)); } GEN intcirc0(GEN a, GEN R, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intcirc(EXPR_ARG, a, R, tab, prec)); } GEN intmellininv0(GEN sig, GEN x, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intmellininv(EXPR_ARG, sig, x, tab, prec)); } GEN intlaplaceinv0(GEN sig, GEN x, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intlaplaceinv(EXPR_ARG, sig, x, tab, prec)); } GEN intfourcos0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intfouriercos(EXPR_ARG, a, b, x, tab, prec)); } GEN intfoursin0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intfouriersin(EXPR_ARG, a, b, x, tab, prec)); } GEN intfourexp0(GEN a, GEN b, GEN x, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intfourierexp(EXPR_ARG, a, b, x, tab, prec)); } GEN intnuminitgen0(GEN a, GEN b, GEN code, long m, long flag, long prec) { EXPR_WRAP(code, intnuminitgen(EXPR_ARG, a, b, m, flag, prec)); } /* m and flag reversed on purpose */ GEN intfuncinit0(GEN a, GEN b, GEN code, long flag, long m, long prec) { EXPR_WRAP(code, intfuncinit(EXPR_ARG, a, b, m, flag? 1: 0, prec)); } #if 0 /* Two variable integration */ typedef struct auxf_s { GEN x; GEN (*f)(void *, GEN, GEN); void *E; } auxf_t; typedef struct indi_s { GEN (*c)(void*, GEN); GEN (*d)(void*, GEN); GEN (*f)(void *, GEN, GEN); void *Ec; void *Ed; void *Ef; GEN tabintern; long prec; } indi_t; static GEN auxf(GEN y, void *E) { auxf_t *D = (auxf_t*) E; return D->f(D->E, D->x, y); } static GEN intnumdoubintern(GEN x, void *E) { indi_t *D = (indi_t*) E; GEN c = D->c(x, D->Ec), d = D->d(x, D->Ed); auxf_t A; A.x = x; A.f = D->f; A.E = D->Ef; return intnum(&A, &auxf, c, d, D->tabintern, D->prec); } GEN intnumdoub(void *Ef, GEN (*evalf)(void *, GEN, GEN), void *Ec, GEN (*evalc)(void*, GEN), void *Ed, GEN (*evald)(void*, GEN), GEN a, GEN b, GEN tabext, GEN tabint, long prec) { indi_t E; E.c = evalc; E.d = evald; E.f = evalf; E.Ec = Ec; E.Ed = Ed; E.Ef = Ef; E.prec = prec; if (typ(tabint) == t_INT) { GEN C = evalc(a, Ec), D = evald(a, Ed); if (typ(C) != t_VEC && typ(D) != t_VEC) { C = gen_0; D = gen_1; } E.tabintern = intnuminit0(C, D, tabint, prec); } else E.tabintern = tabint; return intnum(&E, &intnumdoubintern, a, b, tabext, prec); } GEN intnumdoub0(GEN a, GEN b, int nc, int nd, int nf, GEN tabext, GEN tabint, long prec) { GEN z; push_lex(NULL); push_lex(NULL); z = intnumdoub(chf, &gp_eval2, chc, &gp_eval, chd, &gp_eval, a, b, tabext, tabint, prec); pop_lex(1); pop_lex(1); return z; } #endif /* Numerical summation routine assuming f holomorphic for Re(s) >= sig. * Computes sum_{n>=a} f(n) if sgn >= 0, * sum_{n>=a} (-1)^n f(n) otherwise, where a is real. * Variant of Abel-Plana. */ static GEN auxsum(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN z = mkcomplex(D->a, t); return D->f(D->E, z); } /* assume that conj(f(z)) = f(conj(z)) */ static GEN auxsumintern1(void *E, GEN t, long sgn) { auxint_t *D = (auxint_t*) E; GEN z = mkcomplex(D->a, t), u = D->f(D->E, z); return sgn > 0 ? imag_i(u): real_i(u); } /* no assumption */ static GEN auxsumintern(void *E, GEN t, long sgn) { auxint_t *D = (auxint_t*) E; GEN u,v, z = mkcomplex(D->a, t); u = D->f(D->E, z); gel(z,2) = gneg(t); v = D->f(D->E, z); return sgn > 0 ? gsub(u, v) : gadd(u, v); } static GEN auxsum0(void *E, GEN t) { return auxsumintern(E, t, 1); } static GEN auxsum1(void *E, GEN t) { return auxsumintern1(E, t, 1); } static GEN auxsumalt0(void *E, GEN t) { return auxsumintern(E, t, -1); } static GEN auxsumalt1(void *E, GEN t) { return auxsumintern1(E, t, -1); } static GEN sumnumall(void *E, GEN (*eval)(void*, GEN), GEN a, GEN sig, GEN tab, long flag, long sgn, long prec) { GEN SI, S, nsig, b, signew; long si = 1, flii; pari_sp ltop = avma; auxint_t D; b = suminit_start(sig); flii = gequal0(gel(b,2)); if (!is_scalar_t(typ(a))) pari_err_TYPE("sumnum",a); tab = sumnuminit0(sig, tab, sgn, prec); signew = (typ(sig) == t_VEC) ? gel(sig,1) : sig; a = gceil(a); nsig = gmax(subis(a, 1), gceil(gsub(signew, ghalf))); if (sgn < 0) { if (mpodd(nsig)) nsig = addsi(1, nsig); si = mpodd(a) ? -1 : 1; } SI = real_0(prec); while (cmpii(a, nsig) <= 0) { SI = (si < 0) ? gsub(SI, eval(E, a)) : gadd(SI, eval(E, a)); a = addsi(1, a); if (sgn < 0) si = -si; } D.a = gadd(nsig, ghalf); D.R = gen_0; D.f = eval; D.E = E; D.prec = prec; if (!flii) S = intnum_i(&D, sgn > 0? (flag ? &auxsum1 : &auxsum0) : (flag ? &auxsumalt1 : &auxsumalt0), gen_0, b, tab, prec); else { if (flag) { GEN emp = leafcopy(tab); TABwm(emp) = TABwp(emp); S = gmul2n(intninfinf(&D, sgn > 0? &auxsum1: &auxsumalt1, emp),-1); } else S = intninfinfintern(&D, &auxsum, tab, sgn); } if (flag) S = gneg(S); else { S = gmul2n(S, -1); S = (sgn < 0) ? gneg(S): mulcxI(S); } return gerepileupto(ltop, gadd(SI, S)); } GEN sumnum(void *E, GEN (*f)(void *, GEN), GEN a,GEN sig,GEN tab,long flag,long prec) { return sumnumall(E,f,a,sig,tab,flag,1,prec); } GEN sumnumalt(void *E, GEN (*f)(void *, GEN),GEN a,GEN s,GEN tab,long flag,long prec) { return sumnumall(E,f,a,s,tab,flag,-1,prec); } GEN sumnum0(GEN a, GEN sig, GEN code, GEN tab, long flag, long prec) { EXPR_WRAP(code, sumnum(EXPR_ARG, a, sig, tab, flag, prec)); } GEN sumnumalt0(GEN a, GEN sig, GEN code, GEN tab, long flag, long prec) { EXPR_WRAP(code, sumnumalt(EXPR_ARG, a, sig, tab, flag, prec)); } pari-2.7.5/src/language/default.h0000644000175000017500000000266712605246255015277 0ustar billbill/* This file is autogenerated from the database. */ /* 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,"",""}, {NULL,0,NULL,0,NULL,NULL} /* sentinel */ }; pari-2.7.5/src/language/opcode.h0000644000175000017500000000305212405547147015113 0ustar billbill/* 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. */ BEGINEXTERN typedef enum {Gvoid, Gsmall, Gvec, Gvar, Ggen, Gclosure} Gtype; typedef enum {OCpushlong='A',OCpushgnil,OCpushgen,OCpushreal,OCpushstoi,OCpushvar, OCpop, OCstoi,OCitos,OCtostr,OCvarn,OCcopy,OCcopyifclone, OCprecreal,OCprecdl, OCvec,OCmat,OCcol, OCstackgen, OCcompo1,OCcompo2,OCcompoC,OCcompoL, OCpushptr,OCendptr, OCcompo1ptr,OCcompo2ptr,OCcompoCptr,OCcompoLptr, OCcalllong,OCcallgen,OCcallgen2,OCcallint,OCcallvoid,OCcalluser, OCnewframe,OCsaveframe, OCpushdyn,OCstoredyn,OCnewptrdyn,OCsimpleptrdyn, OCpushlex,OCstorelex,OCnewptrlex,OCsimpleptrlex, OCgetargs,OCdefaultarg,OClocalvar,OClocalvar0, OCcheckargs,OCcheckargs0,OCdefaultgen,OCdefaultlong, OCavma,OCgerepile, OCcowvardyn,OCcowvarlex, OCdup,OCstoreptr,OCcheckuserargs} op_code; ENDEXTERN pari-2.7.5/src/language/default.c0000644000175000017500000005035712573013756015273 0ustar billbill/* 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" /* Simple-minded parsing utilities. These are forbidden to use the GP stack * which may not exist at this point [e.g upon GP initialization] */ /* Return all chars, up to next separator * [as strtok but must handle verbatim character string] */ char* get_sep(const char *t) { char *buf = stack_malloc(strlen(t)+1); char *s = buf; int outer = 1; for(;;) { switch(*s++ = *t++) { case '"': outer = !outer; break; case '\0': return buf; case ';': if (outer) { s[-1] = 0; return buf; } break; case '\\': /* gobble next char */ if (! (*s++ = *t++) ) return buf; } } } static ulong safe_mul(ulong x, ulong y) { ulong z; LOCAL_HIREMAINDER; z = mulll(x, y); return hiremainder? 0: z; } /* "atoul" + optional [kmg] suffix */ static ulong my_int(char *s) { ulong n = 0; char *p = s; while (isdigit((int)*p)) { ulong m; if (n > (~0UL / 10)) pari_err(e_SYNTAX,"integer too large",s,s); n *= 10; m = n; n += *p++ - '0'; if (n < m) pari_err(e_SYNTAX,"integer too large",s,s); } if (n) { switch(*p) { 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; } if (!n) pari_err(e_SYNTAX,"integer too large",s,s); } if (*p) pari_err(e_SYNTAX,"I was expecting an integer here", s, s); return n; } 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)) { avma = av; return dflt; } n = (long)my_int(p); if (n < 0) pari_err(e_SYNTAX,"integer too large",s,s); 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); u = my_int(p); avma = av; return u; } /********************************************************************/ /* */ /* DEFAULTS */ /* */ /********************************************************************/ long getrealprecision(void) { return GP_DATA->fmt->sigd; } long setrealprecision(long n, long *prec) { GP_DATA->fmt->sigd = n; *prec = precreal = ndec2prec(n); return n; } GEN sd_toggle(const char *v, long flag, const char *s, int *ptn) { int state = *ptn; if (v) { int n = (int)get_int(v,0); if (n == state) return gnil; if (n != !state) { char *t = stack_malloc(64 + strlen(s)); (void)sprintf(t, "default: incorrect value for %s [0:off / 1:on]", s); pari_err(e_SYNTAX, t, v,v); } state = *ptn = n; } switch(flag) { case d_RETURN: return utoi(state); case d_ACKNOWLEDGE: if (state) pari_printf(" %s = 1 (on)\n", s); else pari_printf(" %s = 0 (off)\n", s); break; } return gnil; } static void sd_ulong_init(const char *v, const char *s, ulong *ptn, ulong Min, ulong Max) { if (v) { ulong n = get_uint(v); if (n > Max || n < Min) { char *buf = stack_malloc(strlen(s) + 2 * 20 + 40); (void)sprintf(buf, "default: incorrect value for %s [%lu-%lu]", s, Min, Max); pari_err(e_SYNTAX, buf, v,v); } *ptn = n; } } /* msg is NULL or NULL-terminated array with msg[0] != NULL. */ GEN sd_ulong(const char *v, long flag, const char *s, ulong *ptn, ulong Min, ulong Max, const char **msg) { ulong n = *ptn; sd_ulong_init(v, s, ptn, Min, Max); switch(flag) { case d_RETURN: return utoi(*ptn); case d_ACKNOWLEDGE: if (!v || *ptn != n) { if (!msg) /* no specific message */ pari_printf(" %s = %lu\n", s, *ptn); else if (!msg[1]) /* single message, always printed */ pari_printf(" %s = %lu %s\n", s, *ptn, msg[0]); else /* print (new)-n-th message */ pari_printf(" %s = %lu %s\n", s, *ptn, msg[*ptn]); } break; } return gnil; } GEN sd_realprecision(const char *v, long flag) { pariout_t *fmt = GP_DATA->fmt; if (v) { ulong newnb = fmt->sigd, 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); if (prec == precreal) return gnil; precreal = prec; } if (flag == d_RETURN) return stoi(prec2ndec(precreal)); if (flag == d_ACKNOWLEDGE) { long n = prec2ndec(precreal); pari_printf(" realprecision = %ld significant digits", n); if (fmt->sigd < 0) pari_puts(" (all digits displayed)"); else if (n != fmt->sigd) pari_printf(" (%ld digits displayed)", fmt->sigd); pari_putc('\n'); } return gnil; } GEN sd_seriesprecision(const char *v, long flag) { const char *msg[] = {"significant terms", NULL}; return sd_ulong(v,flag,"seriesprecision",&precdl, 1,LGBITS,msg); } static long gp_get_color(char **st) { char *s, *v = *st; int trans; long c; if (isdigit((int)*v)) { c = atol(v); trans = 1; } /* color on transparent background */ else { if (*v == '[') { const char *a[3]; long i = 0; for (a[0] = s = ++v; *s && *s != ']'; s++) if (*s == ',') { *s = 0; a[++i] = s+1; } if (*s != ']') pari_err(e_SYNTAX,"expected character: ']'",s, *st); *s = 0; for (i++; i<3; i++) a[i] = ""; /* properties | color | background */ c = (atoi(a[2])<<8) | atoi(a[0]) | (atoi(a[1])<<4); trans = (*(a[1]) == 0); v = s + 1; } else { c = c_NONE; trans = 0; } } if (trans) c = c | (1L<<12); while (*v && *v++ != ',') /* empty */; if (c != c_NONE) disable_color = 0; *st = v; return c; } /* 1: error, 2: history, 3: prompt, 4: input, 5: output, 6: help, 7: timer */ GEN sd_colors(const char *v, long flag) { long c,l; if (v && !(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS))) { char *v0, *s; disable_color=1; l = strlen(v); if (l <= 2 && strncmp(v, "no", l) == 0) v = ""; if (l <= 6 && strncmp(v, "darkbg", l) == 0) v = "1, 5, 3, 7, 6, 2, 3"; /* Assume recent ReadLine. */ if (l <= 7 && strncmp(v, "lightbg", l) == 0) v = "1, 6, 3, 4, 5, 2, 3"; /* Assume recent ReadLine. */ if (l <= 8 && strncmp(v, "brightfg", l) == 0) /* Good for windows consoles */ 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); for (c=c_ERR; c < c_LAST; c++) gp_colors[c] = gp_get_color(&s); pari_free(v0); } if (flag == d_ACKNOWLEDGE || flag == d_RETURN) { char s[128], *t = s; long col[3], n; for (*t=0,c=c_ERR; c < c_LAST; c++) { n = gp_colors[c]; if (n == c_NONE) sprintf(t,"no"); else { decode_color(n,col); if (n & (1L<<12)) { if (col[0]) sprintf(t,"[%ld,,%ld]",col[1],col[0]); else sprintf(t,"%ld",col[1]); } else sprintf(t,"[%ld,%ld,%ld]",col[1],col[2],col[0]); } t += strlen(t); if (c < c_LAST - 1) { *t++=','; *t++=' '; } } if (flag==d_RETURN) return strtoGENstr(s); pari_printf(" colors = \"%s\"\n",s); } return gnil; } GEN sd_format(const char *v, long flag) { pariout_t *fmt = GP_DATA->fmt; if (v) { char c = *v; if (c!='e' && c!='f' && c!='g') pari_err(e_SYNTAX,"default: inexistent format",v,v); fmt->format = c; v++; if (isdigit((int)*v)) { while (isdigit((int)*v)) v++; } /* FIXME: skip obsolete field width */ if (*v++ == '.') { if (*v == '-') fmt->sigd = -1; else if (isdigit((int)*v)) fmt->sigd=atol(v); } } if (flag == d_RETURN) { char *s = stack_malloc(64); (void)sprintf(s, "%c.%ld", fmt->format, fmt->sigd); return strtoGENstr(s); } if (flag == d_ACKNOWLEDGE) pari_printf(" format = %c.%ld\n", fmt->format, fmt->sigd); return gnil; } GEN 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 }; 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; } GEN sd_secure(const char *v, long flag) { if (v && GP_DATA->secure) pari_ask_confirm("[secure mode]: About to modify the 'secure' flag"); return sd_toggle(v,flag,"secure", &(GP_DATA->secure)); } GEN sd_debug(const char *v, long flag) { return sd_ulong(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); } GEN sd_debugfiles(const char *v, long flag) { return sd_ulong(v,flag,"debugfiles",&DEBUGFILES, 0,20,NULL); } GEN sd_debugmem(const char *v, long flag) { return sd_ulong(v,flag,"debugmem",&DEBUGMEM, 0,20,NULL); } /* set D->hist to size = s / total = t */ static void init_hist(gp_data *D, size_t s, ulong t) { gp_hist *H = D->hist; H->total = t; H->size = s; H->v = (gp_hist_cell*)pari_calloc(s * sizeof(gp_hist_cell)); } GEN sd_histsize(const char *s, long flag) { gp_hist *H = GP_DATA->hist; ulong n = H->size; GEN r = sd_ulong(s,flag,"histsize",&n, 1, (LONG_MAX / sizeof(long)) - 1,NULL); if (n != H->size) { const ulong total = H->total; long g, h, k, kmin; gp_hist_cell *v = H->v, *w; /* v = old data, w = new one */ size_t sv = H->size, sw; init_hist(GP_DATA, n, total); if (!total) return r; w = H->v; sw= H->size; /* copy relevant history entries */ g = (total-1) % sv; h = k = (total-1) % sw; kmin = k - minss(sw, sv); for ( ; k > kmin; k--, g--, h--) { w[h] = v[g]; v[g].z = NULL; if (!g) g = sv; if (!h) h = sw; } /* clean up */ for ( ; v[g].z; g--) { gunclone(v[g].z); if (!g) g = sv; } pari_free((void*)v); } return r; } static void TeX_define(const char *s, const char *def) { fprintf(pari_logfile, "\\ifx\\%s\\undefined\n \\def\\%s{%s}\\fi\n", s,s,def); } static void TeX_define2(const char *s, const char *def) { fprintf(pari_logfile, "\\ifx\\%s\\undefined\n \\def\\%s#1#2{%s}\\fi\n", s,s,def); } static FILE * open_logfile(const char *s) { FILE *log = fopen(s, "a"); if (!log) pari_err_FILE("logfile",s); #ifndef WINCE setbuf(log,(char *)NULL); #endif return log; } GEN sd_log(const char *v, long flag) { const char *msg[] = { "(off)", "(on)", "(on with colors)", "(TeX output)", NULL }; ulong s = logstyle; GEN res = sd_ulong(v,flag,"log", &s, 0, 3, msg); if (!s != !logstyle) /* Compare converts to boolean */ { /* toggled LOG */ if (logstyle) { /* close log */ if (flag == d_ACKNOWLEDGE) pari_printf(" [logfile was \"%s\"]\n", current_logfile); if (pari_logfile) /* paranoia */ { fclose(pari_logfile); pari_logfile = NULL; } } else pari_logfile = open_logfile(current_logfile); } if (pari_logfile && s != logstyle && s == logstyle_TeX) { TeX_define("PARIbreak", "\\hskip 0pt plus \\hsize\\relax\\discretionary{}{}{}"); TeX_define("PARIpromptSTART", "\\vskip\\medskipamount\\bgroup\\bf"); TeX_define("PARIpromptEND", "\\egroup\\bgroup\\tt"); TeX_define("PARIinputEND", "\\egroup"); TeX_define2("PARIout", "\\vskip\\smallskipamount$\\displaystyle{\\tt\\%#1} = #2$"); } /* don't record new value until we are sure everything is fine */ logstyle = s; return res; } GEN sd_TeXstyle(const char *v, long flag) { const char *msg[] = { "(bits 0x2/0x4 control output of \\left/\\PARIbreak)", NULL }; ulong n = GP_DATA->fmt->TeXstyle; GEN z = sd_ulong(v,flag,"TeXstyle", &n, 0, 7, msg); GP_DATA->fmt->TeXstyle = n; return z; } GEN sd_nbthreads(const char *v, long flag) { return sd_ulong(v,flag,"nbthreads",&pari_mt_nbthreads, 1,LONG_MAX,NULL); } GEN sd_output(const char *v, long flag) { const char *msg[] = {"(raw)", "(prettymatrix)", "(prettyprint)", "(external prettyprint)", NULL}; ulong n = GP_DATA->fmt->prettyp; GEN z = sd_ulong(v,flag,"output", &n, 0,3,msg); GP_DATA->fmt->prettyp = n; GP_DATA->fmt->sp = (n != f_RAW); return z; } GEN sd_parisize(const char *v, long flag) { ulong size = top - bot, n = size; GEN r = sd_ulong(v,flag,"parisize",&n, 10000,LONG_MAX,NULL); if (n != size) { if (flag == d_INITRC) pari_init_stack(n, size); else allocatemem(n); } return r; } GEN sd_threadsize(const char *v, long flag) { ulong size = GP_DATA->threadsize, n = size; GEN r = sd_ulong(v,flag,"threadsize",&n, 0,LONG_MAX,NULL); if (n != size) GP_DATA->threadsize = n; return r; } GEN sd_primelimit(const char *v, long flag) { return sd_ulong(v,flag,"primelimit",&(GP_DATA->primelimit), 0,2*(ulong)(LONG_MAX-1024) + 1,NULL); } GEN sd_simplify(const char *v, long flag) { return sd_toggle(v,flag,"simplify", &(GP_DATA->simplify)); } GEN sd_strictmatch(const char *v, long flag) { return sd_toggle(v,flag,"strictmatch", &(GP_DATA->strictmatch)); } GEN sd_strictargs(const char *v, long flag) { return sd_toggle(v,flag,"strictargs", &(GP_DATA->strictargs)); } GEN sd_string(const char *v, long flag, const char *s, char **pstr) { char *old = *pstr; if (v) { char *str, *ev = path_expand(v); long l = strlen(ev) + 256; str = (char *) pari_malloc(l); strftime_expand(ev,str, l-1); pari_free(ev); if (GP_DATA->secure) { char *msg=pari_sprintf("[secure mode]: About to change %s to '%s'",s,str); pari_ask_confirm(msg); pari_free(msg); } if (old) pari_free(old); *pstr = old = pari_strdup(str); pari_free(str); } else if (!old) old = (char*)""; if (flag == d_RETURN) return strtoGENstr(old); if (flag == d_ACKNOWLEDGE) pari_printf(" %s = \"%s\"\n",s,old); return gnil; } GEN sd_logfile(const char *v, long flag) { GEN r = sd_string(v, flag, "logfile", ¤t_logfile); if (v && pari_logfile) { FILE *log = open_logfile(current_logfile); fclose(pari_logfile); pari_logfile = log; } return r; } GEN sd_factor_add_primes(const char *v, long flag) { return sd_toggle(v,flag,"factor_add_primes", &factor_add_primes); } GEN sd_factor_proven(const char *v, long flag) { return sd_toggle(v,flag,"factor_proven", &factor_proven); } GEN sd_new_galois_format(const char *v, long flag) { return sd_toggle(v,flag,"new_galois_format", &new_galois_format); } GEN sd_datadir(const char *v, long flag) { const char *str; if (v) { if (pari_datadir) pari_free(pari_datadir); pari_datadir = path_expand(v); } str = pari_datadir? pari_datadir: "none"; if (flag == d_RETURN) return strtoGENstr(str); if (flag == d_ACKNOWLEDGE) pari_printf(" datadir = \"%s\"\n", str); return gnil; } static GEN sd_PATH(const char *v, long flag, const char* s, gp_path *p) { if (v) { pari_free((void*)p->PATH); p->PATH = pari_strdup(v); if (flag == d_INITRC) return gnil; gp_expand_path(p); } if (flag == d_RETURN) return strtoGENstr(p->PATH); if (flag == d_ACKNOWLEDGE) pari_printf(" %s = \"%s\"\n", s, p->PATH); return gnil; } GEN sd_path(const char *v, long flag) { return sd_PATH(v, flag, "path", GP_DATA->path); } GEN sd_sopath(char *v, int flag) { return sd_PATH(v, flag, "sopath", GP_DATA->sopath); } static const char *DFT_PRETTYPRINTER = "tex2mail -TeX -noindent -ragged -by_par"; GEN sd_prettyprinter(const char *v, long flag) { gp_pp *pp = GP_DATA->pp; if (v && !(GP_DATA->flags & gpd_TEXMACS)) { char *old = pp->cmd; int cancel = (!strcmp(v,"no")); if (GP_DATA->secure) pari_err(e_MISC,"[secure mode]: can't modify 'prettyprinter' default (to %s)",v); if (!strcmp(v,"yes")) v = DFT_PRETTYPRINTER; if (old && strcmp(old,v) && pp->file) { pariFILE *f; if (cancel) f = NULL; else { f = try_pipe(v, mf_OUT); if (!f) { pari_warn(warner,"broken prettyprinter: '%s'",v); return gnil; } } pari_fclose(pp->file); pp->file = f; } pp->cmd = cancel? NULL: pari_strdup(v); if (old) pari_free(old); if (flag == d_INITRC) return gnil; } if (flag == d_RETURN) return strtoGENstr(pp->cmd? pp->cmd: ""); if (flag == d_ACKNOWLEDGE) pari_printf(" prettyprinter = \"%s\"\n",pp->cmd? pp->cmd: ""); return gnil; } /* compare entrees s1 s2 according to the associated function name */ static int 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); } /* ep associated to function f of arity 2. Call f(v,flag) */ static GEN call_f2(entree *ep, const char *v, long flag) { return ((GEN (*)(const char*,long))ep->value)(v, flag); } GEN setdefault(const char *s, const char *v, long flag) { entree *ep; if (!s) { /* list all defaults */ pari_stack st; entree **L; long i; pari_stack_init(&st, sizeof(*L), (void**)&L); defaults_list(&st); qsort (L, st.n, sizeof(*L), compare_name); for (i = 0; i < st.n; i++) (void)call_f2(L[i], NULL, d_ACKNOWLEDGE); pari_stack_delete(&st); return gnil; } ep = is_entry_intern(s, defaults_hash, NULL); if (!ep) { pari_err(e_MISC,"unknown default: %s",s); return NULL; /* not reached */ } 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); } /********************************************************************/ /* */ /* INITIALIZE GP_DATA */ /* */ /********************************************************************/ /* initialize path */ static void init_path(gp_path *path, const char *v) { path->PATH = pari_strdup(v); path->dirs = NULL; } /* initialize D->fmt */ static void init_fmt(gp_data *D) { #ifdef LONG_IS_64BIT static pariout_t DFLT_OUTPUT = { 'g', 38, 1, f_PRETTYMAT, 0 }; #else static pariout_t DFLT_OUTPUT = { 'g', 28, 1, f_PRETTYMAT, 0 }; #endif D->fmt = &DFLT_OUTPUT; } /* initialize D->pp */ static void init_pp(gp_data *D) { gp_pp *p = D->pp; p->cmd = pari_strdup(DFT_PRETTYPRINTER); p->file = NULL; } gp_data * default_gp_data(void) { static gp_data __GPDATA, *D = &__GPDATA; static gp_hist __HIST; static gp_pp __PP; static gp_path __PATH, __SOPATH; static pari_timer __T; D->flags = 0; D->primelimit = 500000; /* GP-specific */ D->breakloop = 1; D->echo = 0; D->lim_lines = 0; D->linewrap = 0; D->recover = 1; D->chrono = 0; D->strictargs = 0; D->strictmatch = 1; D->simplify = 1; D->secure = 0; D->use_readline= 0; D->T = &__T; D->hist = &__HIST; D->pp = &__PP; D->path = &__PATH; D->sopath=&__SOPATH; init_fmt(D); init_hist(D, 5000, 0); init_path(D->path, pari_default_path()); init_path(D->sopath, ""); init_pp(D); return D; } pari-2.7.5/src/language/parse.c0000644000175000017500000026007212405547532014754 0ustar billbill/* A Bison parser, made by GNU Bison 2.5. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2011 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 the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 1 /* Substitute the variable and function names. */ #define yyparse pari_parse #define yylex pari_lex #define yyerror pari_error #define yylval pari_lval #define yychar pari_char #define yydebug pari_debug #define yynerrs pari_nerrs #define yylloc pari_lloc /* Copy the first part of user declarations. */ /* Line 268 of yacc.c */ #line 1 "../src/language/parse.y" /* Copyright (C) 2006 The PARI group. This file is part of the PARI 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. */ #define YYSIZE_T size_t #define YYSTYPE union token_value #define YYLTYPE struct node_loc #define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).start = ((N)?(Rhs)[1].start:(Rhs)[0].end), \ (Current).end = (Rhs)[N].end) #include "parsec.h" #define NOARG(x) newnode(Fnoarg,-1,-1,&(x)) /* Line 268 of yacc.c */ #line 104 "../src/language/parse.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 1 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { KPARROW = 258, KARROW = 259, KDOTDOT = 260, KPE = 261, KSE = 262, KME = 263, KDE = 264, KDRE = 265, KEUCE = 266, KMODE = 267, KAND = 268, KOR = 269, KID = 270, KEQ = 271, KNE = 272, KGE = 273, KLE = 274, KSRE = 275, KSLE = 276, KSR = 277, KSL = 278, KDR = 279, KPP = 280, KSS = 281, KINTEGER = 282, KREAL = 283, KENTRY = 284, KSTRING = 285, DEFFUNC = 286, SEQ = 287, LVAL = 288, INT = 289, SIGN = 290 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; } YYLTYPE; # define yyltype YYLTYPE /* obsolescent; will be withdrawn */ # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ #line 193 "../src/language/parse.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS && (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__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #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 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 638 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 61 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 21 /* YYNRULES -- Number of rules. */ #define YYNRULES 109 /* YYNRULES -- Number of states. */ #define YYNSTATES 189 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 290 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 2, 49, 2, 43, 38, 53, 55, 59, 46, 41, 36, 42, 54, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 35, 40, 37, 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 44, 57, 48, 2, 58, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 60, 2, 51, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 47 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in 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 }; /* 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 }; /* 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, 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, 212, 212, 216, 217, 220, 223, 226, 228, 230, 231 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "\")->\"", "\"->\"", "\"..\"", "\"+=\"", "\"-=\"", "\"*=\"", "\"/=\"", "\"\\\\/=\"", "\"\\\\=\"", "\"%=\"", "\"&&\"", "\"||\"", "\"===\"", "\"==\"", "\"!=\"", "\">=\"", "\"<=\"", "\">>=\"", "\"<<=\"", "\">>\"", "\"<<\"", "\"\\\\/\"", "\"++\"", "\"--\"", "\"integer\"", "\"real number\"", "\"variable name\"", "\"character string\"", "DEFFUNC", "SEQ", "LVAL", "INT", "';'", "','", "'='", "'&'", "'>'", "'<'", "'+'", "'-'", "'%'", "'\\\\'", "'/'", "'*'", "SIGN", "'^'", "'#'", "'!'", "'~'", "'['", "'\\''", "'.'", "'('", "':'", "']'", "'`'", "')'", "'|'", "$accept", "sequnused", "seq", "range", "matrix_index", "backticks", "history", "expr", "lvalue", "matrixelts", "matrixlines", "matrix", "in", "inseq", "compr", "arg", "$@1", "listarg", "funcid", "memberid", "definition", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 59, 44, 61, 38, 62, 60, 43, 45, 37, 92, 47, 42, 290, 94, 35, 33, 126, 91, 39, 46, 40, 58, 93, 96, 41, 124 }; # endif /* 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, 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, 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, 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, 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 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, 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 }; /* 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, 23 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -162 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 }; /* 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 }; /* 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. */ #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, 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, 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, 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, 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 }; #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, 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, 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, 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, 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, -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 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 27, 28, 29, 30, 41, 42, 43, 49, 50, 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, 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, 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 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. However, YYFAIL appears to be in use. Nevertheless, it is formally deprecated in Bison 2.4.2's NEWS entry, where a plan to phase it out is discussed. */ #define YYFAIL goto yyerrlab #if defined YYFAIL /* This is here to suppress warnings from the GCC cpp's -Wunused-macros. Normally we don't worry about that warning, but some users do, and we want to make it easy for users to remove YYFAIL uses, which will produce warnings from Bison 2.5. */ #endif #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (&yylloc, lex, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) #else # define YYLEX yylex (&yylval, &yylloc, lex) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value, Location, lex); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char **lex) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, lex) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; char **lex; #endif { if (!yyvaluep) return; YYUSE (yylocationp); YYUSE (lex); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char **lex) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, lex) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; char **lex; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, lex); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, char **lex) #else static void yy_reduce_print (yyvsp, yylsp, yyrule, lex) YYSTYPE *yyvsp; YYLTYPE *yylsp; int yyrule; char **lex; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) , &(yylsp[(yyi + 1) - (yynrhs)]) , lex); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, yylsp, Rule, lex); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # 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) { 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 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; } } } switch (yycount) { # 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_ } yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; 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; } /* 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; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, char **lex) #else static void yydestruct (yymsg, yytype, yyvaluep, yylocationp, lex) const char *yymsg; int yytype; YYSTYPE *yyvaluep; YYLTYPE *yylocationp; char **lex; #endif { YYUSE (yyvaluep); YYUSE (yylocationp); YYUSE (lex); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { case 63: /* "seq" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1415 "../src/language/parse.c" break; case 64: /* "range" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1424 "../src/language/parse.c" break; case 65: /* "matrix_index" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1433 "../src/language/parse.c" break; case 66: /* "backticks" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1442 "../src/language/parse.c" break; case 67: /* "history" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1451 "../src/language/parse.c" break; case 68: /* "expr" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1460 "../src/language/parse.c" break; case 69: /* "lvalue" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1469 "../src/language/parse.c" break; case 70: /* "matrixelts" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1478 "../src/language/parse.c" break; case 71: /* "matrixlines" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1487 "../src/language/parse.c" break; case 72: /* "matrix" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1496 "../src/language/parse.c" break; case 73: /* "in" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1505 "../src/language/parse.c" break; case 74: /* "inseq" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1514 "../src/language/parse.c" break; case 75: /* "compr" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1523 "../src/language/parse.c" break; case 76: /* "arg" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1532 "../src/language/parse.c" break; case 78: /* "listarg" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1541 "../src/language/parse.c" break; case 79: /* "funcid" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1550 "../src/language/parse.c" break; case 80: /* "memberid" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1559 "../src/language/parse.c" break; case 81: /* "definition" */ /* Line 1391 of yacc.c */ #line 82 "../src/language/parse.y" { pari_discarded++; }; /* Line 1391 of yacc.c */ #line 1568 "../src/language/parse.c" break; default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (char **lex); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (char **lex) #else int yyparse (lex) char **lex; #endif #endif { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Location data for the lookahead symbol. */ YYLTYPE yylloc; /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; /* The location stack. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls; YYLTYPE *yylsp; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; YYLTYPE yyloc; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yyls = yylsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; yylsp = yyls; #if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL /* Initialize the default location before parsing starts. */ yylloc.first_line = yylloc.last_line = 1; yylloc.first_column = yylloc.last_column = 1; #endif /* User initialization code. */ /* Line 1590 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" yylsp[0] = yylloc; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); yyls = yyls1; yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; *++yylsp = yylloc; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* Line 1806 of yacc.c */ #line 85 "../src/language/parse.y" {(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;} break; case 4: /* Line 1806 of yacc.c */ #line 89 "../src/language/parse.y" {(yyval.val)=NOARG((yyloc));} break; case 5: /* Line 1806 of yacc.c */ #line 90 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 6: /* Line 1806 of yacc.c */ #line 91 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (2)].val); (yyloc)=(yylsp[(1) - (2)]);} 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));} break; case 8: /* Line 1806 of yacc.c */ #line 95 "../src/language/parse.y" { (yyval.val)=newnode(Frange,NOARG((yyloc)),NOARG((yyloc)),&(yyloc)); } break; case 9: /* Line 1806 of yacc.c */ #line 96 "../src/language/parse.y" { (yyval.val)=newnode(Frange,(yyvsp[(1) - (1)].val),NOARG((yyloc)),&(yyloc)); } break; case 10: /* Line 1806 of yacc.c */ #line 97 "../src/language/parse.y" { (yyval.val)=newnode(Frange,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].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)); } break; case 12: /* Line 1806 of yacc.c */ #line 101 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(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));} break; case 14: /* Line 1806 of yacc.c */ #line 105 "../src/language/parse.y" {(yyval.val)=1;} break; case 15: /* Line 1806 of yacc.c */ #line 106 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (2)].val)+1;} break; case 16: /* Line 1806 of yacc.c */ #line 109 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,-1,-1,&(yyloc));} break; case 17: /* Line 1806 of yacc.c */ #line 110 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newintnode(&(yylsp[(2) - (2)])),-1,&(yyloc));} break; case 18: /* Line 1806 of yacc.c */ #line 111 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newnode(Fsmall,-(yyvsp[(2) - (2)].val),-1,&(yyloc)),-1,&(yyloc));} break; case 19: /* Line 1806 of yacc.c */ #line 112 "../src/language/parse.y" {(yyval.val)=newopcall(OPhisttime,-1,-1,&(yyloc));} break; case 20: /* Line 1806 of yacc.c */ #line 113 "../src/language/parse.y" {(yyval.val)=newopcall(OPhisttime,newintnode(&(yylsp[(3) - (3)])),-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));} break; case 22: /* Line 1806 of yacc.c */ #line 117 "../src/language/parse.y" {(yyval.val)=newintnode(&(yylsp[(1) - (1)]));} break; case 23: /* Line 1806 of yacc.c */ #line 118 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(yyloc));} break; case 24: /* Line 1806 of yacc.c */ #line 119 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(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));} break; case 26: /* Line 1806 of yacc.c */ #line 122 "../src/language/parse.y" {(yyval.val)=newconst(CSTstr,&(yyloc));} break; case 27: /* Line 1806 of yacc.c */ #line 123 "../src/language/parse.y" {(yyval.val)=newconst(CSTquote,&(yyloc));} break; case 28: /* Line 1806 of yacc.c */ #line 124 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 29: /* Line 1806 of yacc.c */ #line 125 "../src/language/parse.y" {(yyval.val)=newnode(Fcall,(yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].val),&(yyloc));} break; case 30: /* Line 1806 of yacc.c */ #line 126 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 31: /* Line 1806 of yacc.c */ #line 127 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 32: /* Line 1806 of yacc.c */ #line 128 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 33: /* Line 1806 of yacc.c */ #line 129 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 34: /* Line 1806 of yacc.c */ #line 130 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 35: /* Line 1806 of yacc.c */ #line 131 "../src/language/parse.y" {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 36: /* Line 1806 of yacc.c */ #line 132 "../src/language/parse.y" {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 37: /* Line 1806 of yacc.c */ #line 133 "../src/language/parse.y" {(yyval.val)=newopcall(OPpp,(yyvsp[(1) - (2)].val),-1,&(yyloc));} break; case 38: /* Line 1806 of yacc.c */ #line 134 "../src/language/parse.y" {(yyval.val)=newopcall(OPss,(yyvsp[(1) - (2)].val),-1,&(yyloc));} break; case 39: /* Line 1806 of yacc.c */ #line 135 "../src/language/parse.y" {(yyval.val)=newopcall(OPme,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 40: /* Line 1806 of yacc.c */ #line 136 "../src/language/parse.y" {(yyval.val)=newopcall(OPde,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 41: /* Line 1806 of yacc.c */ #line 137 "../src/language/parse.y" {(yyval.val)=newopcall(OPdre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 42: /* Line 1806 of yacc.c */ #line 138 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuce,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 43: /* Line 1806 of yacc.c */ #line 139 "../src/language/parse.y" {(yyval.val)=newopcall(OPmode,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 44: /* Line 1806 of yacc.c */ #line 140 "../src/language/parse.y" {(yyval.val)=newopcall(OPsle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 45: /* Line 1806 of yacc.c */ #line 141 "../src/language/parse.y" {(yyval.val)=newopcall(OPsre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 46: /* Line 1806 of yacc.c */ #line 142 "../src/language/parse.y" {(yyval.val)=newopcall(OPpe,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 47: /* Line 1806 of yacc.c */ #line 143 "../src/language/parse.y" {(yyval.val)=newopcall(OPse,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 48: /* Line 1806 of yacc.c */ #line 144 "../src/language/parse.y" {(yyval.val)=newopcall(OPnb,(yyvsp[(2) - (2)].val),-1,&(yyloc));} break; case 49: /* Line 1806 of yacc.c */ #line 145 "../src/language/parse.y" {(yyval.val)=newopcall(OPlength,(yyvsp[(2) - (2)].val),-1,&(yyloc));} break; case 50: /* Line 1806 of yacc.c */ #line 146 "../src/language/parse.y" {(yyval.val)=newopcall(OPor,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 51: /* Line 1806 of yacc.c */ #line 147 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 52: /* Line 1806 of yacc.c */ #line 148 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 53: /* Line 1806 of yacc.c */ #line 149 "../src/language/parse.y" {(yyval.val)=newopcall(OPid,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 54: /* Line 1806 of yacc.c */ #line 150 "../src/language/parse.y" {(yyval.val)=newopcall(OPeq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 55: /* Line 1806 of yacc.c */ #line 151 "../src/language/parse.y" {(yyval.val)=newopcall(OPne,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 56: /* Line 1806 of yacc.c */ #line 152 "../src/language/parse.y" {(yyval.val)=newopcall(OPge,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 57: /* Line 1806 of yacc.c */ #line 153 "../src/language/parse.y" {(yyval.val)=newopcall(OPg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 58: /* Line 1806 of yacc.c */ #line 154 "../src/language/parse.y" {(yyval.val)=newopcall(OPle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 59: /* Line 1806 of yacc.c */ #line 155 "../src/language/parse.y" {(yyval.val)=newopcall(OPl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 60: /* Line 1806 of yacc.c */ #line 156 "../src/language/parse.y" {(yyval.val)=newopcall(OPs,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 61: /* Line 1806 of yacc.c */ #line 157 "../src/language/parse.y" {(yyval.val)=newopcall(OPp,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 62: /* Line 1806 of yacc.c */ #line 158 "../src/language/parse.y" {(yyval.val)=newopcall(OPsl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 63: /* Line 1806 of yacc.c */ #line 159 "../src/language/parse.y" {(yyval.val)=newopcall(OPsr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 64: /* Line 1806 of yacc.c */ #line 160 "../src/language/parse.y" {(yyval.val)=newopcall(OPmod,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 65: /* Line 1806 of yacc.c */ #line 161 "../src/language/parse.y" {(yyval.val)=newopcall(OPdr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 66: /* Line 1806 of yacc.c */ #line 162 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 67: /* Line 1806 of yacc.c */ #line 163 "../src/language/parse.y" {(yyval.val)=newopcall(OPd,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 68: /* Line 1806 of yacc.c */ #line 164 "../src/language/parse.y" {(yyval.val)=newopcall(OPm,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 69: /* Line 1806 of yacc.c */ #line 165 "../src/language/parse.y" {(yyval.val)=(yyvsp[(2) - (2)].val);} break; case 70: /* Line 1806 of yacc.c */ #line 166 "../src/language/parse.y" {(yyval.val)=newopcall(OPn,(yyvsp[(2) - (2)].val),-1,&(yyloc));} break; case 71: /* Line 1806 of yacc.c */ #line 167 "../src/language/parse.y" {(yyval.val)=newopcall(OPpow,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 72: /* Line 1806 of yacc.c */ #line 168 "../src/language/parse.y" {(yyval.val)=newopcall(OPtrans,(yyvsp[(1) - (2)].val),-1,&(yyloc));} break; case 73: /* Line 1806 of yacc.c */ #line 169 "../src/language/parse.y" {(yyval.val)=newopcall(OPderiv,(yyvsp[(1) - (2)].val),-1,&(yyloc));} break; case 74: /* Line 1806 of yacc.c */ #line 170 "../src/language/parse.y" {(yyval.val)=newopcall(OPfact,(yyvsp[(1) - (2)].val),-1,&(yyloc));} break; case 75: /* Line 1806 of yacc.c */ #line 171 "../src/language/parse.y" {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));} break; case 76: /* Line 1806 of yacc.c */ #line 172 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 77: /* Line 1806 of yacc.c */ #line 173 "../src/language/parse.y" {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),0,&(yyloc));} break; case 78: /* Line 1806 of yacc.c */ #line 174 "../src/language/parse.y" {(yyval.val)=(yyvsp[(2) - (3)].val);} break; case 79: /* Line 1806 of yacc.c */ #line 177 "../src/language/parse.y" {(yyval.val)=newnode(Fentry,newconst(CSTentry,&(yylsp[(1) - (1)])),-1,&(yyloc));} break; case 80: /* Line 1806 of yacc.c */ #line 178 "../src/language/parse.y" {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(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));} break; case 82: /* Line 1806 of yacc.c */ #line 182 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} 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));} break; case 84: /* Line 1806 of yacc.c */ #line 186 "../src/language/parse.y" {(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));} break; case 86: /* Line 1806 of yacc.c */ #line 190 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,-1,-1,&(yyloc));} break; case 87: /* Line 1806 of yacc.c */ #line 191 "../src/language/parse.y" {(yyval.val)=newopcall(OPrange,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));} break; case 88: /* Line 1806 of yacc.c */ #line 192 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,-1,-1,&(yyloc));} break; case 89: /* Line 1806 of yacc.c */ #line 193 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,(yyvsp[(2) - (3)].val),-1,&(yyloc));} break; case 90: /* Line 1806 of yacc.c */ #line 194 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,(yyvsp[(2) - (3)].val),-1,&(yyloc));} break; case 91: /* Line 1806 of yacc.c */ #line 195 "../src/language/parse.y" {(yyval.val)=-1; YYABORT;} 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));} break; case 93: /* Line 1806 of yacc.c */ #line 201 "../src/language/parse.y" {(yyval.val)=newopcall(OPcompr,(yyvsp[(1) - (1)].val),-2,&(yyloc));} break; case 94: /* Line 1806 of yacc.c */ #line 202 "../src/language/parse.y" {(yyval.val)=newopcall3(OPcompr,(yyvsp[(1) - (3)].val),-2,(yyvsp[(3) - (3)].val),&(yyloc));} break; case 95: /* Line 1806 of yacc.c */ #line 203 "../src/language/parse.y" {(yyval.val)=newopcall(OPcomprc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].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));} 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));} break; case 98: /* Line 1806 of yacc.c */ #line 210 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 99: /* Line 1806 of yacc.c */ #line 211 "../src/language/parse.y" {(yyval.val)=newnode(Frefarg,(yyvsp[(2) - (2)].val),-1,&(yyloc));} break; case 100: /* Line 1806 of yacc.c */ #line 212 "../src/language/parse.y" {if (!pari_once) { yyerrok; } pari_once=1;} break; case 101: /* Line 1806 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));} break; case 102: /* Line 1806 of yacc.c */ #line 216 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);} break; case 103: /* Line 1806 of yacc.c */ #line 217 "../src/language/parse.y" {(yyval.val)=newnode(Flistarg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 104: /* Line 1806 of yacc.c */ #line 220 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTentry,&(yylsp[(1) - (4)])),(yyvsp[(3) - (4)].val),&(yyloc));} break; case 105: /* Line 1806 of yacc.c */ #line 223 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),(yyvsp[(1) - (3)].val),&(yyloc));} break; case 106: /* Line 1806 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));} break; case 107: /* Line 1806 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));} break; case 108: /* Line 1806 of yacc.c */ #line 230 "../src/language/parse.y" {(yyval.val)=newnode(Flambda, (yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));} break; case 109: /* Line 1806 of yacc.c */ #line 231 "../src/language/parse.y" {(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" 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); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; *++yylsp = yyloc; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | 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) { ++yynerrs; #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; } # undef YYSYNTAX_ERROR #endif } yyerror_range[1] = yylloc; if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, &yylloc, lex); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yyerror_range[1] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, lex); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; yyerror_range[2] = yylloc; /* Using YYLLOC is tempting, but would change the location of the lookahead. YYLOC is available though. */ YYLLOC_DEFAULT (yyloc, yyerror_range, 2); *++yylsp = yyloc; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (&yylloc, lex, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif 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); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, yylsp, lex); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 2067 of yacc.c */ #line 234 "../src/language/parse.y" pari-2.7.5/src/language/init.c0000644000175000017500000017153012533333715014603 0ustar billbill/* Copyright (C) 2000-2003 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. */ /*******************************************************************/ /* */ /* INITIALIZING THE SYSTEM, ERRORS, STACK MANAGEMENT */ /* */ /*******************************************************************/ #include #if defined(_WIN32) || defined(__CYGWIN32__) # include "../systems/mingw/mingw.h" # ifndef WINCE # include # endif #endif #include "pari.h" #include "paripriv.h" #include "anal.h" const double LOG2 = 0.6931471805599453; /* log(2) */ const double LOG10_2 = 0.3010299956639812; /* log_10(2) */ const double LOG2_10 = 3.321928094887362; /* log_2(10) */ GEN gnil, gen_0, gen_1, gen_m1, gen_2, gen_m2, ghalf, err_e_STACK; static const ulong readonly_constants[] = { evaltyp(t_INT) | _evallg(2), /* gen_0 */ evallgefint(2), evaltyp(t_INT) | _evallg(2), /* gnil */ evallgefint(2), evaltyp(t_INT) | _evallg(3), /* gen_1 */ evalsigne(1) | evallgefint(3), 1, evaltyp(t_INT) | _evallg(3), /* gen_2 */ evalsigne(1) | evallgefint(3), 2, evaltyp(t_INT) | _evallg(3), /* gen_m1 */ evalsigne(-1) | evallgefint(3), 1, evaltyp(t_INT) | _evallg(3), /* gen_m2 */ evalsigne(-1) | evallgefint(3), 2, }; static const long readonly_ghalf[] = { evaltyp(t_FRAC) | _evallg(3), /* ghalf */ (long)(readonly_constants+4), (long)(readonly_constants+7) }; static const ulong readonly_err_STACK[] = { evaltyp(t_ERROR) | _evallg(2), e_STACK }; THREAD GEN bernzone; GEN primetab; /* private primetable */ byteptr diffptr; FILE *pari_outfile, *pari_errfile, *pari_logfile, *pari_infile; char *current_logfile, *current_psfile, *pari_datadir; long gp_colors[c_LAST]; int disable_color; ulong DEBUGFILES, DEBUGLEVEL, DEBUGMEM; long DEBUGVAR; ulong pari_mt_nbthreads; ulong compatible, precreal, precdl, logstyle; gp_data *GP_DATA; GEN pari_colormap, pari_graphcolors; entree **varentries; THREAD pari_sp bot, top, avma; THREAD size_t memused; static void ** MODULES, ** OLDMODULES; static pari_stack s_MODULES, s_OLDMODULES; const long functions_tblsz = 135; /* size of functions_hash */ entree **functions_hash, **defaults_hash; void (*cb_pari_ask_confirm)(const char *); int (*cb_pari_handle_exception)(long); 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); const char * pari_library_path = NULL; static THREAD GEN global_err_data; THREAD jmp_buf *iferr_env; const long CATCH_ALL = -1; /*********************************************************************/ /* */ /* BLOCKS & CLONES */ /* */ /*********************************************************************/ /*#define DEBUG*/ static THREAD long next_block; static THREAD GEN cur_block; /* current block in block list */ #ifdef DEBUG static THREAD long NUM; #endif static void pari_init_blocks(void) { next_block = 0; cur_block = NULL; #ifdef DEBUG NUM = 0; #endif } static void pari_close_blocks(void) { while (cur_block) killblock(cur_block); } /* Return x, where: * x[-4]: reference count * x[-3]: adress of next block * x[-2]: adress of preceding block. * x[-1]: number of allocated blocs. * x[0..n-1]: malloc-ed memory. */ GEN newblock(size_t n) { long *x = (long *) pari_malloc((n + BL_HEAD)*sizeof(long)) + BL_HEAD; bl_refc(x) = 1; bl_next(x) = NULL; bl_prev(x) = cur_block; bl_num(x) = next_block++; if (cur_block) bl_next(cur_block) = x; #ifdef DEBUG err_printf("+ %ld\n", ++NUM); #endif if (DEBUGMEM) { if (!n) pari_warn(warner,"mallocing NULL object in newblock"); if (DEBUGMEM > 2) err_printf("new block, size %6lu (no %ld): %08lx\n", n, next_block-1, x); } return cur_block = x; } GEN gcloneref(GEN x) { if (isclone(x)) { ++bl_refc(x); return x; } else return gclone(x); } void gclone_refc(GEN x) { ++bl_refc(x); } void gunclone(GEN x) { if (--bl_refc(x) > 0) return; BLOCK_SIGINT_START; if (bl_next(x)) bl_prev(bl_next(x)) = bl_prev(x); else { cur_block = bl_prev(x); next_block = bl_num(x); } if (bl_prev(x)) bl_next(bl_prev(x)) = bl_next(x); if (DEBUGMEM > 2) err_printf("killing block (no %ld): %08lx\n", bl_num(x), x); free((void*)bl_base(x)); /* pari_free not needed: we already block */ BLOCK_SIGINT_END; #ifdef DEBUG err_printf("- %ld\n", NUM--); #endif } /* Recursively look for clones in the container and kill them. Then kill * container if clone. SIGINT could be blocked until it returns */ void gunclone_deep(GEN x) { long i, lx; GEN v; if (isclone(x) && bl_refc(x) > 1) { --bl_refc(x); return; } BLOCK_SIGINT_START; switch(typ(x)) { case t_VEC: case t_COL: case t_MAT: lx = lg(x); for (i=1;ivalue; if (bl_num(x) < loc) return 0; /* older */ if (DEBUGMEM>2) err_printf("popping %s (block no %ld)\n", ep->name, bl_num(x)); gunclone_deep(x); return 1; } /*********************************************************************/ /* */ /* C STACK SIZE CONTROL */ /* */ /*********************************************************************/ /* Avoid core dump on deep recursion. Adapted Perl code by Dominic Dunlop */ THREAD void *PARI_stack_limit = NULL; #ifdef STACK_CHECK # ifdef __EMX__ /* Emulate */ void pari_stackcheck_init(void *pari_stack_base) { (void) pari_stack_base; if (!pari_stack_base) { PARI_stack_limit = NULL; return; } PARI_stack_limit = get_stack(1./16, 32*1024); } # else /* !__EMX__ */ #include #include #include /* Set PARI_stack_limit to (a little above) the lowest safe address that can be * used on the stack. Leave PARI_stack_limit at its initial value (NULL) to * show no check should be made [init failed]. Assume stack grows downward. */ void pari_stackcheck_init(void *pari_stack_base) { struct rlimit rip; ulong size; if (!pari_stack_base) { PARI_stack_limit = NULL; return; } if (getrlimit(RLIMIT_STACK, &rip)) return; size = rip.rlim_cur; if (size == (ulong)RLIM_INFINITY || size > (ulong)pari_stack_base) PARI_stack_limit = (void*)(((ulong)pari_stack_base) / 16); else PARI_stack_limit = (void*)((ulong)pari_stack_base - (size/16)*15); } # endif /* !__EMX__ */ #else void pari_stackcheck_init(void *pari_stack_base) { (void) pari_stack_base; PARI_stack_limit = NULL; } #endif /* STACK_CHECK */ /*******************************************************************/ /* HEAP TRAVERSAL */ /*******************************************************************/ struct getheap_t { long n, l; }; static void f_getheap(GEN x, void *D) { struct getheap_t *T = (struct getheap_t*)D; T->n++; T->l += gsizeword(x); } GEN getheap(void) { struct getheap_t T = { 0, 0 }; traverseheap(&f_getheap, &T); return mkvec2s(T.n, T.l + BL_HEAD * T.n); } void traverseheap( void(*f)(GEN, void *), void *data ) { GEN x; for (x = cur_block; x; x = bl_prev(x)) f(x, data); } /*********************************************************************/ /* DAEMON / FORK */ /*********************************************************************/ #if defined(HAS_WAITPID) && defined(HAS_SETSID) # include /* Properly fork a process, detaching from main process group without creating * zombies on exit. Parent returns 1, son returns 0 */ int pari_daemon(void) { pid_t pid = fork(); switch(pid) { case -1: return 1; /* father, fork failed */ case 0: (void)setsid(); /* son becomes process group leader */ if (fork()) exit(0); /* now son exits, also when fork fails */ break; /* grandson: its father is the son, which exited, * hence father becomes 'init', that'll take care of it */ default: /* father, fork succeeded */ (void)waitpid(pid,NULL,0); /* wait for son to exit, immediate */ return 1; } /* grandson */ return 0; } #else int pari_daemon(void) { pari_err_IMPL("pari_daemon without waitpid & setsid"); return 0; } #endif /*********************************************************************/ /* */ /* SYSTEM INITIALIZATION */ /* */ /*********************************************************************/ static int try_to_recover = 0; THREAD VOLATILE int PARI_SIGINT_block = 0, PARI_SIGINT_pending = 0; static void pari_sighandler(int sig); /*********************************************************************/ /* SIGNAL HANDLERS */ /*********************************************************************/ static void dflt_sigint_fun(void) { pari_err(e_MISC, "user interrupt"); } #if defined(_WIN32) || defined(__CYGWIN32__) int win32ctrlc = 0; void dowin32ctrlc(void) { win32ctrlc = 0; cb_pari_sigint(); } #endif static void pari_handle_SIGINT(void) { #ifdef _WIN32 if (++win32ctrlc >= 5) _exit(3); #else cb_pari_sigint(); #endif } static void pari_sighandler(int sig) { const char *msg; #ifndef HAS_SIGACTION /*SYSV reset the signal handler in the handler*/ (void)os_signal(sig,pari_sighandler); #endif switch(sig) { #ifdef SIGBREAK case SIGBREAK: if (PARI_SIGINT_block==1) { PARI_SIGINT_pending=SIGBREAK; mt_sigint(); } else pari_handle_SIGINT(); return; #endif #ifdef SIGINT case SIGINT: if (PARI_SIGINT_block==1) { PARI_SIGINT_pending=SIGINT; mt_sigint(); } else pari_handle_SIGINT(); return; #endif #ifdef SIGSEGV case SIGSEGV: msg="PARI/GP (Segmentation Fault)"; break; #endif #ifdef SIGBUS case SIGBUS: msg="PARI/GP (Bus Error)"; break; #endif #ifdef SIGFPE case SIGFPE: msg="PARI/GP (Floating Point Exception)"; break; #endif #ifdef SIGPIPE case SIGPIPE: { pariFILE *f = GP_DATA->pp->file; if (f && pari_outfile == f->file) { GP_DATA->pp->file = NULL; /* to avoid oo recursion on error */ pari_outfile = stdout; pari_fclose(f); pari_err(e_MISC, "Broken Pipe, resetting file stack..."); } return; /* not reached */ } #endif default: msg="signal handling"; break; } pari_err_BUG(msg); } void pari_sig_init(void (*f)(int)) { #ifdef SIGBUS (void)os_signal(SIGBUS,f); #endif #ifdef SIGFPE (void)os_signal(SIGFPE,f); #endif #ifdef SIGINT (void)os_signal(SIGINT,f); #endif #ifdef SIGBREAK (void)os_signal(SIGBREAK,f); #endif #ifdef SIGPIPE (void)os_signal(SIGPIPE,f); #endif #ifdef SIGSEGV (void)os_signal(SIGSEGV,f); #endif } /*********************************************************************/ /* STACK AND UNIVERSAL CONSTANTS */ /*********************************************************************/ static void init_universal_constants(void) { gen_0 = (GEN)readonly_constants; gnil = (GEN)readonly_constants+2; gen_1 = (GEN)readonly_constants+4; gen_2 = (GEN)readonly_constants+7; gen_m1 = (GEN)readonly_constants+10; gen_m2 = (GEN)readonly_constants+13; ghalf = (GEN)readonly_ghalf; 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) { iferr_env = NULL; 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 */ /*********************************************************************/ void pari_init_defaults(void) { long i; initout(1); #ifdef LONG_IS_64BIT precreal = 4; #else precreal = 5; #endif precdl = 16; compatible = NONE; DEBUGFILES = DEBUGLEVEL = DEBUGMEM = 0; disable_color = 1; logstyle = logstyle_none; current_psfile = pari_strdup("pari.ps"); current_logfile= pari_strdup("pari.log"); pari_logfile = NULL; pari_datadir = os_getenv("GP_DATA_DIR"); if (!pari_datadir) { #if defined(_WIN32) || defined(__CYGWIN32__) if (paricfg_datadir[0]=='@' && paricfg_datadir[1]==0) pari_datadir = win32_datadir(); else #endif pari_datadir = pari_strdup(paricfg_datadir); } else pari_datadir= pari_strdup(pari_datadir); for (i=0; inext; switch(EpVALENCE(ep)) { case EpVAR: case EpINSTALL: /* keep: attach it to last entree seen */ if (last) last->next = ep; else table[i] = ep; ep->next = NULL; last = ep; break; default: freeep(ep); } ep = EP; } } } /* Load in hashtable hash the modules contained in A */ static int gp_init_entrees(pari_stack *p_A, entree **hash) { long i; entree **v = (entree **)*pari_stack_base(p_A); init_hashtable(hash, functions_tblsz); for (i = 0; i < p_A->n; i++) pari_fill_hashtable(hash, v[i]); return (hash == functions_hash); } int gp_init_functions(void) { return gp_init_entrees(new_fun_set? &s_MODULES: &s_OLDMODULES, functions_hash); } extern entree functions_basic[], functions_default[]; static void 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); defaults_hash = (entree**) pari_calloc(sizeof(entree*)*functions_tblsz); pari_add_defaults_module(functions_default); } void pari_add_module(entree *ep) { if (new_fun_set) pari_fill_hashtable(functions_hash, ep); pari_stack_pushp(&s_MODULES, ep); } void pari_add_defaults_module(entree *ep) { pari_fill_hashtable(defaults_hash, ep); } void pari_add_oldmodule(entree *ep) { if (!new_fun_set) pari_fill_hashtable(functions_hash, ep); pari_stack_pushp(&s_OLDMODULES, ep); } /*********************************************************************/ /* PARI THREAD */ /*********************************************************************/ static void pari_mainstack_alloc(struct pari_mainstack *st, size_t s) { st->bot = (pari_sp)pari_malloc(s); st->avma = st->top = st->bot+s; st->memused = 0; } static void pari_mainstack_free(struct pari_mainstack *st) { pari_free((void*)st->bot); st->avma = st->top = st->bot = 0; } static void pari_mainstack_use(struct pari_mainstack *st) { bot = st->bot; top = st->top; avma = st->avma; memused = st->memused; } /* Initial PARI thread structure t with a stack of size s and * argument arg */ void pari_thread_alloc(struct pari_thread *t, size_t s, GEN arg) { pari_mainstack_alloc(&t->st,s); t->data = arg; } void pari_thread_free(struct pari_thread *t) { pari_mainstack_free(&t->st); } void pari_thread_init(void) { pari_init_blocks(); pari_init_errcatch(); pari_init_rand(); pari_init_floats(); pari_init_parser(); pari_init_compiler(); pari_init_evaluator(); pari_init_files(); } void pari_thread_close(void) { pari_close_files(); pari_close_evaluator(); pari_close_compiler(); pari_close_parser(); pari_close_floats(); pari_close_blocks(); } GEN pari_thread_start(struct pari_thread *t) { pari_mainstack_use(&t->st); pari_thread_init(); return t->data; } /*********************************************************************/ /* LIBPARI INIT / CLOSE */ /*********************************************************************/ static void pari_exit(void) { err_printf(" *** Error in the PARI system. End of program.\n"); exit(1); } static void dflt_err_recover(long errnum) { (void) errnum; pari_exit(); } /* 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_whatnow = NULL; cb_pari_pre_recover = NULL; cb_pari_sigint = dflt_sigint_fun; if (init_opts&INIT_JMPm) cb_pari_err_recover = dflt_err_recover; pari_stackcheck_init(&u); pari_init_homedir(); if (init_opts&INIT_DFTm) { pari_init_defaults(); GP_DATA = default_gp_data(); gp_expand_path(GP_DATA->path); } if (init_opts&INIT_SIGm) pari_sig_init(pari_sighandler); pari_init_stack(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(); (void)getabstime(); try_to_recover = 1; if (!(init_opts&INIT_noIMTm)) pari_mt_init(); } void pari_init(size_t parisize, ulong maxprime) { pari_init_opts(parisize, maxprime, INIT_JMPm | INIT_SIGm | INIT_DFTm); } void pari_close_opts(ulong init_opts) { long i; BLOCK_SIGINT_START; 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]; while (ep) { entree *EP = ep->next; if (!EpSTATIC(ep)) { freeep(ep); free(ep); } ep = EP; } } free((void*)varentries); free((void*)primetab); pari_close_seadata(); pari_thread_close(); pari_kernel_close(); free((void*)functions_hash); free((void*)defaults_hash); free((void*)bot); if (diffptr) free((void*)diffptr); free(current_logfile); free(current_psfile); pari_stack_delete(&s_MODULES); pari_stack_delete(&s_OLDMODULES); pari_close_homedir(); if (pari_datadir) free(pari_datadir); if (init_opts&INIT_DFTm) { /* delete GP_DATA */ if (GP_DATA->hist->v) free((void*)GP_DATA->hist->v); if (GP_DATA->pp->cmd) free((void*)GP_DATA->pp->cmd); delete_dirs(GP_DATA->path); free((void*)GP_DATA->path->PATH); } BLOCK_SIGINT_END; } void pari_close(void) { pari_close_opts(INIT_JMPm | INIT_SIGm | INIT_DFTm); } /*******************************************************************/ /* */ /* ERROR RECOVERY */ /* */ /*******************************************************************/ void gp_context_save(struct gp_context* rec) { rec->file = pari_last_tmp_file(); if (DEBUGFILES>1) err_printf("gp_context_save: %s\n", rec->file ? rec->file->name: "NULL"); rec->prettyp = GP_DATA->fmt->prettyp; rec->listloc = next_block; rec->iferr_env = iferr_env; rec->err_data = global_err_data; evalstate_save(&rec->eval); parsestate_save(&rec->parse); } void gp_context_restore(struct gp_context* rec) { long i; if (!try_to_recover) return; /* disable gp_context_restore() and SIGINT */ try_to_recover = 0; BLOCK_SIGINT_START if (DEBUGMEM>2) err_printf("entering recover(), loc = %ld\n", rec->listloc); evalstate_restore(&rec->eval); parsestate_restore(&rec->parse); filestate_restore(rec->file); global_err_data = rec->err_data; iferr_env = rec->iferr_env; GP_DATA->fmt->prettyp = rec->prettyp; for (i = 0; i < functions_tblsz; i++) { entree *ep = functions_hash[i]; while (ep) { entree *EP = ep->next; switch(EpVALENCE(ep)) { case EpVAR: while (pop_val_if_newer(ep,rec->listloc)) /* empty */; break; case EpNEW: break; } ep = EP; } } if (DEBUGMEM>2) err_printf("leaving recover()\n"); BLOCK_SIGINT_END try_to_recover = 1; } static void err_recover(long numerr) { if (cb_pari_pre_recover) cb_pari_pre_recover(numerr); evalstate_reset(); killallfiles(); pari_init_errcatch(); out_puts(pariErr, "\n"); pariErr->flush(); cb_pari_err_recover(numerr); } static void err_init(void) { /* make sure pari_err msg starts at the beginning of line */ if (!pari_last_was_newline()) pari_putc('\n'); pariOut->flush(); pariErr->flush(); out_term_color(pariErr, c_ERR); } static void err_init_msg(int numerr, int user) { const char *gp_function_name; out_puts(pariErr, " *** "); if (numerr != user && (gp_function_name = closure_func_err())) out_printf(pariErr, "%s: ", gp_function_name); else out_puts(pariErr, " "); } void pari_warn(int numerr, ...) { char *ch1; va_list ap; va_start(ap,numerr); err_init(); err_init_msg(numerr, warnuser); switch (numerr) { case warnuser: out_puts(pariErr, "user warning: "); out_print0(pariErr, NULL, va_arg(ap, GEN), f_RAW); break; case warnmem: out_puts(pariErr, "collecting garbage in "); ch1=va_arg(ap, char*); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; case warner: out_puts(pariErr, "Warning: "); ch1=va_arg(ap, char*); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; case warnprec: out_vprintf(pariErr, "Warning: increasing prec in %s; new prec = %ld", ap); break; case warnfile: out_puts(pariErr, "Warning: failed to "), ch1 = va_arg(ap, char*); out_printf(pariErr, "%s: %s", ch1, va_arg(ap, char*)); break; } va_end(ap); out_term_color(pariErr, c_NONE); out_putc(pariErr, '\n'); pariErr->flush(); } void pari_sigint(const char *time_s) { int recover=0; BLOCK_SIGALRM_START err_init(); closure_err(0); err_init_msg(e_MISC, e_USER); out_puts(pariErr, "user interrupt after "); out_puts(pariErr, time_s); out_term_color(pariErr, c_NONE); pariErr->flush(); if (cb_pari_handle_exception) recover = cb_pari_handle_exception(-1); if (!recover && !block) PARI_SIGINT_pending = 0; BLOCK_SIGINT_END if (!recover) err_recover(e_MISC); } #define retmkerr2(x,y)\ do { GEN _v = cgetg(3, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkerr3(x,y,z)\ do { GEN _v = cgetg(4, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkerr4(x,y,z,t)\ do { GEN _v = cgetg(5, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkerr5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkerr6(x,y,z,t,u,v)\ do { GEN _v = cgetg(7, t_ERROR);\ _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) static GEN pari_err2GEN(long numerr, va_list ap) { switch ((enum err_list) numerr) { case e_SYNTAX: { const char *msg = va_arg(ap, char*); const char *s = va_arg(ap,char *); const char *entry = va_arg(ap,char *); retmkerr3(numerr,strtoGENstr(msg), mkvecsmall2((long)s,(long)entry)); } case e_MISC: case e_ALARM: { const char *ch1 = va_arg(ap, char*); retmkerr2(numerr, gvsprintf(ch1,ap)); } case e_NOTFUNC: case e_USER: retmkerr2(numerr,va_arg(ap, GEN)); case e_FILE: { const char *f = va_arg(ap, const char*); retmkerr3(numerr, strtoGENstr(f), strtoGENstr(va_arg(ap, char*))); } case e_OVERFLOW: case e_IMPL: case e_DIM: case e_CONSTPOL: case e_ROOTS0: case e_FLAG: case e_PREC: case e_BUG: case e_ARCH: case e_PACKAGE: retmkerr2(numerr, strtoGENstr(va_arg(ap, char*))); case e_MODULUS: case e_VAR: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); GEN y = va_arg(ap, GEN); retmkerr4(numerr, strtoGENstr(f), x,y); } case e_INV: case e_IRREDPOL: case e_PRIME: case e_SQRTN: case e_TYPE: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); retmkerr3(numerr, strtoGENstr(f), x); } case e_COPRIME: case e_OP: case e_TYPE2: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); GEN y = va_arg(ap, GEN); retmkerr4(numerr,strtoGENstr(f),x,y); } case e_COMPONENT: { const char *f= va_arg(ap, const char *); const char *op = va_arg(ap, const char *); GEN l = va_arg(ap, GEN); GEN x = va_arg(ap, GEN); retmkerr5(numerr,strtoGENstr(f),strtoGENstr(op),l,x); } case e_DOMAIN: { const char *f = va_arg(ap, const char*); const char *v = va_arg(ap, const char *); const char *op = va_arg(ap, const char *); GEN l = va_arg(ap, GEN); GEN x = va_arg(ap, GEN); retmkerr6(numerr,strtoGENstr(f),strtoGENstr(v),strtoGENstr(op),l,x); } case e_PRIORITY: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); const char *op = va_arg(ap, const char *); long v = va_arg(ap, long); retmkerr5(numerr,strtoGENstr(f),x,strtoGENstr(op),stoi(v)); } case e_MAXPRIME: retmkerr2(numerr, utoi(va_arg(ap, ulong))); case e_STACK: return err_e_STACK; default: return mkerr(numerr); } } static char * type_dim(GEN x) { char *v = stack_malloc(64); switch(typ(x)) { case t_MAT: { long l = lg(x), r = (l == 1)? 1: lgcols(x); sprintf(v, "t_MAT (%ldx%ld)", r-1,l-1); break; } case t_COL: sprintf(v, "t_COL (%ld elts)", lg(x)-1); break; case t_VEC: sprintf(v, "t_VEC (%ld elts)", lg(x)-1); break; default: v = (char*)type_name(typ(x)); } return v; } char * pari_err2str(GEN e) { long numerr = err_get_num(e); switch ((enum err_list) numerr) { case e_ALARM: return pari_sprintf("alarm interrupt after %Ps.",gel(e,2)); case e_MISC: return pari_sprintf("%Ps.",gel(e,2)); case e_ARCH: return pari_sprintf("sorry, '%Ps' not available on this system.",gel(e,2)); case e_BUG: return pari_sprintf("bug in %Ps, please report.",gel(e,2)); case e_CONSTPOL: return pari_sprintf("constant polynomial in %Ps.", gel(e,2)); case e_COPRIME: return pari_sprintf("elements not coprime in %Ps:\n %Ps\n %Ps", gel(e,2), gel(e,3), gel(e,4)); case e_DIM: return pari_sprintf("inconsistent dimensions in %Ps.", gel(e,2)); case e_FILE: return pari_sprintf("error opening %Ps: `%Ps'.", gel(e,2), gel(e,3)); case e_FLAG: return pari_sprintf("invalid flag in %Ps.", gel(e,2)); case e_IMPL: return pari_sprintf("sorry, %Ps is not yet implemented.", gel(e,2)); case e_PACKAGE: return pari_sprintf("package %Ps is required, please install it.", gel(e,2)); case e_INV: return pari_sprintf("impossible inverse in %Ps: %Ps.", gel(e,2), gel(e,3)); case e_IRREDPOL: return pari_sprintf("not an irreducible polynomial in %Ps: %Ps.", gel(e,2), gel(e,3)); case e_MAXPRIME: { const char * msg = "not enough precomputed primes"; ulong c = itou(gel(e,2)); if (c) return pari_sprintf("%s, need primelimit ~ %lu.",msg, c); else return pari_strdup(msg); } case e_MEM: return pari_strdup("not enough memory"); case e_MODULUS: { GEN x = gel(e,3), y = gel(e,4); return pari_sprintf("inconsistent moduli in %Ps: %Ps != %Ps", gel(e,2), x, y); } case e_NONE: return NULL; case e_NOTFUNC: return pari_strdup("not a function in function call"); case e_OP: case e_TYPE2: { pari_sp av = avma; char *v; const char *f, *op = GSTR(gel(e,2)); const char *what = numerr == e_OP? "inconsistent": "forbidden"; GEN x = gel(e,3); GEN y = gel(e,4); switch(*op) { case '+': f = "addition"; break; case '*': f = "multiplication"; break; case '/': case '%': case '\\': f = "division"; break; case '=': op = "-->"; f = "assignment"; break; default: f = op; op = ","; break; } v = pari_sprintf("%s %s %s %s %s.", what,f,type_dim(x),op,type_dim(y)); avma = av; return v; } case e_COMPONENT: { const char *f= GSTR(gel(e,2)); const char *op= GSTR(gel(e,3)); GEN l = gel(e,4); if (!*f) return pari_sprintf("non-existent component: index %s %Ps",op,l); return pari_sprintf("non-existent component in %s: index %s %Ps",f,op,l); } case e_DOMAIN: { const char *f = GSTR(gel(e,2)); const char *v = GSTR(gel(e,3)); const char *op= GSTR(gel(e,4)); GEN l = gel(e,5); if (!*op) return pari_sprintf("domain error in %s: %s out of range",f,v); return pari_sprintf("domain error in %s: %s %s %Ps",f,v,op,l); } case e_PRIORITY: { const char *f = GSTR(gel(e,2)); long vx = gvar(gel(e,3)); const char *op= GSTR(gel(e,4)); long v = itos(gel(e,5)); return pari_sprintf("incorrect priority in %s: variable %Ps %s %Ps",f, pol_x(vx), op, pol_x(v)); } case e_OVERFLOW: return pari_sprintf("overflow in %Ps.", gel(e,2)); case e_PREC: return pari_sprintf("precision too low in %Ps.", gel(e,2)); case e_PRIME: return pari_sprintf("not a prime number in %Ps: %Ps.", gel(e,2), gel(e,3)); case e_ROOTS0: return pari_sprintf("zero polynomial in %Ps.", gel(e,2)); case e_SQRTN: return pari_sprintf("not an n-th power residue in %Ps: %Ps.", gel(e,2), gel(e,3)); case e_STACK: { size_t d = top - bot; 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.); return buf; } case e_SYNTAX: return pari_strdup(GSTR(gel(e,2))); case e_TYPE: return pari_sprintf("incorrect type in %Ps (%s).", gel(e,2), type_name(typ(gel(e,3)))); case e_USER: return pari_sprint0("user error: ", gel(e,2), f_RAW); case e_VAR: { GEN x = gel(e,3), y = gel(e,4); return pari_sprintf("inconsistent variables in %Ps, %Ps != %Ps.", gel(e,2), pol_x(varn(x)), pol_x(varn(y))); } } return NULL; /*NOT REACHED*/ } static void pari_err_display(GEN err) { long numerr=err_get_num(err); 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); err_init_msg(numerr, e_USER); pariErr->puts(s); if (numerr==e_NOTFUNC) { GEN fun = gel(err,2); if (gequalX(fun)) { entree *ep = varentries[varn(fun)]; const char *s = ep->name; if (cb_pari_whatnow) cb_pari_whatnow(pariErr,s,1); } } pari_free(s); } } void pari_err(int numerr, ...) { va_list ap; GEN E; va_start(ap,numerr); if (numerr) E = pari_err2GEN(numerr,ap); else { E = va_arg(ap,GEN); numerr = err_get_num(E); } 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_handle_exception && cb_pari_handle_exception(numerr)) return; err_recover(numerr); } GEN pari_err_last(void) { return global_err_data; } const char * numerr_name(long numerr) { switch ((enum err_list) numerr) { case e_ALARM: return "e_ALARM"; case e_ARCH: return "e_ARCH"; case e_BUG: return "e_BUG"; case e_COMPONENT: return "e_COMPONENT"; case e_CONSTPOL: return "e_CONSTPOL"; case e_COPRIME: return "e_COPRIME"; case e_DIM: return "e_DIM"; case e_DOMAIN: return "e_DOMAIN"; case e_FILE: return "e_FILE"; case e_FLAG: return "e_FLAG"; case e_IMPL: return "e_IMPL"; case e_INV: return "e_INV"; case e_IRREDPOL: return "e_IRREDPOL"; case e_MAXPRIME: return "e_MAXPRIME"; case e_MEM: return "e_MEM"; case e_MISC: return "e_MISC"; case e_MODULUS: return "e_MODULUS"; case e_NONE: return "e_NONE"; case e_NOTFUNC: return "e_NOTFUNC"; case e_OP: return "e_OP"; case e_OVERFLOW: return "e_OVERFLOW"; case e_PACKAGE: return "e_PACKAGE"; case e_PREC: return "e_PREC"; case e_PRIME: return "e_PRIME"; case e_PRIORITY: return "e_PRIORITY"; case e_ROOTS0: return "e_ROOTS0"; case e_SQRTN: return "e_SQRTN"; case e_STACK: return "e_STACK"; case e_SYNTAX: return "e_SYNTAX"; case e_TYPE2: return "e_TYPE2"; case e_TYPE: return "e_TYPE"; case e_USER: return "e_USER"; case e_VAR: return "e_VAR"; } return "invalid error number"; } long name_numerr(const char *s) { if (!strcmp(s,"e_ALARM")) return e_ALARM; if (!strcmp(s,"e_ARCH")) return e_ARCH; if (!strcmp(s,"e_BUG")) return e_BUG; if (!strcmp(s,"e_COMPONENT")) return e_COMPONENT; if (!strcmp(s,"e_CONSTPOL")) return e_CONSTPOL; if (!strcmp(s,"e_COPRIME")) return e_COPRIME; if (!strcmp(s,"e_DIM")) return e_DIM; if (!strcmp(s,"e_DOMAIN")) return e_DOMAIN; if (!strcmp(s,"e_FILE")) return e_FILE; if (!strcmp(s,"e_FLAG")) return e_FLAG; if (!strcmp(s,"e_IMPL")) return e_IMPL; if (!strcmp(s,"e_INV")) return e_INV; if (!strcmp(s,"e_IRREDPOL")) return e_IRREDPOL; if (!strcmp(s,"e_MAXPRIME")) return e_MAXPRIME; if (!strcmp(s,"e_MEM")) return e_MEM; if (!strcmp(s,"e_MISC")) return e_MISC; if (!strcmp(s,"e_MODULUS")) return e_MODULUS; if (!strcmp(s,"e_NONE")) return e_NONE; if (!strcmp(s,"e_NOTFUNC")) return e_NOTFUNC; if (!strcmp(s,"e_OP")) return e_OP; if (!strcmp(s,"e_OVERFLOW")) return e_OVERFLOW; if (!strcmp(s,"e_PACKAGE")) return e_PACKAGE; if (!strcmp(s,"e_PREC")) return e_PREC; if (!strcmp(s,"e_PRIME")) return e_PRIME; if (!strcmp(s,"e_PRIORITY")) return e_PRIORITY; if (!strcmp(s,"e_ROOTS0")) return e_ROOTS0; if (!strcmp(s,"e_SQRTN")) return e_SQRTN; if (!strcmp(s,"e_STACK")) return e_STACK; if (!strcmp(s,"e_SYNTAX")) return e_SYNTAX; if (!strcmp(s,"e_TYPE")) return e_TYPE; if (!strcmp(s,"e_TYPE2")) return e_TYPE2; if (!strcmp(s,"e_USER")) return e_USER; if (!strcmp(s,"e_VAR")) return e_VAR; pari_err(e_MISC,"unknown error name"); return -1; /* NOT REACHED */ } GEN errname(GEN err) { if (typ(err)!=t_ERROR) pari_err_TYPE("errname",err); return strtoGENstr(numerr_name(err_get_num(err))); } /* Try f (trapping error e), recover using r (break_loop, if NULL) */ GEN trap0(const char *e, GEN r, GEN f) { long numerr = CATCH_ALL; GEN x; if (!e || !*e) numerr = CATCH_ALL; else numerr = name_numerr(e); if (!f) { pari_warn(warner,"default handlers are no longer supported --> ignored"); return gnil; } x = closure_trapgen(f, numerr); if (x == (GEN)1L) x = r? closure_evalgen(r): gnil; return x; } /*******************************************************************/ /* */ /* CLONING & COPY */ /* Replicate an existing GEN */ /* */ /*******************************************************************/ /* 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 }; static GEN list_internal_copy(GEN z, long nmax) { long i, l; GEN a; 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) ); a[0] = z[0]; return a; } static void listassign(GEN x, GEN y) { long nmax = list_nmax(x); GEN L = list_data(x); if (!nmax && L) nmax = lg(L) + 32; /* not malloc'ed yet */ list_nmax(y) = nmax; list_data(y) = list_internal_copy(L, nmax); } /* copy list on the PARI stack */ GEN listcopy(GEN x) { GEN y = listcreate(), L = list_data(x); if (L) list_data(y) = gcopy(L); return y; } GEN gcopy(GEN x) { long tx = typ(x), lx, i; GEN y; switch(tx) { /* non recursive types */ case t_INT: return signe(x)? icopy(x): gen_0; case t_REAL: case t_STR: case t_VECSMALL: return leafcopy(x); /* one more special case */ case t_LIST: return listcopy(x); } y = cgetg_copy(x, &lx); if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; } for (; icanon = 0; p->len = t; p->x = gcopy_av0(x, &AVMA); p->base= (GEN)AVMA; return p; } /* same, writing t_INT in canonical native form */ GENbin* copy_bin_canon(GEN x) { long t = taille0(x); GENbin *p = (GENbin*)pari_malloc(sizeof(GENbin) + t*sizeof(long)); pari_sp AVMA = (pari_sp)(GENbinbase(p) + t); p->canon = 1; p->len = t; p->x = gcopy_av0_canon(x, &AVMA); p->base= (GEN)AVMA; return p; } GEN gclone(GEN x) { long i,lx,tx = typ(x), t = words_to_allocate(x); GEN y = newblock(t); switch(tx) { /* non recursive types */ case t_INT: lx = lgefint(x); y[0] = evaltyp(t_INT)|evallg(lx); for (i=1; i y) { lswap(*x, *y); x = int_precW(x); y++; } break; } case t_REAL: case t_STR: case t_VECSMALL: break; /* one more special case */ case t_LIST: { GEN Lx = list_data(x); if (Lx) { pari_sp av = avma; GEN L = (GEN)((long)Lx+dec); shiftaddress_canon(L, dec); list_data(x) = list_internal_copy(L, lg(L)); avma = av; } } default: lx = lg(x); for (i=lontyp[tx]; i= lg(v)) pari_err_TYPE("obj_check", S); O = gel(v,K); return isintzero(O)? NULL: O; } GEN obj_checkbuild(GEN S, long tag, GEN (*build)(GEN)) { GEN O = obj_check(S, tag); if (!O) { pari_sp av = avma; O = obj_insert(S, tag, build(S)); avma = av; } return O; } GEN obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), 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)); avma = av; return gcopy(w); } 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); } /* Reset S [last position], freeing all clones */ void obj_free(GEN S) { GEN v = gel(S, lg(S)-1); long i; if (typ(v) != t_VEC) pari_err_TYPE("obj_free", S); for (i = 1; i < lg(v); i++) { GEN o = gel(v,i); if (isclone(o)) gunclone(o); gel(v,i) = gen_0; } } /*******************************************************************/ /* */ /* STACK MANAGEMENT */ /* */ /*******************************************************************/ INLINE void dec_gerepile(pari_sp *x, pari_sp av0, pari_sp av, pari_sp tetpil, size_t dec) { if (*x < av && *x >= av0) { /* update address if in stack */ if (*x < tetpil) *x += dec; else pari_err_BUG("gerepile, significant pointers lost"); } } void gerepileallsp(pari_sp av, pari_sp tetpil, int n, ...) { const pari_sp av0 = avma; const size_t dec = av-tetpil; int i; va_list a; va_start(a, n); (void)gerepile(av,tetpil,NULL); for (i=0; i av) { pari_warn(warner,"bad object %Ps",x); return 0; } tx = typ(x); if (! is_recursive_t(tx)) return 1; lx = lg(x); for (i=lontyp[tx]; iltop in gerepile"); /* dec_gerepile(&q, av0, av, tetpil, dec), saving 1 comparison */ if (q >= (GEN)av0 && q < (GEN)tetpil) q = (GEN) (((pari_sp)q) + dec); for (x = (GEN)av, a = (GEN)tetpil; a > (GEN)av0; ) *--x = *--a; avma = (pari_sp)x; while (x < (GEN)av) { const long tx = typ(x), lx = lg(x); if (! is_recursive_t(tx)) { x += lx; continue; } a = x + lontyp[tx]; x += lx; for ( ; a < x; a++) dec_gerepile((pari_sp*)a, av0, av, tetpil, dec); } return q; } void fill_stack(void) { GEN x = ((GEN)bot); while (x < (GEN)avma) *x++ = 0xfefefefeUL; } void debug_stack(void) { 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--) err_printf("%p:\t0x%lx\t%lu\n",z,*z,*z); } void setdebugvar(long n) { DEBUGVAR=n; } long getstack(void) { return top-avma; } /*******************************************************************/ /* */ /* timer_delay */ /* */ /*******************************************************************/ #if defined(USE_CLOCK_GETTIME) #include void timer_start(pari_timer *T) { struct timespec t; clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t); T->us = t.tv_nsec / 1000; T->s = t.tv_sec; } #elif defined(USE_GETRUSAGE) # include # include void timer_start(pari_timer *T) { struct rusage r; getrusage(RUSAGE_SELF,&r); T->us = r.ru_utime.tv_usec; T->s = r.ru_utime.tv_sec; } #elif defined(USE_FTIME) # include void timer_start(pari_timer *T) { struct timeb t; ftime(&t); T->us = ((long)t.millitm) * 1000; T->s = t.time; } #else static void _get_time(pari_timer *T, long Ticks, long TickPerSecond) { T->us = (long) ((Ticks % TickPerSecond) * (1000000. / TickPerSecond)); T->s = Ticks / TickPerSecond; } # ifdef USE_TIMES # include # include # include void timer_start(pari_timer *T) { # ifdef _SC_CLK_TCK long tck = sysconf(_SC_CLK_TCK); # else long tck = CLK_TCK; # endif struct tms t; times(&t); _get_time(T, t.tms_utime, tck); } # elif defined(WINCE) void timer_start(pari_timer *T) { _get_time(T, GetTickCount(), 1000); } # else # include # ifndef CLOCKS_PER_SEC # define CLOCKS_PER_SEC 1000000 /* may be false on YOUR system */ # endif void timer_start(pari_timer *T) { _get_time(T, clock(), CLOCKS_PER_SEC); } # endif #endif static long timer_aux(pari_timer *T, pari_timer *U) { long s = T->s, us = T->us; timer_start(U); return 1000 * (U->s - s) + (U->us - us + 500) / 1000; } /* return delay, reset timer */ long timer_delay(pari_timer *T) { return timer_aux(T, T); } /* return delay, don't reset timer */ long timer_get(pari_timer *T) { pari_timer t; return timer_aux(T, &t); } static void timer_vprintf(pari_timer *T, const char *format, va_list args) { out_puts(pariErr, "Time "); out_vprintf(pariErr, format,args); out_printf(pariErr, ": %ld\n", timer_delay(T)); pariErr->flush(); } void timer_printf(pari_timer *T, const char *format, ...) { va_list args; va_start(args, format); timer_vprintf(T, format, args); va_end(args); } long timer(void) { static THREAD pari_timer T; return timer_delay(&T);} long gettime(void) { static THREAD pari_timer T; return timer_delay(&T);} static THREAD pari_timer timer2_T, abstimer_T; long timer2(void) { return timer_delay(&timer2_T);} void msgtimer(const char *format, ...) { va_list args; va_start(args, format); timer_vprintf(&timer2_T, format, args); va_end(args); } long getabstime(void) { return timer_get(&abstimer_T);} /*******************************************************************/ /* */ /* FUNCTIONS KNOWN TO THE ANALYZER */ /* */ /*******************************************************************/ GEN pari_version(void) { const ulong mask = (1UL<>= PARI_VERSION_SHIFT; minor = n & mask; n >>= PARI_VERSION_SHIFT; major = n; if (*paricfg_vcsversion) { const char *ver = paricfg_vcsversion; const char *s = strchr(ver, '-'); char t[8]; const long len = s-ver; GEN v; if (!s || len > 6) pari_err_BUG("pari_version()"); /* paranoia */ memcpy(t, ver, len); t[len] = 0; v = cgetg(6, t_VEC); gel(v,1) = utoi(major); gel(v,2) = utoi(minor); gel(v,3) = utoi(patch); gel(v,4) = stoi( atoi(t) ); gel(v,5) = strtoGENstr(s+1); return v; } else { GEN v = cgetg(4, t_VEC); gel(v,1) = utoi(major); gel(v,2) = utoi(minor); gel(v,3) = utoi(patch); return v; } } /* 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. **************************************************************************** */ #include "init.h" #include "default.h" pari-2.7.5/src/language/parse.h0000644000175000017500000000527712405547532014765 0ustar billbill/* A Bison parser, made by GNU Bison 2.5. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2011 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 the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { KPARROW = 258, KARROW = 259, KDOTDOT = 260, KPE = 261, KSE = 262, KME = 263, KDE = 264, KDRE = 265, KEUCE = 266, KMODE = 267, KAND = 268, KOR = 269, KID = 270, KEQ = 271, KNE = 272, KGE = 273, KLE = 274, KSRE = 275, KSLE = 276, KSR = 277, KSL = 278, KDR = 279, KPP = 280, KSS = 281, KINTEGER = 282, KREAL = 283, KENTRY = 284, KSTRING = 285, DEFFUNC = 286, SEQ = 287, LVAL = 288, INT = 289, SIGN = 290 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; } YYLTYPE; # define yyltype YYLTYPE /* obsolescent; will be withdrawn */ # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif pari-2.7.5/src/language/pariinl.c0000644000175000017500000000125412366172547015301 0ustar billbill/* 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. */ #define PARI_NO_MPINL_H #define INLINE #ifndef DISABLE_INLINE # define DISABLE_INLINE #endif #include "pari.h" pari-2.7.5/src/language/members.c0000644000175000017500000002731712405547147015301 0ustar billbill/* Copyright (C) 2000-2003 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" /********************************************************************/ /** **/ /** MEMBER FUNCTIONS **/ /** **/ /********************************************************************/ INLINE int is_ell5(GEN x) { long lx; if (typ(x) != t_VEC) return 0; lx = lg(x); return lx == 17 || (lx == 6 && !is_vec_t(typ(gel(x,2)))); } INLINE int is_ell(GEN x) { long lx = lg(x); return (typ(x) == t_VEC && lx == 17); } static void member_err(const char *s, GEN y) { pari_err_TYPE(s,y); } GEN member_e(GEN x) { GEN y = get_prid(x); if (!y) member_err("e",x); return gel(y,3); } GEN member_f(GEN x) { GEN y = get_prid(x); if (!y) { if (typ(x) == t_FFELT) return utoipos(FF_f(x)); member_err("f",x); } return gel(y,4); } GEN member_p(GEN x) { long t; (void)get_nf(x,&t); switch(t) { case typ_GAL: return gal_get_p(x); case typ_ELL: switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellff_get_p(x); case t_ELL_Qp: return ellQp_get_p(x); default: member_err("p",x); } case typ_MODPR: x = get_prid(x); case typ_PRID: return pr_get_p(x); } switch(typ(x)) { case t_PADIC: return gel(x,2); case t_FFELT: return FF_p_i(x); } member_err("p",x); return NULL; } GEN member_bid(GEN x) { long t; (void)get_nf(x,&t); switch(t) { case typ_BNR: return bnr_get_bid(x); case typ_BID: return x; } member_err("bid",x); return NULL; } GEN member_bnf(GEN x) { long t; GEN y = get_bnf(x,&t); if (!y) member_err("bnf",x); return y; } GEN member_nf(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_RNF) return gel(x,10); member_err("nf",x); } return y; } /* integral basis */ GEN member_zk(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_Q: y = cgetg(3,t_VEC); gel(y,1) = gen_1; gel(y,2) = pol_x(varn(gel(x,1))); return y; case typ_RNF: return gel(x,7); } member_err("zk",x); } return nf_get_zk(y); } GEN member_disc(GEN x) /* discriminant */ { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_Q : return quad_disc(x); case typ_ELL: return ell_get_disc(x); case typ_RNF: return rnf_get_disc(x); } member_err("disc",x); } return nf_get_disc(y); } GEN member_pol(GEN x) /* polynomial */ { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_POL: return x; case typ_Q : return gel(x,1); case typ_GAL: return gal_get_pol(x); case typ_RNF: return rnf_get_pol(x); } if (typ(x)==t_POLMOD) return gel(x,2); if (typ(x)==t_FFELT) return FF_to_FpXQ(x); member_err("pol",x); } return nf_get_pol(y); } GEN member_polabs(GEN x) { long t; (void)get_nf(x,&t); if (t != typ_RNF) member_err("pol",x); return rnf_get_polabs(x); } GEN member_mod(GEN x) /* modulus */ { long t; (void)get_nf(x,&t); switch(t) { case typ_GAL: return gal_get_mod(x); case typ_BNR: return bnr_get_mod(x); case typ_BID: return gel(x,1); } switch(typ(x)) { case t_INTMOD: case t_POLMOD: case t_QUAD: break; case t_PADIC: return gel(x,3); case t_FFELT: return FF_mod(x); default: member_err("mod",x); } return gel(x,1); } GEN member_sign(GEN x) /* signature */ { long t; GEN y = get_nf(x,&t); if (!y) member_err("sign",x); return gel(y,2); } GEN member_r1(GEN x) { return gel(member_sign(x), 1); } GEN member_r2(GEN x) { return gel(member_sign(x), 2); } GEN member_index(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_RNF) return rnf_get_index(x); member_err("index",x); } return nf_get_index(y); } /* x assumed to be output by get_nf: ie a t_VEC with length 11 */ static GEN nfmats(GEN x) { GEN y; if (!x) return NULL; y = gel(x,5); if (typ(y) == t_VEC && lg(y) < 8) return NULL; return y; } GEN member_t2(GEN x) /* T2 matrix */ { long t; GEN y = nfmats(get_nf(x,&t)); if (!y) member_err("t2",x); return gram_matrix(gel(y,2)); } GEN member_diff(GEN x) /* different */ { long t; GEN y = nfmats(get_nf(x,&t)); if (!y) member_err("diff",x); return gel(y,5); } GEN member_codiff(GEN x) /* codifferent */ { long t; GEN T, D, DinvT, nf = get_nf(x,&t), y = nfmats(nf); if (!y) member_err("codiff",x); T = gel(y,4); D = absi(nf_get_disc(nf)); DinvT = ZM_inv(T,D); return gdiv(ZM_hnfmod(DinvT, D), D); } GEN member_roots(GEN x) /* roots */ { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_GAL) return gal_get_roots(x); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Qp: return mkcol( ellQp_root(x, ellQp_get_prec(x)) ); case t_ELL_Q: case t_ELL_Rg: return ellR_roots(x, ellR_get_prec(x)); } member_err("roots",x); } return nf_get_roots(y); } /* assume x output by get_bnf: ie a t_VEC with length 10 */ static GEN check_RES(GEN x, const char *s) { GEN y = gel(x,8); if (typ(y) != t_VEC || lg(y) < 4) member_err(s,x); return y; } /* y = get_bnf(x, &t) */ static GEN _member_clgp(GEN x, GEN y, long t) /* class group (3-component row vector) */ { if (!y) { switch(t) { case typ_QUA: return mkvec3(gel(x,1), gel(x,2), gel(x,3)); case typ_BID: return gel(x,2); } if (typ(x)==t_VEC) switch(lg(x)) { case 3: /* no gen */ case 4: return x; } member_err("clgp",x); } if (t==typ_BNR) return gel(x,5); y = check_RES(y, "clgp"); return gel(y,1); } static GEN _check_clgp(GEN x, GEN y, long t) { GEN c = _member_clgp(x,y,t); checkabgrp(c); return c; } GEN member_clgp(GEN x) { long t; GEN y = get_bnf(x,&t); return _check_clgp(x,y,t); } GEN member_reg(GEN x) /* regulator */ { long t; GEN y = get_bnf(x,&t); if (!y) { if (t == typ_QUA) return gel(x,4); member_err("reg",x); } if (t == typ_BNR) pari_err_IMPL("ray regulator"); y = check_RES(y, "reg"); return gel(y,2); } GEN member_fu(GEN x) /* fundamental units */ { long t; GEN y = get_bnf(x,&t); if (!y) { switch(t) { case typ_Q: x = quad_disc(x); return (signe(x)<0)? cgetg(1,t_VEC): quadunit(x); } member_err("fu",x); } if (t == typ_BNR) pari_err_IMPL("ray units"); return matbasistoalg(y, bnf_get_fu(y)); } /* torsion units. return [w,e] where w is the number of roots of 1, and e a * polymod generator */ GEN member_tu(GEN x) { long t; GEN bnf = get_bnf(x,&t), res = cgetg(3,t_VEC); if (!bnf) { GEN y; if (t != typ_Q) member_err("tu",x); y = quad_disc(x); if (signe(y) > 0 || cmpiu(y,4) > 0) return mkvec2(gen_m1, gen_2); gel(res,1) = utoipos((itos(y) == -4)? 4: 6); gel(res,2) = gcopy(x); } else { if (t == typ_BNR) pari_err_IMPL("ray torsion units"); gel(res,1) = utoipos( bnf_get_tuN(bnf) ); gel(res,2) = basistoalg(bnf, bnf_get_tuU(bnf)); } return res; } GEN member_futu(GEN x) /* concatenation of fu and tu, w is lost */ { return shallowconcat(member_fu(x), gel(member_tu(x),2)); } GEN member_tufu(GEN x) /* concatenation of tu and fu, w is lost */ { return shallowconcat(gel(member_tu(x),2), member_fu(x)); } /* structure of (Z_K/m)^*, where x is an idealstarinit (with or without gen) * or a bnrinit (with or without gen) */ GEN member_zkst(GEN x) { long t; (void)get_nf(x,&t); switch(t) { case typ_BID: return gel(x,2); case typ_BNR: { GEN bid = bnr_get_bid(x); if (typ(bid) == t_VEC && lg(bid) > 2) return gel(bid,2); } } member_err("zkst",x); return NULL; /* not reached */ } GEN member_no(GEN x) /* number of elements of a group (of type clgp) */ { pari_sp av = avma; long t; GEN y = get_bnf(x,&t); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellcard(x, NULL); } x = _check_clgp(x,y,t); avma = av; return gel(x,1); } GEN member_cyc(GEN x) /* cyclic decomposition (SNF) of a group (of type clgp) */ { pari_sp av = avma; long t; GEN y = get_bnf(x,&t); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellgroup(x, NULL); } x = _check_clgp(x,y,t); avma = av; return gel(x,2); } /* SNF generators of a group (of type clgp), or generators of a prime * ideal */ GEN member_gen(GEN x) { pari_sp av; long t; GEN y = get_bnf(x,&t); switch(t) { case typ_MODPR: x = get_prid(x); case typ_PRID: return mkvec2(gel(x,1), gel(x,2)); case typ_GAL: return gal_get_gen(x); case typ_ELL: return ellgenerators(x); } av = avma; x = _check_clgp(x,y,t); if (lg(x)!=4) member_err("gen",x); avma = av; return gel(x,3); } GEN member_group(GEN x) { long t; (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_group(x); if (t == typ_ELL) return ellgroup0(x, NULL, 1); member_err("group",x); return NULL; /* not reached */ } GEN member_orders(GEN x) { long t; (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_orders(x); member_err("orders",x); return NULL; /* not reached */ } GEN member_a1(GEN x) { if (!is_ell5(x)) member_err("a1",x); return ell_get_a1(x); } GEN member_a2(GEN x) { if (!is_ell5(x)) member_err("a2",x); return ell_get_a2(x); } GEN member_a3(GEN x) { if (!is_ell5(x)) member_err("a3",x); return ell_get_a3(x); } GEN member_a4(GEN x) { if (!is_ell5(x)) member_err("a4",x); return ell_get_a4(x); } GEN member_a6(GEN x) { if (!is_ell5(x)) member_err("a6",x); return ell_get_a6(x); } GEN member_b2(GEN x) { if (!is_ell(x)) member_err("b2",x); return ell_get_b2(x); } GEN member_b4(GEN x) { if (!is_ell(x)) member_err("b4",x); return ell_get_b4(x); } GEN member_b6(GEN x) { if (!is_ell(x)) member_err("b6",x); return ell_get_b6(x); } GEN member_b8(GEN x) { if (!is_ell(x)) member_err("b8",x); return ell_get_b8(x); } GEN member_c4(GEN x) { if (!is_ell(x)) member_err("c4",x); return ell_get_c4(x); } GEN member_c6(GEN x) { if (!is_ell(x)) member_err("c6",x); return ell_get_c6(x); } GEN member_j(GEN x) { if (!is_ell(x)) member_err("j",x); return ell_get_j(x); } static int ell_is_complex(GEN x) { long t = ell_get_type(x); return t == t_ELL_Q || t == t_ELL_Rg; } GEN member_omega(GEN x) { if (!is_ell(x)) member_err("omega",x); if (!ell_is_complex(x)) pari_err_TYPE("omega [not defined over C]",x); return ellR_omega(x, ellR_get_prec(x)); } GEN member_eta(GEN x) { if (!is_ell(x)) member_err("eta",x); if (!ell_is_complex(x)) pari_err_TYPE("eta [not defined over C]",x); return ellR_eta(x, ellR_get_prec(x)); } GEN member_area(GEN x) { GEN w, w1, w2, a,b,c,d; long prec; if (!is_ell(x)) member_err("area",x); if (!ell_is_complex(x)) pari_err_TYPE("area [not defined over C]",x); prec = ellR_get_prec(x); w = ellR_omega(x, prec); w1 = gel(w,1); a = real_i(w1); b = imag_i(w1); w2 = gel(w,2); c = real_i(w2); d = imag_i(w2); return gabs(gsub(gmul(a,d),gmul(b,c)), prec); } GEN member_tate(GEN x) { long prec; if (!is_ell(x)) member_err("tate",x); if (ell_get_type(x) != t_ELL_Qp) pari_err_TYPE("tate [not defined over Qp]",x); prec = ellQp_get_prec(x); return ellQp_Tate_uniformization(x, prec); } pari-2.7.5/src/language/init.h0000644000175000017500000036471112605246255014617 0ustar billbill/* This file is autogenerated from the database. */ /* 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","-_"}, {"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."}, {"Euler",0,(void*)mpeuler,3,"p","Euler=Euler(): Euler's constant with current precision."}, {"I",0,(void*)gen_I,3,"","I=I(): square root of -1."}, {"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."}, {"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."}, {"Qfb",0,(void*)Qfb0,2,"GGGDGp","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."}, {"Ser",0,(void*)gtoser,2,"GDnDP","Ser(s,{v='x},{d=seriesprecision}): convert s into a power series with variable v and precision d, starting with the constant coefficient."}, {"Set",0,(void*)gtoset,2,"DG","Set({x=[]}): convert x into a set, i.e. a row vector with strictly increasing coefficients. Empty set if x is omitted."}, {"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."}, {"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<=_",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."}, {"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."}, {"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."}, {"arg",0,(void*)garg,3,"Gp","arg(x): argument of x,such that -pi= 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."}, {"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= 0 is present, returns all convergents from p_0/q_0 up to p_n/q_n."}, {"core",0,(void*)core0,4,"GD0,L,","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."}, {"coredisc",0,(void*)coredisc0,4,"GD0,L,","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."}, {"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."}, {"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."}, {"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."}, {"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."}, {"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."}, {"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]."}, {"ellchangepointinv",0,(void*)ellchangepointinv,5,"GG","ellchangepointinv(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t], inverse of ellchangepoint."}, {"ellconvertname",0,(void*)ellconvertname,5,"G","ellconvertname(name): convert an elliptic curve name (as found in the elldata database) from a string to a triplet [conductor, isogeny class, index]. It will also convert a triplet back to a curve name."}, {"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]."}, {"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."}, {"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)."}, {"ellisoncurve",0,(void*)ellisoncurve,5,"GG","ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if 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."}, {"elllseries",0,(void*)elllseries,5,"GGDGp","elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A a cut-off point close to 1."}, {"ellminimalmodel",0,(void*)ellminimalmodel,5,"GD&","ellminimalmodel(E,{&v}): return the standard minimal integral model of the rational elliptic curve E. Sets v to the corresponding change of variables."}, {"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."}, {"ellordinate",0,(void*)ellordinate,5,"GGp","ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E."}, {"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."}, {"ellrootno",0,(void*)ellrootno,5,"lGDG","ellrootno(E,{p}): root number for the L-function of the elliptic curve E/Q at a prime p (including 0, for the infinite place); global root number if p is omitted."}, {"ellsearch",0,(void*)ellsearch,5,"G","ellsearch(N): returns all curves in the elldata database matching constraint N: given name (N = \"11a1\" or [11,0,1]), given isogeny class (N = \"11a\" or [11,0]), or given conductor (N = 11, \"11\", or [11])."}, {"ellsigma",0,(void*)ellsigma,5,"GDGD0,L,p","ellsigma(L,{z='x},{flag=0}): computes the value at z of the Weierstrass sigma function attached to the lattice w, as given by ellperiods(,1). If flag = 1, returns an arbitrary determination of the logarithm of sigma."}, {"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."}, {"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)]."}, {"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."}, {"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."}, {"exp",0,(void*)gexp,3,"Gp","exp(x): exponential of x."}, {"expm1",0,(void*)gexpm1,3,"Gp","expm1(x): exp(x)-1."}, {"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."}, {"factorff",0,(void*)factorff,4,"GDGDG","factorff(x,{p},{a}): factorization of the polynomial x in the finite field F_p[X]/a(X)F_p[X]."}, {"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."}, {"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."}, {"ffnbirred",0,(void*)ffnbirred0,4,"GLD0,L,","ffnbirred(q,n{,fl=0}): number of monic irreducible polynomials over F_q, of degree n (fl=0, default) or at most n (fl=1)."}, {"fforder",0,(void*)fforder,4,"GDG","fforder(x,{o}): multiplicative order of the finite field element x. Optional o represents a multiple of the order of the element."}, {"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."}, {"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.pol over the field defined by P, where the variable v stands for a root of 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 the conductor."}, {"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."}, {"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."}, {"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."}, {"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 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."}, {"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."}, {"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 for coding of a and b, and m is as in intnuminit. If flag is nonzero, assumes that expr(-X)=conj(expr(X)), which is twice faster."}, {"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 intmellininvshort if several values must be computed."}, {"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 precomputed using the command intfuncinit(t=[[-1],sig[2]],[[1],sig[2]],s) (with possibly its two optional additional parameters), where sig[2] = 1 if not given. Orders of magnitude faster than intmellininv."}, {"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."}, {"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."}, {"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."}, {"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."}, {"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)."}, {"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 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 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."}, {"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."}, {"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."}, {"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."}, {"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 in 2 and Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol."}, {"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."}, {"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."}, {"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 the number of extensions in a fixed algebraic closure."}, {"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)"}, {"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."}, {"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."}, {"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."}, {"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."}, {"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."}, {"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)."}, {"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."}, {"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: do not use d, single reduction step."}, {"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 have polynomial coefficients."}, {"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 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."}, {"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."}, {"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."}, {"quadhilbert",0,(void*)quadhilbert,4,"Gp","quadhilbert(D): relative equation for the Hilbert class field of the quadratic field of discriminant D (which can also be a bnf)."}, {"quadpoly",0,(void*)quadpoly0,4,"GDn","quadpoly(D,{v='x}): quadratic polynomial corresponding to the discriminant D, in variable v."}, {"quadray",0,(void*)quadray,4,"GGp","quadray(D,f): relative equation for the ray class field of conductor f for the quadratic field of discriminant D (which can also be a bnf)."}, {"quadregulator",0,(void*)quadregulator,4,"Gp","quadregulator(x): regulator of the real quadratic field of discriminant x."}, {"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."}, {"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 the order discriminant. If flag is set, just return 1 if the order is maximal, and 0 if not."}, {"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 <= flag (resp. p | flag) if flag > 0 (resp. flag < 0). The answer is guaranteed (i.e a is a norm iff q=1) if L/K is Galois or, under GRH, if S contains all primes less than 12.log(disc(M))^2, where M is the normal closure of L/K."}, {"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."}, {"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."}, {"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."}, {"sign",0,(void*)gsigne,1,"iG","sign(x): sign of x, of type integer, real or fraction"}, {"simplify",0,(void*)simplify,2,"G","simplify(x): simplify the object x as much as possible."}, {"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."}, {"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."}, {"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 up to twice faster."}, {"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."}, {"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."}, {"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\""}, {"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."}, {"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.)."}, {"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 duplicate entries."}, {"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"}, {"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."}, {"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."}, {"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."}, {"znprimroot",0,(void*)znprimroot,4,"G","znprimroot(n): returns a primitive root of n when it exists."}, {"znstar",0,(void*)znstar,4,"G","znstar(n): 3-component vector v, giving the structure of (Z/nZ)^*. v[1] is the order (i.e. eulerphi(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 */ }; pari-2.7.5/src/modules/0000755000175000017500000000000012613365633013355 5ustar billbillpari-2.7.5/src/modules/aprcl.c0000644000175000017500000006311212457150321014615 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* THE APRCL PRIMALITY TEST */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" typedef struct Red { /* global data */ GEN N; /* prime we are certifying */ GEN N2; /* floor(N/2) */ /* globa data for flexible window */ long k, lv; ulong mask; /* reduction data */ long n; GEN C; /* polcyclo(n) */ GEN (*red)(GEN x, struct Red*); } Red; typedef struct Cache { /* data associated to p^k */ GEN aall, tall; GEN cyc; GEN E; GEN eta; GEN matvite, matinvvite; GEN avite, pkvite; ulong ctsgt; /* DEBUG */ } Cache; static GEN makepoldeg1(GEN c, GEN d) { GEN z; if (signe(c)) { z = cgetg(4,t_POL); z[1] = evalsigne(1); gel(z,2) = d; gel(z,3) = c; } else if (signe(d)) { z = cgetg(3,t_POL); z[1] = evalsigne(1); gel(z,2) = d; } else { z = cgetg(2,t_POL); z[1] = evalsigne(0); } return z; } /* T mod polcyclo(p), assume deg(T) < 2p */ static GEN red_cyclop(GEN T, long p) { long i, d; GEN y, z; d = degpol(T) - p; /* < p */ if (d <= -2) return T; /* reduce mod (x^p - 1) */ y = ZX_mod_Xnm1(T, p); z = y+2; /* reduce mod x^(p-1) + ... + 1 */ d = p-1; if (degpol(y) == d) for (i=0; ipow2; i--) x[i-pow2] -= x[i]; for (; i>0; i--) if (x[i]) break; i += 2; z = cgetg(i, t_POL); z[1] = evalsigne(1); for (i--; i>=2; i--) gel(z,i) = stoi(x[i-1]); return z; } /* x t_POL, n > 0. Return x mod polcyclo(2^n) = (x^(2^(n-1)) + 1). IN PLACE */ static GEN red_cyclo2n_ip(GEN x, long n) { long i, pow2 = 1L<<(n-1); for (i = lg(x)-1; i>pow2+1; i--) if (signe(gel(x,i))) gel(x,i-pow2) = subii(gel(x,i-pow2), gel(x,i)); return normalizepol_lg(x, i+1); } static GEN red_cyclo2n(GEN x, long n) { return red_cyclo2n_ip(leafcopy(x), n); } /* x a non-zero VECSMALL */ static GEN smallpolrev(GEN x) { long i,j, lx = lg(x); GEN y; while (lx-- && x[lx]==0) /* empty */; i = lx+2; y = cgetg(i,t_POL); y[1] = evalsigne(1); for (j=2; jC = polcyclo(2^n) */ static GEN _red_cyclo2n(GEN x, Red *R) { return centermod_i(red_cyclo2n(x, R->n), R->N, R->N2); } /* special case R->C = polcyclo(p) */ static GEN _red_cyclop(GEN x, Red *R) { return centermod_i(red_cyclop(x, R->n), R->N, R->N2); } static GEN _red(GEN x, Red *R) { return centermod_i(grem(x, R->C), R->N, R->N2); } static GEN _redsimple(GEN x, Red *R) { return centermodii(x, R->N, R->N2); } static GEN sqrmod(GEN x, Red *R) { return R->red(gsqr(x), R); } static GEN sqrconst(GEN pol, Red *R) { GEN z = cgetg(3,t_POL); gel(z,2) = centermodii(sqri(gel(pol,2)), R->N, R->N2); z[1] = pol[1]; return z; } /* pol^2 mod (x^2+x+1, N) */ static GEN sqrmod3(GEN pol, Red *R) { GEN a,b,bma,A,B; long lv = lg(pol); if (lv==2) return pol; if (lv==3) return sqrconst(pol, R); a = gel(pol,3); b = gel(pol,2); bma = subii(b,a); A = centermodii(mulii(a,addii(b,bma)), R->N, R->N2); B = centermodii(mulii(bma,addii(a,b)), R->N, R->N2); return makepoldeg1(A,B); } /* pol^2 mod (x^2+1,N) */ static GEN sqrmod4(GEN pol, Red *R) { GEN a,b,A,B; long lv = lg(pol); if (lv==2) return pol; if (lv==3) return sqrconst(pol, R); a = gel(pol,3); b = gel(pol,2); A = centermodii(mulii(a, shifti(b,1)), R->N, R->N2); B = centermodii(mulii(subii(b,a),addii(b,a)), R->N, R->N2); return makepoldeg1(A,B); } /* pol^2 mod (polcyclo(5),N) */ static GEN sqrmod5(GEN pol, Red *R) { GEN c2,b,c,d,A,B,C,D; long lv = lg(pol); if (lv==2) return pol; if (lv==3) return sqrconst(pol, R); c = gel(pol,3); c2 = shifti(c,1); d = gel(pol,2); if (lv==4) { A = sqri(d); B = mulii(c2, d); C = sqri(c); A = centermodii(A, R->N, R->N2); B = centermodii(B, R->N, R->N2); C = centermodii(C, R->N, R->N2); return mkpoln(3,A,B,C); } b = gel(pol,4); if (lv==5) { A = mulii(b, subii(c2,b)); B = addii(sqri(c), mulii(b, subii(shifti(d,1),b))); C = subii(mulii(c2,d), sqri(b)); D = mulii(subii(d,b), addii(d,b)); } else { /* lv == 6 */ GEN a = gel(pol,5), a2 = shifti(a,1); /* 2a(d - c) + b(2c - b) */ A = addii(mulii(a2, subii(d,c)), mulii(b, subii(c2,b))); /* c(c - 2a) + b(2d - b) */ B = addii(mulii(c, subii(c,a2)), mulii(b, subii(shifti(d,1),b))); /* (a-b)(a+b) + 2c(d - a) */ C = addii(mulii(subii(a,b),addii(a,b)), mulii(c2,subii(d,a))); /* 2a(b - c) + (d-b)(d+b) */ D = addii(mulii(a2, subii(b,c)), mulii(subii(d,b), addii(d,b))); } A = centermodii(A, R->N, R->N2); B = centermodii(B, R->N, R->N2); C = centermodii(C, R->N, R->N2); D = centermodii(D, R->N, R->N2); return mkpoln(4,A,B,C,D); } static GEN _mul(GEN x, GEN y, Red *R) { return R->red(gmul(x,y), R); } /* jac^floor(N/pk) mod (N, polcyclo(pk)), flexible window */ static GEN _powpolmod(Cache *C, GEN jac, Red *R, GEN (*_sqr)(GEN, Red *)) { const GEN taba = C->aall; const GEN tabt = C->tall; 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; 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); for (f = efin; f >= 1; f--) { GEN t = gel(L, taba[f]); long tf = tabt[f]; res = (f==efin)? t: _mul(t, res, R); while (tf--) { res = _sqr(res, R); if (low_stack(lim, stack_lim(av,1))) { res = gerepilecopy(av, res); if(DEBUGMEM>1) pari_warn(warnmem,"powpolmod: f = %ld",f); } } } return gerepilecopy(av0, res); } static GEN _powpolmodsimple(Cache *C, Red *R, GEN jac) { pari_sp av = avma; GEN w = mulmat_pol(C->matvite, jac); long j, ph = lg(w); R->red = &_redsimple; for (j=1; jN, R->N2), R, &sqrmod); w = centermod_i( gmul(C->matinvvite, w), R->N, R->N2 ); w = gerepileupto(av, w); return RgV_to_RgX(w, 0); } static GEN powpolmod(Cache *C, Red *R, long p, long k, GEN jac) { GEN (*_sqr)(GEN, Red *); if (DEBUGLEVEL>2) C->ctsgt++; if (C->matvite) return _powpolmodsimple(C, R, jac); if (p == 2) /* p = 2 */ { if (k == 2) _sqr = &sqrmod4; else _sqr = &sqrmod; R->n = k; R->red = &_red_cyclo2n; } else if (k == 1) { if (p == 3) _sqr = &sqrmod3; else if (p == 5) _sqr = &sqrmod5; else _sqr = &sqrmod; R->n = p; R->red = &_red_cyclop; } else { R->red = &_red; _sqr = &sqrmod; } return _powpolmod(C, jac, R, _sqr); } /* Return e(t) = \prod_{p-1 | t} p^{1+v_p(t)}} * faet contains the odd prime divisors of e(t) */ static GEN compute_e(ulong t, GEN *faet) { GEN L, P, D = divisorsu(t); long l = lg(D); ulong k; P = vecsmalltrunc_init(l); L = vecsmalltrunc_init(l); for (k=l-1; k>1; k--) /* k != 1: avoid d = 1 */ { ulong d = D[k]; if (uisprime(++d)) { /* we want q = 1 (mod p) prime, not too large */ if (d > 50000000) return gen_0; vecsmalltrunc_append(P, d); vecsmalltrunc_append(L, upowuu(d, 1 + u_lval(t,d))); } } if (faet) *faet = P; return shifti(zv_prod_Z(L), 2 + u_lval(t,2)); } /* Table obtained by the following script: install(compute_e, "LD&"); \\ remove 'static' first table(first = 6, step = 6, MAXT = 8648640)= { emax = 0; forstep(t = first, MAXT, step, e = compute_e(t); if (e > 1.9*emax, emax = e; printf(" if (C < %5.5g) return %8d;\n", 2*log(e)/log(2)*0.9999, t) ); ); } Previous values can be recovered using the following table: T=[6,12,24,48,36,60,120,180,240,504,360,420,720,840,1440,1260,1680,2520,3360,5040,13860,10080,16380,21840,18480,27720,32760,36960,55440,65520,98280,110880,131040,166320,196560,262080,277200,360360,480480,332640,554400,720720,665280,831600,1113840,1441440,1663200,2227680,2162160,2827440,3326400,3603600,6126120,4324320,6683040,7207200,11138400,8648640]; f(t) = 2*log(compute_e(t))/log(2); for (i=1,#T, t=T[i]; printf(" if (C < %5.5g) return %8d;\n", f(t),t)); */ /* assume C < 3514.6 */ static ulong compute_t_small(double C) { if (C < 17.953) return 6; if (C < 31.996) return 12; if (C < 33.996) return 24; if (C < 54.079) return 36; if (C < 65.325) return 60; if (C < 68.457) return 72; if (C < 70.783) return 108; if (C < 78.039) return 120; if (C < 102.41) return 180; if (C < 127.50) return 360; if (C < 136.68) return 420; if (C < 153.43) return 540; if (C < 165.66) return 840; if (C < 169.17) return 1008; if (C < 178.52) return 1080; if (C < 192.68) return 1200; if (C < 206.34) return 1260; if (C < 211.94) return 1620; if (C < 222.09) return 1680; if (C < 225.11) return 2016; if (C < 244.19) return 2160; if (C < 270.29) return 2520; if (C < 279.50) return 3360; if (C < 293.62) return 3780; if (C < 346.68) return 5040; if (C < 348.70) return 6480; if (C < 383.34) return 7560; if (C < 396.68) return 8400; if (C < 426.04) return 10080; if (C < 458.34) return 12600; if (C < 527.16) return 15120; if (C < 595.38) return 25200; if (C < 636.29) return 30240; if (C < 672.53) return 42840; if (C < 684.90) return 45360; if (C < 708.78) return 55440; if (C < 771.30) return 60480; if (C < 775.86) return 75600; if (C < 859.62) return 85680; if (C < 893.16) return 100800; if (C < 912.27) return 110880; if (C < 966.13) return 128520; if (C < 1009.1) return 131040; if (C < 1041.9) return 166320; if (C < 1124.9) return 196560; if (C < 1251.0) return 257040; if (C < 1375.0) return 332640; if (C < 1431.0) return 393120; if (C < 1483.3) return 514080; if (C < 1546.3) return 655200; if (C < 1585.8) return 665280; if (C < 1661.3) return 786240; if (C < 1667.5) return 831600; if (C < 1676.9) return 917280; if (C < 1728.0) return 982800; if (C < 1747.4) return 1081080; if (C < 1773.6) return 1179360; if (C < 1810.6) return 1285200; if (C < 1924.5) return 1310400; if (C < 2001.1) return 1441440; if (C < 2096.3) return 1663200; if (C < 2165.8) return 1965600; if (C < 2321.6) return 2162160; if (C < 2368.2) return 2751840; if (C < 2377.2) return 2827440; if (C < 2514.7) return 3326400; if (C < 2588.5) return 3341520; if (C < 2636.6) return 3603600; if (C < 2667.2) return 3931200; if (C < 3028.6) return 4324320; if (C < 3045.5) return 5654880; if (C < 3080.5) return 6652800; if (C < 3121.6) return 6683040; if (C < 3283.1) return 7207200; return 8648640; } /* return t such that e(t) > sqrt(N), set *faet = odd prime divisors of e(t) */ static ulong compute_t(GEN N, GEN *e, GEN *faet) { /* 2^e b <= N < 2^e (b+1), where b >= 2^52. Approximating log_2 N by * log2(gtodouble(N)) ~ e+log2(b), the error is less than log(1+1/b) < 1e-15*/ double C = dbllog2(N) + 1e-6; /* > log_2 N */ ulong t; GEN B; /* Return "smallest" t such that f(t) >= C, which implies e(t) > sqrt(N) */ /* For N < 2^3515 ~ 10^1058 */ if (C < 3514.6) { t = compute_t_small(C); *e = compute_e(t, faet); return t; } B = sqrti(N); for (t = 8648640+840;; t+=840) { pari_sp av = avma; *e = compute_e(t, faet); if (cmpii(*e, B) > 0) break; avma = av; } return t; } /* T[i] = discrete log of i in (Z/q)^*, q odd prime * To save on memory, compute half the table: T[q-x] = T[x] + (q-1)/2 */ static GEN computetabdl(ulong q) { ulong g, a, i, qs2 = q>>1; /* (q-1)/2 */ GEN T = cgetg(qs2+2,t_VECSMALL); g = pgener_Fl(q); a = 1; for (i=1; i < qs2; i++) /* g^((q-1)/2) = -1 */ { a = Fl_mul(g,a,q); if (a > qs2) T[q-a] = i+qs2; else T[a] = i; } T[qs2+1] = T[qs2] + qs2; T[1] = 0; return T; } /* Return T: T[x] = dl of x(1-x) */ static GEN compute_g(ulong q) { const ulong qs2 = q>>1; /* (q-1)/2 */ ulong x, a; GEN T = computetabdl(q); /* updated in place to save on memory */ a = 0; /* dl[1] */ for (x=2; x<=qs2+1; x++) { /* a = dl(x) */ ulong b = T[x]; /* = dl(x) */ T[x] = b + a + qs2; /* dl(x) + dl(x-1) + dl(-1) */ a = b; } return T; } /* p odd prime */ static GEN get_jac(Cache *C, ulong q, long pk, GEN tabg) { ulong x, qs2 = q>>1; /* (q-1)/2 */ GEN vpk = zero_zv(pk); for (x=2; x<=qs2; x++) vpk[ tabg[x]%pk + 1 ] += 2; vpk[ tabg[x]%pk + 1 ]++; /* x = (q+1)/2 */ return u_red(vpk, C->cyc); } /* p = 2 */ static GEN get_jac2(GEN N, ulong q, long k, GEN *j2q, GEN *j3q) { GEN jpq, vpk, T = computetabdl(q); ulong x, pk, i, qs2; /* could store T[x+1] + T[x] + qs2 (cf compute_g). * Recompute instead, saving half the memory. */ pk = 1UL << k;; vpk = zero_zv(pk); qs2 = q>>1; /* (q-1)/2 */ for (x=2; x<=qs2; x++) vpk[ (T[x]+T[x-1]+qs2)%pk + 1 ] += 2; vpk[ (T[x]+T[x-1]+qs2)%pk + 1 ]++; jpq = u_red_cyclo2n_ip(vpk, k); if (k == 2) return jpq; if (mod8(N) >= 5) { GEN v8 = cgetg(9,t_VECSMALL); for (x=1; x<=8; x++) v8[x] = 0; for (x=2; x<=qs2; x++) v8[ ((3*T[x]+T[x-1]+qs2)&7) + 1 ]++; for ( ; x<=q-1; x++) v8[ ((3*T[q-x]+T[q-x+1]-3*qs2)&7) + 1 ]++; *j2q = RgX_inflate(ZX_sqr(u_red_cyclo2n_ip(v8,3)), pk>>3); *j2q = red_cyclo2n_ip(*j2q, k); } for (i=1; i<=pk; i++) vpk[i] = 0; for (x=2; x<=qs2; x++) vpk[ (2*T[x]+T[x-1]+qs2)%pk + 1 ]++; for ( ; x<=q-1; x++) vpk[ (2*T[q-x]+T[q-x+1]-2*qs2)%pk + 1 ]++; *j3q = ZX_mul(jpq, u_red_cyclo2n_ip(vpk,k)); *j3q = red_cyclo2n_ip(*j3q, k); return jpq; } /* N = 1 mod p^k, return an elt of order p^k in (Z/N)^* */ static GEN finda(Cache *Cp, GEN N, long pk, long p) { GEN a, pv; if (Cp && Cp->avite) { a = Cp->avite; pv = Cp->pkvite; } else { GEN ph, b, q; ulong u = 2; long v = Z_lvalrem(addis(N,-1), p, &q); ph = powuu(p, v-1); pv = muliu(ph, p); /* N - 1 = p^v q */ if (p > 2) { for (;;u++) { a = Fp_pow(utoipos(u), q, N); b = Fp_pow(a, ph, N); if (!gequal1(b)) break; } } else { while (krosi(u,N) >= 0) u++; a = Fp_pow(utoipos(u), q, N); b = Fp_pow(a, ph, N); } /* checking b^p = 1 mod N done economically in caller */ b = gcdii(addis(b,-1), N); if (!gequal1(b)) return NULL; if (Cp) { Cp->avite = a; /* a has order p^v */ Cp->pkvite = pv; } } return Fp_pow(a, divis(pv, pk), N); } /* return 0: N not a prime, 1: no problem so far */ static long filltabs(Cache *C, Cache *Cp, Red *R, long p, long pk, long ltab) { pari_sp av; long i, j; long e; GEN tabt, taba, m; C->cyc = polcyclo(pk,0); if (p > 2) { long LE = pk - pk/p + 1; GEN E = cgetg(LE, t_VECSMALL), eta = cgetg(pk+1,t_VEC); for (i=1,j=0; iE = E; for (i=1; i<=pk; i++) { GEN z = FpX_rem(monomial(gen_1, i-1, 0), C->cyc, R->N); gel(eta,i) = FpX_center(z, R->N, R->N2); } C->eta = eta; } else if (pk >= 8) { long LE = (pk>>2) + 1; GEN E = cgetg(LE, t_VECSMALL); for (i=1,j=0; iE = E; } if (pk > 2 && umodiu(R->N,pk) == 1) { GEN vpa, p1, p2, p3, a2 = NULL, a = finda(Cp, R->N, pk, p); long jj, ph; if (!a) return 0; ph = pk - pk/p; vpa = cgetg(ph+1,t_COL); gel(vpa,1) = a; if (pk > p) a2 = centermodii(sqri(a), R->N, R->N2); jj = 1; for (i=2; iN, R->N2); } if (!gequal1( centermodii( mulii(a, gel(vpa,ph)), R->N, R->N2) )) return 0; p1 = cgetg(ph+1,t_MAT); p2 = cgetg(ph+1,t_COL); gel(p1,1) = p2; for (i=1; i<=ph; i++) gel(p2,i) = gen_1; j = 2; gel(p1,j) = vpa; p3 = vpa; for (j++; j <= ph; j++) { p2 = cgetg(ph+1,t_COL); gel(p1,j) = p2; for (i=1; i<=ph; i++) gel(p2,i) = centermodii(mulii(gel(vpa,i),gel(p3,i)), R->N, R->N2); p3 = p2; } C->matvite = p1; C->matinvvite = FpM_inv(p1, R->N); } tabt = cgetg(ltab+1, t_VECSMALL); taba = cgetg(ltab+1, t_VECSMALL); av = avma; m = divis(R->N, pk); for (e=1; e<=ltab && signe(m); e++) { long s = vali(m); m = shifti(m,-s); tabt[e] = e==1? s: s + R->k; taba[e] = signe(m)? ((mod2BIL(m) & R->mask)+1)>>1: 0; m = shifti(m, -R->k); } setlg(taba, e); C->aall = taba; setlg(tabt, e); C->tall = tabt; avma = av; return 1; } static Cache * alloc_cache(void) { Cache *C = (Cache*)stack_malloc(sizeof(Cache)); C->matvite = NULL; C->avite = NULL; C->ctsgt = 0; return C; } static Cache ** calcglobs(Red *R, ulong t, long *plpC, long *pltab, GEN *pP) { GEN fat, P, E, PE; long lv, i, k, b; Cache **pC; b = expi(R->N)+1; k = 3; while (((k+1)*(k+2) << (k-1)) < b) k++; *pltab = (b/k)+2; R->k = k; R->lv = 1L << (k-1); R->mask = (1UL << k) - 1; fat = factoru_pow(t); P = gel(fat,1); E = gel(fat,2); PE= gel(fat,3); *plpC = lv = vecsmall_max(PE); /* max(p^e, p^e | t) */ pC = (Cache**)stack_malloc((lv+1)*sizeof(Cache*)); pC[1] = alloc_cache(); /* to be used as temp in step5() */ for (i = 2; i <= lv; i++) pC[i] = NULL; for (i=1; i zeta^a. Assume * a reduced mod pk := p^k*/ static GEN aut(long pk, GEN z, long a) { GEN v; long b, i, dz = degpol(z); if (a == 1 || dz < 0) return z; v = cgetg(pk+2,t_POL); v[1] = evalvarn(0); b = 0; gel(v,2) = gel(z,2); /* i = 0 */ for (i = 1; i < pk; i++) { b += a; if (b > pk) b -= pk; /* b = (a*i) % pk */ gel(v,i+2) = b > dz? gen_0: gel(z,b+2); } return normalizepol_lg(v, pk+2); } /* z^v for v in Z[G], represented by couples [sig_x^{-1},x] */ static GEN autvec_TH(long pk, GEN z, GEN v, GEN C) { long i, lv = lg(v); GEN s = pol_1(varn(C)); for (i=1; iN, pk); GEN s = pol_1(varn(R->C)); long i, lv = lg(v); for (i=1; iC), R->C); } return s; } /* 0 <= i < pk, such that x^i = z mod polcyclo(pk), -1 if no such i exist */ static long look_eta(GEN eta, long pk, GEN z) { long i; for (i=1; i<=pk; i++) if (ZX_equal(z, gel(eta,i))) return i-1; return -1; } /* same pk = 2^k */ static long look_eta2(long k, GEN z) { long d, s; if (typ(z) != t_POL) d = 0; /* t_INT */ else { if (!RgX_is_monomial(z)) return -1; d = degpol(z); z = gel(z,d+2); /* leading term */ } s = signe(z); if (!s || !is_pm1(z)) return -1; return (s > 0)? d: d + (1L<<(k-1)); } static long step4a(Cache *C, Red *R, ulong q, long p, long k, GEN tabg) { const long pk = upowuu(p,k); long ind; GEN jpq, s1, s2, s3; if (!tabg) tabg = compute_g(q); jpq = get_jac(C, q, pk, tabg); s1 = autvec_TH(pk, jpq, C->E, C->cyc); s2 = powpolmod(C,R, p,k, s1); s3 = autvec_AL(pk, jpq, C->E, R); s3 = _red(gmul(s3,s2), R); ind = look_eta(C->eta, pk, s3); if (ind < 0) return -1; return (ind%p) != 0; } /* x == -1 mod N ? */ static long is_m1(GEN x, GEN N) { return equalii(addis(x,1), N); } /* p=2, k>=3 */ static long step4b(Cache *C, Red *R, ulong q, long k) { const long pk = 1L << k; long ind; GEN s1, s2, s3, j2q = NULL, j3q = NULL; (void)get_jac2(R->N,q,k, &j2q,&j3q); s1 = autvec_TH(pk, j3q, C->E, C->cyc); s2 = powpolmod(C,R, 2,k, s1); s3 = autvec_AL(pk, j3q, C->E, R); s3 = _red(gmul(s3,s2), R); if (j2q) s3 = _red(gmul(j2q, s3), R); ind = look_eta2(k, s3); if (ind < 0) return -1; if ((ind&1)==0) return 0; if (DEBUGLEVEL>2) C->ctsgt++; s3 = Fp_pow(utoipos(q), R->N2, R->N); return is_m1(s3, R->N); } /* p=2, k=2 */ static long step4c(Cache *C, Red *R, ulong q) { long ind; GEN s0,s1,s3, jpq = get_jac2(R->N,q,2, NULL,NULL); s0 = sqrmod4(jpq, R); s1 = gmulsg(q,s0); s3 = powpolmod(C,R, 2,2, s1); if (mod4(R->N) == 3) s3 = _red(gmul(s0,s3), R); ind = look_eta2(2, s3); if (ind < 0) return -1; if ((ind&1)==0) return 0; if (DEBUGLEVEL>2) C->ctsgt++; s3 = Fp_pow(utoipos(q), R->N2, R->N); return is_m1(s3, R->N); } /* p=2, k=1 */ static long step4d(Cache *C, Red *R, ulong q) { GEN s1 = Fp_pow(utoipos(q), R->N2, R->N); if (DEBUGLEVEL>2) C->ctsgt++; if (is_pm1(s1)) return 0; if (is_m1(s1, R->N)) return (mod4(R->N) == 1); return -1; } static GEN _res(long a, long b) { return b? mkvec2s(a, b): mkvecs(a); } /* return 1 [OK so far] or <= 0 [not a prime] */ static GEN step5(Cache **pC, Red *R, long p, GEN et, ulong ltab, long lpC) { pari_sp av; ulong q; long pk, k, fl = -1; Cache *C, *Cp; forprime_t T; (void)u_forprime_arith_init(&T, 3, ULONG_MAX, 1,p); while( (q = u_forprime_next(&T)) ) { /* q = 1 (mod p) */ if (umodiu(et,q) == 0) continue; if (umodiu(R->N,q) == 0) return _res(1,p); k = u_lval(q-1, p); pk = upowuu(p,k); if (pk <= lpC && pC[pk]) { C = pC[pk]; Cp = pC[p]; } else { C = pC[1]; Cp = NULL; C->matvite = NULL; /* re-init */ } av = avma; if (!filltabs(C, Cp, R, p, pk, ltab)) return _res(1,0); R->C = C->cyc; if (p >= 3) fl = step4a(C,R, q,p,k, NULL); else if (k >= 3) fl = step4b(C,R, q,k); else if (k == 2) fl = step4c(C,R, q); else fl = step4d(C,R, q); if (fl == -1) return _res(q,p); if (fl == 1) return NULL; /*OK*/ avma = av; } pari_err_BUG("aprcl test fails! This is highly improbable"); return NULL; } static GEN step6(GEN N, ulong t, GEN et) { GEN r, N1 = remii(N, et); ulong i; pari_sp av = avma; r = gen_1; for (i=1; i2) err_printf("Step4: %ld q-values\n", l-1); for (i=l-1; i>0; i--) /* decreasing order: slowest first */ { pari_sp av1 = avma; ulong q = faet[i]; GEN faq = factoru_pow(q-1), tabg = compute_g(q); GEN P = gel(faq,1), E = gel(faq,2), PE = gel(faq,3); long lfaq = lg(P); pari_sp av2 = avma; if (DEBUGLEVEL>2) err_printf("testing Jacobi sums for q = %ld...",q); for (j=1; jcyc; if (p >= 3) fl = step4a(C,&R, q,p,e, tabg); else if (e >= 3) fl = step4b(C,&R, q,e); else if (e == 2) fl = step4c(C,&R, q); else fl = step4d(C,&R, q); if (fl == -1) return _res(q,p); if (fl == 1) flaglp[ zv_search(fat, p) ] = 0; } if (DEBUGLEVEL>2) err_printf("OK\n"); avma = av1; } if (DEBUGLEVEL>2) err_printf("Step5: testing conditions lp\n"); for (i=2; i2) { ulong sc = pC[1]->ctsgt; err_printf("Individual Fermat powerings:\n"); for (i=2; ictsgt); sc += pC[i]->ctsgt; } err_printf("Number of Fermat powerings = %lu\n",sc); err_printf("Step6: testing potential divisors\n"); } return step6(N, t, et); } long isprimeAPRCL(GEN N) { pari_sp av = avma; GEN res = aprcl(N); avma = av; return (typ(res) == t_INT); } pari-2.7.5/src/modules/krasner.c0000644000175000017500000006235412405547147015201 0ustar billbill/* Copyright (C) 2009 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" /************************************************************/ /* Computation of all the extensions of a given */ /* degree of a p-adic field */ /* Xavier Roblot */ /************************************************************/ #undef CHECK_EXTENSIONS /* cf. Math. Comp, vol. 70, No. 236, pp. 1641-1659 for more details. Note that n is now e (since the e from the paper is always = 1) and l is now f */ /* Structure for a given type of extension */ typedef struct { GEN p; long e, f, j; long a, b, c; long v; /* auxiliary variable */ long r; /* pr = p^r */ GEN pr; /* p-adic precision for poly. reduction */ GEN q, qm1; /* p^f, q - 1 */ GEN upl; /* cyclotomic polynomial (in v) generating K^ur (mod pr) */ GEN mv; /* -v mod upl (mod pr) */ GEN uplr; /* upl reduced mod p */ GEN frob; /* Frobenius acting of the root of upl (mod pr) */ GEN nbext; /* number of extensions */ GEN roottable; /* table of roots of polynomials over the residue field */ GEN pk; /* powers of p: [p^1, p^2, ..., p^c] */ } KRASNER_t; /* Structure containing the field data (constructed with FieldData) */ typedef struct { GEN p; GEN top; /* absolute polynomial with root zq + pi (mod pr) */ GEN topr; /* absolute polynomial with root zq + pi (mod p) */ GEN eis; /* relative polynomial with root pi (mod pr) (y=zq) */ GEN zq; /* (q-1)-th root of unity (root of upl) (mod pr) (y=zq+pi) */ GEN pi; /* prime element (mod p) (y=zq+pi)*/ GEN ipi; /* p/pi (mod pr) (y=zq+pi) (used to divide by pi) */ GEN pik; /* [1, pi, ..., pi^(e-1), pi^e / p] (mod pr). Note the last one ! */ long cj; /* number of conjugate fields */ } FAD_t; static long ceildiv(ulong a, ulong b) { long c = a/b; if (a%b) c++; return c; } /* Eval P(x) assuming P has positive coefficients and the result is a long */ static ulong ZX_z_eval(GEN P, ulong x) { long i, l = lg(P); ulong z; if (typ(P) == t_INT) return itou(P); if (l == 2) return 0; z = itou(gel(P, l-1)); for (i = l-2; i > 1; i--) z = z*x + itou(gel(P,i)); return z; } /* Eval P(x, y) assuming P has positive coefficients and the result is a long */ static ulong ZXY_z_eval(GEN P, ulong x, ulong y) { long i, l = lg(P); ulong z; if (l == 2) return 0; z = ZX_z_eval(gel(P, l-1), y); for (i = l-2; i > 1; i--) z = z*x + ZX_z_eval(gel(P, i), y); return z; } /* P an Fq[X], where Fq = Fp[Y]/(T(Y)), a an FpX representing the automorphism * y -> a(y). Return a(P), applying a() coefficientwise. */ static GEN FqX_FpXQ_eval(GEN P, GEN a, GEN T, GEN p) { long i, l; GEN Q = cgetg_copy(P, &l); Q[1] = P[1]; for (i = 2; i < l; i++) { GEN cf = gel(P, i); if (typ(cf) == t_POL) { switch(degpol(cf)) { case -1: cf = gen_0; break; case 0: cf = gel(cf,2); break; default: cf = FpX_FpXQ_eval(cf, a, T, p); cf = simplify_shallow(cf); break; } } gel(Q, i) = cf; } return Q; } /* Sieving routines */ static GEN InitSieve(long l) { return zero_F2v(l); } static long NextZeroValue(GEN sv, long i) { for(; i <= sv[1]; i++) if (!F2v_coeff(sv, i)) return i; return 0; /* sieve is full or out of the sieve! */ } static void SetSieveValue(GEN sv, long i) { if (i >= 1 && i <= sv[1]) F2v_set(sv, i); } /* return 1 if the data verify Ore condition and 0 otherwise */ static long VerifyOre(GEN p, long e, long j) { long nv, b, vb, nb; if (j < 0) return 0; nv = e * u_pval(e, p); b = j%e; if (b == 0) return (j == nv); if (j > nv) return 0; /* j < nv */ vb = u_pval(b, p); nb = vb*e; return (nb <= j); } /* Given [K:Q_p] = m and disc(K/Q_p) = p^d, return all decompositions K/K^ur/Q_p * as [e, f, j] with * K^ur/Q_p unramified of degree f, * K/K^ur totally ramified of degree e, and discriminant p^(e+j-1); * thus d = f*(e+j-1) and j > 0 iff ramification is wild */ static GEN possible_efj_by_d(GEN p, long m, long d) { GEN rep, div; long i, ctr, l; if (d == 0) return mkvec(mkvecsmall3(1, m, 0)); /* unramified */ div = divisorsu(ugcd(m, d)); l = lg(div); ctr = 1; rep = cgetg(l, t_VEC); for (i = 1; i < l; i++) { long f = div[i], e = m/f, j = d/f - e + 1; if (VerifyOre(p, e, j)) gel(rep, ctr++) = mkvecsmall3(e, f, j); } setlg(rep, ctr); return rep; } /* return the number of extensions corresponding to (e,f,j) */ static GEN NumberExtensions(KRASNER_t *data) { ulong pp, pa; long e, a, b; GEN p, q, s0, p1; e = data->e; p = data->p; q = data->q; a = data->a; /* floor(j/e) <= v_p(e), hence p^a | e */ b = data->b; /* j % e */ if (is_bigint(p)) /* implies a = 0 */ return b == 0? utoipos(e): mulsi(e, data->qm1); pp = p[2]; switch(a) { case 0: pa = 1; s0 = utoipos(e); break; case 1: pa = pp; s0 = mului(e, powiu(q, e / pa)); break; default: pa = upowuu(pp, a); /* p^a */ s0 = mulsi(e, powiu(q, (e / pa) * ((pa - 1) / (pp - 1)))); } /* s0 = e * q^(e*sum(p^-i, i=1...a)) */ if (b == 0) return s0; /* q^floor((b-1)/p^(a+1)) */ p1 = powiu(q, sdivsi(b-1, muluu(pa, pp))); return mulii(mulii(data->qm1, s0), p1); } static GEN get_topx(KRASNER_t *data, GEN eis) { GEN p1, p2, rpl; long j; pari_sp av, lim; /* 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); 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); } return simplify_shallow(p2); /* ZX */ } /* eis (ZXY): Eisenstein polynomial over the field defined by upl. * topx (ZX): corresponding absolute equation. * Return the struct FAD corresponding to the field it defines (GENs created * as clones). Assume e > 1. */ static void FieldData(KRASNER_t *data, FAD_t *fdata, GEN eis, GEN topx) { GEN p1, zq, ipi, cipi, dipi, t, Q; fdata->p = data->p; t = leafcopy(topx); setvarn(t, data->v); fdata->top = t; fdata->topr = FpX_red(t, data->pr); zq = pol_x(data->v); /* FIXME: do as in CycloPol (not so easy) */ for(;;) { GEN zq2 = zq; zq = Fq_pow(zq, data->q, fdata->top, data->pr); if (gequal(zq, zq2)) break; } fdata->zq = zq; fdata->eis = eis; fdata->pi = Fq_sub(pol_x(data->v), fdata->zq, FpX_red(fdata->top, data->p), data->p); ipi = RgXQ_inv(fdata->pi, fdata->top); ipi = Q_remove_denom(ipi, &dipi); Q = mulii(data->pr, data->p); cipi = Fp_inv(diviiexact(dipi, data->p), Q); fdata->ipi = FpX_Fp_mul(ipi, cipi, Q); /* p/pi mod p^(pr+1) */ /* Last one is in fact pi^e/p */ p1 = FpXQ_powers(fdata->pi, data->e, fdata->topr, data->pr); gel(p1, data->e+1) = ZX_Z_divexact(gel(p1, data->e+1), data->p); fdata->pik = p1; } /* return pol*ipi/p (mod top, pp) if it has integral coefficient, NULL otherwise. The result is reduced mod top, pp */ static GEN DivideByPi(FAD_t *fdata, GEN pp, GEN ppp, GEN pol) { GEN P; long i, l; pari_sp av = avma; /* "pol" is a t_INT or an FpX: signe() works for both */ if (!signe(pol)) return pol; P = Fq_mul(pol, fdata->ipi, fdata->top, ppp); /* FpX */ l = lg(P); for (i = 2; i < l; i++) { GEN r; gel(P,i) = dvmdii(gel(P,i), fdata->p, &r); if (r != gen_0) { avma = av; return NULL; } } return FpX_red(P, pp); } /* return pol# = pol~/pi^vpi(pol~) mod pp where pol~(x) = pol(pi.x + beta) * has coefficients in the field defined by top and pi is a prime element */ static GEN GetSharp(FAD_t *fdata, GEN pp, GEN ppp, GEN pol, GEN beta, long *pl) { GEN p1, p2; long i, v, l, d = degpol(pol); pari_sp av = avma; if (!gequal0(beta)) p1 = FqX_translate(pol, beta, fdata->topr, pp); else p1 = shallowcopy(pol); p2 = p1; for (v = 0;; v++) { for (i = 0; i <= v; i++) { GEN c = gel(p2, i+2); c = DivideByPi(fdata, pp, ppp, c); if (!c) break; gel(p2, i+2) = c; } if (i <= v) break; p1 = shallowcopy(p2); } if (!v) pari_err_BUG("GetSharp [no division]"); for (l = v; l >= 0; l--) { GEN c = gel(p1, l+2); c = DivideByPi(fdata, pp, ppp, c); if (!c) { break; } } *pl = l; if (l < 2) return NULL; /* adjust powers */ for (i = v+1; i <= d; i++) gel(p1, i+2) = Fq_mul(gel(p1, i+2), gel(fdata->pik, i-v+1), fdata->topr, pp); return gerepilecopy(av, normalizepol(p1)); } #ifdef CHECK_EXTENSIONS static void PrintValuations(GEN pol, GEN mod, GEN p) { long i, d = degpol(pol); for (i = 0; i <= d; i++) err_printf("%d ", Z_pval(RgXQ_norm(gel(pol, i+2), mod), p)); } /* Return the degree of pol mod the prime ideal of top */ static long DegreeMod(FAD_t *fdata, GEN pp, GEN ppp, GEN pol) { long d = degpol(pol); /* should be > 0 */ pari_sp av = avma; do { GEN c = gel(pol, d+2); if (!gequal0(c) && !DivideByPi(fdata, pp, ppp, c)) return d; } while (--d >= 1); avma = av; return 0; } #endif /* Compute roots of pol in the residue field. Use table look-up if possible */ static GEN Quick_FqX_roots(KRASNER_t *data, GEN pol) { GEN rts; ulong ind = 0; pol = FpXQX_red(pol, data->uplr, data->p); if (data->roottable) { ind = ZXY_z_eval(pol, data->q[2], data->p[2]); if (gel(data->roottable, ind)) return gel(data->roottable, ind); } rts = FqX_roots(pol, data->uplr, data->p); if (ind) gel(data->roottable, ind) = gclone(rts); return rts; } static void FreeRootTable(GEN T) { if (T) { long j, l = lg(T); for (j = 1; j < l; j++) if (gel(T,j)) gunclone(gel(T,j)); } } /* Return the number of roots of pol congruent to alpha modulo pi working modulo pp (all roots if alpha is NULL); if flag is non-zero, return 1 as soon as a root is found. (Note: ppp = pp*p for DivideByPi) */ static long RootCongruents(KRASNER_t *data, FAD_t *fdata, GEN pol, GEN alpha, GEN pp, GEN ppp, long sl, long flag) { GEN R; long s, i; if (alpha) { /* FIXME: the data used in GetSharp is not reduced */ long l; pol = GetSharp(fdata, pp, ppp, pol, alpha, &l); if (l <= 1) return l; #ifdef CHECK_EXTENSIONS if (l != DegreeMod(fdata, pp, ppp, pol)) pari_err_BUG("RootCongruents [degree mismatch in RCA]"); #endif /* decrease precision if sl gets bigger than a multiple of e */ sl += l; if (sl >= data->e) { sl -= data->e; ppp = pp; pp = diviiexact(pp, data->p); } } R = Quick_FqX_roots(data, pol); for (s = 0, i = 1; i < lg(R); i++) { s += RootCongruents(data, fdata, pol, gel(R, i), pp, ppp, sl, flag); if (flag && s) return 1; } return s; } /* pol is a ZXY defining a polynomial over the field defined by fdata If flag != 0, return 1 as soon as a root is found. Precision are done with a precision of pr. */ static long RootCountingAlgorithm(KRASNER_t *data, FAD_t *fdata, GEN pol, long flag) { long j, l, d; GEN P = cgetg_copy(pol, &l); P[1] = pol[1]; d = l-3; for (j = 0; j < d; j++) { GEN cf = gel(pol, j+2); if (typ(cf) == t_INT) cf = diviiexact(cf, data->p); else cf = ZX_Z_divexact(cf, data->p); gel(P, j+2) = Fq_mul(cf, gel(fdata->pik, j+1), fdata->topr, data->pr); } gel(P, d+2) = gel(fdata->pik, d+1); /* pik[d] = pi^d/p */ return RootCongruents(data, fdata, P, NULL, diviiexact(data->pr, data->p), data->pr, 0, flag); } /* Return non-zero if the field given by fdata defines a field isomorphic to * the one defined by pol */ static long IsIsomorphic(KRASNER_t *data, FAD_t *fdata, GEN pol) { long j, nb; pari_sp av = avma; if (RgX_is_ZX(pol)) return RootCountingAlgorithm(data, fdata, pol, 1); for (j = 1; j <= data->f; j++) { GEN p1 = FqX_FpXQ_eval(pol, fdata->zq, fdata->top, data->pr); nb = RootCountingAlgorithm(data, fdata, p1, 1); if (nb) { avma = av; return nb; } if (j < data->f) pol = FqX_FpXQ_eval(pol, data->frob, data->upl, data->pr); } avma = av; return 0; } /* Compute the number of conjugates fields of the field given by fdata */ static void NbConjugateFields(KRASNER_t *data, FAD_t *fdata) { GEN pol = fdata->eis; long j, nb; pari_sp av = avma; if (RgX_is_ZX(pol)) { /* split for efficiency; contains the case f = 1 */ fdata->cj = data->e / RootCountingAlgorithm(data, fdata, pol, 0); avma = av; return; } nb = 0; for (j = 1; j <= data->f; j++) { GEN p1 = FqX_FpXQ_eval(pol, fdata->zq, fdata->top, data->pr); nb += RootCountingAlgorithm(data, fdata, p1, 0); if (j < data->f) pol = FqX_FpXQ_eval(pol, data->frob, data->upl, data->pr); } avma = av; fdata->cj = data->e * data->f / nb; return; } /* return a minimal list of polynomials generating all the totally ramified extensions of K^ur of degree e and discriminant p^{e + j - 1} in the tamely ramified case */ static GEN TamelyRamifiedCase(KRASNER_t *data) { long av = avma, g; GEN rep, p2, topx, m, eis, Xe = gpowgs(pol_x(0), data->e); #ifdef CHECK_EXTENSIONS FAD_t fdata; long cnt = 0, nb, j; GEN vpl; err_printf("Number of extensions: %ld\n", itos(data->nbext)); #endif g = ugcd(data->e, umodiu(data->qm1, data->e)); /* (e, q-1) */ m = stoi(data->e/g); rep = zerovec(g); eis = gadd(Xe, data->p); topx = get_topx(data, eis); p2 = mkvec2(topx, m); gel(rep, 1) = p2; #ifdef CHECK_EXTENSIONS vpl = zerovec(g); gel(vpl, 1) = eis; if (data->e == 1) nb = 1; else { FieldData(data, &fdata, eis, topx); NbConjugateFields(data, &fdata); nb = fdata.cj; } err_printf("Found %ld field(s)\n", nb); cnt += nb; #endif if (g > 1) { ulong pmodg = umodiu(data->p, g); long r = 1, ct = 1; GEN sv = InitSieve(g-1); while (r) { long gr; GEN p1 = FpXQ_powu(pol_x(data->v), r, data->uplr, data->p); eis = gadd(Xe, ZX_Z_mul(p1, data->p)); /* Adding a ZX and a ZY (cste coefficient) */ ct++; topx = get_topx(data, eis); p2 = mkvec2(topx, m); gel(rep, ct) = p2; #ifdef CHECK_EXTENSIONS gel(vpl, ct) = eis; FieldData(data, &fdata, eis, topx); for (j = 1; j < ct; j++) if (IsIsomorphic(data, &fdata, gel(vpl, j))) pari_err_BUG("TamelyRamifiedCase [isomorphic fields]"); NbConjugateFields(data, &fdata); nb = fdata.cj; err_printf("Found %ld field(s)\n", nb); cnt += nb; #endif gr = r; do { SetSieveValue(sv, gr); gr = Fl_mul(gr, pmodg, g); } while (gr != r); r = NextZeroValue(sv, r); } setlg(rep, ct+1); } #ifdef CHECK_EXTENSIONS if (!equaliu(data->nbext, cnt)) pari_err_BUG("TamelyRamifiedCase [incorrect #fields]"); #endif return gerepilecopy(av, rep); } static long function_l(GEN p, long a, long b, long i) { long l = 1 + a - z_pval(i, p); if (i < b) l++; return (l < 1)? 1: l; } /* Structure of the coefficients set Omega. Each coefficient is [start, zr] * meaning all the numbers of the form: * zeta_0 * p^start + ... + zeta_s * p^c (s = c - start) * with zeta_i roots of unity (powers of zq + zero), zeta_0 = 0 is * possible iff zr = 1 */ static GEN StructureOmega(KRASNER_t *data, GEN *pnbpol) { GEN nbpol, O = cgetg(data->e + 1, t_VEC); long i; /* i = 0 */ gel(O, 1) = mkvecsmall2(1, 0); nbpol = mulii(data->qm1, powiu(data->q, data->c - 1)); for (i = 1; i < data->e; i++) { long v_start, zero = 0; GEN nbcf, p1; v_start = function_l(data->p, data->a, data->b, i); p1 = powiu(data->q, data->c - v_start); if (i == data->b) nbcf = mulii(p1, data->qm1); else { nbcf = mulii(p1, data->q); zero = 1; } gel(O, i+1) = mkvecsmall2(v_start, zero); nbpol = mulii(nbpol, nbcf); } *pnbpol = nbpol; return O; } /* a random element of the finite field */ static GEN RandomFF(KRASNER_t *data) { long i, l = data->f + 2, p = itou(data->p); GEN c = cgetg(l, t_POL); c[1] = evalvarn(data->v); for (i = 2; i < l; i++) gel(c, i) = utoi(random_Fl(p)); return ZX_renormalize(c, l); } static GEN RandomPol(KRASNER_t *data, GEN Omega) { long i, j, l = data->e + 3, end = data->c; GEN pol = cgetg(l, t_POL); pol[1] = evalsigne(1) | evalvarn(0); for (i = 1; i <= data->e; i++) { GEN c, cf = gel(Omega, i); long st = cf[1], zr = cf[2]; /* c = sum_{st <= j <= end} x_j p^j, where x_j are random Fq mod (p,upl) * If (!zr), insist on x_st != 0 */ for (;;) { c = RandomFF(data); if (zr || signe(c)) break; } 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); } gel(pol, i+1) = gen_1; /* monic */ return pol; } static void CloneFieldData(FAD_t *fdata) { fdata->top = gclone(fdata->top); fdata->topr= gclone(fdata->topr); fdata->zq = gclone(fdata->zq); fdata->eis = gclone(fdata->eis); fdata->pi = gclone(fdata->pi); fdata->ipi = gclone(fdata->ipi); fdata->pik = gclone(fdata->pik); } static void FreeFieldData(FAD_t *fdata) { gunclone(fdata->top); gunclone(fdata->topr); gunclone(fdata->zq); gunclone(fdata->eis); gunclone(fdata->pi); gunclone(fdata->ipi); gunclone(fdata->pik); } static GEN WildlyRamifiedCase(KRASNER_t *data) { long nbext, ct, fd, nb = 0, j; GEN nbpol, rpl, rep, Omega; FAD_t **vfd; pari_timer T; pari_sp av = avma, av2; /* Omega = vector giving the structure of the set Omega */ /* nbpol = number of polynomials to consider = |Omega| */ Omega = StructureOmega(data, &nbpol); nbext = itos_or_0(data->nbext); if (!nbext || (nbext & ~LGBITS)) pari_err_OVERFLOW("padicfields [too many extensions]"); if (DEBUGLEVEL>0) { err_printf("There are %ld extensions to find and %Ps polynomials to consider\n", nbext, nbpol); timer_start(&T); } vfd = (FAD_t**)new_chunk(nbext); for (j = 0; j < nbext; j++) vfd[j] = (FAD_t*)new_chunk(sizeof(FAD_t)); ct = 0; fd = 0; av2 = avma; while (fd < nbext) { /* Jump randomly among the polynomials : seems best... */ rpl = RandomPol(data, Omega); if (DEBUGLEVEL>3) err_printf("considering polynomial %Ps\n", rpl); #ifdef CHECK_EXTENSIONS { GEN disc = poldisc0(rpl, 0); long e = data->e, f = data->f, j = data->j; disc = RgXQ_norm(disc, data->upl); if (Z_pval(disc, data->p) != f*(e+j-1)) pari_err_BUG("WildlyRamifiedCase [incorrect discriminant]"); } #endif for (j = 0; j < ct; j++) { nb = IsIsomorphic(data, vfd[j], rpl); if (nb) break; } if (!nb) { GEN topx = get_topx(data, rpl); FAD_t *fdata = (FAD_t*)vfd[ct]; FieldData(data, fdata, rpl, topx); CloneFieldData(fdata); NbConjugateFields(data, fdata); nb = fdata->cj; fd += nb; ct++; if (DEBUGLEVEL>1) err_printf("%ld more extension%s\t(%ld/%ld, %ldms)\n", nb, (nb == 1)? "": "s", fd, nbext, timer_delay(&T)); } avma = av2; } rep = cgetg(ct+1, t_VEC); for (j = 0; j < ct; j++) { GEN topx = ZX_copy(((FAD_t*)vfd[j])->top); GEN p1; setvarn(topx, 0); p1 = mkvec2(topx, stoi(((FAD_t*)vfd[j])->cj)); gel(rep, j+1) = p1; FreeFieldData((FAD_t*)vfd[j]); } FreeRootTable(data->roottable); return gerepileupto(av, rep); } /* return the minimal polynomial (mod pr) of a generator of (F_p^f)^x with variable v */ static GEN CycloPol(KRASNER_t *d) { GEN T, z; /* 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); 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 [ p^1, p^2, ..., p^c ] */ static GEN get_pk(KRASNER_t *data) { long i, l = data->c + 1; GEN pk = cgetg(l, t_VEC), p = data->p; gel(pk, 1) = p; for (i = 2; i <= data->c; i++) gel(pk, i) = mulii(gel(pk, i-1), p); return pk; } /* Compute an absolute polynomial for all the totally ramified extensions of Q_p(z) of degree e and discriminant p^{e + j - 1} where z is a root of upl defining an unramified extension of Q_p */ /* See padicfields for the meaning of flag */ static GEN GetRamifiedPol(GEN p, GEN efj, long flag) { long e = efj[1], f = efj[2], j = efj[3], i, l; const long v = 1; GEN L, pols; KRASNER_t data; pari_sp av = avma; if (DEBUGLEVEL>1) err_printf(" Computing extensions with decomposition [e, f, j] = [%ld, %ld, %ld]\n", e,f,j); data.p = p; data.e = e; data.f = f; data.j = j; data.a = j/e; data.b = j%e; data.c = (e+2*j)/e+1; data.q = powiu(p, f); data.qm1 = subis(data.q, 1); data.v = v; data.r = 1 + ceildiv(2*j + 3, e); /* enough precision */ data.pr = powiu(p, data.r); data.nbext = NumberExtensions(&data); if (flag == 2) return data.nbext; data.upl = CycloPol(&data); /* mv = -v mod upl. If f = 1, then upl = v + c, hence mv = c */ data.mv = f == 1? gel(data.upl, 2) : FpX_neg(pol_x(v), data.pr); data.uplr = FpX_red(data.upl, data.p); data.frob = FpXQ_pow(pol_x(v), p, data.upl, data.pr); if (DEBUGLEVEL>1) err_printf(" Unramified part %Ps\n", data.upl); data.roottable = NULL; if (j) { if (lgefint(data.q) == 3) { ulong npol = upowuu(data.q[2], e+1); if (npol && npol < (1<<19)) data.roottable = const_vec(npol, NULL); } data.pk = get_pk(&data); L = WildlyRamifiedCase(&data); } else L = TamelyRamifiedCase(&data); pols = cgetg_copy(L, &l); if (flag == 1) { GEN E = utoipos(e), F = utoipos(f), D = utoi(f*(e+j-1)); for (i = 1; i < l; i++) { GEN T = gel(L,i); gel(pols, i) = mkvec5(ZX_copy(gel(T, 1)), E,F,D, icopy(gel(T, 2))); } } else { for (i = 1; i < l; i++) { GEN T = gel(L,i); gel(pols, i) = ZX_copy(gel(T,1)); } } return gerepileupto(av, pols); } static GEN possible_efj(GEN p, long m) { /* maximal possible discriminant valuation d <= m * (1+v_p(m)) - 1 */ /* 1) [j = 0, tame] d = m - f with f | m and v_p(f) = v_p(m), or * 2) [j > 0, wild] d >= m, j <= v_p(e)*e */ ulong m1, pve, pp = p[2]; /* pp used only if v > 0 */ long ve, v = u_pvalrem(m, p, &m1); GEN L, D = divisorsu(m1); long i, taum1 = lg(D)-1, nb = 0; if (v) { for (pve = 1,ve = 1; ve <= v; ve++) { pve *= pp; nb += pve * ve; } nb = itos_or_0(muluu(nb, zv_sum(D))); if (!nb || is_bigint( mului(pve, sqru(v)) ) ) pari_err_OVERFLOW("padicfields [too many ramification possibilities]"); } nb += taum1; /* upper bound for the number of possible triples [e,f,j] */ L = cgetg(nb + 1, t_VEC); /* 1) tame */ for (nb=1, i=1; i < lg(D); i++) { long e = D[i], f = m / e; gel(L, nb++) = mkvecsmall3(e, f, 0); } /* 2) wild */ /* Ore's condition: either * 1) j = v_p(e) * e, or * 2) j = a e + b, with 0 < b < e and v_p(b) <= a < v_p(e) */ for (pve = 1, ve = 1; ve <= v; ve++) { pve *= pp; /* = p^ve */ for (i = 1; i < lg(D); i++) { long a,b, e = D[i] * pve, f = m / e; for (b = 1; b < e; b++) for (a = u_lval(b, pp); a < ve; a++) gel(L, nb++) = mkvecsmall3(e, f, a*e + b); gel(L, nb++) = mkvecsmall3(e, f, ve*e); } } setlg(L, nb); return L; } static GEN pols_from_efj(pari_sp av, GEN EFJ, GEN p, long flag) { long i, l; GEN L = cgetg_copy(EFJ, &l); if (l == 1) { avma = av; return flag == 2? gen_0: cgetg(1, t_VEC); } for (i = 1; i < l; i++) gel(L,i) = GetRamifiedPol(p, gel(EFJ,i), flag); if (flag == 2) return gerepileuptoint(av, ZV_sum(L)); return gerepilecopy(av, shallowconcat1(L)); } /* return a minimal list of polynomials generating all the extensions of Q_p of given degree N; if N is a t_VEC [n,d], return extensions of degree n and discriminant p^d. */ /* Return only the polynomials if flag = 0 (default), also the ramification degree, the residual degree and the discriminant if flag = 1 and only the number of extensions if flag = 2 */ GEN padicfields0(GEN p, GEN N, long flag) { pari_sp av = avma; long m = 0, d = -1; GEN L; if (typ(p) != t_INT) pari_err_TYPE("padicfields",p); /* be nice to silly users */ if (!BPSW_psp(p)) pari_err_PRIME("padicfields",p); switch(typ(N)) { case t_VEC: if (lg(N) != 3) pari_err_TYPE("padicfields",N); d = gtos(gel(N,2)); N = gel(N,1); /* fall through */ case t_INT: m = itos(N); if (m <= 0) pari_err_DOMAIN("padicfields", "degree", "<=", gen_0,N); break; default: pari_err_TYPE("padicfields",N); } if (d >= 0) return padicfields(p, m, d, flag); L = possible_efj(p, m); return pols_from_efj(av, L, p, flag); } GEN padicfields(GEN p, long m, long d, long flag) { long av = avma; GEN L = possible_efj_by_d(p, m, d); return pols_from_efj(av, L, p, flag); } pari-2.7.5/src/modules/kummer.c0000644000175000017500000011115012405547147015021 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* KUMMER EXTENSIONS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" typedef struct { GEN R; /* nf.pol */ GEN x; /* tau ( Mod(x, R) ) */ GEN zk;/* action of tau on nf.zk (as t_MAT) */ } tau_s; typedef struct { GEN polnf, invexpoteta1; tau_s *tau; long m; } toK_s; typedef struct { GEN R; /* ZX, compositum(P,Q) */ GEN p; /* QX, Mod(p,R) root of P */ GEN q; /* QX, Mod(q,R) root of Q */ long k; /* Q[X]/R generated by q + k p */ GEN rev; } compo_s; static long prank(GEN cyc, long ell) { long i; for (i=1; i= d); for (j = i+1; j < k; j++) y[j] = 0; return 1; } static int ok_congruence(GEN X, ulong ell, long lW, GEN vecMsup) { long i, l; if (zv_equal0(X)) return 0; l = lg(X); for (i=lW; i>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)); } static GEN reduce_mod_Qell(GEN bnfz, GEN be, GEN gell) { GEN c; be = nf_to_scalar_or_basis(bnfz, be); be = Q_primitive_part(be, &c); if (c) { GEN d, fa = factor(c); gel(fa,2) = FpC_red(gel(fa,2), gell); d = factorback(fa); be = typ(be) == t_INT? mulii(be,d): ZC_Z_mul(be, d); } return be; } /* return q, q^n r = x, v_pr(r) < n for all pr. Insist q is a genuine n-th * root (i.e r = 1) if strict != 0. */ GEN idealsqrtn(GEN nf, GEN x, GEN gn, int strict) { long i, l, n = itos(gn); GEN fa, q, Ex, Pr; fa = idealfactor(nf, x); Pr = gel(fa,1); l = lg(Pr); Ex = gel(fa,2); q = NULL; for (i=1; i1) 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))) { z = idealred_elt(nf, z); be = nfdiv(nf, be, nfpow(nf, z, 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)) { ru = lg(u); for (j=1; j < ru; j++) if (gequal1(gcoeff(u,ru-1,j))) break; if (j < ru) { 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)); } } 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); } static GEN tauofalg(GEN x, tau_s *tau) { long tx = typ(x); if (tx == t_POLMOD) { x = gel(x,2); tx = typ(x); } if (tx == t_POL) x = RgX_RgXQ_eval(x, tau->x, tau->R); return mkpolmod(x, tau->R); } static tau_s * get_tau(tau_s *tau, GEN nf, compo_s *C, long g) { GEN bas = nf_get_zk(nf), U, Uzk; long i, l = lg(bas); /* compute action of tau: q^g + kp */ U = RgX_add(RgXQ_powu(C->q, g, C->R), RgX_muls(C->p, C->k)); U = RgX_RgXQ_eval(C->rev, U, C->R); tau->x = U; tau->R = C->R; Uzk = cgetg(l, t_MAT); for (i=1; izk = Uzk; return tau; } static GEN tauoffamat(GEN x, tau_s *tau); static GEN tauofelt(GEN x, tau_s *tau) { switch(typ(x)) { case t_COL: return RgM_RgC_mul(tau->zk, x); case t_MAT: return tauoffamat(x, tau); default: return tauofalg(x, tau); } } static GEN tauofvec(GEN x, tau_s *tau) { long i, l = lg(x); GEN y = cgetg(l, typ(x)); for (i=1; izk, id), gcoeff(id, 1,1)); } static int isprimeidealconj(GEN nfz, GEN P, GEN Q, tau_s *tau) { GEN p = pr_get_p(P); GEN x = pr_get_gen(P); if (!equalii(p, pr_get_p(Q)) || pr_get_e(P) != pr_get_e(Q) || pr_get_f(P) != pr_get_f(Q)) return 0; if (ZV_equal(x, pr_get_gen(Q))) return 1; for(;;) { if (ZC_prdvd(nfz,x,Q)) return 1; x = FpC_red(tauofelt(x, tau), p); if (ZC_prdvd(nfz,x,P)) return 0; } } static int isconjinprimelist(GEN nfz, GEN S, GEN pr, tau_s *tau) { long i, l; if (!tau) return 0; l = lg(S); for (i=1; iinvexpoteta1) - 1; GEN y = gmul(T->invexpoteta1, Rg_to_RgV(lift_intern(x), degKz)); return gmodulo(gtopolyrev(y,varn(T->polnf)), T->polnf); } static GEN no_sol(long all, long i) { if (!all) pari_err_BUG(stack_sprintf("kummer [bug%ld]", i)); return cgetg(1,t_VEC); } static GEN get_gell(GEN bnr, GEN subgp, long all) { GEN gell; if (all && all != -1) return utoipos(labs(all)); if (!subgp) return ZV_prod(bnr_get_cyc(bnr)); gell = det(subgp); if (typ(gell) != t_INT) pari_err_TYPE("rnfkummer",gell); return gell; } typedef struct { GEN Sm, Sml1, Sml2, Sl, ESml2; } primlist; static int build_list_Hecke(primlist *L, GEN nfz, GEN fa, GEN gothf, GEN gell, tau_s *tau) { GEN listpr, listex, pr, factell; long vp, i, l, ell = itos(gell), degKz = nf_get_degree(nfz); if (!fa) fa = idealfactor(nfz, gothf); listpr = gel(fa,1); listex = gel(fa,2); l = lg(listpr); L->Sm = vectrunc_init(l); L->Sml1= vectrunc_init(l); L->Sml2= vectrunc_init(l); L->Sl = vectrunc_init(l+degKz); L->ESml2=vecsmalltrunc_init(l); for (i=1; iSm,pr,tau)) vectrunc_append(L->Sm,pr); } else { long e = pr_get_e(pr), vd = (vp-1)*(ell-1)-ell*e; if (vd > 0) return 4; if (vd==0) { if (!isconjinprimelist(nfz, L->Sml1,pr,tau)) vectrunc_append(L->Sml1, pr); } else { if (vp==1) return 2; if (!isconjinprimelist(nfz, L->Sml2,pr,tau)) { vectrunc_append(L->Sml2, pr); vecsmalltrunc_append(L->ESml2, vp); } } } } factell = idealprimedec(nfz,gell); l = lg(factell); for (i=1; iSl,pr,tau)) vectrunc_append(L->Sl, pr); } return 0; /* OK */ } /* Return a Flm */ static GEN logall(GEN nf, GEN vec, long lW, long mginv, long ell, GEN pr, long ex) { GEN m, M, bid = Idealstar(nf, idealpows(nf, pr, ex), nf_INIT); long ellrank, i, l = lg(vec); ellrank = prank(bid_get_cyc(bid), ell); M = cgetg(l,t_MAT); for (i=1; i1) err_printf("beta reduced = %Ps\n",be); return be; } static GEN get_Selmer(GEN bnf, GEN cycgen, long rc) { GEN fu = bnf_get_fu_nocheck(bnf), tu = bnf_get_tuU(bnf); GEN units = matalgtobasis(bnf,shallowconcat(fu,tu)); return shallowconcat(units, vecslice(cycgen,1,rc)); } GEN lift_if_rational(GEN x) { long lx, i; GEN y; switch(typ(x)) { default: break; case t_POLMOD: y = gel(x,2); if (typ(y) == t_POL) { long d = degpol(y); if (d > 0) return x; return (d < 0)? gen_0: gel(y,2); } return y; case t_POL: lx = lg(x); for (i=2; i= lW; ) { for (j=dK; j > 0; j--) if (coeff(K, i, j)) break; if (!j) { /* Do our best to ensure that K[dK,i] != 0 */ if (coeff(K, i, dK)) continue; for (j = idx; j < dK; j++) if (coeff(K, i, j) && coeff(K, Kidx[j], dK) != ell - 1) Flv_add_inplace(gel(K,dK), gel(K,j), ell); } if (j != --idx) swap(gel(K, j), gel(K, idx)); Kidx[idx] = i; if (coeff(K,i,idx) != 1) Flc_Fl_div_inplace(gel(K,idx), coeff(K,i,idx), ell); Ki = gel(K,idx); if (coeff(K,i,dK) != 1) { ulong t = Fl_sub(coeff(K,i,dK), 1, ell); Flv_sub_inplace(gel(K,dK), Flc_Fl_mul(Ki, t, ell), ell); } for (j = dK; --j > 0; ) { if (j == idx) continue; if (coeff(K,i,j)) Flv_sub_inplace(gel(K,j), Flc_Fl_mul(Ki, coeff(K,i,j), ell), ell); } } /* ffree = first vector that is not "free" for the scalar products */ ffree = idx; /* Second step: for each hyperplane equation in vecMsup, do the same * thing as before. */ for (i=1; i < lg(vecMsup); i++) { GEN Msup = gel(vecMsup,i); ulong dotprod; if (lgcols(Msup) != 2) continue; Msup = row_zm(Msup, 1); for (j=ffree; --j > 0; ) { dotprod = Flv_dotproduct(Msup, gel(K,j), ell); if (dotprod) { if (j != --ffree) swap(gel(K, j), gel(K, ffree)); if (dotprod != 1) Flc_Fl_div_inplace(gel(K, ffree), dotprod, ell); break; } } if (!j) { /* Do our best to ensure that vecMsup.K[dK] != 0 */ if (Flv_dotproduct(Msup, gel(K,dK), ell) == 0) { for (j = ffree-1; j <= dK; j++) if (Flv_dotproduct(Msup, gel(K,j), ell) && coeff(K,Kidx[j],dK) != ell-1) Flv_add_inplace(gel(K,dK), gel(K,j), ell); } continue; } Ki = gel(K,ffree); dotprod = Flv_dotproduct(Msup, gel(K,dK), ell); if (dotprod != 1) { ulong t = Fl_sub(dotprod,1,ell); Flv_sub_inplace(gel(K,dK), Flc_Fl_mul(Ki,t,ell), ell); } for (j = dK; --j > 0; ) { if (j == ffree) continue; dotprod = Flv_dotproduct(Msup, gel(K,j), ell); if (dotprod) Flv_sub_inplace(gel(K,j), Flc_Fl_mul(Ki,dotprod,ell), ell); } } if (ell == 2) { for (i = ffree, j = ffree-1; i <= dK && j; i++, j--) { swap(gel(K,i), gel(K,j)); } } /* Try to ensure that y = vec_ei(n, i) gives a good candidate */ for (i = 1; i < dK; i++) Flv_add_inplace(gel(K,i), gel(K,dK), ell); return gerepilecopy(av, K); } static GEN Flm_init(long m, long n) { GEN M = cgetg(n+1, t_MAT); long i; for (i = 1; i <= n; i++) gel(M,i) = cgetg(m+1, t_VECSMALL); return M; } static void Flv_fill(GEN v, GEN y) { long i, l = lg(y); for (i = 1; i < l; i++) v[i] = y[i]; } /* if all!=0, give all equations of degree 'all'. Assume bnr modulus is the * conductor */ static GEN rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all) { long ell, i, j, degK, dK; long lSml2, lSl2, lSp, rc, lW; long prec; long rk=0, ncyc=0; GEN mat=NULL, matgrp=NULL, xell, be1 = NULL; long firstpass = all<0; GEN bnf,nf,bid,ideal,arch,cycgen; GEN cyc; GEN Sp,listprSp,matP; GEN res=NULL,u,M,K,y,vecMsup,vecW,vecWB,vecBp,msign; primlist L; bnf = bnr_get_bnf(bnr); (void)bnf_get_fu(bnf); nf = bnf_get_nf(bnf); degK = nf_get_degree(nf); bid = bnr_get_bid(bnr); ideal= bid_get_ideal(bid); arch = bid_get_arch(bid); /* this is the conductor */ ell = itos(gell); i = build_list_Hecke(&L, nf, gel(bid,3), ideal, gell, NULL); if (i) return no_sol(all,i); lSml2 = lg(L.Sml2)-1; Sp = shallowconcat(L.Sm, L.Sml1); lSp = lg(Sp)-1; listprSp = shallowconcat(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1; cycgen = check_and_build_cycgen(bnf); cyc = bnf_get_cyc(bnf); rc = prank(cyc, ell); vecW = get_Selmer(bnf, cycgen, rc); u = get_u(cyc, rc, gell); vecBp = cgetg(lSp+1, t_VEC); matP = cgetg(lSp+1, t_MAT); for (j=1; j<=lSp; j++) { GEN L = isprincipalell(bnf,gel(Sp,j), cycgen,u,gell,rc); gel( matP,j) = gel(L,1); gel(vecBp,j) = gel(L,2); } vecWB = shallowconcat(vecW, vecBp); prec = DEFAULTPREC + nbits2extraprec(((degK-1) * (gexpo(vecWB) + gexpo(nf_get_M(nf))))); if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec); msign = nfsign(nf, vecWB); arch = ZV_to_zv(arch); vecMsup = cgetg(lSml2+1,t_VEC); M = NULL; for (i=1; i<=lSl2; i++) { GEN pr = gel(listprSp,i); long e = pr_get_e(pr), z = ell * (e / (ell-1)); if (i <= lSml2) { z += 1 - L.ESml2[i]; gel(vecMsup,i) = logall(nf, vecWB, 0,0, ell, pr,z+1); } M = vconcat(M, logall(nf, vecWB, 0,0, ell, pr,z)); } lW = lg(vecW); M = vconcat(M, shallowconcat(zero_Flm(rc,lW-1), ZM_to_Flm(matP, ell))); K = Flm_ker(M, ell); dK = lg(K)-1; if (all < 0) K = fix_kernel(K, M, vecMsup, lW, ell); y = cgetg(dK+1,t_VECSMALL); if (all) res = cgetg(1,t_VEC); /* in case all = 1 */ if (all < 0) { ncyc = dK; mat = Flm_init(dK, ncyc); if (all == -1) matgrp = Flm_init(lg(bnr_get_cyc(bnr)), ncyc+1); rk = 0; } xell = monomial(gen_1, ell, 0); do { dK = lg(K)-1; while (dK) { for (i=1; im, T->tau), 0); long i, l = lg(P); for (i=2; i Cl_m(K), lift subgroup from bnr to bnrz using Algo 4.1.11 */ static GEN invimsubgroup(GEN bnrz, GEN bnr, GEN subgroup, toK_s *T) { long l, j; GEN P,raycycz,rayclgpz,raygenz,U,polrel,StZk; GEN nf = checknf(bnr), nfz = checknf(bnrz); GEN polz = nf_get_pol(nfz), zkz = nf_get_zk(nfz); polrel = polrelKzK(T, pol_x(varn(polz))); StZk = Stelt(nf, zkz, polrel); rayclgpz = gel(bnrz,5); raycycz = gel(rayclgpz,2); l = lg(raycycz); raygenz = gel(rayclgpz,3); P = cgetg(l,t_MAT); for (j=1; j= varn(x) */ static GEN split_pol(GEN x, long v, long a, long b) { long i, l = degpol(x); GEN y = x + a, z; if (l < b) b = l; if (a > b || varn(x) != v) return pol_0(v); l = b-a + 3; z = cgetg(l, t_POL); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = gel(y,i); return normalizepol_lg(z, l); } /* return (den_a * z) mod (v^ell - num_a/den_a), assuming deg(z) < 2*ell * allow either num/den to be NULL (= 1) */ static GEN mod_Xell_a(GEN z, long v, long ell, GEN num_a, GEN den_a) { GEN z1 = split_pol(z, v, ell, degpol(z)); GEN z0 = split_pol(z, v, 0, ell-1); /* z = v^ell z1 + z0*/ if (den_a) z0 = gmul(den_a, z0); if (num_a) z1 = gmul(num_a, z1); return gadd(z0, z1); } static GEN to_alg(GEN nfz, GEN 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); return z; } /* th. 5.3.5. and prop. 5.3.9. */ static GEN compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell) { long i, k, m = T->m, vT = 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; r = cgetg(m+1,t_VECSMALL); /* r[i+1] = g^i mod ell */ r[1] = 1; for (i=2; i<=m; i++) r[i] = (r[i-1] * g) % ell; powtaubet = powtau(be, m, T->tau); if (DEBUGLEVEL>1) { err_printf("Computing Newton sums: "); timer_start(&ti); } prim_invbe = Q_primitive_part(nfinv(nfz, be), &C_invbe); powtau_prim_invbe = powtau(prim_invbe, m, T->tau); root = cgetg(ell + 2, t_POL); root[1] = evalsigne(1) | evalvarn(0); for (i = 0; i < ell; i++) gel(root,2+i) = gen_0; for (i = 0; i < m; i++) { /* compute (1/be) ^ (-mu) instead of be^mu [mu << 0]. * 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)); 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); } /* Other roots are as above with z_ell --> z_ell^j. * Treat all contents (C_*) and principal parts (prim_*) separately */ 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))); num_t = Q_remove_denom(p1, &den_t); nfzpol = leafcopy(nf_get_pol(nfz)); setvarn(nfzpol, MAXVARN); S = cgetg(ell+1, t_VEC); /* Newton sums */ gel(S,1) = gen_0; for (k = 2; k <= ell; k++) { /* compute the k-th Newton sum */ pari_sp av = avma; GEN z, D, Rk = gmul(prim_Rk, prim_root); C_Rk = mul_content(C_Rk, C_root); Rk = mod_Xell_a(Rk, 0, ell, NULL, NULL); /* mod X^ell - 1 */ for (i = 2; i < lg(Rk); i++) { if (typ(gel(Rk,i)) != t_POL) continue; z = mod_Xell_a(gel(Rk,i), vT, ell, num_t,den_t); /* mod T^ell - t */ gel(Rk,i) = RgXQX_red(z, nfzpol); /* mod nfz.pol */ } if (den_t) C_Rk = mul_content(C_Rk, ginv(den_t)); prim_Rk = Q_primitive_part(Rk, &D); C_Rk = mul_content(C_Rk, D); /* root^k = prim_Rk * C_Rk */ /* Newton sum is ell * constant coeff (in X), which has degree 0 in T */ z = polcoeff_i(prim_Rk, 0, 0); z = polcoeff_i(z , 0,vT); z = downtoK(T, gmulgs(z, ell)); if (C_Rk) z = gmul(z, C_Rk); gerepileall(av, C_Rk? 3: 2, &z, &prim_Rk, &C_Rk); if (DEBUGLEVEL>1) { err_printf("%ld(%ld) ", k, timer_delay(&ti)); err_flush(); } gel(S,k) = z; } if (DEBUGLEVEL>1) err_printf("\n"); (void)delete_var(); return pol_from_Newton(S); } static GEN lifttoKz(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)); if (typ(x) != t_POL) return gel(I,1); gel(I,2) = algtobasis(nfz, RgX_RgXQ_eval(x, C->p, C->R)); return idealhnf_two(nfz,I); } static void compositum_red(compo_s *C, GEN P, GEN Q) { GEN p, q, a, z = gel(compositum2(P, Q),1); a = gel(z,1); p = gel(gel(z,2), 2); q = gel(gel(z,3), 2); C->k = itos( gel(z,4) ); /* reduce R. FIXME: should be polredbest(a, 1), but breaks rnfkummer bench */ z = polredabs0(a, nf_ORIG|nf_PARTIALFACT); C->R = gel(z,1); a = gel(gel(z,2), 2); C->p = RgX_RgXQ_eval(p, a, C->R); C->q = RgX_RgXQ_eval(q, a, C->R); C->rev = QXQ_reverse(a, C->R); if (DEBUGLEVEL>1) err_printf("polred(compositum) = %Ps\n",C->R); } /* replace P->C^(-deg P) P(xC) for the largest integer C such that coefficients * remain algebraic integers. Lift *rational* coefficients */ static void nfX_Z_normalize(GEN nf, GEN P) { long i, l; GEN C, Cj, PZ = cgetg_copy(P, &l); PZ[1] = P[1]; for (i = 2; i < l; i++) /* minor variation on RgX_to_nfX (create PZ) */ { GEN z = nf_to_scalar_or_basis(nf, gel(P,i)); if (typ(z) == t_INT) gel(PZ,i) = gel(P,i) = z; else gel(PZ,i) = ZV_content(z); } (void)ZX_Z_normalize(PZ, &C); if (C == gen_1) return; Cj = C; for (i = l-2; i > 1; i--) { if (i != l-2) Cj = mulii(Cj, C); gel(P,i) = gdiv(gel(P,i), Cj); } } static GEN _rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { long ell, i, j, m, d, dK, dc, rc, ru, rv, g, mginv, degK, degKz, vnf; long lSp, lSml2, lSl2, lW; GEN polnf,bnf,nf,bnfz,nfz,bid,ideal,cycgen,gell,p1,p2,vselmer; 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; primlist L; toK_s T; tau_s _tau, *tau; compo_s COMPO; pari_timer t; long rk=0, ncyc=0; GEN mat=NULL; long firstpass = all<0; if (DEBUGLEVEL) timer_start(&t); checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); polnf = nf_get_pol(nf); vnf = varn(polnf); if (!vnf) pari_err_PRIORITY("rnfkummer", polnf, "=", 0); /* step 7 */ p1 = bnrconductor(bnr, subgroup, 2); if (DEBUGLEVEL) timer_printf(&t, "[rnfkummer] conductor"); bnr = gel(p1,2); subgroup = gel(p1,3); gell = get_gell(bnr,subgroup,all); ell = itos(gell); if (ell == 1) return pol_x(0); if (!uisprime(ell)) pari_err_IMPL("kummer for composite relative degree"); if (all && all != -1 && umodiu(bnr_get_no(bnr), ell)) return cgetg(1, t_VEC); if (bnf_get_tuN(bnf) % ell == 0) return rnfkummersimple(bnr, subgroup, gell, all); if (all == -1) all = 0; bid = bnr_get_bid(bnr); ideal = bid_get_ideal(bid); /* step 1 of alg 5.3.5. */ if (DEBUGLEVEL>2) err_printf("Step 1\n"); compositum_red(&COMPO, polnf, polcyclo(ell,vnf)); /* step 2 */ if (DEBUGLEVEL>2) err_printf("Step 2\n"); if (DEBUGLEVEL) timer_printf(&t, "[rnfkummer] compositum"); degK = degpol(polnf); degKz = degpol(COMPO.R); m = degKz / degK; d = (ell-1) / m; g = (long)Fl_powu(pgener_Fl(ell), d, ell); if (Fl_powu((ulong)g, m, ell*ell) == 1) g += ell; /* ord(g) = m in all (Z/ell^k)^* */ /* step 3 */ if (DEBUGLEVEL>2) err_printf("Step 3\n"); /* could factor disc(R) using th. 2.1.6. */ bnfz = Buchall(COMPO.R, nf_FORCE, maxss(prec,BIGDEFAULTPREC)); if (DEBUGLEVEL) timer_printf(&t, "[rnfkummer] bnfinit(Kz)"); cycgen = check_and_build_cycgen(bnfz); nfz = bnf_get_nf(bnfz); cyc = bnf_get_cyc(bnfz); rc = prank(cyc,ell); gen = bnf_get_gen(bnfz); u = get_u(cyc, rc, gell); vselmer = get_Selmer(bnfz, cycgen, rc); if (DEBUGLEVEL) timer_printf(&t, "[rnfkummer] Selmer group"); ru = (degKz>>1)-1; rv = rc+ru+1; tau = get_tau(&_tau, nfz, &COMPO, g); /* step 4 */ if (DEBUGLEVEL>2) err_printf("Step 4\n"); vecB=cgetg(rc+1,t_VEC); Tc=cgetg(rc+1,t_MAT); for (j=1; j<=rc; j++) { p1 = tauofideal(gel(gen,j), tau); p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc); Tc[j] = p1[1]; vecB[j]= p1[2]; } vecC = cgetg(rc+1,t_VEC); if (rc) { for (j=1; j<=rc; j++) gel(vecC,j) = cgetg(1, t_MAT); p1 = cgetg(m,t_VEC); gel(p1,1) = matid(rc); for (j=2; j<=m-1; j++) gel(p1,j) = gmul(gel(p1,j-1),Tc); p2 = vecB; for (j=1; j<=m-1; j++) { GEN z = FpM_red(gmulsg((j*d)%ell,gel(p1,m-j)), gell); p2 = tauofvec(p2, tau); for (i=1; i<=rc; i++) gel(vecC,i) = famat_mul(gel(vecC,i), famat_factorback(p2,gel(z,i))); } for (i=1; i<=rc; i++) gel(vecC,i) = famat_reduce(gel(vecC,i)); } /* step 5 */ if (DEBUGLEVEL>2) err_printf("Step 5\n"); Tv = cgetg(rv+1,t_MAT); for (j=1; j<=rv; j++) { p1 = tauofelt(gel(vselmer,j), tau); if (typ(p1) == t_MAT) /* famat */ p1 = nffactorback(nfz, gel(p1,1), FpC_red(gel(p1,2),gell)); gel(Tv,j) = isvirtualunit(bnfz, p1, cycgen,cyc,gell,rc); } P = FpM_ker(RgM_Rg_add_shallow(Tv, stoi(-g)), gell); lW = lg(P); vecW = cgetg(lW,t_VEC); for (j=1; j2) err_printf("Step 6\n"); Q = FpM_ker(RgM_Rg_add_shallow(shallowtrans(Tc), stoi(-g)), gell); /* step 8 */ if (DEBUGLEVEL>2) err_printf("Step 8\n"); p1 = RgXQ_matrix_pow(COMPO.p, degKz, degK, COMPO.R); T.invexpoteta1 = RgM_inv(p1); /* left inverse */ T.polnf = polnf; T.tau = tau; T.m = m; idealz = lifttoKz(nfz, nf, ideal, &COMPO); if (smodis(gcoeff(ideal,1,1), ell)) gothf = idealz; else { /* ell | N(ideal) */ GEN bnrz = Buchray(bnfz, idealz, nf_INIT|nf_GEN); GEN subgroupz = invimsubgroup(bnrz, bnr, subgroup, &T); gothf = bnrconductor(bnrz,subgroupz,0); } /* step 9, 10, 11 */ if (DEBUGLEVEL>2) err_printf("Step 9, 10 and 11\n"); i = build_list_Hecke(&L, nfz, NULL, gothf, gell, tau); if (i) return no_sol(all,i); lSml2 = lg(L.Sml2)-1; Sp = shallowconcat(L.Sm, L.Sml1); lSp = lg(Sp)-1; listprSp = shallowconcat(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1; /* step 12 */ if (DEBUGLEVEL>2) err_printf("Step 12\n"); 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; 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; i2) err_printf("Step 13\n"); vecWA = shallowconcat(vecW, vecAp); vecWB = shallowconcat(vecW, vecBp); /* step 14, 15, and 17 */ if (DEBUGLEVEL>2) err_printf("Step 14, 15 and 17\n"); mginv = (m * Fl_inv(g,ell)) % ell; vecMsup = cgetg(lSml2+1,t_VEC); M = NULL; for (i=1; i<=lSl2; i++) { GEN pr = gel(listprSp,i); long e = pr_get_e(pr), z = ell * (e / (ell-1)); if (i <= lSml2) { z += 1 - L.ESml2[i]; gel(vecMsup,i) = logall(nfz, vecWA,lW,mginv,ell, pr,z+1); } M = vconcat(M, logall(nfz, vecWA,lW,mginv,ell, pr,z)); } dc = lg(Q)-1; if (dc) { GEN QtP = gmul(shallowtrans(Q), matP); M = vconcat(M, shallowconcat(zero_Flm(dc,lW-1), ZM_to_Flm(QtP,ell))); } if (!M) M = zero_Flm(1, lSp + lW - 1); /* step 16 */ if (DEBUGLEVEL>2) err_printf("Step 16\n"); K = Flm_ker(M, ell); if (all < 0) K = fix_kernel(K, M, vecMsup, lW, ell); /* step 18 & ff */ if (DEBUGLEVEL>2) err_printf("Step 18\n"); dK = lg(K)-1; y = cgetg(dK+1,t_VECSMALL); if (all) res = cgetg(1, t_VEC); if (DEBUGLEVEL) timer_printf(&t, "[rnfkummer] candidate list"); if (all < 0) { ncyc = dK; rk = 0; mat = zero_Flm(lg(M)-1, ncyc); } do { dK = lg(K)-1; while (dK) { for (i=1; i1) err_printf("polrel(beta) = %Ps\n", P); if (!all) { H = rnfnormgroup(bnr, P); if (ZM_equal(subgroup, H)) return P; /* DONE */ avma = av; continue; } else { GEN P0 = Q_primpart(lift(P)); GEN g = nfgcd(P0, RgX_deriv(P0), polnf, nf_get_index(nf)); if (degpol(g)) continue; H = rnfnormgroup(bnr, P); if (!ZM_equal(subgroup,H) && !bnrisconductor(bnr,H)) continue; } P = gerepilecopy(av, P); res = shallowconcat(res, P); if (all < 0 && rk == ncyc) return res; if (firstpass) break; } } while (increment(y, dK, ell)); y[dK--] = 0; } } while (firstpass--); if (all) return res; return gen_0; /* FAIL */ } GEN rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { pari_sp av = avma; return gerepilecopy(av, _rnfkummer(bnr, subgroup, all, prec)); } pari-2.7.5/src/modules/stark.c0000644000175000017500000030432512612420067014644 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* COMPUTATION OF STARK UNITS OF TOTALLY REAL FIELDS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define EXTRA_PREC (DEFAULTPREC-1) #define ADD_PREC (DEFAULTPREC-2)*3 /* ComputeCoeff */ typedef struct { GEN L0, L1, L11, L2; /* VECSMALL of p */ GEN L1ray, L11ray; /* precomputed isprincipalray(pr), pr | p */ GEN rayZ; /* precomputed isprincipalray(i), i < condZ */ long condZ; /* generates cond(bnr) \cap Z, assumed small */ } LISTray; /* Char evaluation */ typedef struct { long ord; GEN *val, chi; } CHI_t; /* RecCoeff */ typedef struct { GEN M, beta, B, U, nB; long v, G, N; } RC_data; /********************************************************************/ /* Miscellaneous functions */ /********************************************************************/ /* exp(2iPi/den), assume den a t_INT */ static GEN InitRU(GEN den, long prec) { GEN c, s; if (equaliu(den, 2)) return gen_m1; gsincos(divri(Pi2n(1, prec), den), &s, &c, prec); return mkcomplex(c, s); } /* Compute the image of logelt by character chi, as a complex number */ static GEN ComputeImagebyChar(GEN chi, GEN logelt) { GEN gn = ZV_dotproduct(gel(chi,1), logelt), x = gel(chi,2); long d = itos(gel(chi,3)), n = smodis(gn, d); /* x^d = 1 and, if d even, x^(d/2) = -1 */ if ((d & 1) == 0) { d /= 2; if (n >= d) return gneg(gpowgs(x, n-d)); } return gpowgs(x, n); } /* return n such that C(elt) = z^n */ static ulong EvalChar_n(CHI_t *C, GEN logelt) { GEN n = ZV_dotproduct(C->chi, logelt); return umodiu(n, C->ord); } /* return C(elt) */ static GEN EvalChar(CHI_t *C, GEN logelt) { return C->val[EvalChar_n(C, logelt)]; } static void init_CHI(CHI_t *c, GEN CHI, GEN z) { long i, d = itos(gel(CHI,3)); GEN *v = (GEN*)new_chunk(d); v[0] = gen_1; v[1] = z; for (i=2; ichi = gel(CHI,1); c->ord = d; c->val = v; } /* as t_POLMOD */ static void init_CHI_alg(CHI_t *c, GEN CHI) { long d = itos(gel(CHI,3)); GEN z; switch(d) { case 1: z = gen_1; break; case 2: z = gen_m1; break; default: z = mkpolmod(pol_x(0), polcyclo(d,0)); } init_CHI(c,CHI, z); } /* as t_COMPLEX */ static void init_CHI_C(CHI_t *c, GEN CHI) { init_CHI(c,CHI, gel(CHI,2)); } /* Compute the conjugate character [ZV] */ static GEN ConjChar(GEN chi, GEN cyc) { long i, l = lg(chi); GEN z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = signe(gel(chi,i))? subii(gel(cyc,i), gel(chi,i)): gen_0; return z; } typedef struct { long r; /* rank = lg(gen) */ GEN j; /* current elt is gen[1]^j[1] ... gen[r]^j[r] */ GEN cyc; /* t_VECSMALL of elementary divisors */ } GROUP_t; static int NextElt(GROUP_t *G) { long i = 1; if (G->r == 0) return 0; /* no more elt */ while (++G->j[i] == G->cyc[i]) /* from 0 to cyc[i]-1 */ { G->j[i] = 0; if (++i > G->r) return 0; /* no more elt */ } return i; /* we have multiplied by gen[i] */ } /* Compute all the elements of a group given by its SNF */ static GEN EltsOfGroup(long order, GEN cyc) { long i; GEN rep; GROUP_t G; G.cyc = gtovecsmall(cyc); G.r = lg(cyc)-1; G.j = zero_zv(G.r); rep = cgetg(order + 1, t_VEC); gel(rep,order) = vecsmall_to_col(G.j); for (i = 1; i < order; i++) { (void)NextElt(&G); gel(rep,i) = vecsmall_to_col(G.j); } return rep; } /* Let dataC as given by InitQuotient, compute a system of representatives of the quotient */ static GEN ComputeLift(GEN dataC) { long order, i; pari_sp av = avma; GEN cyc, surj, eltq, elt; order = itos(gel(dataC,1)); cyc = gel(dataC,2); surj = gel(dataC,3); eltq = EltsOfGroup(order, cyc); elt = cgetg(order + 1, t_VEC); for (i = 1; i <= order; i++) gel(elt,i) = inverseimage(surj, gel(eltq,i)); return gerepileupto(av, elt); } /* Return c[1], [c[1]/c[1] = 1,...,c[1]/c[n]] */ static GEN init_get_chic(GEN c) { long i, l = lg(c); GEN C, D = cgetg(l, t_VEC); if (l == 1) C = gen_1; else { C = gel(c,1); gel(D,1) = gen_1; for (i = 2; i < l; i++) gel(D,i) = diviiexact(C, gel(c,i)); } return mkvec2(C, D); } static GEN get_chic(GEN chi, GEN D) { long i, l = lg(chi); GEN chic = cgetg(l, t_VEC); if (l > 1) { gel(chic,1) = gel(chi,1); for (i = 2; i < l; i++) gel(chic,i) = mulii(gel(chi,i), gel(D,i)); } return chic; } /* A character is given by a vector [(c_i), z, d] such that chi(id) = z ^ sum(c_i * a_i) where a_i= log(id) on the generators of bnr z = exp(2i * Pi / d) */ /* U is NULL or a ZM */ static GEN get_Char(GEN chi, GEN initc, GEN U, long prec) { GEN d, chic = get_chic(chi, gel(initc,2)); if (U) chic = ZV_ZM_mul(chic, U); d = ZV_content(chic); if (!signe(d)) d = gen_1; else if (is_pm1(d)) d = gel(initc,1); else { GEN t = gred_frac2(gel(initc,1), d); chic = ZC_Z_divexact(chic, d); if (typ(t) == t_INT) d = t; else { d = gel(t,1); chic = gmul(gel(t,2), chic); } } return mkvec3(chic, InitRU(d, prec), d); } /* prime divisors of conductor */ static GEN divcond(GEN bnr) { GEN bid = bnr_get_bid(bnr); return gmael(bid,3,1); } /* vector of prime ideals dividing bnr but not bnrc */ static GEN get_prdiff(GEN bnr, GEN condc) { GEN prdiff, M = gel(condc,1), D = divcond(bnr), nf = bnr_get_nf(bnr); long nd, i, l = lg(D); prdiff = cgetg(l, t_COL); for (nd=1, i=1; i < l; i++) if (!idealval(nf, M, gel(D,i))) gel(prdiff,nd++) = gel(D,i); setlg(prdiff, nd); return prdiff; } /* Let chi a character defined over bnr and primitive over bnrc, compute the * corresponding primitive character. Returns NULL if bnr = bnrc */ static GEN GetPrimChar(GEN chi, GEN bnr, GEN bnrc, long prec) { long l; pari_sp av = avma; GEN U, M, cond, condc, initc, Mrc; cond = bnr_get_mod(bnr); condc = bnr_get_mod(bnrc); if (gequal(cond, condc)) return NULL; initc = init_get_chic(bnr_get_cyc(bnr)); Mrc = diagonal_shallow(bnr_get_cyc(bnrc)); M = bnrsurjection(bnr, bnrc); (void)ZM_hnfall(shallowconcat(M, Mrc), &U, 1); l = lg(M); U = rowslice(vecslice(U, l, lg(U)-1), 1, l-1); return gerepilecopy(av, get_Char(chi, initc, U, prec)); } #define ch_chi(x) gel(x,1) #define ch_C(x) gel(x,2) #define ch_bnr(x) gel(x,3) #define ch_4(x) gel(x,4) #define ch_CHI(x) gel(x,5) #define ch_diff(x) gel(x,6) #define ch_cond(x) gel(x,7) #define ch_CHI0(x) gel(x,8) #define ch_comp(x) gel(x,9) static GEN GetDeg(GEN dataCR) { long i, l = lg(dataCR); GEN degs = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) degs[i] = eulerphiu(itou(gel(ch_CHI(gel(dataCR, i)), 3))); return degs; } /********************************************************************/ /* 1rst part: find the field K */ /********************************************************************/ static GEN AllStark(GEN data, GEN nf, long flag, long prec); /* Columns of C [HNF] give the generators of a subgroup of the finite abelian * group A [ in terms of implicit generators ], compute data to work in A/C: * 1) order * 2) structure * 3) the matrix A ->> A/C * 4) the group C */ static GEN InitQuotient(GEN C) { long junk; GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = detcyc(D, &junk); return mkvec4(h, D, U, C); } /* Let s: A -> B given by P, and let cycA, cycB be the cyclic structure of * A and B, compute the kernel of s. */ static GEN ComputeKernel0(GEN P, GEN cycA, GEN cycB) { pari_sp av = avma; long nbA = lg(cycA)-1, rk; GEN U, DB = diagonal_shallow(cycB); rk = nbA + lg(cycB) - lg(ZM_hnfall(shallowconcat(P, DB), &U, 1)); U = vecslice(U, 1,rk); U = rowslice(U, 1,nbA); return gerepileupto(av, ZM_hnfmodid(U, cycA)); } /* Let m and n be two moduli such that n|m and let C be a congruence group modulo n, compute the corresponding congruence group modulo m ie the kernel of the map Clk(m) ->> Clk(n)/C */ static GEN ComputeKernel(GEN bnrm, GEN bnrn, GEN dtQ) { pari_sp av = avma; GEN P = ZM_mul(gel(dtQ,3), bnrsurjection(bnrm, bnrn)); return gerepileupto(av, ComputeKernel0(P, bnr_get_cyc(bnrm), gel(dtQ,2))); } static GEN Order(GEN cyc, GEN x) { pari_sp av = avma; long i, l = lg(cyc); GEN c,o,f = gen_1; for (i = 1; i < l; i++) { o = gel(cyc,i); c = gcdii(o, gel(x,i)); if (!is_pm1(c)) o = diviiexact(o,c); f = lcmii(f, o); } return gerepileuptoint(av, f); } /* Let H be a subgroup of cl(bnr)/sugbroup, return 1 if cl(bnr)/subgoup/H is cyclic and the signature of the corresponding field is equal to sig and no finite prime dividing cond(bnr) is totally split in this field. Return 0 otherwise. */ static long IsGoodSubgroup(GEN H, GEN bnr, GEN map) { pari_sp av = avma; long j, f; GEN bnf, mod, mod0, mod1, modH, modH0, p1, p2, p3, p4; GEN bnrH, cycH, iH, qH; p1 = InitQuotient(H); p2 = gel(p1, 2); /* quotient is non cyclic */ if ((lg(p2) > 2) && !gequal1(gel(p2, 2))) { avma = av; return 0; } bnf = bnr_get_bnf(bnr); mod = bnr_get_mod(bnr); mod0 = gel(mod,1); mod1 = gel(mod,2); p1 = concat(map, H); p2 = ZM_hnfall(p1, &p3, 0); setlg(p3, lg(H)); for (j = 1; j < lg(p3); j++) setlg(p3[j], lg(H)); p1 = ZM_hnfmodid(p3, bnr_get_cyc(bnr)); /* H as a subgroup of bnr */ modH = bnrconductor(bnr, p1, 0); /* is the signature correct? */ if (!gequal(gel(modH, 2), mod1)) { avma = av; return 0; } /* if the finite part are the same, then it's good */ if (gequal(gel(modH, 1), mod0)) { avma = av; return 1; } /* we need to check the splitting of primes dividing mod0/p2 */ modH0 = gel(modH, 1); p3 = idealdivexact(bnf, mod0, modH0); p4 = gel(idealfactor(bnf, p3), 1); bnrH = Buchray(bnf, mkvec2(modH, mod1), nf_INIT|nf_GEN); cycH = bnr_get_cyc(bnrH); p2 = ZM_mul(bnrsurjection(bnr, bnrH), p1); /* H as a subgroup of bnrH */ iH = ZM_hnfmodid(p2, cycH); qH = InitQuotient(iH); for (j = 1; j < lg(p4); j++) { GEN pr = gel(p4, j); /* if pr divides modH0, it is ramified, so it's good */ if (!idealval(bnf, modH0, pr)) { /* we compute the inertia degree of pr in bnr(modH)/H*/ p1 = ZM_ZC_mul(gel(qH, 3), isprincipalray(bnrH, pr)); p2 = gel(qH, 2); f = itos(Order(p2, p1)); if (f == 1) { avma = av; return 0; } } } avma = av; return 1; } static GEN get_listCR(GEN bnr, GEN dtQ); static GEN InitChar(GEN bnr, GEN listCR, long prec); /* Given a conductor and a subgroups, return the corresponding complexity and precision required using quickpol. Fill data[5] with listCR */ static long CplxModulus(GEN data, long *newprec) { long pr, ex, dprec = DEFAULTPREC; pari_sp av; GEN pol, listCR, cpl, bnr = gel(data,1), nf = checknf(bnr); listCR = get_listCR(bnr, gel(data,3)); for (av = avma;; avma = av) { gel(data,5) = InitChar(bnr, listCR, dprec); pol = AllStark(data, nf, -1, dprec); pr = nbits2extraprec( gexpo(pol) ); if (pr < 0) pr = 0; dprec = maxss(dprec, pr) + EXTRA_PREC; if (!gequal0(leading_term(pol))) { cpl = RgX_fpnorml2(pol, DEFAULTPREC); if (!gequal0(cpl)) break; } if (DEBUGLEVEL>1) pari_warn(warnprec, "CplxModulus", dprec); } ex = gexpo(cpl); avma = av; if (DEBUGLEVEL>1) err_printf("cpl = 2^%ld\n", ex); gel(data,5) = listCR; *newprec = dprec; return ex; } /* Let f be a conductor without infinite part and let C be a congruence group modulo f, compute (m,D) such that D is a congruence group of conductor m where m is a multiple of f divisible by all the infinite places but one, D is a subgroup of index 2 of Im(C) in Clk(m), and m is such that the intersection of the subgroups H of Clk(n)/Im(C) such that the quotient is cyclic and no prime divding m, but the one infinite prime, is totally split in the extension corresponding to H is trival. Return bnr(m), D, the quotient Ck(m)/D and Clk(m)/C */ static GEN FindModulus(GEN bnr, GEN dtQ, long *newprec) { const long limnorm = 400; long n, i, narch, maxnorm, minnorm, N, nbidnn, s, c, j, k, nbcand; long first = 1, pr, rb, oldcpl = -1, iscyc = 0; pari_sp av = avma, av1; GEN bnf, nf, f, arch, m, listid, idnormn, bnrm, ImC, rep = NULL; GEN candD, p2; bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); f = gel(bnr_get_mod(bnr), 1); /* if cpl < rb, it is not necessary to try another modulus */ rb = expi( powii(mulii(nf_get_disc(nf), ZM_det_triangular(f)), gmul2n(bnr_get_no(bnr), 3)) ); /* Initialization of the possible infinite part */ arch = const_vec(N, gen_1); /* narch = (N == 2)? 1: N; -- if N=2, only one case is necessary */ narch = N; m = mkvec2(NULL, arch); /* go from minnorm up to maxnorm. If necessary, increase these values. * If we cannot find a suitable conductor of norm < limnorm, stop */ maxnorm = 50; minnorm = 1; /* if the extension is cyclic then we _must_ find a suitable conductor */ if (lg(gel(dtQ,2)) == 2 || gequal1(gmael(dtQ,2,2))) iscyc = 1; if (DEBUGLEVEL>1) err_printf("Looking for a modulus of norm: "); for(;;) { listid = ideallist(nf, maxnorm); /* all ideals of norm <= maxnorm */ av1 = avma; for (n = minnorm; n <= maxnorm; n++) { if (DEBUGLEVEL>1) err_printf(" %ld", n); avma = av1; idnormn = gel(listid,n); nbidnn = lg(idnormn) - 1; for (i = 1; i <= nbidnn; i++) { /* finite part of the conductor */ gel(m,1) = idealmul(nf, f, gel(idnormn,i)); for (s = 1; s <= narch; s++) { /* infinite part */ gel(arch,N+1-s) = gen_0; /* compute Clk(m), check if m is a conductor */ bnrm = Buchray(bnf, m, nf_INIT|nf_GEN); c = bnrisconductor(bnrm, NULL); gel(arch,N+1-s) = gen_1; if (!c) continue; /* compute Im(C) in Clk(m)... */ ImC = ComputeKernel(bnrm, bnr, dtQ); /* ... and its subgroups of index 2 with conductor m */ candD = subgrouplist_cond_sub(bnrm, ImC, mkvec(gen_2)); nbcand = lg(candD) - 1; for (c = 1; c <= nbcand; c++) { GEN D = gel(candD,c); long cpl; /* check if the conductor is suitable */ { GEN p1 = InitQuotient(D), p2, ord = gel(p1, 1); GEN map = gel(p1, 3), cyc = gel(p1, 2), H; GEN lH = subgrouplist(cyc, NULL), IK = NULL; long ok = 0; /* if the extension is cyclic, then it's suitable */ if ((lg(cyc) > 2) && !gequal1(gel(cyc, 2))) { for (j = 1; j < lg(lH); j++) { H = gel(lH, j); /* if IK != NULL and H > IK, no need to test H */ if (IK) { p1 = RgM_mul(IK, RgM_inv_upper(H)); if (RgM_is_ZM(p1)) continue; } if (IsGoodSubgroup(H, bnrm, map)) { if (!IK) IK = H; else { /* compute the intersection of IK and H */ p1 = shallowconcat(IK, H); p1 = ZM_hnfall(p1, &p2, 1); setlg(p2, lg(IK)); for (k = 1; k < lg(p2); k++) setlg(p2[k], lg(p1)); IK = ZM_mul(IK, p2); IK = ZM_hnf(shallowconcat(IK, diagonal(cyc))); } if (gequal(ord, ZM_det_triangular(IK))) { ok = 1; break; } } } if (!ok) continue; } } p2 = cgetg(6, t_VEC); /* p2[5] filled in CplxModulus */ gel(p2,1) = bnrm; gel(p2,2) = D; gel(p2,3) = InitQuotient(D); gel(p2,4) = InitQuotient(ImC); if (DEBUGLEVEL>1) err_printf("\nTrying modulus = %Ps and subgroup = %Ps\n", bnr_get_mod(bnrm), D); cpl = CplxModulus(p2, &pr); if (oldcpl < 0 || cpl < oldcpl) { *newprec = pr; if (rep) gunclone(rep); rep = gclone(p2); oldcpl = cpl; } if (oldcpl < rb) goto END; /* OK */ if (DEBUGLEVEL>1) err_printf("Trying to find another modulus..."); first = 0; } } if (!first) goto END; /* OK */ } } /* if necessary compute more ideals */ minnorm = maxnorm; maxnorm <<= 1; if (!iscyc && maxnorm > limnorm) return NULL; } END: if (DEBUGLEVEL>1) err_printf("No, we're done!\nModulus = %Ps and subgroup = %Ps\n", bnr_get_mod(gel(rep,1)), gel(rep,2)); gel(rep,5) = InitChar(gel(rep,1), gel(rep,5), *newprec); return gerepilecopy(av, rep); } /********************************************************************/ /* 2nd part: compute W(X) */ /********************************************************************/ /* compute the list of W(chi) such that Ld(s,chi) = W(chi) Ld(1 - s, chi*), * for all chi in LCHI. All chi have the same conductor (= cond(bnr)). * if check == 0 do not check the result */ 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; 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; CHI_t **lC; GROUP_t G; lC = (CHI_t**)new_chunk(nChar + 1); indW = cgetg(nChar + 1, t_VECSMALL); W = cgetg(nChar + 1, t_VEC); for (ic = 0, i = 1; i <= nChar; i++) { GEN CHI = gel(LCHI,i); if (cmpui(2, gel(CHI,3)) >= 0) { gel(W,i) = gen_1; continue; } /* trivial case */ ic++; indW[ic] = i; lC[ic] = (CHI_t*)new_chunk(sizeof(CHI_t)); init_CHI_C(lC[ic], CHI); } if (!ic) return W; nChar = ic; nf = bnr_get_nf(bnr); diff = nf_get_diff(nf); T = nf_get_Tr(nf); cond = bnr_get_mod(bnr); cond0 = gel(cond,1); condZ = gcoeff(cond0,1,1); cond1 = vec01_to_indices(gel(cond,2)); sqrtnc = gsqrt(idealnorm(nf, cond0), prec); dc = idealmul(nf, diff, cond0); /* compute a system of elements congruent to 1 mod cond0 and giving all possible signatures for cond1 */ sarch = nfarchstar(nf, cond0, cond1); /* find lambda in diff.cond such that gcd(lambda.(diff.cond)^-1,cond0) = 1 and lambda >> 0 at cond1 */ lambda = idealappr(nf, dc); lambda = set_sign_mod_divisor(nf, NULL, lambda, cond,sarch); idg = idealdivexact(nf, lambda, dc); /* find mu in idg such that idh=(mu) / idg is coprime with cond0 and mu >> 0 at cond1 */ if (!gequal1(gcoeff(idg, 1, 1))) { GEN P = divcond(bnr); GEN f = famat_mul_shallow(idealfactor(nf, idg), mkmat2(P, zerocol(lg(P)-1))); GEN mu = set_sign_mod_divisor(nf, NULL, idealapprfact(nf, f), cond,sarch); idh = idealdivexact(nf, mu, idg); muslambda = nfdiv(nf, mu, lambda); } else { /* mu = 1 */ idh = idg; muslambda = nfinv(nf, lambda); } muslambda = Q_remove_denom(muslambda, &den); z = den? InitRU(den, prec): NULL; /* compute a system of generators of (Ok/cond)^*, we'll make them * cond1-positive in the main loop */ zid = Idealstar(nf, cond0, nf_GEN); cyc = gel(zid, 2); gen = gel(zid, 3); nz = lg(gen) - 1; nchi = cgetg(nChar+1, t_VEC); for (ic = 1; ic <= nChar; ic++) gel(nchi,ic) = cgetg(nz + 1, t_VECSMALL); for (i = 1; i <= nz; i++) { if (is_bigint(gel(cyc,i))) pari_err_OVERFLOW("ArtinNumber [conductor too large]"); gel(gen,i) = set_sign_mod_divisor(nf, NULL, gel(gen,i), cond,sarch); classe = isprincipalray(bnr, gel(gen,i)); for (ic = 1; ic <= nChar; ic++) { GEN n = gel(nchi,ic); n[i] = EvalChar_n(lC[ic], classe); } } /* Sum chi(beta) * exp(2i * Pi * Tr(beta * mu / lambda) where beta runs through the classes of (Ok/cond0)^* and beta cond1-positive */ vt = gel(T,1); /* ( Tr(w_i) )_i */ vt = ZV_ZM_mul(vt, zk_multable(nf, muslambda)); /*den (Tr(w_i mu/lambda))_i */ G.cyc = gtovecsmall(cyc); G.r = nz; G.j = zero_zv(nz); 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); vB = const_vec(nz, gen_1); s0 = z? powgi(z, modii(gel(vt,1), den)): gen_1; /* for beta = 1 */ s = const_vec(nChar, s0); while ( (i = NextElt(&G)) ) { gel(vB,i) = FpC_red(nfmuli(nf, gel(vB,i), gel(gen,i)), condZ); for (j=1; jord); for (j=1; jval[ n[i] ]; gel(s,ic) = gadd(gel(s,ic), gmul(val, s0)); } if (low_stack(lim, stack_lim(av2, 1))) { if (DEBUGMEM > 1) pari_warn(warnmem,"ArtinNumber"); gerepileall(av2, 2, &s, &vB); } } classe = isprincipalray(bnr, idh); z = powIs(- (lg(cond1)-1)); for (ic = 1; ic <= nChar; ic++) { s0 = gmul(gel(s,ic), EvalChar(lC[ic], classe)); s0 = gdiv(s0, sqrtnc); if (check && - expo(subrs(gnorm(s0), 1)) < prec2nbits(prec) >> 1) pari_err_BUG("ArtinNumber"); gel(W, indW[ic]) = gmul(s0, z); } return gerepilecopy(av, W); } static GEN ComputeAllArtinNumbers(GEN dataCR, GEN vChar, int check, long prec) { long j, k, cl = lg(dataCR) - 1, J = lg(vChar)-1; GEN W = cgetg(cl+1,t_VEC), WbyCond, LCHI; for (j = 1; j <= J; j++) { GEN LChar = gel(vChar,j), ldata = vecpermute(dataCR, LChar); GEN dtcr = gel(ldata,1), bnr = ch_bnr(dtcr); long l = lg(LChar); if (DEBUGLEVEL>1) err_printf("* Root Number: cond. no %ld/%ld (%ld chars)\n", j, J, l-1); LCHI = cgetg(l, t_VEC); for (k = 1; k < l; k++) gel(LCHI,k) = ch_CHI0(gel(ldata,k)); WbyCond = ArtinNumber(bnr, LCHI, check, prec); for (k = 1; k < l; k++) W[LChar[k]] = WbyCond[k]; } return W; } static GEN SingleArtinNumber(GEN bnr, GEN chi, long prec) { return gel(ArtinNumber(bnr, mkvec(chi), 1, prec), 1); } /* compute the constant W of the functional equation of Lambda(chi). If flag = 1 then chi is assumed to be primitive */ GEN bnrrootnumber(GEN bnr, GEN chi, long flag, long prec) { long l; pari_sp av = avma; GEN cond, condc, bnrc, CHI, cyc; if (flag < 0 || flag > 1) pari_err_FLAG("bnrrootnumber"); checkbnr(bnr); cyc = bnr_get_cyc(bnr); cond = bnr_get_mod(bnr); l = lg(cyc); if (typ(chi) != t_VEC || lg(chi) != l) pari_err_TYPE("bnrrootnumber [character]", chi); if (flag) condc = NULL; else { condc = bnrconductorofchar(bnr, chi); if (gequal(cond, condc)) flag = 1; } if (flag) { GEN initc = init_get_chic(cyc); bnrc = bnr; CHI = get_Char(chi, initc, NULL, prec); } else { bnrc = Buchray(bnr_get_bnf(bnr), condc, nf_INIT|nf_GEN); CHI = GetPrimChar(chi, bnr, bnrc, prec); } return gerepilecopy(av, SingleArtinNumber(bnrc, CHI, prec)); } /********************************************************************/ /* 3rd part: initialize the characters */ /********************************************************************/ /* returns a ZV */ static GEN LiftChar(GEN cyc, GEN Mat, GEN chi, GEN D) { long lm = lg(cyc), l = lg(chi), i, j; GEN lchi = cgetg(lm, t_VEC); for (i = 1; i < lm; i++) { pari_sp av = avma; GEN t, s = mulii(gel(chi,1), gcoeff(Mat, 1, i)); for (j = 2; j < l; j++) { /* rarely exercised: D[1]/D[j] could be precomputed */ t = mulii(gel(chi,j), diviiexact(gel(D,1), gel(D,j))); s = addii(s, mulii(t, gcoeff(Mat, j, i))); } t = diviiexact(mulii(s, gel(cyc,i)), gel(D,1)); gel(lchi,i) = gerepileuptoint(av, modii(t, gel(cyc,i))); } return lchi; } /* Let chi be a character, A(chi) corresponding to the primes dividing diff at s = flag. If s = 0, returns [r, A] where r is the order of vanishing at s = 0 corresponding to diff. No GC */ static GEN ComputeAChi(GEN dtcr, long *r, long flag, long prec) { long l, i; GEN A, diff, chi, bnrc; bnrc = ch_bnr(dtcr); diff = ch_diff(dtcr); l = lg(diff); chi = ch_CHI0(dtcr); A = gen_1; *r = 0; for (i = 1; i < l; i++) { GEN pr = gel(diff,i), B; GEN z = ComputeImagebyChar(chi, isprincipalray(bnrc, pr)); if (flag) B = gsubsg(1, gdiv(z, pr_norm(pr))); else if (gequal1(z)) { B = glog(pr_norm(pr), prec); (*r)++; } else B = gsubsg(1, z); A = gmul(A, B); } return A; } /* simplified version of ComputeAchi: return 1 if L(0,chi) = 0 */ static int L_vanishes_at_0(GEN dtcr) { long l, i; GEN diff, chi, bnrc; bnrc = ch_bnr(dtcr); diff = ch_diff(dtcr); l = lg(diff); chi = ch_CHI0(dtcr); for (i = 1; i < l; i++) { GEN pr = gel(diff,i); GEN z = ComputeImagebyChar(chi, isprincipalray(bnrc, pr)); if (gequal1(z)) return 1; } return 0; } static GEN _data4(GEN arch, long r1, long r2) { GEN z = cgetg(5, t_VECSMALL); long i, b, q = 0; for (i=1; i<=r1; i++) if (signe(gel(arch,i))) q++; z[1] = q; b = r1 - q; z[2] = b; z[3] = r2; z[4] = maxss(b+r2+1, r2+q); return z; } /* Given a list [chi, F = cond(chi)] of characters over Cl(bnr), compute a vector dataCR containing for each character: 2: the constant C(F) [t_REAL] 3: bnr(F) 4: [q, r1 - q, r2, rc] where q = number of real places in F rc = max{r1 + r2 - q + 1, r2 + q} 6: diff(chi) primes dividing m but not F 7: finite part of F 1: chi 5: [(c_i), z, d] in bnr(m) 8: [(c_i), z, d] in bnr(F) 9: if NULL then does not compute (for AllStark) */ static GEN InitChar(GEN bnr, GEN listCR, long prec) { GEN bnf = checkbnf(bnr), nf = bnf_get_nf(bnf); GEN modul, dk, C, dataCR, chi, cond, initc; long N, r1, r2, prec2, i, j, l; pari_sp av = avma; modul = bnr_get_mod(bnr); dk = nf_get_disc(nf); N = nf_get_degree(nf); nf_get_sign(nf, &r1,&r2); prec2 = precdbl(prec) + EXTRA_PREC; C = gmul2n(sqrtr_abs(divir(dk, powru(mppi(prec2),N))), -r2); initc = init_get_chic( bnr_get_cyc(bnr) ); dataCR = cgetg_copy(listCR, &l); for (i = 1; i < l; i++) { GEN olddtcr, dtcr = cgetg(10, t_VEC); gel(dataCR,i) = dtcr; chi = gmael(listCR, i, 1); cond = gmael(listCR, i, 2); /* do we already know the invariants of chi? */ olddtcr = NULL; for (j = 1; j < i; j++) if (gequal(cond, gmael(listCR,j,2))) { olddtcr = gel(dataCR,j); break; } if (!olddtcr) { 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) = cond; if (gequal(cond,modul)) { ch_bnr(dtcr) = bnr; ch_diff(dtcr) = cgetg(1, t_VEC); } else { ch_bnr(dtcr) = Buchray(bnf, cond, nf_INIT|nf_GEN); ch_diff(dtcr) = get_prdiff(bnr, cond); } } else { ch_C(dtcr) = ch_C(olddtcr); ch_bnr(dtcr) = ch_bnr(olddtcr); ch_4(dtcr) = ch_4(olddtcr); ch_diff(dtcr) = ch_diff(olddtcr); ch_cond(dtcr) = ch_cond(olddtcr); } ch_chi(dtcr) = chi; /* the character */ ch_CHI(dtcr) = get_Char(chi,initc,NULL,prec); /* associated to bnr(m) */ ch_comp(dtcr) = gen_1; /* compute this character (by default) */ chi = GetPrimChar(chi, bnr, ch_bnr(dtcr), prec2); if (!chi) chi = ch_CHI(dtcr); ch_CHI0(dtcr) = chi; } return gerepilecopy(av, dataCR); } /* compute the list of characters to consider for AllStark and initialize precision-independent data to compute with them */ static GEN get_listCR(GEN bnr, GEN dtQ) { GEN MrD, listCR, vecchi, lchi, Surj, cond, Mr, d, allCR; long hD, h, nc, i, j, tnc; Surj = gel(dtQ,3); MrD = gel(dtQ,2); Mr = bnr_get_cyc(bnr); hD = itos(gel(dtQ,1)); h = hD >> 1; listCR = cgetg(h + 1, t_VEC); /* non-conjugate characters */ nc = 1; allCR = cgetg(h + 1, t_VEC); /* all characters, including conjugates */ tnc = 1; vecchi = EltsOfGroup(hD, MrD); for (i = 1; tnc <= h; i++) { /* lift a character of D in Clk(m) */ lchi = LiftChar(Mr, Surj, gel(vecchi,i), MrD); for (j = 1; j < tnc; j++) if (ZV_equal(lchi, gel(allCR,j))) break; if (j != tnc) continue; cond = bnrconductorofchar(bnr, lchi); if (gequal0(gel(cond,2))) continue; /* the infinite part of chi is non trivial */ gel(listCR,nc++) = mkvec2(lchi, cond); gel(allCR,tnc++) = lchi; /* if chi is not real, add its conjugate character to allCR */ d = Order(Mr, lchi); if (!equaliu(d, 2)) gel(allCR,tnc++) = ConjChar(lchi, Mr); } setlg(listCR, nc); return listCR; } /* recompute dataCR with the new precision */ static GEN CharNewPrec(GEN dataCR, GEN nf, long prec) { GEN dk, C, p1; long N, l, j, prec2; dk = nf_get_disc(nf); N = nf_get_degree(nf); prec2 = precdbl(prec) + EXTRA_PREC; C = sqrtr(divir(absi(dk), powru(mppi(prec2), N))); l = lg(dataCR); for (j = 1; j < l; j++) { 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; p1 = ch_CHI( dtcr); gel(p1,2) = InitRU(gel(p1,3), prec2); p1 = ch_CHI0(dtcr); gel(p1,2) = InitRU(gel(p1,3), prec2); } return dataCR; } /********************************************************************/ /* 4th part: compute the coefficients an(chi) */ /* */ /* matan entries are arrays of ints containing the coefficients of */ /* an(chi) as a polmod modulo polcyclo(order(chi)) */ /********************************************************************/ static void _0toCoeff(int *rep, long deg) { long i; for (i=0; i i - deg) c += c0[j] * c1[i-j]; T[i] = c; } for (i = 0; i < deg; i++) { c = T[i]; for (j = 0; j < deg; j++) c += reduc[j][i] * T[deg+j]; c0[i] = c; } } /* c0 <- c0 + c1 * c2 */ static void AddMulCoeff(int *c0, int *c1, int* c2, int** reduc, long deg) { long i, j; pari_sp av; int c, *t; if (IsZero(c2,deg)) return; if (!c1) /* c1 == 1 */ { for (i = 0; i < deg; i++) c0[i] += c2[i]; return; } av = avma; t = (int*)new_chunk(2*deg); /* = c1 * c2, not reduced */ for (i = 0; i < 2*deg; i++) { c = 0; for (j = 0; j <= i; j++) if (j < deg && j > i - deg) c += c1[j] * c2[i-j]; t[i] = c; } for (i = 0; i < deg; i++) { c = t[i]; for (j = 0; j < deg; j++) c += reduc[j][i] * t[deg+j]; c0[i] += c; } avma = av; } /* evaluate the Coeff. No Garbage collector */ static GEN EvalCoeff(GEN z, int* c, long deg) { long i,j; GEN e, r; if (!c) return gen_0; #if 0 /* standard Horner */ e = stoi(c[deg - 1]); for (i = deg - 2; i >= 0; i--) e = gadd(stoi(c[i]), gmul(z, e)); #else /* specific attention to sparse polynomials */ e = NULL; for (i = deg-1; i >=0; i=j-1) { for (j=i; c[j] == 0; j--) if (j==0) { if (!e) return NULL; if (i!=j) z = gpowgs(z,i-j+1); return gmul(e,z); } if (e) { r = (i==j)? z: gpowgs(z,i-j+1); e = gadd(gmul(e,r), stoi(c[j])); } else e = stoi(c[j]); } #endif return e; } /* copy the n * (m+1) array matan */ static void CopyCoeff(int** a, int** a2, long n, long m) { long i,j; for (i = 1; i <= n; i++) { int *b = a[i], *b2 = a2[i]; for (j = 0; j < m; j++) b2[j] = b[j]; } } /* return q*p if <= n. Beware overflow */ static long next_pow(long q, long p, long n) { const GEN x = muluu((ulong)q, (ulong)p); const ulong qp = (ulong)x[2]; return (lgefint(x) > 3 || qp > (ulong)n)? 0: qp; } static void an_AddMul(int **an,int **an2, long np, long n, long deg, GEN chi, int **reduc) { GEN chi2 = chi; long q, qk, k; int *c, *c2 = (int*)new_chunk(deg); CopyCoeff(an, an2, n/np, deg); for (q=np;;) { if (gequal1(chi2)) c = NULL; else { Polmod2Coeff(c2, chi2, deg); c = c2; } for(k = 1, qk = q; qk <= n; k++, qk += q) AddMulCoeff(an[qk], c, an2[k], reduc, deg); if (! (q = next_pow(q,np, n)) ) break; chi2 = gmul(chi2, chi); } } /* correct the coefficients an(chi) according with diff(chi) in place */ static void CorrectCoeff(GEN dtcr, int** an, int** reduc, long n, long deg) { pari_sp av = avma; long lg, j, np; pari_sp av1; int **an2; GEN bnrc, diff, chi, pr; CHI_t C; diff = ch_diff(dtcr); lg = lg(diff) - 1; if (!lg) return; if (DEBUGLEVEL>2) err_printf("diff(CHI) = %Ps", diff); bnrc = ch_bnr(dtcr); init_CHI_alg(&C, ch_CHI0(dtcr)); an2 = InitMatAn(n, deg, 0); av1 = avma; for (j = 1; j <= lg; j++) { pr = gel(diff,j); np = itos( pr_norm(pr) ); chi = EvalChar(&C, isprincipalray(bnrc, pr)); an_AddMul(an,an2,np,n,deg,chi,reduc); avma = av1; } FreeMat(an2, n); avma = av; } /* compute the coefficients an in the general case */ static int** ComputeCoeff(GEN dtcr, LISTray *R, long n, long deg) { pari_sp av = avma, av2; long i, l, np; int **an, **reduc, **an2; GEN L, CHI, chi; CHI_t C; CHI = ch_CHI(dtcr); init_CHI_alg(&C, CHI); an = InitMatAn(n, deg, 0); an2 = InitMatAn(n, deg, 0); reduc = InitReduction(CHI, deg); av2 = avma; L = R->L1; l = lg(L); for (i=1; iL1ray,i)); an_AddMul(an,an2,np,n,deg,chi,reduc); } FreeMat(an2, n); CorrectCoeff(dtcr, an, reduc, n, deg); FreeMat(reduc, deg-1); avma = av; return an; } /********************************************************************/ /* 5th part: compute L-functions at s=1 */ /********************************************************************/ static void deg11(LISTray *R, long p, GEN bnr, GEN pr) { GEN z = isprincipalray(bnr, pr); vecsmalltrunc_append(R->L1, p); vectrunc_append(R->L1ray, z); } static void deg12(LISTray *R, long p, GEN bnr, GEN Lpr) { GEN z = isprincipalray(bnr, gel(Lpr,1)); vecsmalltrunc_append(R->L11, p); vectrunc_append(R->L11ray, z); } static void 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) { pari_sp av = avma; GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1); long p,i,l, condZ = itos(gcoeff(cond,1,1)), contZ = itos(content(cond)); GEN prime, Lpr, nf = bnf_get_nf(bnf), dk = nf_get_disc(nf); forprime_t T; l = 1 + PiBound(N0); R->L0 = vecsmalltrunc_init(l); R->L2 = vecsmalltrunc_init(l); R->condZ = condZ; R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l); R->L11= vecsmalltrunc_init(l); R->L11ray= vectrunc_init(l); prime = utoipos(2); u_forprime_init(&T, 2, N0); while ( (p = u_forprime_next(&T)) ) { prime[2] = p; switch (kroiu(dk, p)) { case -1: /* inert */ if (condZ % p == 0) deg0(R,p); else deg2(R,p); break; case 1: /* split */ Lpr = idealprimedec(nf, prime); if (condZ % p != 0) deg12(R, p, bnr, Lpr); else if (contZ % p == 0) deg0(R,p); else { GEN pr = idealval(nf, cond, gel(Lpr,1))? gel(Lpr,2): gel(Lpr,1); deg11(R, p, bnr, pr); } break; default: /* ramified */ if (condZ % p == 0) deg0(R,p); else { GEN pr = gel(idealprimedec(nf,prime),1); deg11(R, p, bnr, pr); } break; } } /* precompute isprincipalray(x), x in Z */ R->rayZ = cgetg(condZ, t_VEC); for (i=1; irayZ,i) = (ugcd(i,condZ) == 1)? isprincipalray(bnr, utoipos(i)): gen_0; gerepileall(av, 7, &(R->L0), &(R->L2), &(R->rayZ), &(R->L1), &(R->L1ray), &(R->L11), &(R->L11ray) ); } static void 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); forprime_t T; R->condZ = condZ; l = PiBound(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); 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); 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); gel(tmpray,j) = gclone( isprincipalray(bnr, pr) ); } avma = av; for (k = 1; k < j; k++) { if (!tmpray[k]) continue; vectrunc_append(R->L1ray, ZC_copy(gel(tmpray,k))); gunclone(gel(tmpray,k)); } } } static GEN /* cf polcoeff */ _sercoeff(GEN x, long n) { long i = n - valp(x); return (i < 0)? gen_0: gel(x,i+2); } static void affect_coeff(GEN q, long n, GEN y) { GEN x = _sercoeff(q,-n); if (x == gen_0) gel(y,n) = NULL; else affgr(x, gel(y,n)); } typedef struct { GEN c1, aij, bij, cS, cT, powracpi; long i0, a,b,c, r, rc1, rc2; } ST_t; /* compute the principal part at the integers s = 0, -1, -2, ..., -i0 of Gamma((s+1)/2)^a Gamma(s/2)^b Gamma(s)^c / (s - z) with z = 0 and 1 */ /* NOTE: surely not the best way to do this, but it's fast enough! */ static void ppgamma(ST_t *T, long prec) { GEN eul, gam,gamun,gamdm, an,bn,cn_evn,cn_odd, x,x2,X,Y, cf, sqpi; GEN p1, p2, aij, bij; long a = T->a; long b = T->b; long c = T->c, r = T->r, i0 = T->i0; long i,j, s,t; pari_sp av; aij = cgetg(i0+1, t_VEC); bij = cgetg(i0+1, t_VEC); for (i = 1; i <= i0; i++) { gel(aij,i) = p1 = cgetg(r+1, t_VEC); gel(bij,i) = p2 = cgetg(r+1, t_VEC); for (j=1; j<=r; j++) { gel(p1,j) = cgetr(prec); gel(p2,j) = cgetr(prec); } } av = avma; x = pol_x(0); x2 = gmul2n(x, -1); /* x/2 */ eul = mpeuler(prec); sqpi= sqrtr_abs(mppi(prec)); /* Gamma(1/2) */ /* expansion of log(Gamma(u)) at u = 1 */ gamun = cgetg(r+3, t_SER); gamun[1] = evalsigne(1) | _evalvalp(0) | evalvarn(0); gel(gamun,2) = gen_0; gel(gamun,3) = gneg(eul); for (i = 2; i <= r; i++) gel(gamun,i+2) = divrs(szeta(i,prec), odd(i)? -i: i); gamun = gexp(gamun, prec); /* Gamma(1 + x) */ gam = gdiv(gamun,x); /* Gamma(x) */ /* expansion of log(Gamma(u) / Gamma(1/2)) at u = 1/2 */ gamdm = cgetg(r+3, t_SER); gamdm[1] = evalsigne(1) | _evalvalp(0) | evalvarn(0); gel(gamdm,2) = gen_0; gel(gamdm,3) = gneg(gadd(gmul2n(mplog2(prec), 1), eul)); for (i = 2; i <= r; i++) gel(gamdm,i+2) = mulri(gel(gamun,i+2), subis(int2n(i), 1)); gamdm = gmul(sqpi, gexp(gamdm, prec)); /* Gamma(1/2 + x) */ /* We simplify to get one of the following two expressions * if (b > a) : sqrt{Pi}^a 2^{a-au} Gamma(u)^{a+c} Gamma( u/2 )^{|b-a|} * if (b <= a): sqrt{Pi}^b 2^{b-bu} Gamma(u)^{b+c} Gamma((u+1)/2)^{|b-a|} */ if (b > a) { t = a; s = b; X = x2; Y = gsub(x2,ghalf); p1 = ser_unscale(gam, ghalf); p2 = gdiv(ser_unscale(gamdm,ghalf), Y); /* Gamma((x-1)/2) */ } else { t = b; s = a; X = gadd(x2,ghalf); Y = x2; p1 = ser_unscale(gamdm,ghalf); p2 = ser_unscale(gam,ghalf); } cf = powru(sqpi, t); an = gpowgs(gpow(gen_2, gsubsg(1,x), prec), t); /* 2^{t-tx} */ bn = gpowgs(gam, t+c); /* Gamma(x)^{t+c} */ cn_evn = gpowgs(p1, s-t); /* Gamma(X)^{s-t} */ cn_odd = gpowgs(p2, s-t); /* Gamma(Y)^{s-t} */ for (i = 0; i < i0/2; i++) { GEN C1,q1, A1 = gel(aij,2*i+1), B1 = gel(bij,2*i+1); GEN C2,q2, A2 = gel(aij,2*i+2), B2 = gel(bij,2*i+2); C1 = gmul(cf, gmul(bn, gmul(an, cn_evn))); p1 = gdiv(C1, gsubgs(x, 2*i)); q1 = gdiv(C1, gsubgs(x, 2*i+1)); /* an(x-u-1) = 2^t an(x-u) */ an = gmul2n(an, t); /* bn(x-u-1) = bn(x-u) / (x-u-1)^{t+c} */ bn = gdiv(bn, gpowgs(gsubgs(x, 2*i+1), t+c)); C2 = gmul(cf, gmul(bn, gmul(an, cn_odd))); p2 = gdiv(C2, gsubgs(x, 2*i+1)); q2 = gdiv(C2, gsubgs(x, 2*i+2)); for (j = 1; j <= r; j++) { affect_coeff(p1, j, A1); affect_coeff(q1, j, B1); affect_coeff(p2, j, A2); affect_coeff(q2, j, B2); } an = gmul2n(an, t); bn = gdiv(bn, gpowgs(gsubgs(x, 2*i+2), t+c)); /* cn_evn(x-2i-2) = cn_evn(x-2i) / (X - (i+1))^{s-t} */ /* cn_odd(x-2i-3) = cn_odd(x-2i-1)/ (Y - (i+1))^{s-t} */ cn_evn = gdiv(cn_evn, gpowgs(gsubgs(X,i+1), s-t)); cn_odd = gdiv(cn_odd, gpowgs(gsubgs(Y,i+1), s-t)); } T->aij = aij; T->bij = bij; avma = av; } static GEN _cond(GEN dtcr) { return mkvec2(ch_cond(dtcr), ch_4(dtcr)); } /* sort chars according to conductor */ static GEN sortChars(GEN dataCR) { const long cl = lg(dataCR) - 1; GEN vCond = cgetg(cl+1, t_VEC); GEN CC = cgetg(cl+1, t_VECSMALL); GEN nvCond = cgetg(cl+1, t_VECSMALL); long j,k, ncond; GEN vChar; for (j = 1; j <= cl; j++) nvCond[j] = 0; ncond = 0; for (j = 1; j <= cl; j++) { GEN cond = _cond(gel(dataCR,j)); for (k = 1; k <= ncond; k++) if (gequal(cond, gel(vCond,k))) break; if (k > ncond) gel(vCond,++ncond) = cond; nvCond[k]++; CC[j] = k; /* char j has conductor number k */ } vChar = cgetg(ncond+1, t_VEC); for (k = 1; k <= ncond; k++) { gel(vChar,k) = cgetg(nvCond[k]+1, t_VECSMALL); nvCond[k] = 0; } for (j = 1; j <= cl; j++) { k = CC[j]; nvCond[k]++; mael(vChar,k,nvCond[k]) = j; } return vChar; } /* Given W(chi), S(chi) and T(chi), return L(1, chi) if fl & 1, else [r(chi), c(chi)] where L(s, chi) ~ c(chi) s^r(chi) at s = 0. If fl & 2, adjust the value to get L_S(s, chi). */ static GEN GetValue(GEN dtcr, GEN W, GEN S, GEN T, long fl, long prec) { pari_sp av = avma; GEN cf, z, p1; long q, b, c, r; int isreal = (itos(gel(ch_CHI0(dtcr), 3)) <= 2); p1 = ch_4(dtcr); q = p1[1]; b = p1[2]; c = p1[3]; if (fl & 1) { /* S(chi) + W(chi).T(chi)) / (C(chi) sqrt(Pi)^{r1 - q}) */ cf = gmul(ch_C(dtcr), powruhalf(mppi(prec), b)); z = gadd(S, gmul(W, T)); if (isreal) z = real_i(z); z = gdiv(z, cf); if (fl & 2) z = gmul(z, ComputeAChi(dtcr, &r, 1, prec)); } else { /* (W(chi).S(conj(chi)) + T(chi)) / (sqrt(Pi)^q 2^{r1 - q}) */ cf = gmul2n(powruhalf(mppi(prec), q), b); z = gadd(gmul(W, gconj(S)), gconj(T)); if (isreal) z = real_i(z); z = gdiv(z, cf); r = 0; if (fl & 2) z = gmul(z, ComputeAChi(dtcr, &r, 0, prec)); z = mkvec2(utoi(b + c + r), z); } return gerepilecopy(av, z); } /* return the order and the first non-zero term of L(s, chi0) at s = 0. If flag != 0, adjust the value to get L_S(s, chi0). */ static GEN GetValue1(GEN bnr, long flag, long prec) { GEN bnf = checkbnf(bnr), nf = bnf_get_nf(bnf); GEN h, R, c, diff; long i, l, r, r1, r2; pari_sp av = avma; nf_get_sign(nf, &r1,&r2); h = bnf_get_no(bnf); R = bnf_get_reg(bnf); c = gneg_i(gdivgs(mpmul(h, R), bnf_get_tuN(bnf))); r = r1 + r2 - 1; if (flag) { diff = divcond(bnr); l = lg(diff) - 1; r += l; for (i = 1; i <= l; i++) c = gmul(c, glog(pr_norm(gel(diff,i)), prec)); } return gerepilecopy(av, mkvec2(stoi(r), c)); } /********************************************************************/ /* 6th part: recover the coefficients */ /********************************************************************/ static long TestOne(GEN plg, RC_data *d) { long j, v = d->v; GEN z = gsub(d->beta, gel(plg,v)); if (expo(z) >= d->G) return 0; for (j = 1; j < lg(plg); j++) if (j != v && mpcmp(d->B, mpabs(gel(plg,j))) < 0) return 0; return 1; } static GEN chk_reccoeff_init(FP_chk_fun *chk, GEN r, GEN mat) { RC_data *d = (RC_data*)chk->data; (void)r; d->U = mat; return d->nB; } static GEN chk_reccoeff(void *data, GEN x) { RC_data *d = (RC_data*)data; GEN v = gmul(d->U, x), z = gel(v,1); if (!gequal1(z)) return NULL; *++v = evaltyp(t_COL) | evallg( lg(d->M) ); if (TestOne(gmul(d->M, v), d)) return v; return NULL; } /* Using Cohen's method */ static GEN RecCoeff3(GEN nf, RC_data *d, long prec) { GEN A, M, nB, cand, p1, B2, C2, tB, beta2, nf2, Bd; GEN beta = d->beta, B = d->B; long N = d->N, v = d->v, e, BIG; long i, j, k, l, ct = 0, prec2; FP_chk_fun chk = { &chk_reccoeff, &chk_reccoeff_init, NULL, NULL, 0 }; chk.data = (void*)d; d->G = minss(-10, -prec2nbits(prec) >> 4); BIG = maxss(32, -(d->G << 1)); tB = sqrtnr(real2n(BIG-N,DEFAULTPREC), N-1); Bd = grndtoi(gmin(B, tB), &e); if (e > 0) return NULL; /* failure */ Bd = addis(Bd, 1); prec2 = nbits2prec( expi(Bd) + 192 ); prec2 = maxss(precdbl(prec), prec2); B2 = sqri(Bd); C2 = shifti(B2, BIG<<1); LABrcf: ct++; beta2 = gprec_w(beta, prec2); nf2 = nfnewprec_shallow(nf, prec2); d->M = M = nf_get_M(nf2); A = cgetg(N+2, t_MAT); for (i = 1; i <= N+1; i++) gel(A,i) = cgetg(N+2, t_COL); gcoeff(A, 1, 1) = gadd(gmul(C2, gsqr(beta2)), B2); for (j = 2; j <= N+1; j++) { p1 = gmul(C2, gmul(gneg_i(beta2), gcoeff(M, v, j-1))); gcoeff(A, 1, j) = gcoeff(A, j, 1) = p1; } for (i = 2; i <= N+1; i++) for (j = i; j <= N+1; j++) { p1 = gen_0; for (k = 1; k <= N; k++) { GEN p2 = gmul(gcoeff(M, k, j-1), gcoeff(M, k, i-1)); if (k == v) p2 = gmul(C2, p2); p1 = gadd(p1,p2); } gcoeff(A, i, j) = gcoeff(A, j, i) = p1; } nB = mului(N+1, B2); d->nB = nB; cand = fincke_pohst(A, nB, -1, prec2, &chk); if (!cand) { if (ct > 3) return NULL; prec2 = precdbl(prec2); if (DEBUGLEVEL>1) pari_warn(warnprec,"RecCoeff", prec2); goto LABrcf; } cand = gel(cand,1); l = lg(cand) - 1; if (l == 1) return coltoalg(nf, gel(cand,1)); if (DEBUGLEVEL>1) err_printf("RecCoeff3: no solution found!\n"); return NULL; } /* Using linear dependance relations */ static GEN RecCoeff2(GEN nf, RC_data *d, long prec) { pari_sp av; GEN vec, M = nf_get_M(nf), beta = d->beta; long i, imin, imax, lM = lg(M); d->G = minss(-20, -prec2nbits(prec) >> 4); vec = shallowconcat(mkvec(gneg(beta)), row(M, d->v)); imin = (long)prec2nbits_mul(prec, .225); imax = (long)prec2nbits_mul(prec, .315); av = avma; for (i = imax; i >= imin; i-=16, avma = av) { long e; GEN v = lindep2(vec, i), z = gel(v,1); if (!signe(z)) continue; *++v = evaltyp(t_COL) | evallg(lM); v = grndtoi(gdiv(v, z), &e); if (e > 0) break; if (TestOne(gmul(M, v), d)) return coltoalg(nf, v); } /* failure */ return RecCoeff3(nf,d,prec); } /* Attempts to find a polynomial with coefficients in nf such that its coefficients are close to those of pol at the place v and less than B at all the other places */ static GEN RecCoeff(GEN nf, GEN pol, long v, long prec) { long j, md, cl = degpol(pol); pari_sp av = avma; RC_data d; /* if precision(pol) is too low, abort */ for (j = 2; j <= cl+1; j++) { GEN t = gel(pol, j); if (prec2nbits(gprecision(t)) - gexpo(t) < 34) return NULL; } md = cl/2; pol = leafcopy(pol); d.N = nf_get_degree(nf); d.v = v; for (j = 1; j <= cl; j++) { /* start with the coefficients in the middle, since they are the harder to recognize! */ long cf = md + (j%2? j/2: -j/2); GEN t, bound = shifti(binomial(utoipos(cl), cf), cl-cf); if (DEBUGLEVEL>1) err_printf("RecCoeff (cf = %ld, B = %Ps)\n", cf, bound); d.beta = real_i( gel(pol,cf+2) ); d.B = bound; if (! (t = RecCoeff2(nf, &d, prec)) ) return NULL; gel(pol, cf+2) = t; } gel(pol,cl+2) = gen_1; return gerepilecopy(av, pol); } /* an[q * i] *= chi for all (i,p)=1 */ static void an_mul(int **an, long p, long q, long n, long deg, GEN chi, int **reduc) { pari_sp av; long c,i; int *T; if (gequal1(chi)) return; av = avma; T = (int*)new_chunk(deg); Polmod2Coeff(T,chi, deg); for (c = 1, i = q; i <= n; i += q, c++) if (c == p) c = 0; else MulCoeff(an[i], T, reduc, deg); avma = av; } /* an[q * i] = 0 for all (i,p)=1 */ static void an_set0_coprime(int **an, long p, long q, long n, long deg) { long c,i; for (c = 1, i = q; i <= n; i += q, c++) if (c == p) c = 0; else _0toCoeff(an[i], deg); } /* an[q * i] = 0 for all i */ static void an_set0(int **an, long p, long n, long deg) { long i; for (i = p; i <= n; i += p) _0toCoeff(an[i], deg); } /* compute the coefficients an for the quadratic case */ static int** computean(GEN dtcr, LISTray *R, long n, long deg) { pari_sp av = avma, av2; long i, p, q, condZ, l; int **an, **reduc; GEN L, CHI, chi, chi1; CHI_t C; CHI = ch_CHI(dtcr); init_CHI_alg(&C, CHI); condZ= R->condZ; an = InitMatAn(n, deg, 1); reduc = InitReduction(CHI, deg); av2 = avma; /* all pr | p divide cond */ L = R->L0; l = lg(L); for (i=1; iL2; l = lg(L); for (i=1; irayZ, p%condZ)); chi1 = chi; for (q=p;;) { an_set0_coprime(an, p,q,n,deg); /* v_p(q) odd */ if (! (q = next_pow(q,p, n)) ) break; an_mul(an,p,q,n,deg,chi,reduc); if (! (q = next_pow(q,p, n)) ) break; chi = gmul(chi, chi1); } } /* 1 prime of degree 1 */ L = R->L1; l = lg(L); for (i=1; iL1ray,i)); chi1 = chi; for(q=p;;) { an_mul(an,p,q,n,deg,chi,reduc); if (! (q = next_pow(q,p, n)) ) break; chi = gmul(chi, chi1); } } /* 2 primes of degree 1 */ L = R->L11; l = lg(L); for (i=1; iL11ray,i); /* use pr1 pr2 = (p) */ if (condZ == 1) ray2 = ZC_neg(ray1); else ray2 = ZC_sub(gel(R->rayZ, p%condZ), ray1); chi11 = EvalChar(&C, ray1); chi12 = EvalChar(&C, ray2); chi1 = gadd(chi11, chi12); chi2 = chi12; for(q=p;;) { an_mul(an,p,q,n,deg,chi1,reduc); if (! (q = next_pow(q,p, n)) ) break; chi2 = gmul(chi2, chi12); chi1 = gadd(chi2, gmul(chi1, chi11)); } } CorrectCoeff(dtcr, an, reduc, n, deg); FreeMat(reduc, deg-1); avma = av; return an; } /* return the vector of A^i/i for i = 1...n */ 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; } static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec); /* compute S and T for the quadratic case. The following cases (cs) are: 1) bnr complex; 2) bnr real and no infinite place divide cond_chi (TBD); 3) bnr real and one infinite place divide cond_chi; 4) bnr real and both infinite places divide cond_chi (TBD) */ static void QuadGetST(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec) { pari_sp av = avma, av1, av2; long ncond, n, j, k, n0; GEN N0, C, T = *pT, S = *pS, an, degs, cs; LISTray LIST; /* initializations */ degs = GetDeg(dataCR); ncond = lg(vChar)-1; C = cgetg(ncond+1, t_VEC); N0 = cgetg(ncond+1, t_VECSMALL); cs = cgetg(ncond+1, t_VECSMALL); n0 = 0; for (j = 1; j <= ncond; j++) { /* FIXME: make sure that this value of c is correct for the general case */ long r1, r2, q; GEN dtcr = gel(dataCR, mael(vChar,j,1)), p1 = ch_4(dtcr), c = ch_C(dtcr); gel(C,j) = c; q = p1[1]; nf_get_sign(bnr_get_nf(gel(dtcr, 3)), &r1, &r2); if (r1 == 2) /* real quadratic */ { cs[j] = 2 + q; /* FIXME: make sure that this value of N0 is correct for the general case */ N0[j] = (long)prec2nbits_mul(prec, 0.35 * gtodouble(c)); if (cs[j] == 2 || cs[j] == 4) /* NOT IMPLEMENTED YET */ { GetST0(bnr, pS, pT, dataCR, vChar, prec); return; } } else /* complex quadratic */ { cs[j] = 1; N0[j] = (long)prec2nbits_mul(prec, 0.7 * gtodouble(c)); } if (n0 < N0[j]) n0 = N0[j]; } if (DEBUGLEVEL>1) err_printf("N0 = %ld\n", n0); InitPrimesQuad(bnr, n0, &LIST); av1 = avma; /* loop over conductors */ for (j = 1; j <= ncond; j++) { GEN c0 = gel(C,j), c1 = divur(1, c0), c2 = divur(2, c0); GEN ec1 = mpexp(c1), ec2 = mpexp(c2), LChar = gel(vChar,j); GEN vf0, vf1, cf0, cf1; const long nChar = lg(LChar)-1, NN = N0[j]; if (DEBUGLEVEL>1) err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", j,ncond,NN); if (realprec(ec1) > prec) ec1 = rtor(ec1, prec); if (realprec(ec2) > prec) ec2 = rtor(ec2, prec); switch(cs[j]) { case 1: cf0 = gen_1; cf1 = c0; vf0 = mpveceint1(rtor(c1, prec), ec1, NN); vf1 = mpvecpowdiv(invr(ec1), NN); break; case 3: cf0 = sqrtr(mppi(prec)); cf1 = gmul2n(cf0, 1); cf0 = gmul(cf0, c0); vf0 = mpvecpowdiv(invr(ec2), NN); vf1 = mpveceint1(rtor(c2, prec), ec2, NN); break; default: cf0 = cf1 = NULL; /* FIXME: not implemented */ vf0 = vf1 = NULL; } for (k = 1; k <= nChar; k++) { const long t = LChar[k], d = degs[t]; const GEN dtcr = gel(dataCR, t), z = gel(ch_CHI(dtcr), 2); GEN p1 = gen_0, p2 = gen_0; int **matan; long c = 0; if (DEBUGLEVEL>1) err_printf("\tcharacter no: %ld (%ld/%ld)\n", t,k,nChar); if (isintzero( ch_comp(gel(dataCR, t)) )) { if (DEBUGLEVEL>1) err_printf("\t no need to compute this character\n"); continue; } av2 = avma; matan = computean(gel(dataCR,t), &LIST, NN, d); for (n = 1; n <= NN; n++) if ((an = EvalCoeff(z, matan[n], d))) { p1 = gadd(p1, gmul(an, gel(vf0,n))); p2 = gadd(p2, gmul(an, gel(vf1,n))); if (++c == 256) { gerepileall(av2,2, &p1,&p2); c = 0; } } gaffect(gmul(cf0, p1), gel(S,t)); gaffect(gmul(cf1, gconj(p2)), gel(T,t)); FreeMat(matan,NN); avma = av2; } if (DEBUGLEVEL>1) err_printf("\n"); avma = av1; } avma = av; } /* s += t*u. All 3 of them t_REAL, except we allow s or u = NULL (for 0) */ static GEN _addmulrr(GEN s, GEN t, GEN u) { if (u) { GEN v = mulrr(t, u); return s? addrr(s, v): v; } return s; } /* s += t. Both real, except we allow s or t = NULL (for exact 0) */ static GEN _addrr(GEN s, GEN t) { return t? (s? addrr(s, t): t) : s; } /* S & T for the general case. This is time-critical: optimize */ static void get_cS_cT(ST_t *T, long n) { pari_sp av; GEN csurn, nsurc, lncsurn, A, B, s, t, Z, aij, bij; long i, j, r, i0; if (T->cS[n]) return; av = avma; aij = T->aij; i0= T->i0; bij = T->bij; r = T->r; Z = cgetg(r+1, t_VEC); gel(Z,1) = NULL; /* unused */ csurn = divru(T->c1, n); nsurc = invr(csurn); lncsurn = logr_abs(csurn); if (r > 1) { gel(Z,2) = lncsurn; /* r >= 2 */ for (i = 3; i <= r; i++) gel(Z,i) = divru(mulrr(gel(Z,i-1), lncsurn), i-1); /* Z[i] = ln^(i-1)(c1/n) / (i-1)! */ } /* i = i0 */ A = gel(aij,i0); t = _addrr(NULL, gel(A,1)); B = gel(bij,i0); s = _addrr(NULL, gel(B,1)); for (j = 2; j <= r; j++) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } for (i = i0 - 1; i > 1; i--) { A = gel(aij,i); if (t) t = mulrr(t, nsurc); B = gel(bij,i); if (s) s = mulrr(s, nsurc); for (j = odd(i)? T->rc2: T->rc1; j > 1; j--) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } s = _addrr(s, gel(B,1)); t = _addrr(t, gel(A,1)); } /* i = 1 */ A = gel(aij,1); if (t) t = mulrr(t, nsurc); B = gel(bij,1); if (s) s = mulrr(s, nsurc); s = _addrr(s, gel(B,1)); t = _addrr(t, gel(A,1)); for (j = 2; j <= r; j++) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } s = _addrr(s, T->b? mulrr(csurn, gel(T->powracpi,T->b)): csurn); if (!s) s = gen_0; if (!t) t = gen_0; gel(T->cS,n) = gclone(s); gel(T->cT,n) = gclone(t); avma = av; } static void clear_cScT(ST_t *T, long N) { GEN cS = T->cS, cT = T->cT; long i; for (i=1; i<=N; i++) if (cS[i]) { gunclone(gel(cS,i)); gunclone(gel(cT,i)); gel(cS,i) = gel(cT,i) = NULL; } } static void init_cScT(ST_t *T, GEN dtcr, long N, long prec) { GEN p1 = ch_4(dtcr); T->a = p1[1]; T->b = p1[2]; T->c = p1[3]; T->rc1 = T->a + T->c; T->rc2 = T->b + T->c; T->r = maxss(T->rc2+1, T->rc1); /* >= 2 */ ppgamma(T, prec); clear_cScT(T, N); } static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec) { pari_sp av = avma, av1, av2; long ncond, n, j, k, jc, n0, prec2, i0, r1, r2; GEN nf = checknf(bnr), racpi, powracpi; GEN N0, C, T = *pT, S = *pS, an, degs, limx; LISTray LIST; ST_t cScT; /* initializations */ degs = GetDeg(dataCR); ncond = lg(vChar)-1; nf_get_sign(nf,&r1,&r2); C = cgetg(ncond+1, t_VEC); N0 = cgetg(ncond+1, t_VECSMALL); n0 = 0; limx = zeta_get_limx(r1, r2, prec2nbits(prec)); for (j = 1; j <= ncond; j++) { GEN dtcr = gel(dataCR, mael(vChar,j,1)), c = ch_C(dtcr); gel(C,j) = c; N0[j] = zeta_get_N0(c, limx); if (n0 < N0[j]) n0 = N0[j]; } i0 = zeta_get_i0(r1, r2, prec2nbits(prec), limx); InitPrimes(bnr, n0, &LIST); prec2 = precdbl(prec) + EXTRA_PREC; racpi = sqrtr(mppi(prec2)); powracpi = cgetg(r1+2,t_VEC); gel(powracpi,1) = racpi; for (j=2; j<=r1; j++) gel(powracpi,j) = mulrr(gel(powracpi,j-1), racpi); cScT.powracpi = powracpi; cScT.cS = cgetg(n0+1, t_VEC); cScT.cT = cgetg(n0+1, t_VEC); for (j=1; j<=n0; j++) gel(cScT.cS,j) = gel(cScT.cT,j) = NULL; cScT.i0 = i0; av1 = avma; for (jc = 1; jc <= ncond; jc++) { const GEN LChar = gel(vChar,jc); const long nChar = lg(LChar)-1, NN = N0[jc]; if (DEBUGLEVEL>1) err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", jc,ncond,NN); cScT.c1 = gel(C,jc); init_cScT(&cScT, gel(dataCR, LChar[1]), NN, prec2); av2 = avma; for (k = 1; k <= nChar; k++) { const long t = LChar[k]; if (DEBUGLEVEL>1) err_printf("\tcharacter no: %ld (%ld/%ld)\n", t,k,nChar); if (!isintzero( ch_comp(gel(dataCR, t)) )) { const long d = degs[t]; const GEN dtcr = gel(dataCR, t), z = gel(ch_CHI(dtcr), 2); GEN p1 = gen_0, p2 = gen_0; long c = 0; int **matan = ComputeCoeff(gel(dataCR,t), &LIST, NN, d); for (n = 1; n <= NN; n++) if ((an = EvalCoeff(z, matan[n], d))) { get_cS_cT(&cScT, n); p1 = gadd(p1, gmul(an, gel(cScT.cS,n))); p2 = gadd(p2, gmul(an, gel(cScT.cT,n))); if (++c == 256) { gerepileall(av2,2, &p1,&p2); c = 0; } } gaffect(p1, gel(S,t)); gaffect(gconj(p2), gel(T,t)); FreeMat(matan, NN); avma = av2; } else if (DEBUGLEVEL>1) err_printf("\t no need to compute this character\n"); } if (DEBUGLEVEL>1) err_printf("\n"); avma = av1; } clear_cScT(&cScT, n0); avma = av; } static void GetST(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec) { const long cl = lg(dataCR) - 1; GEN S, T, nf = checknf(bnr); long j; /* allocate memory for answer */ *pS = S = cgetg(cl+1, t_VEC); *pT = T = cgetg(cl+1, t_VEC); for (j = 1; j <= cl; j++) { gel(S,j) = cgetc(prec); gel(T,j) = cgetc(prec); } if (nf_get_degree(nf) == 2) { QuadGetST(bnr, pS, pT, dataCR, vChar, prec); return; } GetST0(bnr, pS, pT, dataCR, vChar, prec); } /*******************************************************************/ /* */ /* Class fields of real quadratic fields using Stark units */ /* */ /*******************************************************************/ /* compute the Hilbert class field using genus class field theory when the exponent of the class group is exactly 2 (trivial group not covered) */ /* Cf Herz, Construction of class fields, LNM 21, Theorem 1 (VII-6) */ static GEN GenusFieldQuadReal(GEN disc) { long i, i0 = 0, l; pari_sp av = avma; GEN T = NULL, p0 = NULL, P; P = gel(Z_factor(disc), 1); l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); if (mod4(p) == 3) { p0 = p; i0 = i; break; } } l--; /* remove last prime */ if (i0 == l) l--; /* ... remove p0 and last prime */ for (i = 1; i < l; i++) { GEN p = gel(P,i), d, t; if (i == i0) continue; if (equaliu(p, 2)) switch (mod32(disc)) { case 8: d = gen_2; break; case 24: d = shifti(p0, 1); break; default: d = p0; break; } else d = (mod4(p) == 1)? p: mulii(p0, p); t = mkpoln(3, gen_1, gen_0, negi(d)); /* x^2 - d */ T = T? ZX_compositum_disjoint(T, t): t; } return gerepileupto(av, polredbest(T, 0)); } static GEN GenusFieldQuadImag(GEN disc) { long i, l; pari_sp av = avma; GEN T = NULL, P; P = gel(absi_factor(disc), 1); l = lg(P); l--; /* remove last prime */ for (i = 1; i < l; i++) { GEN p = gel(P,i), d, t; if (equaliu(p, 2)) switch (mod32(disc)) { case 24: d = gen_2; break; /* disc = 8 mod 32 */ case 8: d = gen_m2; break; /* disc =-8 mod 32 */ default: d = gen_m1; break; } else d = (mod4(p) == 1)? p: negi(p); t = mkpoln(3, gen_1, gen_0, negi(d)); /* x^2 - d */ T = T? ZX_compositum_disjoint(T, t): t; } return gerepileupto(av, polredbest(T, 0)); } /* if flag != 0, computes a fast and crude approximation of the result */ static GEN AllStark(GEN data, GEN nf, long flag, long newprec) { const long BND = 300; long cl, i, j, cpt = 0, N, h, v, n, r1, r2, den; pari_sp av, av2; int **matan; GEN bnr = gel(data,1), p1, p2, S, T, polrelnum, polrel, Lp, W, veczeta; GEN vChar, degs, C, dataCR, cond1, L1, an; LISTray LIST; pari_timer ti; nf_get_sign(nf, &r1,&r2); N = nf_get_degree(nf); cond1 = gel(bnr_get_mod(bnr), 2); dataCR = gel(data,5); vChar = sortChars(dataCR); v = 1; while (gequal1(gel(cond1,v))) v++; cl = lg(dataCR)-1; degs = GetDeg(dataCR); h = itos(ZM_det_triangular(gel(data,2))) >> 1; LABDOUB: if (DEBUGLEVEL) timer_start(&ti); av = avma; /* characters with rank > 1 should not be computed */ for (i = 1; i <= cl; i++) { GEN chi = gel(dataCR, i); if (L_vanishes_at_0(chi)) ch_comp(chi) = gen_0; } W = ComputeAllArtinNumbers(dataCR, vChar, (flag >= 0), newprec); if (DEBUGLEVEL) timer_printf(&ti,"Compute W"); Lp = cgetg(cl + 1, t_VEC); if (!flag) { GetST(bnr, &S, &T, dataCR, vChar, newprec); if (DEBUGLEVEL) timer_printf(&ti, "S&T"); for (i = 1; i <= cl; i++) { GEN chi = gel(dataCR, i), v = gen_0; if (!isintzero( ch_comp(chi) )) v = gel(GetValue(chi, gel(W,i), gel(S,i), gel(T,i), 2, newprec), 2); gel(Lp, i) = v; } } else { /* compute a crude approximation of the result */ C = cgetg(cl + 1, t_VEC); for (i = 1; i <= cl; i++) gel(C,i) = ch_C(gel(dataCR, i)); n = zeta_get_N0(vecmax(C), zeta_get_limx(r1, r2, prec2nbits(newprec))); if (n > BND) n = BND; if (DEBUGLEVEL) err_printf("N0 in QuickPol: %ld \n", n); InitPrimes(bnr, n, &LIST); L1 = cgetg(cl+1, t_VEC); /* use L(1) = sum (an / n) */ for (i = 1; i <= cl; i++) { GEN dtcr = gel(dataCR,i); matan = ComputeCoeff(dtcr, &LIST, n, degs[i]); av2 = avma; p1 = real_0(newprec); p2 = gel(ch_CHI(dtcr), 2); for (j = 1; j <= n; j++) if ( (an = EvalCoeff(p2, matan[j], degs[i])) ) p1 = gadd(p1, gdivgs(an, j)); gel(L1,i) = gerepileupto(av2, p1); FreeMat(matan, n); } p1 = gmul2n(powruhalf(mppi(newprec), N-2), 1); for (i = 1; i <= cl; i++) { long r; GEN WW, A = ComputeAChi(gel(dataCR,i), &r, 0, newprec); WW = gmul(gel(C,i), gmul(A, gel(W,i))); gel(Lp,i) = gdiv(gmul(WW, gconj(gel(L1,i))), p1); } } p1 = ComputeLift(gel(data,4)); den = flag ? h: 2*h; veczeta = cgetg(h + 1, t_VEC); for (i = 1; i <= h; i++) { GEN z = gen_0, sig = gel(p1,i); for (j = 1; j <= cl; j++) { GEN dtcr = gel(dataCR,j), CHI = ch_CHI(dtcr); GEN t = mulreal(gel(Lp,j), ComputeImagebyChar(CHI, sig)); if (itos(gel(CHI,3)) != 2) t = gmul2n(t, 1); /* character not real */ z = gadd(z, t); } gel(veczeta,i) = gdivgs(z, den); } for (j = 1; j <= h; j++) gel(veczeta,j) = gmul2n(gcosh(gel(veczeta,j), newprec), 1); polrelnum = roots_to_pol(veczeta, 0); if (DEBUGLEVEL) { if (DEBUGLEVEL>1) { err_printf("polrelnum = %Ps\n", polrelnum); err_printf("zetavalues = %Ps\n", veczeta); if (!flag) err_printf("Checking the square-root of the Stark unit...\n"); } timer_printf(&ti, "Compute %s", flag? "quickpol": "polrelnum"); } if (flag) return gerepilecopy(av, polrelnum); /* try to recognize this polynomial */ polrel = RecCoeff(nf, polrelnum, v, newprec); if (!polrel) { for (j = 1; j <= h; j++) gel(veczeta,j) = gsubgs(gsqr(gel(veczeta,j)), 2); polrelnum = roots_to_pol(veczeta, 0); if (DEBUGLEVEL) { if (DEBUGLEVEL>1) { err_printf("It's not a square...\n"); err_printf("polrelnum = %Ps\n", polrelnum); } timer_printf(&ti, "Compute polrelnum"); } polrel = RecCoeff(nf, polrelnum, v, newprec); } if (!polrel) /* FAILED */ { 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); if (DEBUGLEVEL) pari_warn(warnprec, "AllStark", newprec); nf = nfnewprec_shallow(nf, newprec); dataCR = CharNewPrec(dataCR, nf, newprec); gerepileall(av, 2, &nf, &dataCR); goto LABDOUB; } if (DEBUGLEVEL) { if (DEBUGLEVEL>1) err_printf("polrel = %Ps\n", polrel); timer_printf(&ti, "Recpolnum"); } return gerepilecopy(av, polrel); } /********************************************************************/ /* Main functions */ /********************************************************************/ static GEN get_subgroup(GEN H, GEN cyc, const char *s) { if (!H || gequal0(H)) return diagonal_shallow(cyc); if (typ(H) != t_MAT) pari_err_TYPE(stack_strcat(s," [subgroup]"), H); RgM_check_ZM(H, s); return ZM_hnfmodid(H, cyc); } GEN bnrstark(GEN bnr, GEN subgrp, long prec) { long N, newprec; pari_sp av = avma; GEN bnf, p1, cycbnr, nf, data, dtQ; /* check the bnr */ checkbnr(bnr); bnf = checkbnf(bnr); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); if (N == 1) return galoissubcyclo(bnr, subgrp, 0, 0); /* check the bnf */ if (!nf_get_varn(nf)) pari_err_PRIORITY("bnrstark", nf_get_pol(nf), "=", 0); if (nf_get_r2(nf)) pari_err_DOMAIN("bnrstark", "r2", "!=", gen_0, nf); subgrp = get_subgroup(subgrp,bnr_get_cyc(bnr),"bnrstark"); /* compute bnr(conductor) */ p1 = bnrconductor(bnr, subgrp, 2); bnr = gel(p1,2); cycbnr = bnr_get_cyc(bnr); subgrp = gel(p1,3); if (gequal1( ZM_det_triangular(subgrp) )) { avma = av; return pol_x(0); } /* check the class field */ if (!gequal0(gel(bnr_get_mod(bnr), 2))) pari_err_DOMAIN("bnrstark", "r2(class field)", "!=", gen_0, bnr); /* find a suitable extension N */ dtQ = InitQuotient(subgrp); data = FindModulus(bnr, dtQ, &newprec); if (!data) { GEN vec, H, cyc = gel(dtQ,2), U = gel(dtQ,3), M = RgM_inv(U); long i, j = 1, l = lg(M); /* M = indep. generators of Cl_f/subgp, restrict to cyclic components */ vec = cgetg(l, t_VEC); for (i = 1; i < l; i++) { if (is_pm1(gel(cyc,i))) continue; H = ZM_hnfmodid(vecsplice(M,i), cycbnr); gel(vec,j++) = bnrstark(bnr, H, prec); } setlg(vec, j); return gerepilecopy(av, vec); } if (newprec > prec) { if (DEBUGLEVEL>1) err_printf("new precision: %ld\n", newprec); nf = nfnewprec_shallow(nf, newprec); } return gerepileupto(av, AllStark(data, nf, 0, newprec)); } /* For each character of Cl(bnr)/subgp, compute L(1, chi) (or equivalently * the first non-zero term c(chi) of the expansion at s = 0). * If flag & 1: compute the value at s = 1 (for non-trivial characters), * else compute the term c(chi) and return [r(chi), c(chi)] where r(chi) is * the order of L(s, chi) at s = 0. * If flag & 2: compute the value of the L-function L_S(s, chi) where S is the * set of places dividing the modulus of bnr (and the infinite places), * else * compute the value of the primitive L-function associated to chi, * If flag & 4: return also the character */ GEN bnrL1(GEN bnr, GEN subgp, long flag, long prec) { GEN cyc, L1, allCR, listCR; GEN indCR, invCR, Qt; long cl, i, nc; pari_sp av = avma; checkbnr(bnr); if (flag < 0 || flag > 8) pari_err_FLAG("bnrL1"); cyc = bnr_get_cyc(bnr); subgp = get_subgroup(subgp, cyc, "bnrL1"); cl = itou( ZM_det_triangular(subgp) ); Qt = InitQuotient(subgp); /* compute all characters */ allCR = EltsOfGroup(cl, gel(Qt,2)); /* 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; 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; for (j = 1; j <= nc; j++) if (ZV_equal(gmael(listCR, j, 1), clchi)) { a = -j; break; } if (a > 0) { nc++; gel(listCR,nc) = mkvec2(lchi, bnrconductorofchar(bnr, lchi)); indCR[i] = nc; invCR[nc] = i; } else indCR[i] = -invCR[-a]; gel(allCR,i) = lchi; } settyp(allCR[cl], t_VEC); /* set correct type for trivial character */ setlg(listCR, nc + 1); L1 = cgetg((flag&1)? cl: cl+1, t_VEC); if (nc) { GEN dataCR = InitChar(bnr, listCR, prec); GEN W, S, T, vChar = sortChars(dataCR); GetST(bnr, &S, &T, dataCR, vChar, prec); W = ComputeAllArtinNumbers(dataCR, vChar, 1, prec); for (i = 1; i < cl; i++) { long a = indCR[i]; if (a > 0) gel(L1,i) = GetValue(gel(dataCR,a), gel(W,a), gel(S,a), gel(T,a), flag, prec); else gel(L1,i) = gconj(gel(L1,-a)); } } if (!(flag & 1)) gel(L1,cl) = GetValue1(bnr, flag & 2, prec); else cl--; if (flag & 4) { for (i = 1; i <= cl; i++) gel(L1,i) = mkvec2(gel(allCR,i), gel(L1,i)); } return gerepilecopy(av, L1); } /*******************************************************************/ /* */ /* Hilbert and Ray Class field using Stark */ /* */ /*******************************************************************/ /* P in A[x,y], deg_y P < 2, return P0 and P1 in A[x] such that P = P0 + P1 y */ static void split_pol_quad(GEN P, GEN *gP0, GEN *gP1) { long i, l = lg(P); GEN P0 = cgetg(l, t_POL), P1 = cgetg(l, t_POL); P0[1] = P1[1] = P[1]; for (i = 2; i < l; i++) { GEN c = gel(P,i), c0 = c, c1 = gen_0; if (typ(c) == t_POL) /* write c = c1 y + c0 */ switch(degpol(c)) { case -1: c0 = gen_0; break; default: c1 = gel(c,3); /* fall through */ case 0: c0 = gel(c,2); break; } gel(P0,i) = c0; gel(P1,i) = c1; } *gP0 = normalizepol_lg(P0, l); *gP1 = normalizepol_lg(P1, l); } /* k = nf quadratic field, P relative equation of H_k (Hilbert class field) * return T in Z[X], such that H_k / Q is the compositum of Q[X]/(T) and k */ static GEN makescind(GEN nf, GEN P) { GEN Pp, p, pol, G, L, a, roo, P0,P1, Ny,Try, nfpol = nf_get_pol(nf); long i, is_P; split_pol_quad(lift_intern(P), &P0, &P1); /* P = P0 + y P1, Norm_{k/Q}(P) = P0^2 + Tr y P0P1 + Ny P1^2, irreducible/Q */ Ny = gel(nfpol, 2); Try = negi(gel(nfpol, 3)); pol = RgX_add(RgX_sqr(P0), RgX_Rg_mul(RgX_sqr(P1), Ny)); if (signe(Try)) pol = RgX_add(pol, RgX_Rg_mul(RgX_mul(P0,P1), Try)); /* pol = rnfequation(nf, P); */ G = galoisinit(pol, NULL); L = gal_get_group(G); p = gal_get_p(G); a = FpX_quad_root(nfpol, p, 0); /* P mod a prime \wp above p (which splits) */ Pp = FpXY_evalx(P, a, p); roo = gal_get_roots(G); is_P = gequal0( FpX_eval(Pp, remii(gel(roo,1),p), p) ); /* each roo[i] mod p is a root of P or (exclusive) tau(P) mod \wp */ /* record whether roo[1] is a root of P or tau(P) */ for (i = 1; i < lg(L); i++) { GEN perm = gel(L,i); long k = perm[1]; if (k == 1) continue; k = gequal0( FpX_eval(Pp, remii(gel(roo,k),p), p) ); /* roo[k] is a root of the other polynomial */ if (k != is_P) { long o = perm_order(perm); if (o != 2) perm = perm_pow(perm, o >> 1); /* perm has order two and doesn't belong to Gal(H_k/k) */ return galoisfixedfield(G, perm, 1, varn(P)); } } pari_err_BUG("makescind"); return NULL; /*not reached*/ } /* pbnf = NULL if no bnf is needed, f = NULL may be passed for a trivial * conductor */ static void quadray_init(GEN *pD, GEN f, GEN *pbnf, long prec) { GEN D = *pD, nf, bnf = NULL; if (typ(D) == t_INT) { int isfund; if (pbnf) { long v = f? gvar(f): NO_VARIABLE; if (v == NO_VARIABLE) v = fetch_user_var("y"); bnf = Buchall(quadpoly0(D, v), nf_FORCE, prec); nf = bnf_get_nf(bnf); isfund = equalii(D, nf_get_disc(nf)); } else isfund = Z_isfundamental(D); if (!isfund) pari_err_DOMAIN("quadray", "isfundamental(D)", "=",gen_0, D); } else { bnf = checkbnf(D); nf = bnf_get_nf(bnf); if (nf_get_degree(nf) != 2) pari_err_DOMAIN("quadray", "degree", "!=", gen_2, nf_get_pol(nf)); D = nf_get_disc(nf); } if (pbnf) *pbnf = bnf; *pD = D; } /* compute the polynomial over Q of the Hilbert class field of Q(sqrt(D)) where D is a positive fundamental discriminant */ static GEN quadhilbertreal(GEN D, long prec) { pari_sp av = avma; long newprec; GEN bnf; VOLATILE GEN bnr, dtQ, data, nf, cyc, M; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); (void)≺ /* prevent longjmp clobbering it */ (void)&bnf; /* prevent longjmp clobbering it, avoid warning due to * quadray_init call : discards qualifiers from pointer type */ quadray_init(&D, NULL, &bnf, prec); cyc = bnf_get_cyc(bnf); if (lg(cyc) == 1) { avma = av; return pol_x(0); } /* if the exponent of the class group is 2, use Genus Theory */ if (equaliu(gel(cyc,1), 2)) return gerepileupto(av, GenusFieldQuadReal(D)); bnr = Buchray(bnf, gen_1, nf_INIT|nf_GEN); M = diagonal_shallow(bnr_get_cyc(bnr)); dtQ = InitQuotient(M); nf = bnf_get_nf(bnf); for(;;) { VOLATILE GEN pol = NULL; pari_CATCH(e_PREC) { prec += EXTRA_PREC; if (DEBUGLEVEL) pari_warn(warnprec, "quadhilbertreal", prec); bnr = bnrnewprec_shallow(bnr, prec); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); } pari_TRY { /* find the modulus defining N */ pari_timer T; if (DEBUGLEVEL) timer_start(&T); data = FindModulus(bnr, dtQ, &newprec); if (DEBUGLEVEL) timer_printf(&T,"FindModulus"); if (!data) { long i, l = lg(M); GEN vec = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN t = gcoeff(M,i,i); gcoeff(M,i,i) = gen_1; gel(vec,i) = bnrstark(bnr, M, prec); gcoeff(M,i,i) = t; } return gerepileupto(av, vec); } if (newprec > prec) { if (DEBUGLEVEL>1) err_printf("new precision: %ld\n", newprec); nf = nfnewprec_shallow(nf, newprec); } pol = AllStark(data, nf, 0, newprec); } pari_ENDCATCH; if (pol) { pol = makescind(nf, pol); return gerepileupto(av, polredbest(pol, 0)); } } } /*******************************************************************/ /* */ /* Hilbert and Ray Class field using CM (Schertz) */ /* */ /*******************************************************************/ /* form^2 = 1 ? */ static int hasexp2(GEN form) { GEN a = gel(form,1), b = gel(form,2), c = gel(form,3); return !signe(b) || absi_equal(a,b) || equalii(a,c); } static int uhasexp2(GEN form) { long a = form[1], b = form[2], c = form[3]; return !b || a == labs(b) || a == c; } GEN qfbforms(GEN D) { ulong d = itou(D), dover3 = d/3, t, b2, a, b, c, h; GEN L = cgetg((long)(sqrt(d) * log2(d)), t_VEC); b2 = b = (d&1); h = 0; if (!b) /* b = 0 treated separately to avoid special cases */ { t = d >> 2; /* (b^2 - D) / 4*/ for (a=1; a*a<=t; a++) if (c = t/a, t == c*a) gel(L,++h) = mkvecsmall3(a,0,c); b = 2; b2 = 4; } /* now b > 0, b = D (mod 2) */ for ( ; b2 <= dover3; b += 2, b2 = b*b) { t = (b2 + d) >> 2; /* (b^2 - D) / 4*/ /* b = a */ if (c = t/b, t == c*b) gel(L,++h) = mkvecsmall3(b,b,c); /* b < a < c */ for (a = b+1; a*a < t; a++) if (c = t/a, t == c*a) { gel(L,++h) = mkvecsmall3(a, b,c); gel(L,++h) = mkvecsmall3(a,-b,c); } /* a = c */ if (a * a == t) gel(L,++h) = mkvecsmall3(a,b,a); } setlg(L,h+1); return L; } /* gcd(n, 24) */ static long GCD24(long n) { switch(n % 24) { case 0: return 24; case 1: return 1; case 2: return 2; case 3: return 3; case 4: return 4; case 5: return 1; case 6: return 6; case 7: return 1; case 8: return 8; case 9: return 3; case 10: return 2; case 11: return 1; case 12: return 12; case 13: return 1; case 14: return 2; case 15: return 3; case 16: return 8; case 17: return 1; case 18: return 6; case 19: return 1; case 20: return 4; case 21: return 3; case 22: return 2; case 23: return 1; default: return 0; } } struct gpq_data { long p, q; GEN sqd; /* sqrt(D), t_REAL */ GEN u, D; GEN pq, pq2; /* p*q, 2*p*q */ GEN qfpq ; /* class of \P * \Q */ }; /* find P and Q two non principal prime ideals (above p <= q) such that * cl(P) = cl(Q) if P,Q have order 2 in Cl(K). * Ensure that e = 24 / gcd(24, (p-1)(q-1)) = 1 */ /* D t_INT, discriminant */ static void init_pq(GEN D, struct gpq_data *T) { const long Np = 6547; /* N.B. primepi(50000) = 5133 */ const ulong maxq = 50000; GEN listp = cgetg(Np + 1, t_VECSMALL); /* primes p */ GEN listP = cgetg(Np + 1, t_VEC); /* primeform(p) if of order 2, else NULL */ GEN gcd24 = cgetg(Np + 1, t_VECSMALL); /* gcd(p-1, 24) */ forprime_t S; long l = 1; double best = 0.; ulong q; u_forprime_init(&S, 2, ULONG_MAX); T->D = D; T->p = T->q = 0; for(;;) { GEN Q; long i, gcdq, mod; int order2, store; double t; q = u_forprime_next(&S); if (best > 0 && q >= maxq) { if (DEBUGLEVEL) pari_warn(warner,"possibly suboptimal (p,q) for D = %Ps", D); break; } if (kroiu(D, q) < 0) continue; /* inert */ Q = redimag(primeform_u(D, q)); if (is_pm1(gel(Q,1))) continue; /* Q | q is principal */ store = 1; order2 = hasexp2(Q); gcd24[l] = gcdq = GCD24(q-1); mod = 24 / gcdq; /* mod must divide p-1 otherwise e > 1 */ listp[l] = q; gel(listP,l) = order2 ? Q : NULL; t = (q+1)/(double)(q-1); for (i = 1; i < l; i++) /* try all (p, q), p < q in listp */ { long p = listp[i], gcdp = gcd24[i]; double b; /* P,Q order 2 => cl(Q) = cl(P) */ if (order2 && gel(listP,i) && !gequal(gel(listP,i), Q)) continue; if (gcdp % gcdq == 0) store = 0; /* already a better one in the list */ if ((p-1) % mod) continue; b = (t*(p+1)) / (p-1); /* (p+1)(q+1) / (p-1)(q-1) */ if (b > best) { store = 0; /* (p,q) always better than (q,r) for r >= q */ best = b; T->q = q; T->p = p; if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", p, q); } /* won't improve with this q as largest member */ if (best > 0) break; } /* if !store or (q,r) won't improve on current best pair, forget that q */ if (store && t*t > best) if (++l >= Np) pari_err_BUG("quadhilbert (not enough primes)"); if (!best) /* (p,q) with p < q always better than (q,q) */ { /* try (q,q) */ if (gcdq >= 12 && umodiu(D, q)) /* e = 1 and unramified */ { double b = (t*q) / (q-1); /* q(q+1) / (q-1)^2 */ if (b > best) { best = b; T->q = T->p = q; if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", q, q); } } } /* If (p1+1)(q+1) / (p1-1)(q-1) <= best, we can no longer improve * even with best p : stop */ if ((listp[1]+1)*t <= (listp[1]-1)*best) break; } if (DEBUGLEVEL>1) err_printf("(p, q) = %ld, %ld; gain = %f\n", T->p, T->q, 12*best); } static GEN gpq(GEN form, struct gpq_data *T) { pari_sp av = avma; long a = form[1], b = form[2], c = form[3]; long p = T->p, q = T->q; GEN form2, w, z; int fl, real = 0; form2 = qficomp(T->qfpq, mkvec3s(a, -b, c)); /* form2 and form yield complex conjugate roots : only compute for the * lexicographically smallest of the 2 */ fl = cmpis(gel(form2,1), a); if (fl <= 0) { if (fl < 0) return NULL; fl = cmpis(gel(form2,2), b); if (fl <= 0) { if (fl < 0) return NULL; /* form == form2 : real root */ real = 1; } } if (p == 2) { /* (a,b,c) = (1,1,0) mod 2 ? */ if (a % q == 0 && (a & b & 1) && !(c & 1)) { /* apply S : make sure that (a,b,c) represents odd values */ lswap(a,c); b = -b; } } if (a % p == 0 || a % q == 0) { /* apply T^k, look for c' = a k^2 + b k + c coprime to N */ while (c % p == 0 || c % q == 0) { c += a + b; b += a << 1; } lswap(a, c); b = -b; /* apply S */ } /* now (a,b,c) ~ form and (a,pq) = 1 */ /* gcd(2a, u) = 2, w = u mod 2pq, -b mod 2a */ w = Z_chinese(T->u, stoi(-b), T->pq2, utoipos(a << 1)); z = double_eta_quotient(utoipos(a), w, T->D, T->p, T->q, T->pq, T->sqd); if (real && typ(z) == t_COMPLEX) z = gcopy(gel(z, 1)); return gerepileupto(av, z); } /* returns an equation for the Hilbert class field of Q(sqrt(D)), D < 0 * fundamental discriminant */ static GEN quadhilbertimag(GEN D) { GEN L, P, Pi, Pr, qfp, u; pari_sp av = avma; long h, i, prec; struct gpq_data T; pari_timer ti; if (DEBUGLEVEL>1) timer_start(&ti); if (lgefint(D) == 3) switch (D[2]) { /* = |D|; special cases where e > 1 */ case 3: case 4: case 7: case 8: case 11: case 19: case 43: case 67: case 163: return pol_x(0); } L = qfbforms(D); h = lg(L)-1; if ((1L << vals(h)) == h) /* power of 2 */ { /* check whether > |Cl|/2 elements have order <= 2 ==> 2-elementary */ long lim = (h>>1) + 1; for (i=1; i <= lim; i++) if (!uhasexp2(gel(L,i))) break; if (i > lim) return GenusFieldQuadImag(D); } if (DEBUGLEVEL>1) timer_printf(&ti,"class number = %ld",h); init_pq(D, &T); qfp = primeform_u(D, T.p); T.pq = muluu(T.p, T.q); T.pq2 = shifti(T.pq,1); if (T.p == T.q) { GEN qfbp2 = qficompraw(qfp, qfp); u = gel(qfbp2,2); T.u = modii(u, T.pq2); T.qfpq = redimag(qfbp2); } else { GEN qfq = primeform_u(D, T.q), bp = gel(qfp,2), bq = gel(qfq,2); T.u = Z_chinese(bp, bq, utoipos(T.p << 1), utoipos(T.q << 1)); /* T.u = bp (mod 2p), T.u = bq (mod 2q) */ T.qfpq = qficomp(qfp, qfq); } /* u modulo 2pq */ prec = LOWDEFAULTPREC; Pr = cgetg(h+1,t_VEC); Pi = cgetg(h+1,t_VEC); for(;;) { long ex, exmax = 0, r1 = 0, r2 = 0; pari_sp av0 = avma; T.sqd = sqrtr_abs(itor(D, prec)); for (i=1; i<=h; i++) { GEN s = gpq(gel(L,i), &T); if (DEBUGLEVEL>3) err_printf("%ld ", i); if (!s) continue; if (typ(s) != t_COMPLEX) gel(Pr, ++r1) = s; /* real root */ else gel(Pi, ++r2) = s; ex = gexpo(s); if (ex > 0) exmax += ex; } if (DEBUGLEVEL>1) timer_printf(&ti,"roots"); setlg(Pr, r1+1); setlg(Pi, r2+1); P = roots_to_pol_r1(shallowconcat(Pr,Pi), 0, r1); 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); if (DEBUGLEVEL) pari_warn(warnprec,"quadhilbertimag",prec); } return gerepileupto(av,P); } GEN quadhilbert(GEN D, long prec) { GEN d = D; quadray_init(&d, NULL, NULL, 0); return (signe(d)>0)? quadhilbertreal(D,prec) : quadhilbertimag(d); } /* return a vector of all roots of 1 in bnf [not necessarily quadratic] */ static GEN getallrootsof1(GEN bnf) { GEN T, u, nf = bnf_get_nf(bnf), tu; long i, n = bnf_get_tuN(bnf); if (n == 2) { long N = nf_get_degree(nf); return mkvec2(scalarcol_shallow(gen_m1, N), scalarcol_shallow(gen_1, N)); } tu = poltobasis(nf, bnf_get_tuU(bnf)); T = zk_multable(nf, tu); u = cgetg(n+1, t_VEC); gel(u,1) = tu; for (i=2; i <= n; i++) gel(u,i) = ZM_ZC_mul(T, gel(u,i-1)); return u; } /* assume bnr has the right conductor */ static GEN get_lambda(GEN bnr) { GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf), pol = nf_get_pol(nf); GEN f = gel(bnr_get_mod(bnr), 1), labas, lamodf, u; long a, b, f2, i, lu, v = varn(pol); f2 = 2 * itos(gcoeff(f,1,1)); u = getallrootsof1(bnf); lu = lg(u); for (i=1; i1) err_printf("quadray: looking for [a,b] != unit mod 2f\n[a,b] = "); for (a=0; a1) err_printf("[%ld,%ld] ",a,b); labas = poltobasis(nf, la); lamodf = ZC_hnfrem(labas, f); for (i=1; i1) err_printf("\n"); err_printf("lambda = %Ps\n",la); } return labas; } pari_err_BUG("get_lambda"); return NULL; } static GEN to_approx(GEN nf, GEN a) { GEN M = nf_get_M(nf); return gadd(gel(a,1), gmul(gcoeff(M,1,2),gel(a,2))); } /* Z-basis for a (over C) */ static GEN get_om(GEN nf, GEN a) { return mkvec2(to_approx(nf,gel(a,2)), to_approx(nf,gel(a,1))); } /* Compute all elts in class group G = [|G|,c,g], c=cyclic factors, g=gens. * Set list[j + 1] = g1^e1...gk^ek where j is the integer * ek + ck [ e(k-1) + c(k-1) [... + c2 [e1]]...] */ static GEN getallelts(GEN bnr) { GEN nf, C, c, g, list, pows, gk; long lc, i, j, no; nf = bnr_get_nf(bnr); no = itos( bnr_get_no(bnr) ); c = bnr_get_cyc(bnr); g = bnr_get_gen_nocheck(bnr); lc = lg(c)-1; list = cgetg(no+1,t_VEC); gel(list,1) = matid(nf_get_degree(nf)); /* (1) */ if (!no) return list; pows = cgetg(lc+1,t_VEC); c = leafcopy(c); settyp(c, t_VECSMALL); for (i=1; i<=lc; i++) { long k = itos(gel(c,i)); c[i] = k; gk = cgetg(k, t_VEC); gel(gk,1) = gel(g,i); for (j=2; j j only involves g(k-i)...gk */ i = 1; for (j=1; j < C[1]; j++) gel(list, j+1) = gmael(pows,lc,j); while(j 1) a = idealmoddivisor(bnr, idealmul(nf, a, gel(list,k))); gel(list, ++j) = a; } return list; } /* x quadratic integer (approximate), recognize it. If error return NULL */ static GEN findbezk(GEN nf, GEN x) { GEN a,b, M = nf_get_M(nf), u = gcoeff(M,1,2); long ea, eb; /* u t_COMPLEX generator of nf.zk, write x ~ a + b u, a,b in Z */ b = grndtoi(mpdiv(imag_i(x), gel(u,2)), &eb); if (eb > -20) return NULL; a = grndtoi(mpsub(real_i(x), mpmul(b,gel(u,1))), &ea); if (ea > -20) return NULL; return signe(b)? coltoalg(nf, mkcol2(a,b)): a; } static GEN findbezk_pol(GEN nf, GEN x) { long i, lx = lg(x); GEN y = cgetg(lx,t_POL); for (i=2; i20 || gexpo(p2)> prec2nbits(minss(prec,realprec(p2)))-10) return NULL; return gexp(p1,prec); } /* Computes P_2(X)=polynomial in Z_K[X] closest to prod_gc(X-th2(gc)) where the product is over the ray class group bnr.*/ static GEN computeP2(GEN bnr, long prec) { long clrayno, i, first = 1; pari_sp av=avma, av2; GEN listray, P0, P, lanum, la = get_lambda(bnr); GEN nf = bnr_get_nf(bnr), f = gel(bnr_get_mod(bnr), 1); listray = getallelts(bnr); clrayno = lg(listray)-1; av2 = avma; PRECPB: if (!first) { if (DEBUGLEVEL) pari_warn(warnprec,"computeP2",prec); nf = gerepilecopy(av2, nfnewprec_shallow(checknf(bnr),prec)); } first = 0; lanum = to_approx(nf,la); P = cgetg(clrayno+1,t_VEC); for (i=1; i<=clrayno; i++) { GEN om = get_om(nf, idealdiv(nf,f,gel(listray,i))); GEN s = computeth2(om,lanum,prec); if (!s) { prec = precdbl(prec); goto PRECPB; } gel(P,i) = s; } P0 = roots_to_pol(P, 0); P = findbezk_pol(nf, P0); if (!P) { prec = get_prec(P0, prec); goto PRECPB; } return gerepilecopy(av, P); } #define nexta(a) (a>0 ? -a : 1-a) static GEN do_compo(GEN x, GEN y) { long a, i, l = lg(y); GEN z; y = leafcopy(y); /* y := t^deg(y) y(#/t) */ for (i = 2; i < l; i++) gel(y,i) = monomial(gel(y,i), l-i-1, MAXVARN); 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; } } #undef nexta static GEN galoisapplypol(GEN nf, GEN s, GEN x) { long i, lx = lg(x); GEN y = cgetg(lx,t_POL); for (i=2; i>2); if (equalui(ell,D)) /* ell = |D| */ { p2 = gcoeff(nffactor(nf,p2),1,1); return do_compo(p1,p2); } if (ell%4 == 3) ell = -ell; /* nf = K = Q(a), L = K(b) quadratic extension = Q(t) */ polLK = quadpoly(stoi(ell)); /* relative polynomial */ res = rnfequation2(nf, polLK); vx = nf_get_varn(nf); polL = gsubst(gel(res,1),0,pol_x(vx)); /* = charpoly(t) */ a = gsubst(lift(gel(res,2)), 0,pol_x(vx)); b = gsub(pol_x(vx), gmul(gel(res,3), a)); nfL = nfinit(polL, DEFAULTPREC); p1 = gcoeff(nffactor(nfL,p1),1,1); 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 */ 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); } /* I integral ideal in HNF. (x) = I, x small in Z ? */ static long isZ(GEN I) { GEN x = gcoeff(I,1,1); if (signe(gcoeff(I,1,2)) || !equalii(x, gcoeff(I,2,2))) return 0; return is_bigint(x)? -1: itos(x); } /* Treat special cases directly. return NULL if not special case */ static GEN treatspecialsigma(GEN bnr) { GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf); GEN f = gel(bnr_get_mod(bnr), 1), D = nf_get_disc(nf); GEN p1, p2; long Ds, fl, tryf, i = isZ(f); if (i == 1) return quadhilbertimag(D); /* f = 1 */ if (equaliu(D,3)) /* Q(j) */ { if (i == 4 || i == 5 || i == 7) return polcyclo(i,0); if (!equaliu(gcoeff(f,1,1),9) || !equaliu(Q_content(f),3)) return NULL; /* f = P_3^3 */ p1 = mkpolmod(bnf_get_tuU(bnf), nf_get_pol(nf)); return gadd(monomial(gen_1,3,0), p1); /* x^3+j */ } if (equaliu(D,4)) /* Q(i) */ { if (i == 3 || i == 5) return polcyclo(i,0); if (i != 4) return NULL; p1 = mkpolmod(bnf_get_tuU(bnf), nf_get_pol(nf)); return gadd(monomial(gen_1,2,0), p1); /* x^2+i */ } Ds = smodis(D,48); if (i) { if (i==2 && Ds%16== 8) return compocyclo(nf, 4,1); if (i==3 && Ds% 3== 1) return compocyclo(nf, 3,1); if (i==4 && Ds% 8== 1) return compocyclo(nf, 4,1); if (i==6 && Ds ==40) return compocyclo(nf,12,1); return NULL; } p1 = gcoeff(f,1,1); /* integer > 0 */ if (is_bigint(p1)) return NULL; tryf = p1[2]; p2 = gcoeff(f,2,2); /* integer > 0 */ if (is_pm1(p2)) fl = 0; else { if (Ds % 16 != 8 || !equaliu(Q_content(f),2)) return NULL; fl = 1; tryf >>= 1; } if (tryf <= 3 || umodiu(D, tryf) || !uisprime(tryf)) return NULL; if (fl) tryf <<= 2; return compocyclo(nf,tryf,2); } GEN quadray(GEN D, GEN f, long prec) { GEN bnr, y, bnf; pari_sp av = avma; if (isint1(f)) return quadhilbert(D, prec); quadray_init(&D, f, &bnf, prec); bnr = Buchray(bnf, f, nf_INIT|nf_GEN); if (is_pm1(bnr_get_no(bnr))) { avma = av; return pol_x(0); } if (signe(D) > 0) y = bnrstark(bnr,NULL,prec); else { bnr = gel(bnrconductor(bnr,NULL,2), 2); y = treatspecialsigma(bnr); if (!y) y = computeP2(bnr, prec); } return gerepileupto(av, y); } pari-2.7.5/src/modules/galpol.c0000644000175000017500000000360512366172547015010 0ustar billbill/* Copyright (C) 2000-2003 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" GEN galoisnbpol(long a) { GEN n; pariFILE *F; char *s = stack_malloc(strlen(pari_datadir) + 11 + 20 + 1); sprintf(s,"%s/galpol/%ld/nb", pari_datadir, a); F = pari_fopengz(s); if (!F) pari_err_FILE("galpol file",s); n = gp_read_stream(F->file); if (!n || typ(n)!=t_INT) pari_err_FILE("galpol file [incompatible]",s); pari_fclose(F); return n; } GEN galoisgetpol(long a, long b, long sig) { pariFILE *F; GEN V; const char *si; char *s; if (a<=0) pari_err_DOMAIN("galoisgetpol", "degree", "<=", gen_0, stoi(a)); if (b<0) pari_err_DOMAIN("galoisgetpol", "index", "<", gen_0, stoi(b)); if (!b) return galoisnbpol(a); switch(sig) { case 1: si="real"; break; case 2: if (a%2==0) { si="complex"; break; } pari_err_DOMAIN("galoisgetpol", "s", ">", gen_1, stoi(sig)); default: pari_err_FLAG("galoisgetpol"); return NULL; } s = pari_sprintf("%s/galpol/%ld/%ld/%s", pari_datadir, a,b,si); F = pari_fopengz(s); pari_free(s); if (!F) { long n = itos(galoisnbpol(a)); if (b > n) pari_err_DOMAIN("galoisgetpol", "group index", ">", stoi(n), stoi(b)); else pari_err_FILE("galpol file", F->name); } V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC) pari_err_FILE("galpol file", F->name); pari_fclose(F); return V; } pari-2.7.5/src/modules/galois.c0000644000175000017500000017447712405547147015024 0ustar billbill/* 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. */ /**************************************************************/ /* */ /* Galois group for degree between 8 and 11 (included) */ /* */ /**************************************************************/ #include "pari.h" #include "paripriv.h" #define NMAX 11 /* maximum degree */ typedef GEN PERM; typedef PERM *GROUP; typedef struct { PERM *a; long nm, nv; } resolv; /* resolvent */ typedef struct { long pr, prmax, N; GEN p, r, coef; } buildroot; static long isin_G_H(buildroot *BR, long n1, long n2); static long *par_vec; /* k-1 entries filled so far * m = maximal allowed value, n = sum to reach with remaining elements */ static void do_par(GEN T, long k, long n, long m) { long i; if (n <= 0) { GEN t = cgetg(k, t_VECSMALL); for (i=1; i 7) { err_printf("Partitions of %ld (%ld)\n",n, p); for (i=1; i<=p; i++) err_printf("i = %ld: %Ps\n",i,gel(T,i)); } T[0] = evallg(p + 1) | evaltyp(t_VEC); return T; } /* affect to the permutation x the N arguments that follow */ static void _aff(long N, PERM x,...) { va_list args; long i; va_start(args,x); for (i=1; i<=N; i++) x[i] = va_arg(args,int); va_end(args); } /* return an array of length |len| from the arguments (for galoismodulo) */ static GEN _gr(long len,...) { va_list args; long i, l = labs(len); GEN x = new_chunk(l+1); va_start(args,len); x[0] = len; for (i=1; i<=l; i++) x[i] = va_arg(args,int); va_end(args); return x; } /* return a VECSMALL of length l from the arguments (for galoismodulo11) */ static GEN _typ(long l,...) { va_list args; long i; GEN x = cgetg(l+1, t_VECSMALL); va_start(args,l); for (i=1; i<=l; i++) x[i] = va_arg(args,int); va_end(args); return x; } /* create a permutation with the N arguments of the function */ static PERM _cr(long N, long a,...) { static long x[NMAX+1]; va_list args; long i; va_start(args, a); x[0] = N; x[1] = a; for (i=2; i<=N; i++) x[i] = va_arg(args,int); va_end(args); return x; } static PERM permmul(PERM s1, PERM s2) { long i, n1 = s1[0]; PERM s3 = (PERM)stack_malloc((n1+1) * sizeof(long)); for (i=1; i<=n1; i++) s3[i] = s1[s2[i]]; s3[0] = n1; return s3; } static void printperm(PERM perm) { long i, n = perm[0]; err_printf("("); for (i=1; i<=n; i++) err_printf(" %d",perm[i]); err_printf(" )\n"); } static int raye(long *g, long num) { long i, nb = labs(g[0]); for (i=1; i<=nb; i++) if (g[i] == num) return 0; return 1; } /* we can never determine the group completely in there */ static long rayergroup11(long EVEN, long num, long *gr) { long r = 0; if (EVEN) switch(num) { case 2: case 5: if (gr[3]) { gr[3]=0; r++; } case 3: case 6: case 7: if (gr[2]) { gr[2]=0; r++; } case 4: if (gr[1]) { gr[1]=0; r++; } } else switch(num) { case 2: case 3: if (gr[1]) { gr[1]=0; r++; } } return r; } static long rayergroup(long EVEN, long **GR, long num, long *gr) { long i,nbgr,r; if (!GR) return rayergroup11(EVEN,num,gr); nbgr = lg(GR); r = 0 ; if (EVEN) { for (i=1; i 0 && raye(GR[i],num)) { gr[i]=0; r++; } } return r; } static long galmodp(long EVEN, GEN pol, GEN dpol, GEN TYP, long *gr, long **GR) { long i,k,l,n,nbremain; GEN p1, dtyp; forprime_t T; switch(degpol(pol)) { case 8: nbremain = EVEN? 28: 22; break; case 9: nbremain = EVEN? 18: 16; break; case 10: nbremain = EVEN? 12: 33; break; default: nbremain = EVEN? 5: 3; break; /* case 11 */ } u_forprime_init(&T, 2, ULONG_MAX); dtyp = new_chunk(NMAX+1); k = gr[0]; for (i=1; ir; long i, l = lg(r), p = BR->pr; if (p > BR->prmax) pari_err_BUG("fixprex [precision too large]"); for (i = 1; i < l; i++) preci(gel(r,i), p); } static long getpreci(buildroot *BR) { GEN x = gmael(BR->r,1,1); return (typ(x)==t_COMPLEX)? realprec(gel(x,1)): realprec(x); } #define setcard_obj(x,n) ((x)[0] = (PERM)(n)) #define getcard_obj(x) ((long)((x)[0])) /* allocate a list of m arrays of length n (index 0 is codeword) */ static PERM * alloc_pobj(long n, long m) { long i; PERM *g = (PERM*) stack_malloc( (m+1)*sizeof(PERM) + (n+1)*m * sizeof(long) ); PERM gpt = (PERM) (g + (m+1)); for (i=1; i<=m; i++) { g[i] = gpt; gpt += (n+1); } setcard_obj(g, m); return g; } static GROUP allocgroup(long n, long card) { GROUP gr = alloc_pobj(n,card); long i; for (i=1; i<=card; i++) gr[i][0] = n; return gr; } static pariFILE * galopen(const char *pre, long n, long n1, long n2) { pari_sp av = avma; char *s = stack_malloc(strlen(pari_datadir) + 3 + 4 * 20 + 1 + 3); pariFILE *f; (void)sprintf(s, "%s/galdata/%s%ld_%ld_%ld", pari_datadir, pre, n, n1, n2); f = pari_fopengz(s); if (!f) pari_err_FILE("galois file",s); avma = av; return f; } static char bin(char c) { if (c>='0' && c<='9') c -= '0'; else if (c>='A' && c<='Z') c -= 'A'-10; else if (c>='a' && c<='z') c -= 'a'-36; else pari_err_TYPE("bin [not alphanumeric]", stoi(c)); return c; } #define BUFFS 512 /* fill in g[i][j] (i<=n, j<=m) with (buffered) data from f->file */ static void read_obj(PERM *g, pariFILE *f, long n, long m) { long i, j, k, N = m*n; char *ch = stack_malloc(N); pari_fread_chars(ch, N, f->file); for (k = 0, i = 1; i <= n; i++) for (j = 1; j <= m; j++,k++) g[i][j] = bin(ch[k]); pari_fclose(f); } #undef BUFFS /* the first 8 bytes contain size data (possibly padded with \0) */ static GROUP lirecoset(long n1, long n2, long n) { GROUP gr; char c, ch[8]; long m, cardgr; pariFILE *f = galopen("COS", n, n1, n2); pari_fread_chars(&c, 1, f->file); m=bin(c); pari_fread_chars(&c, 1, f->file); pari_fread_chars(ch, 6, f->file); cardgr=atol(ch); gr=allocgroup(m,cardgr); read_obj(gr, f,cardgr,m); return gr; } static void lireresolv(long n1, long n2, long n, resolv *R) { char ch[5]; long nm, nv; pariFILE *f = galopen("RES", n, n1, n2); pari_fread_chars(ch,5,f->file); nm = atol(ch); pari_fread_chars(ch,3,f->file); nv = atol(ch); R->a = alloc_pobj(nv,nm); read_obj(R->a, f,nm,nv); R->nm = nm; R->nv = nv; } static int cmp_re(GEN x, GEN y) { if (typ(x) != t_COMPLEX) return -1; if (typ(y) != t_COMPLEX) return 1; /* t_REALS are smallest */ return gcmp(gel(x,1), gel(y,1)); } /* multiply the r o bb. Sort first to detect pairs of conjugate */ static GEN Monomial(GEN r, PERM bb, long nbv) { GEN t, R = cgetg(nbv + 1, t_VEC); long i, s = 1; for (i = 1; i <= nbv; i++) { t = gel(r,bb[i]); if (typ(t) == t_COMPLEX && signe(gel(t,1)) < 0) { s = -s; t = gneg(t); } gel(R,i) = t; } if (nbv > 2) gen_sort_inplace(R, (void*)&cmp_re, cmp_nodata, NULL); else if (nbv == 2 && typ(gel(R,2)) != t_COMPLEX) swap(gel(R,1), gel(R,2)); t = NULL; for (i=1; i<=nbv; i++) { GEN c = gel(R,i); if (typ(c) == t_COMPLEX && i < nbv) { /* detect conjugates */ GEN n = gel(R,++i); if (!absr_cmp(gel(n,1), gel(c,1)) && !absr_cmp(gel(n,2), gel(c,2)) && signe(gel(c,2)) != signe(gel(n,2))) c = addrr(sqrr(gel(c,1)), sqrr(gel(c,2))); else c = gmul(c,n); } t = t? gmul(t, c): c; } if (s < 0) t = gneg(t); return t; } /* sum(i = 1, R->nm, Monomial(r, R->a[i], R->nv)). Sort real / imaginary part * separately by increasing absolute values, to increase stability */ static GEN gpolynomial(GEN r, resolv *R) { GEN RE = cgetg(R->nm+1, t_VEC), IM = cgetg(R->nm+1, t_VEC), re, im; long i, k; for (i = k = 1; i <= R->nm; i++) { GEN m = Monomial(r,R->a[i], R->nv); if (typ(m) == t_REAL) gel(RE, i) = m; else { gel(RE, i) = gel(m,1); gel(IM, k++) = gel(m,2); } } setlg(IM, k); RE = vecpermute(RE, gen_indexsort(RE, (void*)&absr_cmp, cmp_nodata)); IM = vecpermute(IM, gen_indexsort(IM, (void*)&absr_cmp, cmp_nodata)); re = gel(RE,1); for (i = 2; i <= R->nm; i++) re = addrr(re, gel(RE,i)); if (k == 1) return re; im = gel(IM,1); for (i = 2; i < k; i++) im = addrr(im, gel(IM,i)); return mkcomplex(re, im); } static void zaux1(GEN *z, GEN *r) { GEN p2,p1; p2=gsub(r[1], gadd(r[2],r[5])); p2=gmul(p2, gsub(r[2],r[5])); p1=gmul(p2,r[1]); p2=gsub(r[3],gadd(r[2],r[4])); p2=gmul(p2,gsub(r[4],r[2])); p1=gadd(p1,gmul(p2,r[3])); p2=gmul(r[5],gsub(r[4],r[5])); z[1]=gadd(p1,gmul(p2,r[4])); p2=gsub(r[1],gadd(r[3],r[4])); p2=gmul(p2,gsub(r[3],r[4])); p1=gmul(p2,r[1]); p2=gsub(r[5],gadd(r[3],r[2])); p2=gmul(p2,gsub(r[2],r[3])); p1=gadd(p1,gmul(p2,r[5])); p2=gmul(r[4],gsub(r[2],r[4])); z[2]=gadd(p1,gmul(p2,r[2])); } static void zaux(GEN *z, GEN *r) { zaux1(z, r); zaux1(z+2, r+5); } static GEN gpoly(GEN rr, long n1, long n2) { const long N = lg(rr)-1; GEN p1,p2,z[6], *r = (GEN*)rr; /* syntaxic kludge */ long i,j; if (N==8) { if (n1==47 && n2==46) { p1=gsub(r[3],r[4]); for (i=1; i<3; i++) for (j=i+1; j<5; j++) p1 = gmul(p1,gsub(r[i],r[j])); for (i=5; i<8; i++) for (j=i+1; j<9; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2=r[1]; for (i=2; i<5; i++) p2=gadd(p2,r[i]); for (i=5; i<9; i++) p2=gsub(p2,r[i]); } else /* n1==44 && n2==40 */ { for (i=1; i<5; i++) z[i] = gadd(r[2*i-1],r[2*i]); p1 = gsub(r[1],r[2]); for (i=2; i<5; i++) p1 = gmul(p1,gsub(r[2*i-1],r[2*i])); p2=gsub(z[3],z[4]); for (i=1; i<3; i++) for (j=i+1; j<5; j++) p2 = gmul(p2,gsub(z[i],z[j])); } return gmul(p1,p2); } if (N==9) { if (n1==31 && n2==29) { p1=gsub(r[2],r[3]); for (j=2; j<4; j++) p1 = gmul(p1,gsub(r[1],r[j])); for (i=4; i<6; i++) for (j=i+1; j<7; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2 = gsub(r[8],r[9]); for (j=8; j<10; j++) p2 = gmul(p2,gsub(r[7],r[j])); } else /* ((n1==34 && n2==31) || (n1=33 && n2==30)) */ { p1=r[1]; for (i=2; i<4; i++) p1=gadd(p1,r[i]); p2=r[4]; for (i=5; i<7; i++) p2=gadd(p2,r[i]); p1=gmul(p1,p2); p2=r[7]; for (i=8; i<10; i++) p2=gadd(p2,r[i]); } return gmul(p1,p2); } if (N==10) { if ((n1==45 && n2==43) || (n1==44 && n2==42)) { p1=r[1]; for (i=2; i<6; i++) p1=gadd(p1,r[i]); p2=r[6]; for (i=7; i<11; i++) p2=gadd(p2,r[i]); return gmul(p1,p2); } else if ((n1==45 && n2==39) || (n1==44 && n2==37)) { p1 = gadd(r[1],r[2]); for (i=2; i<6; i++) p1 = gmul(p1,gadd(r[2*i-1],r[2*i])); return p1; } else if ((n1==43 && n2==41) || (n1==33 && n2==27)) { p1=gsub(r[4],r[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p1=gmul(p1,gsub(r[i],r[j])); p2=gsub(r[9],r[10]); for (i=6; i<9; i++) for (j=i+1; j<11; j++) p2=gmul(p2,gsub(r[i],r[j])); return gmul(p1,p2); } else if ((n1==43 && n2==33) || (n1==42 && n2==28) || (n1==41 && n2==27) || (n1==40 && n2==21)) { p2=gadd(r[2],r[5]); p2=gsub(p2,gadd(r[3],r[4])); p1=gmul(p2,r[1]); p2=gsub(r[3],gadd(r[4],r[5])); p1=gadd(p1,gmul(p2,r[2])); p2=gsub(r[4],r[5]); p1=gadd(p1,gmul(p2,r[3])); z[1]=gadd(p1,gmul(r[4],r[5])); p2=gadd(r[7],r[10]); p2=gsub(p2,gadd(r[8],r[9])); p1=gmul(p2,r[6]); p2=gsub(r[8],gadd(r[9],r[10])); p1=gadd(p1,gmul(p2,r[7])); p2=gsub(r[9],r[10]); p1=gadd(p1,gmul(p2,r[8])); z[2]=gadd(p1,gmul(r[9],r[10])); return gadd(gsqr(z[1]), gsqr(z[2])); } else if (n1==41 && n2==40) { p1=gsub(r[4],r[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2=gsub(r[9],r[10]); for (i=6; i<9; i++) for (j=i+1; j<11; j++) p2 = gmul(p2,gsub(r[i],r[j])); return gadd(p1,p2); } else if ((n1==41 && n2==22) || (n1==40 && n2==11) || (n1==17 && n2==5) || (n1==10 && n2==4) || (n1==9 && n2==3) || (n1==6 && n2==1)) { p1=gadd(r[1],r[6]); for (i=2; i<6; i++) p1=gmul(p1,gadd(r[i],r[i+5])); return p1; } else if ((n1==39 && n2==38) || (n1==29 && n2==25)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(r[1],r[2]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[2*i-1],r[2*i])); p2=gsub(z[4],z[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==39 && n2==36) || (n1==37 && n2==34) || (n1==29 && n2==23) || (n1==24 && n2==15)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(z[4],z[5]); p2=gmul(gsub(z[3],z[4]),gsub(z[3],z[5])); for (i=1; i<3; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==39 && n2==29) || (n1==38 && n2==25) || (n1==37 && n2==24) || (n1==36 && n2==23) || (n1==34 && n2==15)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p2=gadd(z[2],z[5]); p2=gsub(p2,gadd(z[3],z[4])); p1=gmul(p2,z[1]); p2=gsub(z[3],gadd(z[4],z[5])); p1=gadd(p1,gmul(p2,z[2])); p2=gsub(z[4],z[5]); p1=gadd(p1,gmul(p2,z[3])); p1=gadd(p1,gmul(z[4],z[5])); return gsqr(p1); } else if ((n1==39 && n2==22) || (n1==38 && n2==12) || (n1==36 && n2==11) || (n1==29 && n2== 5) || (n1==25 && n2== 4) || (n1==23 && n2== 3) || (n1==16 && n2== 2) || (n1==14 && n2== 1)) { p1=r[1]; for (i=2; i<6; i++) p1=gadd(p1,r[2*i-1]); p2=r[2]; for (i=2; i<6; i++) p2=gadd(p2,r[2*i]); return gmul(p1,p2); } else if (n1==28 && n2==18) { zaux(z, r); p1=gmul(z[1],gsub(z[3],z[4])); p2=gmul(z[2],gadd(z[3],z[4])); return gadd(p1,p2); } else if (n1==27 && n2==20) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); p1 = gsub(p1,p2); p2=r[1]; for (i=2; i<6 ; i++) p2=gadd(p2,r[i]); for ( ; i<11; i++) p2=gsub(p2,r[i]); return gmul(p1,p2); } else if (n1==27 && n2==19) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); return gsub(p1,p2); } else if ((n1==27 && n2==17) || (n1==21 && n2==9)) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); return gadd(p1,p2); } else if (n1==23 && n2==16) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(z[1],gadd(z[2],z[5])); p1=gmul(p1,gsub(z[2],z[5])); p2=gmul(p1,z[1]); p1=gsub(z[3],gadd(z[2],z[4])); p1=gmul( p1,gsub(z[4],z[2])); p2=gadd(p2,gmul(p1,z[3])); p1=gmul(z[5],gsub(z[4],z[5])); p2=gadd(p2,gmul(p1,z[4])); p1=gsub(r[1],r[2]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[2*i-1],r[2*i])); return gmul(p1,p2); } else if (n1==22 && n2==12) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p1=gsub(r[1],r[6]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[i],r[i+5])); p2=gsub(z[4],z[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==22 && n2==11) || (n1==5 && n2==3)) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p1=gsub(z[4],z[5]); p2=gmul(gsub(z[3],z[4]),gsub(z[3],z[5])); for (i=1; i<3; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==22 && n2==5) || (n1==12 && n2==4) || (n1==11 && n2==3)) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p2=gadd(z[2],z[5]); p2=gsub(p2,gadd(z[3],z[4])); p1=gmul(p2,z[1]); p2=gsub(z[3],gadd(z[4],z[5])); p1=gadd(p1,gmul(p2,z[2])); p2=gsub(z[4],z[5]); p1=gadd(p1,gmul(p2,z[3])); p1=gadd(p1,gmul(z[4],z[5])); return gsqr(p1); } else if (n1==21 && n2==10) { zaux(z, r); p1=gmul(z[1],z[4]); p2=gmul(z[2],z[3]); return gsub(p1,p2); } } pari_err_TYPE("gpoly [undefined invariant polynomial]", mkvecsmall2(n1,n2)); return NULL; /* not reached */ } /* a is a t_VECSMALL representing a polynomial */ static GEN new_pol(long N, GEN r, GEN a) { long i, j, l = lg(a); GEN x, z, v = cgetg(N+1, t_VEC); for (i=1; i<=N; i++) { z = gel(r,i); x = gaddsg(a[2], z); for (j = 3; j < l; j++) x = gaddsg(a[j], gmul(z,x)); gel(v,i) = x; } return gclone(v); } /* BR->r[l], BR->coef[l] hold data related to Tschirnausen transform of * degree l - 1 */ static void tschirn(buildroot *BR) { long i, k, v = varn(BR->p), l = lg(BR->r); GEN a, h, r; if (l >= BR->N) pari_err_BUG("tschirn"); if (DEBUGLEVEL) err_printf("\n$$$$$ Tschirnhaus transformation of degree %ld: $$$$$\n",l-1); a = gel(BR->coef,l); /* fill with random polynomial of degree <= l-1 */ do { a[1]=0; for (i=2; i < l+2; i++) a[i] = random_bits(3) + 1; h = Flx_to_ZX(Flx_renormalize(a,l+2)); } while (degpol(h) <= 0 || !ZX_is_squarefree(h)); setvarn(h, v); k = 0; (void)ZXQ_charpoly_sqf(BR->p, h, &k, v); a[2] += k; r = gel(BR->r,1); preci(r, BR->prmax); /* max accuracy original roots */ vectrunc_append(BR->r, new_pol(BR->N, r, a)); fixprec(BR); /* restore accuracy */ } static GEN sortroots(GEN newr, GEN oldr) { long e, e0, i, j, k, l = lg(newr); GEN r = cgetg(l, t_VEC), z = cgetg(l, t_VEC), t = const_vecsmall(l-1, 1); k = 0; /* gcc -Wall */ for (i=1; ir; long i, l = lg(r); for (i = 1; i < l; i++) gunclone(gel(r,i)); setlg(r, 1); } /* increase the roots accuracy */ static void moreprec(buildroot *BR) { long d = BR->pr - BR->prmax; if (d > 0) { /* recompute roots */ pari_sp av = avma; long l = lg(BR->r); GEN ro; if (d < BIGDEFAULTPREC-2) d = BIGDEFAULTPREC-2; BR->prmax = maxss(BR->prmax+d, (long)(BR->prmax * 1.2)); if (DEBUGLEVEL) { err_printf("$$$$$ New prec = %ld\n",BR->prmax); err_flush(); } ro = sortroots(QX_complex_roots(BR->p,BR->prmax), gel(BR->r,1)); delete_roots(BR); vectrunc_append(BR->r, gclone(ro)); for (d = 2; d < l; d++) vectrunc_append(BR->r, new_pol(BR->N, ro, gel(BR->coef,d))); avma = av; } fixprec(BR); } /* determine "sufficient" extra bit-precision such that we may decide * (heuristic) whether z is an integer. */ static GEN get_ro(long N, GEN rr, PERM S1, PERM S2, resolv *R) { GEN r = cgetg(N+1, t_VEC); long i; for (i=1; i<=N; i++) r[i] = rr[ S1[S2[i] ] ]; return R->a? gpolynomial(r, R): gpoly(r,R->nm,R->nv); } /* typ(z) = t_REAL, return zi = t_INT approximation */ static long sufprec_r(GEN z) { long p = bit_prec(z); /* bit accuracy of fractional part large enough ? */ return ( p - expo(z) > maxss(3*32, (long)0.2*p) ); } /* typ(z) = t_REAL or t_COMPLEX, return zi = t_INT approximation */ static long sufprec(GEN z) { if (typ(z) == t_REAL) return sufprec_r(z); else return sufprec_r(gel(z,2)) && sufprec_r(gel(z,1)); } static GEN get_ro_perm(PERM S1, PERM S2, long d, resolv *R, buildroot *BR) { GEN ro, roi; long e; for (;;) { ro = get_ro(BR->N, gel(BR->r, d), S1,S2,R); roi = grndtoi(ro, &e); if (e < 0) { if (e < -64 || sufprec(ro)) break; e = 0; } BR->pr += nbits2extraprec(e + 10); moreprec(BR); } if (e > -10 || typ(roi) == t_COMPLEX) return NULL; /* compute with 128 more bits */ BR->pr += MEDDEFAULTPREC-2; moreprec(BR); ro = get_ro(BR->N, gel(BR->r, d), S1,S2,R); BR->pr -= MEDDEFAULTPREC-2; fixprec(BR); /* ro closer to roi (32 more bits) ? */ return (gexpo(gsub(ro, roi)) < e - 32) ? roi: NULL; } static void dbg_rac(long nri,long nbracint,long numi[],GEN racint[],long multi[]) { long k; err_printf("\t# rational integer roots = %ld:",nbracint-nri); for (k = nri+1; k <= nbracint; k++) err_printf(" %ld^%ld", numi[k], multi[k]); err_printf("\n"); for (k = nri+1; k <= nbracint; k++) err_printf("\t%2ld: %Ps\n", numi[k], racint[k]); err_flush(); } #define M 2521 /* return NULL if not included, the permutation of the roots otherwise */ static PERM check_isin(buildroot *BR, resolv *R, GROUP tau, GROUP ss) { long nogr, nocos, init, i, j, k, l, d; pari_sp av1 = avma, av2; long nbgr,nbcos,nbracint,nbrac,lastnbri,lastnbrm; static long numi[M],numj[M],lastnum[M],multi[M],norac[M],lastnor[M]; GEN racint[M], roint; if (getpreci(BR) != BR->pr) fixprec(BR); nbcos = getcard_obj(ss); nbgr = getcard_obj(tau); lastnbri = lastnbrm = -1; nbracint = nbrac = 0; /* gcc -Wall*/ for (nogr=1; nogr<=nbgr; nogr++) { PERM T = tau[nogr]; if (DEBUGLEVEL) err_printf(" ----> Group # %ld/%ld:\n",nogr,nbgr); init = 0; d = 1; for (;;) { if (!init) { av2 = avma; nbrac = nbracint = 0; for (nocos=1; nocos<=nbcos; nocos++, avma = av2) { roint = get_ro_perm(T, ss[nocos], d, R, BR); if (!roint) continue; nbrac++; if (nbrac >= M) { pari_warn(warner, "more than %ld rational integer roots\n", M); avma = av1; goto NEXT; } for (j=1; j<=nbracint; j++) if (equalii(roint,racint[j])) { multi[j]++; break; } if (j > nbracint) { nbracint = j; multi[j] = 1; numi[j] = nocos; racint[j] = gerepileuptoint(av2,roint); av2 = avma; } numj[nbrac] = nocos; norac[nbrac] = j; } if (DEBUGLEVEL) dbg_rac(0,nbracint,numi,racint,multi); for (i=1; i<=nbracint; i++) if (multi[i]==1) return permmul(T, ss[numi[i]]); init = 1; } else { nbrac = nbracint = 0; for (l=1; l<=lastnbri; l++, avma = av1) { long nri = nbracint; av2 = avma; for (k=1; k<=lastnbrm; k++) if (lastnor[k]==l) { nocos = lastnum[k]; roint = get_ro_perm(T, ss[nocos], d, R, BR); if (!roint) { avma = av2; continue; } nbrac++; for (j=nri+1; j<=nbracint; j++) if (equalii(roint,racint[j])) { multi[j]++; break; } if (j > nbracint) { nbracint = j; multi[j] = 1; numi[j] = nocos; racint[j] = gerepileuptoint(av2,roint); av2=avma; } numj[nbrac] = nocos; norac[nbrac] = j; } if (DEBUGLEVEL) dbg_rac(nri,nbracint,numi,racint,multi); for (i=nri+1; i<=nbracint; i++) if (multi[i]==1) return permmul(T, ss[numi[i]]); } } avma = av1; if (!nbracint) break; lastnbri = nbracint; lastnbrm = nbrac; for (j=1; j<=nbrac; j++) { lastnum[j] = numj[j]; lastnor[j] = norac[j]; } NEXT: if (DEBUGLEVEL) { err_printf(" all integer roots are double roots\n"); err_printf(" Working with polynomial #%ld:\n", d+1); } if (++d >= lg(BR->r)) tschirn(BR); } } return NULL; } #undef M /* DEGREE 8 */ static long galoisprim8(long EVEN, buildroot *BR) { long rep; rep=isin_G_H(BR,50,43); if (rep) return EVEN? 37: 43; if (!EVEN) return 50; rep=isin_G_H(BR,49,48); if (!rep) return 49; rep=isin_G_H(BR,48,36); if (!rep) return 48; rep=isin_G_H(BR,36,25); return rep? 25: 36; } static long galoisimpodd8(buildroot *BR, long nh) { long rep; if (nh!=47) goto IMPODD_8_6; rep=isin_G_H(BR,47,46); if (!rep) goto IMPODD_8_5; rep=isin_G_H(BR,46,28); if (rep) goto IMPODD_8_7; else return 46; IMPODD_8_5: rep=isin_G_H(BR,47,35); if (rep) goto IMPODD_8_9; else return 47; IMPODD_8_6: rep=isin_G_H(BR,44,40); if (rep) goto IMPODD_8_10; else goto IMPODD_8_11; IMPODD_8_7: rep=isin_G_H(BR,28,21); if (rep) return 21; else goto IMPODD_8_33; IMPODD_8_9: rep=isin_G_H(BR,35,31); if (rep) goto IMPODD_8_13; else goto IMPODD_8_14; IMPODD_8_10: rep=isin_G_H(BR,40,26); if (rep) goto IMPODD_8_15; else goto IMPODD_8_16; IMPODD_8_11: rep=isin_G_H(BR,44,38); if (rep) goto IMPODD_8_17; else goto IMPODD_8_18; IMPODD_8_12: rep=isin_G_H(BR,16,7); if (rep) goto IMPODD_8_19; else return 16; IMPODD_8_13: rep=isin_G_H(BR,31,21); return rep? 21: 31; IMPODD_8_14: rep=isin_G_H(BR,35,30); if (rep) goto IMPODD_8_34; else goto IMPODD_8_20; IMPODD_8_15: rep=isin_G_H(BR,26,16); if (rep) goto IMPODD_8_12; else goto IMPODD_8_21; IMPODD_8_16: rep=isin_G_H(BR,40,23); if (rep) goto IMPODD_8_22; else return 40; IMPODD_8_17: rep=isin_G_H(BR,38,31); if (rep) goto IMPODD_8_13; else return 38; IMPODD_8_18: rep=isin_G_H(BR,44,35); if (rep) goto IMPODD_8_9; else return 44; IMPODD_8_19: rep=isin_G_H(BR,7,1); return rep? 1: 7; IMPODD_8_20: rep=isin_G_H(BR,35,28); if (rep) goto IMPODD_8_7; else goto IMPODD_8_23; IMPODD_8_21: rep=isin_G_H(BR,26,17); if (rep) goto IMPODD_8_24; else goto IMPODD_8_25; IMPODD_8_22: rep=isin_G_H(BR,23,8); if (rep) goto IMPODD_8_26; else return 23; IMPODD_8_23: rep=isin_G_H(BR,35,27); if (rep) goto IMPODD_8_27; else goto IMPODD_8_28; IMPODD_8_24: rep=isin_G_H(BR,17,7); if (rep) goto IMPODD_8_19; else return 17; IMPODD_8_25: rep=isin_G_H(BR,26,15); if (rep) goto IMPODD_8_29; else return 26; IMPODD_8_26: rep=isin_G_H(BR,8,1); return rep? 1: 8; IMPODD_8_27: rep=isin_G_H(BR,27,16); if (rep) goto IMPODD_8_12; else return 27; IMPODD_8_28: rep=isin_G_H(BR,35,26); if (rep) goto IMPODD_8_15; else return 35; IMPODD_8_29: rep=isin_G_H(BR,15,7); if (rep) goto IMPODD_8_19; rep=isin_G_H(BR,15,6); if (!rep) goto IMPODD_8_32; rep=isin_G_H(BR,6,1); return rep? 1: 6; IMPODD_8_32: rep=isin_G_H(BR,15,8); if (rep) goto IMPODD_8_26; else return 15; IMPODD_8_33: rep=isin_G_H(BR,28,16); if (rep) goto IMPODD_8_12; else return 28; IMPODD_8_34: rep=isin_G_H(BR,30,21); return rep? 21: 30; } static long galoisimpeven8(buildroot *BR, long nh) { long rep; if (nh!=45) goto IMPEVEN_8_6; rep=isin_G_H(BR,45,42); if (!rep) goto IMPEVEN_8_5; rep=isin_G_H(BR,42,34); if (rep) goto IMPEVEN_8_7; else goto IMPEVEN_8_8; IMPEVEN_8_5: rep=isin_G_H(BR,45,41); if (rep) goto IMPEVEN_8_9; else return 45; IMPEVEN_8_6: rep=isin_G_H(BR,39,32); if (rep) goto IMPEVEN_8_10; else goto IMPEVEN_8_11; IMPEVEN_8_7: rep=isin_G_H(BR,34,18); if (rep) goto IMPEVEN_8_21; else goto IMPEVEN_8_45; IMPEVEN_8_8: rep=isin_G_H(BR,42,33); if (rep) goto IMPEVEN_8_14; else return 42; IMPEVEN_8_9: rep=isin_G_H(BR,41,34); if (rep) goto IMPEVEN_8_7; else goto IMPEVEN_8_15; IMPEVEN_8_10: rep=isin_G_H(BR,32,22); if (rep) goto IMPEVEN_8_16; else goto IMPEVEN_8_17; IMPEVEN_8_11: rep=isin_G_H(BR,39,29); if (rep) goto IMPEVEN_8_18; else goto IMPEVEN_8_19; IMPEVEN_8_12: rep=isin_G_H(BR,14,4); return rep? 4: 14; IMPEVEN_8_14: rep=isin_G_H(BR,33,18); if (rep) goto IMPEVEN_8_21; else goto IMPEVEN_8_22; IMPEVEN_8_15: rep=isin_G_H(BR,41,33); if (rep) goto IMPEVEN_8_14; else goto IMPEVEN_8_23; IMPEVEN_8_16: rep=isin_G_H(BR,22,11); if (rep) goto IMPEVEN_8_24; else goto IMPEVEN_8_25; IMPEVEN_8_17: rep=isin_G_H(BR,32,13); if (rep) goto IMPEVEN_8_26; else goto IMPEVEN_8_27; IMPEVEN_8_18: rep=isin_G_H(BR,29,22); if (rep) goto IMPEVEN_8_16; else goto IMPEVEN_8_28; IMPEVEN_8_19: rep=isin_G_H(BR,39,24); if (rep) goto IMPEVEN_8_29; else return 39; IMPEVEN_8_20: rep=isin_G_H(BR,9,4); if (rep) return 4; else goto IMPEVEN_8_30; IMPEVEN_8_21: rep=isin_G_H(BR,18,10); if (rep) goto IMPEVEN_8_31; else goto IMPEVEN_8_32; IMPEVEN_8_22: rep=isin_G_H(BR,33,13); if (rep) goto IMPEVEN_8_26; else return 33; IMPEVEN_8_23: rep=isin_G_H(BR,41,29); if (rep) goto IMPEVEN_8_18; else goto IMPEVEN_8_33; IMPEVEN_8_24: rep=isin_G_H(BR,11,5); if (rep) return 5; else goto IMPEVEN_8_34; IMPEVEN_8_25: rep=isin_G_H(BR,22,9); if (rep) goto IMPEVEN_8_20; else return 22; IMPEVEN_8_26: rep=isin_G_H(BR,13,3); return rep? 3: 13; IMPEVEN_8_27: rep=isin_G_H(BR,32,12); if (rep) goto IMPEVEN_8_35; else return 32; IMPEVEN_8_28: rep=isin_G_H(BR,29,20); if (rep) goto IMPEVEN_8_36; else goto IMPEVEN_8_37; IMPEVEN_8_29: rep=isin_G_H(BR,24,14); if (rep) goto IMPEVEN_8_12; else goto IMPEVEN_8_38; IMPEVEN_8_30: rep=isin_G_H(BR,9,3); if (rep) return 3; else goto IMPEVEN_8_39; IMPEVEN_8_31: rep=isin_G_H(BR,10,2); return rep? 2: 10; IMPEVEN_8_32: rep=isin_G_H(BR,18,9); if (rep) goto IMPEVEN_8_20; else return 18; IMPEVEN_8_33: rep=isin_G_H(BR,41,24); if (rep) goto IMPEVEN_8_29; else return 41; IMPEVEN_8_34: rep=isin_G_H(BR,11,4); if (rep) return 4; else goto IMPEVEN_8_44; IMPEVEN_8_35: rep=isin_G_H(BR,12,5); return rep? 5: 12; IMPEVEN_8_36: rep=isin_G_H(BR,20,10); if (rep) goto IMPEVEN_8_31; else return 20; IMPEVEN_8_37: rep=isin_G_H(BR,29,19); if (rep) goto IMPEVEN_8_40; else goto IMPEVEN_8_41; IMPEVEN_8_38: rep=isin_G_H(BR,24,13); if (rep) goto IMPEVEN_8_26; else goto IMPEVEN_8_42; IMPEVEN_8_39: rep=isin_G_H(BR,9,2); return rep? 2: 9; IMPEVEN_8_40: rep=isin_G_H(BR,19,10); if (rep) goto IMPEVEN_8_31; else goto IMPEVEN_8_43; IMPEVEN_8_41: rep=isin_G_H(BR,29,18); if (rep) goto IMPEVEN_8_21; else return 29; IMPEVEN_8_42: rep=isin_G_H(BR,24,9); if (rep) goto IMPEVEN_8_20; else return 24; IMPEVEN_8_43: rep=isin_G_H(BR,19,9); if (rep) goto IMPEVEN_8_20; else return 19; IMPEVEN_8_44: rep=isin_G_H(BR,11,2); return rep? 2: 11; IMPEVEN_8_45: rep=isin_G_H(BR,34,14); if (rep) goto IMPEVEN_8_12; else return 34; } static long closure8(long EVEN, buildroot *BR) { long rep; if (!EVEN) { rep=isin_G_H(BR,50,47); if (rep) return galoisimpodd8(BR,47); rep=isin_G_H(BR,50,44); if (rep) return galoisimpodd8(BR,44); } else { rep=isin_G_H(BR,49,45); if (rep) return galoisimpeven8(BR,45); rep=isin_G_H(BR,49,39); if (rep) return galoisimpeven8(BR,39); } return galoisprim8(EVEN, BR); } static GROUP initgroup(long n, long nbgr) { GROUP t = allocgroup(n,nbgr); PERM ID = t[1]; long i; for (i = 1; i <= n; i++) ID[i] = i; return t; } static PERM data8(long N, long n1, long n2, GROUP *t) { switch(n1) { case 7: if (n2!=1) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 6, 5, 8, 7); return (*t)[1]; case 9: if (n2!=4) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 4, 3, 5, 6, 8, 7); return (*t)[1]; case 10: if (n2!=2) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 6, 5, 8, 7); return (*t)[1]; case 11: switch(n2) { case 2: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 5, 6, 3, 4, 8, 7); return _cr(N, 1, 3, 5, 8, 2, 4, 6, 7); case 4: *t=initgroup(N,1); return _cr(N, 1, 3, 7, 5, 2, 4, 8, 6); }break; case 14: if (n2!=4) break; *t=initgroup(N,1); return _cr(N, 1, 2, 4, 3, 5, 6, 8, 7); case 15: if (n2!=6 && n2!=8) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 6, 5, 8, 7); return (*t)[1]; case 16: if (n2!=7) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 18: switch(n2) { case 9: *t=initgroup(N,3); _aff(N, (*t)[2], 1, 5, 3, 7, 2, 6, 4, 8); _aff(N, (*t)[3], 1, 2, 3, 4, 6, 5, 8, 7); return (*t)[1]; case 10: *t=initgroup(N,3); _aff(N, (*t)[2], 1, 6, 3, 8, 2, 5, 4, 7); _aff(N, (*t)[3], 1, 5, 3, 7, 2, 6, 4, 8); return (*t)[1]; }break; case 19: if (n2!=9) break; *t=initgroup(N,1); return _cr(N, 1, 5, 3, 8, 2, 6, 4, 7); case 20: if (n2!=10) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 22: switch(n2) { case 9: *t=initgroup(N,6); _aff(N, (*t)[2], 1, 2, 7, 8, 3, 4, 6, 5); _aff(N, (*t)[3], 1, 2, 7, 8, 3, 4, 5, 6); _aff(N, (*t)[4], 1, 2, 5, 6, 3, 4, 8, 7); _aff(N, (*t)[5], 1, 2, 5, 6, 3, 4, 7, 8); _aff(N, (*t)[6], 1, 2, 3, 4, 5, 6, 8, 7); return _cr(N, 1, 3, 5, 7, 2, 4, 6, 8); case 11: *t=initgroup(N,6); _aff(N, (*t)[2], 1, 2, 5, 6, 7, 8, 4, 3); _aff(N, (*t)[3], 1, 2, 5, 6, 7, 8, 3, 4); _aff(N, (*t)[4], 1, 2, 3, 4, 7, 8, 6, 5); _aff(N, (*t)[5], 1, 2, 3, 4, 7, 8, 5, 6); _aff(N, (*t)[6], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; }break; case 23: if (n2!=8) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 6, 5, 8, 7); case 26: if (n2!=15 && n2!=17) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 28: if (n2!=21) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 7, 8, 5, 6); case 29: if (n2!=18 && n2!=19) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 30: if (n2!=21) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 7, 8, 5, 6); case 31: if (n2!=21) break; *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 4, 7, 8, 5, 6); _aff(N, (*t)[3], 1, 2, 5, 6, 7, 8, 3, 4); return (*t)[1]; case 32: if (n2!=12 && n2!=13) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 33: switch(n2) { case 13: *t=initgroup(N,1); return _cr(N, 1, 5, 2, 6, 3, 7, 4, 8); case 18: *t=initgroup(N,1); return _cr(N, 1, 2, 5, 6, 3, 4, 7, 8); }break; case 34: switch(n2) { case 14: *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 8, 6, 7); _aff(N, (*t)[3], 1, 2, 3, 4, 5, 7, 8, 6); return _cr(N, 1, 5, 2, 6, 3, 7, 4, 8); case 18: *t=initgroup(N,1); return _cr(N, 1, 2, 5, 6, 3, 4, 8, 7); }break; case 39: if (n2!=24) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 40: if (n2!=23) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 41: switch(n2) { case 24: *t=initgroup(N,1); return _cr(N, 1, 5, 2, 6, 3, 7, 4, 8); case 29: *t=initgroup(N,1); return _cr(N, 1, 2, 5, 6, 3, 4, 7, 8); }break; case 42: if (n2!=34) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 5, 6, 8, 7); case 45: if (n2!=41 && n2!=42) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; case 46: if (n2!=28) break; *t=initgroup(N,1); return _cr(N, 1, 2, 5, 6, 3, 4, 7, 8); case 47: if (n2!=35) break; *t=initgroup(N,1); return _cr(N, 1, 2, 5, 6, 3, 4, 7, 8); case 49: if (n2!=48) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 7); return (*t)[1]; } *t=initgroup(N,1); return (*t)[1]; } static long galoismodulo8(long EVEN, GEN pol, GEN dpol) { long res, gr[51]; pari_sp av = avma; long **GR = (long**)cgeti(49); GEN TYP = partitions_galois(8); /* List of possible types in group j: GR[j][0] = #GR[j] if * the group is odd, - #GR[j] if even */ GR[ 1]= _gr( 4, 1,5,15,22); GR[ 2]= _gr( -3, 1,5,15); GR[ 3]= _gr( -2, 1,5); GR[ 4]= _gr( -3, 1,5,15); GR[ 5]= _gr( -3, 1,5,15); GR[ 6]= _gr( 5, 1,4,5,15,22); GR[ 7]= _gr( 5, 1,3,5,15,22); GR[ 8]= _gr( 5, 1,4,5,15,22); GR[ 9]= _gr( -4, 1,3,5,15); GR[10]= _gr( -4, 1,3,5,15); GR[11]= _gr( -4, 1,3,5,15); GR[12]= _gr( -5, 1,5,9,15,20); GR[13]= _gr( -4, 1,5,9,20); GR[14]= _gr( -4, 1,5,9,15); GR[15]= _gr( 6, 1,3,4,5,15,22); GR[16]= _gr( 5, 1,3,5,15,22); GR[17]= _gr( 7, 1,3,5,11,13,15,22); GR[18]= _gr( -4, 1,3,5,15); GR[19]= _gr( -5, 1,3,5,12,15); GR[20]= _gr( -4, 1,3,5,15); GR[21]= _gr( 5, 1,3,5,13,15); GR[22]= _gr( -4, 1,3,5,15); GR[23]= _gr( 7, 1,4,5,9,15,20,22); GR[24]= _gr( -6, 1,3,5,9,15,20); GR[25]= _gr( -3, 1,5,21); GR[26]= _gr( 8, 1,3,4,5,11,13,15,22); GR[27]= _gr( 8, 1,2,3,4,5,13,15,22); GR[28]= _gr( 7, 1,3,5,12,13,15,22); GR[29]= _gr( -5, 1,3,5,12,15); GR[30]= _gr( 7, 1,3,4,5,11,13,15); GR[31]= _gr( 7, 1,2,3,4,5,13,15); GR[32]= _gr( -6, 1,3,5,9,15,20); GR[33]= _gr( -6, 1,3,5,9,15,20); GR[34]= _gr( -5, 1,3,5,9,15); GR[35]= _gr( 10, 1,2,3,4,5,11,12,13,15,22); GR[36]= _gr( -5, 1,5,9,20,21); GR[37]= _gr( -5, 1,5,9,15,21); GR[38]= _gr( 11, 1,2,3,4,5,9,10,13,15,19,20); GR[39]= _gr( -7, 1,3,5,9,12,15,20); GR[40]= _gr( 10, 1,3,4,5,9,11,13,15,20,22); GR[41]= _gr( -7, 1,3,5,9,12,15,20); GR[42]= _gr( -8, 1,3,5,6,8,9,15,20); GR[43]= _gr( 8, 1,4,5,9,15,19,21,22); GR[44]= _gr( 14, 1,2,3,4,5,9,10,11,12,13,15,19,20,22); GR[45]= _gr( -9, 1,3,5,6,8,9,12,15,20); GR[46]= _gr( 10, 1,3,5,6,8,9,12,13,15,22); GR[47]= _gr( 16, 1,2,3,4,5,6,7,8,9,11,12,13,14,15,20,22); GR[48]= _gr( -8, 1,3,5,9,12,15,20,21); gr[0]=51; res = galmodp(EVEN,pol,dpol,TYP,gr,GR); avma=av; if (!res) return 0; return EVEN? 49: 50; } /* DEGREE 9 */ static long galoisprim9(long EVEN, buildroot *BR) { long rep; if (!EVEN) { rep=isin_G_H(BR,34,26); if (!rep) return 34; rep=isin_G_H(BR,26,19); if (!rep) return 26; rep=isin_G_H(BR,19,16); if (rep) return 16; rep=isin_G_H(BR,19,15); return rep? 15: 19; } rep=isin_G_H(BR,33,32); if (!rep) goto PRIM_9_7; rep=isin_G_H(BR,32,27); return rep? 27: 32; PRIM_9_7: rep=isin_G_H(BR,33,23); if (!rep) return 33; rep=isin_G_H(BR,23,14); if (!rep) return 23; rep=isin_G_H(BR,14,9); return rep? 9: 14; } static long galoisimpodd9(buildroot *BR) { long rep; rep=isin_G_H(BR,31,29); if (!rep) goto IMPODD_9_5; rep=isin_G_H(BR,29,20); if (!rep) return 29; IMPODD_9_3: rep=isin_G_H(BR,20,12); if (!rep) return 20; IMPODD_9_4: rep=isin_G_H(BR,12,4); return rep? 4: 12; IMPODD_9_5: rep=isin_G_H(BR,31,28); if (!rep) goto IMPODD_9_9; rep=isin_G_H(BR,28,22); if (!rep) return 28; IMPODD_9_7: rep=isin_G_H(BR,22,13); if (!rep) return 22; IMPODD_9_8: rep=isin_G_H(BR,13,4); return rep? 4: 13; IMPODD_9_9: rep=isin_G_H(BR,31,24); if (!rep) return 31; rep=isin_G_H(BR,24,22); if (rep) goto IMPODD_9_7; rep=isin_G_H(BR,24,20); if (rep) goto IMPODD_9_3; rep=isin_G_H(BR,24,18); if (!rep) return 24; rep=isin_G_H(BR,18,13); if (rep) goto IMPODD_9_8; rep=isin_G_H(BR,18,12); if (rep) goto IMPODD_9_4; rep=isin_G_H(BR,18,8); if (!rep) return 18; rep=isin_G_H(BR,8,4); return rep? 4: 8; } static long galoisimpeven9(buildroot *BR) { long rep; rep=isin_G_H(BR,30,25); if (!rep) goto IMPEVEN_9_7; rep=isin_G_H(BR,25,17); if (!rep) return 25; IMPEVEN_9_3: rep=isin_G_H(BR,17,7); if (!rep) goto IMPEVEN_9_5; IMPEVEN_9_4: rep=isin_G_H(BR,7,2); return rep? 2: 7; IMPEVEN_9_5: rep=isin_G_H(BR,17,6); if (!rep) return 17; IMPEVEN_9_6: rep=isin_G_H(BR,6,1); return rep? 1: 6; IMPEVEN_9_7: rep=isin_G_H(BR,30,21); if (!rep) return 30; rep=isin_G_H(BR,21,17); if (rep) goto IMPEVEN_9_3; rep=isin_G_H(BR,21,11); if (!rep) goto IMPEVEN_9_13; rep=isin_G_H(BR,11,7); if (rep) goto IMPEVEN_9_4; rep=isin_G_H(BR,11,5); if (!rep) return 11; rep=isin_G_H(BR,5,2); return rep? 2: 5; IMPEVEN_9_13: rep=isin_G_H(BR,21,10); if (!rep) return 21; rep=isin_G_H(BR,10,6); if (rep) goto IMPEVEN_9_6; rep=isin_G_H(BR,10,3); if (!rep) return 10; rep=isin_G_H(BR,3,1); return rep? 1: 3; } static long closure9(long EVEN, buildroot *BR) { long rep; if (!EVEN) { rep=isin_G_H(BR,34,31); if (rep) return galoisimpodd9(BR); } else { rep=isin_G_H(BR,33,30); if (rep) return galoisimpeven9(BR); } return galoisprim9(EVEN, BR); } static PERM data9(long N, long n1, long n2, GROUP *t) { switch(n1) { case 6: if (n2!=1) break; *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 9, 7); _aff(N, (*t)[3], 1, 2, 3, 4, 5, 6, 9, 7, 8); return (*t)[1]; case 7: if (n2!=2) break; *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 9, 7); _aff(N, (*t)[3], 1, 2, 3, 4, 5, 6, 9, 7, 8); return (*t)[1]; case 8: if (n2!=4) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 4, 7, 2, 5, 8, 3, 6, 9); return (*t)[1]; case 12: if (n2!=4) break; *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 9, 7); _aff(N, (*t)[3], 1, 2, 3, 4, 5, 6, 9, 7, 8); return (*t)[1]; case 13: if (n2!=4) break; *t=initgroup(N,1); return _cr(N, 1, 4, 7, 2, 5, 8, 3, 6, 9); case 14: if (n2!=9) break; *t=initgroup(N,3); _aff(N, (*t)[2], 1, 2, 3, 5, 6, 4, 9, 7, 8); _aff(N, (*t)[3], 1, 2, 3, 6, 4, 5, 8, 9, 7); return (*t)[1]; case 17: if (n2!=6) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 7, 8, 9, 4, 5, 6); return (*t)[1]; case 21: if (n2!=10) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 7, 8, 9, 4, 5, 6); return (*t)[1]; case 33: if (n2!=32) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 7, 9, 8); return (*t)[1]; } *t=initgroup(N,1); return (*t)[1]; } static long galoismodulo9(long EVEN, GEN pol, GEN dpol) { long res, gr[35]; pari_sp av = avma; long **GR = (long**) cgeti(33); GEN TYP = partitions_galois(9); /* 42 TYPES ORDONNES CROISSANT (T[1],...,T[30])*/ GR[ 1]= _gr( -3, 1,12,30); GR[ 2]= _gr( -2, 1,12); GR[ 3]= _gr( -4, 1,5,12,30); GR[ 4]= _gr( 4, 1,4,12,26); GR[ 5]= _gr( -3, 1,5,12); GR[ 6]= _gr( -4, 1,10,12,30); GR[ 7]= _gr( -3, 1,10,12); GR[ 8]= _gr( 5, 1,4,5,12,26); GR[ 9]= _gr( -4, 1,5,12,18); GR[10]= _gr( -6, 1,5,10,12,25,30); GR[11]= _gr( -5, 1,5,10,12,25); GR[12]= _gr( 5, 1,4,10,12,26); GR[13]= _gr( 5, 1,4,10,12,26); GR[14]= _gr( -4, 1,5,12,18); GR[15]= _gr( 5, 1,5,12,18,29); GR[16]= _gr( 6, 1,4,5,12,18,26); GR[17]= _gr( -5, 1,6,10,12,30); GR[18]= _gr( 7, 1,4,5,10,12,25,26); GR[19]= _gr( 7, 1,4,5,12,18,26,29); GR[20]= _gr( 9, 1,4,6,9,10,12,24,26,30); GR[21]= _gr( -7, 1,5,6,10,12,25,30); GR[22]= _gr( 7, 1,4,6,10,12,26,30); GR[23]= _gr( -6, 1,5,10,12,18,25); GR[24]= _gr( 11, 1,4,5,6,9,10,12,24,25,26,30); GR[25]= _gr( -7, 1,3,6,8,10,12,30); GR[26]= _gr( 9, 1,4,5,10,12,18,25,26,29); GR[27]= _gr( -5, 1,5,12,27,30); GR[28]= _gr( 12, 1,2,3,4,6,7,8,10,11,12,26,30); GR[29]= _gr( 12, 1,3,4,6,8,9,10,12,15,24,26,30); GR[30]= _gr(-11, 1,3,5,6,8,10,12,14,17,25,30); GR[31]= _gr( 19, 1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,24,25,26,30); GR[32]= _gr( -7, 1,5,10,12,25,27,30); gr[0]=35; res = galmodp(EVEN,pol,dpol,TYP,gr,GR); avma=av; if (!res) return 0; return EVEN? 33: 34; } /* DEGREE 10 */ static long galoisprim10(long EVEN, buildroot *BR) { long rep; if (EVEN) { rep=isin_G_H(BR,44,31); if (!rep) return 44; rep=isin_G_H(BR,31,26); if (!rep) return 31; rep=isin_G_H(BR,26,7); return rep? 7: 26; } else { rep=isin_G_H(BR,45,35); if (!rep) return 45; rep=isin_G_H(BR,35,32); if (!rep) goto PRIM_10_7; rep=isin_G_H(BR,32,13); return rep? 13: 32; PRIM_10_7: rep=isin_G_H(BR,35,30); return rep? 30: 35; } } static long galoisimpeven10(buildroot *BR, long nogr) { long rep; if (nogr==42) { rep=isin_G_H(BR,42,28); if (!rep) return 42; rep=isin_G_H(BR,28,18); return rep? 18: 28; } else { rep=isin_G_H(BR,37,34); if (!rep) goto IMPEVEN_10_5; rep=isin_G_H(BR,34,15); if (rep) goto IMPEVEN_10_7; else return 34; IMPEVEN_10_5: rep=isin_G_H(BR,37,24); if (!rep) return 37; rep=isin_G_H(BR,24,15); if (!rep) return 24; IMPEVEN_10_7: rep=isin_G_H(BR,15,8); return rep? 8: 15; } } static long galoisimpodd10(buildroot *BR, long nogr) { long rep; if (nogr==43) { rep=isin_G_H(BR,43,41); if (!rep) goto IMPODD_10_3; rep=isin_G_H(BR,41,40); if (rep) goto IMPODD_10_4; else goto IMPODD_10_5; IMPODD_10_3: rep=isin_G_H(BR,43,33); if (rep) goto IMPODD_10_6; else return 43; IMPODD_10_4: rep=isin_G_H(BR,40,21); if (rep) goto IMPODD_10_7; else goto IMPODD_10_8; IMPODD_10_5: rep=isin_G_H(BR,41,27); if (rep) goto IMPODD_10_9; else goto IMPODD_10_10; IMPODD_10_6: rep=isin_G_H(BR,33,27); if (rep) goto IMPODD_10_9; else return 33; IMPODD_10_7: rep=isin_G_H(BR,21,10); if (rep) goto IMPODD_10_12; else goto IMPODD_10_13; IMPODD_10_8: rep=isin_G_H(BR,40,12); if (rep) goto IMPODD_10_14; else goto IMPODD_10_15; IMPODD_10_9: rep=isin_G_H(BR,27,21); if (rep) goto IMPODD_10_7; else goto IMPODD_10_16; IMPODD_10_10: rep=isin_G_H(BR,41,22); if (!rep) return 41; rep=isin_G_H(BR,22,12); if (rep) goto IMPODD_10_14; else goto IMPODD_10_18; IMPODD_10_12: rep=isin_G_H(BR,10,4); return rep? 4: 10; IMPODD_10_13: rep=isin_G_H(BR,21,9); if (rep) goto IMPODD_10_19; else return 21; IMPODD_10_14: rep=isin_G_H(BR,12,4); return rep? 4: 12; IMPODD_10_15: rep=isin_G_H(BR,40,11); if (rep) goto IMPODD_10_20; else return 40; IMPODD_10_16: rep=isin_G_H(BR,27,20); if (!rep) goto IMPODD_10_21; rep=isin_G_H(BR,20,10); if (rep) goto IMPODD_10_12; return 20; IMPODD_10_18: rep=isin_G_H(BR,22,11); if (rep) goto IMPODD_10_20; else goto IMPODD_10_23; IMPODD_10_19: rep=isin_G_H(BR,9,6); if (rep) goto IMPODD_10_24; else goto IMPODD_10_25; IMPODD_10_20: rep=isin_G_H(BR,11,3); if (rep) goto IMPODD_10_26; else return 11; IMPODD_10_21: rep=isin_G_H(BR,27,19); if (rep) goto IMPODD_10_27; rep=isin_G_H(BR,27,17); if (rep) goto IMPODD_10_28; else return 27; IMPODD_10_23: rep=isin_G_H(BR,22,5); if (rep) goto IMPODD_10_29; else return 22; IMPODD_10_24: rep=isin_G_H(BR,6,2); if (rep) return 2; else goto IMPODD_10_30; IMPODD_10_25: rep=isin_G_H(BR,9,3); if (!rep) return 9; IMPODD_10_26: rep=isin_G_H(BR,3,2); if (rep) return 2; else goto IMPODD_10_31; IMPODD_10_27: rep=isin_G_H(BR,19,9); if (rep) goto IMPODD_10_19; else return 19; IMPODD_10_28: rep=isin_G_H(BR,17,10); if (rep) goto IMPODD_10_12; else goto IMPODD_10_32; IMPODD_10_29: rep=isin_G_H(BR,5,4); if (rep) return 4; else goto IMPODD_10_33; IMPODD_10_30: rep=isin_G_H(BR,6,1); return rep? 1: 6; IMPODD_10_31: rep=isin_G_H(BR,3,1); return rep? 1: 3; IMPODD_10_32: rep=isin_G_H(BR,17,9); if (rep) goto IMPODD_10_19; else goto IMPODD_10_60; IMPODD_10_33: rep=isin_G_H(BR,5,3); if (rep) goto IMPODD_10_26; else return 5; IMPODD_10_60: rep=isin_G_H(BR,17,5); if (rep) goto IMPODD_10_29; else return 17; } else { rep=isin_G_H(BR,39,38); if (!rep) goto IMPODD_10_36; rep=isin_G_H(BR,38,25); if (rep) goto IMPODD_10_37; else goto IMPODD_10_38; IMPODD_10_36: rep=isin_G_H(BR,39,36); if (rep) goto IMPODD_10_39; else goto IMPODD_10_40; IMPODD_10_37: rep=isin_G_H(BR,25,4); return rep? 4: 25; IMPODD_10_38: rep=isin_G_H(BR,38,12); if (rep) goto IMPODD_10_41; else return 38; IMPODD_10_39: rep=isin_G_H(BR,36,23); if (rep) goto IMPODD_10_42; else goto IMPODD_10_43; IMPODD_10_40: rep=isin_G_H(BR,39,29); if (rep) goto IMPODD_10_44; else goto IMPODD_10_45; IMPODD_10_41: rep=isin_G_H(BR,12,4); return rep? 4: 12; IMPODD_10_42: rep=isin_G_H(BR,23,16); if (rep) goto IMPODD_10_46; else goto IMPODD_10_47; IMPODD_10_43: rep=isin_G_H(BR,36,11); if (rep) goto IMPODD_10_48; else return 36; IMPODD_10_44: rep=isin_G_H(BR,29,25); if (rep) goto IMPODD_10_37; else goto IMPODD_10_49; IMPODD_10_45: rep=isin_G_H(BR,39,22); if (rep) goto IMPODD_10_50; else return 39; IMPODD_10_46: rep=isin_G_H(BR,16,2); return rep? 2: 16; IMPODD_10_47: rep=isin_G_H(BR,23,14); if (rep) goto IMPODD_10_51; else goto IMPODD_10_52; IMPODD_10_48: rep=isin_G_H(BR,11,3); if (rep) goto IMPODD_10_53; else return 11; IMPODD_10_49: rep=isin_G_H(BR,29,23); if (rep) goto IMPODD_10_42; else goto IMPODD_10_54; IMPODD_10_50: rep=isin_G_H(BR,22,12); if (rep) goto IMPODD_10_41; else goto IMPODD_10_55; IMPODD_10_51: rep=isin_G_H(BR,14,1); return rep? 1: 14; IMPODD_10_52: rep=isin_G_H(BR,23,3); if (!rep) return 23; IMPODD_10_53: rep=isin_G_H(BR,3,2); if (rep) return 2; else goto IMPODD_10_57; IMPODD_10_54: rep=isin_G_H(BR,29,5); if (rep) goto IMPODD_10_58; else return 29; IMPODD_10_55: rep=isin_G_H(BR,22,11); if (rep) goto IMPODD_10_48; rep=isin_G_H(BR,22,5); if (rep) goto IMPODD_10_58; else return 22; IMPODD_10_57: rep=isin_G_H(BR,3,1); return rep? 1: 3; IMPODD_10_58: rep=isin_G_H(BR,5,4); if (rep) return 4; rep=isin_G_H(BR,5,3); if (rep) goto IMPODD_10_53; else return 5; } } static long closure10(long EVEN, buildroot *BR) { long rep; if (EVEN) { rep=isin_G_H(BR,44,42); if (rep) return galoisimpeven10(BR,42); rep=isin_G_H(BR,44,37); if (rep) return galoisimpeven10(BR,37); } else { rep=isin_G_H(BR,45,43); if (rep) return galoisimpodd10(BR,43); rep=isin_G_H(BR,45,39); if (rep) return galoisimpodd10(BR,39); } return galoisprim10(EVEN, BR); } static PERM data10(long N, long n1,long n2,GROUP *t) { switch(n1) { case 6: if (n2!=2) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 5, 6, 10, 9, 8, 7); case 9: if (n2!=3 && n2!=6) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 10, 9, 8, 7); return (*t)[1]; case 10: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 10, 9, 8, 7); return (*t)[1]; case 14: case 16:*t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 17: if (n2!=5) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 10, 9, 8, 7); return (*t)[1]; case 19: case 20: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 10, 7, 9); return (*t)[1]; case 21: if (n2!=10) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 5, 6, 8, 10, 7, 9); case 23: if (n2!=3) break; *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 25: *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 26: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 4, 9, 6, 8, 10, 3, 7, 5); return _cr(N, 1, 2, 3, 10, 6, 5, 7, 4, 8, 9); case 27: if (n2!=17 && n2!=21) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 10, 7, 9); return (*t)[1]; case 28: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 8, 10, 7, 9); return (*t)[1]; case 29: if (n2!=5) break; *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 32: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 4, 9, 6, 8, 10, 3, 7, 5); return _cr(N, 1, 2, 3, 10, 6, 5, 7, 4, 8, 9); case 36: if (n2!=11) break; *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 38: if (n2!=12) break; *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 39: if (n2!=22) break; *t=initgroup(N,1); return _cr(N, 1, 3, 5, 7, 9, 2, 4, 6, 8, 10); case 40: if (n2!=12) break; *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 5, 6, 7, 8, 10, 9); case 41: if (n2!=22 && n2!=40) break; *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 7, 8, 10, 9); return (*t)[1]; } *t=initgroup(N,1); return (*t)[1]; } static long galoismodulo10(long EVEN, GEN pol, GEN dpol) { long res, gr[46]; pari_sp av = avma; long **GR = (long**) cgeti(45); GEN TYP = partitions_galois(10); GR[ 1]= _gr( 4, 1,6,30,42); GR[ 2]= _gr( 3, 1,6,30); GR[ 3]= _gr( 5, 1,5,6,30,42); GR[ 4]= _gr( 4, 1,5,23,30); GR[ 5]= _gr( 7, 1,5,6,22,23,30,42); GR[ 6]= _gr( 5, 1,6,24,30,42); GR[ 7]= _gr( -4, 1,5,14,30); GR[ 8]= _gr( -4, 1,3,5,30); GR[ 9]= _gr( 6, 1,5,6,24,30,42); GR[10]= _gr( 5, 1,5,23,24,30); GR[11]= _gr( 7, 1,5,6,11,30,33,42); GR[12]= _gr( 7, 1,5,6,11,23,30,33); GR[13]= _gr( 7, 1,4,5,14,23,30,34); GR[14]= _gr( 8, 1,2,3,4,5,6,30,42); GR[15]= _gr( -6, 1,3,5,18,22,30); GR[16]= _gr( 7, 1,3,5,6,17,23,30); GR[17]= _gr( 8, 1,5,6,22,23,24,30,42); GR[18]= _gr( -6, 1,5,22,24,30,40); GR[19]= _gr( 7, 1,5,6,22,24,30,42); GR[20]= _gr( 6, 1,5,22,23,24,30); GR[21]= _gr( 9, 1,3,5,6,23,24,26,30,42); GR[22]= _gr( 11, 1,3,5,6,11,13,22,23,30,33,42); GR[23]= _gr( 12, 1,2,3,4,5,6,17,18,22,23,30,42); GR[24]= _gr( -7, 1,3,5,18,22,30,40); GR[25]= _gr( 8, 1,3,5,18,22,23,30,39); GR[26]= _gr( -5, 1,5,14,22,30); GR[27]= _gr( 10, 1,3,5,6,22,23,24,26,30,42); GR[28]= _gr( -8, 1,3,5,22,24,26,30,40); GR[29]= _gr( 14, 1,2,3,4,5,6,17,18,22,23,30,39,40,42); GR[30]= _gr( 8, 1,5,6,14,22,30,39,42); GR[31]= _gr( -6, 1,5,14,22,30,40); GR[32]= _gr( 8, 1,4,5,14,22,23,30,34); GR[33]= _gr( 14, 1,3,5,6,15,17,22,23,24,26,29,30,40,42); GR[34]= _gr( -9, 1,3,5,11,13,18,22,30,32); GR[35]= _gr( 12, 1,4,5,6,14,22,23,30,34,39,40,42); GR[36]= _gr( 18, 1,2,3,4,5,6,11,12,13,17,18,22,23,30,31,32,33,42); GR[37]= _gr(-12, 1,3,5,11,13,16,18,22,30,32,35,40); GR[38]= _gr( 18, 1,3,4,5,6,11,13,15,17,18,21,22,23,30,32,33,35,39); GR[39]= _gr( 24, 1,2,3,4,5,6,11,12,13,15,16,17,18,21,22,23,30,31,32,33,35,39,40,42); GR[40]= _gr( 14, 1,3,5,6,7,9,11,23,24,26,27,30,33,42); GR[41]= _gr( 18, 1,3,5,6,7,9,11,13,16,20,22,23,24,26,27,30,33,42); GR[42]= _gr(-17, 1,3,5,7,9,11,13,16,18,20,22,24,26,27,30,35,40); GR[43]= _gr( 32, 1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,33,35,40,42); GR[44]= _gr(-22, 1,3,5,7,9,11,13,14,16,18,20,22,24,26,27,30,32,35,36,38,40,41); gr[0]=46; res = galmodp(EVEN,pol,dpol,TYP,gr,GR); avma=av; if (!res) return 0; return EVEN? 44: 45; } /* DEGREE 11 */ static long closure11(long EVEN, buildroot *BR) { long rep; if (EVEN) { rep=isin_G_H(BR,7,6); if (!rep) return 7; rep=isin_G_H(BR,6,5); if (!rep) return 6; rep=isin_G_H(BR,5,3); if (!rep) return 5; rep=isin_G_H(BR,3,1); return rep? 1: 3; } else { 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); setvarn(r, 0); r = nffactor(h, r); /* S11 (P10*P10*P90) or F_110[11] (11 factors of degree 10) */ return (lgcols(r)-1 == 11)? 4: 8; } } static PERM data11(long N, long n1, GROUP *t) { switch(n1) { case 5: *t=initgroup(N,1); return _cr(N, 1, 2, 3, 7, 8, 6, 11, 5, 9, 4, 10); case 6: *t=initgroup(N,1); return _cr(N, 1, 2, 3, 4, 6, 10, 11, 9, 7, 5, 8); case 7: *t=initgroup(N,2); _aff(N, (*t)[2], 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10); return (*t)[1]; } *t=initgroup(N,1); return (*t)[1]; } static long galoismodulo11(long EVEN, GEN pol, GEN dpol) { long res, gr[6] = {0, 1, 1, 1, 1, 1}; pari_sp av = avma; GEN TYP = cgetg(EVEN? 9: 6, t_VEC); gel(TYP,1) = _typ(1, 11); if (EVEN) { gel(TYP,2) = _typ(3, 8,2,1); gel(TYP,3) = _typ(3, 6,3,2); gel(TYP,4) = _typ(3, 5,5,1); gel(TYP,5) = _typ(5, 4,4,1,1,1); gel(TYP,6) = _typ(5, 3,3,3,1,1); gel(TYP,7) = _typ(7, 2,2,2,2,1,1,1); gel(TYP,8) = _typ(11, 1,1,1,1,1,1,1,1,1,1,1); } else { gel(TYP,2) = _typ(2, 10,1); gel(TYP,3) = _typ(3, 5,5,1); gel(TYP,4) = _typ(6, 2,2,2,2,2,1); gel(TYP,5) = _typ(11, 1,1,1,1,1,1,1,1,1,1,1); } res = galmodp(EVEN,pol,dpol,TYP,gr,NULL); avma=av; if (!res) return 0; return EVEN? 7: 8; } static void init_isin(long N, long n1, long n2, GROUP *tau, PERM *s0, resolv *R) { int fl = 1; if (DEBUGLEVEL) { err_printf("\n*** Entering isin_%ld_G_H_(%ld,%ld)\n",N,n1,n2); err_flush(); } switch(N) { case 8: if ((n1==47 && n2==46) || (n1==44 && n2==40)) fl=0; *s0=data8(N, n1,n2,tau); break; case 9: if ((n1==31 && n2==29) || (n1==34 && n2==31) || (n1==33 && n2==30)) fl=0; *s0=data9(N,n1,n2,tau); break; case 10: if ((n1==45 && (n2==43||n2==39)) || (n1==44 && (n2==42||n2==37)) || (n1==43 && (n2==41||n2==33)) || (n1==42 && n2==28) || (n1==41 && (n2==40||n2==27||n2==22)) || (n1==40 && (n2==21||n2==11)) || (n1==39 && (n2==38||n2==36||n2==29||n2==22)) || (n1==38 && (n2==25||n2==12)) || (n1==37 && (n2==34||n2==24)) || (n1==36 && (n2==23||n2==11)) || (n1==34 && n2==15) || (n1==33 && n2==27) || (n1==29 && (n2==25||n2==23||n2==5)) || (n1==28 && n2==18) || (n1==27 && (n2==20||n2==19||n2==17)) || (n1==25 && n2==4) || (n1==24 && n2==15) || (n1==23 && (n2==16||n2==3)) || (n1==22 && (n2==12||n2==11||n2==5)) || (n1==21 && (n2==10||n2==9)) || (n1==17 && n2==5) || (n1==16 && n2==2) || (n1==14 && n2==1) || (n1==12 && n2==4) || (n1==11 && n2==3) || (n1==10 && n2==4) || (n1== 9 && n2==3) || (n1== 6 && n2==1) || (n1== 5 && n2==3)) fl = 0; *s0=data10(N,n1,n2,tau); break; default: /* case 11: */ *s0=data11(N,n1,tau); break; } if (fl) lireresolv(n1,n2,N,R); else { R->a = NULL; R->nm = n1; R->nv = n2; } } static long isin_G_H(buildroot *BR, long n1, long n2) { pari_sp av = avma; const long N = BR->N; PERM s0, ww; GROUP tau, ss = lirecoset(n1,n2,N); resolv R; init_isin(N,n1,n2, &tau, &s0, &R); ww = check_isin(BR, &R, tau, ss); if (ww) { GEN z = cgetg(N+1, t_VEC); long i, j, l = lg(BR->r); s0 = permmul(ww, s0); if (DEBUGLEVEL) { err_printf("\n Output of isin_%ld_G_H(%ld,%ld): %ld",N,n1,n2,n2); err_printf("\n Reordering of the roots: "); printperm(s0); err_flush(); } for (i = 1; i < l; i++) { GEN p1 = gel(BR->r,i); for (j=1; j<=N; j++) gel(z,j) = gel(p1,s0[j]); for (j=1; j<=N; j++) gel(p1,j) = gel(z,j); } avma = av; return n2; } if (DEBUGLEVEL) { err_printf(" Output of isin_%ld_G_H(%ld,%ld): not included.\n",N,n1,n2); err_flush(); } avma = av; return 0; } GEN polgaloisnamesbig(long n, long k) { pari_sp av = avma; char *s = stack_malloc(strlen(pari_datadir) + 13 + 20 + 3); pariFILE *f; GEN V; (void)sprintf(s, "%s/galdata/NAM%ld", pari_datadir, n); f = pari_fopengz(s); if (!f) { pari_warn(warner,"Galois names files not available, please upgrade galdata\n[missing %s]",s); avma = av; return strtoGENstr(""); } V = gp_read_stream(f->file); if (!V || typ(V)!=t_VEC || k>=lg(V)) pari_err_FILE("galois file %s",s); pari_fclose(f); return gerepilecopy(av, gel(V,k)); } /* pol a monic ZX */ GEN galoisbig(GEN pol, long prec) { pari_sp av = avma; const long *tab; const long tab8[]={0, 8,8,8,8,8,16,16,16,16,16, 16,24,24,24,32,32,32,32,32,32, 32,32,48,48,56,64,64,64,64,64, 64,96,96,96,128,168,168,192,192,192, 192,288,336,384,576,576,1152,1344,20160,40320}; const long tab9[]={0, 9,9,18,18,18,27,27,36,36,54, 54,54,54,72,72,72,81,108,144,162, 162,162,216,324,324,432,504,648,648,648, 1296,1512,181440,362880}; const long tab10[]={0, 10,10,20,20,40,50,60,80,100,100, 120,120,120,160,160,160,200,200,200,200, 200,240,320,320,320,360,400,400,640,720, 720,720,800,960,1440, 1920,1920,1920,3840,7200,14400,14400,28800,1814400,3628800}; const long tab11[]={0, 11,22,55,110,660,7920,19958400,39916800}; GEN res, dpol = ZX_disc(pol); long t = 0, N = degpol(pol), EVEN = Z_issquare(dpol); if (DEBUGLEVEL) { err_printf("Galoisbig: polynomial #1 = %Ps\n", pol); err_printf("%s group\n", EVEN? "EVEN": "ODD"); err_flush(); } switch(N) { case 8: t = galoismodulo8(EVEN,pol,dpol); tab=tab8; break; case 9: t = galoismodulo9(EVEN,pol,dpol); tab=tab9; break; case 10:t = galoismodulo10(EVEN,pol,dpol); tab=tab10; break; case 11:t = galoismodulo11(EVEN,pol,dpol); tab=tab11; break; default: pari_err_IMPL("galois in degree > 11"); return NULL; /* not reached */ } if (!t) { buildroot BR; long i; GEN r, z = cgetg(N + 1, t_VEC); for (i = 1; i <= N; i++) { GEN v = cgetg(i+2,t_VECSMALL); gel(z,i) = v; v[1] = 0; } BR.coef = z; BR.p = pol; BR.pr = prec + nbits2extraprec((long)(cauchy_bound(pol) / LOG2)); BR.prmax = BR.pr + BIGDEFAULTPREC-2; BR.N = N; BR.r = vectrunc_init(N+1); r = gclone ( QX_complex_roots(BR.p, BR.prmax) ); vectrunc_append(BR.r, r); preci(r, BR.pr); switch(N) { case 8: t = closure8(EVEN, &BR); break; case 9: t = closure9(EVEN, &BR); break; case 10: t = closure10(EVEN, &BR); break; case 11: t = closure11(EVEN, &BR); break; } for (i = 1; i < lg(BR.r); i++) gunclone(gel(BR.r,i)); } avma = av; res = cgetg(5,t_VEC); gel(res,1) = stoi(tab[t]); gel(res,2) = stoi(EVEN? 1: -1); gel(res,3) = stoi(t); gel(res,4) = polgaloisnamesbig(N,t); return res; } pari-2.7.5/src/modules/subfield.c0000644000175000017500000006446412405547147015335 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* SUBFIELDS OF A NUMBER FIELD */ /* J. Klueners and M. Pohst, J. Symb. Comp. (1996), vol. 11 */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" typedef struct _poldata { GEN pol; GEN dis; /* |disc(pol)| */ GEN roo; /* roots(pol) */ GEN den; /* multiple of index(pol) */ } poldata; typedef struct _primedata { GEN p; /* prime */ GEN pol; /* pol mod p, squarefree */ GEN ff; /* factorization of pol mod p */ GEN Z; /* cycle structure of the above [ Frobenius orbits ] */ long lcm; /* lcm of the above */ GEN T; /* ffinit(p, lcm) */ GEN fk; /* factorization of pol over F_(p^lcm) */ GEN firstroot; /* *[i] = index of first root of fk[i] */ GEN interp; /* *[i] = interpolation polynomial for fk[i] * [= 1 on the first root firstroot[i], 0 on the others] */ GEN bezoutC; /* Bezout coefficients associated to the ff[i] */ GEN Trk; /* used to compute traces (cf poltrace) */ } primedata; typedef struct _blockdata { poldata *PD; /* data depending from pol */ primedata *S;/* data depending from pol, p */ GEN DATA; /* data depending from pol, p, degree, # translations [updated] */ long N; /* deg(PD.pol) */ long d; /* subfield degree */ long size;/* block degree = N/d */ } blockdata; static GEN print_block_system(blockdata *B, GEN Y, GEN BS); static GEN test_block(blockdata *B, GEN L, GEN D); /* COMBINATORIAL PART: generate potential block systems */ #define BIL 32 /* for 64bit machines also */ /* Computation of potential block systems of given size d associated to a * rational prime p: give a row vector of row vectors containing the * potential block systems of imprimitivity; a potential block system is a * vector of row vectors (enumeration of the roots). */ static GEN calc_block(blockdata *B, GEN Z, GEN Y, GEN SB) { long r = lg(Z), lK, i, j, t, tp, T, u, nn, lnon, lY; GEN K, n, non, pn, pnon, e, Yp, Zp, Zpp; pari_sp av0 = avma; if (DEBUGLEVEL>3) { err_printf("lg(Z) = %ld, lg(Y) = %ld\n", r,lg(Y)); if (DEBUGLEVEL > 5) { err_printf("Z = %Ps\n",Z); err_printf("Y = %Ps\n",Y); } } lnon = minss(BIL, r); e = new_chunk(BIL); n = new_chunk(r); non = new_chunk(lnon); pnon = new_chunk(lnon); pn = new_chunk(lnon); Zp = cgetg(lnon,t_VEC); Zpp = cgetg(lnon,t_VEC); nn = 0; for (i=1; isize; for (j = 1; j < r; j++) if (n[j] % k) break; if (j == r) { gel(Yp,lY) = Z; SB = print_block_system(B, Yp, SB); avma = av; } } gel(Yp,lY) = Zp; K = divisorsu(n[1]); lK = lg(K); for (i=1; isize*k, lpn = 0; for (j=2; j= BIL) pari_err_OVERFLOW("calc_block"); pn[lpn] = n[j]; pnon[lpn] = j; ngcd = ugcd(ngcd, n[j]); } if (dk % ngcd) continue; T = 1L< print_block_system */ if (!T) continue; } if (dk == n[1]) { /* empty subset, t = 0. Split out for clarity */ Zp[1] = Z[1]; setlg(Zp, 2); for (u=1,j=2; j>=1) { if (tp&1) { nn += pn[u]; e[u] = 1; } else e[u] = 0; } if (dk != nn) continue; for (j=1; jN; long *k, *n, **e, *t; GEN D, De, Z, cyperm, perm, VOID = cgetg(1, t_VECSMALL); if (DEBUGLEVEL>5) err_printf("Y = %Ps\n",Y); n = new_chunk(N+1); D = vectrunc_init(N+1); t = new_chunk(r+1); k = new_chunk(r+1); Z = cgetg(r+1, t_VEC); for (ns=0,i=1; isize; De = cgetg(ki+1,t_VEC); for (j=1; j<=ki; j++) gel(De,j) = VOID; for (j=1; j<=si; j++) { GEN cy = gel(Yi,j); for (l=1,lp=0; l<=n[j]; l++) { lp++; if (lp > ki) lp = 1; gel(De,lp) = vecsmall_append(gel(De,lp), cy[l]); } } append(D, De); if (si>1 && ki>1) { GEN p1 = cgetg(si,t_VEC); for (j=2; j<=si; j++) p1[j-1] = Yi[j]; ns++; t[ns] = si-1; k[ns] = ki-1; gel(Z,ns) = p1; } } if (DEBUGLEVEL>2) err_printf("\nns = %ld\n",ns); if (!ns) return test_block(B, SB, D); setlg(Z, ns+1); e = (long**)new_chunk(ns+1); for (i=1; i<=ns; i++) { e[i] = new_chunk(t[i]+1); for (j=1; j<=t[i]; j++) e[i][j] = 0; } cyperm= cgetg(N+1,t_VECSMALL); perm = cgetg(N+1,t_VECSMALL); i = ns; do { pari_sp av = avma; for (u=1; u<=N; u++) perm[u] = u; for (u=1; u<=ns; u++) for (v=1; v<=t[u]; v++) perm_mul_i(perm, cycle_power_to_perm(cyperm, gmael(Z,u,v), e[u][v])); SB = test_block(B, SB, im_block_by_perm(D,perm)); avma = av; /* i = 1..ns, j = 1..t[i], e[i][j] loop through 0..k[i]. * TODO: flatten to 1-dimensional loop */ if (++e[ns][t[ns]] > k[ns]) { j = t[ns]-1; while (j>=1 && e[ns][j] == k[ns]) j--; if (j >= 1) { e[ns][j]++; for (l=j+1; l<=t[ns]; l++) e[ns][l] = 0; } else { i = ns-1; while (i>=1) { j = t[i]; while (j>=1 && e[i][j] == k[i]) j--; if (j<1) i--; else { e[i][j]++; for (l=j+1; l<=t[i]; l++) e[i][l] = 0; for (ll=i+1; ll<=ns; ll++) for (l=1; l<=t[ll]; l++) e[ll][l] = 0; break; } } } } } while (i > 0); return SB; } /* ALGEBRAIC PART: test potential block systems */ static GEN polsimplify(GEN x) { long i,lx = lg(x); for (i=2; i M[i] for some i; 1 otherwise */ static long ok_coeffs(GEN g,GEN M) { long i, lg = lg(g)-1; /* g is monic, and cst term is ok */ for (i=3; i 0) return 0; return 1; } /* assume x in Fq, return Tr_{Fq/Fp}(x) as a t_INT */ static GEN trace(GEN x, GEN Trq, GEN p) { long i, l; GEN s; if (typ(x) == t_INT) return Fp_mul(x, gel(Trq,1), p); l = lg(x)-1; if (l == 1) return gen_0; x++; s = mulii(gel(x,1), gel(Trq,1)); for (i=2; ip, pol = FpX_red(gel(DATA,1), p); long i, l; interp = gel(DATA,9); bezoutC= gel(DATA,6); h = NULL; l = lg(interp); for (i=1; iT, p); t = poltrace(t, gel(S->Trk,i), p); t = FpX_mul(t, gel(bezoutC,i), p); h = h? FpX_add(h,t,p): t; } return FpX_rem(h, pol, p); } /* g in Z[X] potentially defines a subfield of Q[X]/f. It is a subfield iff A * (cf subfield) was a block system; then there * exists h in Q[X] such that f | g o h. listdelta determines h s.t f | g o h * in Fp[X] (cf chinese_retrieve_pol). Try to lift it; den is a * multiplicative bound for denominator of lift. */ static GEN embedding(GEN g, GEN DATA, primedata *S, GEN den, GEN listdelta) { GEN TR, w0_Q, w0, w1_Q, w1, wpow, h0, gp, T, q2, q, maxp, a, p = S->p; long rt; pari_sp av; T = gel(DATA,1); rt = brent_kung_optpow(degpol(T), 4, 3); maxp= gel(DATA,7); gp = RgX_deriv(g); av = avma; w0 = chinese_retrieve_pol(DATA, S, listdelta); w0_Q = centermod(gmul(w0,den), p); h0 = FpXQ_inv(FpX_FpXQ_eval(gp,w0, T,p), T,p); /* = 1/g'(w0) mod (T,p) */ wpow = NULL; q = sqri(p); for(;;) {/* Given g,w0,h0 in Z[x], s.t. h0.g'(w0) = 1 and g(w0) = 0 mod (T,p), find * [w1,h1] satisfying the same conditions mod p^2, [w1,h1] = [w0,h0] (mod p) * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */ if (DEBUGLEVEL>1) err_printf("lifting embedding mod p^k = %Ps^%ld\n",S->p, Z_pval(q,S->p)); /* w1 := w0 - h0 g(w0) mod (T,q) */ if (wpow) a = FpX_FpXQV_eval(g,wpow, T,q); else a = FpX_FpXQ_eval(g,w0, T,q); /* first time */ /* now, a = 0 (p) */ a = FpXQ_mul(ZX_neg(h0), ZX_Z_divexact(a, p), T,p); w1 = ZX_add(w0, ZX_Z_mul(a, p)); w1_Q = centermod(ZX_Z_mul(w1, remii(den,q)), q); if (ZX_equal(w1_Q, w0_Q)) { GEN G = is_pm1(den)? g: RgX_rescale(g,den); if (gequal0(RgX_RgXQ_eval(G, w1_Q, T))) break; } else if (cmpii(q,maxp) > 0) { GEN G = is_pm1(den)? g: RgX_rescale(g,den); if (gequal0(RgX_RgXQ_eval(G, w1_Q, T))) break; if (DEBUGLEVEL) err_printf("coeff too big for embedding\n"); return NULL; } gerepileall(av, 5, &w1,&h0,&w1_Q,&q,&p); q2 = sqri(q); wpow = FpXQ_powers(w1, rt, T, q2); /* h0 := h0 * (2 - h0 g'(w1)) mod (T,q) * = h0 + h0 * (1 - h0 g'(w1)) */ a = FpXQ_mul(ZX_neg(h0), FpX_FpXQV_eval(gp, FpXV_red(wpow,q),T,q), T,q); a = ZX_Z_add_shallow(a, gen_1); /* 1 - h0 g'(w1) = 0 (p) */ a = FpXQ_mul(h0, ZX_Z_divexact(a, p), T,p); h0 = ZX_add(h0, ZX_Z_mul(a, p)); w0 = w1; w0_Q = w1_Q; p = q; q = q2; } TR = gel(DATA,5); if (!gequal0(TR)) w1_Q = RgX_translate(w1_Q, TR); return gdiv(w1_Q,den); } /* return U list of polynomials s.t U[i] = 1 mod fk[i] and 0 mod fk[j] for all * other j */ static GEN get_bezout(GEN pol, GEN fk, GEN p) { long i, l = lg(fk); GEN A, B, d, u, v, U = cgetg(l, t_VEC); for (i=1; i 0) pari_err_COPRIME("get_bezout",A,B); d = constant_term(d); if (!gequal1(d)) v = FpX_Fp_mul(v, Fp_inv(d, p), p); gel(U,i) = FpX_mul(B,v, p); } return U; } 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 y,p1,p2,Trk,pow,pow1; k = degpol(gel(ff,r-1)); /* largest degree in modular factorization */ pow = cgetg(k+1, t_VEC); gel(pow,1) = gen_0; /* dummy */ gel(pow,2) = Frob; pow1= cgetg(k+1, t_VEC); /* 1st line */ for (i=3; i<=k; i++) gel(pow,i) = FpM_mul(gel(pow,i-1), Frob, p); gel(pow1,1) = gen_0; /* dummy */ for (i=2; i<=k; i++) { p1 = cgetg(N+1, t_VEC); gel(pow1,i) = p1; p2 = gel(pow,i); for (j=1; j<=N; j++) gel(p1,j) = gcoeff(p2,1,j); } /* Trk[i] = line 1 of x -> x + x^p + ... + x^{p^(i-1)} */ Trk = pow; /* re-use (destroy) pow */ gel(Trk,1) = vec_ei(N,1); for (i=2; i<=k; i++) gel(Trk,i) = gadd(gel(Trk,i-1), gel(pow1,i)); y = cgetg(r, t_VEC); for (i=1; iff), v = fetch_var(), N = degpol(S->pol); GEN T, p = S->p; if (S->lcm == degpol(gel(S->ff,lff-1))) { T = leafcopy(gel(S->ff,lff-1)); setvarn(T, v); } else T = init_Fq(p, S->lcm, v); name_var(v,"y"); S->T = T; S->firstroot = cgetg(lff, t_VECSMALL); S->interp = cgetg(lff, t_VEC); S->fk = cgetg(N+1, t_VEC); for (l=1,j=1; jff, j), deg1 = FpX_factorff_irred(F, T,p); GEN H = gel(deg1,1), a = Fq_neg(constant_term(H), T,p); GEN Q = FqX_div(F, H, T,p); GEN q = Fq_inv(FqX_eval(Q, a, T,p), T,p); gel(S->interp,j) = FqX_Fq_mul(Q, q, T,p); /* = 1 at a, 0 at other roots */ S->firstroot[j] = l; for (i=1; ifk, l) = gel(deg1, i); } S->Trk = init_traces(S->ff, T,p); S->bezoutC = get_bezout(S->pol, S->ff, p); } static void choose_prime(primedata *S, GEN pol, GEN dpol) { long i, j, k, r, lcm, oldlcm, N = degpol(pol); ulong p, pp; GEN Z, ff, oldff, n, oldn; pari_sp av; forprime_t T; u_forprime_init(&T, (N*N) >> 2, ULONG_MAX); oldlcm = 0; oldff = oldn = NULL; pp = 0; /* gcc -Wall */ av = avma; for(k = 1; k < 11 || !oldlcm; k++,avma = av) { if (k > 5 * N) pari_err_OVERFLOW("choose_prime [too many block systems]"); do p = u_forprime_next(&T); while (!umodiu(dpol, p)); ff = gel(Flx_factor(ZX_to_Flx(pol,p), p), 1); r = lg(ff)-1; if (r == N || r >= BIL) continue; n = cgetg(r+1, t_VECSMALL); lcm = n[1] = degpol(gel(ff,1)); for (j=2; j<=r; j++) { n[j] = degpol(gel(ff,j)); lcm = clcm(lcm, n[j]); } if (lcm <= oldlcm) continue; /* false when oldlcm = 0 */ if (DEBUGLEVEL) err_printf("p = %ld,\tlcm = %ld,\torbits: %Ps\n",p,lcm,n); pp = p; oldn = n; oldff = ff; oldlcm = lcm; if (r == 1) break; av = avma; } if (DEBUGLEVEL) err_printf("Chosen prime: p = %ld\n", pp); FlxV_to_ZXV_inplace(oldff); S->ff = oldff; S->lcm= oldlcm; S->p = utoipos(pp); S->pol = FpX_red(pol, S->p); init_primedata(S); n = oldn; r = lg(n); Z = cgetg(r,t_VEC); for (k=0,i=1; iZ = Z; } /* maxroot t_REAL */ static GEN bound_for_coeff(long m, GEN rr, GEN *maxroot) { long i,r1, lrr=lg(rr); GEN p1,b1,b2,B,M, C = matpascal(m-1); for (r1=1; r1 < lrr; r1++) if (typ(gel(rr,r1)) != t_REAL) break; r1--; rr = gabs(rr,0); *maxroot = vecmax(rr); for (i=1; i pol(X+1) ] and update DATA * 1: polynomial pol * 2: p^e (for Hensel lifts) such that p^e > max(M), * 3: Hensel lift to precision p^e of DATA[4] * 4: roots of pol in F_(p^S->lcm), * 5: number of polynomial changes (translations) * 6: Bezout coefficients associated to the S->ff[i] * 7: Hadamard bound for coefficients of h(x) such that g o h = 0 mod pol. * 8: bound M for polynomials defining subfields x PD->den * 9: *[i] = interpolation polynomial for S->ff[i] [= 1 on the first root S->firstroot[i], 0 on the others] */ static void compute_data(blockdata *B) { GEN ffL, roo, pe, p1, p2, fk, fhk, MM, maxroot, pol; primedata *S = B->S; GEN p = S->p, T = S->T, ff = S->ff, DATA = B->DATA; long i, j, l, e, N, lff = lg(ff); if (DEBUGLEVEL>1) err_printf("Entering compute_data()\n\n"); pol = B->PD->pol; N = degpol(pol); roo = B->PD->roo; if (DATA) { GEN Xm1 = gsub(pol_x(varn(pol)), gen_1); GEN TR = addis(gel(DATA,5), 1); GEN mTR = negi(TR), interp, bezoutC; if (DEBUGLEVEL>1) err_printf("... update (translate) an existing DATA\n\n"); gel(DATA,5) = TR; pol = RgX_translate(gel(DATA,1), gen_m1); p1 = cgetg_copy(roo, &l); for (i=1; i 0) /* do not turn pol_1(0) into gen_1 */ { p1 = RgX_translate(gel(interp,i), gen_m1); gel(interp,i) = FpXX_red(p1, p); } if (degpol(gel(bezoutC,i)) > 0) { p1 = RgX_translate(gel(bezoutC,i), gen_m1); gel(bezoutC,i) = FpXX_red(p1, p); } } ff = cgetg(lff, t_VEC); /* copy, do not overwrite! */ for (i=1; iff,i), mTR), p); } else { DATA = cgetg(10,t_VEC); fk = S->fk; gel(DATA,5) = gen_0; gel(DATA,6) = leafcopy(S->bezoutC); gel(DATA,9) = leafcopy(S->interp); } gel(DATA,1) = pol; MM = gmul2n(bound_for_coeff(B->d, roo, &maxroot), 1); gel(DATA,8) = MM; e = logint(shifti(vecmax(MM),20), p, &pe); /* overlift 2^20 [for d-1 test] */ gel(DATA,2) = pe; gel(DATA,4) = roots_from_deg1(fk); /* compute fhk = ZpX_liftfact(pol,fk,T,p,e,pe) in 2 steps * 1) lift in Zp to precision p^e */ ffL = ZpX_liftfact(pol, ff, NULL, p, e, pe); fhk = NULL; for (l=i=1; isize + N*(N-1)/2); p1 = divrr(mulrr(p1,p2), gsqrt(B->PD->dis,DEFAULTPREC)); gel(DATA,7) = mulii(shifti(ceil_safe(p1), 1), B->PD->den); if (DEBUGLEVEL>1) { err_printf("f = %Ps\n",DATA[1]); err_printf("p = %Ps, lift to p^%ld\n", p, e); err_printf("2 * Hadamard bound * ind = %Ps\n",DATA[7]); err_printf("2 * M = %Ps\n",DATA[8]); } if (B->DATA) { DATA = gclone(DATA); if (isclone(B->DATA)) gunclone(B->DATA); } B->DATA = DATA; } /* g = polynomial, h = embedding. Return [[g,h]] */ static GEN _subfield(GEN g, GEN h) { return mkvec(mkvec2(g,h)); } /* Return a subfield, gen_0 [ change p ] or NULL [ not a subfield ] */ static GEN subfield(GEN A, blockdata *B) { long N, i, j, d, lf, m = lg(A)-1; GEN M, pe, pol, fhk, g, e, d_1_term, delta, listdelta, whichdelta; GEN T = B->S->T, p = B->S->p, firstroot = B->S->firstroot; pol= gel(B->DATA,1); N = degpol(pol); d = N/m; /* m | N */ pe = gel(B->DATA,2); fhk= gel(B->DATA,3); M = gel(B->DATA,8); delta = cgetg(m+1,t_VEC); whichdelta = cgetg(N+1, t_VECSMALL); d_1_term = gen_0; for (i=1; i<=m; i++) { GEN Ai = gel(A,i), p1 = gel(fhk,Ai[1]); for (j=2; j<=d; j++) p1 = Fq_mul(p1, gel(fhk,Ai[j]), T, pe); gel(delta,i) = p1; if (DEBUGLEVEL>5) err_printf("delta[%ld] = %Ps\n",i,p1); /* g = prod (X - delta[i]) * if g o h = 0 (pol), we'll have h(Ai[j]) = delta[i] for all j */ /* fk[k] belongs to block number whichdelta[k] */ for (j=1; j<=d; j++) whichdelta[Ai[j]] = i; if (typ(p1) == t_POL) p1 = constant_term(p1); d_1_term = addii(d_1_term, p1); } d_1_term = centermod(d_1_term, pe); /* Tr(g) */ if (absi_cmp(d_1_term, gel(M,3)) > 0) { if (DEBUGLEVEL>1) err_printf("d-1 test failed\n"); return NULL; } g = FqV_roots_to_pol(delta, T, pe, 0); g = centermod(polsimplify(g), pe); /* assume g in Z[X] */ if (!ok_coeffs(g,M)) { if (DEBUGLEVEL>2) err_printf("pol. found = %Ps\n",g); if (DEBUGLEVEL>1) err_printf("coeff too big for pol g(x)\n"); return NULL; } if (!FpX_is_squarefree(g, p)) { if (DEBUGLEVEL>2) err_printf("pol. found = %Ps\n",g); if (DEBUGLEVEL>1) err_printf("changing f(x): p divides disc(g)\n"); compute_data(B); return subfield(A, B); } lf = lg(firstroot); listdelta = cgetg(lf, t_VEC); for (i=1; iDATA, B->S, B->PD->den, listdelta); if (!e) return NULL; if (DEBUGLEVEL) err_printf("... OK!\n"); return _subfield(g, e); } /* L list of current subfields, test whether potential block D is a block, * if so, append corresponding subfield */ static GEN test_block(blockdata *B, GEN L, GEN D) { pari_sp av = avma; GEN sub = subfield(D, B); if (sub) { GEN old = L; L = gclone( L? shallowconcat(L, sub): sub ); if (old) gunclone(old); } avma = av; return L; } /* subfields of degree d */ static GEN subfields_of_given_degree(blockdata *B) { pari_sp av = avma; GEN L; if (DEBUGLEVEL) err_printf("\n* Look for subfields of degree %ld\n\n", B->d); B->DATA = NULL; compute_data(B); L = calc_block(B, B->S->Z, cgetg(1,t_VEC), NULL); if (DEBUGLEVEL>9) err_printf("\nSubfields of degree %ld: %Ps\n", B->d, L? L: cgetg(1,t_VEC)); if (isclone(B->DATA)) gunclone(B->DATA); avma = av; return L; } static GEN fix_var(GEN x, long v) { long i, l = lg(x); if (!v) return x; for (i=1; ipol = T; setvarn(T, 0); if (nf) { PD->den = Q_denom(nf_get_zk(nf)); PD->roo = nf_get_roots(nf); PD->dis = mulii(absi(nf_get_disc(nf)), sqri(nf_get_index(nf))); } else { PD->den = initgaloisborne(T,NULL,nbits2prec(bit_accuracy(ZX_max_lg(T))), &L,NULL,&dis); PD->roo = L; PD->dis = absi(dis); } } static GEN subfieldsall(GEN nf) { pari_sp av = avma; long N, ld, i, v0; GEN G, pol, dg, LSB, NLSB; poldata PD; primedata S; blockdata B; /* much easier if nf is Galois (WSS) */ G = galoisinit(nf, NULL); if (G != gen_0) { GEN L, S, p; long l; pol = get_nfpol(nf, &nf); L = lift_intern( galoissubfields(G, 0, varn(pol)) ); l = lg(L); S = cgetg(l, t_VECSMALL); for (i=1; i 2) { B.PD = &PD; B.S = &S; B.N = N; choose_prime(&S, PD.pol, PD.dis); for (i=ld-1; i>1; i--) { B.size = dg[i]; B.d = N / B.size; NLSB = subfields_of_given_degree(&B); if (NLSB) { LSB = concat(LSB, NLSB); gunclone(NLSB); } } (void)delete_var(); /* from choose_prime */ } LSB = shallowconcat(LSB, _subfield(pol, pol_x(0))); if (DEBUGLEVEL) err_printf("\n***** Leaving subfields\n\n"); return fix_var(gerepilecopy(av, LSB), v0); } GEN nfsubfields(GEN nf, long d) { pari_sp av = avma; long N, v0; GEN LSB, pol, G; poldata PD; primedata S; blockdata B; if (!d) return subfieldsall(nf); pol = get_nfpol(nf, &nf); /* in order to treat trivial cases */ RgX_check_ZX(pol,"nfsubfields"); v0 = varn(pol); N = degpol(pol); if (d == N) return gerepilecopy(av, _subfield(pol, pol_x(v0))); if (d == 1) return gerepilecopy(av, _subfield(pol_x(v0), pol)); if (d < 1 || d > N || N % d) return cgetg(1,t_VEC); /* much easier if nf is Galois (WSS) */ G = galoisinit(nf? nf: pol, NULL); if (G != gen_0) { /* Bingo */ GEN L = galoissubgroups(G), F; long k,i, l = lg(L), o = N/d; F = cgetg(l, t_VEC); k = 1; for (i=1; i N) break; memcpy(c2 + 2, c + 2, (N-1)*sizeof(long)); /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */ for (qn = q; qn <= N; qn *= q) { ulong k0 = N/qn, k, k2; /* k2 = k*qn */ for (k = k0, k2 = k*qn; k > 0; k--, k2 -=qn) c2[k2] += c[k]; if (q > k0) break; /* <=> q*qn > N */ } swap(c, c2); } else /* p > sqrt(N): simpler */ for (i=1; i 1) break; /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */ for (k = N/p, k2 = k*p; k > 0; k--, k2 -= p) c[k2] += c[k]; } } avma = av; pari_free(c2); return c; } GEN dirzetak(GEN nf, GEN b) { GEN z, c; long n; if (typ(b) != t_INT) pari_err_TYPE("dirzetak",b); if (signe(b) <= 0) return cgetg(1,t_VEC); nf = checknf(nf); n = itou_or_0(b); if (!n) pari_err_OVERFLOW("dirzetak"); c = dirzetak0(nf, n); z = vecsmall_to_vec(c); pari_free(c); return z; } /* return a t_REAL */ GEN zeta_get_limx(long r1, long r2, long bit) { pari_sp av = avma; GEN p1, p2, c0, c1, A0; long r = r1 + r2, N = r + r2; /* c1 = N 2^(-2r2 / N) */ c1 = mulrs(powrfrac(real2n(1, DEFAULTPREC), -2*r2, N), N); p1 = powru(Pi2n(1, DEFAULTPREC), r - 1); p2 = mulir(powuu(N,r), p1); shiftr_inplace(p2, -r2); c0 = sqrtr( divrr(p2, powru(c1, r+1)) ); A0 = logr_abs( gmul2n(c0, bit) ); p2 = divrr(A0, c1); p1 = divrr(mulur(N*(r+1), logr_abs(p2)), addsr(2*(r+1), gmul2n(A0,2))); return gerepileuptoleaf(av, divrr(addrs(p1, 1), powruhalf(p2, N))); } /* N_0 = floor( C_K / limx ). Large */ long zeta_get_N0(GEN C, GEN limx) { long e; pari_sp av = avma; GEN z = gcvtoi(gdiv(C, limx), &e); /* avoid truncation error */ if (e >= 0 || is_bigint(z)) pari_err_OVERFLOW("zeta_get_N0 [need too many primes]"); if (DEBUGLEVEL>1) err_printf("\ninitzeta: N0 = %Ps\n", z); avma = av; return itos(z); } /* even i such that limx^i ( (i\2)! )^r1 ( i! )^r2 ~ B. Small. */ static long get_i0(long r1, long r2, GEN B, GEN limx) { long imin = 1, imax = 1400; while(imax - imin >= 4) { long i = (imax + imin) >> 1; GEN t = powru(limx, i); if (!r1) t = mulrr(t, powru(mpfactr(i , DEFAULTPREC), r2)); else if (!r2) t = mulrr(t, powru(mpfactr(i/2, DEFAULTPREC), r1)); else { GEN u1 = mpfactr(i/2, DEFAULTPREC); GEN u2 = mpfactr(i, DEFAULTPREC); if (r1 == r2) t = mulrr(t, powru(mulrr(u1,u2), r1)); else t = mulrr(t, mulrr(powru(u1,r1), powru(u2,r2))); } if (mpcmp(t, B) >= 0) imax = i; else imin = i; } return imax & ~1; /* make it even */ } /* assume limx = zeta_get_limx(r1, r2, bit), a t_REAL */ long zeta_get_i0(long r1, long r2, long bit, GEN limx) { pari_sp av = avma; GEN B = gmul(sqrtr( divrr(powrs(mppi(DEFAULTPREC), r2-3), limx) ), gmul2n(powuu(5, r1), bit + r2)); long i0 = get_i0(r1, r2, B, limx); if (DEBUGLEVEL>1) { err_printf("i0 = %ld\n",i0); err_flush(); } avma = av; return i0; } /* sum(j=1, r-k+1, A[j] * B[j]), assumes k <= r and A[j],B[j] are 'mp' */ INLINE GEN sumprod(GEN A, GEN B, long r, long k) { GEN s = signe(gel(A,1))? mpmul(gel(A,1), gel(B,1)): gen_0; long j; for (j=2; j<=r-k+1; j++) if (signe(gel(A,j))) s = mpadd(s, mpmul(gel(A,j), gel(B,j))); return s; } GEN initzeta(GEN T, long prec) { GEN znf, nf, bnf, gr2, gru, p1, p2, cst, coef; GEN limx, resi,zet,C,coeflog,racpi,aij,tabj,colzero, tabcstn, tabcstni; GEN c_even, ck_even, c_odd, ck_odd, serie_even, serie_odd, serie_exp; GEN VOID; long N0, i0, r1, r2, r, R, N, i, j, k, n, bit = prec2nbits(prec) + 6; pari_timer ti; pari_sp av, av2; long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; /*************** residue & constants ***************/ T = get_bnfpol(T, &bnf, &nf); if (!nf) { bnf = Buchall(T, 0, prec); nf = bnf_get_nf(bnf); } else if (!bnf) { if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec); bnf = Buchall(nf, 0, prec); } else if (nf_get_prec(bnf) < prec) { bnf = bnfnewprec(bnf, prec); nf = bnf_get_nf(bnf); } prec = precdbl(prec); racpi = sqrtr(mppi(prec)); /* all the above left on stack for efficiency */ /* class number & regulator */ N = nf_get_degree(nf); nf_get_sign(nf, &r1, &r2); gr2 = gmael(nf,2,2); r = r1 + r2; R = r+2; znf = cgetg(10,t_VEC); VOID = cgetg(1, t_STR); /* unused value */ av = avma; resi = gerepileupto(av, gdivgs(mpmul(shifti(bnf_get_no(bnf),r1), bnf_get_reg(bnf)), bnf_get_tuN(bnf))); /* hr 2^r1 / w*/ av = avma; p1 = sqrtr_abs(itor(nf_get_disc(nf), prec)); p2 = gmul2n(powru(racpi,N), r2); cst = gerepileuptoleaf(av, divrr(p1,p2)); /* N0, i0 */ limx = zeta_get_limx(r1, r2, bit); N0 = zeta_get_N0(cst, limx); i0 = zeta_get_i0(r1, r2, bit + 4, limx); /* Array of i/cst (i=1..N0) */ av = avma; tabcstn = cgetg(N0+1,t_VEC); tabcstni = cgetg(N0+1,t_VEC); p1 = invr(cst); for (i=1; i<=N0; i++) gel(tabcstni,i) = gel(tabcstn,i) = mulur(i,p1); tabcstn = gclone(tabcstn); tabcstni = gclone(tabcstni); /********** compute a(i,j) **********/ if (DEBUGLEVEL>1) timer_start(&ti); zet = cgetg(R,t_VEC); gel(zet,1) = mpeuler(prec); for (i=2; i1) timer_printf(&ti,"a(i,j)"); gel(znf,1) = mkvecsmall2(r1,r2); gel(znf,2) = resi; gel(znf,5) = cst; gel(znf,6) = logr_abs(cst); gel(znf,7) = aij; /************* Calcul du nombre d'ideaux de norme donnee *************/ coef = dirzetak0(nf,N0); tabj = cgetg(N0+1,t_MAT); if (DEBUGLEVEL>1) timer_printf(&ti,"coef"); colzero = zerocol(r+1); for (i=1; i<=N0; i++) if (coef[i]) { GEN t = cgetg(r+2,t_COL); p1 = logr_abs(gel(tabcstn,i)); togglesign(p1); gel(t,1) = utoi(coef[i]); gel(t,2) = mulur(coef[i], p1); for (j=2; j<=r; j++) { pari_sp av2 = avma; gel(t,j+1) = gerepileuptoleaf(av2, divru(mulrr(gel(t,j), p1), j)); } gel(tabj,i) = t; /* tabj[n,j] = coef(n)*ln(c/n)^(j-1)/(j-1)! */ } else gel(tabj,i) = colzero; if (DEBUGLEVEL>1) timer_printf(&ti,"a(n)"); coeflog=cgetg(N0+1,t_VEC); gel(coeflog,1) = VOID; for (i=2; i<=N0; i++) if (coef[i]) { court[2] = i; p1 = glog(court,prec); setsigne(p1, -1); gel(coeflog,i) = p1; } else gel(coeflog,i) = VOID; if (DEBUGLEVEL>1) timer_printf(&ti,"log(n)"); gel(znf,3) = tabj; gel(znf,8) = vecsmall_copy(coef); gel(znf,9) = coeflog; /******************** Calcul des coefficients Cik ********************/ C = cgetg(r+1,t_MAT); for (k=1; k<=r; k++) gel(C,k) = cgetg(i0+1,t_COL); av2 = avma; for (i=1; i<=i0; i++) { for (k=1; k<=r; k++) { GEN A = gel(aij,i) + k; /* A[j] = aij[i, j+k] */ GEN t = sumprod(A, gel(tabj,1), r, k); /* n = 1 */ if (i > 1 && signe(t)) t = mpmul(t, gel(tabcstni,1)); for (n=2; n<=N0; n++) if (coef[n]) { /* sum(j=1, r-k+1, aij[i,j+k] * tabj[n, j]) */ GEN s = sumprod(A, gel(tabj,n), r, k); if (!signe(s)) continue; if (i > 1) s = mpmul(s, gel(tabcstni,n)); t = mpadd(t,s); } togglesign(t); gcoeff(C,i,k) = gerepileuptoleaf(av2,t); av2 = avma; } if (i > 1 && i < i0) { for (n=1; n<=N0; n++) if (coef[n]) mpmulz(gel(tabcstni,n), gel(tabcstn,n), gel(tabcstni,n)); } } gel(znf,4) = C; if (DEBUGLEVEL>1) timer_printf(&ti,"Cik"); gunclone(tabcstn); gunclone(tabcstni); pari_free((void*)coef); return znf; } static void znf_get_sign(GEN znf, long *r1, long *r2) { GEN v = gel(znf,1); *r1 = v[1]; *r2 = v[2]; } /* s != 0,1 */ static GEN slambdak(GEN znf, long s, long flag, long prec) { GEN resi, C, cst, cstlog, coeflog, cs, coef; GEN lambd, gammas2, gammaunmoins2, var1, var2; GEN gar, val, valm, valk, valkm; long r1, r2, r, i0, i, k, N0; znf_get_sign(znf, &r1, &r2); r = r1+r2; resi = gel(znf,2); C = gel(znf,4); cst = gel(znf,5); cstlog = gel(znf,6); coef = gel(znf,8); coeflog= gel(znf,9); i0 = nbrows(C); N0 = lg(coef)-1; if (s < 0 && (r2 || !odd(s))) s = 1 - s; /* s >= 2 or s < 0 */ lambd = gdiv(resi, mulss(s, s-1)); gammas2 = ggamma(gmul2n(stoi(s),-1),prec); gar = gpowgs(gammas2,r1); cs = mpexp( mulrs(cstlog,s) ); val = stoi(s); valm = stoi(1 - s); if (s < 0) /* r2 = 0 && odd(s) */ { gammaunmoins2 = ggamma(gmul2n(valm,-1),prec); /* gamma((1-s) / 2) */ var1 = var2 = gen_1; for (i=2; i<=N0; i++) if (coef[i]) { GEN gexpro = mpexp(mulrs(gel(coeflog,i),s)); var1 = gadd(var1, mulsr(coef[i],gexpro)); var2 = gadd(var2, divsr(coef[i],mulsr(i,gexpro))); } lambd = gadd(lambd,gmul(gmul(var1,cs),gar)); lambd = gadd(lambd,gmul(gmul(var2,gdiv(cst,cs)), gpowgs(gammaunmoins2,r1))); var1 = gen_0; for (i=1; i<=i0; i+=2) { valk = val; valkm = valm; for (k=1; k<=r; k++) { GEN c = gcoeff(C,i,k); var1 = mpadd(var1,mpdiv(c,valk )); valk = mulii(val,valk); var1 = mpadd(var1,mpdiv(c,valkm)); valkm = mulii(valm,valkm); } val = addis(val, 2); valm = addis(valm,2); } } else { GEN tabj = gel(znf,3), aij = gel(znf,7), A = gel(aij,s); long n; gar = gmul(gar,gpowgs(mpfactr(s-1,prec),r2)); /* x gamma(s)^r2 */ /* n = 1 */ var1 = gen_1; var2 = (s <= i0)? sumprod(A, gel(tabj,1), r, 0): gen_0; for (n=2; n<=N0; n++) if (coef[n]) { GEN gexpro = mpexp( mulrs(gel(coeflog,n),s) ); var1 = mpadd(var1, mulsr(coef[n],gexpro)); if (s <= i0) { GEN t = sumprod(A, gel(tabj,n), r, 0); if (!signe(t)) continue; var2 = mpadd(var2, mpdiv(t, mulsr(n,gexpro))); } } lambd = gadd(lambd,gmul(gmul(var1,cs),gar)); lambd = gadd(lambd,gmul(var2,gdiv(cst,cs))); var1 = gen_0; for (n=1; n<=i0; n++) { valk = val; valkm = valm; if (n == s) for (k=1; k<=r; k++) { GEN c = gcoeff(C,n,k); var1 = mpadd(var1,mpdiv(c,valk)); valk = mulii(val,valk); } else for (k=1; k<=r; k++) { GEN c = gcoeff(C,n,k); var1 = mpadd(var1,mpdiv(c,valk )); valk = mulii(val,valk); var1 = mpadd(var1,mpdiv(c,valkm)); valkm = mulii(valm,valkm); } val = addis(val,1); valm = addis(valm,1); } } lambd = gadd(lambd, var1); if (!flag) lambd = gdiv(lambd,gmul(gar,cs)); /* zetak */ return lambd; } /* s not an integer */ static GEN cxlambdak(GEN znf, GEN s, long flag, long prec) { GEN resi, C, cst, cstlog, coeflog, cs, coef; GEN lambd, gammas, gammaunmoins, gammas2, gammaunmoins2, var1, var2; GEN smoinun, unmoins, gar, val, valm, valk, valkm, Pi, sPi; long r1, r2, r, i0, i, k, N0, bigprec; znf_get_sign(znf, &r1, &r2); resi = gel(znf,2); C = gel(znf,4); cst = gel(znf,5); cstlog = gel(znf,6); coef = gel(znf,8); coeflog= gel(znf,9); r1 = mael(znf,1,1); r2 = mael(znf,1,2); r = r1+r2; i0 = nbrows(C); N0 = lg(coef)-1; bigprec = precision(cst); Pi = mppi(bigprec); s = gtofp(s, bigprec); sPi = gmul(s, Pi); smoinun = gsubgs(s,1); unmoins = gneg(smoinun); lambd = gdiv(resi,gmul(s,smoinun)); gammas = ggamma(s,prec); gammas2= ggamma(gmul2n(s,-1),prec); gar = gmul(gpowgs(gammas,r2),gpowgs(gammas2,r1)); cs = gexp(gmul(cstlog,s),prec); gammaunmoins = gdiv(Pi, gmul(gsin(sPi,prec),gammas)); gammaunmoins2= gdiv(gmul(gmul(sqrtr(Pi),gpow(gen_2,smoinun,prec)), gammas2), gmul(gcos(gmul2n(sPi,-1),prec),gammas)); var1 = var2 = gen_1; for (i=2; i<=N0; i++) if (coef[i]) { GEN gexpro = gexp(gmul(gel(coeflog,i),s),bigprec); var1 = gadd(var1,gmulsg(coef[i], gexpro)); var2 = gadd(var2,gdivsg(coef[i], gmulsg(i,gexpro))); } lambd = gadd(lambd,gmul(gmul(var1,cs),gar)); lambd = gadd(lambd,gmul(gmul(gmul(var2,gdiv(cst,cs)), gpowgs(gammaunmoins,r2)), gpowgs(gammaunmoins2,r1))); val = s; valm = unmoins; var1 = gen_0; for (i=1; i<=i0; i++) { valk = val; valkm = valm; for (k=1; k<=r; k++) { GEN c = gcoeff(C,i,k); var1 = gadd(var1,gdiv(c,valk )); valk = gmul(val, valk); var1 = gadd(var1,gdiv(c,valkm)); valkm = gmul(valm,valkm); } if (r2) { val = gaddgs(val, 1); valm = gaddgs(valm,1); } else { val = gaddgs(val, 2); valm = gaddgs(valm,2); i++; } } lambd = gadd(lambd, var1); if (!flag) lambd = gdiv(lambd,gmul(gar,cs)); /* zetak */ return lambd; } GEN gzetakall(GEN znf, GEN s, long flag, long prec) { pari_sp av = avma; GEN z; if (typ(znf)!=t_VEC || lg(znf)!=10 || typ(gel(znf,1)) != t_VECSMALL) pari_err_TYPE("zetakall", znf); if (isint(s, &s)) { long ss = itos(s), r1, r2; if (ss==1) pari_err_DOMAIN("zetak", "argument", "=", gen_1, s); znf_get_sign(znf, &r1, &r2); if (ss==0) { avma = av; if (flag) pari_err_DOMAIN("zetak", "argument", "=", gen_0, s); if (r1 + r2 > 1) return gen_0; return r1? mkfrac(gen_m1, gen_2): gneg(gel(znf, 2)); } if (!flag && ss < 0 && (r2 || !odd(ss))) return gen_0; z = slambdak(znf, itos(s), flag, prec+EXTRAPRECWORD); } else z = cxlambdak(znf, s, flag, prec+EXTRAPRECWORD); if (gprecision(z) > prec) z = gprec_w(z, prec); return gerepileupto(av, z); } GEN gzetak(GEN nfz, GEN s, long prec) { return gzetakall(nfz,s,0,prec); } GEN glambdak(GEN nfz, GEN s, long prec) { return gzetakall(nfz,s,1,prec); } pari-2.7.5/src/modules/groupid.c0000644000175000017500000005014012366172547015177 0ustar billbill/* Copyright (C) 2003 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" static long groupelts_sumorders(GEN S) { long i, s = 0; for(i=1; i < lg(S); i++) s += perm_order(gel(S,i)); return s; } static long vecgroup_sumorders(GEN L) { long i, s = 0; for(i=1; i3*/ { long q= p[2], q2 = q*q, p3 = (q%3 == 1), p9 = (q%9 == 1); if (s==7+47*q+7*q2) return 1; /* 3p.3 */ if (s==61-61*q+61*q2) return 1+p3; /* 9p */ if (s==1+59*q+q2) return 3; /* p:9 */ if (s==7+11*q+7*q2) return 3+p9; /* p:3x3 */ return 2+2*p3+p9; /* 3^2xp */ } break; } case 3: switch(e[1]+e[2]+e[3]) { case 3: /*pqr*/ if (p[1]==2 && p[2]==3) /*6p*/ { long q = p[3],q2 = q*q, pmq = (q%3==1)? 2: 0; if (s==13-13*q+13*q2) return 1+pmq; /* S3xp */ if (s==7+7*q+7*q2) return 2+pmq; /* D2px3 */ if (s==7-q+7*q2) return 3+pmq; /* 3:2+p:2 */ if (s==21-21*q+21*q2) return 4+pmq; /* 6p */ if (s==1+19*q+q2) return 1; /* p:6 */ return 2; /* p:3x2 */ } break; } } { const long tab[]={ 24, 173, 301, 99, 125, 113, 101, 97, 85, 161, 133, 189, 67, 87, 73, 105, -1, 36, 255, 671, 265, 219, 427, 243, 147, 275, 115, 127, 121, 159, 111, 175, -1, 40, 391, 903, 263, 311, 291, 271, 227, 207, 483, 399, 567, 163, 187, 315, -1, 56, 697, 1849, 585, 557, 529, 413, 385, 989, 817, 1161, 351, 357, 645, -1, 60, 945, 721, 561, 1617, 211, 497, 337, 373, 651, 581, 693, 501, 1029, -1, 70, 1333, 1197, 973, 2709, -1, 75, 3647, 271, 847, -1, 84, 647, 935, 1935, 1295, 1071, 3311, 451, 699, 595, 1333, 469, 1099, 1419, 987, 2107, -1, 88, 1573, 4773, 1397, 1353, 1309, 953, 909, 2553, 2109, 2997, 865, 1665, -1, 90, 1659, 1891, 1371, 3843, 775, 1407, 735, 903, 615, 1575, -1, 104, 2143, 6751, 991, 1935, 1883, 1831, 1307, 1255, 3611, 2983, 4239, 731, 1203, 2355, -1, 105, 1785, 6321, -1, 110, 793, 993, 3441, 2793, 2441, 6993,-1, 126, 1533, 2037, 3397, 3477, 2749, 7869, 777, 937, 721, 1281, 1425, 2881, 1369, 1849, 1201, 3225, -1, -1}; long i; const long *t; for(t=tab;*t!=-1;t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==s) return i; return -1; } while (*t>=0) t++; } } { const long tab[]={ 16, 1710031, 550075, 70099, 70075, 870059, 110059, 30079, 30071, 30063, 470131, 70155, 70107, 110115, 310307, -1, 32, 6830063, 150323, 1830171, /*230171*/0, 230227, 30283, 30251, 30203, /*70267*/0, 70219, 110227, /*230171*/0, /*70187*/0, /*70187*/0, 110155, 3430123, 430123, 30191, 30175, 30159, 1110387, 150563, 150387, 230323, 230411, 230299, 70619, 70467, 70355, /*70379*/0, /*70379*/0, /*70267*/0, 70291, 70555, 70331, 1750291, 230291, 430275, 70411, 70363, 70315, 110331, 30371, 30323, 950819, 150995, 150643, 230691, 30747, 30635, 632451, -1, 48, 430156, 11970124, 10219, 430324, 110324, 30396, 30444, 30348, 230300, 110300, 230396, /*70396*/0, /*70396*/0, 70540, 30412, 30364, 30380, 30332, 70492, 3850300, 490396, 490300, 6090236, 770236, 210316, 210284, 210252, 30299, 30371, 30363, 110299, 70311, 110271, 70588, 230732, 70876, 110636, 30868, 30628, 30596, 30644, 150684, 70828, 3290524, 490620, 490428, 770460, 30627, 70571, 10643, 151740, 2171228, -1, 54, 10256, 16410120, 70292, 610232, 10373, 10292, 10616, 70517, 5610228, 210309, 210228, 250448, 70616, 11696, 2370552, -1, /*64*/ 72, 110307, 26230195, 210272, 30523, 110631, 30739, 70575, 30683, 14030351, 1830403, 1830299, 770346, 110586, 10750330, 10620, 210420, 71223, 9150663, 30426, 30858, 30978, 30954, 31074, 30762, 210452, 210538, 770634, 210730, 490626, 210722, 31018, 111234, 31450, 71106, 31322, 5750594, 750682, 750506, 10346, 10826, 10490, 70620, 11124, 10716, 30786, 31746, 210636, 491202, 72402, 3751122, -1, 80, 430250, 35910186, 110282, 430530, 110530, 30650, 30730, 30570, 230482, 110482, 230642, /*70642*/0, /*70642*/0, 70882, 30666, 30586, 30618, 30538, 70786, 11550450, 1470594, 1470450, 18270354, 2310354, 630474, 630426, 630378, 110562, 30562, 110722, 30722, 70546, 30546, 30946, 70962, 231202, 71442, 111042, 31426, 31026, 30978, 31058, 151106, 71346, 9870786, 1470930, 1470642, 2310690, 10467, 71266, 152866, 6511842, -1, 81,49210121, 6730319, 250427, 250319, 16450238, 610238, 70454, 70346, 70400, 70319, 5650670, 250994, 250670, 610589, 2412452, -1, /*96*/ 100, 30393, 57310217, 10481, 30693, 36470341, 630408, 30968, 13310392, 210416, 10576, 11256, 10856, 11096, 630648, 31768, 8470616, -1, 108, 30552, 60170280, 610359, 30984, 38290440, 210660, 1830540, 30849, 30660, 31308, 211137, 20570532, 770721, 770532, 70769, 11636, 11813, 610647, 70647, 250674, 70674, 70890, 211092, 1830852, 31389, 31092, 32388, 211965, 13090836, 491133, 490836, 751080, 211416, 33576, 8691288, 70904, 11048, 71720, 13688, 12344, 251538, 751608, 212280, 36600, 5532024,-1, 112, 430344, 73530248, 430736, 110736, 30904, 31016, 30792, 230664, 110664, 230888, 0/*70888*/, 0/*70888*/, 71224, 30920, 30808, 30856, 30744, 71080, 23650600, 3010792, 3010600, 37410472, 4730472, 1290632, 1290568, 1290504, 71336, 231672, 72008, 111448, 31984, 31424, 31360, 31472, 151528, 71864, 20211048, 3011240, 3010856, 4730920, 30643, 153992, 13332456,-1, 120,2310456, 770488, 110648, 63210360, 30763, 210552, 30712, 31256, 31240, 31336, 31400, 31496, 31480, 31096, 630498, 210808, 770968, 211128, 490904, 211064, 630744, 2310888, 631032, 1470840, 630984, 31128, 111368, 31608, 71224, 31464, 33810648, 4410744, 4410552, 11211, 31263, 11416, 210858, 11290, 11090, 211032, 31352, 32600, 630738, 491864, 1471704, 72664, 22051224, -1, -1}; long i; const long *t; GEN Z = groupelts_center(S), L = group_subgroups(G); long scenter = groupelts_sumorders(Z), svecgroup = vecgroup_sumorders(L); long u = svecgroup+10000*scenter; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==u) return i; switch(n) { case 32: switch(u) { case 230171: { const long good[]={2,0}, bad[]={4,5,0}; return indexgroupcentre(G,Z,good,bad)? 4: 12; } case 70267: if (s==135) return 9; return 32; case 70187: { const long good[]={8,0}, bad[]={7,9,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 70379: { const long good[]={4,0},bad[]={0}; return indexgroupsubgroup(L,8,good,bad)? 31: 30; } } break; case 48: case 80: { const long good[]={5,8,0},bad[]={6,7,0}; return indexgroupcentre(G,Z,good,bad)? 12: 13; } case 112: { const long good[]={7,4,0},bad[]={5,6,0}; return indexgroupcentre(G,Z,good,bad)? 11: 12; } } return -1; } while (*t!=-1) t++; } { const long tab[]={ 64, 1270001, /*4270003*/0, /*4270003*/0, 8190072, 6430073, 6670445, 5550446, 8190278, 7070279, 6350071, 5230072, 8110154, /*5870155*/0, /*5870155*/0, /*4270042*/0, /*4270042*/0, 7710246, 7390277, 6750037, 8032377, 8670266, 6750397, 11390022, 7710267, 7070277, /*3630046*/0, /*3630046*/0, 3630057, 4830196, 4830207, 4671808, 9070697, 6670700, 8750094, 6990091, 6350111, 5870115, 6671599, 5711601, 5551702, 5871512, 6351709, 5391711, /*3630046*/0, 3630047, 4111467, /*4430156*/0, /*4430156*/0, 3790166, /*2510026*/0, /*2510026*/0, 4470028, 4150300, 3830030, 13470021, 20350065, 10910041, 16514365, /*12190433*/0, 34110271, /*16514475*/0, 15230465, /*10910433*/0, 9630041, 13470233, /*16514475*/0, 20834696, /*10910433*/0, 13954343, /*12190433*/0, 19553542, 13474377, 25790466, 15870467, 18914476, 14110477, /*14590443*/0, 13310443, 11550043, /*14590443*/0, 10270043, 8990002, 8990546, 8990646, 8993647, 8356896, 13310905, 13310915, 12039018, 16990866, 12670888, 15071116, 11551217, 12038218, 16031739, 12512740, 12353138, 12993048, 15391849, 11872850, 12993551, 12353851, 8991446, 8991447, 8354830, 9951566, 9951666, 8674709, 9317039, 8031897, 8030187, 7713641, 7714641, 7074743, 9236585, 9236415, 9236586, 10990821, 9879066, 8751833, 9873399, 8751766, 10990754, 8593054, 8593087, 6830446, 6833546, 17472434, 13953445, 14432313, 16352544, 12833555, 13313423, 15635143, 13234877, 13874853, 12755287, 17870919, 14190949, 13075209, 11955310, 10835253, 9715354, 11312124, 10193135, 11074927, 12197529, 9957664, 11074970, 12196539, 9956674, 9958907, 10439497, 9479551, 9554015, 8433958, 9553915, 8434058, 8918081, 7798421, 10110856, 10110756, 9476648, 8991757, 8991857, 8356682, 10994275, 8750435, 8590474, 9230510, 10355254, 8115355, 13556790, 15790679, 11310691, 12275539, 14035061, 11795172, 8750465, 7474472, 8750475, 8114920, 6110196, 6111806, 5951808, 10191819, 9238364, 8271841, 8590736, 9390959, 8432079, 25470255, 41792701, 25470275, 20355344, 27233751, 18593673, 19717567, 23394762, 17312707, 19717633, 46115277, 31557088, 22917189, 24677288, 24039835, 24676366, 16032362, 17793529, 17153269, 38432486, 21153763, 23393635, 16037076, 27710971, 27074338, 20995174, 23396204, 20193482, 17157790, 19550231, 14751475, 17153832, 19070249, 16038080, 33391110, 25875097, 22197835, 22195018, 21070221, 24590112, 18999456, 15952565, 18356361, 17237769, 18359003, 15951169, 14832955, 16110295, 18350268, 21392354, 22030301, 18353365, 15955257, 13550032, 18430405, 18434015, 17150260, 17154128, 27234036, 23710639, 20194057, 21157900, 24198470, 20679613, 21158141, 22435065, 21318520, 20197076, 67390501, 83715011, 51070497, 54590283, 58915129, 50275230, 52035340, 263870051, -1, -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,32); long idxlist=vecsmall_pack(V,10,9967); long w=10000*svecgroup+idxlist; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 64: switch(w) { case 4270003: return (scenter==439)? 2: 3; case 5870155: { const long good[]={8,9,0},bad[]={7,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 4270042: { const long good[]={13,0},bad[]={14,0}; return indexgroupcentre(G,Z,good,bad)? 15: 16; } case 4430156: { const long good[]={18,20,0},bad[]={19,0}; return indexgroupcentre(G,Z,good,bad)? 47: 48; } case 2510026: return scenter==1367? 50: 51; case 12190433: return scenter==47? 59: 70; case 16514475: { const long good[]={22,24,28,0},bad[]={23,25,27,30,0}; return indexgroupcentre(G,Z,good,bad)? 61: 66; } case 10910433: { const long good[]={23,31,0},bad[]={25,26,29,30,33,0}; return indexgroupcentre(G,Z,good,bad)? 63: 68; } case 14590443: { const long good[]={28,33,0},bad[]={30,34,0}; return indexgroupcentre(G,Z,good,bad)? 77: 80; } case 3630046: { const long good[]={3,0},bad[]={12,16,0}; if (scenter==695) return 26; return indexgroupcentre(G,Z,good,bad)? 27: 44; } } break; } return -1; } while (*t!=-1) t++; } } { const long tab[]={ 96, 316010002, 252010002, 707020000, 676160124, 676170124, 87180027, 988190278, 892200028, 876030110, 876040110, 876120110, 215111237, 503062153, 972141052, 972131052, 455091156, 167101154, 620160033, 620170033, 908031033, 908121033, 908041033, 199101564, 7130153, 7140153, 812150123, 247051165, 487091566, 812151024, 391071276, 103081274, 247111377, 988180195, 892190205, 924190197, 828200207, 103050134, 679020464, 295091075, 199070145, 391060235, 103101076, 7080146, 135111157, 295020044, 684030223, 684040223, 908050274, 135060255, 7070285, 812080286, 71092475, 876102476, 908112287, 684120223, 748130243, 748140243, 620150254, 492160043, 492170043, 764180045, 700190477, 636200047, 963110003, 779050031, 935100032, 799110033, 819210003, 791260032, 246270050, 723330003, 987340003, 651360031, 623380033, 647263930, 839351534, 455321350, 178211335, 791244031, 322256848, 189340236, 130316409, 599331360, 743244548, 935295937, 551333907, 189222029, 274255883, 525275609, 82306043, 610289391, 82315641, 82307025, 647262487, 839353950, 0/*455322385*/, 0/*455322385*/, 178233588, 791245051, 322256982, 130307015, 658286619, 983297004, 983297037, 599333858, 631365165, 631376165, 535386399, 66408676, 354390966, 871428265, 775411064, 631376407, 535386309, 114430028, 823441008, 314398920, 74437993, 831420054, 42405827, 90439425, 799440830, 847426805, 767410275, 815440314, 863429143, 487360134, 487371044, 66211564, 66231664, 871295713, 66231764, 679242567, 125228724, 210253894, 18306803, 546288536, 162390938, 919437378, 871401018, 162255761, 967304398, 967313318, 413274329, 498283470, 498288163, 29345108, 967401139, 727449579, 679411219, 775352619, 583261276, 919295225, 66312839, 423381047, 2437470, 759424560, 711448550, 770222372, 109272382, 551210244, 258222592, 551230264, 295242430, 647254411, 199262266, 482272602, 871283751, 423293752, 519303751, 519312662, 71320222, 167332232, 226340245, 327352266, 167360274, 167372584, 103382587, 647392595, 455406162, 263412616, 327428742, 487438955, 295440098, 358290331, 622253358, 886280358, 322410312, 754400322, 394443122, 282440313, 354423123, 522430323, 726220349, 990273529, 470450359, 742460359, 522470032, 198470031, 282480353, 290490033, 274500353, 414470000, 614490000, 605473864, 664459790, 723464091, 893482714, 675465704, 845486215, 184493728, 653478045, 941489155, 605501588, 925482982, 264492577, 589502601, 312450472, 371466994, 285450492, 989464902, 578470486, 770489139, 994490497, 546500507, 604460529, 65270050, 684510049, 468510050, 134510562, 831510052, -1 -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,48); long idx48=vecsmall_pack(V,10,9967); long idx32=vecgroup_idxlist(L,32)[1]; long w=1000000*(svecgroup%997)+10000*idx32+idx48; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 96: switch(w) { case 455322385: { const long good[]={37,40,0},bad[]={34,41,0}; return indexgroupcentre(G,Z,good,bad)? 96: 97; } } break; } return -1; } while (*t!=-1) t++; } } } return 0; } long group_ident(GEN G, GEN S) { pari_sp av = avma; long idx = group_ident_i(G, S); if (idx < 0) pari_err_TYPE("group_ident [not a group]", G); if (!idx) pari_err_IMPL("galoisidentify for groups of order > 127"); avma = av; return idx; } long group_ident_trans(GEN G, GEN S) { const long tab[]={ 4, 1, 2, -1, 6, 2, 1, -1, 8, 1, 2, 4, 5, 3, -1, 9, 1, 2, -1, 10, 2, 1, -1, 12, 5, 1, 4, 3, 2, -1, 14, 2, 1, -1, 15, 1, -1, 16, 1, 4, 10, 8, 5, 6, 13, 12, 14, 2, 9, 7, 11, 3, -1, 18, 5, 1, 3, 4, 2, -1, 20, 2, 1, 5, 4, 3, -1, 21, 2, 1, -1, 22, 2, 1, -1, 24, 8, 1, 7, 5, 12, 13, 6, 14, 2, 15, 4, 10, 9, 11, 3, -1, 25, 1, 2, -1, 26, 2, 1, -1, 27, 1, 2, 3, 5, 4, -1, 28, 3, 1, 4, 2, -1, 30, 2, 4, 3, 1, -1, -1}; long n = group_order(G), s; const long *t; if (n == 1) return 1; /* N.B. known up to 32 (Cannon-Holt) */ if (n > 30) pari_err_IMPL("group_ident_trans [n > 30]"); if (uisprime(n)) return 1; s = group_ident(G,S); for(t=tab;*t>=0;t++) { if (t[0]==n) return t[s]; while (*t>=0) t++; } return 0; /*NOT REACHED*/ } pari-2.7.5/src/modules/genus2red.c0000644000175000017500000021230512413013143015402 0ustar billbill/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** IGUSA INVARIANTS **/ /** (GP2C-generated) **/ /** **/ /********************************************************************/ /* j2(a0,a1,a2,a3,a4,a5,a6) = (-120*a0*a6+20*a1*a5-8*a2*a4+3*a3^2) / 4; */ static GEN igusaj2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gadd(gsub(gadd(gmul(gmulsg(-120, a0), a6), gmul(gmulsg(20, a1), a5)), gmul(gmulsg(8, a2), a4)), gmulsg(3, gsqr(a3))), -2)); } /* j4(a0,a1,a2,a3,a4,a5,a6) = (240*(a0*a3*a4*a5+a1*a2*a3*a6)-400*(a0*a2*a5^2+a1^2*a4*a6)-64*(a0*a4^3+a2^3*a6)+16*(a1*a3*a4^2+a2^2*a3*a5)-672*a0*a3^2*a6+240*a1^2*a5^2-112*a1*a2*a4*a5-8*a1*a3^2*a5+16*a2^2*a4^2-16*a2*a3^2*a4+3*a3^4+2640*a0^2*a6^2-880*a0*a1*a5*a6+1312*a0*a2*a4*a6) / 2^7 */ static GEN igusaj4(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gadd(gsub(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gsub(gadd(gsub(gsub(gmulsg(240, gadd(gmul(gmul(gmul(a0, a3), a4), a5), gmul(gmul(gmul(a1, a2), a3), a6))), gmulsg(400, gadd(gmul(gmul(a0, a2), gsqr(a5)), gmul(gmul(gsqr(a1), a4), a6)))), gmulsg(64, gadd(gmul(a0, gpowgs(a4, 3)), gmul(gpowgs(a2, 3), a6)))), gmulsg(16, gadd(gmul(gmul(a1, a3), gsqr(a4)), gmul(gmul(gsqr(a2), a3), a5)))), gmul(gmul(gmulsg(672, a0), gsqr(a3)), a6)), gmul(gmulsg(240, gsqr(a1)), gsqr(a5))), gmul(gmul(gmul(gmulsg(112, a1), a2), a4), a5)), gmul(gmul(gmulsg(8, a1), gsqr(a3)), a5)), gmul(gmulsg(16, gsqr(a2)), gsqr(a4))), gmul(gmul(gmulsg(16, a2), gsqr(a3)), a4)), gmulsg(3, gpowgs(a3, 4))), gmul(gmulsg(2640, gsqr(a0)), gsqr(a6))), gmul(gmul(gmul(gmulsg(880, a0), a1), a5), a6)), gmul(gmul(gmul(gmulsg(1312, a0), a2), a4), a6)), -7)); } /* j6(a0,a1,a2,a3,a4,a5,a6) = (1600*(a0^2*a4^2*a5^2+a1^2*a2^2*a6^2)+1600*(a0*a1*a2*a5^3+a1^3*a4*a5*a6)+640*(a0*a1*a3*a4*a5^2+a1^2*a2*a3*a5*a6)-4000*(a0^2*a3*a5^3+a1^3*a3*a6^2)-384*(a0*a1*a4^3*a5+a1*a2^3*a5*a6)-640*(a0*a2^2*a4*a5^2+a1^2*a2*a4^2*a6)+80*(a0*a2*a3^2*a5^2+a1^2*a3^2*a4*a6)+192*(a0*a2*a3*a4^2*a5+a1*a2^2*a3*a4*a6)-48*(a0*a3^3*a4*a5+a1*a2*a3^3*a6)-224*(a1^2*a3*a4^2*a5+a1*a2^2*a3*a5^2)+64*(a1^2*a4^4+a2^4*a5^2)-64*(a1*a2*a3*a4^3+a2^3*a3*a4*a5)+16*(a1*a3^3*a4^2+a2^2*a3^3*a5)-4096*(a0^2*a4^3*a6+a0*a2^3*a6^2)+6400*(a0^2*a2*a5^2*a6+a0*a1^2*a4*a6^2)+10560*(a0^2*a3*a4*a5*a6+a0*a1*a2*a3*a6^2)+2624*(a0*a1*a3*a4^2*a6+a0*a2^2*a3*a5*a6)-4432*a0*a1*a3^2*a5*a6-8*a2*a3^4*a4+a3^6-320*a1^3*a5^3+64*a1^2*a2*a4*a5^2+176*a1^2*a3^2*a5^2+128*a1*a2^2*a4^2*a5+112*a1*a2*a3^2*a4*a5-28*a1*a3^4*a5+16*a2^2*a3^2*a4^2+5120*a0^3*a6^3-2544*a0^2*a3^2*a6^2+312*a0*a3^4*a6-14336*a0^2*a2*a4*a6^2+1024*a0*a2^2*a4^2*a6-2560*a0^2*a1*a5*a6^2-2240*a0*a1^2*a5^2*a6-6528*a0*a1*a2*a4*a5*a6-1568*a0*a2*a3^2*a4*a6) / 2^10 */ static GEN igusaj6(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gsub(gsub(gsub(gsub(gadd(gsub(gadd(gsub(gadd(gadd(gsub(gadd(gadd(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gadd(gsub(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gsub(gsub(gsub(gadd(gadd(gmulsg(1600, gadd(gmul(gmul(gsqr(a0), gsqr(a4)), gsqr(a5)), gmul(gmul(gsqr(a1), gsqr(a2)), gsqr(a6)))), gmulsg(1600, gadd(gmul(gmul(gmul(a0, a1), a2), gpowgs(a5, 3)), gmul(gmul(gmul(gpowgs(a1, 3), a4), a5), a6)))), gmulsg(640, gadd(gmul(gmul(gmul(gmul(a0, a1), a3), a4), gsqr(a5)), gmul(gmul(gmul(gmul(gsqr(a1), a2), a3), a5), a6)))), gmulsg(4000, gadd(gmul(gmul(gsqr(a0), a3), gpowgs(a5, 3)), gmul(gmul(gpowgs(a1, 3), a3), gsqr(a6))))), gmulsg(384, gadd(gmul(gmul(gmul(a0, a1), gpowgs(a4, 3)), a5), gmul(gmul(gmul(a1, gpowgs(a2, 3)), a5), a6)))), gmulsg(640, gadd(gmul(gmul(gmul(a0, gsqr(a2)), a4), gsqr(a5)), gmul(gmul(gmul(gsqr(a1), a2), gsqr(a4)), a6)))), gmulsg(80, gadd(gmul(gmul(gmul(a0, a2), gsqr(a3)), gsqr(a5)), gmul(gmul(gmul(gsqr(a1), gsqr(a3)), a4), a6)))), gmulsg(192, gadd(gmul(gmul(gmul(gmul(a0, a2), a3), gsqr(a4)), a5), gmul(gmul(gmul(gmul(a1, gsqr(a2)), a3), a4), a6)))), gmulsg(48, gadd(gmul(gmul(gmul(a0, gpowgs(a3, 3)), a4), a5), gmul(gmul(gmul(a1, a2), gpowgs(a3, 3)), a6)))), gmulsg(224, gadd(gmul(gmul(gmul(gsqr(a1), a3), gsqr(a4)), a5), gmul(gmul(gmul(a1, gsqr(a2)), a3), gsqr(a5))))), gmulsg(64, gadd(gmul(gsqr(a1), gpowgs(a4, 4)), gmul(gpowgs(a2, 4), gsqr(a5))))), gmulsg(64, gadd(gmul(gmul(gmul(a1, a2), a3), gpowgs(a4, 3)), gmul(gmul(gmul(gpowgs(a2, 3), a3), a4), a5)))), gmulsg(16, gadd(gmul(gmul(a1, gpowgs(a3, 3)), gsqr(a4)), gmul(gmul(gsqr(a2), gpowgs(a3, 3)), a5)))), gmulsg(4096, gadd(gmul(gmul(gsqr(a0), gpowgs(a4, 3)), a6), gmul(gmul(a0, gpowgs(a2, 3)), gsqr(a6))))), gmulsg(6400, gadd(gmul(gmul(gmul(gsqr(a0), a2), gsqr(a5)), a6), gmul(gmul(gmul(a0, gsqr(a1)), a4), gsqr(a6))))), gmulsg(10560, gadd(gmul(gmul(gmul(gmul(gsqr(a0), a3), a4), a5), a6), gmul(gmul(gmul(gmul(a0, a1), a2), a3), gsqr(a6))))), gmulsg(2624, gadd(gmul(gmul(gmul(gmul(a0, a1), a3), gsqr(a4)), a6), gmul(gmul(gmul(gmul(a0, gsqr(a2)), a3), a5), a6)))), gmul(gmul(gmul(gmul(gmulsg(4432, a0), a1), gsqr(a3)), a5), a6)), gmul(gmul(gmulsg(8, a2), gpowgs(a3, 4)), a4)), gpowgs(a3, 6)), gmul(gmulsg(320, gpowgs(a1, 3)), gpowgs(a5, 3))), gmul(gmul(gmul(gmulsg(64, gsqr(a1)), a2), a4), gsqr(a5))), gmul(gmul(gmulsg(176, gsqr(a1)), gsqr(a3)), gsqr(a5))), gmul(gmul(gmul(gmulsg(128, a1), gsqr(a2)), gsqr(a4)), a5)), gmul(gmul(gmul(gmul(gmulsg(112, a1), a2), gsqr(a3)), a4), a5)), gmul(gmul(gmulsg(28, a1), gpowgs(a3, 4)), a5)), gmul(gmul(gmulsg(16, gsqr(a2)), gsqr(a3)), gsqr(a4))), gmul(gmulsg(5120, gpowgs(a0, 3)), gpowgs(a6, 3))), gmul(gmul(gmulsg(2544, gsqr(a0)), gsqr(a3)), gsqr(a6))), gmul(gmul(gmulsg(312, a0), gpowgs(a3, 4)), a6)), gmul(gmul(gmul(gmulsg(14336, gsqr(a0)), a2), a4), gsqr(a6))), gmul(gmul(gmul(gmulsg(1024, a0), gsqr(a2)), gsqr(a4)), a6)), gmul(gmul(gmul(gmulsg(2560, gsqr(a0)), a1), a5), gsqr(a6))), gmul(gmul(gmul(gmulsg(2240, a0), gsqr(a1)), gsqr(a5)), a6)), gmul(gmul(gmul(gmul(gmul(gmulsg(6528, a0), a1), a2), a4), a5), a6)), gmul(gmul(gmul(gmul(gmulsg(1568, a0), a2), gsqr(a3)), a4), a6)), -10)); } /********************************************************************/ /** **/ /** A REDUCTION ALGORITHM "A LA TATE" FOR CURVES OF GENUS 2 **/ /** **/ /********************************************************************/ /* Based on genus2reduction-0.3, http://www.math.u-bordeaux1.fr/~liu/G2R/ * by Qing Liu * and Henri Cohen * Qing Liu: Modeles minimaux des courbes de genre deux * J. fuer die Reine und Angew. Math., 453 (1994), 137-164. * http://www.math.u-bordeaux1.fr/~liu/articles/modregE.ps */ /* some auxiliary polynomials, gp2c-generated */ /* apol2(a0,a1,a2) = -5*a1^2+12*a0*a2; */ static GEN apol2(GEN a0, GEN a1, GEN a2) { return gadd(gmulsg(-5, gsqr(a1)), gmul(gmulsg(12, a0), a2)); } /* apol3(a0,a1,a2,a3) = 5*a1^3+9*a0*(-2*a1*a2+3*a0*a3); */ static GEN apol3(GEN a0, GEN a1, GEN a2, GEN a3) { return gadd(gmulsg(5, gpowgs(a1, 3)), gmul(gmulsg(9, a0), gadd(gmul(gmulsg(-2, a1), a2), gmul(gmulsg(3, a0), a3)))); } /* apol5(a0,a1,a2,a3,a4,a5) = a1^5+3*a0*(-2*a1^3*a2+9*a0*a1^2*a3-36*a0^2*a1*a4+108*a0^3*a5); */ static GEN apol5(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5) { return gadd(gpowgs(a1, 5), gmul(gmulsg(3, a0), gadd(gsub(gadd(gmul(gmulsg(-2, gpowgs(a1, 3)), a2), gmul(gmul(gmulsg(9, a0), gsqr(a1)), a3)), gmul(gmul(gmulsg(36, gsqr(a0)), a1), a4)), gmul(gmulsg(108, gpowgs(a0, 3)), a5)))); } /* bpol2(a0,a1,a2,a3,a4) = 2*a2^2-5*a1*a3+10*a0*a4; */ static GEN bpol2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4) { return gadd(gsub(gmulsg(2, gsqr(a2)), gmul(gmulsg(5, a1), a3)), gmul(gmulsg(10, a0), a4)); } static const long VERYBIG = (1L<<20); static long myval(GEN x, GEN p) { return signe(x)? Z_pval(x,p): VERYBIG; } static long my3val(GEN x) { return signe(x)? Z_lval(x,3): VERYBIG; } /* largest power of p dividing pol */ static long polval(GEN pol, GEN p) { long v, i, lx = lg(pol); if (!signe(pol)) return VERYBIG; v = myval(gel(pol,2),p); for(i = 3;i= m) { m = e; l = i; } } z = gel(P,l); } *maxord = m; return z; } D = Q; for(;;) { GEN T; m++; D = FpX_deriv(D, p); T = FpX_gcd(z, D, p); if (degpol(T) == 0) break; z = T; } if (m >= 3 && degpol(z) == 2) { GEN F = FpX_factor(z,p); z = gcoeff(F,1,1); } *maxord = m; return z; } /* deg(H mod p) = 3, return v_p( disc(correspondig p-adic factor) ) */ static long discpart(GEN H, GEN p, long prec) { GEN list, prod, dis; long i, j; if (degpol(FpX_red(H,p)) != 3) pari_err_BUG("discpart [must not reach]"); list = padicfactors(H,p,prec); prod = pol_1(varn(H)); for(i = 1; i < lg(list); i++) { GEN t = gel(list,i); for(j = 3; j < lg(t); j++) /* include if non-constant mod p */ if (!valp(gel(t,j))) { prod = RgX_mul(prod,t); break; } } if (degpol(prod) != 3) pari_err_BUG("discpart [prod degree]"); dis = RgX_disc(prod); return gequal0(dis)? prec+1: valp(dis); } /* B = b0 X^6 + ... + b6 a ZX, 0 <= j <= 3. * Return theta_j(H) := min { v_p(b_i) / (i - j), lambda < i <= 6 } >= 0. * N.B. 60 theta \in Z */ static GEN theta_j(GEN B, GEN p, long j) { GEN theta, b0, b1, b2, b3, b4, b5, b6, v = new_chunk(7); long i; RgX_to_6(B, &b0,&b1,&b2,&b3,&b4,&b5,&b6); v[0] = myval(b0,p); v[1] = myval(b1,p); v[2] = myval(b2,p); v[3] = myval(b3,p); v[4] = myval(b4,p); v[5] = myval(b5,p); v[6] = myval(b6,p); theta = stoi(v[1+j]); for(i = 2+j; i <= 6; i++) theta = gmin(theta, frac2s(v[i], i-j)); return theta; } /* compute theta_3 for B in Z[i][X], p = 3 */ 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)); 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)); return frac2s(min3(6*v2, 3*v1, 2*v0), 6); } /* T an FpX of degree 1, return its root */ static GEN deg1root(GEN T, GEN p) { GEN a = gel(T,2), b = gel(T,3); return Fp_neg(Fp_div(a, b, p), p); } /* H = minimal minimal over Z_p, p > 2. * alpha = 0,1 * quad = 1 if root of order 3 in F_p^2 \ F_p, 0 otherwise * 0 <= lambda <= 3, t_INT * theta = theta(H, p), rational * beta >= 0, t_INT */ static GEN polymini(GEN pol, GEN p) { GEN a0, a1, a2, a3, a4, a5, a6; GEN H, Hp, rac, theta, polf, pro, quad; long alpha, lambda, maxord, beta; alpha = polval(pol,p); H = RgX_Rg_div(pol, powiu(p,alpha)); RgX_to_6(H, &a0,&a1,&a2,&a3,&a4,&a5,&a6); if (dvdii(a0,p) && dvdii(a1,p) && dvdii(a2,p) && dvdii(a3,p)) { H = RgX_recip6(H); RgX_to_6(H, &a0,&a1,&a2,&a3,&a4,&a5,&a6); } alpha = alpha&1; beta = 0; lambda = 0; if (!dvdii(a1,p)) lambda = 1; if (!dvdii(a2,p)) lambda = 2; if (!dvdii(a3,p)) lambda = 3; quad = gen_0; for(;;) { theta = theta_j(H,p,lambda); if (gcmp(theta,gen_1)>= 0) { long ent = itos(gfloor(theta)); GEN pent = powiu(p,ent); H = RgX_Rg_div(RgX_unscale(H,pent), powiu(pent,6-lambda)); alpha = (alpha+lambda*ent)&1; beta += ent; theta = gsubgs(theta,ent); } Hp = FpX_red(H, p); if (!gequal0(theta)) break; rac = factmz(Hp,p, &maxord); if (maxord <= 2) { if (degpol(Hp) <= 3) break; goto end; } else { /* maxord >= 3 */ if (degpol(rac) == 2) { quad = gen_1; goto end; } rac = deg1root(rac, p); H = RgX_translate(H, rac); lambda = 6-maxord; } } 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) { pol = RgX_unscale(H, p); if (alpha) pol = RgX_Rg_mul(pol, p); return polymini(pol, p); } } else if (lambda == 3 && alpha == 1) { if (degpol(Hp) == 3) { if (myval(truecoeff(H,6),p) >= 3 && myval(truecoeff(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 */ theta = gadd(theta,gen_1); alpha = 0; beta--; } } else if (degpol(Hp) == 6 && !gequal0(theta)) { rac = factmz(RgX_mulXn(Hp, -3), p, &maxord); if (maxord == 3) { rac = deg1root(rac, p); pro = RgX_translate(RgX_unscale(H,p), rac); /* H(rac + px) */ if (polval(pro,p)>= 3) { H = RgX_Rg_div(pro, powiu(p,3)); alpha = 0; beta--; theta = theta_j(H,p,3); } } } } end: polf = cgetg(7, t_VEC); gel(polf,1) = H; gel(polf,2) = stoi(lambda); gel(polf,3) = theta; gel(polf,4) = stoi(alpha); gel(polf,5) = quad; gel(polf,6) = stoi(beta); return polf; } /* a in Q[i], return a^3 mod 3 */ static GEN zi_pow3mod(GEN a) { GEN x, y; if (typ(a) != t_COMPLEX) return gmodgs(a,3); x = gmodgs(gel(a,1), 3); y = gmodgs(gel(a,2), 3); return mkcomplex(x, negi(y)); } static GEN polymini_zi(GEN pol) /* polynome minimal dans Z[i] */ { GEN p, polh, rac, theta; GEN a0, a1, a2, a3, a4, a5, a6; long alpha,beta; p = stoi(3); 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); for(;;) { polh = RgX_translate(polh, rac); theta = theta_3_zi(polh); if (gcmp(theta,gen_1) >= 0) { long ent = itos(gfloor(theta)); GEN pent = powiu(p,ent); polh = RgX_Rg_div(RgX_unscale(polh,pent), powiu(pent,3)); alpha = (alpha+ent)&1; beta += ent; theta = gsubgs(theta,ent); } RgX_to_6(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6); if (!gequal0(theta) || !myval_zi(a4) || !myval_zi(a5)) break; rac = zi_pow3mod(gdiv(a6, gneg(a3))); } if (alpha && myval_zi(a0) >= 3 && myval_zi(a1) >= 2 && myval_zi(a2) >= 1) { theta = gadd(theta, gen_1); beta--; alpha = 0; } return mkvec3(theta, stoi(alpha), stoi(beta)); } /* pol is a ZX, minimal polynomial over Z_3[i,Y]/(Y^2-3) */ static GEN polymini_zi2(GEN pol) { long alpha, beta, v = MAXVARN; GEN a0, a1, a2, a3, a4, a5, a6; GEN p, polh, rac, theta, y = pol_x(v); 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(gsub(truecoeff(polh,6), truecoeff(polh,0))) > 0) rac = gen_I(); else rac = gen_1; alpha = 0; beta = 0; for(;;) { polh = RgX_translate(polh, rac); theta = theta_3_zi2(polh); if (gcmp(theta,gen_1) >= 0) { long ent = itos(gfloor(theta)); GEN pent = gpowgs(y, ent); polh = RgX_Rg_div(RgX_unscale(polh, pent), gpowgs(pent,3)); alpha = (alpha+ent)&1; beta += ent; theta = gsubgs(theta,ent); } 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); rac = zi_pow3mod(gdiv(a6,gneg(a3))); } if (alpha) { if (myval_zi2(a0) >= 3 && myval_zi2(a1) >= 2 && myval_zi2(a2) >= 1) { theta = gadd(theta,gen_1); beta--; alpha = 0; } else pari_err_BUG("polymini_zi2 [alpha]"); } return mkcol2(theta, stoi(beta)); } struct igusa { GEN j2, i4, j4, j6, j8, j10, i12; GEN a0, A2, A3, A5, B2; }; struct igusa_p { long eps, eps2, tt, r1, r2, R, tame; GEN p, stable, val, neron; const char *type; }; static void stable_reduction(struct igusa *I, struct igusa_p *Ip) { static const long deg[9] = { 0,2,4,4,6,8,10,12 }; GEN j2 = I->j2, i4 = I->i4, j6 = I->j6, j8 = I->j8, j10 = I->j10; GEN i12 = I->i12, p = Ip->p, val = Ip->val; GEN J, v, s, Ieps; long r1, r2, r3, r4, i, eps, eps2; v = cgetg(8,t_COL); for(i = 1; i <= 7; i++) gel(v,i) = frac2s(val[i], deg[i]); s = gel(v,1); for(i = 2; i <= 7; i++) if (gcmp(gel(v,i),s) < 0) s = gel(v,i); switch(itos_or_0(p)) { case 2: eps = 4; eps2 = 5; Ieps = j8; break; case 3: eps = 3; eps2 = 4; Ieps = j6; break; default: eps = 1; eps2 = 1; Ieps = gdivgs(j2,12); break; } Ip->eps = eps; Ip->eps2 = eps2; r1 = 3*eps*val[3]; r3 = eps*val[6] + val[eps2]; r2 = eps*val[7]; r4 = min3(r1, r2, r3); /* s = max(v_p(X) / deg(X)) */ J = cgetg(1, t_VEC); if (gequal(s,gel(v,6))) Ip->tt = 1; else if (gequal(s,gel(v,7))) { J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) ); Ip->tt = 2; } else if (gequal(s,gel(v,3))) Ip->tt = (val[2] == val[3] || 2*val[4] == 3*val[3])? 3: 4; else if (r3 == r4) { GEN a,b, P, sj, pj, t = gmul(gpowgs(j10,eps),Ieps); sj = gaddsg(1728, gdiv(gpowgs(i12,eps), t)); pj = gdiv(gpowgs(i4,3*eps), t); a = gmod(sj, p); b = gmod(pj, p); P = mkpoln(3, gen_1, Fp_neg(a,p), b, 0); /* X^2 - SX + P: roots j1,j2 */ J = FpX_roots(P, p); switch(lg(J)-1) { case 0: P = FpX_to_mod(P, p); a = FpX_to_mod(pol_x(0), p); b = FpX_to_mod(deg1pol_shallow(b, gen_m1,0), p); J = mkvec2(mkpolmod(a,P), mkpolmod(b,P)); break; case 1: a = Fp_to_mod(gel(J,1), p); J = mkvec2(a, a); break; case 2: settyp(J, t_VEC); J = FpV_to_mod(J, p); break; } Ip->tt = 5; } else if (r2 == r4) { J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) ); Ip->tt = 6; } else Ip->tt = 7; /* r1 == r4 */ Ip->stable = mkvec2(stoi(Ip->tt), J); } struct red { const char *t, *pages; GEN g; }; /* destroy v */ static GEN zv_snf(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { long j, a = v[i]; for (j = i+1; j < l; j++) { long b = v[j], d = ugcd(a,b); v[i] = a = a*(b/d); v[j] = d; } } for (i = l-1; i > 0; i--) if (v[i] != 1) { setlg(v, i+1); break; } return zv_to_ZV(v); } static GEN cyclic(long n) { return (n <= 1)? cgetg(1, t_VECSMALL): mkvecsmall(n); } static GEN dicyclic(long a, long b) { long d; if (!a) a = 1; if (!b) b = 1; if (a < b) lswap(a,b); d = ugcd(a,b); if (d == 1) return cyclic(a*b); return mkvecsmall2(a*b/d, d); } /* Z/2xZ/2, resp Z/4 for n even, resp. odd */ static GEN groupH(long n) { return odd(n)? cyclic(4): dicyclic(2,2); } static long get_red(struct red *S, struct igusa_p *Ip, GEN polh, GEN p, long alpha, long r) { GEN val = Ip->val; long indice; switch(r) { case 0: indice = FpX_is_squarefree(FpX_red(polh,p), p) ? 0 : val[6] - val[7] + val[Ip->eps2]/Ip->eps; S->t = stack_sprintf("I{%ld}", indice); S->pages = "159-177"; S->g = cyclic(indice); return indice ? indice: 1; case 6: if (alpha == 0) /* H(px) /p^3 */ polh = RgX_Rg_div(RgX_unscale(polh,p), powiu(p,3)); indice = FpX_is_squarefree(FpX_red(polh,p), p) ? 0 : val[6] - val[7] + val[Ip->eps2]/Ip->eps; S->t = stack_sprintf("I*{%ld}", indice); S->pages = "159-177"; S->g = groupH(indice); return indice + 5; case 3: S->t = "III"; S->pages = "161-177"; S->g = cyclic(2); return 2; case 9: S->t = "III*"; S->pages = "162-177"; S->g = cyclic(2); return 8; case 2: S->t = "II"; S->pages = "159-174"; S->g = cyclic(1); return 1; case 8: S->t = "IV*"; S->pages = "160-175"; S->g = cyclic(3); return 7; case 4: S->t = "IV"; S->pages = "160-174"; S->g = cyclic(3); return 3; case 10: S->t = "II*"; S->pages = "160-174"; S->g = cyclic(1); return 9; default: pari_err_BUG("get_red [type]"); S->t = ""; S->pages = ""; /* gcc -Wall */ S->g = NULL; return -1; /*notreached*/ } } static long labelm3(GEN polh, GEN theta, long alpha, long dismin, struct igusa *I, struct igusa_p *Ip); /* Ip->tt = 1 */ static long tame_1(struct igusa *I, struct igusa_p *Ip) { GEN p = Ip->p, val = Ip->val; GEN r, n, pro1, pro2; long condp = -1, va0, va5; va0 = myval(I->a0,p); va5 = myval(I->A5,p); if (!gequal0(I->A5) && 20*va0+val[6] > 6*va5) { pro1 = frac2s(val[6]-2*va5, 20); pro2 = frac2s(5*val[6]-6*va5, 40); } else { pro1 = frac2s(10*va0-val[6], 30); pro2 = frac2s(5*va0-val[6], 10); } n = lcmii(denom(pro1),denom(pro2)); r = modii(gmul(n,pro1), n); switch(itos(n)) { case 1: condp = 0; Ip->type = "[I{0-0-0}] page 155"; Ip->neron = cyclic(1); break; case 2: switch(itos(r)) { case 0: condp = 4; Ip->type = "[I*{0-0-0}] page 155"; Ip->neron = mkvecsmall4(2,2,2,2); break; case 1: condp = 2; Ip->type = "[II] page 155"; Ip->neron = cyclic(1); break; default: pari_err_BUG("tame_1 [bug1]"); } break; case 4: condp = 4; Ip->type = "[VI] page 156"; Ip->neron = dicyclic(2,2); break; default: pari_err_BUG("tame_1 [bug8]"); } return condp; } static void tame_234_init(struct igusa *I, struct igusa_p *Ip, long v12, long *pn, long *pq, long *pr, long *flc) { long va0, va5, vb2; GEN p = Ip->p, pro1, pro2, n, r, q; va0 = myval(I->a0,p); va5 = myval(I->A5,p); vb2 = myval(I->B2,p); if (9*vb2 >= 6*va0+v12 && 36*va5 >= 120*va0+5*v12) { pro1 = frac2s(12*va0-v12, 36); pro2 = frac2s(6*va0-v12, 12); n = lcmii(denom(pro1),denom(pro2)); r = gmul(n,pro1); q = gmul(n,pro2); *flc = 1; } else if (120*va0+5*v12 > 36*va5 && 60*vb2 >= 12*va5+5*v12) { pro1 = frac2s(36*va5-25*v12, 240); n = denom(pro1); q = gmul(n,pro1); r = gmulsg(-2,q); *flc = 1; } else if (6*va0+v12 > 9*vb2 && 12*va5+5*v12 > 60*vb2) { pro1 = frac2s(v12-6*vb2, 12); pro2 = frac2s(v12-9*vb2, 12); n = lcmii(denom(pro1),denom(pro2)); r = gmul(n,pro1); q = gmul(n,pro2); *flc = 2; } else { pari_err_BUG("tame234 [bug9]"); return; /*not reached*/ } r = gmod(r,n); q = gmod(q,n); *pn = itos(n); *pq = itos(q); *pr = itos(r); } /* Ip->tt = 2 */ static long tame_2(struct igusa *I, struct igusa_p *Ip, long v12) { long condp = -1, d, n, q, r, flc; GEN val = Ip->val; tame_234_init(I, Ip, v12, &n, &q, &r, &flc); d = n * (6*val[6]-5*val[7]) / 6; switch(n) { case 1: condp = 1; Ip->type = stack_sprintf("[I{%ld-0-0}] page 170", d); Ip->neron = cyclic(d); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-0-0}] page 171",d/2); Ip->neron = concat(dicyclic(2,2),groupH(d/2)); break; case 1: switch(q) { case 0: condp = 2; Ip->type = stack_sprintf("[II*{%ld-0}] page 172",d/2); Ip->neron = cyclic(1); break; case 1: condp = 3; Ip->type = stack_sprintf("[II{%ld-0}] page 171",d/2); Ip->neron = cyclic(2*d); break; default: pari_err_BUG("tame2 [bug10]"); } break; default: pari_err_BUG("tame2 [bug11]"); } break; case 3: condp = 3; Ip->neron = cyclic(d); switch(r) { case 1: Ip->type = stack_sprintf("[IV-II{%ld}] page 175", (d-2)/3); break; case 2: Ip->type = stack_sprintf("[IV*-II{%ld}] page 175", (d-1)/3); break; default: pari_err_BUG("tame2 [bug12]"); } break; case 4: switch(r) { case 1: switch(q) { case 1: condp = 3; Ip->type = stack_sprintf("[III-II{%ld}] page 177",(d-2)/4); Ip->neron = cyclic(d/2); break; case 3: condp = 4; Ip->type = stack_sprintf("[III*-II*{%ld}] page 178",(d-2)/4); Ip->neron = cyclic(8); break; default: pari_err_BUG("tame2 [bug13]"); } break; case 3: switch(q) { case 1: condp = 4; Ip->type = stack_sprintf("[III-II*{%ld}] page 178",(d-2)/4); Ip->neron = cyclic(8); break; case 3: condp = 3; Ip->type = stack_sprintf("[III*-II{%ld}] page 178",(d-2)/4); Ip->neron = cyclic(d/2); break; default: pari_err_BUG("tame2 [bug14]"); } break; default: pari_err_BUG("tame2 [bug15]"); } break; case 6: switch(r) { case 2: condp = 4; Ip->type = stack_sprintf("[II*-II*{%ld}] page 176", (d-4)/6); Ip->neron = groupH((d+2)/6); break; case 4: condp = 4; Ip->type = stack_sprintf("[II-II*{%ld}] page 176", (d-2)/6); Ip->neron = groupH((d+4)/6); break; break; default: pari_err_BUG("tame2 [bug16]"); } break; default: pari_err_BUG("tame2 [bug17]"); } return condp; } /* Ip->tt = 3 */ static long tame_3(struct igusa *I, struct igusa_p *Ip, long v12) { long condp = -1, n, q, r, flc; long va5, d1, d2; GEN val = Ip->val, e1, e2; tame_234_init(I, Ip, v12, &n, &q, &r, &flc); va5 = 2*val[6]-5*val[3]; e1 = gmin(stoi(val[7]-3*val[3]),gmul2n(stoi(va5),-2)); e2 = gsub(gmul2n(stoi(va5),-1),e1); d1 = itos(gmulsg(n,e1)); d2 = itos(gmulsg(n,e2)); switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld-%ld-0}] page 179", d1,d2); Ip->neron = dicyclic(d1,d2); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-%ld-0}] page 180", d1/2,d2/2); Ip->neron = concat(groupH(d1/2),groupH(d2/2)); break; case 1: switch(flc) { case 1:condp = 3; Ip->type = stack_sprintf("[2I{%ld}-0] page 181", d1); Ip->neron = cyclic(d1); break; case 2: condp = 3; Ip->type = stack_sprintf("[II{%ld-%ld}] page 182",d1/2,d2/2); if ((d1*d2-4)&7) Ip->neron = cyclic(2*d1); else Ip->neron = dicyclic(d1,2); /* FIXME: "or" same with d1<->d2 */ break; } break; default: pari_err_BUG("tame3 [bug20]"); } break; case 4: condp = 4; Ip->type = stack_sprintf("[III{%ld}] page 182", d1/2); Ip->neron = groupH(d1/2); break; default: pari_err_BUG("tame3 [bug21]"); } return condp; } /* Ip->tt = 4 */ static long tame_4(struct igusa *I, struct igusa_p *Ip, long v12) { long condp = -1, d1, d2, d3, f1, f2, g, h, n, q, r, flc; GEN val = Ip->val, e1, e2, e3, vl, vn, vm; tame_234_init(I, Ip, v12, &n, &q, &r, &flc); vl = stoi(val[6]-5*val[1]); vn = stoi(val[7]-6*val[1]); vm = stoi(val[2]-2*val[1]); e1 = gmin3(gdivgs(vl,3), gmul2n(vn,-1), vm); e2 = gmin(gmul2n(gsub(vl,e1),-1), gsub(vn,e1)); e3 = gsub(vl,gadd(e1,e2)); d1 = itos(gmulsg(n,e1)); d2 = itos(gmulsg(n,e2)); d3 = itos(gmulsg(n,e3)); g = d1*d2 + d1*d3 + d2*d3; h = cgcd(cgcd(d1,d2),d3); switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld-%ld-%ld}] page 182",d1,d2,d3); Ip->neron = dicyclic(h,g/h); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-%ld-%ld}] page 183",d1/2,d2/2,d3/2); Ip->neron = concat(groupH(g/4), groupH(2-((h&2)>>1))); break; case 1: if (d1 == d2 || d1 == d3) f2 = d1; else if (d2 == d3) f2 = d2; else { pari_err_BUG("tame4 [bug23]"); return -1; /*not reached*/ } f1 = d1+d2+d3-2*f2; switch(q) { case 0: condp = 3; Ip->type = stack_sprintf("[II*{%ld-%ld}] page 184", f1/2,f2); Ip->neron = cyclic(f2); break; case 1: condp = 3; Ip->type = stack_sprintf("[II{%ld-%ld}] page 183", f1/2,f2); Ip->neron = cyclic(2*f1+f2); break; default: pari_err_BUG("tame4 [bug24]"); } break; default: pari_err_BUG("tame4 [bug25]"); } break; case 3: condp = 4; Ip->type = stack_sprintf("[III{%ld}] page 184",d1); Ip->neron = (d1%3)? cyclic(9): dicyclic(3,3); break; case 6: condp = 4; Ip->type = stack_sprintf("[III*{%ld}] page 184",d1/2); Ip->neron = cyclic(1); break; default: pari_err_BUG("tame4 [bug26]"); } return condp; } /* p = 3 */ static void tame_567_init_3(struct igusa_p *Ip, GEN dk, long *pd, long *pn, long *pdm, long *pr) { long n = 1 + Ip->r1/6; *pd = itos(gmulgs(dk,n)); *pn = n; *pr = -1; /* unused */ *pdm = 0; } static void tame_567_init(struct igusa *I, struct igusa_p *Ip, GEN dk, long *pd, long *pn, long *pdm, long *pr) { long va0, va2, va3, va5, vb2; long d, v1, v2; GEN r, n, m; GEN pro1, dm, rk; GEN p = Ip->p, val = Ip->val; long v5; if (equalis(p, 3)) { tame_567_init_3(Ip, dk, pd, pn, pdm, pr); return; } /* assume p > 3 */ va0 = myval(I->a0,p); va2 = myval(I->A2,p); va3 = myval(I->A3,p); va5 = myval(I->A5,p); vb2 = myval(I->B2,p); v5 = myval(subii(mulii(I->A2,I->A3),mulsi(3,I->A5)),p); rk = gadd(frac2s(va0, 2), gmin3(gmul2n(dk,-1), frac2s(2*va3-3*va2, 8), frac2s(2*v5 - 5*va2, 12))); v1 = 2*va3-4*va0-val[1]; v2 = 6*va5-20*va0-5*val[1]; /* the definition of n differs according to the parity of val[1] */ if (! odd(val[Ip->eps2])) { if (3*vb2 >= 2*va0+2*val[1] && v1 >= 0 && v2 >= 0 && (v1 == 0 || v2 == 0)) { /* Prop 4.3.1 (a) */ pro1 = frac2s(va0+val[1], 6); n = lcmii(denom(dk),denom(pro1)); r = gmul(n,pro1); } else if (20*va0+5*val[1] > 6*va5 && 10*vb2 >= 2*va5+5*val[1]) { /* Prop 4.3.1 (b) */ pro1 = frac2s(2*va5+val[1], 8); n = lcmii(denom(dk),denom(pro1)); r = gmul(n,pro1); } else if (2*va0+2*val[1] > 3*vb2 && 2*va5+5*val[1] > 10*vb2) { /* Prop 4.3.1 (c) */ pro1 = gmul2n(stoi(vb2),-2); n = lcmii(denom(dk),denom(pro1)); r = gmul(n,pro1); } else if (3*vb2 >= 2*va0+2*val[1] && 2*va3 > 4*va0+val[1] && 6*va5 > 20*va0+5*val[1]) { /* Prop 4.3.1 (d) */ if (gequal0(I->A2)) pari_err_BUG("tame567 [bug27]"); n = lcmii(denom(dk),denom(rk)); r = gmul(n,rk); } else { pari_err_BUG("tame567 [bug29]"); return; /*not reached*/ } } else { m = denom(dk); r = gmul(m,dk); n = gmul2n(m,1); } d = itos(gmul(n,dk)); dm = modsi(d,n); r = modii(r,n); *pd = d; *pn = itos(n); *pr = itos(r); *pdm = itos(dm); } static long tame_5(struct igusa *I, struct igusa_p *Ip, GEN dk) { long condp = -1, d, n, dm, r; GEN val = Ip->val; tame_567_init(I, Ip, dk, &d, &n, &dm, &r); if (! odd(val[Ip->eps2])) { switch(n) { case 1: condp = 0; Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158", d); Ip->neron = cyclic(1); break; case 2: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",(d-2)/2); Ip->neron = mkvecsmall4(2,2,2,2); break; case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-I*{0}-%ld] page 159",(d-1)/2); Ip->neron = dicyclic(2,2); break; } break; case 3: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[IV-IV*-%ld] page 165",(d-3)/3); Ip->neron = dicyclic(3,3); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-IV-%ld] page 160",(d-1)/3); Ip->neron = cyclic(3); break; case 2: condp = 4; Ip->type = stack_sprintf("[IV*-IV*-%ld] page 166",(d-4)/3); Ip->neron = dicyclic(3,3); break; } break; case 2: switch(r) { case 0: case 2: condp = 2; Ip->type = stack_sprintf("[I{0}-IV*-%ld] page 160",(d-2)/3); Ip->neron = cyclic(3); break; case 1: condp = 4; Ip->type = stack_sprintf("[IV-IV-%ld] page 165",(d-2)/3); Ip->neron = dicyclic(3,3); break; } break; } break; case 4: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[III-III*-%ld] page 169",(d-4)/4); Ip->neron = dicyclic(2,2); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-III-%ld] page 161",(d-1)/4); Ip->neron = cyclic(2); break; case 2: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-III*-%ld] page 162",(d-5)/4); Ip->neron = mkvecsmall3(2,2,2); break; } break; case 2: condp = 4; Ip->neron = dicyclic(2,2); switch(r) { case 1: Ip->type = stack_sprintf("[III-III-%ld] page 169",(d-2)/4); break; case 3: Ip->type = stack_sprintf("[III*-III*-%ld] page 169",(d-6)/4); break; default: pari_err_BUG("tame5 [bug29]"); } break; case 3: switch(r) { case 0: case 3: condp = 2; Ip->type = stack_sprintf("[I{0}-III*-%ld] page 162",(d-3)/4); Ip->neron = cyclic(2); break; case 1: case 2: condp = 4; Ip->type = stack_sprintf("[I*{0}-III-%ld] page 162",(d-3)/4); Ip->neron = mkvecsmall3(2,2,2); break; } break; } break; case 6: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[II-II*-%ld] page 163",(d-6)/6); Ip->neron = cyclic(1); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-II-%ld] page 159",(d-1)/6); Ip->neron = cyclic(1); break; case 2: case 5: condp = 4; Ip->type = stack_sprintf("[II*-IV-%ld] page 164",(d-7)/6); Ip->neron = cyclic(3); break; case 3: case 4: condp = 4; Ip->type = stack_sprintf("[I*{0}-IV*-%ld] page 161",(d-7)/6); Ip->neron = mkvecsmall2(6,2); break; } break; case 2: switch(r) { case 1: condp = 4; Ip->type = stack_sprintf("[II-II-%ld] page 163",(d-2)/6); Ip->neron = cyclic(1); break; case 3: case 5: condp = 4; Ip->type = stack_sprintf("[I*{0}-II*-%ld] page 160",(d-8)/6); Ip->neron = dicyclic(2,2); break; default: pari_err_BUG("tame5 [bug30]"); } break; case 3: Ip->neron = cyclic(3); switch(r) { case 1: case 2: condp = 4; Ip->type = stack_sprintf("[II-IV-%ld] page 164",(d-3)/6); break; case 4: case 5: condp = 4; Ip->type = stack_sprintf("[II*-IV*-%ld] page 164",(d-9)/6); break; default: pari_err_BUG("tame5 [bug31]"); } break; case 4: switch(r) { case 1: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-II-%ld] page 160",(d-4)/6); Ip->neron = dicyclic(2,2); break; case 5: condp = 4; Ip->type = stack_sprintf("[II*-II*-%ld] page 163",(d-10)/6); Ip->neron = cyclic(1); break; default: pari_err_BUG("tame5 [bug32]"); } break; case 5: switch(r) { case 0: case 5: condp = 2; Ip->type = stack_sprintf("[I{0}-II*-%ld] page 160",(d-5)/6); Ip->neron = cyclic(1); break; case 1: case 4: condp = 4; Ip->type = stack_sprintf("[II-IV*-%ld] page 164",(d-5)/6); Ip->neron = cyclic(3); break; case 2: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-IV-%ld] page 161",(d-5)/6); Ip->neron = mkvecsmall2(6,2); break; } break; default: pari_err_BUG("tame5 [bug33]"); } break; case 12: condp = 4; switch(dm) { case 1: switch(r) { case 3: case 10: Ip->type = stack_sprintf("[II*-III-%ld] page 166",(d-13)/12); Ip->neron = cyclic(2); break; case 4: case 9: Ip->type = stack_sprintf("[IV-III*-%ld] page 167",(d-13)/12); Ip->neron = cyclic(6); break; default: pari_err_BUG("tame5 [bug34]"); } break; case 5: switch(r) { case 2: case 3: Ip->type = stack_sprintf("[II-III-%ld] page 166",(d-5)/12); Ip->neron = cyclic(2); break; case 8: case 9: Ip->type = stack_sprintf("[IV*-III*-%ld] page 168",(d-17)/12); Ip->neron = cyclic(6); break; default: pari_err_BUG("tame5 [bug35]"); } break; case 7: switch(r) { case 3: case 4: Ip->type = stack_sprintf("[IV-III-%ld] page 167",(d-7)/12); Ip->neron = cyclic(6); break; case 9: case 10: Ip->type = stack_sprintf("[II*-III*-%ld] page 167",(d-19)/12); Ip->neron = cyclic(2); break; default: pari_err_BUG("tame5 [bug36]"); } break; case 11: switch(r) { case 3: case 8: Ip->type = stack_sprintf("[IV*-III-%ld] page 168",(d-11)/12); Ip->neron = cyclic(6); break; case 2: case 9: Ip->type = stack_sprintf("[II-III*-%ld] page 166",(d-11)/12); Ip->neron = cyclic(2); break; default: pari_err_BUG("tame5 [bug37]"); } break; default: pari_err_BUG("tame5 [bug38]"); } break; default: pari_err_BUG("tame5 [bug39]"); } } else { r %= (n >> 1); switch(n) { case 2: condp = 2; Ip->type = stack_sprintf("[2I{0}-%ld] page 159",(d/2)); Ip->neron = cyclic(1); break; case 4: condp = 4; Ip->type = stack_sprintf("[2I*{0}-%ld] page 159",(d/2-1)/2); Ip->neron = dicyclic(2,2); break; case 6: condp = 4; Ip->neron = cyclic(3); switch(r) { case 1: Ip->type = stack_sprintf("[2IV-%ld] page 165",(d/2-1)/3); break; case 2: Ip->type = stack_sprintf("[2IV*-%ld] page 165",(d/2-2)/3); break; default: pari_err_BUG("tame5 [bug40]"); } break; case 8: condp = 4; Ip->neron = cyclic(2); switch(r) { case 1: Ip->type = stack_sprintf("[2III-%ld] page 168",(d/2-1)/4); break; case 3: Ip->type = stack_sprintf("[2III*-%ld] page 168",(d/2-3)/4); break; default: pari_err_BUG("tame5 [bug41]"); } break; case 12: condp = 4; Ip->neron = cyclic(1); switch(r) { case 1: Ip->type = stack_sprintf("[2II-%ld] page 162",(d/2-1)/6); break; case 5: Ip->type = stack_sprintf("[2II*-%ld] page 163",(d/2-5)/6); break; default: pari_err_BUG("tame5 [bug42]"); } break; default: pari_err_BUG("tame5 [bug43]"); } } return condp; } static long tame_6(struct igusa *I, struct igusa_p *Ip, GEN dk, GEN polh, GEN theta, long alpha, long dismin) { long condp = -1, d, d1, n, dm, r; GEN val = Ip->val, d1k; tame_567_init(I, Ip, dk, &d, &n, &dm, &r); d1k = frac2s(Ip->eps*(val[6]-val[7])+val[Ip->eps2], Ip->eps); d1 = itos(gmulsg(n,d1k)); switch(n) { case 1: condp = 1; Ip->type = stack_sprintf("[I{%ld}-I{0}-%ld] page 170",d1,d); Ip->neron = cyclic(d1); break; case 2: switch(dm) { case 0: condp = 4; Ip->type=stack_sprintf("[I*{0}-I*{%ld}-%ld] page 171", d1/2,(d-2)/2); Ip->neron = concat(groupH(d1/2), dicyclic(2,2)); break; case 1: return labelm3(polh,theta,alpha,dismin,I,Ip); default: pari_err_BUG("tame6 [bug44]"); } break; case 3: condp = 3; Ip->neron = dicyclic(3,d1/3); switch(dm) { case 1: Ip->type = stack_sprintf("[IV-I{%ld}-%ld] page 173",d1/3,(d-1)/3); break; case 2: Ip->type = stack_sprintf("[IV*-I{%ld}-%ld] page 173",d1/3,(d-2)/3); break; default: pari_err_BUG("tame6 [bug45]"); } break; case 4: switch(dm) { case 1: switch(r) { case 0: case 1: condp = 3; Ip->type=stack_sprintf("[III-I{%ld}-%ld] page 176",d1/4,(d-1)/4); Ip->neron = dicyclic(2,d1/4); break; case 2: case 3: condp = 4; Ip->type=stack_sprintf("[III*-I*{%ld}-%ld] page 177",d1/4,(d-5)/4); Ip->neron = concat(groupH(d1/4), cyclic(2)); break; break; default: pari_err_BUG("tame6 [bug46]"); } break; case 3: switch(r) { case 0: case 3: condp = 3; Ip->type=stack_sprintf("[III*-I{%ld}-%ld] page 176",d1/4,(d-3)/4); Ip->neron = dicyclic(2,d1/4); break; case 1: case 2: condp = 4; Ip->type=stack_sprintf("[III-I*{%ld}-%ld] page 177",d1/4,(d-3)/4); Ip->neron = concat(groupH(d1/4), cyclic(2)); break; default: pari_err_BUG("tame6 [bug47]"); } break; default: pari_err_BUG("tame6 [bug48]"); } break; case 6: switch(dm) { case 1: switch(r) { case 0: case 1: condp = 3; Ip->type = stack_sprintf("[II-I{%ld}-%ld] page 172",d1/6,(d-1)/6); Ip->neron = cyclic(d1/6); break; case 3: case 4: condp = 4; Ip->type=stack_sprintf("[IV*-I*{%ld}-%ld] page 174",d1/6,(d-7)/6); Ip->neron = concat(groupH(d1/6), cyclic(3)); break; default: pari_err_BUG("tame6 [bug49]"); } break; case 2: condp = 4; Ip->type = stack_sprintf("[II*-I*{%ld}-%ld] page 174",d1/6,(d-8)/6); Ip->neron = groupH(d1/6); break; case 4: condp = 4; Ip->type = stack_sprintf("[II-I*{%ld}-%ld] page 173",d1/6,(d-4)/6); Ip->neron = groupH(d1/6); break; case 5: switch(r) { case 0: case 5: condp = 3; Ip->type=stack_sprintf("[II*-I{%ld}-%ld] page 172",d1/6,(d-5)/6); Ip->neron = cyclic(d1/6); break; case 2: case 3: condp = 4; Ip->type=stack_sprintf("[IV-I*{%ld}-%ld] page 174",d1/6,(d-5)/6); Ip->neron = concat(groupH(d1/6), cyclic(3)); break; default: pari_err_BUG("tame6 [bug50]"); } break; default: pari_err_BUG("tame6 [bug51]"); } break; default: pari_err_BUG("tame6 [bug52]"); } return condp; } static long tame_7(struct igusa *I, struct igusa_p *Ip, GEN dk, GEN polh, GEN theta, long alpha, long dismin) { long condp = -1, d, d1, d2, n, dm, r; GEN val = Ip->val, d1k, d2k, pro1; tame_567_init(I, Ip, dk, &d, &n, &dm, &r); pro1 = frac2s(Ip->eps*val[6]+val[Ip->eps2]-3*Ip->eps*val[3], Ip->eps); d1k = gmin(stoi(val[7]-3*val[3]),gmul2n(pro1,-1)); d2k = gsub(pro1,d1k); d1 = itos(gmulsg(n,d1k)); d2 = itos(gmulsg(n,d2k)); switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld}-I{%ld}-%ld] page 179",d1,d2,d); Ip->neron = dicyclic(d1,d2); break; case 2: if ( odd(val[Ip->eps2]) ) { condp = 3; Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d1,d/2); Ip->neron = cyclic(d1); } else if (dm == 0) { condp = 4; Ip->type = stack_sprintf("[I*{%ld}-I*{%ld}-%ld] page 180", d1/2,d2/2,(d-2)/2); Ip->neron = concat(groupH(d1/2),groupH(d2/2)); } else { GEN H; if (d1 != d2) return labelm3(polh,theta,alpha,dismin,I,Ip); condp = 3; H = groupH(d1/2); Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page 180", d1/2,d1/2,(d-1)/2); Ip->neron = concat(H, H); } break; case 4: condp = 4; Ip->type = stack_sprintf("[2I*{%ld}-%ld] page 181",d1/2,(d-2)/4); Ip->neron = groupH(d1/2); break; default: pari_err_BUG("tame7 [bug55]"); } return condp; } static long tame(GEN polh, GEN theta, long alpha, long dismin, struct igusa *I, struct igusa_p *Ip) { GEN val = Ip->val, dk; Ip->tame = 1; switch(Ip->tt) { case 1: return tame_1(I, Ip); case 2: return tame_2(I, Ip, myval(I->i12, Ip->p)); case 3: return tame_3(I, Ip, 3*myval(I->i4, Ip->p)); case 4: return tame_4(I, Ip, 6*myval(I->j2, Ip->p)); case 5: dk = frac2s(Ip->eps*val[6]-5*val[Ip->eps2], 12*Ip->eps); return tame_5(I, Ip, dk); case 6: dk = frac2s(Ip->eps*val[7]-6*val[Ip->eps2], 12*Ip->eps); return tame_6(I, Ip, dk, polh, theta, alpha, dismin); case 7: dk = frac2s(Ip->eps*val[3]-2*val[Ip->eps2], 4*Ip->eps); return tame_7(I, Ip, dk, polh, theta, alpha, dismin); } return -1; /*not reached*/ } /* maxc = maximum conductor valuation at p */ static long get_maxc(GEN p) { switch (itos_or_0(p)) { case 2: return 20; break; case 3: return 10; break; case 5: return 9; break; default: return 4; break; /* p > 5 */ } } /* p = 3 */ static long quartic(GEN polh, long alpha, long dismin, struct igusa_p *Ip) { GEN theta, val = Ip->val, p = Ip->p; GEN polf = polymini_zi2(ZX_Z_mul(polh, powiu(p, alpha))); long condp = -1, d, R, r1, beta; theta = gel(polf,1); beta = itos(gel(polf,2)); if (odd(beta)) pari_err_BUG("quartic [type over Z[i] must be [K-K-(2*m)]]"); R = beta/2; r1 = itos(gmulgs(theta,6)); switch(Ip->tt) { case 1: case 5: d = 0;break; case 3: d = val[6] - 5*val[3]/2;break; case 7: d = val[6] - 3*val[3] + val[Ip->eps2]/Ip->eps;break; default: pari_err_BUG("quartic [type choices]"); d = 0; /*not reached*/ } switch(r1) { case 0: if (d) { condp = 3; Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d,R); Ip->neron = cyclic(d); } else { condp = 2; Ip->neron = cyclic(1); if (R) Ip->type = stack_sprintf("[2I{0}-%ld] page 159",R); else Ip->type = "[II] page 155"; } break; case 6: condp = 4; Ip->type = stack_sprintf("[2I*{%ld}-%ld] pages 159, 181",d,R); Ip->neron = dicyclic(2,2); break; case 3: condp = 4; Ip->type = stack_sprintf("[2III-%ld] page 168",R); Ip->neron = cyclic(2); break; case 9: condp = 4; Ip->type = stack_sprintf("[2III*-%ld] page 168",R); Ip->neron = cyclic(2); break; case 2: condp = dismin-12*R-13; Ip->type = stack_sprintf("[2II-%ld] page 162",R); Ip->neron = cyclic(1); break; case 8: condp = dismin-12*R-19; Ip->type = stack_sprintf("[2IV*-%ld] page 165",R); Ip->neron = cyclic(3); break; case 4: condp = dismin-12*R-15; Ip->type = stack_sprintf("[2IV-%ld] page 165",R); Ip->neron = cyclic(3); break; case 10: condp = dismin-12*R-21; Ip->type = stack_sprintf("[2II*-%ld] page 163",R); Ip->neron = cyclic(1); break; default: pari_err_BUG("quartic [type1]"); } if (condp > get_maxc(p) || condp < 0) pari_err_BUG("quartic [conductor]"); return condp; } static long litredtp(long alpha, long alpha1, GEN theta, GEN theta1, GEN polh, GEN polh1, long dismin, struct igusa *I, struct igusa_p *Ip) { GEN val = Ip->val, p = Ip->p; long condp = -1, indice, d, R = Ip->R; if ((Ip->r1 == 0||Ip->r1 == 6) && (Ip->r2 == 0||Ip->r2 == 6)) { /* (r1,r2) = (0,0), (0,6), (6,0) or (6,6) */ if (Ip->tt == 5) { switch(Ip->r1 + Ip->r2) { case 0: /* (0,0) */ condp = 0; Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158",R); Ip->neron = cyclic(1); break; case 6: /* (0,6) or (6,0) */ condp = 2; Ip->type = stack_sprintf("[I*{0}-I{0}-%ld] page 159",R); Ip->neron = dicyclic(2,2); break; case 12: /* (6,6) */ condp = 4; Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",R); Ip->neron = mkvecsmall4(2,2,2,2); break; } return condp; } if (Ip->r1 == Ip->r2) return tame(polh, theta, alpha, dismin, I, Ip); if (Ip->tt == 6) { d = val[6] - val[7] + (val[Ip->eps2]/Ip->eps); if (Ip->r1 && alpha1 == 0) /* H(px) / p^3 */ polh1 = RgX_Rg_div(RgX_unscale(polh1,p), powiu(p,3)); if (FpX_is_squarefree(FpX_red(polh1,p),p)) { indice = 0; condp = 3-Ip->r2/6; } else { indice = d; condp = 3-Ip->r1/6; } } else { /* Ip->tt == 7 */ long d1; d = val[6] - 3*val[3] + (val[Ip->eps2]/Ip->eps); if (gequal1(theta1)) /* H(px) / p^3 */ polh1 = RgX_Rg_div(RgX_unscale(polh1,p), powiu(p,3)); d1 = minss(val[7]-3*val[3],d/2); if (d == 2*d1) indice = d1; else { indice = discpart(polh1,p,d1+1); if (indice>= d1+1) indice = d-d1; else indice = d1; } condp = 3; } if (Ip->r1) { /* (6,0) */ Ip->neron = concat(cyclic(d-indice),groupH(indice)); if (Ip->tt == 6) Ip->type = stack_sprintf("[I*{%ld}-I{%ld}-%ld] page 170",indice,d-indice,R); else Ip->type = stack_sprintf("[I*{%ld}-I{%ld}-%ld] page 180",indice,d-indice,R); } else { /* (0,6) */ Ip->neron = concat(cyclic(indice),groupH(d-indice)); if (Ip->tt == 6) Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page 170", indice,d-indice,R); else Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page 180", indice,d-indice,R); } return condp; } if (Ip->tt == 7) pari_err_BUG("litredtp [switch ri]"); { struct red S1, S; long comp = get_red(&S1, Ip, polh1, p, alpha1, Ip->r1) + get_red(&S, Ip, polh, p, alpha, Ip->r2); Ip->type = stack_sprintf("[%s-%s-%ld] pages %s", S1.t, S.t, R, S.pages); Ip->neron = concat(S1.g, S.g); condp = (R >= 0)? dismin-comp+2-12*R: dismin-comp+4; } if (condp > get_maxc(p)) pari_err_BUG("litredtp [conductor]"); return condp; } static long labelm3(GEN polh, GEN theta, long alpha, long dismin, struct igusa *I, struct igusa_p *Ip) { GEN polh1, theta1, polf, val = Ip->val, p = Ip->p; long alpha1, lambda, beta, R; polh1 = polh; theta1 = theta; alpha1 = alpha; polf = polymini(ZX_Z_mul(RgX_recip6(polh), powiu(p,alpha)), p); polh = gel(polf,1); lambda= itos(gel(polf,2)); theta = gel(polf,3); alpha = itos(gel(polf,4)); beta = itos(gel(polf,6)); if (lambda != 3) pari_err_BUG("labelm3 [lambda = 3]"); R = beta-alpha1-alpha; if (R&1) pari_err_BUG("labelm3 [R odd]"); R >>= 1; if (R <= -2) pari_err_BUG("labelm3 [R <= -2]"); if (val[Ip->eps2] % (2*Ip->eps)) pari_err_BUG("labelm3 [val(eps2)]"); if (R >= 0 && (alpha+alpha1) >= 1) pari_err_BUG("labelm3 [minimal equation]"); Ip->r1 = itos(gmulgs(theta1,6)) + 6*alpha1; Ip->r2 = itos(gmulgs(theta, 6)) + 6*alpha; Ip->R = R; return litredtp(alpha, alpha1, theta, theta1, polh, polh1, dismin, I, Ip); } /* p = 3 */ static long quadratic(GEN polh, long alpha, long dismin, struct igusa *I, struct igusa_p *Ip) { long alpha1, beta, R; GEN polf, polh1, theta, theta1; alpha1 = alpha; polf = polymini_zi(ZX_Z_mul(polh, powiu(Ip->p,alpha))); theta = gel(polf,1); alpha = itos(gel(polf,2)); beta = itos(gel(polf,3)); if (alpha && beta >= 1) pari_err_BUG("quadratc"); R = beta-alpha; if (R >= 0 && alpha1) { dismin -= 10; if (DEBUGLEVEL) err_printf("(Care: minimal discriminant over Z[i] smaller than over Z)\n"); } Ip->r1 = itos(gmulgs(theta,6))+6*alpha; Ip->r2 = Ip->r1; Ip->R = R; alpha1 = alpha; theta1 = theta; polh1 = polh; /* FIXME !!! */ return litredtp(alpha, alpha1, theta, theta1, polh, polh1, dismin, I, Ip); } static long genus2localred(struct igusa *I, struct igusa_p *Ip, GEN p, GEN polmini) { GEN val, polh, theta, list, c1, c2, c3, c4, c5, c6, prod; long i, vb5, vb6, d, dismin, alpha, lambda; long condp = -1, indice, vc6, mm, nb, dism; val = cgetg(8, t_VECSMALL); Ip->tame = 0; Ip->neron = NULL; Ip->type = NULL; Ip->p = p; Ip->val = val; val[1] = myval(I->j2,p); val[2] = myval(I->j4,p); val[3] = myval(I->i4,p); val[4] = myval(I->j6,p); val[5] = myval(I->j8,p); val[6] = myval(I->j10,p); val[7] = myval(I->i12,p); dismin = val[6]; stable_reduction(I, Ip); if (dismin == 0) { Ip->tame = 1; Ip->type = "[I{0-0-0}] page 155"; Ip->neron = cyclic(1); return 0; } if (dismin == 1) { Ip->type = "[I{1-0-0}] page 170"; Ip->neron = cyclic(1); return 1; } if (dismin == 2) switch(Ip->tt) { case 2: Ip->type = "[I{2-0-0}] page 170"; Ip->neron = cyclic(2); return 1; case 3: Ip->type = "[I{1-1-0}] page 179"; Ip->neron = cyclic(1); return 2; case 5: if (cmpis(p,3) <= 0) pari_err_BUG("genus2localred [tt 1]"); Ip->type = "[I{0}-II-0] page 159"; Ip->neron = cyclic(1); return 2; default: pari_err_BUG("genus2localred [tt 2]"); } if (equaliu(p,2)) return -1; polh = gel(polmini,1); lambda = itos(gel(polmini,2)); theta = gel(polmini,3); alpha = itos(gel(polmini,4)); if (!gequal0(gel(polmini,5))) return equalis(p,3)? quadratic(polh, alpha, dismin, I, Ip): tame(polh, theta, alpha, dismin, I, Ip); if (gequal0(theta) && lambda<= 2) { if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 3]"); return tame(polh, theta, alpha, dismin, I, Ip); } if (dismin == 3) { switch(Ip->tt) { case 2: return tame(polh, theta, alpha, dismin, I, Ip); case 3: Ip->type = "[I{2-1-0}] page 179"; Ip->neron = cyclic(2); return 2; case 4: Ip->type = "[I{1-1-1}] page 182"; Ip->neron = cyclic(3); return 2; case 5: if (equalis(p,3) && !gequal(theta,ghalf)) return labelm3(polh,theta,alpha,dismin,I,Ip); Ip->type = "[I{0}-III-0] page 161"; Ip->neron = cyclic(2); return 2; case 6: if (equalis(p,3)) pari_err_BUG("genus2localred [conductor]"); Ip->type = "[I{1}-II-0] page 172"; Ip->neron = cyclic(1); return 3; } pari_err_BUG("genus2localred [switch tt 4]"); return -1; /* not reached */ } switch(lambda) { case 0: switch(itos(gmulgs(theta, 60))+alpha) { case 10: condp = dismin-1; Ip->type = "[V] page 156"; Ip->neron = cyclic(3); break; case 11: condp = dismin-11; Ip->type = "[V*] page 156"; Ip->neron = cyclic(3); break; case 12: condp = dismin-2; Ip->type = "[IX-2] page 157"; Ip->neron = cyclic(5); break; case 13: condp = dismin-12; Ip->type = "[VIII-4] page 157"; Ip->neron = cyclic(1); break; case 24: condp = dismin-8; Ip->type = "[IX-4] page 158"; Ip->neron = cyclic(5); break; case 15: case 16: if (Ip->tt>= 5) pari_err_BUG("genus2localred [tt 6]"); return tame(polh, theta, alpha, dismin, I, Ip); case 20: case 21: { GEN b0, b1, b2, b3, b4, b5, b6, b02, b03, b04, b05; RgX_to_6(polh, &b0,&b1,&b2,&b3,&b4,&b5,&b6); vb5 = myval(b5,p); vb6 = myval(b6,p); if (vb6 >= 3) { if (vb5 < 2) pari_err_BUG("genus2localred [red1]"); if (vb5 >= 3) { condp = dismin-8; Ip->type = "[II*-IV-(-1)] page 164"; Ip->neron = cyclic(3); } else { condp = dismin-7; Ip->type = "[IV-III*-(-1)] page 167"; Ip->neron = cyclic(6); } break; } if (dvdii(b0,p)) pari_err_BUG("genus2localred [b0]"); b02 = gsqr(b0); b03 = gmul(b02, b0); b04 = gmul(b03, b0); b05 = gmul(b04, b0); c1 = gmul2n(b1,-1); c2 = gmul2n(gsub(gmul(b0,b2), gsqr(c1)),-1); c3 = gmul2n(gsub(gmul(b02,b3), gmul2n(gmul(c1,c2),1)),-1); c4 = gsub(gmul(b03,b4), gadd(gmul2n(gmul(c1,c3),1),gsqr(c2))); c5 = gsub(gmul(b04,b5), gmul2n(gmul(c2,c3),1)); c6 = gsub(gmul(b05,b6), gsqr(c3)); /* b0^5*H(x/b0) = (x^3+c1*x^2+c2*x+c3)^2+c4*x^2+c5*x+c6 */ vc6 = myval(c6,p); if (vc6 == 2) { if (alpha) { condp = dismin-16; Ip->type = "[IV] page 155"; Ip->neron = cyclic(1); } else { condp = dismin-6; Ip->type = "[III] page 155"; Ip->neron = dicyclic(3,3); } } else { if (myval(c3,p) > 1) pari_err_BUG("genus2localred [c3]"); mm = min3(3*myval(c4,p)-4, 3*myval(c5,p)-5, 3*vc6-6); if (alpha) { condp = dismin-mm-16; Ip->type = stack_sprintf("[III*{%ld}] page 184", mm); Ip->neron = cyclic(1); } else { condp = dismin-mm-6; Ip->type = stack_sprintf("[III{%ld}] page 184", mm); Ip->neron = (mm%3)? cyclic(9): dicyclic(3,3); } } } break; case 30: return equalis(p,3)? quartic(polh, alpha, dismin, Ip) : tame(polh, theta, alpha, dismin, I, Ip); default: pari_err_BUG("genus2localred [red2]"); } break; case 1: switch(itos(gmulgs(theta, 60))+alpha) { case 12: condp = dismin; Ip->type = "[VIII-1] page 156"; Ip->neron = cyclic(1); break; case 13: condp = dismin-10; Ip->type = "[IX-3] page 157"; Ip->neron = cyclic(5); break; case 24: condp = dismin-4; Ip->type = "[IX-1] page 157"; Ip->neron = cyclic(5); break; case 25: condp = dismin-14; Ip->type = "[VIII-3] page 157"; Ip->neron = cyclic(1); break; case 36: condp = dismin-8; Ip->type = "[VIII-2] page 157"; Ip->neron = cyclic(1); break; case 15: condp = dismin-1; Ip->type = "[VII] page 156"; Ip->neron = cyclic(2); break; case 16: condp = dismin-11; Ip->type = "[VII*] page 156"; Ip->neron = cyclic(2); break; case 20: if (cmpis(p,3)) { d = 6*val[6]-5*val[7]-2; if (d%6) pari_err_BUG("genus2localred [index]"); dism = (d/6); } else { list = padicfactors(polh,p,dismin-5); nb = lg(list); prod = pol_1(varn(polh)); for(i = 1;i 2) pari_err_BUG("genus2localred [padicfactors]"); dism = valp(RgX_disc(prod)) - 1; } condp = dismin-dism-3; Ip->type = stack_sprintf("[II-II*{%ld}] page 176", dism); Ip->neron = groupH(dism+1); break; case 21: vb6 = myval(truecoeff(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); if (vb5 == 2) { if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 6]"); return tame(polh, theta, alpha, dismin, I, Ip); } condp = dismin-7; Ip->type = "[II*-III-(-1)] page 167"; Ip->neron = cyclic(2); break; } break; case 2: if (equalis(denom(theta),4)) { if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]"); return tame(polh, theta, alpha, dismin, I, Ip); } if (!equalis(p,3) && equalis(denom(theta),3)) return tame(polh, theta, alpha, dismin, I, Ip); list = padicfactors(polh,p,dismin-10*alpha); nb = lg(list); prod = pol_1(varn(polh)); for(i = 1;itype = stack_sprintf("[IV-II{%ld}] page 175", dism); Ip->neron = cyclic(3*dism+2); break; case 1: condp = dismin-dism-10; Ip->type = stack_sprintf("[II*-II*{%ld}] page 176",dism); Ip->neron = groupH(dism+1); break; break; case 2: case 3: if (myval(truecoeff(polh,0),p) == 2) { if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]"); return tame(polh, theta, alpha, dismin, I, Ip); } dism++; indice = val[6]-(5*val[3]/2)-dism; condp = dismin-dism-indice-2; Ip->type = stack_sprintf("[II{%ld-%ld}] page 182", dism,indice); Ip->neron = both_odd(dism,indice)? dicyclic(2,2*dism): cyclic(4*dism); break; case 4: condp = dismin-dism-5; Ip->type = stack_sprintf("[IV*-II{%ld}] page 175",dism+1); Ip->neron = cyclic(3*dism+4); break; } break; case 3: if (!equalis(p,3) || Ip->tt <= 4) return tame(polh, theta, alpha, dismin, I, Ip); return labelm3(polh,theta,alpha,dismin,I,Ip); /* p = 3 */ default: pari_err_BUG("genus2localred [switch lambda]"); } if (condp < 2 || condp > get_maxc(p)) pari_err_BUG("genus2localred [conductor]"); return condp; } static long chk_pol(GEN P) { switch(typ(P)) { case t_INT: break; case t_POL: RgX_check_ZX(P,"genus2red"); return varn(P); break; default: pari_err_TYPE("genus2red", P); } return -1; } /* P,Q are ZX, study Y^2 + Q(X) Y = P(X) */ GEN genus2red(GEN Q, GEN P, GEN p) { pari_sp av = avma; struct igusa I; GEN j22, j42, j2j6, a0,a1,a2,a3,a4,a5,a6, V,polr,facto,factp, vecmini, cond; long i, l, dd, vP,vQ; vP = chk_pol(P); vQ = chk_pol(Q); if (vP < 0) { if (vQ < 0) pari_err_TYPE("genus2red",mkvec2(P,Q)); P = scalarpol(P,vQ); } else if (vQ < 0) Q = scalarpol(Q,vP); if (p && typ(p) != t_INT) pari_err_TYPE("genus2red", p); polr = ZX_add(ZX_sqr(Q), gmul2n(P,2)); /* ZX */ switch(degpol(polr)) { case 5: case 6: break; default: pari_err_DOMAIN("genus2red","genus","!=", gen_2,mkvec2(P,Q)); } RgX_to_6(polr, &a0,&a1,&a2,&a3,&a4,&a5,&a6); I.j10 = !signe(a0)? mulii(sqri(a1), ZX_disc(polr)): ZX_disc(polr); if (!signe(I.j10)) pari_err_DOMAIN("genus2red","genus","<",gen_2,mkvec2(P,Q)); I.j10 = gmul2n(I.j10, -12); /* t_INT */ if (p == NULL) { facto = factor(absi(I.j10)); factp = gel(facto,1); } else { factp = mkcol(p); facto = mkmat2(factp, mkcol(gen_1)); } l = lg(factp); vecmini = cgetg(l, t_COL); for(i = 1; i= 0) N = zv_snf(Ip.neron); if (DEBUGLEVEL) { if (!p) err_printf("p = %Ps\n", q); err_printf("(potential) stable reduction: %Ps\n", Ip.stable); if (f >= 0) { err_printf("reduction at p: %s, %Ps", Ip.type, N); err_printf(", f = %ld\n", f); } } red = f >= 0? mkvec2(strtoGENstr(Ip.type), N): cgetg(1, t_VEC); gel(V, i) = mkvec3(q, Ip.stable, red); } if (p) V = gel(V,1); cond = factorback(facto); /* remove denominator 2 coming from f = -1 in genuslocalred(, p = 2) */ if (typ(cond) != t_INT) cond = gel(cond,1); return gerepilecopy(av, mkvec4(cond, facto, polr, V)); } pari-2.7.5/src/modules/ellsea.c0000644000175000017500000014327212414216316014767 0ustar billbill/* Copyright (C) 2008 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. */ /* This file is a C version by Bill Allombert of the 'ellsea' GP package * whose copyright statement is as follows: Authors: Christophe Doche Sylvain Duquesne Universite Bordeaux I, Laboratoire A2X For the AREHCC project, see http://www.arehcc.com/ Contributors: Karim Belabas (code cleanup and package release, faster polynomial arithmetic) 'ellsea' 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. */ /* Extension to non prime finite fields by Bill Allombert 2012 */ #include "pari.h" #include "paripriv.h" static GEN modular_eqn; void pari_init_seadata(void) { modular_eqn = NULL; } void pari_close_seadata(void) { if (modular_eqn) gunclone(modular_eqn); } static int FqX_equal(GEN x, GEN y) { return gequal(x,y); } static int FlxX_equal(GEN x, GEN y) { return gequal(x,y); } static char * seadata_filename(ulong ell) { return stack_sprintf("%s/seadata/sea%ld", pari_datadir, ell); } static GEN get_seadata(ulong ell) { pari_sp av=avma; GEN eqn; char *s = seadata_filename(ell); pariFILE *F = pari_fopengz(s); if (!F) return NULL; if (ell==0) { eqn = gp_readvec_stream(F->file); pari_fclose(F); modular_eqn = gclone(eqn); avma=av; return gen_0; } else { eqn = gp_read_stream(F->file); pari_fclose(F); return eqn; } } /*Builds the modular equation corresponding to the vector list. Shallow */ static GEN list_to_pol(GEN list, long vx, long vy) { long i, l = lg(list); GEN P = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN L = gel(list,i); if (typ(L) == t_VEC) L = RgV_to_RgX_reverse(L, vy); gel(P, i) = L; } return RgV_to_RgX_reverse(P, vx); } struct meqn { char type; GEN eq; }; static int get_modular_eqn(struct meqn *M, ulong ell, long vx, long vy) { GEN eqn; long idx = uprimepi(ell)-1; if (!modular_eqn && !get_seadata(0)) pari_err_PACKAGE("seadata"); if (idx && idxtype = *GSTR(gel(eqn, 2)); M->eq = list_to_pol(gel(eqn, 3), vx, vy); return 1; } static void err_modular_eqn(long ell) { pari_err_FILE("seadata file", seadata_filename(ell)); } GEN 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 (varncmp(vx,vy)>=0) pari_err_PRIORITY("ellmodulareqn", pol_x(vx), ">=", vy); if (ell < 0 || !uisprime(ell)) pari_err_PRIME("ellmodulareqn (level)", stoi(ell)); if (!get_modular_eqn(&meqn, ell, vx, vy)) err_modular_eqn(ell); return gerepilecopy(av,mkvec2(meqn.eq, stoi(meqn.type=='A'))); } /*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) { GEN res = cgetg(precS+1, t_VEC); long k, h; if (precS == 0) return res; gel(res, 1) = Fq_div(a4, stoi(-5), T, p); if (precS == 1) return res; gel(res, 2) = Fq_div(a6, stoi(-7), T, p); for (k = 3; k <= precS; ++k) { pari_sp btop = avma; GEN a = gen_0; 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); gel(res, k) = gerepileupto(btop, a); } 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)); } /****************************************************************************/ /* SIMPLE ELLIPTIC CURVE OVER Fq */ /****************************************************************************/ static GEN Fq_ellj(GEN a4, GEN a6, GEN T, GEN p) { pari_sp ltop=avma; GEN a43 = Fq_mulu(Fq_powu(a4, 3, T, p), 4, T, p); GEN j = Fq_div(Fq_mulu(a43, 1728, T, p), Fq_add(a43, Fq_mulu(Fq_sqr(a6, T, p), 27, T, p), T, p), T, p); return gerepileupto(ltop, j); } /****************************************************************************/ /* EIGENVALUE */ /****************************************************************************/ struct eigen_ellinit { GEN a4, h, T, p; GEN RHS, DRHS, X12, Gr, nGr,O; ulong pp; }; static void init_eigen(struct eigen_ellinit *Edat, GEN a4, GEN a6, GEN h, GEN T, GEN p) { pari_sp ltop = avma; GEN RHS = FqX_rem(mkpoln(4, gen_1, gen_0, a4, a6), h, T, p); GEN DRHS = FqX_rem(mkpoln(3, utoi(3), gen_0, a4), h, T, p); GEN lambda = FqXQ_div(DRHS, FqX_mulu(RHS, 4, T, p), h, T, p); GEN C = FqX_sub(FqXQ_mul(lambda, DRHS, h, T, p), monomial(gen_2,1,0), T, p); GEN D = FqXQ_mul(FqX_mulu(lambda, 2, T, p),FqX_sub(pol_x(0), C, T, p), h, T, p); GEN X12 = mkvec2(C, FqX_Fq_add(D, gen_m1, T, p)); GEN Gr = T ? FpXQXQ_halfFrobenius(RHS, h, T, p): FpXQ_pow(RHS, shifti(p, -1), h, p); GEN nGr = FqX_neg(Gr, T, p); gerepileall(ltop, 5, &RHS, &DRHS, &X12, &Gr, &nGr); Edat->a4 = gcopy(a4); Edat->h = gcopy(h); Edat->T = T; Edat->p = p; Edat->pp = 0; Edat->RHS = RHS; Edat->DRHS = DRHS; Edat->X12 = X12; Edat->Gr = Gr; Edat->nGr = nGr; Edat->O = mkvec2(pol_x(0), pol_1(0)); } static void init_eigenu(struct eigen_ellinit *Edat, GEN a4, GEN a6, GEN h, GEN T, ulong p) { pari_sp ltop = avma; long vT = get_Flx_var(T); GEN g1 = pol1_Flx(vT), g0 = pol0_Flx(vT); GEN RHS = FlxqX_rem(mkpoln(4, g1, g0, a4, a6), h, T, p); GEN DRHS = FlxqX_rem(mkpoln(3, Fl_to_Flx(3, T[1]), g0, a4), h, T, p); GEN lambda = FlxqXQ_div(DRHS, FlxX_Fl_mul(RHS, 4, p), h, T, p); GEN C = FlxX_sub(FlxqXQ_mul(lambda, DRHS, h, T, p), monomial(Fl_to_Flx(2,vT),1,0), p); GEN D = FlxqXQ_mul(FlxX_double(lambda, p),FlxX_sub(pol_x(0), C, p), h, T, p); GEN X12 = mkvec2(C, FlxX_Flx_add(D, Fl_to_Flx(p-1,vT), p)); GEN Gr = FlxqXQ_halfFrobenius(RHS,h,T,p); GEN nGr = FlxX_neg(Gr, p); GEN O = mkvec2(monomial(g1,1,0), monomial(g1,0,0)); gerepileall(ltop, 6, &RHS, &DRHS, &X12, &Gr, &nGr, &O); Edat->a4 = gcopy(a4); Edat->h = gcopy(h); Edat->T = T; Edat->p = NULL; Edat->pp = p; Edat->RHS = RHS; Edat->DRHS = DRHS; Edat->X12 = X12; Edat->Gr = Gr; Edat->nGr = nGr; Edat->O = O; } static GEN eigen_elldbl(void *E, GEN P) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN T = Edat->T, p = Edat->p, h = Edat->h, x, y; if (ell_is_inf(P)) return gcopy(P); x = gel(P,1), y = gel(P,2); if (FqX_equal(x, pol_x(0)) && FqX_equal(y, pol_1(0))) return Edat->X12; else { GEN t1 = FqX_Fq_add(FqX_mulu(FqXQ_sqr(x,h,T,p),3,T, p), Edat->a4, T, p); GEN t2 = FqXQ_mul(FqX_mulu(y, 2, T, p), Edat->RHS, h, T, p); GEN lambda = FqXQ_div(t1, t2, h, T, p); GEN C = FqX_sub(FqXQ_mul(FqXQ_sqr(lambda, h, T, p), Edat->RHS, h, T, p), FqX_mulu(x, 2, T, p), T, p); GEN D = FqX_sub(FqXQ_mul(lambda, FqX_sub(x, C, T, p), h, T, p), y, T, p); return gerepilecopy(ltop, mkvec2(C,D)); } } /* Returns the addition of [P[1], P[2]*Y] and of [Q[1], Q[2]*Y] * Computations are done modulo Y^2 - (X^3 + a4X + a6) * An inversion is equivalent to 4M, so that this function requires about 7M * which is the same as with the method using ell-division polynomials * Working in mixed projective coordinates would require 11M */ static GEN eigen_elladd(void *E, GEN P, GEN Q) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN Px, Py, Qx, Qy; GEN T = Edat->T, p = Edat->p, h = Edat->h, lambda, C, D; if (ell_is_inf(P)) return gcopy(Q); if (ell_is_inf(Q)) return gcopy(P); Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (FqX_equal(Px, Qx)) { if (FqX_equal(Py, Qy)) return eigen_elldbl(E, P); else return ellinf(); } lambda = FqXQ_div(FqX_sub(Py, Qy, T, p), FqX_sub(Px, Qx, T, p), h, T, p); C = FqX_sub(FqX_sub(FqXQ_mul(FqXQ_sqr(lambda, h, T, p), Edat->RHS, h, T, p), Px, T, p), Qx, T, p); D = FqX_sub(FqXQ_mul(lambda, FqX_sub(Px, C, T, p), h, T, p), Py, T, p); return gerepilecopy(ltop, mkvec2(C,D)); } static GEN eigenu_elldbl(void *E, GEN P) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN T = Edat->T, h = Edat->h, x, y; long vT = get_Flx_var(T); ulong p = Edat->pp; if (ell_is_inf(P)) return gcopy(P); x = gel(P,1), y = gel(P,2); if (FlxX_equal(x, monomial(pol1_Flx(vT),1,0)) && FlxX_equal(y, monomial(pol1_Flx(vT),0,0))) return Edat->X12; else { GEN t1 = FlxX_Flx_add(FlxX_triple(FlxqXQ_sqr(x,h,T,p),p), Edat->a4, p); GEN t2 = FlxqXQ_mul(FlxX_double(y, p), Edat->RHS, h, T, p); GEN lambda = FlxqXQ_div(t1, t2, h, T, p); GEN C = FlxX_sub(FlxqXQ_mul(FlxqXQ_sqr(lambda, h, T, p), Edat->RHS, h, T, p), FlxX_double(x, p), p); GEN D = FlxX_sub(FlxqXQ_mul(lambda, FlxX_sub(x, C, p), h, T, p), y, p); return gerepilecopy(ltop, mkvec2(C,D)); } } /* Returns the addition of [P[1], P[2]*Y] and of [Q[1], Q[2]*Y] * Computations are done modulo Y^2 - (X^3 + a4X + a6) * An inversion is equivalent to 4M, so that this function requires about 7M * which is the same as with the method using ell-division polynomials * Working in mixed projective coordinates would require 11M */ static GEN eigenu_elladd(void *E, GEN P, GEN Q) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN Px, Py, Qx, Qy; GEN T = Edat->T, h = Edat->h, lambda, C, D; ulong p = Edat->pp; if (ell_is_inf(P)) return gcopy(Q); if (ell_is_inf(Q)) return gcopy(P); Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (FlxX_equal(Px, Qx)) { if (FlxX_equal(Py, Qy)) return eigenu_elldbl(E, P); else return ellinf(); } lambda = FlxqXQ_div(FlxX_sub(Py, Qy, p), FlxX_sub(Px, Qx, p), h, T, p); C = FlxX_sub(FlxX_sub(FlxqXQ_mul(FlxqXQ_sqr(lambda, h, T, p), Edat->RHS, h, T, p), Px, p), Qx, p); D = FlxX_sub(FlxqXQ_mul(lambda, FlxX_sub(Px, C, p), h, T, p), Py, p); return gerepilecopy(ltop, mkvec2(C,D)); } static GEN eigen_ellmulu(struct eigen_ellinit *E, GEN z, ulong n) { pari_sp av = avma; if (!n || ell_is_inf(z)) return mkvec(gen_0); if (n == 1) return gcopy(z); if (E->pp) return gerepileupto(av, gen_powu(z, n, E, &eigenu_elldbl, &eigenu_elladd)); else return gerepileupto(av, gen_powu(z, n, E, &eigen_elldbl, &eigen_elladd)); } /*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)*/ static ulong find_eigen_value(GEN a4, GEN a6, ulong ell, GEN h, GEN T, GEN p, GEN tr) { pari_sp ltop = avma; GEN BP, Dr; ulong t; 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), 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) { pari_sp btop = avma; for (t = 1; t <= (ell>>1); t++) { if (gequal(gel(Dr,2), Edat.Gr)) { avma = ltop; return t; } if (gequal(gel(Dr,2), Edat.nGr)) { avma = ltop; return ell-t; } 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; } } /*Finds the eigenvalue of the Frobenius modulo ell^k given E, ell, k, h factor *of the ell-division polynomial, lambda the previous eigen value and p */ 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; struct eigen_ellinit Edat; GEN BP, Dr, Gr, nGr; /*[0,Gr], BP, Dr are not points on the curve. */ /*To obtain the corresponding points, multiply the y-coordinates by Y */ 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), ZXX_to_FlxX(h, pp, get_FpX_var(T)), ZXT_to_FlxT(T,pp), pp); else init_eigen(&Edat, a4, a6, h, T, p); BP = eigen_ellmulu(&Edat, Edat.O, ellk1); Dr = eigen_ellmulu(&Edat, Edat.O, lambda); Gr = Edat.Gr; nGr = Edat.nGr; btop = avma; st_lim = stack_lim(btop, 1); 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))) Dr = gerepileupto(btop, Dr); } pari_err_BUG("find_eigen_value_power"); return 0; /* NOT REACHED */ } /*Finds the kernel polynomial h, dividing the ell-division polynomial from the 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) { const long ext = 2; pari_sp ltop = avma; GEN M, N, V, K, K1, K2, v, tlist, res; 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++) { 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 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); 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); } 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++) { 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)); } 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); } 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) { 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 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 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)); } /* Finds the isogenous EC, and the sum of the x-coordinates of the points in * the kernel of the isogeny E -> Eb * 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) { pari_sp ltop = avma, btop; GEN Roots, gprime, u1; long k, vx = 0, vJ = MAXVARN; GEN E4 = Fq_div(a4, stoi(-3), T, p); GEN E6 = Fq_mul(a6, shifti(p, -1), 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 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 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); avma = ltop; return NULL; } gprime = Fq_div(a, b, T, p); 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)); } pari_err_BUG("find_isogenous_from_Atkin, kernel not found"); return NULL; } /* Finds E' ell-isogenous to E and the trace term p1 from canonical modular * equation meqn * 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) { pari_sp ltop = avma; long vx = 0, vJ = MAXVARN; GEN h; GEN E4 = Fq_div(a4, stoi(-3), T, p); GEN E6 = Fq_mul(a6, shifti(p, -1), 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 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 DxJg = FqX_deriv(Dxg, T, p); GEN ExJ = FqX_eval(DxJg, j, T, p); ulong tis = ugcd(12, ell-1), is = 12 / tis; 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(dJ)==0) { GEN jl; if (DEBUGLEVEL) err_printf("Division by zero for prime %Ps\n", T, p); 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); 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 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 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); 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); } 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); 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) { 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); } static GEN find_kernel_power(GEN Eba4, GEN Eba6, GEN Eca4, GEN Eca6, ulong ell, struct meqn *MEQN, GEN kpoly, GEN Ib, GEN T, GEN p) { 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 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); btop = avma; for (i = 1; i < l1; i++) { GEN kpoly2, h; 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)))); 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))); return gerepilecopy(ltop, mkvecn(5, a4t, a6t, kpoly_new, gtmp, Ic)); } avma = btop; } pari_err_BUG("failed to find kernel polynomial"); return NULL; /*NOT REACHED*/ } /****************************************************************************/ /* TRACE */ /****************************************************************************/ enum mod_type {MTpathological, MTAtkin, MTElkies, MTone_root, MTroots}; static GEN Flxq_study_eqn(long ell, GEN mpoly, GEN T, ulong p, long *pt_dG, long *pt_r) { GEN Xq = FlxqX_Frobenius(mpoly, T, p); GEN G = FlxqX_gcd(FlxX_sub(Xq, pol_x(0), p), mpoly, T, p); *pt_dG = degpol(G); if (!*pt_dG) { GEN L = FlxqXQ_matrix_pow(Xq, ell+1, ell+1, mpoly, T, p); long vT = get_Flx_var(T); long s = ell + 1 - FlxqM_rank(FlxM_Flx_add_shallow(L, Fl_to_Flx(p-1, vT), p), T, p); *pt_r = (ell + 1)/s; return NULL; } return G; } 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 G = FpX_gcd(FpX_sub(XP, pol_x(0), p), mpoly, p); *pt_dG = degpol(G); if (!*pt_dG) { GEN L = FpXQ_matrix_pow(XP, ell+1, ell+1, mpoly, p); long s = ell + 1 - FpM_rank(RgM_Rg_add_shallow(L, gen_m1), p); *pt_r = (ell + 1)/s; return NULL; } return FpX_oneroot(G, p); } static GEN FpXQ_study_eqn(long ell, GEN mpoly, GEN T, GEN p, long *pt_dG, long *pt_r) { GEN G; if (lgefint(p)==3) { ulong pp = p[2]; GEN Tp = ZXT_to_FlxT(T,pp); GEN mpolyp = ZXX_to_FlxX(mpoly,pp,get_FpX_var(T)); G = Flxq_study_eqn(ell, mpolyp, Tp, pp, pt_dG, pt_r); if (!G) return NULL; G = FlxX_to_ZXX(G); } else { GEN Xq = FpXQX_Frobenius(mpoly, T, p); G = FpXQX_gcd(FpXX_sub(Xq, pol_x(0), p), mpoly, T, p); *pt_dG = degpol(G); if (!*pt_dG) { GEN L = FpXQXQ_matrix_pow(Xq, ell+1, ell+1, mpoly, T, p); long s = ell + 1 - FqM_rank(RgM_Rg_add(L, gen_m1), T, p); *pt_r = (ell + 1)/s; return NULL; } } return gel(FqX_roots(G, T, p), 1); } /* Berlekamp variant */ static GEN study_modular_eqn(long ell, GEN mpoly, GEN T, GEN p, enum mod_type *mt, long *ptr_r) { pari_sp ltop = avma; GEN g = gen_0; *ptr_r = 0; /*gcc -Wall*/ if (degpol(FqX_gcd(mpoly, FqX_deriv(mpoly, T, p), T, p)) > 0) *mt = MTpathological; else { long dG; g = T ? FpXQ_study_eqn(ell, mpoly, T, p, &dG, ptr_r) : Fp_study_eqn(ell, mpoly, p, &dG, ptr_r); switch(dG) { case 0: *mt = MTAtkin; break; case 1: *mt = MTone_root; break; case 2: *mt = MTElkies; break; default: *mt = (dG == ell + 1)? MTroots: MTpathological; } } if (DEBUGLEVEL) switch(*mt) { case MTone_root: err_printf("One root\t"); break; case MTElkies: err_printf("Elkies\t"); break; case MTroots: err_printf("l+1 roots\t"); break; case MTAtkin: err_printf("Atkin\t"); break; case MTpathological: err_printf("Pathological\n"); break; } return g ? gerepilecopy(ltop, g): NULL; } /*Returns the trace modulo ell^k when ell is an Elkies prime */ 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; GEN tmp, Eba4, Eba6, Eca4, Eca6, Ib, kpoly; ulong lambda, ellk = upowuu(ell, k), pellk = umodiu(q, ellk); long cnt; if (DEBUGLEVEL) { err_printf("Trace mod %ld", ell); } Eba4 = a4; Eba6 = a6; tmp = find_isogenous(a4,a6, ell, MEQN, g, T, p); if (!tmp) { avma = ltop; return NULL; } Eca4 = gel(tmp, 1); Eca6 = gel(tmp, 2); kpoly = gel(tmp, 3); Ib = pol_x(0); lambda = find_eigen_value(a4, a6, ell, kpoly, T, p, tr); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(ti)); if (smallfact && ell>smallfact) { ulong pell = pellk%ell; 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); for (cnt = 2; cnt <= k; cnt++) { GEN tmp; if (DEBUGLEVEL) err_printf(", %Ps", powuu(ell, cnt)); tmp = find_kernel_power(Eba4, Eba6, Eca4, Eca6, ell, MEQN, kpoly, Ib, T, p); if (!tmp) { avma = ltop; return NULL; } lambda = find_eigen_value_power(a4, a6, ell, cnt, gel(tmp,3), lambda, T, p); Eba4 = Eca4; Eba6 = Eca6; Eca4 = gel(tmp,1); Eca6 = gel(tmp,2); kpoly = gel(tmp,4); Ib = gel(tmp, 5); if (low_stack(st_lim, stack_lim(btop, 1))) gerepileall(btop, 6, &Eba4, &Eba6, &Eca4, &Eca6, &kpoly, &Ib); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(ti)); } avma = ltop; return mkvecsmall(Fl_add(lambda, Fl_div(pellk, lambda, ellk), ellk)); } /*Returns the possible values of the trace when ell is an Atkin prime, */ /*given r the splitting degree of the modular equation at J = E.j */ static GEN find_trace_Atkin(ulong ell, long r, GEN q) { pari_sp ltop = avma; long nval = 0; ulong teta, pell = umodiu(q, ell), invp = Fl_inv(pell, ell); GEN val_pos = cgetg(1+ell, t_VECSMALL), P = gel(factoru(r), 1); GEN S = mkvecsmall4(0, pell, 0, 1); GEN U = mkvecsmall3(0, ell-1, 0); pari_sp btop = avma; if (r==2 && krouu(ell-pell, ell) < 0) val_pos[++nval] = 0; for (teta = 1; teta < ell; teta++, avma = btop) { ulong disc = Fl_sub(Fl_sqr(teta,ell), Fl_mul(4UL,pell,ell), ell); GEN a; if (krouu(disc, ell) >= 0) continue; S[3] = Fl_neg(teta, ell); U[3] = Fl_mul(invp, teta, ell); a = Flxq_powu(U, r/P[1], S, ell); if (!Flx_equal1(a) && Flx_equal1(Flxq_powu(a, P[1], S, ell))) { pari_sp av = avma; long i, l=lg(P); for (i = 2; i < l; i++, avma = av) if (Flx_equal1(Flxq_powu(U, r/P[i], S, ell))) break; if (i==l) val_pos[++nval] = teta; } } return gerepileupto(ltop, vecsmall_shorten(val_pos, nval)); } /*Returns the possible traces when there is only one root */ static GEN find_trace_one_root(ulong ell, GEN q) { ulong a = Fl_double(Fl_sqrt(umodiu(q,ell), ell), ell); return mkvecsmall2(a, ell - a); } static GEN find_trace_lp1_roots(long ell, GEN q) { ulong ell2 = ell * ell, pell = umodiu(q, ell2); ulong a = Fl_sqrt(pell%ell, ell); ulong pa = Fl_add(Fl_div(pell, a, ell2), a, ell2); return mkvecsmall2(pa, ell2 - pa); } /*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) { pari_sp ltop = avma; GEN g, meqnj, tr, tr2; long k = 1, kt, r; enum mod_type mt; struct meqn MEQN; pari_timer ti; if (ell <= 13) { long lp = expi(q); switch(ell) { case 3: k = 3 + (lp > 160) + (lp > 350); break; case 5: k = 2 + (lp > 260); break; case 7: k = 2 + (lp > 390); break; default:k = 1 + (lp > 260); } } kt = k; if (!get_modular_eqn(&MEQN, ell, 0, MAXVARN)) 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); 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 * computing modulo this factor */ switch (mt) { case MTone_root: tr2 = find_trace_one_root(ell, q); kt = k = 1; /* Must take k = 1 because we can't apply Hensel: no guarantee that a * root mod ell^2 exists */ tr = find_trace_Elkies_power(a4,a6,ell, k, &MEQN, g, tr2, q, T, p, smallfact, &ti); if (!tr) tr = tr2; break; case MTElkies: /* Contrary to MTone_root, may look mod higher powers of ell */ tr = find_trace_Elkies_power(a4,a6,ell, k, &MEQN, g, NULL, q, T, p, smallfact, &ti); if (!tr) { avma = ltop; return NULL; } break; case MTroots: tr = find_trace_lp1_roots(ell, q); kt = 2; break; case MTAtkin: tr = find_trace_Atkin(ell, r, q); if (lg(tr)==1) pari_err_PRIME("ellsea",p); kt = 1; break; default: /* case MTpathological: */ avma = ltop; return NULL; } if (DEBUGLEVEL) { long n = lg(tr)-1; if (n > 1 || mt == MTAtkin) { err_printf("%3ld trace(s)",n); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(&ti)); } err_printf("\n"); } *ptr_kt = kt; return gerepileupto(ltop, tr); } /* A partition of compile_atkin in baby and giant is represented as the binary developpement of an integer; if the i-th bit is 1, the i-th prime in compile-atkin is a baby. The optimum is obtained when the ratio between the number of possibilities for traces modulo giants (p_g) and babies (p_b) is near 3/4. */ static long separation(GEN cnt) { pari_sp btop, st_lim; long k = lg(cnt)-1, l = (1L<=0) continue; res = mkvec2(utoi(B[i]), b); } return gerepilecopy(ltop, res); } static GEN compute_diff(GEN v) { pari_sp av = avma; long i, l = lg(v) - 1; GEN diff = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(diff, i) = subii(gel(v, i+1), gel(v, i)); return gerepileupto(av, ZV_sort_uniq(diff)); } static int cmp_atkin(void*E, GEN a, GEN b) { long ta=typ(a)==t_INT, tb=typ(b)==t_INT, c; (void) E; if (ta || tb) return ta-tb; c = lg(gel(a,2)) - lg(gel(b,2)); if (c) return c; return cmpii(gel(b,1), gel(a,1)); } static void add_atkin(GEN atkin, GEN trace, long *nb) { long l = lg(atkin)-1; long i, k = gen_search(atkin, trace, 1, NULL, cmp_atkin); if (k==0 || k > l) return; for (i = l; i > k; i--) gel(atkin,i) = gel(atkin,i-1); if (typ(gel(atkin,l))==t_INT) (*nb)++; gel(atkin,k) = trace; } /* V = baby / giant, P = Pb / Pg */ static GEN BSGS_pre(GEN *pdiff, GEN V, GEN P, void *E, const struct bb_group *grp) { GEN diff = compute_diff(V); GEN pre = cgetg(lg(diff), t_VEC); long i, l = lg(diff); gel(pre, 1) = grp->pow(E, P, gel(diff, 1)); /* what we'd _really_ want here is a hashtable diff[i] -> pre[i] */ for (i = 2; i < l; i++) { pari_sp av = avma; GEN d = subii(gel(diff, i), gel(diff, i-1)); GEN Q = grp->mul(E, gel(pre, i-1), grp->pow(E, P, d)); gel(pre, i) = gerepilecopy(av, Q); } *pdiff = diff; return pre; } /* u = trace_elkies, Mu = prod_elkies. Let caller collect garbage */ /* Match & sort: variant from Lercier's thesis, section 11.2.3 */ /* baby/giant/table updated in place: this routines uses * size(baby)+size(giant)+size(table)+size(table_ind) + O(log p) * bits of stack */ 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; 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; 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); 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++) { GEN t = Z_chinese_post(u, stoi(r2[i]), C, U, NULL); gel(card, i) = subii(pp1, Fp_center(t, C, Cs2)); } return gen_select_order(card, E, grp); } if (DEBUGLEVEL>=2) timer_start(&ti); av1 = avma; best_i = separation( get_lgatkin(compile_atkin, k) ); avma = av1; baby = possible_traces(compile_atkin, stoi(best_i), &Mb, 1); giant = possible_traces(compile_atkin, subis(int2n(k), best_i+1), &Mg, 0); lbaby = lg(baby); lgiant = lg(giant); den = Fp_inv(Fp_mul(Mu, Mb, Mg), Mg); av2 = avma; for (i = 1; i < lgiant; i++, avma = av2) affii(Fp_mul(gel(giant,i), den, Mg), gel(giant,i)); gen_sort_inplace(giant, (void*)&cmpii, &cmp_nodata, NULL); Sg = Fp_mul(negi(u), den, Mg); den = Fp_inv(Fp_mul(Mu, Mg, Mb), Mb); dec_inf = divii(mulii(Mb,addii(Mg,shifti(Sg,1))), shifti(Mg,1)); togglesign(dec_inf); /* now, dec_inf = ceil(- (Mb/2 + Sg Mb/Mg) ) */ div = mulii(truedivii(dec_inf, Mb), Mb); av2 = avma; for (i = 1; i < lbaby; i++, avma = av2) { GEN b = addii(Fp_mul(Fp_sub(gel(baby,i), u, Mb), den, Mb), div); if (cmpii(b, dec_inf) < 0) b = addii(b, Mb); affii(b, gel(baby,i)); } gen_sort_inplace(baby, (void*)&cmpii, &cmp_nodata, NULL); SgMb = mulii(Sg, Mb); P = grp->rand(E); point = grp->pow(E,P, Mu); Pb = grp->pow(E,point, Mg); Pg = grp->pow(E,point, Mb); /* Precomputation for babies */ pre = BSGS_pre(&diff, baby, Pb, E, grp); /*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); /* (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)); for (i = 2; i < lbaby; i++) { 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(DEBUGMEM>1) pari_warn(warnmem,"match_and_sort, baby = %ld", i); point = gerepileupto(av1, point); } } avma = av1; /* Precomputations for giants */ pre = BSGS_pre(&diff, giant, Pg, E, grp); /* Look for a collision among the x-coordinates */ table_ind = vecsmall_indexsort(table); table = perm_mul(table,table_ind); av1 = avma; lim = stack_lim(av1,3); point = grp->pow(E, Pg, gel(giant, 1)); for (i = 1; ; i++) { GEN d; long h = grp->hash(gel(point, 1)); long s = zv_search(table, h); if (s) { while (table[s] == h && s) s--; for (s++; s < lbaby && table[s] == h; s++) { GEN B = gel(baby,table_ind[s]), G = gel(giant,i); GEN GMb = mulii(G, Mb), BMg = mulii(B, Mg); GEN Be = subii(subii(pp1, u), mulii(Mu, addii(SgMb, BMg))); GEN Bp = grp->pow(E,P, Be); /* 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))); if (DEBUGLEVEL>=2) timer_printf(&ti,"match_and_sort"); return gen_select_order(card, E, grp); } } } 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(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 */ } static GEN get_bound_bsgs(long lp) { GEN B; if (lp <= 160) B = divru(powru(dbltor(1.048), lp), 9); else if (lp <= 192) B = divrr(powru(dbltor(1.052), lp), dbltor(16.65)); else B = mulrr(powru(dbltor(1.035), minss(lp,307)), dbltor(1.35)); return mulru(B, 1000000); } /*FIXME: the name of the function does not quite match what it does*/ static const struct bb_group * 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); } return get_FpXQE_group(pt_E,a4,a6,T,p); } /* E is an elliptic curve defined over Z or over Fp in ellinit format, defined * by the equation E: y^2 + a1*x*y + a2*y = x^3 + a2*x^2 + a4*x + a6 * p is a prime number * set smallfact to stop whenever a small factor > smallfact of the order is * detected. Useful when searching for a good curve for cryptographic * applications */ 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; GEN TR, TR_mod, compile_atkin, bound, bound_bsgs, champ; GEN prod_atkin = gen_1, max_traces = gen_0; 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); } /*First compute the trace modulo 2 */ switch(FqX_nbroots(mkpoln(4, gen_1, gen_0, a4, a6), T, p)) { case 3: /* bonus time: 4 | #E(Fq) = q+1 - t */ i = mod4(q)+1; if (i > 2) i -= 4; TR_mod = utoipos(4); TR = stoi(i); break; case 1: TR_mod = gen_2; TR = gen_0; break; default : /* 0 */ TR_mod = gen_2; TR = gen_1; break; } if (smallfact == 1 && !mpodd(TR)) { if (DEBUGLEVEL) err_printf("Aborting: #E(Fq) divisible by 2\n"); avma = ltop; return gen_0; } /* compile_atkin is a vector containing informations about Atkin primes, * informations about Elkies primes lie in Mod(TR, TR_mod). */ u_forprime_init(&TT, 3, 1000); /* way beyond what seadata provides */ 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); 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 (!trace_mod) continue; nbtrace = lg(trace_mod) - 1; ellkt = (long)upowuu(ell, kt); if (nbtrace == 1) { long t_mod_ellkt = trace_mod[1]; if (smallfact && ell > smallfact) { /* does ell divide q + 1 - t ? */ long card_mod_ell = (umodiu(q,ell) + 1 - t_mod_ellkt) % ell ; if (!card_mod_ell) { if (DEBUGLEVEL) err_printf("\nAborting: #E(Fq) divisible by %ld\n",ell); avma = ltop; return gen_0; } } (void)Z_incremental_CRT(&TR, t_mod_ellkt, &TR_mod, ellkt); } else { add_atkin(compile_atkin, mkvec2(utoipos(ellkt), trace_mod), &nb_atkin); prod_atkin = value(-1, compile_atkin, nb_atkin); } if (cmpii(mulii(TR_mod, prod_atkin), bound) > 0) { GEN bound_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)) { max_traces = divis(muliu(max_traces,nbtrace), ellkt); if (DEBUGLEVEL>=3) err_printf("At least %Ps remaining possibilities.\n",max_traces); } if (cmpir(max_traces, bound_tr) < 0) { GEN bound_atkin = truedivii(bound, TR_mod); champ = champion(compile_atkin, nb_atkin, bound_atkin); max_traces = gel(champ,2); if (DEBUGLEVEL>=2) err_printf("%Ps remaining possibilities.\n", max_traces); if (cmpir(max_traces, bound_tr) < 0) { GEN res, cat = shallowextract(compile_atkin, gel(champ,1)); const struct bb_group *grp; if (DEBUGLEVEL) err_printf("Match and sort for %Ps possibilities.\n", max_traces); grp = get_FqE_group(&E,a4,a6,T,p); res = match_and_sort(cat, TR_mod, TR, q, E, grp); return gerepileuptoint(ltop, res); } } } if (low_stack(st_lim, stack_lim(btop, 1))) gerepileall(btop,5, &TR,&TR_mod, &compile_atkin, &max_traces, &prod_atkin); } return NULL;/*not reached*/ } GEN Fp_ellcard_SEA(GEN a4, GEN a6, GEN p, long smallfact) { return Fq_ellcard_SEA(a4, a6, p, NULL, p, smallfact); } GEN ellsea(GEN E, GEN p, long smallfact) { pari_sp av = avma; GEN a4 = modii(mulis(Rg_to_Fp(gel(E,10), p), -27), p); GEN a6 = modii(mulis(Rg_to_Fp(gel(E,11), p), -54), p); GEN card = Fp_ellcard_SEA(a4, a6, p, smallfact); if (!card) pari_err_PACKAGE("seadata"); return gerepileuptoint(av, subii(addis(p,1),card)); } pari-2.7.5/src/modules/mpqs.c0000644000175000017500000034710012405547147014507 0ustar billbill/* 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. */ /* Written by Thomas Papanikolaou and Xavier Roblot * * Implementation of the Self-Initializing Multi-Polynomial Quadratic Sieve * based on code developed as part of the LiDIA project * (http://www.informatik.tu-darmstadt.de/TI/LiDIA/) * * Extensively modified by The PARI group. */ /* Notation commonly used in this file, and sketch of algorithm: * * Given an odd integer N > 1 to be factored, we throw in a small odd and * squarefree multiplier k so as to make kN congruent 1 mod 4 and to have * many small primes over which X^2 - kN splits. We compute a factor base * FB of such primes, and then essentially look for values x0 such that * Q0(x0) = x0^2 - kN can be decomposed over this factor base, up to a * possible factor dividing k and a possible "large prime". Relations * involving the latter can be combined into full relations (working mod N * now) which don't, and full relations, by Gaussian elimination over the * 2-element field for the exponent vectors, will finally lead us to an * expression X^2 - Y^2 divisible by N and hopefully to a nontrivial * splitting when we compute gcd(X +- Y, N). Note that this can never * split prime powers. (Any odd prime dividing the X - Y factor, say, will * divide it to the same power as it divides N.) * * Candidates x0 are found by sieving along arithmetic progressions modulo * the small primes in the factor base, and evaluation of candidates picks * out those x0 where many of these APs happen to coincide, resulting in a * highly divisible Q0(x0). * * The Multi-Polynomial version improves this by choosing a modest subset of * factor base primes and forcing these to divide Q0(x). Let A be the product * of the chosen primes, and write Q(x) = Q0(2Ax + B) = (2Ax + B)^2 - kN = * 4A(Ax^2 + Bx + C), where B has been suitably chosen. For each A, there * are 2^omega_A possible values for B when A is the product of omega_A * distinct primes, but we'll use only half of these, since the other half * is more easily covered by exploiting the symmetry x <-> -x of the original * quadratic. The "Self-Initializating" bit refers to the fact that switching * from one B to the next can be done very fast, whereas switching to the * next A involves some recomputation from scratch. (C is never needed * explicitly except for debug diagnostics.) Thus we can very quickly run * through an entire "cohort" of polynomials sharing the same A. * * The sieve now ranges over values x0 such that |x0| < M (we use x = x0 + M * as the non-negative array subscript). The coefficients A are chosen so * that A*M is approximately sqrt(kN). Then |B| will be bounded by about * (j+4)*A, and |C| = -C will be about (M/4)*sqrt(kN), so Q(x0)/(4A) will * take values roughly between -|C| and 3|C|. * * There are numerous refinements to this basic outline (e.g. it is more * efficient to _not_ use the very smallest primes in the FB for sieving, * incorporating them only after selecting candidates). The substition of * 2Ax+B into X^2 - kN, with odd B, forces 2 to occur; when kN is 1 mod 8, * it will always occur at least to the 3rd power; when kN = 5 mod 8, it * will always occur exactly to the 2nd power. We never sieve on 2 and we * always pull out the power of 2 directly (which is easy, of course). * The prime factor(s) of k will show up whenever 2Ax + B has a factor in * common with k; we don't sieve on these either but can easily recognize * them in a candidate. */ #include "pari.h" #include "paripriv.h" static char * paristrtok_r(char *str, const char *delim, char **saveptr) { char *res; if (!str) str = *saveptr; str += strspn(str, delim); if (!*str) return NULL; res = str; str += strcspn(str, delim); if (*str) *str++ = 0; *saveptr = str; return res; } /** DEBUG **/ /* #define MPQS_DEBUG_VERBOSE 1 */ /* histograms are pretty, but don't help performance after all (see below) */ /* #define MPQS_USE_HISTOGRAMS */ #include "mpqs.h" /*********************************************************************/ /** **/ /** INITIAL SIZING **/ /** **/ /*********************************************************************/ /* number of decimal digits of argument - for parameter choosing and for * diagnostics */ static long decimal_len(GEN N) { pari_sp av = avma; long d = strlen(itostr(N)); avma = av; return d; } /* To be called after choosing k and putting kN into the handle: * Pick up the requested parameter set for the given size of kN in decimal * digits and fill in various fields in the handle. Return 0 when kN is * too large, 1 when we're ok. */ static int mpqs_set_parameters(mpqs_handle_t *h) { long i; const mpqs_parameterset_t *P; double mb; h->digit_size_kN = decimal_len(h->kN); if (h->digit_size_kN <= 9) i = 0; else if (h->digit_size_kN > MPQS_MAX_DIGIT_SIZE_KN) return 0; else i = h->digit_size_kN - 9; /* (cf PARI bug#235) the following has always been, and will remain, * a moving target... increased thresholds from 64, 80 to 79, 86 * respectively --GN20050601. Note that the new values correspond to * kN having >= 86 or >= 95 decimal digits, respectively. Note also * that the current sizing parameters for 90 or more digits are based * on 100% theory and 0% practice. */ if (i >= 79) pari_warn(warner, "MPQS: factoring this number will take %s hours:\nN = %Ps", i >= 86 ? "many": "several", h->N); if (DEBUGLEVEL >= 5) { err_printf("MPQS: kN = %Ps\n", h->kN); err_printf("MPQS: kN has %ld decimal digits\n", h->digit_size_kN); } P = &(mpqs_parameters[i]); h->tolerance = P->tolerance; h->lp_scale = P->lp_scale; /* make room for prime factors of k if any: */ h->size_of_FB = P->size_of_FB + h->_k->omega_k; /* for the purpose of Gauss elimination etc., prime factors of k behave * like real FB primes, so take them into account when setting the goal: */ h->target_no_rels = (h->size_of_FB >= 200 ? h->size_of_FB + 70 : (mpqs_int32_t)(h->size_of_FB * 1.35)); h->M = P->M; h->omega_A = P->omega_A; h->no_B = 1UL << (P->omega_A - 1); h->pmin_index1 = P->pmin_index1; /* certain subscripts into h->FB should also be offset by omega_k: */ h->index0_FB = 3 + h->_k->omega_k; /* following are converted from % to parts per thousand: */ h->first_sort_point = 10 * P->first_sort_point; h->sort_pt_interval = 10 * P->sort_pt_interval; mb = (h->size_of_FB + 1)/(8.*1048576.) * h->target_no_rels; if (mb > 128.) { pari_warn(warner, "MPQS: Gauss elimination will require more than\n\t128MBy of memory"); if (DEBUGLEVEL >= 1) err_printf("\t(estimated memory needed: %4.1fMBy)\n", mb); } return 1; } /*********************************************************************/ /** **/ /** OBJECT HOUSEKEEPING **/ /** **/ /*********************************************************************/ /* The sub-constructors for the pieces of the handle will be called in the * same order as their appearance here, and the later ones in part rely on * the earlier ones having filled in some fields. * There's a single destructor to handle all cleanup at the end (except * for mpqs() itself resetting avma). */ /* main handle constructor */ static mpqs_handle_t * mpqs_handle_ctor(GEN N) { mpqs_handle_t *h = (mpqs_handle_t *) pari_calloc(sizeof(mpqs_handle_t)); h->N = N; #ifdef MPQS_DEBUG_VERBOSE err_printf("MPQS DEBUG: created handle @0x%p\n", (void *)h); #endif return h; } /* factor base constructor. Really a home-grown memalign(3c) underneath. * We don't want FB entries to straddle L1 cache line boundaries, and * malloc(3c) only guarantees alignment adequate for all primitive data * types of the platform ABI - typically to 8 or 16 byte boundaries. * Also allocate the inv_A_H array. * The FB array pointer is returned for convenience */ static mpqs_FB_entry_t * mpqs_FB_ctor(mpqs_handle_t *h) { /* leave room for slots 0, 1, and sentinel slot at the end of the array */ long size_FB_chunk = (h->size_of_FB + 3) * sizeof(mpqs_FB_entry_t); /* like FB, except this one does not have a sentinel slot at the end */ long size_IAH_chunk = (h->size_of_FB + 2) * sizeof(mpqs_inv_A_H_t); char *fbp = (char*)pari_malloc(size_FB_chunk + 64); char *iahp = (char*)pari_malloc(size_IAH_chunk + 64); long fbl, iahl; h->FB_chunk = (void *)fbp; h->invAH_chunk = (void *)iahp; /* round up to next higher 64-bytes-aligned address */ fbl = (((long)fbp) + 64) & ~0x3FL; /* and put the actual array there */ h->FB = (mpqs_FB_entry_t *)fbl; iahl = (((long)iahp) + 64) & ~0x3FL; h->inv_A_H = (mpqs_inv_A_H_t *)iahl; return (mpqs_FB_entry_t *)fbl; } /* sieve array constructor; also allocates the candidates array, the * histograms, and temporary storage for relations under construction */ static void mpqs_sieve_array_ctor(mpqs_handle_t *h) { long size = (h->M << 1) + 1; mpqs_int32_t size_of_FB = h->size_of_FB; h->sieve_array = (unsigned char *) pari_malloc(size * sizeof(unsigned char)); h->sieve_array_end = h->sieve_array + size - 2; h->sieve_array_end[1] = 255; /* sentinel */ h->candidates = (long *)pari_malloc(MPQS_CANDIDATE_ARRAY_SIZE * sizeof(long)); /* Room needed for string representation of a relation - worst case: * + leading " 1 1" * + trailing " 0\n" with final NUL character * + in between up to size_of_FB pairs each consisting of an exponent, a * subscript into FB, and two spaces. * Subscripts into FB fit into 5 digits, and exponents fit into 3 digits * with room to spare -- anything needing 3 or more digits for the * subscript must come with an exponent of at most 2 digits. Moreover the * product of the first 58 primes is larger than 10^110 (and the righthand * sides of proto-relations are much smaller than kN: on the order of * M*sqrt(kN)), so there cannot be more than 60 pairs in all, even if * size_of_FB > 10^5. --GN */ /* whereas mpqs_self_init() uses size_of_FB+1, we just use the size as * it is, not counting FB[1], to start off the following estimate */ if (size_of_FB > 60) size_of_FB = 60; h->relations = (char *) pari_malloc((8 + size_of_FB * 9) * sizeof(char)); /* and for tracking which primes occur in the current relation: */ h->relaprimes = (long *) pari_malloc((size_of_FB << 1) * sizeof(long)); #ifdef MPQS_USE_HISTOGRAMS /* histograms to be used only when kN isn't very small */ if (h->size_of_FB > MPQS_MIN_SIZE_FB_FOR_HISTO) { h->do_histograms = 1; h->histo_full = (long *) pari_calloc(128 * sizeof(long)); h->histo_lprl = (long *) pari_calloc(128 * sizeof(long)); h->histo_drop = (long *) pari_calloc(128 * sizeof(long)); } #endif } /* mpqs() calls the following (after recording avma) to allocate GENs for * the current polynomial and self-initialization scratchpad data on the * PARI stack. This space is released by mpqs() itself at the end. */ static void mpqs_poly_ctor(mpqs_handle_t *h) { mpqs_int32_t i; long size_per = h->omega_A * sizeof(mpqs_per_A_prime_t); h->per_A_pr = (mpqs_per_A_prime_t *) pari_calloc(size_per); /* Sizing: A is the product of omega_A primes, each well below word * size. * |B| is bounded by (omega_A + 4) * A, so can have at most one word * more, and that's generous. * |C| is less than A*M^2, so can take at most two words more than A. * The array H holds residues modulo A, so the same size as used for A * is sufficient. */ h->A = cgeti(h->omega_A + 2); h->B = cgeti(h->omega_A + 3); #ifdef MPQS_DEBUG h->C = cgeti(h->omega_A + 4); #endif for (i = 0; i < h->omega_A; i++) h->per_A_pr[i]._H = cgeti(h->omega_A + 2); /* the handle starts out all zero, so in particular bin_index and index_i * are initially 0. * TODO: index_j currently initialized in mqps() but this is going to * change. */ } /* main handle destructor, also cleans up all other allocated pieces * (except for stuff created on the PARI stack which the caller should * deal with by resetting avma) */ static void mpqs_handle_dtor(mpqs_handle_t *h) { #define myfree(x) if(x) pari_free((void*)x) myfree((h->per_A_pr)); myfree((h->relaprimes)); myfree(h->relations); #ifdef MPQS_USE_HISTOGRAMS myfree((h->histo_drop)); myfree((h->histo_lprl)); myfree((h->histo_full)); #endif myfree((h->candidates)); myfree((h->sieve_array)); myfree((h->invAH_chunk)); myfree((h->FB_chunk)); myfree(h); } /* TODO: relationsdb handle */ /*********************************************************************/ /** **/ /** FACTOR BASE SETUP **/ /** **/ /*********************************************************************/ /* fill in the best-guess multiplier k for N. We force kN = 1 mod 4. * Caller should proceed to fill in kN */ static ulong mpqs_find_k(mpqs_handle_t *h) { const pari_sp av = avma; const long N_mod_8 = mod8(h->N), N_mod_4 = N_mod_8 & 3; forprime_t S; struct { const mpqs_multiplier_t *_k; long np; /* number of primes in factorbase so far for this k */ double value; /* the larger, the better */ } cache[MPQS_POSSIBLE_MULTIPLIERS]; ulong p, i, j, nbk = MPQS_POSSIBLE_MULTIPLIERS; for (i = j = 0; i < sizeof(cand_multipliers)/sizeof(mpqs_multiplier_t); i++) { const mpqs_multiplier_t *cand_k = &cand_multipliers[i]; long k = cand_k->k; double v; if ((k & 3) != N_mod_4) continue; /* want kN = 1 (mod 4) */ v = -0.35 * log2((double)k); if ((k & 7) == N_mod_8) v += LOG2; /* kN = 1 (mod 8) */ cache[j].np = 0; cache[j]._k = cand_k; cache[j].value = v; if (++j == nbk) break; /* enough */ } nbk = j; u_forprime_init(&S, 2, ULONG_MAX); while ( (p = u_forprime_next(&S)) ) { ulong Np = umodiu(h->N, p); long kroNp, seen = 0; if (!Np) return p; kroNp = krouu(Np, p); for (i = 0; i < nbk; i++) { if (cache[i].np > MPQS_MULTIPLIER_SEARCH_DEPTH) continue; seen++; if (krouu(cache[i]._k->k % p, p) == kroNp) /* kronecker(k*N, p)=1 */ { cache[i].value += log2((double) p)/p; cache[i].np++; } } if (!seen) break; /* we're gone through SEARCH_DEPTH primes for all k */ } if (!p) pari_err_OVERFLOW("mpqs_find_k [ran out of primes]"); { long best_i = 0; double v = cache[0].value; for (i = 1; i < nbk; i++) if (cache[i].value > v) { best_i = i; v = cache[i].value; } h->_k = cache[best_i]._k; avma = av; return 0; } } /******************************/ /* Create a factor base of 'size' primes p_i such that legendre(k*N, p_i) != -1 * We could have shifted subscripts down from their historical arrangement, * but this seems too risky for the tiny potential gain in memory economy. * The real constraint is that the subscripts of anything which later shows * up at the Gauss stage must be nonnegative, because the exponent vectors * there use the same subscripts to refer to the same FB entries. Thus in * particular, the entry representing -1 could be put into FB[0], but could * not be moved to FB[-1] (although mpqs_FB_ctor() could be easily adapted * to support negative subscripts).-- The historically grown layout is: * FB[0] is unused. * FB[1] is not explicitly used but stands for -1. * FB[2] contains 2 (always). * Before we are called, the size_of_FB field in the handle will already have * been adjusted by _k->omega_k, so there's room for the primes dividing k, * which when present will occupy FB[3] and following. * The "real" odd FB primes begin at FB[h->index0_FB]. * FB[size_of_FB+1] is the last prime p_i. * FB[size_of_FB+2] is a sentinel to simplify some of our loops. * Thus we allocate size_of_FB+3 slots for FB. * * If a prime factor of N is found during the construction, it is returned * in f, otherwise f = 0. */ /* returns the FB array pointer for convenience */ static mpqs_FB_entry_t * mpqs_create_FB(mpqs_handle_t *h, ulong *f) { const pari_sp av = avma; mpqs_int32_t size = h->size_of_FB; long i; mpqs_uint32_t k = h->_k->k; mpqs_FB_entry_t *FB; forprime_t S; FB = mpqs_FB_ctor(h); FB[2].fbe_p = 2; /* the fbe_logval and the fbe_sqrt_kN for 2 are never used */ FB[2].fbe_flags = MPQS_FBE_CLEAR; (void)u_forprime_init(&S, 3, ULONG_MAX); /* the first loop executes h->_k->omega_k = 0, 1, or 2 times */ for (i = 3; i < h->index0_FB; i++) { mpqs_uint32_t kp = (ulong)h->_k->kp[i-3]; if (MPQS_DEBUGLEVEL >= 7) err_printf(",<%lu>", (ulong)kp); FB[i].fbe_p = kp; /* we *could* flag divisors of k here, but so far I see no need, * and no flags bit has been assigned for the purpose */ FB[i].fbe_flags = MPQS_FBE_CLEAR; FB[i].fbe_flogp = (float) log2((double) kp); FB[i].fbe_sqrt_kN = 0; } /* now i == h->index0_FB */ while (i < size + 2) { ulong p = u_forprime_next(&S); if (p > k || k % p) { ulong kN_mod_p = umodiu(h->kN, p); long kr = krouu(kN_mod_p, p); if (kr != -1) { if (kr == 0) { *f = p; return FB; } FB[i].fbe_p = (mpqs_uint32_t) p; FB[i].fbe_flags = MPQS_FBE_CLEAR; /* dyadic logarithm of p; single precision suffices */ FB[i].fbe_flogp = (float) log2((double)p); /* cannot yet fill in fbe_logval because the scaling multiplier * depends on the largest prime in FB, as yet unknown */ /* x such that x^2 = kN (mod p_i) */ FB[i++].fbe_sqrt_kN = (mpqs_uint32_t)Fl_sqrt(kN_mod_p, p); } } } avma = av; if (MPQS_DEBUGLEVEL >= 7) { err_printf("MPQS: FB [-1,2"); for (i = 3; i < h->index0_FB; i++) err_printf(",<%lu>", FB[i].fbe_p); for (; i < size + 2; i++) err_printf(",%lu", FB[i].fbe_p); err_printf("]\n"); } FB[i].fbe_p = 0; /* sentinel */ h->largest_FB_p = FB[i-1].fbe_p; /* at subscript size_of_FB + 1 */ /* locate the smallest prime that will be used for sieving */ for (i = h->index0_FB; FB[i].fbe_p != 0; i++) if (FB[i].fbe_p >= h->pmin_index1) break; h->index1_FB = i; /* with our parameters this will never fall of the end of the FB */ *f = 0; return FB; } /*********************************************************************/ /** **/ /** MISC HELPER FUNCTIONS **/ /** **/ /*********************************************************************/ /* Effect of the following: multiplying the base-2 logarithm of some * quantity by log_multiplier will rescale something of size * log2 ( sqrt(kN) * M / (largest_FB_prime)^tolerance ) * to 232. Note that sqrt(kN) * M is just A*M^2, the value our polynomials * take at the outer edges of the sieve interval. The scale here leaves * a little wiggle room for accumulated rounding errors from the approximate * byte-sized scaled logarithms for the factor base primes which we add up * in the sieving phase.-- The threshold is then chosen so that a point in * the sieve has to reach a result which, under the same scaling, represents * log2 ( sqrt(kN) * M / (largest_FB_prime)^tolerance ) * in order to be accepted as a candidate. */ /* The old formula was... * log_multiplier = * 127.0 / (0.5 * log2 (handle->dkN) * + log2((double)M) * - tolerance * log2((double)handle->largest_FB_p) * ); * and we used to use this with a constant threshold of 128. */ /* NOTE: We used to divide log_multiplier by an extra factor 2, and in * compensation we were multiplying by 2 when the fbe_logp fields were being * filled in, making all those bytes even. Tradeoff: the extra bit of * precision is helpful, but interferes with a possible sieving optimization * (artifically shift right the logp's of primes in A, and just run over both * arithmetical progressions (which coincide in this case) instead of * skipping the second one, to avoid the conditional branch in the * mpqs_sieve() loops). We could still do this, but might lose a little bit * accuracy for those primes. Probably no big deal. */ static void mpqs_set_sieve_threshold(mpqs_handle_t *h) { mpqs_FB_entry_t *FB = h->FB; long i; double log_maxval; double log_multiplier; h->l2sqrtkN = 0.5 * log2(h->dkN); h->l2M = log2((double)h->M); log_maxval = h->l2sqrtkN + h->l2M - MPQS_A_FUDGE; log_multiplier = 232.0 / log_maxval; h->sieve_threshold = (unsigned char) (log_multiplier * (log_maxval - h->tolerance * log2((double)h->largest_FB_p) ) ) + 1; /* That "+ 1" really helps - we may want to tune towards somewhat smaller * tolerances (or introduce self-tuning one day)... */ /* If this turns out to be <128, scream loudly. * That means that the FB or the tolerance or both are way too * large for the size of kN. (Normally, the threshold should end * up in the 150...170 range.) */ if (h->sieve_threshold < 128) { h->sieve_threshold = 128; pari_warn(warner, "MPQS: sizing out of tune, FB size or tolerance\n\ttoo large"); } /* Now fill in the byte-sized approximate scaled logarithms of p_i */ if (DEBUGLEVEL >= 5) { err_printf("MPQS: computing logarithm approximations for p_i in FB\n"); } for (i = h->index0_FB; i < h->size_of_FB + 2; i++) { FB[i].fbe_logval = (unsigned char) (log_multiplier * FB[i].fbe_flogp); } } /* Given the partially populated handle, find the optimum place in the FB * to pick prime factors for A from. The lowest admissible subscript is * index0_FB, but unless kN is very small, we stay away a bit from that. * The highest admissible is size_of_FB + 1, where the largest FB prime * resides. The ideal corner is about (sqrt(kN)/M) ^ (1/omega_A), * so that A will end up of size comparable to sqrt(kN)/M; experimentally * it seems desirable to stay slightly below this. Moreover, the selection * of the individual primes happens to err on the large side, for which we * compensate a bit, using the (small positive) quantity MPQS_A_FUDGE. * We rely on a few auxiliary fields in the handle to be already set by * mqps_set_sieve_threshold() before we are called. * Return 1 on success, and 0 otherwise. */ static int mpqs_locate_A_range(mpqs_handle_t *h) { /* i will be counted up to the desirable index2_FB + 1, and omega_A is never * less than 3, and we want * index2_FB - (omega_A - 1) + 1 >= index0_FB + omega_A - 3, * so: */ long i = h->index0_FB + 2*(h->omega_A) - 4; double l2_target_pA; mpqs_FB_entry_t *FB = h->FB; h->l2_target_A = (h->l2sqrtkN - h->l2M - MPQS_A_FUDGE); l2_target_pA = h->l2_target_A / h->omega_A; /* find the sweet spot, normally shouldn't take long */ while ((FB[i].fbe_p != 0) && (FB[i].fbe_flogp <= l2_target_pA)) i++; #ifdef MPQS_DEBUG_LOCATE_A_RANGE err_printf("MPQS DEBUG: omega_A=%ld, index0=%ld, i=%ld\n", (long) h->omega_A, (long) h->index0_FB, i); #endif /* check whether this hasn't walked off the top end... */ /* The following should actually NEVER happen. */ if (i > h->size_of_FB - 3) { /* this isn't going to work at all. */ pari_warn(warner, "MPQS: sizing out of tune, FB too small or\n\tway too few primes in A"); return 0; } h->index2_FB = i - 1; #ifdef MPQS_DEBUG_LOCATE_A_RANGE err_printf("MPQS DEBUG: index2_FB = %ld\n", i - 1); #endif /* GN20050723 * assert: index0_FB + (omega_A - 3) [the lowest FB subscript eligible to * be used in picking primes for A] plus (omega_A - 2) does not exceed * index2_FB [the subscript from which the choice of primes for A starts, * putting omega_A - 1 of them at or below index2_FB, and the last and * largest one above, cf. mpqs_si_choose_primes() below]. * Moreover, index2_FB indicates the last prime below the ideal size, unless * (when kN is very small) the ideal size was too small to use. */ return 1; } /*********************************************************************/ /** **/ /** HISTOGRAMS AND THRESHOLD FEEDBACK **/ /** **/ /*********************************************************************/ #ifdef MPQS_USE_HISTOGRAMS /* The histogram-related code is left in this file, but all under the * above #ifdef, and disabled by default. I'm finding that: * - merely keeping the numbers updated in mpqs_eval_cand() below (and * keeping the "negligible" 1.5 or 3KBys' worth of extra arrays in use) * causes us to run quite noticeably slower: 8-10% for a 73-digit number, * - mpqs_eval_cand() has already become so much faster than it used to be * that raising the threshold to get rid of many low-valued unpromising * candidates does not save any significant time, and even losing a pretty * small number of additional LP relations actually harms us by lowering * the efficiency of LP relation combining. * (The first point might be due merely to code bloat and less effective * compiler optimizations - I'm not sure about that.) * Just for getting a visual impression of how the sieve is performing, * however, this is nice to have available. Just turn on the #define at * the top of the file and recompile with it. --GN2005-02-03 */ /* histogram evaluation happens very infrequently if at all. So we'll do * all the adding and putting-into-relation-with here, while mpqs_eval_cand() * merely bumps one cell at a time and doesn't keep running totals. */ static void mpqs_print_histo(mpqs_handle_t *h) { long i, tot = 0; if (!h->do_histograms) return; err_printf("\nMPQS: values from sieve vs. distribution of evaluated candidates:\n"); err_printf(" val ___full __lprel ___none ___total\n"); for (i = 127; i >= 0; i--) { long rowtot = h->histo_full[i] + h->histo_lprl[i] + h->histo_drop[i]; tot += rowtot; if ((rowtot > 0) || (i == h->sieve_threshold)) err_printf("%s[%3d] %7ld %7ld %7ld %8ld\n", i + 128 == h->sieve_threshold ? "^-" : " ", i + 128, h->histo_full[i], h->histo_lprl[i], h->histo_drop[i], rowtot); } err_printf(" (total evaluated candidates: %ld)\n", tot); } /* evaluation/feedback heuristics: * First of all, refuse to draw any conclusions unless and until there's * enough material to be statistically significant. * Second, after sifting through the histo arrays, the new threshold is * set to the minimum of the following three quantities: * - the position where going down from the top value the histo_full * totals first exceed 100 - MPQS_HISTO_FREL_QUANTILE percent of all * full relations found so far by direct sieving. (I.e. if the quantile * is 4, we want to keep all rows which account for 96% of all frels * obtained from the sieve. Note that once we increase the threshold, * further counts will be biased against smaller values; but we normally * don't expect to do many adjustments.) * - the position where, going down from the top towards smaller values, * the cumulative number of useless candidates in histo_drop first exceeds * MPQS_HISTO_DROP_LIMIT times the number of useful ones. I.e. when that * limit is 2, we're aiming for at least about 1/3 of all candidates coming * from the sieve to result in usable relations. * - one less than the position where the histo_lprl count first falls below * MPQS_HISTO_LPREL_BASEFLOW times the number of useless candidates. This * one will be capable of lowering the current threshold (but never below * 128). * FIXME: For Double Large Prime mode, this will need to be seriously reworked. */ /* This function returns 1 when it actually did something and decided on a * good threshold (although possibly the same as it was before), -1 when * there was nothing to do and never will be ("don't call us again"), 0 * when the caller should retry somewhat later. Note that mpqs() already * knows the total number of candidates generated so far (from the return * values of mpqs_eval_sieve()), and won't call us too early; but we also * insist on minimal standards for the column sums. Conversely when we ever * lower the threshold, we ask for a re-evaluation later on. * NB With the present accounting, once the threshold has been raised, it * won't ever be lowered again, since the increasing counts above it will * totally swamp the few earlier measurements below which can no longer * grow. So we might chop off those accumulating loops at the current sieve * threshold. */ static int mpqs_eval_histograms(mpqs_handle_t *h) { long tot_full = 0, tot_lprl = 0, tot_drop = 0, total = 0; long target_full, i; int th_full, th_base, th_drop; int th = h->sieve_threshold - 128; if (!h->do_histograms) return -1; /* first compute column sums */ for (i = 127; i >= 0; i--) { tot_full += h->histo_full[i]; tot_lprl += h->histo_lprl[i]; tot_drop += h->histo_drop[i]; } total = tot_full + tot_lprl + tot_drop; if ((total < MPQS_MIN_CANDS_FOR_HISTO) || (tot_full < MPQS_MIN_FRELS_FOR_HISTO)) return 0; /* too early to call the race */ th_full = th_drop = th_base = -1; /* find the full relations quantile point */ target_full = tot_full - (tot_full * MPQS_HISTO_FREL_QUANTILE) / 100.; tot_full = 0; for (i = 127; i >= th; i--) { if ((tot_full += h->histo_full[i]) >= target_full) { th_full = i; break; } } /* find the "lp relations baseflow" point */ for (i = 127; i >= th; i--) { if (h->histo_lprl[i] + 1 < MPQS_HISTO_LPREL_BASEFLOW * h->histo_drop[i]) { th_base = i; break; } } /* find the wastefulness point */ tot_lprl = 0; tot_drop = 0; for (i = 127; i >= th; i--) { tot_lprl += h->histo_full[i] + h->histo_lprl[i]; tot_drop += h->histo_drop[i]; if (tot_drop > MPQS_HISTO_DROP_LIMIT * (tot_lprl + 1)) { th_drop = i; break; } } /* if these loops found nothing, then th_(full|base|drop) will still be -1. * We won't tighten the sieve, but th_base would tell us we should loosen * it (reluctantly). */ if (MPQS_DEBUGLEVEL >= 5) { mpqs_print_histo(h); if (th_full >= 0) err_printf("MPQS: threshold estimate for full rels: %d\n", th_full + 128); if (th_drop >= 0) err_printf("MPQS: threshold estimate for useful candidates: %d\n", th_drop + 128); } /* any reason to open up the sieve? wait until a minimal number of lprels * at the threshold has been seen before going down... */ if ((th > 0) && (th_base <= th) && (h->histo_lprl[th] > (MPQS_MIN_FRELS_FOR_HISTO * 3.5)) ) { h->sieve_threshold = th + 127; if (MPQS_DEBUGLEVEL >= 4) err_printf("MPQS: loosening sieve tolerance, new threshold %d\n", h->sieve_threshold); return 0; /* this should be re-examined after a bit */ } /* otherwise, any reason to tighten it? */ th = (th_full < th_drop ? th_full : th_drop) + 128; if (th > h->sieve_threshold) { h->sieve_threshold = th; if (MPQS_DEBUGLEVEL >= 4) err_printf("MPQS: tightening sieve tolerance, new threshold %d\n", h->sieve_threshold); } /* maybe also loosen it if th_drop persistently stays below th... */ return 1; /* wait a good while before rechecking */ } #endif /*********************************************************************/ /** **/ /** RELATIONS AS STRINGS AND RELATIONS DATABASE **/ /** **/ /*********************************************************************/ /* determines a unique name for a file based on a short nickname * name is allocated on the stack */ static char * mpqs_get_filename(char *dir, const char *s) { char *buf = stack_malloc(strlen(dir) + strlen(s) + 2); #if defined(__EMX__) || defined(WINCE) sprintf(buf, "%s\\%s", dir,s); #else sprintf(buf, "%s/%s", dir,s); #endif return buf; } /* compares two `large prime' relations according to their first element * (the large prime itself). */ static int mpqs_relations_cmp(const void *a, const void *b) { char **sa = (char**) a; char **sb = (char**) b; long qa = strtol(*sa, NULL, 10); long qb = strtol(*sb, NULL, 10); /* atol() isn't entirely portable for the Full Relations case where the strings of digits are too long to fit into a long --GN */ if (qa < qb) return -1; else if (qa > qb) return 1; else return strcmp(*sa, *sb); } static void pari_fputs(char *s, pariFILE *f) { if (fputs(s, f->file) < 0) pari_err_FILE("output file [fputs]", f->name); } #define min_bufspace 120UL /* use new buffer when < min_bufspace left */ #define buflist_size 1024 /* size of list-of-buffers blocks */ /* Given a file "filename" containing full or `large prime' relations, * rearrange the file so that relations are sorted by their first elements. * Works also for sorting full relations. Works in memory, discards duplicate * lines, and overwrites the original file. */ static long mpqs_sort_lp_file(char *filename) { pariFILE *pTMP; FILE *TMP; char *old_s, *buf, *cur_line; char **sort_table, **buflist, **next_buflist, **buflist_head; long i, j, count; size_t length, bufspace; pari_sp av=avma; buflist_head = (char**) stack_malloc(buflist_size * sizeof(char*)); buflist = buflist_head; *buflist++ = NULL; /* flag this as last and only buflist block */ /* extra blocks may be allocated as needed and linked ahead of * buflist_head. NB: whilst extra buflist blocks might have been * needed when we were still sorting entire FREL files (more than 1023 * buffers, corresponding to about 20000 lines of ~200 characters), they * should never be touched now that we only sort LPNEW and FNEW files, which * are rather shorter. But the code might as well stay around for future * upgrades to handling even larger numbers (and factor bases and thus * relations files). It costs one comparison per buffer allocation. --GN */ pTMP = pari_fopen_or_fail(filename, READ); TMP = pTMP->file; /* get first buffer and read first line, if any, into it */ buf = (char*) pari_malloc(MPQS_STRING_LENGTH * sizeof(char)); cur_line = buf; bufspace = MPQS_STRING_LENGTH; if (fgets(cur_line, bufspace, TMP) == NULL) { /* file empty */ pari_free(buf); pari_fclose(pTMP); avma = av; return 0; } /* enter first buffer into buflist */ *buflist++ = buf; /* can't overflow the buflist block */ length = strlen(cur_line) + 1; /* count the \0 byte as well */ bufspace -= length; sort_table = (char**)avma; /* at start of loop, one line from the file is sitting in cur_line inside buf, * the next will go into cur_line + length, and there's room for bufspace * further characters in buf. The loop reads another line if one exists, and * if this overruns the current buffer, it allocates a fresh one --GN */ for (i=0, sort_table--; /* until end of file */; i++, sort_table--) { /* sort_table is allocated on the stack, 0x100 cells at a time. Hence the * stack must be left alone in the rest of the loop to keep the array * connected. In particular, buffers can't be new_chunk'ed */ if ((i & 0xff) == 0) (void)new_chunk(0x100); *sort_table = cur_line; cur_line += length; /* if little room is left, allocate a fresh buffer before attempting to * read a line, and remember to free it if no further line is forthcoming. * This avoids some copying of partial lines --GN */ if (bufspace < min_bufspace) { if (MPQS_DEBUGLEVEL >= 7) err_printf("MQPS: short of space -- another buffer for sorting\n"); buf = (char*) pari_malloc(MPQS_STRING_LENGTH * sizeof(char)); cur_line = buf; bufspace = MPQS_STRING_LENGTH; if (fgets(cur_line, bufspace, TMP) == NULL) { pari_free(buf); break; } /* remember buffer for later deallocation */ if (buflist - buflist_head >= buflist_size) { /* need another buflist block */ next_buflist = (char**) pari_malloc(buflist_size * sizeof(char*)); *next_buflist = (char*)buflist_head; /* link */ buflist_head = next_buflist; buflist = buflist_head + 1; } *buflist++ = buf; length = strlen(cur_line) + 1; bufspace -= length; continue; } /* normal case: try fitting another line into the current buffer */ if (fgets(cur_line, bufspace, TMP) == NULL) break; /* none exists */ length = strlen(cur_line) + 1; bufspace -= length; /* check whether we got the entire line or only part of it */ if (bufspace == 0 && cur_line[length-2] != '\n') { size_t lg1; if (MPQS_DEBUGLEVEL >= 7) err_printf("MQPS: line wrap -- another buffer for sorting\n"); buf = (char*) pari_malloc(MPQS_STRING_LENGTH * sizeof(char)); /* remember buffer for later deallocation */ if (buflist - buflist_head >= buflist_size) { /* need another buflist block */ next_buflist = (char**)pari_malloc(buflist_size * sizeof(char*)); *next_buflist = (char*)buflist_head; /* link */ buflist_head = next_buflist; buflist = buflist_head + 1; } *buflist++ = buf; /* copy what we've got to the new buffer */ (void)strcpy(buf, cur_line); /* cannot overflow */ cur_line = buf + length - 1; /* point at the \0 byte */ bufspace = MPQS_STRING_LENGTH - length + 1; /* read remainder of line */ if (fgets(cur_line, bufspace, TMP) == NULL) pari_err_FILE("TMP file [fgets]", pTMP->name); lg1 = strlen(cur_line); length += lg1; /* we already counted the \0 once */ bufspace -= (lg1 + 1); /* but here we must take it into account */ cur_line = buf; /* back up to the beginning of the line */ } } /* for */ pari_fclose(pTMP); /* sort the whole lot in place by swapping pointers */ qsort(sort_table, i, sizeof(char*), mpqs_relations_cmp); /* copy results back to the original file, skipping exact duplicates */ pTMP = pari_fopen_or_fail(filename, WRITE); old_s = sort_table[0]; pari_fputs(sort_table[0], pTMP); count = 1; for(j = 1; j < i; j++) { if (strcmp(old_s, sort_table[j])) { pari_fputs(sort_table[j], pTMP); count++; } old_s = sort_table[j]; } pari_fclose(pTMP); if (MPQS_DEBUGLEVEL >= 6) err_printf("MPQS: done sorting one file.\n"); /* deallocate buffers and any extraneous buflist blocks except the first */ while (*--buflist) { if (buflist != buflist_head) /* not a linkage pointer */ pari_free((void*) *buflist); /* free a buffer */ else { /* linkage pointer */ next_buflist = (char**)(*buflist); pari_free((void*)buflist_head); /* free a buflist block */ buflist_head = next_buflist; buflist = buflist_head + buflist_size; } } avma = av; return count; } /* appends contents of file fp1 to f (auxiliary routine for merge sort) and * returns number of lines copied. Close f afterwards */ static long mpqs_append_file(pariFILE *f, FILE *fp1) { FILE *fp = f->file; char line[MPQS_STRING_LENGTH]; long c = 0; while (fgets(line, MPQS_STRING_LENGTH, fp1)) { pari_fputs(line, f); c++; } if (fflush(fp)) pari_warn(warner, "error whilst flushing file %s", f->name); pari_fclose(f); return c; } /* Merge-sort on the files LPREL and LPNEW; assumes that LPREL and LPNEW are * already sorted. Creates/truncates the TMP file, writes result to it and * closes it (via mpqs_append_file()). Instead of LPREL, LPNEW we may also call * this with FREL, FNEW. In the latter case pCOMB should be NULL (and we * return the count of all full relations), in the former non-NULL (and we * return the count of frels we expect to be able to combine out of the * present lprels). If pCOMB is non-NULL, the combinable lprels are written * out to this separate file. * We keep only one occurrence of each `large prime' in TMP (i.e. in the * future LPREL file). --GN */ #define swap_lines() { char *line_tmp;\ line_tmp = line_new_old; \ line_new_old = line_new; \ line_new = line_tmp; } static long mpqs_mergesort_lp_file0(FILE *LPREL, FILE *LPNEW, pariFILE *pCOMB, pariFILE *pTMP) { char line1[MPQS_STRING_LENGTH], line2[MPQS_STRING_LENGTH]; char line[MPQS_STRING_LENGTH]; char *line_new = line1, *line_new_old = line2; long q_new, q_new_old = -1, q, i = 0, c = 0; long comb_in_progress; if ( !fgets(line_new, MPQS_STRING_LENGTH, LPNEW) ) { /* LPNEW is empty: copy LPREL to TMP. Could be done by a rename if we * didn't want to count the lines (again)... however, this case will not * normally happen */ i = mpqs_append_file(pTMP, LPREL); return pCOMB ? 0 : i; } /* we now have a line_new from LPNEW */ if (!fgets(line, MPQS_STRING_LENGTH, LPREL)) { /* LPREL is empty: copy LPNEW to TMP... almost. */ pari_fputs(line_new, pTMP); if (!pCOMB) { /* full relations mode */ i = mpqs_append_file(pTMP, LPNEW); return i + 1; } /* LP mode: check for combinable relations */ q_new_old = atol(line_new); /* we need to retain a copy of the old line just for a moment, because we * may yet have to write it to pCOMB. Do this by swapping the two buffers */ swap_lines(); comb_in_progress = 0; i = 0; while (fgets(line_new, MPQS_STRING_LENGTH, LPNEW)) { q_new = atol(line_new); if (q_new_old == q_new) { /* found combinables, check whether we're already busy on this particular `large prime' */ if (!comb_in_progress) { /* if not, write first line to pCOMB, creating and opening the * file first if it isn't open yet */ pari_fputs(line_new_old, pCOMB); comb_in_progress = 1; } /* in any case, write the current line, and count it */ pari_fputs(line_new, pCOMB); i++; } else { /* not combinable */ q_new_old = q_new; comb_in_progress = 0; /* and dump it to the TMP file */ pari_fputs(line_new, pTMP); /* and stash it away for a moment */ swap_lines(); } } /* while */ pari_fclose(pTMP); return i; } /* normal case: both LPNEW and LPREL are not empty */ q_new = atol(line_new); q = atol(line); for(;;) { /* main merging loop */ i = comb_in_progress = 0; /* first the harder case: let LPNEW catch up with LPREL, and possibly overtake it, checking for combinables coming from LPNEW alone */ while (q > q_new) { if (!pCOMB || !comb_in_progress) pari_fputs(line_new, pTMP); if (!pCOMB) c++; /* in FREL mode, count lines written */ else if (!comb_in_progress) { q_new_old = q_new; swap_lines(); } if (!fgets(line_new, MPQS_STRING_LENGTH, LPNEW)) { pari_fputs(line, pTMP); if (!pCOMB) c++; else c += i; i = mpqs_append_file(pTMP, LPREL); return pCOMB? c: c + i; } q_new = atol(line_new); if (!pCOMB) continue; /* LP mode only: */ if (q_new_old != q_new) /* not combinable */ comb_in_progress = 0; /* next loop will deal with it, or loop may end */ else { /* found combinables, check whether we're already busy on this `large prime' */ if (!comb_in_progress) { pari_fputs(line_new_old, pCOMB); comb_in_progress = 1; } /* in any case, write the current line, and count it */ pari_fputs(line_new, pCOMB); i++; } } /* while q > q_new */ /* q <= q_new */ if (pCOMB) c += i; /* accumulate count of combinables */ i = 0; /* and clear it */ comb_in_progress = 0;/* redundant */ /* now let LPREL catch up with LPNEW, and possibly overtake it */ while (q < q_new) { pari_fputs(line, pTMP); if (!pCOMB) c++; if (!fgets(line, MPQS_STRING_LENGTH, LPREL)) { pari_fputs(line_new, pTMP); i = mpqs_append_file(pTMP, LPNEW); return pCOMB? c: c + i + 1; } else q = atol(line); } /* q >= q_new */ /* Finally, it may happen that q == q_new, indicating combinables whose * `large prime' is already in LPREL, and appears now once or more often in * LPNEW. Thus in this sub-loop we advance LPNEW. The `line' from LPREL is * left alone, and will be written to TMP the next time around the main for * loop; we only write it to pCOMB here -- unless all we find is an exact * duplicate of the line we already have, that is. (There can be at most * one such, and if so it is simply discarded.) */ while (q == q_new) { if (!strcmp(line_new, line)) { /* duplicate -- move right ahead to the next LPNEW line */ ;/* do nothing here */ } else if (!pCOMB) { /* full relations mode: write line_new out first, keep line */ pari_fputs(line_new, pTMP); c++; } else { /* LP mode, and combinable relation */ if (!comb_in_progress) { pari_fputs(line, pCOMB); comb_in_progress = 1; } pari_fputs(line_new, pCOMB); i++; } /* NB comb_in_progress is cleared by q_new becoming bigger than q, thus * the current while loop terminating, the next time through the main for * loop */ /* common ending: get another line_new, if any */ if (!fgets(line_new, MPQS_STRING_LENGTH, LPNEW)) { pari_fputs(line, pTMP); if (!pCOMB) c++; else c += i; i = mpqs_append_file(pTMP, LPREL); return pCOMB? c: c + i; } else q_new = atol(line_new); } /* while */ if (pCOMB) c += i; /* accumulate count of combinables */ } } static long mpqs_mergesort_lp_file(char *REL_str, char *NEW_str, char *TMP_str, pariFILE *pCOMB) { pariFILE *pREL = pari_fopen_or_fail(REL_str, READ); pariFILE *pNEW = pari_fopen_or_fail(NEW_str, READ); pariFILE *pTMP = pari_fopen_or_fail(TMP_str, WRITE); long tp; tp = mpqs_mergesort_lp_file0(pREL->file, pNEW->file, pCOMB, pTMP); pari_fclose(pREL); pari_fclose(pNEW); pari_unlink(REL_str); if (rename(TMP_str,REL_str)) pari_err_FILE("output file [rename]", REL_str); if (MPQS_DEBUGLEVEL >= 6) err_printf("MPQS: renamed file %s to %s\n", TMP_str, REL_str); return tp; } /*********************************************************************/ /** **/ /** SELF-INITIALIZATION **/ /** **/ /*********************************************************************/ #ifdef MPQS_DEBUG /* Debug-only helper routine: check correctness of the root z mod p_i * by evaluting A * z^2 + B * z + C mod p_i (which should be 0). * C is written as (B*B-kN)/(4*A) */ static void check_root(mpqs_handle_t *h, long p, long start) { long z = start - ((long)(h->M) % p); if (smodis(addii(h->C, mului(z, addii(h->B, mului(z, h->A)))), p)) { err_printf("MPQS: p = %ld\n", p); err_printf("MPQS: A = %Ps\n", h->A); err_printf("MPQS: B = %Ps\n", h->B); err_printf("MPQS: C = %Ps\n", h->C); err_printf("MPQS: z = %ld\n", z); pari_err_BUG("MPQS: self_init: found wrong polynomial"); } } #endif /* There are four parts to self-initialization, which are exercised at * somewhat different times: * - choosing a new coefficient A (selecting the prime factors to go into it, * and doing the required bookkeeping in the FB entries, including clearing * out the flags from the previous cohort), together with: * - doing the actual computations associated with a new A * - choosing a new B keeping the same A (very much simpler and quicker) * - and a small common bit that needs to happen in both cases. * As to the first item, the new scheme works as follows: * We pick omega_A - 1 prime factors for A below the index2_FB point which * marks their ideal size, and one prime above this point, choosing the * latter so as to get log2(A) as close as possible to l2_target_A. * The lower prime factors are chosen using bit patterns of constant weight, * gradually moving away from index2_FB towards smaller FB subscripts. * If this bumps into index0_FB (might happen for very small input), we * back up by increasing index2_FB by two, and from then on choosing only * bit patterns with either or both of their bottom bits set, so at least * one of the omega_A - 1 smaller prime factor will be beyond the original * index2_FB point. In this way we avoid re-using A's which had already * been done. * (The choice of the upper "flyer" prime is of course constrained by the * size of the FB, which normally should never be anywhere close to becoming * a problem. In unfortunate cases, e.g. for very small kN, we might have * to live with a rather non-optimal choice. * Then again, MPQS as such is surprisingly robust. One day, I had got the * order of entries in mpqs_parameterset_t mixed up, and was running on a * smallish N with a huuuuge factor base and extremely tiny sieve interval, * and it still managed to factor it fairly quickly...) * * Mathematically, there isn't much more to this than the usual formula for * solving a quadratic (over the field of p elements for each prime p in * the FB which doesn't divide A), solving a linear equation for each of * the primes which do divide A, and precomputing differences between roots * mod p so we can adjust the roots quickly when we change B. * See Thomas Sosnowski's diploma thesis. */ /* Helper function: * Increment *x (!=0) to a larger value which has the same number of 1s in its * binary representation. Wraparound can be detected by the caller as long as * we keep total_no_of_primes_for_A strictly less than BITS_IN_LONG. * * Changed switch to increment *x in all cases to the next larger number * which (a) has the same count of 1 bits and (b) does not arise from the * old value by moving a single 1 bit one position to the left (which was * undesirable for the sieve). --GN based on discussion with TP */ INLINE void mpqs_increment(mpqs_uint32_t *x) { mpqs_uint32_t r1_mask, r01_mask, slider=1UL; /* 32-way computed jump handles 22 out of 32 cases */ switch (*x & 0x1F) { case 29: (*x)++; break; /* shifts a single bit, but we postprocess this case */ case 26: (*x) += 2; break; /* again */ case 1: case 3: case 6: case 9: case 11: case 17: case 19: case 22: case 25: case 27: (*x) += 3; return; case 20: (*x) += 4; break; /* again */ case 5: case 12: case 14: case 21: (*x) += 5; return; case 2: case 7: case 13: case 18: case 23: (*x) += 6; return; case 10: (*x) += 7; return; case 8: (*x) += 8; break; /* and again */ case 4: case 15: (*x) += 12; return; default: /* 0, 16, 24, 28, 30, 31 */ /* isolate rightmost 1 */ r1_mask = ((*x ^ (*x - 1)) + 1) >> 1; /* isolate rightmost 1 which has a 0 to its left */ r01_mask = ((*x ^ (*x + r1_mask)) + r1_mask) >> 2; /* simple cases. Both of these shift a single bit one position to the left, and will need postprocessing */ if (r1_mask == r01_mask) { *x += r1_mask; break; } if (r1_mask == 1) { *x += r01_mask; break; } /* general case -- idea: add r01_mask, kill off as many 1 bits as possible * to its right while at the same time filling in 1 bits from the LSB. */ if (r1_mask == 2) { *x += (r01_mask>>1) + 1; return; } while (r01_mask > r1_mask && slider < r1_mask) { r01_mask >>= 1; slider <<= 1; } *x += r01_mask + slider - 1; return; } /* post-process all cases which couldn't be finalized above. If we get here, slider still has its original value. */ r1_mask = ((*x ^ (*x - 1)) + 1) >> 1; r01_mask = ((*x ^ (*x + r1_mask)) + r1_mask) >> 2; if (r1_mask == r01_mask) { *x += r1_mask; return; } if (r1_mask == 1) { *x += r01_mask; return; } if (r1_mask == 2) { *x += (r01_mask>>1) + 1; return; } while (r01_mask > r1_mask && slider < r1_mask) { r01_mask >>= 1; slider <<= 1; } *x += r01_mask + slider - 1; return; } /* self-init (1): advancing the bit pattern, and choice of primes for A. * The first time this is called, it finds h->bin_index == 0, which tells us * to initialize things from scratch. On later occasions, we need to begin * by clearing the MPQS_FBE_DIVIDES_A bit in the fbe_flags of the former * prime factors of A. We use, of course, the per_A_pr array for finding * them. Upon successful return, that array will have been filled in, and * the flag bits will have been turned on again in the right places. * We return 1 (true) when we could set things up successfully, and 0 when * we found we'd be using more bits to the left in bin_index than we have * matching primes for in the FB. In the latter case, bin_index will be * zeroed out, index2_FB will be incremented by 2, index2_moved will be * turned on, and the caller, after checking that index2_FB has not become * too large, should just call us again, which then is guaranteed to succeed: * we'll start again with a right-justified sequence of 1 bits in bin_index, * now interpreted as selecting primes relative to the new index2_FB. */ #ifndef MPQS_DEBUG_SI_CHOOSE_PRIMES # define MPQS_DEBUG_SI_CHOOSE_PRIMES 0 #endif INLINE int mpqs_si_choose_primes(mpqs_handle_t *h) { mpqs_FB_entry_t *FB = h->FB; mpqs_per_A_prime_t *per_A_pr = h->per_A_pr; double l2_last_p = h->l2_target_A; mpqs_int32_t omega_A = h->omega_A; int i, j, v2, prev_last_p_idx; int room = h->index2_FB - h->index0_FB - omega_A + 4; /* GN 20050723: I.e., index2_FB minus (index0_FB + omega_A - 3) plus 1 * The notion of room here (cf mpqs_locate_A_range() above) is the number * of primes at or below index2_FB which are eligible for A. * At the very least, we need omega_A - 1 of them, and it is guaranteed * by mpqs_locate_A_range() that at least this many are available when we * first get here. The logic here ensures that the lowest FB slot used * for A is never less than index0_FB + omega_A - 3. In other words, when * omega_A == 3 (very small kN), we allow ourselves to reach all the way * down to index0_FB; otherwise, we keep away from it by at least one * position. For omega_A >= 4 this avoids situations where the selection * of the smaller primes here has advanced to a lot of very small ones, and * the single last larger one has soared away to bump into the top end of * the FB. */ mpqs_uint32_t room_mask; mpqs_int32_t p; ulong bits; /* XXX also clear the index_j field here? */ if (h->bin_index == 0) { /* first time here, or after increasing index2_FB, initialize to a pattern * of omega_A - 1 consecutive right-justified 1 bits. * Caller will have ensured that there are enough primes for this in the * FB below index2_FB. */ h->bin_index = (1UL << (omega_A - 1)) - 1; prev_last_p_idx = 0; } else { /* clear out the old flags */ for (i = 0; i < omega_A; i++) MPQS_FLG(i) &= ~MPQS_FBE_DIVIDES_A; prev_last_p_idx = MPQS_I(omega_A-1); /* find out how much maneuvering room we have before we're up against * the index0_FB wall */ if (room > 30) room = 30; room_mask = ~((1UL << room) - 1); /* bump bin_index to the next acceptable value. If index2_moved is off, * call mpqs_increment() just once; otherwise, repeat until there's * something in the least significant 2 bits - this to ensure that we * never re-use an A which we'd used before increasing index2_FB - but * also stop if something shows up in the forbidden bits on the left * where we'd run out of bits or out of subscripts (i.e. walk beyond * index0_FB + omega_A - 3). */ mpqs_increment(&h->bin_index); if (h->index2_moved) { while ((h->bin_index & (room_mask | 0x3)) == 0) mpqs_increment(&h->bin_index); } /* ok so did we fall off the edge on the left? */ if ((h->bin_index & room_mask) != 0) { /* Yes. Turn on the index2_moved flag in the handle */ h->index2_FB += 2; /* caller to check this isn't too large!!! */ h->index2_moved = 1; h->bin_index = 0; if (MPQS_DEBUG_SI_CHOOSE_PRIMES || (MPQS_DEBUGLEVEL >= 5)) err_printf("MPQS: wrapping, more primes for A now chosen near FB[%ld] = %ld\n", (long)h->index2_FB, (long)FB[h->index2_FB].fbe_p); return 0; /* back off - caller should retry */ } } /* assert: we aren't occupying any of the room_mask bits now, and if * index2_moved had already been on, at least one of the two LSBs is on */ bits = h->bin_index; if (MPQS_DEBUG_SI_CHOOSE_PRIMES || (MPQS_DEBUGLEVEL >= 6)) err_printf("MPQS: new bit pattern for primes for A: 0x%lX\n", bits); /* map bits to FB subscripts, counting downward with bit 0 corresponding * to index2_FB, and accumulate logarithms against l2_last_p */ j = h->index2_FB; v2 = vals((long)bits); if (v2) { j -= v2; bits >>= v2; } for (i = omega_A - 2; i >= 0; i--) { MPQS_I(i) = j; l2_last_p -= MPQS_LP(i); MPQS_FLG(i) |= MPQS_FBE_DIVIDES_A; bits &= ~1UL; if (!bits) break; /* that was the i=0 iteration */ v2 = vals((long)bits); j -= v2; bits >>= v2; } /* Choose the larger prime. Note we keep index2_FB <= size_of_FB - 3 */ for (j = h->index2_FB + 1; (p = FB[j].fbe_p) != 0; j++) { if (FB[j].fbe_flogp > l2_last_p) break; } /* GN 20050724: The following trick avoids generating a relatively large * proportion of duplicate relations when the last prime happens to fall * into an area where there are large gaps from one FB prime to the next, * and would otherwise often be repeated (so that successive A's would * wind up too similar to each other). While this trick isn't perfect, * it seems to get rid of a major part of the potential duplication. */ if ((p != 0) && (j == prev_last_p_idx)) { j++; p = FB[j].fbe_p; } MPQS_I(omega_A - 1) = (p == 0 ? /* did we fall off the end of the FB? */ h->size_of_FB + 1 : /* then improvise */ j); MPQS_FLG(omega_A - 1) |= MPQS_FBE_DIVIDES_A; if (MPQS_DEBUG_SI_CHOOSE_PRIMES || (MPQS_DEBUGLEVEL >= 6)) { err_printf("MPQS: chose primes for A"); for (i = 0; i < omega_A; i++) { err_printf(" FB[%ld]=%ld%s", (long) MPQS_I(i), (long) MPQS_AP(i), i < omega_A - 1 ? "," : "\n"); } } return 1; } /* compute coefficients of the sieving polynomial for self initializing * variant. Coefficients A and B are returned and several tables are * updated. */ /* A and B are kept on the PARI stack in preallocated GENs. So is C when * we're compiled for debugging. */ static void mpqs_self_init(mpqs_handle_t *h) { const ulong size_of_FB = h->size_of_FB + 1; mpqs_FB_entry_t *FB = h->FB; mpqs_inv_A_H_t *inv_A_H = h->inv_A_H; const pari_sp av = avma; GEN p1, p2; GEN A = h->A; GEN B = h->B; mpqs_per_A_prime_t *per_A_pr = h->per_A_pr; long i, j; long inv_A2; ulong p; #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: enter self init, avma = 0x%lX\n", (ulong)avma); #endif /* when all of the B's have already been used, choose new A ; this is indicated by setting index_j to 0 */ if (++h->index_j == (mpqs_uint32_t)h->no_B) { h->index_j = 0; h->index_i++; /* count finished A's */ } if (h->index_j == 0) /* "mpqs_self_init_A()" */ { /* compute first polynomial with new A */ if (!mpqs_si_choose_primes(h)) { /* We ran out of room towards small primes, and index2_FB was raised. * Check that we're still ok in that direction before re-trying the * operation, which then is guaranteed to succeed. The invariant we * maintain towards the top end is that h->size_of_FB - h->index2_FB >= 3, * but note that our size_of_FB is one larger. */ /* "throw exception up to caller." ( bin_index set to impossible value * 0 by mpqs_si_choose_primes() */ if (size_of_FB - h->index2_FB < 4) return; (void) mpqs_si_choose_primes(h); } /* assert: bin_index and per_A_pr are now populated with consistent * values */ /* compute A = product of omega_A primes given by bin_index */ p1 = NULL; for (i = 0; i < h->omega_A; i++) { p = (ulong) MPQS_AP(i); p1 = p1 ? muliu(p1, p): utoipos(p); } affii(p1, A); avma = av; /* Compute H[i], 0 <= i < omega_A. Also compute the initial * B = sum(v_i*H[i]), by taking all v_i = +1 */ /* TODO: following needs to be changed later for segmented FB and sieve * interval, where we'll want to precompute several B's. */ p2 = NULL; for (i = 0; i < h->omega_A; i++) { p = (ulong) MPQS_AP(i); p1 = divis(A, (long)p); p1 = muliu(p1, Fl_inv(umodiu(p1, p), p)); p1 = muliu(p1, MPQS_SQRT(i)); affii(remii(p1, A), MPQS_H(i)); p2 = p2 ? addii(p2, MPQS_H(i)) : MPQS_H(i); } affii(p2, B); avma = av; /* must happen outside the loop */ /* ensure B = 1 mod 4 */ if (mod2(B) == 0) affii(addii(B, mului(mod4(A), A)), B); /* B += (A % 4) * A; */ p1 = shifti(A, 1); /* compute the roots z1, z2, of the polynomial Q(x) mod p_j and * initialize start1[i] with the first value p_i | Q(z1 + i p_j) * initialize start2[i] with the first value p_i | Q(z2 + i p_j) * The following loop "miraculously" does The Right Thing for the * primes dividing k (where sqrt_kN is 0 mod p). Primes dividing A * are skipped here, and are handled further down in the common part * of SI. */ for (j = 3; (ulong)j <= size_of_FB; j++) { ulong mb, tmp1, tmp2, m; if (FB[j].fbe_flags & MPQS_FBE_DIVIDES_A) continue; p = (ulong)FB[j].fbe_p; m = h->M % p; inv_A2 = Fl_inv(umodiu(p1, p), p); /* = 1/(2*A) mod p_j */ mb = umodiu(B, p); if (mb) mb = p - mb; /* mb = -B mod p */ tmp1 = Fl_sub(mb, FB[j].fbe_sqrt_kN, p); tmp1 = Fl_mul(tmp1, inv_A2, p); FB[j].fbe_start1 = (mpqs_int32_t)Fl_add(tmp1, m, p); tmp2 = Fl_add(mb, FB[j].fbe_sqrt_kN, p); tmp2 = Fl_mul(tmp2, inv_A2, p); FB[j].fbe_start2 = (mpqs_int32_t)Fl_add(tmp2, m, p); for (i = 0; i < h->omega_A - 1; i++) { ulong h = umodiu(MPQS_H(i), p) << 1; if (h > p) h -= p; MPQS_INV_A_H(i,j) = Fl_mul(h, inv_A2, p); /* 1/A * H[i] mod p_j */ } } } else /* "mpqs_self_init_B()" */ { /* no "real" computation -- use recursive formula */ /* The following exploits that B is the sum of omega_A terms +-H[i]. * Each time we switch to a new B, we choose a new pattern of signs; * the precomputation of the inv_A_H array allows us to change the * two arithmetic progressions equally fast. The choice of sign * patterns does *not* follow the bit pattern of the ordinal number * of B in the current cohort; rather, we use a Gray code, changing * only one sign each time. When the i-th rightmost bit of the new * ordinal number index_j of B is 1, the sign of H[i] is changed; * the next bit to the left tells us whether we should be adding or * subtracting the difference term. We never need to change the sign * of H[omega_A-1] (the topmost one), because that would just give us * the same sieve items Q(x) again with the opposite sign of x. This * is why we only precomputed inv_A_H up to i = omega_A - 2. */ ulong v2 = 0; /* 2-valuation of h->index_j */ j = h->index_j; /* could use vals() here, but we need to right shift the bit pattern * anyway in order to find out which inv_A_H entries must be added to or * subtracted from the modular roots */ while ((j & 1) == 0) { v2++; j >>= 1; } /* v2 = v_2(index_j), determine new starting positions for sieving */ p1 = shifti(MPQS_H(v2), 1); if (j & 2) { /* j = 3 mod 4 */ for (j = 3; (ulong)j <= size_of_FB; j++) { if (FB[j].fbe_flags & MPQS_FBE_DIVIDES_A) continue; p = (ulong)FB[j].fbe_p; FB[j].fbe_start1 = Fl_sub(FB[j].fbe_start1, MPQS_INV_A_H(v2,j), p); FB[j].fbe_start2 = Fl_sub(FB[j].fbe_start2, MPQS_INV_A_H(v2,j), p); } p1 = addii(B, p1); } else { /* j = 1 mod 4 */ for (j = 3; (ulong)j <= size_of_FB; j++) { if (FB[j].fbe_flags & MPQS_FBE_DIVIDES_A) continue; p = (ulong)FB[j].fbe_p; FB[j].fbe_start1 = Fl_add(FB[j].fbe_start1, MPQS_INV_A_H(v2,j), p); FB[j].fbe_start2 = Fl_add(FB[j].fbe_start2, MPQS_INV_A_H(v2,j), p); } p1 = subii(B, p1); } affii(p1, B); } avma = av; /* p=2 is a special case. start1[2], start2[2] are never looked at, * so don't bother setting them. */ /* "mpqs_self_init_common()" */ /* now compute zeros of polynomials that have only one zero mod p because p divides the coefficient A */ /* compute coefficient -C */ p1 = diviiexact(subii(h->kN, sqri(B)), shifti(A, 2)); for (i = 0; i < h->omega_A; i++) { ulong tmp, s; p = (ulong) MPQS_AP(i); tmp = Fl_div(umodiu(p1, p), umodiu(B, p), p); s = (tmp + h->M) % p; FB[MPQS_I(i)].fbe_start1 = (mpqs_int32_t)s; FB[MPQS_I(i)].fbe_start2 = (mpqs_int32_t)s; } if (MPQS_DEBUGLEVEL >= 6) { /* must happen before resetting avma, because of the absi() */ err_printf("MPQS: chose Q_%ld(x) = %Ps x^2 %c %Ps x + C\n", (long) h->index_j, h->A, signe(h->B) < 0? '-': '+', absi(h->B)); } avma = av; #ifdef MPQS_DEBUG /* stash C into the handle. Since check_root() is the only thing which * uses it, and only for debugging, C doesn't even exist as a field in * the handle unless we're built with MPQS_DEBUG. */ affii(negi(p1), h->C); for (j = 3; j <= size_of_FB; j++) { check_root(h, FB[j].fbe_p, FB[j].fbe_start1); check_root(h, FB[j].fbe_p, FB[j].fbe_start2); avma = av; } if (DEBUGLEVEL >= 6) PRINT_IF_VERBOSE("MPQS: checking of roots of Q(x) was successful\n"); #endif #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: leave self init, avma = 0x%lX\n", (ulong)avma); #endif } /*********************************************************************/ /** **/ /** THE SIEVE **/ /** **/ /*********************************************************************/ /* Main sieving routine: * p4 = 4*p (used for loop unrolling) * log_p: approximation for log(p) * begin: points to a sieve array * end: points to the end of the sieve array * starting_sieving_index: marks the first FB element used for sieving */ INLINE void mpqs_sieve_p(unsigned char *begin, unsigned char *end, long p4, long p, unsigned char log_p) { register unsigned char *e = end - p4; /* Loop unrolled some time ago. It might be better to let the compiler worry * about *this* kind of optimization, based on its knowledge of whatever * useful tricks the machine instruction set architecture is offering * ("speculative loads" being the buzzword). --GN */ while (e - begin >= 0) /* signed comparison */ { (*begin) += log_p, begin += p; (*begin) += log_p, begin += p; (*begin) += log_p, begin += p; (*begin) += log_p, begin += p; } while (end - begin >= 0) /* again */ (*begin) += log_p, begin += p; } static void mpqs_sieve(mpqs_handle_t *h) { long p, l = h->index1_FB; mpqs_FB_entry_t *ptr_FB; unsigned char *sieve_array = h->sieve_array; unsigned char *sieve_array_end = h->sieve_array_end; for (ptr_FB = &(h->FB[l]); (p = ptr_FB->fbe_p) != 0; ptr_FB++, l++) { unsigned char log_p = ptr_FB->fbe_logval; long start1 = ptr_FB->fbe_start1; long start2 = ptr_FB->fbe_start2; /* sieve with FB[l] from start_1[l] */ /* if start1 != start2 sieve with FB[l] from start_2[l] */ /* Maybe it is more efficient not to have a conditional branch in * the present loop body, and instead to right-shift log_p one bit * based on a flag bit telling us that we're on a one-root prime? * And instead roll the two invocations of mpqs_sieve_p into one. */ mpqs_sieve_p(sieve_array + start1, sieve_array_end, p << 2, p, log_p); if (start1 != start2) mpqs_sieve_p(sieve_array + start2, sieve_array_end, p << 2, p, log_p); } } /******************************/ /* Could make shameless use of the fact that M is divisible by 4, but * let the compiler worry about loop unrolling. Indeed I wonder whether * modern compilers woudln't have an easier time optimizing this if it * were written as array accesses. Doing so. */ static long mpqs_eval_sieve(mpqs_handle_t *h) { long x = 0, count = 0, M_2 = h->M << 1; /* TODO: replace the following by an auto-adjusting threshold driven * by histogram yield measurements */ unsigned char th = h->sieve_threshold; unsigned char *sieve_array = h->sieve_array; long *candidates = h->candidates; /* The following variation on the original is marginally faster with a * good optimizing compiler. Exploiting the sentinel, we don't need to * check for x < M_2 in the inner while loop - this more than makes up * for the "lack" of explicit unrolling. Optimizations like loop * unrolling are best left to the compiler anyway... */ while (count < MPQS_CANDIDATE_ARRAY_SIZE - 1) { while (sieve_array[x] < th) x++; if (x >= M_2) break; candidates[count++] = x++; } candidates[count] = 0; return count; } /*********************************************************************/ /** **/ /** CONSTRUCTING RELATIONS **/ /** **/ /*********************************************************************/ /* Main relation routine */ static void mpqs_add_factor(char **last, ulong ei, ulong pi) { sprintf(*last, " %lu %lu", ei, pi); *last += strlen(*last); } /* concatenate " 0" */ static void mpqs_add_0(char **last) { char *s = *last; *s++ = ' '; *s++ = '0'; *s++ = 0; *last = s; } #ifdef MPQS_DEBUG static GEN mpqs_factorback(mpqs_handle_t *h, char *relations) { char *s, *t = stack_strdup(relations), *tok; GEN N = h->N, prod = gen_1; long i; mpqs_FB_entry_t *FB = h->FB; s = paristrtok_r(t, " \n", &tok); while (s != NULL) { long e = atol(s); if (!e) break; s = paristrtok_r(NULL, " \n", &tok); i = atol(s); /* special case -1 */ if (i == 1) { prod = Fp_neg(prod,N); s = paristrtok_r(NULL, " \n", &tok); continue; } prod = Fp_mul(prod, Fp_powu(utoipos(FB[i].fbe_p), e, N), N); s = paristrtok_r(NULL, " \n", &tok); } return prod; } #endif /* NB FREL, LPREL are actually FNEW, LPNEW when we get called */ static long mpqs_eval_cand(mpqs_handle_t *h, long number_of_cand, FILE *FREL, FILE *LPREL) { pari_sp av; long number_of_relations = 0; char *relations = h->relations; long *relaprimes = h->relaprimes; ulong i, pi; mpqs_FB_entry_t *FB = h->FB; GEN A = h->A; GEN B = h->B; /* we don't need coefficient C here */ int pii; long *candidates = h->candidates; av = avma; #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: enter eval cand, avma = 0x%lX\n", (ulong)avma); #endif for (i = 0; i < (ulong)number_of_cand; i++, avma = av) { GEN Qx, Qx_part, A_2x_plus_B, Y; long powers_of_2, p; long x = candidates[i]; long x_minus_M = x - h->M; char *relations_end = relations; int relaprpos = 0; #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: eval loop 1, avma = 0x%lX\n", (ulong)avma); #endif *relations_end = 0; #ifdef MPQS_DEBUG_VERYVERBOSE err_printf("%c", (char)('0' + i%10)); #endif /* A_2x_plus_B = (A*(2x)+B), Qx = (A*(2x)+B)^2/(4*A) = Q(x) */ A_2x_plus_B = addii(mulis(A, x_minus_M << 1), B); Y = absi(A_2x_plus_B); Qx = subii(sqri(A_2x_plus_B), h->kN); #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: eval loop 2, avma = 0x%lX\n", (ulong)avma); #endif /* When N is relatively small, it may happen that Qx is outright * divisible by N at this point. In any case, when no extensive prior * trial division / Rho / ECM had been attempted, gcd(Qx,N) may turn * out to be a nontrivial factor of N (larger than what the FB contains * or we'd have found it already, but possibly smaller than the large- * prime bound). This is too rare to check for here in the inner loop, * but it will be caught if such an LP relation is ever combined with * another. */ /* Qx cannot possibly vanish here */ if (!signe(Qx)) { PRINT_IF_VERBOSE("<+>"); continue; } else if (signe(Qx) < 0) { setabssign(Qx); mpqs_add_factor(&relations_end, 1, 1); /* i = 1, ei = 1, pi */ } /* divide by powers of 2; we're really dealing with 4*A*Q(x), so we * always have at least 2^2 here, and at least 2^3 when kN is 1 mod 4 */ powers_of_2 = vali(Qx); Qx = shifti(Qx, -powers_of_2); mpqs_add_factor(&relations_end, powers_of_2, 2); /* That has dealt with a possible -1 and the power of 2. First pass * over odd primes in FB: pick up all possible divisors of Qx including * those sitting in k or in A, and remember them in relaprimes. Do not * yet worry about possible repeated factors, these will be found in the * second pass. */ Qx_part = A; /* The first pass recognizes divisors of A by their corresponding flags * bit in the FB entry. (Divisors of k require no special treatment at * this stage.) We construct a preliminary table of FB subscripts and * "exponents" of the FB primes which divide Qx. (We store subscripts * rather than the primes themselves because the string representation * of a relation is in terms of the subscripts.) * We must distinguish three cases so we can do the right thing in the * 2nd pass: prime not in A which divides Qx, prime in A which does not * divide Qx/A, prime in A which does divide Qx/A. The first and third * kinds need checking for repeated factors, the second kind doesn't. The * first and second kinds contribute 1 to the exponent in the relation, * the 3rd kind contributes 2. We store 1,0,2 respectively in these three * cases. * Factors in common with k are much simpler - if they occur, they occur * exactly to the first power, and this makes no difference in the first * pass - here they behave just like every normal odd factor base prime. */ for (pi = 3; (p = FB[pi].fbe_p); pi++) { long tmp_p = x % p; ulong ei = 0; /* Here we use that MPQS_FBE_DIVIDES_A equals 1. */ ei = FB[pi].fbe_flags & MPQS_FBE_DIVIDES_A; if (tmp_p == FB[pi].fbe_start1 || tmp_p == FB[pi].fbe_start2) { /* p divides Q(x)/A (and possibly A), 1st or 3rd case */ relaprimes[relaprpos++] = pi; relaprimes[relaprpos++] = 1 + ei; Qx_part = muliu(Qx_part, p); } else if (ei) { /* p divides A but does not divide Q(x)/A, 2nd case */ relaprimes[relaprpos++] = pi; relaprimes[relaprpos++] = 0; } } /* We have now accumulated the known factors of Qx except for possible * repeated factors and for possible large primes. Divide off what we * have. (This is faster than dividing off A and each prime separately.) */ Qx = diviiexact(Qx, Qx_part); /* (ToDo: MPQS_DEBUG sanity check...) */ #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: eval loop 3, avma = 0x%lX\n", (ulong)avma); #endif /* second pass - deal with any repeated factors, and write out the string * representation of the tentative relation. At this point, the only * primes which can occur again in the adjusted Qx are those in relaprimes * which are followed by 1 or 2. We must pick up those followed by a 0, * too, though. */ PRINT_IF_VERBOSE("a"); for (pii = 0; pii < relaprpos; pii+=2) { long remd_p; ulong ei = relaprimes[pii+1]; GEN Qx_div_p; pi = relaprimes[pii]; /* Here, prime factors of k go their separate way. We could have * introduced another FB entry flag for marking them, but it is easier * to identify them just by their position before index0_FB. */ if ((mpqs_int32_t)pi < h->index0_FB) { #ifdef MPQS_DEBUG PRINT_IF_VERBOSE("\bk!"); #endif mpqs_add_factor(&relations_end, 1, pi); continue; } if (ei == 0) /* p divides A and that was it */ { mpqs_add_factor(&relations_end, 1, pi); continue; } p = FB[pi].fbe_p; #ifdef MPQS_DEBUG_CANDIDATE_EVALUATION err_printf("MPQS DEBUG: Qx=%Ps p=%ld\n", Qx, (long)p); #endif /* otherwise p might still divide the current adjusted Qx. Try it... */ /* NOTE: break out of loop when remaining Qx is 1 ? Or rather, suppress * the trial divisions, since we still need to write our string. * Actually instead of testing for 1, test whether Qx is smaller than p; * cf Karim's mail from 20050124. If it is, without being 1, then it has * a common factor with k. But those factors are soon going to have * disappeared before we get here. However, inserting * an explicit if (!is_pm1(Qx)) here did not help any. */ Qx_div_p = divis_rem(Qx, p, &remd_p); while (remd_p == 0) { ei++; Qx = Qx_div_p; Qx_div_p = divis_rem(Qx, p, &remd_p); } mpqs_add_factor(&relations_end, ei, pi); } #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: eval loop 4, avma = 0x%lX\n", (ulong)avma); #endif PRINT_IF_VERBOSE("\bb"); if (is_pm1(Qx)) { mpqs_add_0(&relations_end); fprintf(FREL, "%s :%s\n", itostr(Y), relations); number_of_relations++; #ifdef MPQS_USE_HISTOGRAMS /* bump full relations counter at candidate's value */ if (h->do_histograms) h->histo_full[sa[x]-128]++; #endif #ifdef MPQS_DEBUG { pari_sp av1 = avma; GEN rhs = mpqs_factorback(h, relations); GEN Qx_2 = remii(sqri(Y), h->N); if (!equalii(Qx_2, rhs)) { PRINT_IF_VERBOSE("\b(!)\n"); err_printf("MPQS: %Ps @ %Ps :%s\n", Y, Qx, relations); err_printf("\tQx_2 = %Ps\n", Qx_2); err_printf("\t rhs = %Ps\n", rhs); pari_err_BUG("MPQS: wrong full relation found"); } else PRINT_IF_VERBOSE("\b(:)"); avma = av1; } #endif } else if (cmpis(Qx, h->lp_bound) > 0) { /* TODO: check for double large prime */ #ifdef MPQS_USE_HISTOGRAMS /* bump useless-candidates counter at candidate's value */ if (h->do_histograms) h->histo_drop[sa[x]-128]++; #endif PRINT_IF_VERBOSE("\b."); } else { /* if (mpqs_isprime(itos(Qx))) */ mpqs_add_0(&relations_end); fprintf(LPREL, "%s @ %s :%s\n", itostr(Qx), itostr(Y), relations); #ifdef MPQS_USE_HISTOGRAMS /* bump LP relations counter at candidate's value */ if (h->do_histograms) h->histo_lprl[sa[x]-128]++; #endif #ifdef MPQS_DEBUG { pari_sp av1 = avma; GEN rhs = mpqs_factorback(h, relations); GEN Qx_2 = remii(sqri(Y), h->N); rhs = modii(mulii(rhs, Qx), h->N); if (!equalii(Qx_2, rhs)) { PRINT_IF_VERBOSE("\b(!)\n"); err_printf("MPQS: %Ps @ %Ps :%s\n", Y, Qx, relations); err_printf("\tQx_2 = %Ps\n", Qx_2); err_printf("\t rhs = %Ps\n", rhs); pari_err_BUG("MPQS: wrong large prime relation found"); } else PRINT_IF_VERBOSE("\b(;)"); avma = av1; } #endif } #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: eval loop end, avma = 0x%lX\n", (ulong)avma); #endif } /* for */ PRINT_IF_VERBOSE("\n"); #ifdef MPQS_DEBUG_AVMA err_printf("MPQS DEBUG: leave eval cand, avma = 0x%lX\n", (ulong)avma); #endif return number_of_relations; } /*********************************************************************/ /** **/ /** COMBINING RELATIONS **/ /** **/ /*********************************************************************/ /* combines the large prime relations in COMB to full relations in FNEW. * FNEW is assumed to be open for writing / appending. */ typedef struct { long q; char Y[MPQS_STRING_LENGTH]; char E[MPQS_STRING_LENGTH]; } mpqs_lp_entry; static void mpqs_set_exponents(long *ei, char *r) { char *s, b[MPQS_STRING_LENGTH], *tok; long e; strcpy(b, r); s = paristrtok_r(b, " \n", &tok); while (s != NULL) { e = atol(s); if (!e) break; s = paristrtok_r(NULL, " \n", &tok); ei[ atol(s) ] += e; s = paristrtok_r(NULL, " \n", &tok); } } static void set_lp_entry(mpqs_lp_entry *e, char *buf) { char *s1, *s2; s1 = buf; s2 = strchr(s1, ' '); *s2 = '\0'; e->q = atol(s1); s1 = s2 + 3; s2 = strchr(s1, ' '); *s2 = '\0'; strcpy(e->Y, s1); s1 = s2 + 3; s2 = strchr(s1, '\n'); *s2 = '\0'; strcpy(e->E, s1); } static long mpqs_combine_large_primes(mpqs_handle_t *h, FILE *COMB, pariFILE *pFNEW, GEN *f) { pari_sp av0 = avma, av, av2; char new_relation[MPQS_STRING_LENGTH], buf[MPQS_STRING_LENGTH]; mpqs_lp_entry e[2]; /* we'll use the two alternatingly */ long *ei, ei_size = h->size_of_FB + 2; long old_q; GEN inv_q, Y1, Y2, new_Y, new_Y1; long i, l, c = 0; *f = NULL; if (!fgets(buf, MPQS_STRING_LENGTH, COMB)) return 0; /* should not happen */ ei = (long *) new_chunk(ei_size); av = avma; /* put first lp relation in row 0 of e */ set_lp_entry(&e[0], buf); i = 1; /* second relation will go into row 1 */ old_q = e[0].q; while (!invmod(utoipos(old_q), h->N, &inv_q)) /* can happen */ { inv_q = gcdii(inv_q, h->N); /* inv_q can no longer be 1 here (it could while we were doing this mod * kN instead of mod N), but never mind - we're not in the fast path * at this point. It could be N when N is quite small; or we might * just have found a divisor by sheer luck. */ if (is_pm1(inv_q) || equalii(inv_q, h->N)) /* pity */ { #ifdef MPQS_DEBUG err_printf("MPQS: skipping relation with non-invertible q\n"); #endif if (!fgets(buf, MPQS_STRING_LENGTH, COMB)) { avma = av0; return 0; } avma = av; set_lp_entry(&e[0], buf); old_q = e[0].q; continue; } *f = gerepileuptoint(av0, inv_q); return c; } Y1 = strtoi(e[0].Y); av2 = avma; /* preserve inv_q and Y1 */ while (fgets(buf, MPQS_STRING_LENGTH, COMB)) { set_lp_entry(&e[i], buf); if (e[i].q != old_q) { /* switch to combining a new bunch, swapping the rows */ old_q = e[i].q; avma = av; /* discard old inv_q and Y1 */ if (!invmod(utoipos(old_q), h->N, &inv_q)) /* can happen --GN */ { inv_q = gcdii(inv_q, h->N); if (is_pm1(inv_q) || equalii(inv_q, h->N)) /* pity */ { #ifdef MPQS_DEBUG err_printf("MPQS: skipping relation with non-invertible q\n"); #endif old_q = -1; /* sentinel */ av2 = avma = av; continue; /* discard this combination */ } *f = gerepileuptoint(av0, inv_q); return c; } Y1 = strtoi(e[i].Y); i = 1 - i; /* subsequent relations go to other row */ av2 = avma; /* preserve inv_q and Y1 */ continue; } /* count and combine the two we've got, and continue in the same row */ c++; memset((void *)ei, 0, ei_size * sizeof(long)); mpqs_set_exponents(ei, e[0].E); mpqs_set_exponents(ei, e[1].E); Y2 = strtoi(e[i].Y); new_Y = modii(mulii(mulii(Y1, Y2), inv_q), h->N); new_Y1 = subii(h->N, new_Y); if (absi_cmp(new_Y1, new_Y) < 0) new_Y = new_Y1; strcpy(new_relation, itostr(new_Y)); strcat(new_relation, " :"); if (ei[1] & 1) strcat(new_relation, " 1 1"); for (l = 2; l < ei_size; l++) if (ei[l]) { sprintf(buf, " %ld %ld", ei[l], l); strcat(new_relation, buf); } strcat(new_relation, " 0"); if (DEBUGLEVEL >= 6) { err_printf("MPQS: combining\n"); err_printf(" {%ld @ %s : %s}\n", old_q, e[1-i].Y, e[1-i].E); err_printf(" * {%ld @ %s : %s}\n", e[i].q, e[i].Y, e[i].E); err_printf(" == {%s}\n", new_relation); } strcat(new_relation, "\n"); #ifdef MPQS_DEBUG { GEN Qx_2, prod; char *s = strchr(new_relation, ':') + 2; pari_sp av1 = avma; Qx_2 = modii(sqri(new_Y), h->N); prod = mpqs_factorback(h, s); if (!equalii(Qx_2, prod)) pari_err_BUG("MPQS: combined large prime relation is false"); avma = av1; } #endif pari_fputs(new_relation, pFNEW); avma = av2; } /* while */ if (DEBUGLEVEL >= 4) err_printf("MPQS: combined %ld full relation%s\n", c, (c!=1 ? "s" : "")); avma = av0; return c; } /*********************************************************************/ /** **/ /** FROM RELATIONS TO DIVISORS **/ /** **/ /*********************************************************************/ /* create and read an F2m from a relation file FREL. * Also record the position of each relation in the file for later use * rows = size_of_FB+1, cols = rel */ static GEN stream_read_F2m(pariFILE *pFREL, long rows, long cols, long *fpos) { FILE *FREL = pFREL->file; long i, e, p; char buf[MPQS_STRING_LENGTH], *s; GEN m; long space = 2*((nbits2nlong(rows)+3)*cols+1); if ((long)((GEN)avma - (GEN)bot) < space) { pari_sp av = avma; m = gclone(zero_F2m(rows, cols)); if (DEBUGLEVEL>=4) err_printf("MPQS: allocating %ld words for Gauss\n",space); avma = av; } else m = zero_F2m_copy(rows, cols); for (i = 0;; i++) { char *tok=NULL; if (i < cols && (fpos[i] = ftell(FREL)) < 0) pari_err_FILE("full relations file [ftell]", pFREL->name); if (!fgets(buf, MPQS_STRING_LENGTH, FREL)) break; s = strchr(buf, ':'); if (!s) pari_err_FILE("full relations file [strchr]", pFREL->name); s = paristrtok_r(s+2, " \n", &tok); while (s != NULL) { e = atol(s); if (!e) break; s = paristrtok_r(NULL, " \n", &tok); p = atol(s); if (e & 1) F2m_set(m, p, i+1); s = paristrtok_r(NULL, " \n", &tok); } } if (i != cols) { err_printf("MPQS: full relations file %s than expected", i > cols ? "longer" : "shorter"); pari_err(e_BUG, "MPQS [panicking]"); } return m; } /* NB: overwrites rel */ static GEN mpqs_add_relation(GEN Y_prod, GEN N, long *ei, char *rel) { pari_sp av = avma; GEN res; char *s, *tok=NULL; s = strchr(rel, ':') - 1; *s = '\0'; res = remii(mulii(Y_prod, strtoi(rel)), N); s = paristrtok_r(s + 3, " \n", &tok); while (s != NULL) { long e = atol(s), i; if (!e) break; s = paristrtok_r(NULL, " \n", &tok); i = atol(s); /* bug in g++-3.4.1: miscompiles ei[ atol(s) ] */ ei[i] += e; s = paristrtok_r(NULL, " \n", &tok); } return gerepileuptoint(av, res); } static char* mpqs_get_relation(char *buf, long pos, pariFILE *pFREL) { if (fseek(pFREL->file, pos, SEEK_SET)) pari_err_FILE("FREL file [fseek]", pFREL->name); if (!fgets(buf, MPQS_STRING_LENGTH, pFREL->file)) pari_err_FILE("FREL file [fgets]", pFREL->name); return buf; } #define isprobableprime(n) (MR_Jaeschke((n),17)) static int split(GEN N, GEN *e, GEN *res) { ulong mask; long flag; GEN base; if (isprobableprime(N)) { *e = gen_1; return 1; } if (Z_issquareall(N, &base)) { /* squares could cost us a lot of time */ /* GN20050707: as used now, this is always called with res!=NULL */ *res = base; *e = gen_2; if (DEBUGLEVEL >= 5) err_printf("MPQS: decomposed a square\n"); return 1; } mask = 7; /* 5th/7th powers aren't worth the trouble. OTOH once we have the hooks for * dealing with cubes, higher powers can be handled essentially for free) */ if ( (flag = is_357_power(N, &base, &mask)) ) { *res = base; *e = utoipos(flag); if (DEBUGLEVEL >= 5) err_printf("MPQS: decomposed a %s\n", (flag == 3 ? "cube" : (flag == 5 ? "5th power" : "7th power"))); return 1; } *e = gen_0; return 0; /* known composite */ } static GEN 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; long *fpos, *ei; long i, j, H_cols, H_rows; long res_last, res_next, res_size, res_max; GEN m, ker_m; long done, rank; char buf[MPQS_STRING_LENGTH]; fpos = (long *) pari_malloc(rel * sizeof(long)); m = stream_read_F2m(pFREL, h->size_of_FB+1, rel, fpos); if (DEBUGLEVEL >= 7) err_printf("\\\\ MATRIX READ BY MPQS\nFREL=%Ps\n",m); ker_m = F2m_ker_sp(m,0); rank = lg(ker_m)-1; if (isclone(m)) gunclone(m); if (DEBUGLEVEL >= 4) { if (DEBUGLEVEL >= 7) { err_printf("\\\\ KERNEL COMPUTED BY MPQS\n"); err_printf("KERNEL=%Ps\n",ker_m); } err_printf("MPQS: Gauss done: kernel has rank %ld, taking gcds...\n", rank); } H_rows = rel; H_cols = rank; if (!H_cols) { /* trivial kernel. Fail gracefully: main loop may look for more relations */ if (DEBUGLEVEL >= 3) pari_warn(warner, "MPQS: no solutions found from linear system solver"); pari_free(fpos); /* ei not yet allocated */ avma = av; return NULL; /* no factors found */ } /* If the rank is r, we can expect up to 2^r pairwise coprime factors, * but it may happen that a kernel basis vector contributes nothing new to * the decomposition. We allocate room for up to eight factors initially * (certainly adequate when one or two basis vectors work), adjusting this * down at the end to what we actually found, or up if we are very lucky and * find more factors. In the upper half of our vector, we store information * 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); if (rank > (long)BITS_IN_LONG - 2) res_max = LONG_MAX; /* the common case, unfortunately */ else res_max = 1L<size_of_FB + 2) * sizeof(long)); for (i = 1; i <= H_cols; i++) { /* loop over kernel basis */ X = Y_prod = gen_1; memset((void *)ei, 0, (h->size_of_FB + 2) * sizeof(long)); av3 = avma; lim3 = stack_lim(av3,1); 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(DEBUGMEM>1) pari_warn(warnmem,"[1]: mpqs_solve_linear_system"); Y_prod = gerepileuptoint(av3, Y_prod); } } Y_prod = gerepileuptoint(av3, Y_prod); av3 = avma; lim3 = stack_lim(av3,1); for (j = 2; j <= h->size_of_FB + 1; j++) if (ei[j]) { if (ei[j] & 1) pari_err_BUG("MPQS (relation is a nonsquare)"); 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(DEBUGMEM>1) pari_warn(warnmem,"[2]: mpqs_solve_linear_system"); X = gerepileupto(av3, X); } } X = gerepileuptoint(av3, X); if (MPQS_DEBUGLEVEL >= 1) { if (signe(remii(subii(sqri(X), sqri(Y_prod)), N))) { /* shouldn't happen */ err_printf("MPQS: X^2 - Y^2 != 0 mod N\n"); err_printf("\tindex i = %ld\n", i); pari_warn(warner, "MPQS: wrong relation found after Gauss"); } } /* At this point, X^2 == Y^2 mod N. Indeed, something stronger is true: * We have gcd(X-Y, N) * gcd(X+Y, N) == N. Why? * First, N divides X^2 - Y^2, so it divides the lefthand side. * Second, let P be any prime factor of N. If P were to divide both * X-Y and X+Y, then it would divide their sum 2X. But X (in the present * backwards notation!) is a product of powers of FB primes, and no FB * prime is a divisor of N, or we would have found out about it already * whilst constructing the FB. * Therefore in the following it is sufficient to work with gcd(X+Y, N) * alone, and never look at gcd(X-Y, N). */ done = 0; /* (re-)counts probably-prime factors (or powers whose bases we * don't want to handle any further) */ X_plus_Y = addii(X, Y_prod); if (res_next < 3) { /* we still haven't decomposed the original N, and want both a gcd and * its cofactor. */ D1 = gcdii(X_plus_Y, N); if (is_pm1(D1) || equalii(D1,N)) { avma = av3; continue; } /* got something that works */ if (DEBUGLEVEL >= 5) err_printf("MPQS: splitting N after %ld kernel vector%s\n", i+1, (i? "s" : "")); /* GN20050707 Fixed: * Don't divide N in place. We still need it for future X and Y_prod * computations! */ gel(res,1) = diviiexact(N, D1); gel(res,2) = D1; res_last = res_next = 3; if ( split(gel(res,1), &gel(res,res_size+1), &gel(res,1)) ) done++; if ( split(D1, &gel(res,res_size+2), &gel(res,2)) ) done++; if (done == 2) break; /* both factors look prime or were powers */ /* GN20050707: moved following line down to here, was before the * two split() invocations. Very rare case anyway. */ if (res_max == 2) break; /* two out of two possible factors seen */ if (DEBUGLEVEL >= 5) err_printf("MPQS: got two factors, looking for more...\n"); } else { /* we already have factors */ for (j=1; j < res_next; j++) { /* loop over known-composite factors */ if (gel(res,res_size+j) && gel(res,res_size+j) != gen_0) { done++; continue; /* skip probable primes etc */ } /* actually, also skip square roots of squares etc. They are a lot * smaller than the original N, and should be easy to deal with later */ av3 = avma; D1 = gcdii(X_plus_Y, gel(res,j)); if (is_pm1(D1) || equalii(D1, gel(res,j))) { avma = av3; continue; } /* got one which splits this factor */ if (DEBUGLEVEL >= 5) err_printf("MPQS: resplitting a factor after %ld kernel vectors\n", i+1); /* always plural */ /* first make sure there's room for another factor */ if (res_next > res_size) { /* need to reallocate (_very_ rare case) */ long i1, size = 2*res_size; GEN RES; if (size > res_max) size = res_max; RES = cgetg(2*size+1, t_VEC); for (i1=2*size; i1>=res_next; i1--) gel(RES,i1) = NULL; for (i1=1; i1 res_max) { /* all possible factors seen, outer loop postprocessing will * proceed to break out of the outer loop below. */ break; } } /* loop over known composite factors */ if (res_next > res_last) { res_last = res_next - 1; /* we might have resplit more than one */ if (DEBUGLEVEL >= 5) err_printf("MPQS: got %ld factors%s\n", res_last, (done < res_last ? ", looking for more..." : "")); res_last = res_next; } /* break out of the outer loop when we have seen res_max factors, and * 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))) { long i1; if(DEBUGMEM>1) pari_warn(warnmem,"[3]: mpqs_solve_linear_system"); /* gcopy would have a problem with our NULL pointers... */ new_res = cgetg(lg(res), t_VEC); for (i1=2*res_size; i1>=res_next; i1--) new_res[i1] = 0; for (i1=1; i1= 6) err_printf("MPQS: wrapping up vector of %ld factors\n", res_last); for (i=1,j=1; i <= res_last; i++) { GEN F = gel(res, res_size+i); icopyifstack(gel(res,i), gel(new_res,j++)); /* factor */ gel(new_res,j++) = /* exponent */ F ? (F == gen_0 ? gen_1 : (isonstack(F) ? icopy(F) : F)) : gen_1; /* F was NULL */ gel(new_res,j++) = /* class */ F == gen_0 ? gen_0 : /* known composite */ NULL; /* base of power or suspected prime -- mark as `unknown' */ if (DEBUGLEVEL >= 6) err_printf("\tpackaging %ld: %Ps ^%ld (%s)\n", i, res[i], itos(gel(new_res,j-2)), (F == gen_0 ? "comp." : "unknown")); } return gerepileupto(av, new_res); } /*********************************************************************/ /** **/ /** MAIN ENTRY POINT AND DRIVER ROUTINE **/ /** **/ /*********************************************************************/ /* All percentages below are actually fixed-point quantities scaled by 10 * (value of 1 means 0.1%, 1000 means 100%) */ /* Factors N using the self-initializing multipolynomial quadratic sieve * (SIMPQS). Returns one of the two factors, or (usually) a vector of factors * and exponents and information about which ones are still composite, or NULL * when something goes wrong or when we can't seem to make any headway. */ /* TODO: this function to be renamed mpqs_main() with several extra parameters, * with mpqs() as a wrapper for the standard case, so we can do partial runs * across several machines etc. (from gp or a dedicated C program). --GN */ static GEN mpqs_i(mpqs_handle_t *handle) { GEN N = handle->N, fact; /* will in the end hold our factor(s) */ mpqs_int32_t size_of_FB; /* size of the factor base */ mpqs_FB_entry_t *FB; /* factor base */ mpqs_int32_t M; /* sieve interval size [-M, M] */ /* local loop / auxiliary vars */ ulong p; /* already exists in the handle, keep for convenience */ long lp_bound; /* size limit for large primes */ long lp_scale; /* ...relative to largest FB prime */ /* bookkeeping */ long tc; /* # of candidates found in one iteration */ long tp; /* # of recently sorted LP rels */ long tff = 0; /* # recently found full rels from sieving */ long tfc; /* # full rels recently combined from LPs */ double tfc_ratio = 0; /* recent (tfc + tff) / tff */ ulong sort_interval; /* determine when to sort and merge */ ulong followup_sort_interval; /* temporary files (scaled percentages) */ long percentage = 0; /* scaled by 10, see comment above */ double net_yield; long total_full_relations = 0, total_partial_relations = 0, total_no_cand = 0; long vain_iterations = 0, good_iterations = 0, iterations = 0; #ifdef MPQS_USE_HISTOGRAMS long histo_checkpoint = MPQS_MIN_CANDS_FOR_HISTO; #endif pariFILE *pFNEW, *pLPNEW, *pCOMB, *pFREL, *pLPREL; char *dir, *COMB_str, *FREL_str, *FNEW_str, *LPREL_str, *LPNEW_str, *TMP_str; pari_timer T; /* END: global variables to disappear as soon as possible */ /******************************/ pari_sp av = avma; if (DEBUGLEVEL >= 4) { timer_start(&T); err_printf("MPQS: number to factor N = %Ps\n", N); } handle->digit_size_N = decimal_len(N); if (handle->digit_size_N > MPQS_MAX_DIGIT_SIZE_KN) { pari_warn(warner, "MPQS: number too big to be factored with MPQS,\n\tgiving up"); return NULL; } if (DEBUGLEVEL >= 4) err_printf("MPQS: factoring number of %ld decimal digits\n", handle->digit_size_N); p = mpqs_find_k(handle); if (p) { avma = av; return utoipos(p); } if (DEBUGLEVEL >= 5) err_printf("MPQS: found multiplier %ld for N\n", handle->_k->k); handle->kN = muliu(N, handle->_k->k); if (!mpqs_set_parameters(handle)) { pari_warn(warner, "MPQS: number too big to be factored with MPQS,\n\tgiving up"); return NULL; } size_of_FB = handle->size_of_FB; M = handle->M; sort_interval = handle->first_sort_point; followup_sort_interval = handle->sort_pt_interval; if (DEBUGLEVEL >= 5) err_printf("MPQS: creating factor base and allocating arrays...\n"); FB = mpqs_create_FB(handle, &p); if (p) { avma = av; return utoipos(p); } mpqs_sieve_array_ctor(handle); mpqs_poly_ctor(handle); lp_bound = handle->largest_FB_p; if (lp_bound > MPQS_LP_BOUND) lp_bound = MPQS_LP_BOUND; /* don't allow large primes to have room for two factors both bigger than * what the FB contains (...yet!) */ lp_scale = handle->lp_scale; if (lp_scale >= handle->largest_FB_p) lp_scale = handle->largest_FB_p - 1; lp_bound *= lp_scale; handle->lp_bound = lp_bound; handle->dkN = gtodouble(handle->kN); /* compute the threshold and fill in the byte-sized scaled logarithms */ mpqs_set_sieve_threshold(handle); if (!mpqs_locate_A_range(handle)) return NULL; if (DEBUGLEVEL >= 4) { err_printf("MPQS: sieving interval = [%ld, %ld]\n", -(long)M, (long)M); /* that was a little white lie, we stop one position short at the top */ err_printf("MPQS: size of factor base = %ld\n", (long)size_of_FB); err_printf("MPQS: striving for %ld relations\n", (long)handle->target_no_rels); err_printf("MPQS: coefficients A will be built from %ld primes each\n", (long)handle->omega_A); err_printf("MPQS: primes for A to be chosen near FB[%ld] = %ld\n", (long)handle->index2_FB, (long)FB[handle->index2_FB].fbe_p); err_printf("MPQS: smallest prime used for sieving FB[%ld] = %ld\n", (long)handle->index1_FB, (long)FB[handle->index1_FB].fbe_p); err_printf("MPQS: largest prime in FB = %ld\n", (long)handle->largest_FB_p); err_printf("MPQS: bound for `large primes' = %ld\n", (long)lp_bound); } if (DEBUGLEVEL >= 5) { err_printf("MPQS: sieve threshold = %u\n", (unsigned int)handle->sieve_threshold); } if (DEBUGLEVEL >= 4) { err_printf("MPQS: first sorting at %ld%%, then every %3.1f%% / %3.1f%%\n", sort_interval/10, followup_sort_interval/10., followup_sort_interval/20.); } /* main loop which * - computes polynomials and their zeros (SI) * - does the sieving * - tests candidates of the sieve array */ /* Let (A, B_i) the current pair of coeffs. If i == 0 a new A is generated */ handle->index_j = (mpqs_uint32_t)-1; /* increment below will have it start at 0 */ if (DEBUGLEVEL >= 5) err_printf("MPQS: starting main loop\n"); /* compute names for the temp files we'll need */ dir = pari_unique_dir("MPQS"); TMP_str = mpqs_get_filename(dir, "LPTMP"); FREL_str = mpqs_get_filename(dir, "FREL"); FNEW_str = mpqs_get_filename(dir, "FNEW"); LPREL_str = mpqs_get_filename(dir, "LPREL"); LPNEW_str = mpqs_get_filename(dir, "LPNEW"); COMB_str = mpqs_get_filename(dir, "COMB"); #define unlink_all()\ pari_unlink(FREL_str);\ pari_unlink(FNEW_str);\ pari_unlink(LPREL_str);\ pari_unlink(LPNEW_str);\ if (pCOMB) pari_unlink(COMB_str);\ rmdir(dir); pari_free(dir); pFREL = pari_fopen_or_fail(FREL_str, WRITE); pari_fclose(pFREL); pLPREL = pari_fopen_or_fail(LPREL_str, WRITE); pari_fclose(pLPREL); pFNEW = pari_fopen_or_fail(FNEW_str, WRITE); pLPNEW= pari_fopen_or_fail(LPNEW_str, WRITE); pCOMB = NULL; for(;;) { /* FNEW and LPNEW are open for writing */ iterations++; /* self initialization: compute polynomial and its zeros */ mpqs_self_init(handle); if (handle->bin_index == 0) { /* have run out of primes for A */ /* We might change some parameters. For the moment, simply give up */ if (DEBUGLEVEL >= 2) err_printf("MPQS: Ran out of primes for A, giving up.\n"); pari_fclose(pFNEW); pari_fclose(pLPNEW); /* FREL, LPREL are closed at this point */ unlink_all(); avma = av; return NULL; } memset((void*)(handle->sieve_array), 0, (M << 1) * sizeof(unsigned char)); mpqs_sieve(handle); tc = mpqs_eval_sieve(handle); total_no_cand += tc; if (DEBUGLEVEL >= 6) err_printf("MPQS: found %lu candidate%s\n", tc, (tc==1? "" : "s")); if (tc) { long t = mpqs_eval_cand(handle, tc, pFNEW->file, pLPNEW->file); total_full_relations += t; tff += t; good_iterations++; } #ifdef MPQS_USE_HISTOGRAMS if (handle->do_histograms && !handle->done_histograms && total_no_cand >= histo_checkpoint) { int res = mpqs_eval_histograms(handle); if (res >= 0) { /* retry later */ if (res > 0) /* histo_checkpoint *= 2.6; */ handle->do_histograms = 0; /* no, don't retry later */ else histo_checkpoint += (MPQS_MIN_CANDS_FOR_HISTO /* >> 1 */); } else handle->done_histograms = 1; } #endif percentage = (long)((1000.0 * total_full_relations) / handle->target_no_rels); if ((ulong)percentage < sort_interval) continue; /* most main loops continue here! */ /* Extra processing when we have completed a sort interval: */ if (DEBUGLEVEL >= 3) { if (DEBUGLEVEL >= 4) err_printf("\nMPQS: passing the %3.1f%% sort point, time = %ld ms\n", sort_interval/10., timer_delay(&T)); else err_printf("\nMPQS: passing the %3.1f%% sort point\n", sort_interval/10.); err_flush(); } /* sort LPNEW and merge it into LPREL, diverting combinables into COMB */ pari_fclose(pLPNEW); (void)mpqs_sort_lp_file(LPNEW_str); pCOMB = pari_fopen_or_fail(COMB_str, WRITE); tp = mpqs_mergesort_lp_file(LPREL_str, LPNEW_str, TMP_str, pCOMB); pari_fclose(pCOMB); pLPNEW = pari_fopen_or_fail(LPNEW_str, WRITE); /* combine whatever there is to be combined */ tfc = 0; if (tp > 0) { /* build full relations out of large prime relations */ pCOMB = pari_fopen_or_fail(COMB_str, READ); tfc = mpqs_combine_large_primes(handle, pCOMB->file, pFNEW, &fact); pari_fclose(pCOMB); /* now FREL, LPREL are closed and FNEW, LPNEW are still open */ if (fact) { /* factor found during combining */ if (DEBUGLEVEL >= 4) { err_printf("\nMPQS: split N whilst combining, time = %ld ms\n", timer_delay(&T)); err_printf("MPQS: found factor = %Ps\n", fact); } pari_fclose(pLPNEW); pari_fclose(pFNEW); unlink_all(); return gerepileupto(av, fact); } total_partial_relations += tp; } /* sort FNEW and merge it into FREL */ pari_fclose(pFNEW); (void)mpqs_sort_lp_file(FNEW_str); /* definitive count (combinables combined, and duplicates removed) */ total_full_relations = mpqs_mergesort_lp_file(FREL_str, FNEW_str, TMP_str, NULL); /* FNEW stays closed until we need to reopen it for another iteration */ /* Due to the removal of duplicates, percentage may actually decrease at * this point. Looks funny in the diagnostics but is nothing to worry * about: we _are_ making progress. */ percentage = (long)((1000.0 * total_full_relations) / handle->target_no_rels); net_yield = (total_full_relations * 100.) / (total_no_cand ? total_no_cand : 1); vain_iterations = (long)((1000.0 * (iterations - good_iterations)) / iterations); /* Now estimate the current full relations yield rate: we directly see * each time through the main loop how many full relations we're getting * as such from the sieve (tff since the previous checkpoint), but * only at checkpoints do we see how many we're typically combining * (tfc). So we're really producing (tfc+tff)/tff as many full rels, * and when we get close to 100%, we should bias the next interval by * the inverse ratio. * Avoid drawing conclusions from too-small samples during very short * follow-on intervals (in this case we'll just re-use an earlier * estimated ratio). */ if ((tfc >= 16) && (tff >= 20)) tfc_ratio = (tfc + tff + 0.) / tff; /* floating-point division */ tff = 0; /* reset this count (tfc is always fresh) */ if (percentage >= 1000) /* when Gauss had failed */ sort_interval = percentage + 2; else if (percentage >= 820) { if (tfc_ratio > 1.) { if (percentage + (followup_sort_interval >> 1) * tfc_ratio > 994) { /* aim for a _slight_ overshoot */ sort_interval = (ulong)(percentage + 2 + (1000 - percentage) / tfc_ratio); } else if (percentage >= 980) sort_interval = percentage + 8; else sort_interval = percentage + (followup_sort_interval >> 1); } else { if (percentage >= 980) sort_interval = percentage + 10; else sort_interval = percentage + (followup_sort_interval >> 1); if (sort_interval >= 1000 && percentage < 1000) sort_interval = 1000; } } else sort_interval = percentage + followup_sort_interval; if (DEBUGLEVEL >= 4) { err_printf("MPQS: done sorting%s, time = %ld ms\n", tp > 0 ? " and combining" : "", timer_delay(&T)); err_printf("MPQS: found %3.1f%% of the required relations\n", percentage/10.); if (DEBUGLEVEL >= 5) { /* total_full_relations are always plural */ /* GN20050708: present code doesn't succeed in discarding all * dups, so don't lie about it... */ err_printf("MPQS: found %ld full relations\n", total_full_relations); if (lp_scale > 1) err_printf("MPQS: (%ld of these from partial relations)\n", total_partial_relations); err_printf("MPQS: Net yield: %4.3g full relations per 100 candidates\n", net_yield); err_printf("MPQS: %4.3g full relations per 100 polynomials\n", (total_full_relations * 100.) / iterations); err_printf("MPQS: %4.1f%% of the polynomials yielded no candidates\n", vain_iterations/10.); err_printf("MPQS: next sort point at %3.1f%%\n", sort_interval/10.); } } if (percentage < 1000) { pFNEW = pari_fopen_or_fail(FNEW_str, WRITE); /* LPNEW and FNEW are again open for writing */ continue; /* main loop */ } /* percentage >= 1000, which implies total_full_relations > size_of_FB: try finishing it off */ /* solve the system over F_2 */ /* present code does NOT in fact guarantee absence of dup FRELs, * therefore removing the adjective "distinct" for the time being */ if (DEBUGLEVEL >= 4) err_printf("\nMPQS: starting Gauss over F_2 on %ld relations\n", total_full_relations); pFREL = pari_fopen_or_fail(FREL_str, READ); fact = mpqs_solve_linear_system(handle, pFREL, total_full_relations); pari_fclose(pFREL); if (fact) { /* solution found */ if (DEBUGLEVEL >= 4) { err_printf("\nMPQS: time in Gauss and gcds = %ld ms\n", timer_delay(&T)); if (typ(fact) == t_INT) err_printf("MPQS: found factor = %Ps\n", fact); else { long j, nf = (lg(fact)-1)/3; if (nf == 2) /* GN20050707: Changed the arrangement of the two factors, * to match the debug diagnostics in mpqs_solve_linear_system() * above */ err_printf("MPQS: found factors = %Ps\n\tand %Ps\n", fact[1], fact[4]); else { /* GN20050707: Changed loop to scan upwards instead of downwards, * to match the debug diagnostics in mpqs_solve_linear_system() * above */ err_printf("MPQS: found %ld factors =\n", nf); for (j=1; j<=nf; j++) err_printf("\t%Ps%s\n", fact[3*j-2], (j= 4) { err_printf("\nMPQS: time in Gauss and gcds = %ld ms\n",timer_delay(&T)); err_printf("MPQS: no factors found.\n"); if (percentage <= MPQS_ADMIT_DEFEAT) err_printf("\nMPQS: restarting sieving ...\n"); else err_printf("\nMPQS: giving up.\n"); } if (percentage > MPQS_ADMIT_DEFEAT) { pari_fclose(pLPNEW); unlink_all(); avma = av; return NULL; } pFNEW = pari_fopen_or_fail(FNEW_str, WRITE); } } /* main loop */ } GEN mpqs(GEN N) { mpqs_handle_t *handle = mpqs_handle_ctor(N); GEN fact = mpqs_i(handle); mpqs_handle_dtor(handle); return fact; } pari-2.7.5/src/modules/part.c0000644000175000017500000002667112366172547014510 0ustar billbill/* Copyright (C) 2002 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. */ /* Original code contributed by: Ralf Stephan (ralf@ark.in-berlin.de). * * 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 * 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 * * ------------------------------------------------------------------ * The first restriction depends on Pari's maximum precision of floating * point reals, which is 268435454 bits in 2.2.4, since the algorithm needs * high precision exponentials. For that engine, the maximum possible argument * would be in [5*10^15,10^16], the computation of which would need days on * a ~1-GHz computer. */ #include "pari.h" #include "paripriv.h" /****************************************************************/ /* Given: b = N-1/24; * c = sqrt(2/3)*Pi*sqrt(b) * d = 1 / ((2*b)^(3/2) * Pi); * * Psi(N, q) = my(a = c/q); sqrt(q) * (a*cosh(a) - sinh(a)) */ static GEN psi(GEN c, ulong q, long prec) { GEN a = divru(c, q), ea = mpexp(a), invea = invr(ea); GEN cha = shiftr(addrr(ea, invea), -1); /* ch(a) */ GEN sha = shiftr(subrr(ea, invea), -1); /* sh(a) */ 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)))) * Never called with q < 3, so ignore this case */ static GEN L(GEN n, ulong q, 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); pari_sp av = avma; for (h = 1, hn = 0; h <= qov2; h++, avma = av) /* symmetry h <-> q-h */ { 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); } return shiftr(res,1); } /* Return a low precision estimate of log p(n). */ static GEN estim(GEN n) { pari_sp av = avma; GEN p1, pi = mppi (DEFAULTPREC); p1 = divru( itor(shifti(n,1), DEFAULTPREC), 3 ); p1 = mpexp( mulrr(pi, sqrtr(p1)) ); /* exp(Pi * sqrt(2N/3)) */ p1 = divri (shiftr(p1,-2), n); p1 = divrr(p1, sqrtr( stor(3,DEFAULTPREC) )); return gerepileupto(av, mplog(p1)); } static void pinit(GEN n, GEN *c, GEN *d, ulong prec) { GEN b = divru( itor( subis(muliu(n,24), 1), prec ), 24 ); /* n - 1/24 */ GEN sqrtb = sqrtr(b), Pi = mppi(prec), pi2sqrt2, pisqrt2d3; pisqrt2d3 = mulrr(Pi, sqrtr( divru(stor(2, prec), 3) )); pi2sqrt2 = mulrr(Pi, sqrtr( stor(8, prec) )); *c = mulrr(pisqrt2d3, sqrtb); *d = invr( mulrr(pi2sqrt2, mulrr(b,sqrtb)) ); } /* part(n) = round(sum(q=1,5 + 0.24*sqrt(n), L(n,q)*Psi(n,q))) */ GEN numbpart(GEN n) { pari_sp ltop = avma, av; GEN sum, est, C, D, p1, p2; long prec, bitprec; ulong q; if (typ(n) != t_INT) pari_err_TYPE("partition function",n); if (signe(n) < 0) return gen_0; if (cmpiu(n, 2) < 0) return gen_1; if (cmpii(n, uu32toi(0x38d7e, 0xa4c68000)) >= 0) pari_err_OVERFLOW("numbpart [n < 10^15]"); est = estim(n); bitprec = (long)(rtodbl(est)/LOG2) + 32; prec = nbits2prec(bitprec); pinit(n, &C, &D, prec); sum = cgetr (prec); affsr(0, sum); /* Because N < 10^16 and q < sqrt(N), q fits into a long * In fact q < 2 LONG_MAX / 3 */ av = avma; togglesign(est); for (q = (ulong)(sqrt(gtodouble(n))*0.24 + 5); q >= 3; q--, avma=av) { GEN t = L(n, q, bitprec); if (absr_cmp(t, mpexp(divru(est,q))) < 0) continue; t = mulrr(t, psi(gprec_w(C, nbits2prec(bitprec / q + 32)), q, prec)); affrr(addrr(sum, t), sum); } p1 = addrr(sum, psi(C, 1, prec)); p2 = psi(C, 2, prec); affrr(mod2(n)? subrr(p1,p2): addrr(p1,p2), sum); return gerepileuptoint (ltop, roundr(mulrr(D,sum))); } /* for loop over partitions of integer k. * nbounds can restrict partitions to have length between nmin and nmax * (the length is the number of non zero entries) and * abounds restrict to integers between amin and amax. * * Start from central partition. * By default, remove zero entries on the left. * * Algorithm: * * A partition of k is an increasing sequence v1,... vn with sum(vi)=k * The starting point is the minimal n-partition of k: a,...a,a+1,.. a+1 * (a+1 is repeated r times with k = a * n + r). * * The procedure to obtain the next partition: * - find the last index i*amax || *amin<0 || *amax<=0) pari_err_TYPE("forpart [expect 0<=min<=max, 0amin=1; if (abound) parse_interval(abound,&T->amin,&T->amax); else T->amax = k; /* strip leading zeros ? */ T->strip = (T->amin > 0) ? 1 : 0; /* bound on number of non-zero coefficients */ T->nmin=0; if (nbound) parse_interval(nbound,&T->nmin,&T->nmax); else T->nmax = k; /* non empty if nmin*amin <= k <= amax*nmax */ if ( T->amin*T->nmin > k || k > T->amax * T->nmax ) { T->nmin = T->nmax = 0; } else { /* to reach nmin one must have k <= nmin*amax, otherwise increase nmin */ if ( T->nmin * T->amax < k ) T->nmin = 1 + (k - 1) / T->amax; /* ceil( k/tmax ) */ /* decrease nmax (if strip): k <= amin*nmax */ if (T->strip && T->nmax > k/T->amin) T->nmax = k / T->amin; /* strip implies amin>0 */ /* fixme: take ceil( ) */ /* no need to change amin */ /* decrease amax if amax + (nmin-1)*amin > k */ if ( T->amax + (T->nmin-1)* T->amin > k ) T->amax = k - (T->nmin-1)* T->amin; } if ( T->amax < T->amin ) T->nmin = T->nmax = 0; T->v = zero_zv(T->nmax); /* partitions will be of length <= nmax */ T->k = k; } GEN forpart_next(forpart_t *T) { GEN v = T->v; long n = lg(v)-1; long i, s, a, k, vi, vn; if (n>0 && v[n]) { /* find index to increase: i s.t. v[i+1],...v[n] is central a,..a,a+1,..a+1 keep s = v[i] + v[i+1] + ... + v[n] */ s = a = v[n]; for(i = n-1; i>0 && v[i]+1 >= a; s += v[i--]); if (i == 0) { /* v is central [ a, a, .. a, a+1, .. a+1 ] */ if ((n+1) * T->amin > s || n == T->nmax) return NULL; i = 1; n++; setlg(v, n+1); vi = T->amin; } else { s += v[i]; vi = v[i]+1; } } else { /* init v */ s = T->k; if (T->amin == 0) T->amin = 1; if (T->strip) { n = T->nmin; setlg(T->v, n+1); } if (s==0) { if (n==0 && T->nmin==0) {T->nmin++; return v;} return NULL; } if (n==0) return NULL; vi = T->amin; i = T->strip ? 1 : n + 1 - T->nmin; /* first non-zero index */ } /* now fill [ v[i],... v[n] ] with s, start at vi */ vn = s - (n-i)*vi; /* expected value for v[n] */ if (T->amax && vn > T->amax) { /* do not exceed amax */ long ai, q, r; vn -= vi; ai = T->amax - vi; q = vn / ai; /* number of nmax */ r = vn % ai; /* value before nmax */ /* fill [ v[i],... v[n] ] as [ vi,... vi, vi+r, amax,... amax ] */ while ( q-- ) v[n--] = T->amax; if ( n >= i ) v[n--] = vi + r; while ( n >= i ) v[n--] = vi; } else { /* fill as [ v[i], ... v[i], vn ] */ for ( k=i; kv; long n = lg(v)-1; long j, ni, q, r; long i, s; if (n>0 && v[n]) { /* find index to decrease: start of last constant sequence, excluding v[n] */ i = n-1; s = v[n]; while (i>1 && (v[i-1]==v[i] || v[i+1]==T->amax)) s+= v[i--]; if (!i) return NULL; /* amax condition: cannot decrease i if maximal on the right */ if ( v[i+1] == T->amax ) return NULL; /* amin condition: stop if below except if strip & try to remove */ if (v[i] == T->amin) { if (!T->strip) return NULL; s += v[i]; v[i] = 0; } else { v[i]--; s++; } /* zero case... */ if (v[i] == 0) { if (T->nmin > n-i) return NULL; /* need too many non zero coeffs */ /* reduce size of v ? */ if (T->strip) { i = 0; n--; setlg(v, n+1); } } } else { s = T->k; i = 0; if (s==0) { if (n==0 && T->nmin==0) {T->nmin++; return v;} return NULL; } if (n*T->amax < s || s < T->nmin*T->amin) return NULL; } /* set minimal partition of sum s starting from index i+1 */ ni = n-i; q = s / ni; r = s % ni; for(j=i+1; j<=n-r; j++) v[j]=q; for(j=n-r+1; j<=n; j++) v[j]=q + 1; return v; } static long countpart(long k, GEN abound, GEN nbound) { pari_sp av = avma; long n; forpart_t T; if (k<0) return 0; forpart_init(&T, k, abound, nbound); for (n=0; forpart_next(&T); n++) avma = av; return n; } GEN partitions(long k, GEN abound, GEN nbound) { GEN v; forpart_t T; long i, n = countpart(k,abound,nbound); if (n==0) return cgetg(1, t_VEC); forpart_init(&T, k, abound, nbound); v = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) gel(v,i)=zv_copy(forpart_next(&T)); return v; } void forpart(void *E, long call(void*, GEN), long k, GEN abound, GEN nbound) { GEN v; forpart_t T; forpart_init(&T, k, abound, nbound); while ((v=forpart_next(&T))) if (call(E, v)) break; } void forpart0(GEN k, GEN code, GEN abound, GEN nbound) { pari_sp av = avma; if (typ(k) != t_INT) pari_err_TYPE("forpart",k); if (signe(k)<0) return; push_lex(gen_0, code); forpart((void*)code, &gp_evalvoid, itos(k), abound, nbound); pop_lex(1); avma=av; } pari-2.7.5/src/modules/mpqs.h0000644000175000017500000005371112314242551014504 0ustar billbill/* - debug support */ #ifdef MPQS_DEBUG_VERYVERBOSE # ifndef MPQS_DEBUG_VERBOSE # define MPQS_DEBUG_VERBOSE # endif #endif #ifdef MPQS_DEBUG_VERBOSE # ifndef MPQS_DEBUG # define MPQS_DEBUG # endif # define PRINT_IF_VERBOSE(x) err_printf(x) #else # define PRINT_IF_VERBOSE(x) #endif #ifdef MPQS_DEBUG # define MPQS_DEBUGLEVEL 1000 /* infinity */ #else # define MPQS_DEBUGLEVEL DEBUGLEVEL #endif /* - string and external file stuff for the relations "database" */ #ifndef SEEK_SET # define SEEK_SET 0 #endif #ifdef __CYGWIN32__ /* otherwise fseek() goes crazy due to silent \n <--> LF translations */ # define WRITE "wb" # define READ "rb" #else # define WRITE "w" # define READ "r" #endif #define MPQS_STRING_LENGTH (4 * 1024UL) /* - non-configurable sizing parameters */ #define MPQS_POSSIBLE_MULTIPLIERS 5 /* how many values for k we'll try */ /* following must be in range of the cand_multipliers table below */ #define MPQS_MULTIPLIER_SEARCH_DEPTH 5 /* how many primes to inspect per k */ /* `large primes' must be smaller than * min(MPQS_LP_BOUND, largest_FB_p) * MPQS_LP_FACTOR * - increased this with the idea of capping it at about 2^30 */ #define MPQS_LP_BOUND 12500000 /* works for 32 and 64bit */ /* see mpqs_locate_A_range() for an explanation of the following. I had * some good results with about -log2(0.85) but in the range I was testing, * this shifts the primes for A only by one position in the FB. Don't go * over the top with this one... */ #define MPQS_A_FUDGE 0.15 /* ~ -log2(0.9) */ #define MPQS_CANDIDATE_ARRAY_SIZE 2000 /* max. this many cand's per poly */ #ifdef MPQS_USE_HISTOGRAMS /* histogram evaluation/feedback available when size_of_FB exceeds this: */ # define MPQS_MIN_SIZE_FB_FOR_HISTO 600 /* min number of candidates to look at before evaluating histograms */ # define MPQS_MIN_CANDS_FOR_HISTO 4000 /* min number of full relations to have been created before etc. */ # define MPQS_MIN_FRELS_FOR_HISTO 110 /* see mpqs_eval_histograms() for explanation of the following */ # define MPQS_HISTO_FREL_QUANTILE 2.4 # define MPQS_HISTO_DROP_LIMIT 3.6 # define MPQS_HISTO_LPREL_BASEFLOW 1.4 #endif /* give up when nothing found after ~1.5 times the required number of * relations has been computed (N might be a prime power or the * parameters might be exceptionally unfortunate for it) */ #define MPQS_ADMIT_DEFEAT 1500 /* - structures, types, and constants */ /* -- reasonably-sized integers */ #ifdef LONG_IS_64BIT typedef int mpqs_int32_t; typedef unsigned int mpqs_uint32_t; typedef unsigned long mpqs_uint64_t; #else typedef long mpqs_int32_t; typedef unsigned long mpqs_uint32_t; typedef struct { ulong _w0; ulong _w1; } mpqs_uint64_t; #endif /* -- we'll sometimes want to use the machine's native size here, and * sometimes (for future double-large-primes) force 64 bits - thus: */ typedef union mpqs_invp { ulong _ul; mpqs_uint64_t _u64; } mpqs_invp_t; /* -- factor base entries should occupy 32 bytes (and we'll keep them * aligned, for good L1 cache hit rates). Some of the entries will be * abused for e.g. -1 and (factors of) k instead for real factor base * primes, and for a sentinel at the end. This is why __p is a signed * field.-- The two start fields depend on the current polynomial and * keep changing during sieving, the flags will also change depending on * the current A. */ /* Let (z1, z2) be the roots of Q(x) = A x^2 + Bx + C mod p_i; then * Q(z1 + p_i Z) == 0 mod p_i and Q(z2 + p_i Z) == 0 mod p_i; * start_1, start_2 are the positions where p_i divides Q(x) for the * first time, already adjusted for the fact that the sieving array, * nominally [-M, M], is represented by a 0-based C array of length * 2M + 1. For the prime factors of A and those of k, the two roots * are equal mod p_i. */ #define MPQS_FB_ENTRY_PAD 32 typedef union mpqs_FB_entry { char __pad[MPQS_FB_ENTRY_PAD]; struct { mpqs_int32_t __p; /* the prime p */ /* Following two are not yet used: */ float __flogp; /* its logarithm as a 4-byte float */ mpqs_invp_t __invp; /* 1/p mod 2^64 or 2^BITS_IN_LONG */ mpqs_int32_t __start1; /* representatives of the two APs mod p */ mpqs_int32_t __start2; mpqs_uint32_t __sqrt_kN; /* sqrt(kN) mod p */ unsigned char __val; /* 8-bit approx. scaled log for sieving */ unsigned char __flags; } __entry; } mpqs_FB_entry_t; /* --- convenience accessor macros for the preceding: */ #define fbe_p __entry.__p #define fbe_flogp __entry.__flogp #define fbe_invp __entry.__invp #define fbe_start1 __entry.__start1 #define fbe_start2 __entry.__start2 #define fbe_sqrt_kN __entry.__sqrt_kN #define fbe_logval __entry.__val #define fbe_flags __entry.__flags /* --- flag bits for fbe_flags: */ /* TODO */ #define MPQS_FBE_CLEAR 0x0 /* no flags */ /* following used for odd FB primes, and applies to the divisors of A but not * those of k. Must occupy the rightmost bit because we also use it as a * shift count after extracting it from the byte. */ #define MPQS_FBE_DIVIDES_A 0x1ul /* and Q(x) mod p only has degree 1 */ /* XX tentative: one bit to mark normal FB primes, * XX one to mark the factors of k, * XX one to mark primes used in sieving, * XX later maybe one to mark primes of which we'll be tracking the square, * XX one to mark primes currently in use for A; * XX once we segment the FB, one bit marking the members of the first segment */ /* -- multiplier k and associated quantities: More than two prime factors * for k will be pointless in practice, thus capping them at two. */ #define MPQS_MAX_OMEGA_K 2 typedef struct mpqs_multiplier { mpqs_uint32_t k; /* the multiplier (odd, squarefree) */ mpqs_uint32_t omega_k; /* number (>=0) of primes dividing k */ mpqs_uint32_t kp[MPQS_MAX_OMEGA_K]; /* prime factors of k, if any */ } mpqs_multiplier_t; static const mpqs_multiplier_t cand_multipliers[] = { { 1, 0, { 0, 0} }, { 3, 1, { 3, 0} }, { 5, 1, { 5, 0} }, { 7, 1, { 7, 0} }, { 11, 1, { 11, 0} }, { 13, 1, { 13, 0} }, { 15, 2, { 3, 5} }, { 17, 1, { 17, 0} }, { 19, 1, { 19, 0} }, { 21, 2, { 3, 7} }, { 23, 1, { 23, 0} }, { 29, 1, { 29, 0} }, { 31, 1, { 31, 0} }, { 33, 2, { 3, 11} }, { 35, 2, { 5, 7} }, { 37, 1, { 37, 0} }, { 39, 2, { 3, 13} }, { 41, 1, { 41, 0} }, { 43, 1, { 43, 0} }, { 47, 1, { 47, 0} }, { 51, 2, { 3, 17} }, { 53, 1, { 53, 0} }, { 55, 2, { 5, 11} }, { 57, 2, { 3, 19} }, { 59, 1, { 59, 0} }, { 61, 1, { 61, 0} }, { 65, 2, { 5, 13} }, { 67, 1, { 67, 0} }, { 69, 2, { 3, 23} }, { 71, 1, { 71, 0} }, { 73, 1, { 73, 0} }, { 77, 2, { 7, 11} }, { 79, 1, { 79, 0} }, { 83, 1, { 83, 0} }, { 85, 2, { 5, 17} }, { 87, 2, { 3, 29} }, { 89, 1, { 89, 0} }, { 91, 2, { 7, 13} }, { 93, 2, { 3, 31} }, { 95, 2, { 5, 19} }, { 97, 1, { 97, 0} } }; /* -- the array of (Chinese remainder) idempotents which add/subtract up to * the middle coefficient B, and for convenience, the FB subscripts of the * primes in current use for A. We keep these together since both arrays * are of the same size and are used at the same times. */ typedef struct mqps_per_A_prime { GEN _H; /* summand for B */ mpqs_int32_t _i; /* subscript into FB */ } mpqs_per_A_prime_t; /* following cooperate with names of local variables in the self_init fcns. * per_A_pr must exist and be an alias for the eponymous handle pointer for * all of these, and FB must exist and correspond to the handle FB pointer * for all but the first two of them. */ #define MPQS_H(i) (per_A_pr[i]._H) #define MPQS_I(i) (per_A_pr[i]._i) #define MPQS_AP(i) (FB[per_A_pr[i]._i].fbe_p) #define MPQS_LP(i) (FB[per_A_pr[i]._i].fbe_flogp) #define MPQS_SQRT(i) (FB[per_A_pr[i]._i].fbe_sqrt_kN) #define MPQS_FLG(i) (FB[per_A_pr[i]._i].fbe_flags) /* -- the array of addends / subtrahends for changing polynomials during * self-initialization: (1/A) H[i] mod p_j, with i subscripting the inner * array in each entry, and j choosing the entry in an outer array. * Entries will occupy 64 bytes each no matter what (which imposes one * sizing restriction: at most 17 prime factors for A; thus i will range * from 0 to at most 15.) This wastes a little memory for smaller N but * makes it easier for compilers to generate efficient code. */ /* NOTE: At present, memory locality vis-a-vis accesses to this array is good * in the slow (new A) branch of mpqs_self_init(), but poor in the fast * (same A, new B) branch, which now loops over the outer array index, * reading just one field of each inner array each time through the FB * loop. This doesn't really harm, but will improve one day when we do * segmented sieve arrays with the associated segmented FB-range accesses. */ #define MPQS_MAX_OMEGA_A 17 typedef struct mpqs_inv_A_H { mpqs_uint32_t _i[MPQS_MAX_OMEGA_A - 1]; } mpqs_inv_A_H_t; #define MPQS_INV_A_H(i,j) (inv_A_H[j]._i[i]) /* -- global handle for keeping track of everything used throughout any one * factorization attempt. The order of the fields is roughly determined by * wanting to keep the most frequently used stuff near the beginning. */ typedef struct mpqs_handle { /* pointers into pari_malloc()d memory which must be freed at the end: */ unsigned char *sieve_array; /* 0-based, representing [-M,M-1] */ unsigned char *sieve_array_end; /* points at sieve_array[M-1] */ mpqs_FB_entry_t *FB; /* (aligned) FB array itself */ long *candidates; /* collects promising sieve subscripts */ char *relations; /* freshly found relations (strings) */ long *relaprimes; /* prime/exponent pairs in a relation */ mpqs_inv_A_H_t *inv_A_H; /* self-init: (aligned) stepping array, and */ mpqs_per_A_prime_t *per_A_pr; /* FB subscripts of primes in A etc. */ /* other stuff that's being used all the time */ mpqs_int32_t M; /* sieving over |x| <= M */ mpqs_int32_t size_of_FB; /* # primes in FB (or dividing k) */ /* the following three are in non-descending order, and the first two must * be adjusted for omega_k at the beginning */ mpqs_int32_t index0_FB; /* lowest subscript into FB of a "real" prime * (i.e. other than -1, 2, factors of k) */ mpqs_int32_t index1_FB; /* lowest subscript into FB for sieving */ mpqs_int32_t index2_FB; /* primes for A are chosen relative to this */ unsigned char index2_moved; /* true when we're starved for small A's */ unsigned char sieve_threshold; /* distinguishes candidates in sieve */ #ifdef MPQS_USE_HISTOGRAMS /* histogram feedback */ unsigned char do_histograms; /* (boolean) enable histogram updating */ unsigned char done_histograms; /* histos have been eval'd for feedback */ /* more pari_malloc()d memory here: */ long *histo_full; /* distribution of full rels from sieve */ long *histo_lprl; /* - of LP rels from sieve */ long *histo_drop; /* - of useless candidates */ #endif GEN N; /* given number to be factored */ GEN kN; /* N with multiplier (on PARI stack) */ /* quantities associated with the current polynomial; all these also * live in preallocated slots on the PARI stack: */ GEN A; /* leading coefficient */ GEN B; /* middle coefficient */ #ifdef MPQS_DEBUG GEN C; /* and constant coefficient */ #endif mpqs_int32_t omega_A; /* number of primes going into each A */ mpqs_int32_t no_B; /* number of B's for each A: 2^(omega_A-1) */ double l2_target_A; /* ~log2 of desired typical A */ /* counters and bit pattern determining and numbering the current * polynomial: */ mpqs_uint32_t bin_index; /* bit pattern for selecting primes for A */ mpqs_uint32_t index_i; /* running count of A's */ mpqs_uint32_t index_j; /* B's ordinal number in A's cohort */ /* TODO: one more to follow here... */ /* further sizing parameters: */ mpqs_int32_t target_no_rels; /* target number of full relations */ mpqs_int32_t largest_FB_p; /* largest prime in the FB */ mpqs_int32_t pmin_index1; /* lower bound for primes used for sieving */ mpqs_int32_t lp_scale; /* factor by which LPs may exceed FB primes */ mpqs_int32_t first_sort_point; /* when to sort and combine */ mpqs_int32_t sort_pt_interval; /* (in units of 1/1000) */ /* subscripts determining where to pick primes for A... */ /* FIXME: lp_bound might have to be mpqs_int64_t ? or mpqs_invp_t ? */ long lp_bound; /* cutoff for Large Primes */ long digit_size_N; long digit_size_kN; const mpqs_multiplier_t *_k; /* multiplier k and associated quantities */ double tolerance; /* controls the tightness of the sieve */ double dkN; /* - double prec. approximation of kN */ double l2sqrtkN; /* ~log2(sqrt(kN)) */ double l2M; /* ~log2(M) (cf. below) */ /* TODO: need an index2_FB here to remember where to start picking primes */ /* Put statistics here ? Currently keep them as local variables in mpqs() */ /* bookkeeping pointers to containers of aligned memory chunks: */ void *FB_chunk; /* (unaligned) chunk containing the FB */ void *invAH_chunk; /* (unaligned) chunk for self-init array */ } mpqs_handle_t; /* -- sizing table entries */ /* The "tolerance" is explained below apropos of mpqs_set_sieve_threshold(). * The LP scale, for very large kN, prevents us from accumulating vast amounts * of LP relations with little chance of hitting any particular large prime * a second time and being able to combine a full relation from two LP ones; * however, the sieve threshold (determined by the tolerance) already works * against very large LPs being produced.-- The present relations "database" * can detect duplicate full relations only during the sort/combine phases, * so we must do some sort points even for tiny kN where we do not admit * large primes at all. * Some constraints imposed by the present implementation: * + omega_A should be at least 3, and no more than MPQS_MAX_OMEGA_A * + The size of the FB must be large enough compared to omega_A * (about 2*omega_A + 3, but this is always true below) */ /* XXX Changes needed for segmented mode: * XXX When using it (kN large enough), * XXX - M must become a multiple of the (cache block) segment size * XXX (or to keep things simple: a multiple of 32K) * XXX - we need index3_FB to seperate (smaller) primes used for normal * XXX sieving from larger ones used with transaction buffers * XXX (and the locate_A_range and associated logic must be changed to * XXX cap index2_FB below index3_FB instead of below size_of_FB) */ typedef struct mpqs_parameterset { float tolerance; /* "mesh width" of the sieve */ /* XX following subject to further change */ mpqs_int32_t lp_scale; /* factor by which LPs may exceed FB primes */ mpqs_int32_t M; /* size of half the sieving interval */ mpqs_int32_t size_of_FB; /* #primes to use for FB (including 2) */ mpqs_int32_t omega_A; /* #primes to go into each A */ /* following is auto-adjusted to account for prime factors of k inserted * near the start of the FB. NB never ever sieve on the prime 2 (which * would just contribute a constant at each sieve point). */ mpqs_int32_t pmin_index1; /* lower bound for primes used for sieving */ /* the remaining two are expressed in percent (of the target number of full * relations), and determine when we stop sieving to review the contents * of the relations DB and sort them and combine full relations from LP * ones. Note that the handle has these in parts per thousand instead. */ mpqs_int32_t first_sort_point; mpqs_int32_t sort_pt_interval; } mpqs_parameterset_t; /* - the table of sizing parameters itself */ /* indexed by size of kN in decimal digits, subscript 0 corresponding to * 9 (or fewer) digits */ static const mpqs_parameterset_t mpqs_parameters[] = { /* tol lp_scl M szFB oA pmx1 1st sti */ { /*9*/ 0.8, 1, 900, 20, 3, 5, 70, 8}, { /*10*/ 0.8, 1, 900, 21, 3, 5, 70, 8}, { /*11*/ 0.8, 1, 920, 22, 3, 5, 70, 6}, { /*12*/ 0.8, 1, 960, 24, 3, 5, 70, 6}, { /*13*/ 0.8, 1, 1020, 26, 3, 5, 70, 6}, { /*14*/ 0.8, 1, 1100, 29, 3, 5, 70, 6}, { /*15*/ 0.8, 1, 1200, 32, 3, 5, 60, 8}, { /*16*/ 0.8, 1, 1500, 35, 3, 5, 60, 8}, { /*17*/ 0.8, 1, 1900, 40, 3, 5, 60, 8}, { /*18*/ 0.8, 1, 2500, 60, 3, 5, 50, 10}, { /*19*/ 0.8, 1, 3200, 80, 3, 5, 50, 10}, { /*20*/ 0.8, 1, 4000, 100, 3, 5, 40, 10}, { /*21*/ 0.8, 1, 4300, 100, 3, 5, 40, 10}, { /*22*/ 0.8, 1, 4500, 120, 3, 5, 40, 10}, { /*23*/ 0.8, 1, 4800, 140, 3, 5, 30, 10}, { /*24*/ 0.8, 1, 5100, 160, 4, 7, 30, 10}, { /*25*/ 0.8, 1, 5400, 180, 4, 7, 30, 10}, { /*26*/ 0.9, 1, 5700, 200, 4, 7, 30, 10}, { /*27*/ 1.12, 1, 6000, 220, 4, 7, 30, 10}, { /*28*/ 1.17, 1, 6300, 240, 4, 11, 30, 10}, { /*29*/ 1.22, 1, 6500, 260, 4, 11, 30, 10}, { /*30*/ 1.30, 1, 6800, 325, 4, 11, 20, 10}, { /*31*/ 1.33, 1, 7000, 355, 4, 13, 20, 10}, { /*32*/ 1.36, 1, 7200, 375, 5, 13, 20, 10}, { /*33*/ 1.40, 1, 7400, 400, 5, 13, 20, 10}, { /*34*/ 1.43, 1, 7600, 425, 5, 17, 20, 10}, /* around here, sieving takes long enough to make it worthwhile recording * LP relations into their separate output files, although they tend not * yet to contribute a lot to the full relations until we get up to around * 47 digits or so. */ { /*35*/ 1.48, 30, 7800, 550, 5, 17, 20, 10}, { /*36*/ 1.53, 45, 8100, 650, 5, 17, 20, 10}, { /*37*/ 1.60, 60, 9000, 750, 6, 19, 20, 10}, { /*38*/ 1.66, 70, 10000, 850, 6, 19, 20, 10}, { /*39*/ 1.69, 80, 11000, 950, 6, 23, 20, 10}, /* around here, the largest prime in FB becomes comparable to M in size */ { /*40*/ 1.69, 80, 12500, 1000, 6, 23, 20, 10}, { /*41*/ 1.69, 80, 14000, 1150, 6, 23, 10, 10}, { /*42*/ 1.69, 80, 15000, 1300, 6, 29, 10, 10}, { /*43*/ 1.69, 80, 16000, 1500, 6, 29, 10, 10}, { /*44*/ 1.69, 80, 17000, 1700, 7, 31, 10, 10}, { /*45*/ 1.69, 80, 18000, 1900, 7, 31, 10, 10}, { /*46*/ 1.69, 80, 20000, 2100, 7, 37, 10, 10}, { /*47*/ 1.69, 80, 25000, 2300, 7, 37, 10, 10}, { /*48*/ 1.69, 80, 27500, 2500, 7, 37, 10, 10}, { /*49*/ 1.72, 80, 30000, 2700, 7, 41, 10, 10}, { /*50*/ 1.75, 80, 35000, 2900, 7, 41, 10, 10}, { /*51*/ 1.80, 80, 40000, 3000, 7, 43, 10, 10}, { /*52*/ 1.85, 80, 50000, 3200, 7, 43, 10, 10}, { /*53*/ 1.90, 80, 60000, 3500, 7, 47, 10, 10}, { /*54*/ 1.95, 80, 70000, 3800, 7, 47, 10, 10}, { /*55*/ 1.95, 80, 80000, 4100, 7, 53, 10, 10}, { /*56*/ 1.95, 80, 90000, 4400, 7, 53, 10, 8}, { /*57*/ 2.00, 80, 100000, 4700, 8, 53, 10, 8}, { /*58*/ 2.05, 80, 110000, 5000, 8, 59, 10, 8}, { /*59*/ 2.10, 80, 120000, 5400, 8, 59, 10, 8}, { /*60*/ 2.15, 80, 130000, 5800, 8, 61, 10, 8}, { /*61*/ 2.20, 80, 140000, 6100, 8, 61, 10, 8}, { /*62*/ 2.25, 80, 150000, 6400, 8, 67, 10, 6}, { /*63*/ 2.39, 80, 160000, 6700, 8, 67, 10, 6}, { /*64*/ 2.30, 80, 165000, 7000, 8, 67, 10, 6}, { /*65*/ 2.31, 80, 170000, 7300, 8, 71, 10, 6}, { /*66*/ 2.32, 80, 175000, 7600, 8, 71, 10, 6}, { /*67*/ 2.33, 80, 180000, 7900, 8, 73, 10, 6}, { /*68*/ 2.34, 80, 185000, 8200, 8, 73, 10, 6}, { /*69*/ 2.35, 80, 190000, 8600, 8, 79, 8, 6}, { /*70*/ 2.36, 80, 195000, 8800, 8, 79, 8, 6}, { /*71*/ 2.37, 80, 200000, 9000, 9, 79, 8, 6}, { /*72*/ 2.38, 80, 205000, 9250, 9, 83, 5, 5}, { /*73*/ 2.41, 80, 210000, 9500, 9, 83, 5, 5}, { /*74*/ 2.46, 80, 220000, 9750, 9, 83, 5, 5}, { /*75*/ 2.51, 80, 230000, 10000, 9, 89, 5, 5}, { /*76*/ 2.56, 80, 240000, 10500, 9, 89, 5, 5}, { /*77*/ 2.58, 80, 250000, 11200, 9, 89, 5, 5}, { /*78*/ 2.60, 80, 260000, 12500, 9, 89, 5, 5}, { /*79*/ 2.63, 80, 270000, 14000, 9, 97, 5, 4}, { /*80*/ 2.65, 80, 280000, 15500, 9, 97, 5, 4}, { /*81*/ 2.72, 80, 300000, 17000, 9, 97, 4, 4}, { /*82*/ 2.77, 80, 320000, 18500, 9, 101, 4, 4}, { /*83*/ 2.82, 80, 340000, 20000, 10, 101, 4, 4}, { /*84*/ 2.84, 80, 360000, 21500, 10, 103, 4, 4}, { /*85*/ 2.86, 80, 400000, 23000, 10, 103, 4, 3}, { /*86*/ 2.88, 80, 460000, 24500, 10, 107, 4, 3}, /* architectures with 1MBy L2 cache will become noticeably slower here * as 2*M exceeds that mark - to be addressed in a future version by * segmenting the sieve interval */ { /*87*/ 2.90, 80, 520000, 26000, 10, 107, 4, 3}, { /*88*/ 2.91, 80, 580000, 27500, 10, 109, 4, 3}, { /*89*/ 2.92, 80, 640000, 29000, 10, 109, 4, 3}, { /*90*/ 2.93, 80, 700000, 30500, 10, 113, 2, 2}, { /*91*/ 2.94, 80, 770000, 32200, 10, 113, 2, 2}, /* entries below due to Thomas Denny, never tested */ { /*92*/ 3.6, 90, 2000000, 35000, 9, 113, 2, 2}, { /*93*/ 3.7, 90, 2000000, 37000, 9, 113, 2, 2}, { /*94*/ 3.7, 90, 2000000, 39500, 9, 127, 2, 2}, { /*95*/ 3.7, 90, 2500000, 41500, 9, 127, 2, 2}, { /*96*/ 3.8, 90, 2500000, 45000, 10, 127, 2, 2}, { /*97*/ 3.8, 90, 2500000, 47500, 10, 131, 2, 2}, { /*98*/ 3.7, 90, 3000000, 51000, 10, 131, 2, 2}, { /*99*/ 3.8, 90, 3000000, 53000, 10, 133, 2, 2}, {/*100*/ 3.8, 90, 3500000, 51000, 10, 133, 2, 2}, {/*101*/ 3.8, 90, 3500000, 54000, 10, 139, 2, 2}, {/*102*/ 3.8, 90, 3500000, 57000, 10, 139, 2, 2}, {/*103*/ 3.9, 90, 4000000, 61000, 10, 139, 2, 2}, {/*104*/ 3.9, 90, 4000000, 66000, 10, 149, 2, 2}, {/*105*/ 3.9, 90, 4000000, 70000, 10, 149, 2, 2}, {/*106*/ 3.9, 90, 4000000, 75000, 10, 151, 2, 2}, {/*107*/ 3.9, 90, 4000000, 80000, 10, 151, 2, 2}, }; #define MPQS_MAX_DIGIT_SIZE_KN 107 pari-2.7.5/src/modules/thue.c0000644000175000017500000012036712434213470014467 0ustar billbill/* 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" /********************************************************************/ /** **/ /** THUE EQUATION SOLVER (G. Hanrot) **/ /** **/ /********************************************************************/ /* 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 */ /* 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 */ (void)checkbnf(gel(tnf,2)); return (typ(gel(tnf,3)) == t_COL && typ(gel(tnf,4)) == t_COL && typ(gel(tnf,5)) == t_MAT && typ(gel(tnf,6)) == t_MAT && 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 myround(GEN x, long dir) { GEN eps = powis(stoi(dir > 0? 10: -10), -10); return gmul(x, gadd(gen_1, eps)); } /* v a t_VEC/t_VEC */ static GEN vecmax_shallow(GEN v) { return gel(v, vecindexmax(v)); } static GEN tnf_get_roots(GEN poly, long prec, long S, long T) { GEN R0 = QX_complex_roots(poly, prec), R = cgetg(lg(R0), t_COL); long k; for (k=1; k<=S; k++) gel(R,k) = gel(R0,k); /* swap roots to get the usual order */ for (k=1; k<=T; k++) { gel(R,k+S) = gel(R0,2*k+S-1); gel(R,k+S+T)= gel(R0,2*k+S); } return R; } /* Computation of the logarithmic height of x (given by embeddings) */ static GEN LogHeight(GEN x, long prec) { 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); } /* |x|^(1/n), x t_INT */ static GEN absisqrtn(GEN x, long n, long prec) { GEN r = itor(x,prec); setabssign(r); return sqrtnr(r, n); } static GEN get_emb(GEN x, GEN r) { long l = lg(r), i; GEN y; if (typ(x) == t_INT) return const_col(l-1, x); y = cgetg(l, t_COL); for (i=1; i1) err_printf("epsilon_3 -> %Ps\n",eps3); *eps5 = mulur(r, eps3); return A; } /* Performs basic computations concerning the equation. * Returns a "tnf" structure containing * 1) the polynomial * 2) the bnf (used to solve the norm equation) * 3) roots, with presumably enough precision * 4) The logarithmic heights of units * 5) The matrix of conjugates of units * 6) its inverse * 7) a few technical constants */ static GEN inithue(GEN P, GEN bnf, long flag, long prec) { GEN MatFU, x0, tnf, tmp, gpmin, dP, csts, ALH, eps5, ro, c1, c2, Ind = gen_1; long k,j, n = degpol(P); long s,t, prec_roots; if (!bnf) { bnf = Buchall(P, nf_FORCE, DEFAULTPREC); if (flag) (void)bnfcertify(bnf); else Ind = floorr(mulru(bnf_get_reg(bnf), 5)); } nf_get_sign(bnf_get_nf(bnf), &s, &t); prec_roots = prec; for(;;) { ro = tnf_get_roots(P, prec_roots, s, t); MatFU = Conj_LH(bnf_get_fu(bnf), &ALH, ro, prec); if (MatFU) break; prec_roots = precdbl(prec_roots); if (DEBUGLEVEL>1) pari_warn(warnprec, "inithue", prec_roots); } dP = ZX_deriv(P); c1 = NULL; /* min |P'(r_i)|, i <= s */ for (k=1; k<=s; k++) { tmp = gabs(poleval(dP,gel(ro,k)),prec); if (!c1 || gcmp(tmp,c1) < 0) c1 = tmp; } c1 = gdiv(int2n(n-1), c1); c1 = gprec_w(myround(c1, 1), DEFAULTPREC); c2 = NULL; /* max |r_i - r_j|, i!=j */ for (k=1; k<=n; k++) for (j=k+1; j<=n; j++) { tmp = gabs(gsub(gel(ro,j),gel(ro,k)), prec); if (!c2 || gcmp(c2,tmp) > 0) c2 = tmp; } c2 = gprec_w(myround(c2, -1), DEFAULTPREC); if (t==0) x0 = real_1(DEFAULTPREC); else { gpmin = NULL; /* min |P'(r_i)|, i > s */ for (k=1; k<=t; k++) { tmp = gabs(poleval(dP,gel(ro,s+k)), prec); if (!gpmin || gcmp(tmp,gpmin) < 0) gpmin = tmp; } gpmin = gprec_w(gpmin, DEFAULTPREC); /* Compute x0. See paper, Prop. 2.2.1 */ x0 = gmul(gpmin, vecmax_shallow(gabs(imag_i(ro), prec))); x0 = sqrtnr(gdiv(int2n(n-1), x0), n); } if (DEBUGLEVEL>1) 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); gel(tnf,1) = P; gel(tnf,2) = bnf; gel(tnf,3) = ro; gel(tnf,4) = ALH; gel(tnf,5) = MatFU; gel(tnf,6) = T_A_Matrices(MatFU, s+t-1, &eps5, prec); gel(tnf,7) = csts; 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; return tnf; } typedef struct { GEN c10, c11, c13, c15, bak, NE, ALH, Ind, hal, MatFU, ro, Hmu; GEN delta, lambda, inverrdelta; long r, iroot, deg; } baker_s; /* 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))); } /* 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 = 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 = gprec_w(myround(c9, 1), 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)); 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))))); if (DEBUGLEVEL>1) { err_printf(" B0 = %Ps\n",B0); err_printf(" Baker = %Ps\n",c9); } return B0; } /* || x d ||, x t_REAL, d t_INT */ static GEN errnum(GEN x, GEN d) { GEN dx = mulir(d, x), D = subri(dx, roundr(dx)); setabssign(D); return D; } /* Try to reduce the bound through continued fractions; see paper. */ static int CF_1stPass(GEN *B0, GEN kappa, baker_s *BS) { GEN a, b, q, ql, qd, l0, denbound = mulri(*B0, kappa); if (cmprr(mulrr(dbltor(0.1),sqrr(denbound)), BS->inverrdelta) > 0) return -1; q = denom( bestappr(BS->delta, denbound) ); qd = errnum(BS->delta, q); ql = errnum(BS->lambda,q); l0 = subrr(ql, addrr(mulrr(qd, *B0), divri(dbltor(0.1),kappa))); if (signe(l0) <= 0) return 0; if (BS->r > 1) { a = BS->c15; b = BS->c13; } else { a = BS->c11; b = BS->c10; l0 = mulrr(l0, Pi2n(1, DEFAULTPREC)); } *B0 = divrr(mplog(divrr(mulir(q,a), l0)), b); if (DEBUGLEVEL>1) err_printf(" B0 -> %Ps\n",*B0); return 1; } static void get_B0Bx(baker_s *BS, GEN l0, GEN *B0, GEN *Bx) { GEN t = divrr(mulir(BS->Ind, BS->c15), l0); *B0 = divrr(mulir(BS->Ind, mplog(t)), BS->c13); *Bx = sqrtnr(shiftr(t,1), BS->deg); } static int LLL_1stPass(GEN *pB0, GEN kappa, baker_s *BS, GEN *pBx) { GEN B0 = *pB0, Bx = *pBx, lllmat, C, l0, l1, triv; long e; C = grndtoi(mulir(mulii(BS->Ind, kappa), gpow(B0, dbltor(2.2), DEFAULTPREC)), &e); if (DEBUGLEVEL > 1) err_printf("C (bitsize) : %d\n", expi(C)); lllmat = matid(3); if (cmpri(B0, BS->Ind) > 0) { gcoeff(lllmat, 1, 1) = grndtoi(divri(B0, BS->Ind), &e); triv = shiftr(sqrr(B0), 1); } else triv = addir(sqri(BS->Ind), sqrr(B0)); 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); l0 = gnorml2(gel(lllmat,1)); l0 = subrr(divir(l0, dbltor(1.8262)), triv); /* delta = 0.99 */ if (signe(l0) <= 0) return 0; l1 = shiftr(addri(shiftr(B0,1), BS->Ind), -1); l0 = divri(subrr(sqrtr(l0), l1), C); if (signe(l0) <= 0) return 0; get_B0Bx(BS, l0, &B0, &Bx); if (DEBUGLEVEL>=2) { err_printf("LLL_First_Pass successful\n"); err_printf("B0 -> %Ps\n", B0); err_printf("x <= %Ps\n", Bx); } *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 0) return 0; if (!signe(y)) return 1; /* y = 0 taken care of in SmallSols */ x = gadd(z1, gmul(ro1, y)); x = grndtoi(real_i(x), &e); 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); 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 GEN GuessQi(GEN b, GEN c, GEN *eps) { const long shift = 33; GEN Q, Lat, C = int2n(shift); Lat = matid(3); gcoeff(Lat,3,1) = ground(gmul2n(b, shift)); gcoeff(Lat,3,2) = ground(gmul2n(c, shift)); gcoeff(Lat,3,3) = C; Q = gel(lllint(Lat),1); if (gequal0(gel(Q,2))) return NULL; /* FAIL */ *eps = gadd(gadd(gel(Q,3), gmul(gel(Q,1),b)), gmul(gel(Q,2),c)); *eps = mpabs(*eps); return Q; } /* x a t_REAL */ static GEN 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) { long j, k, nmax, d; GEN bndcf; if (expo(bound) < 0) return bound; d = degpol(poly); bndcf = sqrtnr(shiftr(c1,1), d - 2); if (cmprr(bound, bndcf) < 0) return bound; /* divide by log((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); bound = myfloor(bound); for (k = 1; k <= s; k++) { GEN t = contfrac0(real_i(gel(roo,k)), NULL, nmax); GEN pm1, qm1, p0, q0; pm1 = gen_0; p0 = gen_1; qm1 = gen_1; q0 = gen_0; for (j = 1; j < lg(t); j++) { GEN p, q, z, Q, R; 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) */ Q = dvmdii(rhs, z, &R); if (R != gen_0) continue; setabssign(Q); if (Z_ispowerall(Q, d, &Q)) { if (!is_pm1(Q)) { p = mulii(p, Q); q = mulii(q, Q); } add_pm(pS, p, q, z, d, rhs); } } 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(real_i(gel(roo,k)))); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); roo = vec_shorten(cleanroots(poly, prec), s); k--; } } return bndcf; } static void check_y_root(GEN *pS, GEN P, GEN Y) { GEN r = nfrootsQ(P); long j; for (j = 1; j < lg(r); j++) if (typ(gel(r,j)) == t_INT) add_sol(pS, gel(r,j), Y); } static void check_y(GEN *pS, GEN P, GEN poly, GEN Y, GEN rhs) { long j, l = lg(poly); GEN Yn = Y; gel(P, l-1) = gel(poly, l-1); for (j = l-2; j >= 2; j--) { gel(P,j) = mulii(Yn, gel(poly,j)); if (j > 2) Yn = mulii(Yn, Y); } gel(P,2) = subii(gel(P,2), rhs); /* P = poly(Y/y)*y^deg(poly) - rhs */ check_y_root(pS, P, Y); } /* Check for solutions under a small bound (see paper) */ static GEN SmallSols(GEN S, GEN x3, GEN poly, GEN rhs) { pari_sp av = avma, lim = stack_lim(av, 1); GEN X, P, rhs2; long j, l = lg(poly), n = degpol(poly); ulong y, By; x3 = myfloor(x3); if (DEBUGLEVEL>1) err_printf("* Checking for small solutions <= %Ps\n", x3); if (lgefint(x3) > 3) pari_err_OVERFLOW(stack_sprintf("thue (SmallSols): y <= %Ps", x3)); By = itou(x3); /* y = 0 first: solve X^n = rhs */ if (odd(n)) { if (Z_ispowerall(absi(rhs), n, &X)) add_sol(&S, signe(rhs) > 0? X: negi(X), gen_0); } else if (signe(rhs) > 0 && Z_ispowerall(rhs, n, &X)) { add_sol(&S, X, gen_0); add_sol(&S, negi(X), gen_0); } rhs2 = shifti(rhs,1); /* y != 0 */ P = cgetg(l, t_POL); P[1] = poly[1]; for (y = 1; y <= By; y++) { pari_sp av2 = avma; long lS = lg(S); GEN Y = utoipos(y); /* try y */ check_y(&S, P, poly, Y, rhs); /* try -y */ for (j = l-2; j >= 2; j -= 2) togglesign( gel(P,j) ); if (j == 0) gel(P,2) = subii(gel(P,2), rhs2); 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(DEBUGMEM>1) pari_warn(warnmem,"SmallSols"); gerepileall(av, 2, &S, &rhs2); P = cgetg(l, t_POL); P[1] = poly[1]; } } return S; } /* Computes [x]! */ static double fact(double x) { double ft = 1.0; x = floor(x); while (x>1) { ft *= x; x--; } return ft ; } static GEN RgX_homogenize(GEN P, long v) { GEN Q = leafcopy(P); long i, l = lg(P), d = degpol(P); for (i = 2; i < l; i++) gel(Q,i) = monomial(gel(Q,i), d--, v); return Q; } /* Compute all relevant constants needed to solve the equation P(x,y)=a given * the solutions of N_{K/Q}(x)=a (see inithue). */ GEN thueinit(GEN pol, long flag, long prec) { GEN POL, C, L, fa, tnf, bnf = NULL; pari_sp av = avma; long k, 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); dpol = degpol(pol); 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); if (lfa > 2 || itos(gcoeff(fa,1,2)) > 1) { /* reducible polynomial */ 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(); if (e != 1) { if (lfa == 2) { tnf = mkvec2(mkvec3(pol,C,L), mkvec2(thueinit(f, flag, prec), E)); delete_var(); delete_var(); delete_var(); return gerepilecopy(av, tnf); } P = gpowgs(f,e); } else P = f; 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)); delete_var(); delete_var(); delete_var(); return gerepilecopy(av, tnf); } if (dpol <= 2) pari_err_DOMAIN("thue", "degree","<=",gen_2,pol); s = sturm(pol); if (s) { long PREC, n = degpol(pol); double d, dr, dn = (double)n; 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 * the time not sharp, ie 10 to 30 decimal digits above what is _really_ * necessary. Note that the limiting step is the reduction. See paper. */ PREC = nbits2prec((long)((5.83 + (dr+4)*5 + log(fact(dr+3)) + (dr+3)*log(dr+2) + (dr+3)*log(d) + log(log(2*d*(dr+2))) + (dr+1)) /10.)*32+32); if (flag == 0) PREC = (long)(2.2 * PREC); /* Lazy, to be improved */ if (PREC < prec) PREC = prec; if (DEBUGLEVEL >=2) err_printf("prec = %d\n", PREC); for (;;) { if (( tnf = inithue(pol, bnf, flag, PREC) )) break; PREC = precdbl(PREC); if (DEBUGLEVEL>1) pari_warn(warnprec,"thueinit",PREC); bnf = NULL; avma = av; } } else { GEN ro = roots(pol, DEFAULTPREC), c0 = imag_i(gel(ro,1)); for (k=2; kr > 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)); } 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; p1 = gdiv(gel(fu,2), gel(fu,3)); delta = divrr(garg(p1,prec), Pi2); 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); } 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) { 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"); /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */ for (;;) { GEN oldB0 = B0, kappa = utoipos(10); long cf; for (cf = 0; cf < 10; cf++, kappa = muliu(kappa,10)) { int res = CF_1stPass(&B0, kappa, BS); if (res < 0) return NULL; /* prec problem */ if (res) break; if (DEBUGLEVEL>1) err_printf("CF failed. Increasing kappa\n"); } if (!step && cf == 10) { /* Semirational or totally rational case */ GEN Q, ep, q, l0, denbound; if (! (Q = GuessQi(BS->delta, BS->lambda, &ep)) ) break; denbound = gadd(B0, absi(gel(Q,1))); q = denom( bestappr(BS->delta, denbound) ); l0 = subrr(errnum(BS->delta, q), ep); if (signe(l0) <= 0) break; B0 = divrr(mplog(divrr(mulir(gel(Q,2), BS->c15), l0)), BS->c13); if (DEBUGLEVEL>1) err_printf("Semirat. reduction: B0 -> %Ps\n",B0); } /* if no progress, stop */ if (gcmp(oldB0, gadd(B0,dbltor(0.1))) <= 0) return gmin(oldB0, B0); else step++; } i2++; if (i2 == i1) i2++; if (i2 > BS->r) break; } pari_err_BUG("thue (totally rational case)"); return NULL; /* not reached */ } static GEN get_Bx_LLL(long i1, GEN Delta, GEN Lambda, GEN eps5, 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); if (DEBUGLEVEL>1) err_printf(" Entering LLL...\n"); /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */ for (;;) { GEN oldBx = Bx, kappa = utoipos(10); const long cfMAX = 10; long cf; 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"); } /* FIXME: TO BE COMPLETED */ if (!step && cf == cfMAX) { /* Semirational or totally rational case */ GEN Q, ep, q, l0, denbound; if (! (Q = GuessQi(BS->delta, BS->lambda, &ep)) ) break; /* Beware Q[2]] = gen_0 */ denbound = gadd(mulri(B0, absi(gel(Q,1))), mulii(BS->Ind, absi(gel(Q,2)))); q = denom( bestappr(BS->delta, denbound) ); l0 = divri(subrr(errnum(BS->delta, q), ep), absi(gel(Q,2))); if (signe(l0) <= 0) break; get_B0Bx(BS, l0, &B0, &Bx); if (DEBUGLEVEL>1) err_printf("Semirat. reduction: B0 -> %Ps x <= %Ps\n",B0, Bx); } /* if no progress, stop */ if (oldBx && gcmp(oldBx, Bx) <= 0) return oldBx; else step++; } i2++; if (i2 == i1) i2++; if (i2 > BS->r) break; } pari_err_BUG("thue (totally rational case)"); return NULL; /* not reached */ } static GEN LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne, GEN *pS) { 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; baker_s BS; pari_sp av = avma; bnf = gel(tnf,2); csts = gel(tnf,7); if (!ne) { 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"); } 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); BS.r = r = s+t-1; n = degpol(P); ro = gel(tnf,3); BS.ALH = gel(tnf,4); MatFU = gel(tnf,5); A = gel(tnf,6); c1 = gel(csts,1); c1 = gmul(absi(rhs), c1); c2 = gel(csts,2); BS.hal = gel(csts,3); x0 = gel(csts,4); eps5 = gel(csts,5); Prec = gtolong(gel(csts,6)); BS.Ind = gel(csts,7); BS.MatFU = MatFU; BS.bak = mulss(n, (n-1)*(n-2)); /* safe */ BS.deg = n; 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)); Vect = gmul(gabs(A,DEFAULTPREC), const_col(r, gen_1)); c14 = mulrr(c4, vecmax_shallow(Vect)); 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)); zp1 = dbltor(0.01); x3 = gmax(x2, sqrtnr(shiftr(divrr(c14,zp1),1),n)); b = cgetg(r+1,t_COL); for (iroot=1; iroot<=s; iroot++) { GEN Delta, MatNE, Hmu, c5, c7; 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)); c5 = myround(gprec_w(c5,DEFAULTPREC), 1); c7 = mulur(r,c5); BS.c10 = divur(n,c7); BS.c13 = divur(n,c5); if (DEBUGLEVEL>1) { err_printf("* real root no %ld/%ld\n", iroot,s); err_printf(" c10 = %Ps\n",BS.c10); err_printf(" c13 = %Ps\n",BS.c13); } prec = Prec; for (;;) { if (( MatNE = Conj_LH(ne, &Hmu, ro, prec) )) break; prec = precdbl(prec); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); ro = tnf_get_roots(P, prec, s, t); } BS.ro = ro; BS.iroot = iroot; for (ine=1; ine1) 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); } Lambda = RgM_RgC_mul(A,Vect2); 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.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; } else { if (! (Bx = get_Bx_LLL(i1, Delta, Lambda, eps5, prec, &BS)) ) goto PRECPB; 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; } } } return gmax(x0, MiddleSols(pS, x3, ro, P, rhs, s, c1)); PRECPB: ne = gerepilecopy(av, ne); prec += nbits2extraprec(5 * prec2nbits(DEFAULTPREC)); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); tnf = inithue(P, bnf, 0, prec); *pS = cgetg(1, t_VEC); /* reset */ return LargeSols(P, tnf, rhs, ne, pS); } /* restrict to solutions (x,y) with L | x, replacing each by (x/L, y) */ static GEN filter_sol_x(GEN S, GEN L) { long i, k, l; if (is_pm1(L)) return S; l = lg(S); k = 1; for (i = 1; i < l; i++) { GEN s = gel(S,i), r; gel(s,1) = dvmdii(gel(s,1), L, &r); if (r == gen_0) gel(S, k++) = s; } setlg(S, k); return S; } static GEN sol_0(void) { GEN S = cgetg(2, t_VEC); gel(S,1) = mkvec2(gen_0,gen_0); return S; } /* 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 */ GEN thue(GEN tnf, GEN rhs, GEN ne) { pari_sp av = avma; GEN POL, C, L, x3, S; 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); /* 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); } 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); } else if (typ(gel(tnf,2)) == t_REAL) { /* Case s=0. All solutions are "small". */ GEN c0 = gel(tnf,2); /* t_REAL */ if (!signe(rhs)) { avma = av; return sol_0(); } 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); } else if (typ(gmael(tnf,2,1)) == t_VEC) /* reducible case, pure power*/ { long e; tnf = gel(tnf,2); e = itos( gel(tnf,2) ); if (!signe(rhs)) { avma = av; return sol_0(); } 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)); } else if (typ(gel(tnf,2)) == t_VEC) /* 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); } P = cgetg(lg(POL), t_POL); P[1] = POL[1]; D = divisors(rhs); l = lg(D); for (i = 1; i < l; i++) { GEN Rab, ry, df = gel(D,i), dg = diviiexact(rhs, df); long k; 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 */ 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); Rab = gsubst(gsubst(R, va, negi(df)), vb, odd(e)? negi(dg): 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); } } return gerepilecopy(av, filter_sol_x(S, L)); } /********************************************************************/ /** **/ /** BNFISINTNORM (K. Belabas) **/ /** **/ /********************************************************************/ struct sol_abs { GEN rel; /* Primes PR[i] above a, expressed on generators of Cl(K) */ GEN partrel; /* list of vectors, partrel[i] = rel[1..i] * u[1..i] */ GEN cyc; /* orders of generators of Cl(K) given in bnf */ long *f; /* f[i] = f(PR[i]/p), inertia degree */ long *n; /* a = prod p^{ n_p }. n[i]=n_p if PR[i] divides p */ long *next; /* index of first P above next p, 0 if p is last */ long *S; /* S[i] = n[i] - sum_{ 1<=k<=i } f[k]*u[k] */ long *u; /* We want principal ideals I = prod PR[i]^u[i] */ GEN normsol;/* lists of copies of the u[] which are solutions */ long nPR; /* length(T->rel) = #PR */ long sindex, smax; /* current index in T->normsol; max. index */ }; /* u[1..i] has been filled. Norm(u) is correct. * Check relations in class group then save it. */ static void test_sol(struct sol_abs *T, long i) { long k, l; GEN s; if (T->partrel && !ZV_dvd(gel(T->partrel, i), T->cyc)) return; if (T->sindex == T->smax) { /* no more room in solution list: enlarge */ long new_smax = T->smax << 1; GEN new_normsol = new_chunk(new_smax+1); for (k=1; k<=T->smax; k++) gel(new_normsol,k) = gel(T->normsol,k); T->normsol = new_normsol; T->smax = new_smax; } gel(T->normsol, ++T->sindex) = s = cgetg_copy(T->u, &l); for (k=1; k <= i; k++) s[k] = T->u[k]; for ( ; k < l; k++) s[k] = 0; if (DEBUGLEVEL>2) { err_printf("sol = %Ps\n",s); if (T->partrel) err_printf("T->partrel = %Ps\n",T->partrel); err_flush(); } } /* partrel[i] <-- partrel[i-1] + u[i] * rel[i] */ static void fix_partrel(struct sol_abs *T, long i) { pari_sp av = avma; GEN part1 = gel(T->partrel,i); GEN part0 = gel(T->partrel,i-1); GEN rel = gel(T->rel, i); ulong u = T->u[i]; long k, l = lg(part1); for (k=1; k < l; k++) affii(addii(gel(part0,k), muliu(gel(rel,k), u)), gel(part1,k)); avma = av; } /* Recursive loop. Suppose u[1..i] has been filled * Find possible solutions u such that, Norm(prod PR[i]^u[i]) = a, taking * into account: * 1) the relations in the class group if need be. * 2) the factorization of a. */ static void isintnorm_loop(struct sol_abs *T, long i) { if (T->S[i] == 0) /* sum u[i].f[i] = n[i], do another prime */ { long k, next = T->next[i]; if (next == 0) { test_sol(T, i); return; } /* no primes left */ /* some primes left */ if (T->partrel) gaffect(gel(T->partrel,i), gel(T->partrel, next-1)); for (k=i+1; k < next; k++) T->u[k] = 0; i = next-1; } else if (i == T->next[i]-2 || i == T->nPR-1) { /* only one Prime left above prime; change prime, fix u[i+1] */ long q; if (T->S[i] % T->f[i+1]) return; q = T->S[i] / T->f[i+1]; i++; T->u[i] = q; if (T->partrel) fix_partrel(T,i); if (T->next[i] == 0) { test_sol(T,i); return; } } i++; T->u[i] = 0; if (T->partrel) gaffect(gel(T->partrel,i-1), gel(T->partrel,i)); if (i == T->next[i-1]) { /* change prime */ if (T->next[i] == i+1 || i == T->nPR) /* only one Prime above p */ { T->S[i] = 0; T->u[i] = T->n[i] / T->f[i]; /* we already know this is exact */ if (T->partrel) fix_partrel(T, i); } else T->S[i] = T->n[i]; } else T->S[i] = T->S[i-1]; /* same prime, different Prime */ for(;;) { isintnorm_loop(T, i); T->S[i] -= T->f[i]; if (T->S[i] < 0) break; T->u[i]++; if (T->partrel) { pari_sp av = avma; gaffect(ZC_add(gel(T->partrel,i), gel(T->rel,i)), gel(T->partrel,i)); avma = av; } } } static int get_sol_abs(struct sol_abs *T, GEN bnf, GEN a, GEN *ptPR) { GEN nf = bnf_get_nf(bnf); GEN fact = absi_factor(a), 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 */ T->f = new_chunk(max+1); T->n = new_chunk(max+1); T->next = new_chunk(max+1); *ptPR = PR = cgetg(max+1, t_VEC); /* length to be fixed later */ nPR = 0; for (i = 1; i <= nP; i++) { GEN L = idealprimedec(nf, gel(P,i)); long lL = lg(L), gcd, k, v; ulong vn = itou(gel(E,i)); /* check that gcd_{P | p} f_P divides n_p */ gcd = pr_get_f(gel(L,1)); for (j=2; gcd > 1 && j < lL; j++) gcd = ugcd(gcd, pr_get_f(gel(L,j))); if (gcd > 1 && vn % gcd) { if (DEBUGLEVEL>2) { err_printf("gcd f_P does not divide n_p\n"); err_flush(); } return 0; } v = (i==nP)? 0: nPR + lL; for (k = 1; k < lL; k++) { GEN pr = gel(L,k); gel(PR, ++nPR) = pr; T->f[nPR] = pr_get_f(pr) / gcd; T->n[nPR] = vn / gcd; T->next[nPR] = v; } } T->nPR = nPR; setlg(PR, nPR + 1); T->u = cgetg(nPR+1, t_VECSMALL); T->S = new_chunk(nPR+1); T->cyc = bnf_get_cyc(bnf); Ngen = lg(T->cyc)-1; if (Ngen == 0) T->rel = T->partrel = NULL; /* trivial Cl(K), no relations to check */ else { int triv = 1; T->partrel = new_chunk(nPR+1); T->rel = new_chunk(nPR+1); for (i=1; i <= nPR; i++) { GEN c = isprincipal(bnf, gel(PR,i)); gel(T->rel,i) = c; if (triv && !ZV_equal0(c)) triv = 0; /* non trivial relations in Cl(K)*/ } /* triv = 1: all ideals dividing a are principal */ if (triv) T->rel = T->partrel = NULL; } if (T->partrel) { long B = ZV_max_lg(T->cyc) + 3; for (i = 0; i <= nPR; i++) { /* T->partrel[0] also needs to be initialized */ GEN c = cgetg(Ngen+1, t_COL); gel(T->partrel,i) = c; for (j=1; j<=Ngen; j++) { GEN z = cgeti(B); gel(c,j) = z; z[1] = evalsigne(0)|evallgefint(B); } } } T->smax = 511; T->normsol = new_chunk(T->smax+1); T->S[0] = T->n[1]; T->next[0] = 1; T->sindex = 0; isintnorm_loop(T, 0); return 1; } /* Look for unit of norm -1. Return 1 if it exists and set *unit, 0 otherwise */ static long get_unit_1(GEN bnf, GEN *unit) { GEN v, nf = bnf_get_nf(bnf); long i, n = nf_get_degree(nf); if (DEBUGLEVEL > 2) err_printf("looking for a fundamental unit of norm -1\n"); if (odd(n)) { *unit = gen_m1; return 1; } v = nfsign_units(bnf, NULL, 0); for (i = 1; i < lg(v); i++) if ( Flv_sum( gel(v,i), 2) ) { *unit = gel(bnf_get_fu(bnf), i); return 1; } return 0; } GEN bnfisintnormabs(GEN bnf, GEN a) { struct sol_abs T; GEN nf, res, PR; long i; if (typ(a) != t_INT) pari_err_TYPE("bnfisintnormabs",a); 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); /* |a| > 1 => T.nPR > 0 */ res = cgetg(T.sindex+1, t_VEC); for (i=1; i<=T.sindex; i++) { GEN x = vecsmall_to_col( gel(T.normsol,i) ); x = isprincipalfact(bnf, NULL, PR, x, nf_FORCE | nf_GEN_IF_PRINCIPAL); gel(res,i) = coltoliftalg(nf, x); /* x solution, up to sign */ } return res; } GEN bnfisintnorm(GEN bnf, GEN a) { 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); long norm_1 = 0; /* gcc -Wall */ /* update z in place to get correct signs: multiply by unit of norm -1 if * it exists, otherwise delete solution with wrong sign */ for (i = j = 1; i < l; i++) { 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 (sNx != sa) { if (! unit) norm_1 = get_unit_1(bnf, &unit); if (!norm_1) { if (DEBUGLEVEL > 2) err_printf("%Ps eliminated because of sign\n",x); continue; } if (xpol) x = (unit == gen_m1)? RgX_neg(x): RgXQ_mul(unit,x,T); else x = (unit == gen_m1)? gneg(x): RgX_Rg_mul(unit,x); } gel(z,j++) = x; } setlg(z, j); return gerepilecopy(av, z); } pari-2.7.5/src/modules/elldata.c0000644000175000017500000001440712366172547015142 0ustar billbill/* Copyright (C) 2005 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. */ /********************************************************************/ /** **/ /** INTERFACE TO JOHN CREMONA ELLIPTIC CURVES DATABASE **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static long strtoclass(const char *s) { long c=0; while (*s && *s<='9') s++; if (!*s) return -1; while ('a'<=*s && *s<='z') c = 26*c + *(s++)-'a'; return c; } /*Take a curve name like "100a2" and set * f to the conductor, (100) * c to the isogeny class (in base 26), ("a" or 0) * i to the curve index (2). * return 0 if parse error. */ static int ellparsename(const char *s, long *f, long *c, long *i) { long j; *f=-1; *c=-1; *i=-1; if (*s<'0' || *s>'9') return 0; *f=0; for (j=0;j<10 && '0'<=*s && *s<='9';j++) *f=10**f+*(s++)-'0'; if (j==10) {*f=-1; return 0;} if (*s<'a' || *s>'z') return !*s; *c=0; for (j=0; j<7 && 'a'<=*s && *s<='z';j++) *c=26**c+*(s++)-'a'; if (j==7) {*c=-1; return 0;} if (*s<'0' || *s>'9') return !*s; *i=0; for (j=0; j<10 && '0'<=*s && *s<='9';j++) *i=10**i+*(s++)-'0'; if (j==10) {*i=-1; return 0;} return !*s; } /* Take an integer and convert it to base 26 */ static GEN ellrecode(long x) { GEN str; char *s; long d = 0, n = x; do { d++; n /= 26; } while (n); str = cgetg(nchar2nlong(d+1)+1, t_STR); s = GSTR(str); s[d] = 0; n = x; do { s[--d] = n%26 + 'a'; n /= 26; } while (n); return str; } GEN ellconvertname(GEN n) { switch(typ(n)) { case t_STR: { long f,i,c; if (!ellparsename(GSTR(n),&f,&c,&i)) pari_err_TYPE("ellconvertname", n); if (f<0 || c<0 || i<0) pari_err_TYPE("ellconvertname [incomplete name]", n); return mkvec3s(f,c,i); } case t_VEC: if (lg(n)==4) { pari_sp av = avma; GEN f=gel(n,1), c=gel(n,2), s=gel(n,3); if (typ(f)!=t_INT || typ(c)!=t_INT || typ(s)!=t_INT) pari_err_TYPE("ellconvertname",n); return gerepilecopy(av, shallowconcat1(mkvec3(f, ellrecode(itos(c)), s))); } /*fall through*/ } pari_err_TYPE("ellconvertname",n); return NULL; /*Not reached*/ } static GEN ellcondfile(long f) { pari_sp av = avma; long n = f / 1000; char *s = stack_malloc(strlen(pari_datadir) + 12 + 20 + 1); pariFILE *F; GEN V; sprintf(s, "%s/elldata/ell%ld", pari_datadir, n); F = pari_fopengz(s); if (!F) pari_err_FILE("elldata file",s); avma = av; V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC ) pari_err_FILE("elldata file [read]",s); pari_fclose(F); return V; } /* return the vector of all curves of conductor f */ static int cmpi1(GEN x, GEN v) { return cmpii(x, gel(v,1)); } static GEN ellcondlist(long f) { pari_sp av = avma; GEN V = ellcondfile(f); long i = tablesearch(V, utoipos(f), &cmpi1); if (i) { GEN v = gel(V,i); return vecslice(v,2, lg(v)-1); } avma = av; return cgetg(1,t_VEC); } static GEN ellsearchbyname(GEN V, char *name) { GEN x; long j; for (j=1; j=2 ? gtos(gel(A,2)): -1; i = l>=3 ? gtos(gel(A,3)): -1; if (l>=3) A = ellconvertname(A); } else if (typ(A)==t_STR) { if (!ellparsename(GSTR(A),&f,&c,&i)) pari_err_TYPE("ellsearch",A); } else { pari_err_TYPE("ellsearch",A); return NULL; } if (f <= 0) pari_err_DOMAIN("ellsearch", "conductor", "<=", gen_0,stoi(f)); V = ellcondlist(f); if (c >= 0) V = (i < 0)? ellsearchbyclass(V,c): ellsearchbyname(V, GSTR(A)); return gerepilecopy(av, V); } GEN ellsearchcurve(GEN name) { pari_sp ltop=avma; long f, c, i; if (!ellparsename(GSTR(name),&f,&c,&i)) pari_err_TYPE("ellsearch",name); if (f<0 || c<0 || i<0) pari_err_TYPE("ellsearch [incomplete name]", name); return gerepilecopy(ltop, ellsearchbyname(ellcondlist(f), GSTR(name))); } GEN ellidentify(GEN E) { pari_sp ltop=avma; GEN V, M, G = ellglobalred(E), N = gel(G,1); long j; V = ellcondlist(itos(N)); M = ellchangecurve(vecslice(E,1,5),gel(G,2)); for (j=1; jb) break; for(k=2; k 'all'; use strict; use PARI::822; my (%funcs, %Fun_by_sec); PARI::822::read(\%funcs, "pari.desc"); open (FILE, "../../doc/usersFUNCS.tex") || die; for (keys %funcs) { my ($s) = $funcs{$_}->{Section}; next if (!$s); push(@{$Fun_by_sec{$s}}, $_); } while () { if (/^% *SECTION *: *(.*) */) { my ($sec) = $1; next if (!$Fun_by_sec{$sec}); for ( sort @{$Fun_by_sec{$sec}} ) { my ($fun) = $funcs{$_}; my ($doc) = $fun->{Doc}; next if (!defined($doc)); my ($args) = $fun->{Help}; my ($v); $doc =~ s/^[\n\t ]*(.)/uc($1)/e; $args =~ s/ *:.*//s; if (!$args || $args =~ /^\w+=\w+\(\)/) { $args = $v = ''; } else { $args =~ s/^[^(]*\((.*)\)/$1/; # args proper $v = $args; $v =~ s/([{}&])/\\$1/g; $v =~ s/\^(\d+)/^{$1}/g; $v =~ s/\[\]/[\\,]/g; $v =~ s/(\w\w+)/\\var{$1}/g; $v =~ s/\^([a-z])/\\hbox{\\kbd{\\pow}}$1/g; $v =~ s/\\var\{flag\}/\\fl/g; $v =~ s/\\var\{(\d+)\}/{$1}/g; $v = "\$($v)\$"; } if ($doc !~ /\\syn\w*\{/ && $sec !~ /programming\/control/) { $doc .= library_syntax($fun, $args); } s/_def_//; my ($secname) = $_; my ($l) = ($fun->{Section} =~ 'default')? "def,$_": $_; my ($idx) = ($secname =~ s/_/\\_/g)? $l: $secname; print "\n\\subsec{$secname$v}\\kbdsidx{$idx}\\label{se:$l}\n$doc\n"; } } print; } sub library_syntax { my ($fun, $args) = @_; return '' if ($fun->{Class} =~ /^(highlevel|gp|default|gp_default)$/); my ($Cname) = $fun->{'C-Name'}; return '' if (!$Cname); my ($Variant) = $fun->{Variant}; my (@proto) = split(//, $fun->{Prototype}); $args =~ s/[{}&]//g; $args =~ s/=[^,\)]*//g; # delete default values my (@ARGS) = split(/[,^] */, $args); # ^ for O(p^e) my ($type) = "GEN"; my (@vars)=(); $args = ''; for (my $i = 0; $i <= $#proto; ) { my ($c) = $proto[$i++]; if ($c eq 'l') { $type = "long"; next; } if ($c eq 'v') { $type = "void"; next; } if ($c =~ /^[GWIJE]$/) {$args .= ", GEN " . shift(@ARGS); next;} if ($c eq 'L') {$args .= ", long " . shift(@ARGS); next;} if ($c eq 'n') {my ($v) = shift(@ARGS); push @vars,"\\kbd{$v}"; $args .= ", long " . $v; next;} if ($c =~ /^[rs]$/) {$args .= ", const char *" . shift(@ARGS); next;} if ($c eq 'p') {$args .= ", long prec"; next;} if ($c eq 'P') {$args .= ", long precdl"; next;} if ($c eq 'C') {$args .= ", GEN ctx"; next;} if ($c eq '') { next; } if ($c eq 'D') { $c = $proto[$i++]; if ($c eq 'G') {$args .= ", GEN " . shift(@ARGS) ." = NULL"; next;} if ($c =~ /^[rs]$/) {$args .= ", const char *" . shift(@ARGS) ." = NULL"; next;} if ($c eq '&') {$args .= ", GEN *". shift(@ARGS) ." = NULL"; next;} if ($c eq 'P') {$args .= ", long precdl"; next;} if ($c eq 'n') { my ($v) = shift(@ARGS); $args .= ", long $v = -1"; push @vars,"\\kbd{$v}"; next; } if ($c eq 'V') { next; } if ($c =~ /^[EI]$/) { $args .= ", GEN ". shift(@ARGS) ." = NULL"; next; } while (($c = $proto[$i++]) ne ',') {} } } $args =~ s/^, //; my ($post); my ($l)=scalar @vars; if ($l==0) { $post=''; } elsif ($l==1) { $post = ", where $vars[0] is a variable number"; } else { my ($vl)=join(", ",@vars); $post = ", where $vl are variable numbers"; } my ($txt) = "\n\nThe library syntax is \\fun{$type}{$Cname}{$args}$post."; $txt .= "\n$Variant" if ($Variant); return $txt; } pari-2.7.5/src/desc/merge_8220000755000175000017500000000041711636712103014235 0ustar billbill#!/usr/bin/perl -w use PARI::822; open(IN, $ARGV[0]) || die "cannot find $ARGV[0]"; for () { s/^\d+\s+\d+\s+//; PARI::822::read(\%funcs,$_,1) } for (keys %funcs) { $funcs{$_}->{'Class'} = 'basic' if (!defined($funcs{$_}->{'Class'})); } PARI::822::write(\%funcs); pari-2.7.5/src/desc/PARI/0000755000175000017500000000000012613365633013356 5ustar billbillpari-2.7.5/src/desc/PARI/822.pm0000755000175000017500000000721412314242551014225 0ustar billbill#!/usr/bin/perl -w #Copyright (C) 2003 The PARI group. # #This file is part of the GP2C 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. #Based on Debconf::Format::822 by Joey Hess . package PARI::822; use strict; sub new { bless {} } =d1 NAME PARI::822::read -- Read Description files. =head1 SYNOPSIS $database->PARI::822::new(); $database->read($filename,$mode) PARI::822::read(\%database,$filename,$mode) =head1 DESCRIPTION read the database file $filename and merge the information in the database. Mode is a bitmap flag mode&1: new values cannot overwrite old ones. mode&2: new functions are not allowed. =cut sub read { local $/="\n"; local *FILE; my ($ret,$file,$check)=@_; $check=0 if (!defined($check)); my $invars=0; my ($key, $value); my $last_was_void=0; my $entry; my ($store) = sub { $value =~ s/\s*$//; if (!defined($ret->{$entry}->{$key})) { $ret->{$entry}->{$key}=$value; } elsif (($check&1) and $ret->{$entry}->{$key} ne $value) { die "Unmatched data: $entry: $key: $ret->{$entry}->{$key} ne $value"; } }; open FILE,"<$file"; while (my $line = ) { chomp $line; if ($invars && $line =~ /^\s/) { $line =~ s/^\s//; $value.= ($last_was_void?"\n\n$line":"\n$line"); $last_was_void = 0; next; } $last_was_void = ($line =~ /^\s*$/); next if ($last_was_void); $store->() if ($invars); ($key, $value)=split(/:\s*/, $line, 2); die("Bad entry in $file: $key") if (!defined($value)); if ($key eq 'Function') { $entry=$value; die("New function $value") if (($check&2) and !defined($ret->{$entry})); } $invars=1; } $store->() if ($invars); return 0; } =d1 NAME PARI::822::write -- Write Description files. =head1 SYNOPSIS $database->PARI::822::new(); $database->write($filename) PARI::822::write(\%database,STREAM) =head1 DESCRIPTION output a database to STREAM in canonical 822 format. =cut sub write { my @order=("Function","Class","Section","C-Name","Prototype","Help", "Iterator","Wrapper","Description","Doc"); my %knowfields=map {$_ => 1} @order; my %data=%{shift()}; my $STREAM=shift; defined($STREAM) or $STREAM=*STDOUT; foreach my $func (sort keys %data) { foreach my $field (@order) { my $val=$data{$func}->{$field}; next if (!defined($val)); $val =~ s/\n/\n /g; print $STREAM $field.": $val\n"; } foreach my $field (sort keys %{$data{$func}}) { next if ($knowfields{$field}); my $val=$data{$func}->{$field}; $val =~ s/\n/\n /g; print $STREAM $field.": $val\n"; } print $STREAM "\n"; } } 1; pari-2.7.5/src/desc/gen_proto0000755000175000017500000000343512405547147014553 0ustar billbill#!/usr/bin/perl -w use PARI::822; $class=$ARGV[0]; %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, ); print <) { 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() { 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("",@tab[0..$c-1]); $post = join("",@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; } pari-2.7.5/src/basemath/0000755000175000017500000000000012613365633013471 5ustar billbillpari-2.7.5/src/basemath/F2xqE.c0000644000175000017500000005332212366172547014574 0ustar billbill/* Copyright (C) 2012 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 F_2^n */ /***********************************************************************/ /** **/ /** F2xqE **/ /** **/ /***********************************************************************/ /* Theses functions deal with point over elliptic curves over F_2^n defined * by an equation of the form: ** y^2+x*y=x^3+a_2*x^2+a_6 if the curve is ordinary. ** y^2+a_3*y=x^3+a_4*x+a_6 if the curve is supersingular. * Most of the time a6 is omitted since it can be recovered from any point * on the curve. * For supersingular curves, the parameter a2 is replaced by [a3,a4,a3^-1]. */ GEN RgE_to_F2xqE(GEN x, GEN T) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_F2xq(gel(x,1),T),Rg_to_F2xq(gel(x,2),T)); } GEN F2xqE_changepoint(GEN x, GEN ch, GEN T) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = F2xq_inv(u, T); v2 = F2xq_sqr(v, T); v3 = F2xq_mul(v,v2, T); p1 = F2x_add(gel(x,1),r); z = cgetg(3,t_VEC); gel(z,1) = F2xq_mul(v2, p1, T); gel(z,2) = F2xq_mul(v3, F2x_add(gel(x,2), F2x_add(F2xq_mul(s, p1, T),t)), T); return gerepileupto(av, z); } GEN F2xqE_changepointinv(GEN x, GEN ch, GEN T) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = F2xq_sqr(u, T); u3 = F2xq_mul(u,u2, T); u2X = F2xq_mul(u2,X, T); z = cgetg(3, t_VEC); gel(z,1) = F2x_add(u2X,r); gel(z,2) = F2x_add(F2xq_mul(u3,Y, T), F2x_add(F2xq_mul(s,u2X, T), t)); return z; } static GEN F2xqE_dbl_slope(GEN P, GEN a, GEN T, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P)) return ellinf(); x = gel(P,1); y = gel(P,2); if (typ(a)==t_VECSMALL) { GEN a2 = a; if (!lgpol(gel(P,1))) return ellinf(); *slope = F2x_add(x, F2xq_div(y, x, T)); Q = cgetg(3,t_VEC); gel(Q, 1) = F2x_add(F2xq_sqr(*slope, T), F2x_add(*slope, a2)); gel(Q, 2) = F2x_add(F2xq_mul(*slope, F2x_add(x, gel(Q, 1)), T), F2x_add(y, gel(Q, 1))); } else { GEN a3 = gel(a,1), a4 = gel(a,2), a3i = gel(a,3); *slope = F2xq_mul(F2x_add(a4, F2xq_sqr(x, T)), a3i, T); Q = cgetg(3,t_VEC); gel(Q, 1) = F2xq_sqr(*slope, T); gel(Q, 2) = F2x_add(F2xq_mul(*slope, F2x_add(x, gel(Q, 1)), T), F2x_add(y, a3)); } return Q; } GEN F2xqE_dbl(GEN P, GEN a, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_dbl_slope(P, a, T,&slope)); } static GEN F2xqE_add_slope(GEN P, GEN Q, GEN a, GEN T, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (F2x_equal(Px, Qx)) { if (F2x_equal(Py, Qy)) return F2xqE_dbl_slope(P, a, T, slope); else return ellinf(); } *slope = F2xq_div(F2x_add(Py, Qy), F2x_add(Px, Qx), T); R = cgetg(3,t_VEC); if (typ(a)==t_VECSMALL) { GEN a2 = a; gel(R, 1) = F2x_add(F2x_add(F2x_add(F2x_add(F2xq_sqr(*slope, T), *slope), Px), Qx), a2); gel(R, 2) = F2x_add(F2xq_mul(*slope, F2x_add(Px, gel(R, 1)), T), F2x_add(Py, gel(R, 1))); } else { GEN a3 = gel(a,1); gel(R, 1) = F2x_add(F2x_add(F2xq_sqr(*slope, T), Px), Qx); gel(R, 2) = F2x_add(F2xq_mul(*slope, F2x_add(Px, gel(R, 1)), T), F2x_add(Py, a3)); } return R; } GEN F2xqE_add(GEN P, GEN Q, GEN a, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_add_slope(P, Q, a, T, &slope)); } static GEN F2xqE_neg_i(GEN P, GEN a) { GEN LHS; if (ell_is_inf(P)) return P; LHS = typ(a)==t_VECSMALL ? gel(P,1): gel(a,1); return mkvec2(gel(P,1), F2x_add(LHS, gel(P,2))); } GEN F2xqE_neg(GEN P, GEN a, GEN T) { GEN LHS; (void) T; if (ell_is_inf(P)) return ellinf(); LHS = typ(a)==t_VECSMALL ? gel(P,1): gel(a,1); return mkvec2(gcopy(gel(P,1)), F2x_add(LHS, gel(P,2))); } GEN F2xqE_sub(GEN P, GEN Q, GEN a2, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_add_slope(P, F2xqE_neg_i(Q, a2), a2, T, &slope)); } struct _F2xqE { GEN a2, a6; GEN T; }; static GEN _F2xqE_dbl(void *E, GEN P) { struct _F2xqE *ell = (struct _F2xqE *) E; return F2xqE_dbl(P, ell->a2, ell->T); } static GEN _F2xqE_add(void *E, GEN P, GEN Q) { struct _F2xqE *ell=(struct _F2xqE *) E; return F2xqE_add(P, Q, ell->a2, ell->T); } static GEN _F2xqE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _F2xqE *e=(struct _F2xqE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = F2xqE_neg(P, e->a2, e->T); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepileupto(av, gen_pow(P, n, e, &_F2xqE_dbl, &_F2xqE_add)); } GEN F2xqE_mul(GEN P, GEN n, GEN a2, GEN T) { struct _F2xqE E; E.a2 = a2; E.T = T; return _F2xqE_mul(&E, P, n); } /* Finds a random non-singular point on E */ GEN random_F2xqE(GEN a, GEN a6, GEN T) { pari_sp ltop = avma; GEN x, y, rhs, u; do { avma= ltop; x = random_F2x(F2x_degree(T),T[1]); if (typ(a) == t_VECSMALL) { GEN a2 = a, x2; if (!lgpol(x)) { avma=ltop; retmkvec2(pol0_Flx(T[1]), F2xq_sqrt(a6,T)); } u = x; x2 = F2xq_sqr(x, T); rhs = F2x_add(F2xq_mul(x2,F2x_add(x,a2),T),a6); rhs = F2xq_div(rhs,x2,T); } else { GEN a3 = gel(a,1), a4 = gel(a,2), a3i = gel(a,3), u2i; u = a3; u2i = F2xq_sqr(a3i,T); rhs = F2x_add(F2xq_mul(x,F2x_add(F2xq_sqr(x,T),a4),T),a6); rhs = F2xq_mul(rhs,u2i,T); } } while (F2xq_trace(rhs,T)); y = F2xq_mul(F2xq_Artin_Schreier(rhs, T), u, T); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _F2xqE_rand(void *E) { struct _F2xqE *ell=(struct _F2xqE *) E; return random_F2xqE(ell->a2, ell->a6, ell->T); } static const struct bb_group F2xqE_group={_F2xqE_add,_F2xqE_mul,_F2xqE_rand,hash_GEN,zvV_equal,ell_is_inf, NULL}; const struct bb_group * get_F2xqE_group(void ** pt_E, GEN a2, GEN a6, GEN T) { struct _F2xqE *e = (struct _F2xqE *) stack_malloc(sizeof(struct _F2xqE)); e->a2 = a2; e->a6 = a6; e->T = T; *pt_E = (void *) e; return &F2xqE_group; } GEN F2xqE_order(GEN z, GEN o, GEN a2, GEN T) { pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.T=T; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &F2xqE_group)); } GEN F2xqE_log(GEN a, GEN b, GEN o, GEN a2, GEN T) { pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.T=T; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &F2xqE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN F2xqE_vert(GEN P, GEN Q, GEN T) { if (ell_is_inf(P)) return pol1_F2x(T[1]); return F2x_add(gel(Q, 1), gel(P, 1)); } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN F2xqE_tangent_update(GEN R, GEN Q, GEN a2, GEN T, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol1_F2x(T[1]); } else if (!lgpol(gel(R,1))) { *pt_R = ellinf(); return F2xqE_vert(R, Q, T); } else { GEN slope, 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)); return F2x_add(gel(Q, 2), tmp2); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN F2xqE_chord_update(GEN R, GEN P, GEN Q, GEN a2, GEN T, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return F2xqE_vert(P, Q, T); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return F2xqE_vert(R, Q, T); } else if (F2x_equal(gel(P, 1), gel(R, 1))) { if (F2x_equal(gel(P, 2), gel(R, 2))) return F2xqE_tangent_update(R, Q, a2, T, pt_R); else { *pt_R = ellinf(); return F2xqE_vert(R, Q, T); } } else { GEN slope, 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)); return F2x_add(gel(Q, 2), tmp2); } } /* Returns the Miller function f_{m, Q} evaluated at the point P using the standard Miller algorithm. */ struct _F2xqE_miller { GEN T, a2, P; }; static GEN F2xqE_Miller_dbl(void* E, GEN d) { struct _F2xqE_miller *m = (struct _F2xqE_miller *)E; GEN T = m->T, a2 = m->a2, P = m->P; GEN v, line; GEN num = F2xq_sqr(gel(d,1), T); GEN denom = F2xq_sqr(gel(d,2), T); GEN point = gel(d,3); line = F2xqE_tangent_update(point, P, a2, T, &point); num = F2xq_mul(num, line, T); v = F2xqE_vert(point, P, T); denom = F2xq_mul(denom, v, T); return mkvec3(num, denom, point); } static GEN F2xqE_Miller_add(void* E, GEN va, GEN vb) { struct _F2xqE_miller *m = (struct _F2xqE_miller *)E; GEN T = m->T, a2 = m->a2, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN num = F2xq_mul(na, nb, T); GEN denom = F2xq_mul(da, db, T); line = F2xqE_chord_update(pa, pb, P, a2, T, &point); num = F2xq_mul(num, line, T); v = F2xqE_vert(point, P, T); denom = F2xq_mul(denom, v, T); return mkvec3(num, denom, point); } static GEN F2xqE_Miller(GEN Q, GEN P, GEN m, GEN a2, GEN T) { pari_sp ltop = avma; struct _F2xqE_miller d; GEN v, num, denom, g1; d.a2 = a2; d.T = T; d.P = P; g1 = pol1_F2x(T[1]); v = gen_pow(mkvec3(g1,g1,Q), m, (void*)&d, F2xqE_Miller_dbl, F2xqE_Miller_add); num = gel(v,1); denom = gel(v,2); if (!lgpol(num) || !lgpol(denom)) { avma = ltop; return NULL; } return gerepileupto(ltop, F2xq_div(num, denom, T)); } GEN F2xqE_weilpairing(GEN P, GEN Q, GEN m, GEN a2, GEN T) { pari_sp ltop = avma; GEN num, denom, result; if (ell_is_inf(P) || ell_is_inf(Q) || F2x_equal(P,Q)) return pol1_F2x(T[1]); num = F2xqE_Miller(P, Q, m, a2, T); if (!num) return pol1_F2x(T[1]); denom = F2xqE_Miller(Q, P, m, a2, T); if (!denom) { avma=ltop; return pol1_F2x(T[1]); } result = F2xq_div(num, denom, T); return gerepileupto(ltop, result); } GEN F2xqE_tatepairing(GEN P, GEN Q, GEN m, GEN a2, GEN T) { GEN num; if (ell_is_inf(P) || ell_is_inf(Q)) return pol1_F2x(T[1]); num = F2xqE_Miller(P, Q, m, a2, T); return num? num: pol1_F2x(T[1]); } /***********************************************************************/ /** **/ /** Point counting **/ /** **/ /***********************************************************************/ static GEN Z2x_rshift(GEN y, long x) { GEN z; long i, l; if (!x) return pol0_Flx(y[1]); z = cgetg_copy(y, &l); z[1] = y[1]; for(i=2; i>x; return Flx_renormalize(z, l); } /* Solve the linear equation approximation in the Newton algorithm */ static GEN gen_Z2x_Dixon(GEN F, GEN V, long N, void *E, GEN lin(void *E, GEN F, GEN d, long N), GEN invl(void *E, GEN d)) { pari_sp av = avma; long N2, M; GEN VN2, V2, VM, bil; ulong q = 1UL<>1; M = N - N2; F = FlxT_red(F, q); VN2 = gen_Z2x_Dixon(F, V, N2, E, lin, invl); bil = lin(E, F, VN2, N); V2 = Z2x_rshift(Flx_sub(V, bil, q), N2); VM = gen_Z2x_Dixon(F, V2, M, E, lin, invl); return gerepileupto(av, Flx_add(VN2, Flx_Fl_mul(VM, 1UL<>1; m = N - n; F = ZXT_remi2n(F, N); Xn = gen_Z2X_Dixon(F, V, n, E, lin, lins, invls); FXn = lin(E, F, Xn, N); Vm = ZX_shifti(ZX_sub(V, FXn), -n); Xm = gen_Z2X_Dixon(F, Vm, m, E, lin, lins, invls); return gerepileupto(av, ZX_remi2n(ZX_add(Xn, ZX_shifti(Xm, n)), N)); } /* H -> H mod 2*/ static GEN _can_invls(void *E, GEN V) {(void) E; return V; } /* H -> H-(f0*H0-f1*H1) */ static GEN _can_lin(void *E, GEN F, GEN V, long N) { pari_sp av=avma; GEN d0, d1, z; (void) E; RgX_even_odd(V, &d0, &d1); z = ZX_sub(V, ZX_sub(ZX_mul(gel(F,1), d0), ZX_mul(gel(F,2), d1))); return gerepileupto(av, ZX_remi2n(z, N)); } static GEN _can_lins(void *E, GEN F, GEN V, long N) { GEN D=Flx_splitting(V, 2), z; ulong q = 1UL< P-(P0^2-X*P1^2) */ static GEN _can_iter(void *E, GEN f2, GEN q) { GEN f0, f1, z; (void) E; RgX_even_odd(f2, &f0, &f1); z = ZX_add(ZX_sub(f2, FpX_sqr(f0, q)), RgX_shift_shallow(FpX_sqr(f1, q), 1)); return mkvec3(z,f0,f1); } /* H -> H-(2*P0*H0-2*X*P1*H1) */ static GEN _can_invd(void *E, GEN V, GEN v, GEN q, long M) { GEN F; (void)E; (void)q; F = mkvec2(ZX_shifti(gel(v,2),1), ZX_shifti(RgX_shift_shallow(gel(v,3),1),1)); return gen_Z2X_Dixon(F, V, M, NULL, _can_lin, _can_lins, _can_invls); } /* Lift P to Q such that Q(x^2)=Q(x)*Q(-x) mod 2^n if Q = Q0(X^2)+X*Q1(X^2), solve Q(x^2) = Q0^2-X*Q1^2 */ static GEN F2x_canonlift(GEN P, long n) { return gen_ZpX_Newton(F2x_to_ZX(P),gen_2, n, NULL, _can_iter, _can_invd); } static GEN Z2XQ_frob(GEN x, GEN T, GEN q) { return FpX_rem(RgX_inflate(x, 2), T, q); } static GEN Z2xq_frob(GEN x, GEN T, ulong q) { return Flx_rem(Flx_inflate(x, 2), T, q); } struct _frob_lift { GEN T, sqx; }; /* H -> S^-1(H) mod 2 */ static GEN _frob_invls(void *E, GEN V) { struct _frob_lift *F = (struct _frob_lift*) E; GEN sqx = F->sqx; return F2x_to_Flx(F2xq_sqrt_fast(Flx_to_F2x(V), gel(sqx,1), gel(sqx,2))); } /* H -> f1*S(H) + f2*H */ static GEN _frob_lin(void *E, GEN F, GEN x2, long N) { GEN T = gel(F,3); GEN q = int2n(N); GEN y2 = Z2XQ_frob(x2, T, q); GEN lin = ZX_add(ZX_mul(gel(F,1), y2), ZX_mul(gel(F,2), x2)); (void) E; return FpX_rem(ZX_remi2n(lin, N), T, q); } static GEN _frob_lins(void *E, GEN F, GEN x2, long N) { GEN T = gel(F,3); ulong q = 1UL< P(X,S(X)) */ static GEN _lift_iter(void *E, GEN x2, GEN q) { struct _frob_lift *F = (struct _frob_lift*) E; long N = expi(q); GEN TN = ZXT_remi2n(F->T, N); GEN y2 = Z2XQ_frob(x2, TN, q); GEN x2y2 = FpX_rem(ZX_remi2n(ZX_mul(x2, y2), N), TN, q); GEN s = ZX_add(ZX_add(x2, ZX_shifti(y2, 1)), ZX_shifti(x2y2, 3)); GEN V = ZX_add(ZX_add(ZX_sqr(s), y2), ZX_shifti(x2y2, 2)); return mkvec4(FpX_rem(ZX_remi2n(V, N), TN, q),x2,y2,s); } /* H -> Dx*H+Dy*S(H) */ static GEN _lift_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _frob_lift *F = (struct _frob_lift*) E; GEN TM = ZXT_remi2n(F->T, M); GEN x2 = gel(v,2), y2 = gel(v,3), s = gel(v,4), r; GEN Dx = ZX_add(ZX_mul(ZX_Z_add(ZX_shifti(y2, 4), gen_2), s), ZX_shifti(y2, 2)); GEN Dy = ZX_add(ZX_Z_add(ZX_mul(ZX_Z_add(ZX_shifti(x2, 4), utoi(4)), s), gen_1), ZX_shifti(x2, 2)); Dx = FpX_rem(ZX_remi2n(Dx, M), TM, qM); Dy = FpX_rem(ZX_remi2n(Dy, M), TM, qM); r = mkvec3(Dy, Dx, TM); return gen_Z2X_Dixon(r, V, M, E, _frob_lin, _frob_lins, _frob_invls); } /* Let P(X,Y)=(X+2*Y+8*X*Y)^2+Y+4*X*Y Solve P(x,S(x))=0 [mod 2^n,T] assuming x = x0 [mod 2,T] we set s = X+2*Y+8*X*Y, P = s^2+Y+4*X*Y Dx = dP/dx = (16*s+4)*x+(4*s+1) Dy = dP/dy = (16*y+2)*s+4*y */ static GEN solve_AGM_eqn(GEN x0, long n, GEN T, GEN sqx) { struct _frob_lift F; F.T=T; F.sqx=sqx; return gen_ZpX_Newton(x0, gen_2, n, &F, _lift_iter, _lift_invd); } static GEN Z2XQ_invnorm_pcyc(GEN a, GEN T, long e) { GEN q = int2n(e); GEN z = ZpXQ_norm_pcyc(a, T, q, gen_2); return Fp_inv(z, q); } /* Assume a = 1 [4] */ static GEN Z2XQ_invnorm(GEN a, GEN T, long e) { pari_timer ti; GEN pe = int2n(e), s; if (degpol(a)==0) return Fp_inv(Fp_powu(gel(a,2), get_FpX_degree(T), pe), pe); if (DEBUGLEVEL>=3) timer_start(&ti); s = ZpXQ_log(a, T, gen_2, e); if (DEBUGLEVEL>=3) timer_printf(&ti,"Z2XQ_log"); s = Fp_neg(FpXQ_trace(s, T, pe), pe); if (DEBUGLEVEL>=3) timer_printf(&ti,"FpXQ_trace"); s = modii(gel(Qp_exp(cvtop(s, gen_2, e-2)),4),pe); if (DEBUGLEVEL>=3) timer_printf(&ti,"Qp_exp"); return s; } /* Assume a2==0, so 4|E(F_p): if t^4 = a6 then (t,t^2) is of order 4 8|E(F_p) <=> trace(a6)==0 */ static GEN F2xq_elltrace_Harley(GEN a6, GEN T2) { pari_sp ltop = avma; pari_timer ti; GEN T, sqx; GEN x, x2, t; long n = F2x_degree(T2), N = ((n + 1)>>1) + 2; long ispcyc; if (n==1) return gen_m1; if (n==2) return F2x_degree(a6) ? gen_1 : stoi(-3); if (n==3) return F2x_degree(a6) ? (F2xq_trace(a6,T2) ? stoi(-3): gen_1) : stoi(5); timer_start(&ti); sqx = mkvec2(F2xq_sqrt(polx_F2x(T2[1]),T2), T2); if (DEBUGLEVEL>1) timer_printf(&ti,"Sqrtx"); ispcyc = zx_is_pcyc(F2x_to_Flx(T2)); T = ispcyc? F2x_to_ZX(T2): F2x_canonlift(T2, N-2); if (DEBUGLEVEL>1) timer_printf(&ti,"Teich"); T = FpX_get_red(T, int2n(N)); if (DEBUGLEVEL>1) timer_printf(&ti,"Barrett"); x = solve_AGM_eqn(F2x_to_ZX(a6), N-2, T, sqx); if (DEBUGLEVEL>1) timer_printf(&ti,"Lift"); x2 = ZX_Z_add_shallow(ZX_shifti(x,2), gen_1); t = (ispcyc? Z2XQ_invnorm_pcyc: Z2XQ_invnorm)(x2, T, N); if (DEBUGLEVEL>1) timer_printf(&ti,"Norm"); if (cmpii(sqri(t), int2n(n + 2)) > 0) t = subii(t, int2n(N)); return gerepileuptoint(ltop, t); } GEN F2xq_ellcard(GEN a, GEN a6, GEN T) { pari_sp av = avma; long n = F2x_degree(T); GEN q = int2u(n), c; if (typ(a)==t_VECSMALL) { GEN t = F2xq_elltrace_Harley(a6, T); c = addii(q, F2xq_trace(a,T) ? addui(1,t): subui(1,t)); } else if (n==1) { long a4i = lgpol(gel(a,2)), a6i = lgpol(a6); return utoi(a4i? (a6i? 1: 5): 3); } else if (n==2) { GEN a3 = gel(a,1), a4 = gel(a,2), x = polx_F2x(T[1]), x1 = pol1_F2x(T[1]); GEN a613 = F2xq_mul(F2x_add(x1, a6),a3,T), a43= F2xq_mul(a4,a3,T); long f0= F2xq_trace(F2xq_mul(a6,a3,T),T); long f1= F2xq_trace(F2x_add(a43,a613),T); long f2= F2xq_trace(F2x_add(F2xq_mul(a43,x,T),a613),T); long f3= F2xq_trace(F2x_add(F2xq_mul(a43,F2x_add(x,x1),T),a613),T); c = utoi(9-2*(f0+f1+f2+f3)); } else { struct _F2xqE e; long m = (n+1)>>1; GEN q1 = addis(q, 1); GEN v = n==4 ? mkvec4s(13,17,21,25) : odd(n) ? mkvec3(subii(q1,int2u(m)),q1,addii(q1,int2u(m))): mkvec5(subii(q1,int2u(m+1)),subii(q1,int2u(m)),q1, addii(q1,int2u(m)),addii(q1,int2u(m+1))); e.a2=a; e.a6=a6; e.T=T; c = gen_select_order(v,(void*)&e, &F2xqE_group); if (n==4 && equaliu(c, 21)) /* Ambiguous case */ { GEN d = F2xq_powu(polx_F2x(T[1]),3,T), a3 = gel(a,1); e.a6 = F2x_add(a6,F2xq_mul(d,F2xq_sqr(a3,T),T)); /* twist */ c = subui(34, gen_select_order(mkvec2s(13,25),(void*)&e, &F2xqE_group)); } } return gerepileuptoint(av, c); } /***********************************************************************/ /** **/ /** Group structure **/ /** **/ /***********************************************************************/ static GEN _F2xqE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _F2xqE *e = (struct _F2xqE *) E; return F2xq_order(F2xqE_weilpairing(P,Q,m,e->a2,e->T), F, e->T); } GEN F2xq_ellgroup(GEN a2, GEN a6, GEN N, GEN T, GEN *pt_m) { struct _F2xqE e; GEN q = int2u(F2x_degree(T)); e.a2=a2; e.a6=a6; e.T=T; return gen_ellgroup(N, subis(q,1), pt_m, (void*)&e, &F2xqE_group, _F2xqE_pairorder); } GEN F2xq_ellgens(GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T) { GEN P; pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.a6=a6; e.T=T; switch(lg(D)-1) { case 0: return cgetg(1,t_VEC); case 1: P = gen_gener(gel(D,1), (void*)&e, &F2xqE_group); P = mkvec(F2xqE_changepoint(P, ch, T)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &F2xqE_group, _F2xqE_pairorder); gel(P,1) = F2xqE_changepoint(gel(P,1), ch, T); gel(P,2) = F2xqE_changepoint(gel(P,2), ch, T); break; } return gerepilecopy(av, P); } pari-2.7.5/src/basemath/FpX_factor.c0000644000175000017500000021465412415474305015701 0ustar billbill/* Copyright (C) 2012 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" /***********************************************************************/ /** **/ /** Factorisation over finite field **/ /** **/ /***********************************************************************/ /*******************************************************************/ /* */ /* ROOTS MODULO a prime p (no multiplicities) */ /* */ /*******************************************************************/ /* Check types and replace F by a monic normalized FpX having the same roots * Don't bother to make constant polynomials monic */ static void factmod_init(GEN *F, GEN p) { if (typ(p)!=t_INT) pari_err_TYPE("factmod",p); if (signe(p) < 0) pari_err_PRIME("factmod",p); if (typ(*F)!=t_POL) pari_err_TYPE("factmod",*F); if (lgefint(p) == 3) { ulong pp = p[2]; if (pp < 2) pari_err_PRIME("factmod", p); *F = RgX_to_Flx(*F, pp); if (lg(*F) > 3) *F = Flx_normalize(*F, pp); } else { *F = RgX_to_FpX(*F, p); if (lg(*F) > 3) *F = FpX_normalize(*F, p); } } /* as above, assume p prime and *F a ZX */ static void ZX_factmod_init(GEN *F, GEN p) { if (lgefint(p) == 3) { ulong pp = p[2]; *F = ZX_to_Flx(*F, pp); if (lg(*F) > 3) *F = Flx_normalize(*F, pp); } else { *F = FpX_red(*F, p); if (lg(*F) > 3) *F = FpX_normalize(*F, p); } } /* return 1,...,p-1 [not_0 = 1] or 0,...,p [not_0 = 0] */ static GEN all_roots_mod_p(ulong p, int not_0) { GEN r; ulong i; if (not_0) { r = cgetg(p, t_VECSMALL); for (i = 1; i < p; i++) r[i] = i; } else { r = cgetg(p+1, t_VECSMALL); for (i = 0; i < p; i++) r[i+1] = i; } return r; } /* X^n - 1 */ static GEN Flx_Xnm1(long sv, long n, ulong p) { GEN t = cgetg(n+3, t_VECSMALL); long i; t[1] = sv; t[2] = p - 1; for (i = 3; i <= n+1; i++) t[i] = 0; t[i] = 1; return t; } /* X^n + 1 */ static GEN Flx_Xn1(long sv, long n, ulong p) { GEN t = cgetg(n+3, t_VECSMALL); long i; (void) p; t[1] = sv; t[2] = 1; for (i = 3; i <= n+1; i++) t[i] = 0; t[i] = 1; return t; } static ulong Fl_nonsquare(ulong p) { long k = 2; for (;; k++) { long i = krouu(k, p); if (!i) pari_err_PRIME("Fl_nonsquare",utoipos(p)); if (i < 0) return k; } } /* f monic Flx, f(0) != 0. Return a monic squarefree g with the same * roots as f */ static GEN Flx_cut_out_roots(GEN f, ulong p) { GEN g = Flx_mod_Xnm1(f, p-1, p); /* f mod x^(p-1) - 1 */ if (g != f && degpol(g) >= 0) { (void)Flx_valrem(g, &g); /* reduction may introduce 0 root */ g = Flx_gcd(g, Flx_Xnm1(g[1], p-1, p), p); g = Flx_normalize(g, p); } return g; } /* by checking f(0..p-1) */ GEN Flx_roots_naive(GEN f, ulong p) { long d, n = 0; ulong s = 1UL, r; GEN q, y = cgetg(degpol(f) + 1, t_VECSMALL); pari_sp av2, av = avma; if (Flx_valrem(f, &f)) y[++n] = 0; f = Flx_cut_out_roots(f, p); d = degpol(f); if (d < 0) return all_roots_mod_p(p, n == 0); av2 = avma; while (d > 1) /* d = current degree of f */ { q = Flx_div_by_X_x(f, s, p, &r); /* TODO: FFT-type multi-evaluation */ if (r) avma = av2; else { y[++n] = s; d--; f = q; av2 = avma; } if (++s == p) break; } if (d == 1) { /* -f[2]/f[3], root of deg 1 polynomial */ r = Fl_mul(p - Fl_inv(f[3], p), f[2], p); if (r >= s) y[++n] = r; /* otherwise double root */ } avma = av; fixlg(y, n+1); return y; } static GEN Flx_root_mod_2(GEN f) { int z1, z0 = !(f[2] & 1); long i,n; GEN y; for (i=2, n=1; i < lg(f); i++) n += f[i]; z1 = n & 1; y = cgetg(z0+z1+1, t_VECSMALL); i = 1; if (z0) y[i++] = 0; if (z1) y[i ] = 1; return y; } static ulong Flx_oneroot_mod_2(GEN f) { long i,n; if (!(f[2] & 1)) return 0; for (i=2, n=1; i < lg(f); i++) n += f[i]; if (n & 1) return 1; return 2; } static GEN FpX_roots_i(GEN f, GEN p); static GEN Flx_roots_i(GEN f, ulong p); static GEN FpX_Berlekamp_i(GEN f, GEN pp, long flag); /* Generic driver to computes the roots of f modulo pp, using 'Roots' when * pp is a small prime. * if (gpwrap), check types thoroughly and return t_INTMODs, otherwise * assume that f is an FpX, pp a prime and return t_INTs */ static GEN rootmod_aux(GEN f, GEN pp, GEN (*Roots)(GEN,ulong), int gpwrap) { pari_sp av = avma; GEN y; if (gpwrap) factmod_init(&f, pp); else ZX_factmod_init(&f, pp); switch(lg(f)) { case 2: pari_err_ROOTS0("rootmod"); case 3: avma = av; return cgetg(1,t_COL); } if (typ(f) == t_VECSMALL) { ulong p = pp[2]; if (p == 2) y = Flx_root_mod_2(f); else { if (!odd(p)) pari_err_PRIME("rootmod",utoi(p)); y = Roots(f, p); } y = Flc_to_ZC(y); } else y = FpX_roots_i(f, pp); if (gpwrap) y = FpC_to_mod(y, pp); return gerepileupto(av, y); } /* assume that f is a ZX an pp a prime */ GEN FpX_roots(GEN f, GEN pp) { return rootmod_aux(f, pp, Flx_roots_i, 0); } /* no assumptions on f and pp */ GEN rootmod2(GEN f, GEN pp) { return rootmod_aux(f, pp, &Flx_roots_naive, 1); } GEN rootmod(GEN f, GEN pp) { return rootmod_aux(f, pp, &Flx_roots_i, 1); } GEN rootmod0(GEN f, GEN p, long flag) { switch(flag) { case 0: return rootmod(f,p); case 1: return rootmod2(f,p); default: pari_err_FLAG("polrootsmod"); } return NULL; /* not reached */ } /* assume x reduced mod p > 2, monic. */ static int FpX_quad_factortype(GEN x, GEN p) { GEN b = gel(x,3), c = gel(x,2); GEN D = subii(sqri(b), shifti(c,2)); return kronecker(D,p); } /* assume x reduced mod p, monic. Return one root, or NULL if irreducible */ GEN FpX_quad_root(GEN x, GEN p, int unknown) { GEN s, u, D, b = gel(x,3), c = gel(x,2); if (equaliu(p, 2)) { if (!signe(b)) return c; return signe(c)? NULL: gen_1; } D = subii(sqri(b), shifti(c,2)); D = remii(D,p); if (unknown && kronecker(D,p) == -1) return NULL; 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); } 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; } /* disc(x^2+bx+c) = b^2 - 4c */ static ulong Fl_disc_bc(ulong b, ulong c, ulong p) { return Fl_sub(Fl_sqr(b,p), Fl_double(Fl_double(c,p),p), p); } /* p > 2 */ static ulong Flx_quad_root(GEN x, ulong p, int unknown) { ulong s, u, 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); } static ulong Flx_otherroot(GEN x, ulong r, ulong p) { return Fl_neg(Fl_add(x[3], r, p), p); } /* 'todo' contains the list of factors to be split. * 'done' the list of finished factors, no longer touched */ struct split_t { GEN todo, done; }; static void split_init(struct split_t *S, long max) { S->todo = vectrunc_init(max); S->done = vectrunc_init(max); } #if 0 /* move todo[i] to done */ static void split_convert(struct split_t *S, long i) { long n = lg(S->todo)-1; vectrunc_append(S->done, gel(S->todo,i)); if (n) gel(S->todo,i) = gel(S->todo, n); setlg(S->todo, n); } #endif /* append t to todo */ static void split_add(struct split_t *S, GEN t) { vectrunc_append(S->todo, t); } /* delete todo[i], add t to done */ static void split_moveto_done(struct split_t *S, long i, GEN t) { long n = lg(S->todo)-1; vectrunc_append(S->done, t); if (n) gel(S->todo,i) = gel(S->todo, n); setlg(S->todo, n); } /* append t to done */ static void split_add_done(struct split_t *S, GEN t) { vectrunc_append(S->done, t); } /* split todo[i] into a and b */ static void split_todo(struct split_t *S, long i, GEN a, GEN b) { gel(S->todo, i) = a; split_add(S, b); } /* split todo[i] into a and b, moved to done */ static void split_done(struct split_t *S, long i, GEN a, GEN b) { split_moveto_done(S, i, a); split_add_done(S, b); } /* by splitting, assume p > 2 prime, deg(f) > 0, and f monic */ static GEN FpX_roots_i(GEN f, GEN p) { GEN pol, pol0, a, q; struct split_t S; split_init(&S, lg(f)-1); settyp(S.done, t_COL); 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 ZC_copy(S.done); case 2: { GEN s, r = FpX_quad_root(f, p, 1); if (r) { split_add_done(&S, r); s = FpX_otherroot(f,r, p); /* f not known to be square free yet */ if (!equalii(r, s)) split_add_done(&S, s); } return sort(S.done); } } a = FpXQ_pow(pol_x(varn(f)), subiu(p,1), f,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; split_add(&S, FpX_normalize(a,p)); q = shifti(p,-1); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); for (pol0[2] = 1;; pol0[2]++) { long j, l = lg(S.todo); if (l == 1) return sort(S.done); if (pol0[2] == 100 && !BPSW_psp(p)) pari_err_PRIME("polrootsmod",p); for (j = 1; j < l; j++) { GEN c = gel(S.todo,j); switch(degpol(c)) { /* convert linear and quadratics to roots, try to split the rest */ case 1: split_moveto_done(&S, j, subii(p, gel(c,2))); j--; l--; break; case 2: { GEN r = FpX_quad_root(c, p, 0), s = FpX_otherroot(c,r, p); split_done(&S, j, r, s); j--; l--; break; } default: { /* b = pol^(p-1)/2 - 1 */ GEN b = FpX_Fp_sub_shallow(FpXQ_pow(pol,q, c,p), gen_1, p); long db; b = FpX_gcd(c,b, p); db = degpol(b); if (db && db < degpol(c)) { b = FpX_normalize(b, p); c = FpX_div(c,b, p); split_todo(&S, j, b, c); } } } } } } /* assume p > 2 prime */ static ulong Flx_oneroot_i(GEN f, ulong p) { GEN pol, a; ulong q; long da; if (Flx_val(f)) return 0; switch(degpol(f)) { case 1: return Fl_neg(f[2], p); case 2: return Flx_quad_root(f, p, 1); } 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); da = degpol(a); if (!da) return p; a = Flx_normalize(a,p); q = p >> 1; pol = polx_Flx(f[1]); for(pol[2] = 1;; pol[2]++) { if (pol[2] == 1000 && !uisprime(p)) pari_err_PRIME("Flx_oneroot",utoipos(p)); switch(da) { case 1: return Fl_neg(a[2], p); case 2: return Flx_quad_root(a, p, 0); default: { GEN b = Flx_Fl_add(Flxq_powu(pol,q, a,p), p-1, p); long db; b = Flx_gcd(a,b, p); db = degpol(b); if (db && db < da) { b = Flx_normalize(b, p); if (db <= (da >> 1)) { a = b; da = db; } else { a = Flx_div(a,b, p); da -= db; } } } } } } /* assume p > 2 prime */ static GEN FpX_oneroot_i(GEN f, GEN p) { GEN pol, pol0, a, q; long da; if (ZX_val(f)) return gen_0; switch(degpol(f)) { case 1: return subii(p, gel(f,2)); case 2: return FpX_quad_root(f, p, 1); } a = FpXQ_pow(pol_x(varn(f)), subiu(p,1), f,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); da = degpol(a); if (!da) return NULL; a = FpX_normalize(a,p); q = shifti(p,-1); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); for (pol0[2]=1; ; pol0[2]++) { if (pol0[2] == 1000 && !BPSW_psp(p)) pari_err_PRIME("FpX_oneroot",p); switch(da) { case 1: return subii(p, gel(a,2)); case 2: return FpX_quad_root(a, p, 0); default: { GEN b = FpX_Fp_sub_shallow(FpXQ_pow(pol,q, a,p), gen_1, p); long db; b = FpX_gcd(a,b, p); db = degpol(b); if (db && db < da) { b = FpX_normalize(b, p); if (db <= (da >> 1)) { a = b; da = db; } else { a = FpX_div(a,b, p); da -= db; } } } } } } ulong Flx_oneroot(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); avma = av; return r; } /* assume that p is prime */ GEN FpX_oneroot(GEN f, GEN pp) { pari_sp av = avma; ZX_factmod_init(&f, pp); switch(lg(f)) { case 2: avma = av; return gen_0; case 3: avma = av; return NULL; } if (typ(f) == t_VECSMALL) { ulong r, p = pp[2]; if (p == 2) r = Flx_oneroot_mod_2(f); else r = Flx_oneroot_i(f, p); avma = av; return (r == p)? NULL: utoi(r); } f = FpX_oneroot_i(f, pp); if (!f) { avma = av; return NULL; } return gerepileuptoint(av, f); } /*******************************************************************/ /* */ /* FACTORISATION MODULO p */ /* */ /*******************************************************************/ /* Functions giving information on the factorisation. */ /* u in Z[X], return kernel of (Frob - Id) over Fp[X] / u */ GEN 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); 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)); } GEN F2x_Berlekamp_ker(GEN u) { pari_sp ltop=avma; long j,N = F2x_degree(u); GEN Q, XP; pari_timer T; timer_start(&T); XP = F2xq_sqr(polx_F2x(u[1]),u); Q = F2xq_matrix_pow(XP,N,N,u); for (j=1; j<=N; j++) F2m_flip(Q,j,j); if(DEBUGLEVEL>=9) timer_printf(&T,"Berlekamp matrix"); Q = F2m_ker_sp(Q,0); if(DEBUGLEVEL>=9) timer_printf(&T,"kernel"); return gerepileupto(ltop,Q); } GEN Flx_Berlekamp_ker(GEN u, ulong l) { pari_sp ltop=avma; long j,N = degpol(u); GEN Q, XP; 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); 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"); Q = Flm_ker_sp(Q,l,0); if(DEBUGLEVEL>=9) timer_printf(&T,"kernel"); return gerepileupto(ltop,Q); } /* product of terms of degree 1 in factorization of f */ static 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); return FpX_gcd(z,f,p); } /* Compute the number of roots in Fp without counting multiplicity * return -1 for 0 polynomial. lc(f) must be prime to p. */ long FpX_nbroots(GEN f, GEN p) { pari_sp av = avma; GEN z = FpX_split_part(f, p); avma = av; return degpol(z); } int 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 ? */ } /* Flv_Flx( Flm_Flc_mul(x, Flx_Flv(y), p) ) */ static GEN Flm_Flx_mul(GEN x, GEN y, ulong p) { long i,k,l, ly = lg(y)-1; GEN z; long vs=y[1]; if (ly==1) return zero_Flx(vs); l = lgcols(x); y++; z = zero_zv(l) + 1; if (SMALL_ULONG(p)) { for (k=1; k>1)) { /* here e = degpol(z) */ d++; w = Flm_Flx_mul(MP, w, p); /* w^p mod (z,p) */ g = Flx_gcd(z, Flx_sub(w, PolX, p), p); lgg = degpol(g); if (!lgg) continue; e -= lgg; D[d] = lgg/d; *nb += D[d]; if (DEBUGLEVEL>5) err_printf(" %3ld fact. of degree %3ld\n", D[d], d); if (!e) break; z = Flx_div(z, g, p); w = Flx_rem(w, z, p); } if (e) { if (DEBUGLEVEL>5) err_printf(" %3ld fact. of degree %3ld\n",1,e); D[e] = 1; (*nb)++; } avma = av; return D; } /* z must be squarefree mod p*/ long Flx_nbfact(GEN z, ulong p) { pari_sp av = avma; long nb; (void)Flx_nbfact_by_degree(z, &nb, p); avma = av; return nb; } long Flx_nbroots(GEN f, ulong p) { long n = degpol(f); pari_sp av = avma; GEN z, X; if (n <= 1) return n; X = polx_Flx(f[1]); z = Flxq_powu(X, p, f, p); z = Flx_sub(z, X, p); z = Flx_gcd(z, f, p); avma = av; return degpol(z); } long FpX_nbfact(GEN u, GEN p) { pari_sp av = avma; GEN vker = FpX_Berlekamp_ker(u, p); avma = av; return lg(vker)-1; } static GEN try_pow(GEN w0, GEN pol, GEN p, GEN q, long r) { GEN w2, w = FpXQ_pow(w0,q, pol,p); long s; if (gequal1(w)) return w0; for (s=1; s 2 */ static GEN FpX_is_irred_2(GEN f, GEN p, long d) { switch(d) { case -1: case 0: return NULL; case 1: return gen_1; } return FpX_quad_factortype(f, p) == -1? gen_1: NULL; } /* p > 2 */ static GEN FpX_degfact_2(GEN f, GEN p, long d) { switch(d) { case -1:retmkvec2(mkvecsmall(-1),mkvecsmall(1)); case 0: return trivial_fact(); case 1: retmkvec2(mkvecsmall(1), mkvecsmall(1)); } switch(FpX_quad_factortype(f, p)) { case 1: retmkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1: retmkvec2(mkvecsmall(2), mkvecsmall(1)); default: retmkvec2(mkvecsmall(1), mkvecsmall(2)); } } GEN prime_fact(GEN x) { retmkmat2(mkcolcopy(x), mkcol(gen_1)); } GEN trivial_fact(void) { retmkmat2(cgetg(1,t_COL), cgetg(1,t_COL)); } /* Mod(0,p) * x, where x is f's main variable */ static GEN Mod0pX(GEN f, GEN p) { return scalarpol(mkintmod(gen_0, p), varn(f)); } static GEN zero_fact_intmod(GEN f, GEN p) { return prime_fact(Mod0pX(f,p)); } /* not gerepile safe */ static GEN FpX_factor_2(GEN f, GEN p, long d) { GEN r, s, R, S; long v; int sgn; switch(d) { case -1: retmkvec2(mkcol(pol_0(varn(f))), mkvecsmall(1)); case 0: retmkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); case 1: retmkvec2(mkcol(f), mkvecsmall(1)); } r = FpX_quad_root(f, p, 1); if (!r) return mkvec2(mkcol(f), mkvecsmall(1)); v = varn(f); s = FpX_otherroot(f, r, p); if (signe(r)) r = subii(p, r); if (signe(s)) s = subii(p, s); sgn = cmpii(s, r); if (sgn < 0) swap(s,r); R = deg1pol_shallow(gen_1, r, v); if (!sgn) return mkvec2(mkcol(R), mkvecsmall(2)); S = deg1pol_shallow(gen_1, s, v); return mkvec2(mkcol2(R,S), mkvecsmall2(1,1)); } static GEN FpX_factor_deg2(GEN f, GEN p, long d, long flag) { switch(flag) { case 2: return FpX_is_irred_2(f, p, d); case 1: return FpX_degfact_2(f, p, d); default: return FpX_factor_2(f, p, d); } } static int F2x_quad_factortype(GEN x) { return x[2] == 7 ? -1: x[2] == 6 ? 1 :0; } static GEN F2x_is_irred_2(GEN f, long d) { return d == 1 || (d==2 && F2x_quad_factortype(f) == -1)? gen_1: NULL; } static GEN F2x_degfact_2(GEN f, long d) { if (!d) return trivial_fact(); if (d == 1) return mkvec2(mkvecsmall(1), mkvecsmall(1)); switch(F2x_quad_factortype(f)) { case 1: return mkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1:return mkvec2(mkvecsmall(2), mkvecsmall(1)); default: return mkvec2(mkvecsmall(1), mkvecsmall(2)); } } static GEN F2x_factor_2(GEN f, long d) { long v = f[1]; if (d < 0) pari_err(e_ROOTS0,"Flx_factor_2"); if (!d) return mkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); if (d == 1) return mkvec2(mkcol(f), mkvecsmall(1)); switch(F2x_quad_factortype(f)) { case -1: return mkvec2(mkcol(f), mkvecsmall(1)); case 0: return mkvec2(mkcol(mkvecsmall2(v,2+F2x_coeff(f,0))), mkvecsmall(2)); default: return mkvec2(mkcol2(mkvecsmall2(v,2),mkvecsmall2(v,3)), mkvecsmall2(1,1)); } } static GEN F2x_factor_deg2(GEN f, long d, long flag) { switch(flag) { case 2: return F2x_is_irred_2(f, d); case 1: return F2x_degfact_2(f, d); default: return F2x_factor_2(f, d); } } static void split_squares(struct split_t *S, GEN g, ulong p) { ulong q = p >> 1; GEN a = Flx_mod_Xnm1(g, q, p); /* mod x^(p-1)/2 - 1 */ if (degpol(a) < 0) { ulong i; split_add_done(S, (GEN)1); for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_sqr(i,p)); } else { (void)Flx_valrem(a, &a); if (degpol(a)) { a = Flx_gcd(a, Flx_Xnm1(g[1], q, p), p); if (degpol(a)) split_add(S, Flx_normalize(a, p)); } } } static void split_nonsquares(struct split_t *S, GEN g, ulong p) { ulong q = p >> 1; GEN a = Flx_mod_Xn1(g, q, p); /* mod x^(p-1)/2 + 1 */ if (degpol(a) < 0) { ulong i, z = Fl_nonsquare(p); split_add_done(S, (GEN)z); for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_mul(z, Fl_sqr(i,p), p)); } else { (void)Flx_valrem(a, &a); if (degpol(a)) { a = Flx_gcd(a, Flx_Xn1(g[1], q, p), p); if (degpol(a)) split_add(S, Flx_normalize(a, p)); } } } /* p > 2. f monic Flx, f(0) != 0. Add to split_t structs coprime factors * of g = \prod_{f(a) = 0} (X - a). Return 0 when f(x) = 0 for all x in Fp* */ static int split_Flx_cut_out_roots(struct split_t *S, GEN f, ulong p) { GEN a, g = Flx_mod_Xnm1(f, p-1, p); /* f mod x^(p-1) - 1 */ long d = degpol(g); if (d < 0) return 0; if (g != f) { (void)Flx_valrem(g, &g); d = degpol(g); } /*kill powers of x*/ if (!d) return 1; if (p <= 1.4 * (ulong)d) { /* small p; split further using x^((p-1)/2) +/- 1. * 30% degree drop makes the extra gcd worth it. */ split_squares(S, g, p); split_nonsquares(S, g, p); } else { /* large p; use x^(p-1) - 1 directly */ a = Flxq_powu(polx_Flx(f[1]), p-1, g,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 g */ g = Flx_gcd(g,a, p); if (degpol(g)) split_add(S, Flx_normalize(g,p)); } return 1; } /* by splitting, assume p > 2 prime, deg(f) > 0, and f monic */ static GEN Flx_roots_i(GEN f, ulong p) { GEN pol, g; ulong q = p >> 1; struct split_t S; split_init(&S, lg(f)-1); settyp(S.done, t_VECSMALL); if (Flx_valrem(f, &g)) 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]); for (pol[2]=1; ; pol[2]++) { long j, l = lg(S.todo); if (l == 1) { vecsmall_sort(S.done); return S.done; } if (pol[2] == 100 && !uisprime(p)) pari_err_PRIME("polrootsmod",utoipos(p)); for (j = 1; j < l; j++) { GEN c = gel(S.todo,j); switch(degpol(c)) { case 1: split_moveto_done(&S, j, (GEN)(p - c[2])); j--; l--; break; case 2: { ulong r = Flx_quad_root(c, p, 0), s = Flx_otherroot(c,r, p); split_done(&S, j, (GEN)r, (GEN)s); j--; l--; break; } default: { GEN b = Flx_Fl_add(Flxq_powu(pol,q, c,p), p-1, p); /* pol^(p-1)/2 */ long db; b = Flx_gcd(c,b, p); db = degpol(b); if (db && db < degpol(c)) { b = Flx_normalize(b, p); c = Flx_div(c,b, p); split_todo(&S, j, b, c); } } } } } } GEN Flx_roots(GEN f, ulong p) { pari_sp av = avma; switch(lg(f)) { case 2: pari_err_ROOTS0("Flx_roots"); case 3: avma = av; return cgetg(1, t_VECSMALL); } if (p == 2) return Flx_root_mod_2(f); return gerepileuptoleaf(av, Flx_roots_i(Flx_normalize(f, p), p)); } /* assume x reduced mod p, monic. */ static int Flx_quad_factortype(GEN x, ulong p) { ulong b = x[3], c = x[2]; return krouu(Fl_disc_bc(b, c, p), p); } static GEN Flx_is_irred_2(GEN f, ulong p, long d) { if (!d) return NULL; if (d == 1) return gen_1; return Flx_quad_factortype(f, p) == -1? gen_1: NULL; } static GEN Flx_degfact_2(GEN f, ulong p, long d) { if (!d) return trivial_fact(); if (d == 1) return mkvec2(mkvecsmall(1), mkvecsmall(1)); switch(Flx_quad_factortype(f, p)) { case 1: return mkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1:return mkvec2(mkvecsmall(2), mkvecsmall(1)); default: return mkvec2(mkvecsmall(1), mkvecsmall(2)); } } /* p > 2 */ static GEN Flx_factor_2(GEN f, ulong p, long d) { ulong r, s; GEN R,S; long v = f[1]; if (d < 0) pari_err(e_ROOTS0,"Flx_factor_2"); if (!d) return mkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); if (d == 1) return mkvec2(mkcol(f), mkvecsmall(1)); r = Flx_quad_root(f, p, 1); if (r==p) return mkvec2(mkcol(f), mkvecsmall(1)); s = Flx_otherroot(f, r, p); r = Fl_neg(r, p); s = Fl_neg(s, p); if (s < r) lswap(s,r); R = mkvecsmall3(v,r,1); if (s == r) return mkvec2(mkcol(R), mkvecsmall(2)); S = mkvecsmall3(v,s,1); return mkvec2(mkcol2(R,S), mkvecsmall2(1,1)); } static GEN Flx_factor_deg2(GEN f, ulong p, long d, long flag) { switch(flag) { case 2: return Flx_is_irred_2(f, p, d); case 1: return Flx_degfact_2(f, p, d); default: return Flx_factor_2(f, p, d); } } static GEN F2x_factcantor_i(GEN f, long flag) { long j, e, nbfact, d = F2x_degree(f); ulong k; GEN X, E, f2, g, g1, u, v, y, t; if (d <= 2) return F2x_factor_deg2(f, d, flag); /* to hold factors and exponents */ t = flag ? cgetg(d+1,t_VECSMALL): cgetg(d+1,t_VEC); E = cgetg(d+1, t_VECSMALL); X = polx_F2x(f[1]); e = nbfact = 1; for(;;) { f2 = F2x_gcd(f,F2x_deriv(f)); if (flag == 2 && F2x_degree(f2) > 0) return NULL; g1 = F2x_div(f,f2); k = 0; while (F2x_degree(g1)>0) { pari_sp av; long du, dg, dg1; k++; if (k%2==0) { k++; f2 = F2x_div(f2,g1); } u = g1; g1 = F2x_gcd(f2,g1); du = F2x_degree(u); dg1 = F2x_degree(g1); if (dg1>0) { f2= F2x_div(f2,g1); if (du == dg1) continue; u = F2x_div( u,g1); du -= dg1; } /* here u is square-free (product of irred. of multiplicity e * k) */ v = X; av = avma; for (d=1; d <= du>>1; d++) { v = F2xq_sqr(v, u); g = F2x_gcd(F2x_add(v, X), u); dg = F2x_degree(g); if (dg <= 0) {avma = (pari_sp)v; v = gerepileuptoleaf(av,v); continue;} /* g is a product of irred. pols, all of which have degree d */ j = nbfact+dg/d; if (flag) { if (flag == 2) return NULL; for ( ; nbfact 0) return NULL; g1 = Flx_div(f,f2,p); k = 0; while (degpol(g1)>0) { pari_sp av; long du,dg; k++; if (k%p==0) { k++; f2 = Flx_div(f2,g1,p); } u = g1; g1 = Flx_gcd(f2,g1, p); if (degpol(g1)>0) { u = Flx_div( u,g1,p); f2= Flx_div(f2,g1,p); } du = degpol(u); if (du <= 0) continue; /* here u is square-free (product of irred. of multiplicity e * k) */ v=X; av = avma; for (d=1; d <= du>>1; d++) { v = Flxq_powu(v, p, u, p); g = Flx_gcd(Flx_sub(v, X, p), u, p); dg = degpol(g); if (dg <= 0) {avma = (pari_sp)v; v = gerepileuptoleaf(av,v); continue;} /* g is a product of irred. pols, all of which have degree d */ j = nbfact+dg/d; if (flag) { if (flag == 2) return NULL; for ( ; nbfact0) { long du,dg; GEN u, S; k++; u = g1; g1 = FpX_gcd(f2,g1, pp); if (degpol(g1)>0) { u = FpX_div( u,g1,pp); f2= FpX_div(f2,g1,pp); } du = degpol(u); if (du <= 0) continue; /* 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); for (d=1; d <= du>>1; d++) { v = FpX_FpXQV_eval(v, S, u, pp); g = FpX_gcd(ZX_sub(v, X), u, pp); dg = degpol(g); if (dg <= 0) continue; /* g is a product of irred. pols, all of which have degree d */ j = nbfact+dg/d; if (flag) { if (flag == 2) return NULL; for ( ; nbfactir) swap(t[i],t[ir]); ir++;} /* assume x1 != 0 */ static GEN deg1_Flx(ulong x1, ulong x0, ulong sv) { return mkvecsmall3(sv, x0, x1); } long F2x_split_Berlekamp(GEN *t) { GEN u = *t, a, b, vker; long lb, d, i, ir, L, la, sv = u[1], du = F2x_degree(u); if (du == 1) return 1; if (du == 2) { if (F2x_quad_factortype(u) == 1) /* 0 is a root: shouldn't occur */ { t[0] = mkvecsmall2(sv, 2); t[1] = mkvecsmall2(sv, 3); return 2; } return 1; } vker = F2x_Berlekamp_ker(u); lb = lgcols(vker); d = lg(vker)-1; ir = 0; /* t[i] irreducible for i < ir, still to be treated for i < L */ for (L=1; L> 1; /* (p-1) / 2 */ ir = 0; /* t[i] irreducible for i < ir, still to be treated for i < L */ for (L=1; L 1) return NULL; if (flag == 1) t[1] = 1; else gel(t,1) = polx_F2x(f[1]); E[1] = val; nbfact++; } for(;;) { f2 = F2x_gcd(f,F2x_deriv(f)); if (flag == 2 && F2x_degree(f2)) return NULL; g1 = F2x_degree(f2)? F2x_div(f,f2): f; /* squarefree */ k = 0; while (F2x_degree(g1)>0) { GEN u; k++; if (k%2 == 0) { k++; f2 = F2x_div(f2,g1); } u = g1; /* deg(u) > 0 */ if (!F2x_degree(f2)) g1 = pol1_F2x(0); /* only its degree (= 0) matters */ else { long dg1; g1 = F2x_gcd(f2,g1); dg1 = F2x_degree(g1); if (dg1) { f2= F2x_div(f2,g1); if (F2x_degree(u) == dg1) continue; u = F2x_div( u,g1); } } /* u is square-free (product of irred. of multiplicity e * k) */ gel(t,nbfact) = u; d = F2x_split_Berlekamp(&gel(t,nbfact)); if (flag == 2 && d != 1) return NULL; if (flag == 1) for (j=0; j<(ulong)d; j++) t[nbfact+j] = F2x_degree(gel(t,nbfact+j)); for (j=0; j<(ulong)d; j++) E[nbfact+j] = e*k; nbfact += d; } j = F2x_degree(f2); if (!j) break; e *= 2; f = F2x_deflate(f2, 2); } if (flag == 2) return gen_1; /* irreducible */ setlg(t, nbfact); setlg(E, nbfact); y = mkvec2(t,E); return flag ? sort_factor(y, (void*)&cmpGuGu, cmp_nodata) : sort_factor_pol(y, cmpGuGu); } static GEN Flx_Berlekamp_i(GEN f, ulong p, long flag) { long e, nbfact, val, d = degpol(f); ulong k, j; GEN y, E, f2, g1, t; if (p == 2) { GEN F = F2x_Berlekamp_i(Flx_to_F2x(f),flag); if (flag==0) F2xV_to_FlxV_inplace(gel(F,1)); return F; } if (d <= 2) return Flx_factor_deg2(f,p,d,flag); /* to hold factors and exponents */ t = cgetg(d+1, flag? t_VECSMALL: t_VEC); E = cgetg(d+1,t_VECSMALL); val = Flx_valrem(f, &f); e = nbfact = 1; if (val) { if (flag == 2 && val > 1) return NULL; if (flag == 1) t[1] = 1; else gel(t,1) = polx_Flx(f[1]); E[1] = val; nbfact++; } for(;;) { f2 = Flx_gcd(f,Flx_deriv(f,p), p); if (flag == 2 && degpol(f2)) return NULL; g1 = degpol(f2)? Flx_div(f,f2,p): f; /* squarefree */ k = 0; while (degpol(g1)>0) { GEN u; k++; if (k%p == 0) { k++; f2 = Flx_div(f2,g1,p); } u = g1; /* deg(u) > 0 */ if (!degpol(f2)) g1 = pol1_Flx(0); /* only its degree (= 0) matters */ else { g1 = Flx_gcd(f2,g1, p); if (degpol(g1)) { f2= Flx_div(f2,g1,p); if (lg(u) == lg(g1)) continue; u = Flx_div( u,g1,p); } } /* u is square-free (product of irred. of multiplicity e * k) */ u = Flx_normalize(u,p); gel(t,nbfact) = u; d = Flx_split_Berlekamp(&gel(t,nbfact), p); if (flag == 2 && d != 1) return NULL; if (flag == 1) for (j=0; j<(ulong)d; j++) t[nbfact+j] = degpol(gel(t,nbfact+j)); for (j=0; j<(ulong)d; j++) E[nbfact+j] = e*k; nbfact += d; } if (!p) break; j = degpol(f2); if (!j) break; if (j % p) pari_err_PRIME("factmod",utoi(p)); e *= p; f = Flx_deflate(f2, p); } if (flag == 2) return gen_1; /* irreducible */ setlg(t, nbfact); setlg(E, nbfact); y = mkvec2(t,E); return flag ? sort_factor(y, (void*)&cmpGuGu, cmp_nodata) : sort_factor_pol(y, cmpGuGu); } /* f an FpX or an Flx */ static GEN FpX_Berlekamp_i(GEN f, GEN pp, long flag) { long e, nbfact, val, d = degpol(f); ulong k, j; GEN y, E, f2, g1, t; if (typ(f) == t_VECSMALL) {/* lgefint(pp) == 3 */ ulong p = pp[2]; GEN F; if (p == 2) { F = F2x_Berlekamp_i(Flx_to_F2x(f), flag); if (flag==0) F2xV_to_ZXV_inplace(gel(F,1)); } else { F = Flx_Berlekamp_i(f, p, flag); if (flag==0) FlxV_to_ZXV_inplace(gel(F,1)); } return F; } /* p is large (and odd) */ if (d <= 2) return FpX_factor_deg2(f,pp,d,flag); /* to hold factors and exponents */ t = cgetg(d+1, flag? t_VECSMALL: t_VEC); E = cgetg(d+1,t_VECSMALL); val = ZX_valrem(f, &f); e = nbfact = 1; if (val) { if (flag == 2 && val > 1) return NULL; if (flag == 1) t[1] = 1; else gel(t,1) = pol_x(varn(f)); E[1] = val; nbfact++; } f2 = FpX_gcd(f,ZX_deriv(f), pp); if (flag == 2 && degpol(f2)) return NULL; g1 = degpol(f2)? FpX_div(f,f2,pp): f; /* squarefree */ k = 0; while (degpol(g1)>0) { GEN u; k++; u = g1; /* deg(u) > 0 */ if (!degpol(f2)) g1 = pol_1(0); /* only its degree (= 0) matters */ else { g1 = FpX_gcd(f2,g1, pp); if (degpol(g1)) { f2= FpX_div(f2,g1,pp); if (lg(u) == lg(g1)) continue; u = FpX_div( u,g1,pp); } } /* u is square-free (product of irred. of multiplicity e * k) */ u = FpX_normalize(u,pp); gel(t,nbfact) = u; d = FpX_split_Berlekamp(&gel(t,nbfact), pp); if (flag == 2 && d != 1) return NULL; if (flag == 1) for (j=0; j<(ulong)d; j++) t[nbfact+j] = degpol(gel(t,nbfact+j)); for (j=0; j<(ulong)d; j++) E[nbfact+j] = e*k; nbfact += d; } if (flag == 2) return gen_1; /* irreducible */ setlg(t, nbfact); setlg(E, nbfact); y = mkvec2(t,E); return flag ? sort_factor(y, (void*)&cmpGuGu, cmp_nodata) : sort_factor_pol(y, cmpii); } GEN FpX_factor(GEN f, GEN p) { pari_sp av = avma; ZX_factmod_init(&f, p); return gerepilecopy(av, FpX_Berlekamp_i(f, p, 0)); } GEN Flx_factor(GEN f, ulong p) { pari_sp av = avma; GEN F = (degpol(f)>log2(p))? Flx_factcantor_i(f,p,0): Flx_Berlekamp_i(f,p,0); return gerepilecopy(av, F); } GEN F2x_factor(GEN f) { pari_sp av = avma; return gerepilecopy(av, F2x_Berlekamp_i(f, 0)); } GEN factormod0(GEN f, GEN p, long flag) { switch(flag) { case 0: return factmod(f,p); case 1: return simplefactmod(f,p); default: pari_err_FLAG("factormod"); } return NULL; /* not reached */ } /*******************************************************************/ /* */ /* FACTORIZATION IN F_q */ /* */ /*******************************************************************/ static GEN to_Fq(GEN x, GEN T, GEN p) { long i, lx, tx = typ(x); GEN y; if (tx == t_INT) y = mkintmod(x,p); else { if (tx != t_POL) pari_err_TYPE("to_Fq",x); lx = lg(x); y = cgetg(lx,t_POL); y[1] = x[1]; for (i=2; i>1), S, T, p); GEN V = FlxqXQV_autsum(mkvec3(xp, Xp, ap2), get_Flx_degree(T), S, T, p); return gel(V,3); } GEN FpXQXQ_halfFrobenius(GEN a, GEN S, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; long v = get_FpX_var(T); GEN Tp = ZXT_to_FlxT(T,pp), Sp = ZXX_to_FlxX(S, pp, v); return FlxX_to_ZXX(FlxqXQ_halfFrobenius(ZXX_to_FlxX(a,pp,v),Sp,Tp,pp)); } else { GEN xp = FpXQ_pow(pol_x(get_FpX_var(T)), p, 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); return gel(V,3); } } GEN 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 = 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); } GEN 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 = FpXQXQ_pow(X, p, S, T, p); GEN Xq = gel(FpXQXQV_autpow(mkvec2(xp,Xp), n, S, T, p), 2); return gerepilecopy(av, Xq); } static GEN FqX_Frobenius_powers(GEN S, GEN T, GEN p) { long N = degpol(S); if (lgefint(p)==3) { ulong pp = p[2]; GEN Tp = ZXT_to_FlxT(T, pp), Sp = ZXX_to_FlxX(S, pp, get_FpX_var(T)); GEN Xq = FlxqX_Frobenius(Sp, Tp, pp); return FlxqXQ_powers(Xq, N-1, Sp, Tp, pp); } else { GEN Xq = FpXQX_Frobenius(S, T, p); return FpXQXQ_powers(Xq, N-1, S, T, p); } } static GEN FqX_Frobenius_eval(GEN x, GEN V, GEN S, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; long v = get_FpX_var(T); GEN Tp = ZXT_to_FlxT(T, pp), Sp = ZXX_to_FlxX(S, pp, v); GEN xp = ZXX_to_FlxX(x, pp, v); return FlxX_to_ZXX(FlxqX_FlxqXQV_eval(xp, V, Sp, Tp, pp)); } else return FpXQX_FpXQXQV_eval(x, V, S, T, p); } static GEN FpXQX_split_part(GEN f, GEN T, GEN p) { long n = degpol(f); GEN z, X = pol_x(varn(f)); if (n <= 1) return f; f = FpXQX_red(f, T, p); z = FpXQX_Frobenius(f, T, p); z = FpXX_sub(z, X , p); return FpXQX_gcd(z, f, T, p); } static GEN FlxqX_split_part(GEN f, GEN T, ulong p) { long n = degpol(f); GEN z, Xq, X = polx_FlxX(varn(f),get_Flx_var(T)); if (n <= 1) return f; f = FlxqX_red(f, T, p); Xq = FlxqX_Frobenius(f, T, p); z = FlxX_sub(Xq, X , p); return FlxqX_gcd(z, f, T, p); } long FpXQX_nbroots(GEN f, GEN T, GEN p) { pari_sp av = avma; GEN z; if(lgefint(p)==3) { ulong pp=p[2]; z = FlxqX_split_part(ZXX_to_FlxX(f,pp,varn(T)),ZXT_to_FlxT(T,pp),pp); } else z = FpXQX_split_part(f, T, p); avma = av; return degpol(z); } long FqX_nbroots(GEN f, GEN T, GEN p) { return T ? FpXQX_nbroots(f, T, p): FpX_nbroots(f, p); } long FlxqX_nbroots(GEN f, GEN T, ulong p) { pari_sp av = avma; GEN z = FlxqX_split_part(f, T, p); avma = av; return degpol(z); } GEN FlxqX_Berlekamp_ker(GEN u, GEN T, ulong p) { pari_sp ltop=avma; long j,N = degpol(u); GEN Xq = FlxqX_Frobenius(u,T,p); GEN Q = FlxqXQ_matrix_pow(Xq,N,N,u,T,p); for (j=1; j<=N; j++) gcoeff(Q,j,j) = Flx_Fl_add(gcoeff(Q,j,j), p-1, p); return gerepileupto(ltop, FlxqM_ker(Q,T,p)); } GEN FpXQX_Berlekamp_ker(GEN u, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp=p[2]; long v = get_FpX_var(T); GEN Tp = ZXT_to_FlxT(T,pp), Sp = ZXX_to_FlxX(u,pp,v); return FlxM_to_ZXM(FlxqX_Berlekamp_ker(Sp, Tp, pp)); } else { pari_sp ltop=avma; long j,N = degpol(u); GEN Xq = FpXQX_Frobenius(u,T,p); GEN Q = FpXQXQ_matrix_pow(Xq,N,N,u,T,p); for (j=1; j<=N; j++) gcoeff(Q,j,j) = Fq_sub(gcoeff(Q,j,j), gen_1, T, p); return gerepileupto(ltop, FqM_ker(Q,T,p)); } } long FpXQX_nbfact(GEN u, GEN T, GEN p) { pari_sp av = avma; GEN vker = FpXQX_Berlekamp_ker(u, T, p); avma = av; return lg(vker)-1; } long FqX_nbfact(GEN u, GEN T, GEN p) { return T ? FpX_nbfact(u, p): FpXQX_nbfact(u, T, p); } long FqX_split_Berlekamp(GEN *t, GEN T, GEN p) { GEN u = *t, a,b,vker,pol; long vu = varn(u), vT = varn(T), dT = degpol(T); long d, i, ir, L, la, lb; T = FpX_get_red(T, p); vker = FpXQX_Berlekamp_ker(u,T,p); vker = RgM_to_RgXV(vker,vu); d = lg(vker)-1; ir = 0; /* t[i] irreducible for i < ir, still to be treated for i < L */ for (L=1; L 6) timer_start(&ti); av = avma; is2 = equaliu(p, 2); for(cnt = 1;;cnt++, avma = av) { /* splits *t with probability ~ 1 - 2^(1-r) */ w = w0 = FqX_rand(dt,v, T,p); if (degpol(w) <= 0) continue; for (l=1; l 6) err_printf("[FqX_split] splitting time: %ld (%ld trials)\n", timer_delay(&ti),cnt); l /= d; t[l] = FqX_div(*t,w, T,p); *t = w; FqX_split(t+l,d,q,S,T,p); FqX_split(t ,d,q,S,T,p); } /*******************************************************************/ /* */ /* FACTOR USING TRAGER'S TRICK */ /* */ /*******************************************************************/ static GEN FqX_frob_deflate(GEN f, GEN T, GEN p) { GEN F = RgX_deflate(f, itos(p)), frobinv = powiu(p, degpol(T)-1); long i, l = lg(F); for (i=2; i 0 */ static GEN FqX_split_Trager(GEN A, GEN T, GEN p) { GEN c, P, u, fa, n; long lx, i, k; u = A; n = NULL; for (k = 0; cmpui(k, p) < 0; k++) { GEN U; c = deg1pol_shallow(stoi(k) , gen_0, varn(T)); U = FqX_translate(u, c, T, p); n = FpX_FpXY_resultant(T, U, p); if (FpX_is_squarefree(n, p)) break; n = NULL; } if (!n) return NULL; if (DEBUGLEVEL>4) err_printf("FqX_split_Trager: choosing k = %ld\n",k); /* n guaranteed to be squarefree */ fa = FpX_factor(n, p); fa = gel(fa,1); lx = lg(fa); if (lx == 2) return mkcol(A); /* P^k, P irreducible */ P = cgetg(lx,t_COL); c = FpX_neg(c,p); for (i=lx-1; i>1; i--) { GEN F = FqX_translate(gel(fa,i), c, T, p); F = FqX_normalize(FqX_gcd(u, F, T, p), T, p); if (typ(F) != t_POL || degpol(F) == 0) pari_err_IRREDPOL("FqX_split_Trager [modulus]",T); u = FqX_div(u, F, T, p); gel(P,i) = F; } gel(P,1) = u; return P; } static long isabsolutepol(GEN f) { long i, l = lg(f); for(i=2; i 0) return 0; } return 1; } static void add(GEN z, GEN g, long d) { vectrunc_append(z, mkvec2(utoipos(d), g)); } /* return number of roots of u; assume deg u >= 0 */ long FqX_split_deg1(GEN *pz, GEN u, GEN T, GEN p) { long dg, N = degpol(u); GEN v, S, g, X, z = vectrunc_init(N+1); *pz = z; if (N == 0) return 0; if (N == 1) return 1; v = X = pol_x(varn(u)); S = FqX_Frobenius_powers(u, T, p); vectrunc_append(z, S); v = FqX_Frobenius_eval(v, S, u, T, p); g = FqX_gcd(FpXX_sub(v,X,p),u, T,p); dg = degpol(g); if (dg > 0) add(z, FqX_normalize(g,T,p), dg); return dg; } /* return number of factors; z not properly initialized if deg(u) <= 1 */ long FqX_split_by_degree(GEN *pz, GEN u, GEN T, GEN p) { long nb = 0, d, dg, N = degpol(u); GEN v, S, g, X, z = vectrunc_init(N+1); *pz = z; if (N <= 1) return 1; v = X = pol_x(varn(u)); S = FqX_Frobenius_powers(u, T, p); vectrunc_append(z, S); for (d=1; d <= N>>1; d++) { v = FqX_Frobenius_eval(v, S, u, T, p); g = FqX_gcd(FpXX_sub(v,X,p),u, T,p); dg = degpol(g); if (dg <= 0) continue; /* all factors of g have degree d */ add(z, FqX_normalize(g, T,p), dg / d); nb += dg / d; N -= dg; if (N) { u = FqX_div(u,g, T,p); v = FqX_rem(v,u, T,p); } } if (N) { add(z, FqX_normalize(u, T,p), 1); nb++; } return nb; } /* see roots_from_deg1() */ static GEN FqXC_roots_from_deg1(GEN x, GEN T, GEN p) { long i,l = lg(x); GEN r = cgetg(l,t_COL); for (i=1; i=0) { GEN z, d = F2xq_div(c, F2xq_sqr(b,T),T); if (F2xq_trace(d,T)) return cgetg(1, t_COL); z = F2xq_mul(b, F2xq_Artin_Schreier(d, T), T); return mkcol2(z, F2x_add(b, z)); } else return mkcol(F2xq_sqrt(c, 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); if (equaliu(p, 2)) { GEN f2 = ZXX_to_F2xX(x, get_FpX_var(T)); s = F2xqX_quad_roots(f2, ZX_to_F2x(get_FpX_mod(T))); 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)); 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); return mkcol2(s,Fq_sub(nb,s,T,p)); } static GEN FqX_roots_i(GEN f, GEN T, GEN p) { GEN R; f = FqX_normalize(f, T, p); if (!signe(f)) pari_err_ROOTS0("FqX_roots"); if (isabsolutepol(f)) { f = simplify_shallow(f); if (typ(f) == t_INT) return cgetg(1, t_COL); return FpX_rootsff_i(f, T, p); } if (degpol(f)==2) return gen_sort(FqX_quad_roots(f,T,p), (void*) &cmp_RgX, &cmp_nodata); switch( FqX_split_deg1(&R, f, T, p) ) { case 0: return cgetg(1, t_COL); case 1: if (lg(R) == 1) { R = mkvec(f); break; } /* fall through */ default: R = FqX_split_roots(R, T, p, NULL); } R = FqXC_roots_from_deg1(R, T, p); gen_sort_inplace(R, (void*) &cmp_RgX, &cmp_nodata, NULL); return R; } GEN FqX_roots(GEN x, GEN T, GEN p) { pari_sp av = avma; if (!T) return FpX_roots(x, p); return gerepileupto(av, FqX_roots_i(x, T, p)); } static long FqX_sqf_split(GEN *t0, GEN q, GEN T, GEN p) { GEN *t = t0, u = *t, v, S, g, X; long d, dg, N = degpol(u); if (N == 1) return 1; v = X = pol_x(varn(u)); S = FqX_Frobenius_powers(u, T, p); for (d=1; d <= N>>1; d++) { v = FqX_Frobenius_eval(v, S, u, T, p); g = FqX_normalize(FqX_gcd(FpXX_sub(v,X,p),u, T,p),T,p); dg = degpol(g); if (dg <= 0) continue; /* all factors of g have degree d */ *t = g; FqX_split(t, d, q, S, T, p); t += dg / d; N -= dg; if (N) { u = FqX_div(u,g, T,p); v = FqX_rem(v,u, T,p); } } if (N) *t++ = u; return t - t0; } /* not memory-clean */ static GEN FpX_factorff_i(GEN P, GEN T, GEN p) { GEN V, E, F = FpX_factor(P,p); long i, lfact = 1, nmax = lgpol(P), n = lgcols(F); V = cgetg(nmax,t_VEC); E = cgetg(nmax,t_VECSMALL); for(i=1;i 0 */ static GEN FqX_factor_i(GEN f, GEN T, GEN p) { long pg, j, k, e, N, lfact, pk, d = degpol(f); GEN E, f2, f3, df1, df2, g1, u, q, t; switch(d) { case -1: retmkmat2(mkcolcopy(f), mkvecsmall(1)); case 0: return trivial_fact(); } T = FpX_normalize(T, p); f = FqX_normalize(f, T, p); if (isabsolutepol(f)) return FpX_factorff_i(simplify_shallow(f), T, p); pg = itos_or_0(p); df2 = NULL; /* gcc -Wall */ t = cgetg(d+1,t_VEC); E = cgetg(d+1, t_VECSMALL); q = powiu(p, degpol(T)); e = lfact = 1; pk = 1; f3 = NULL; df1 = FqX_deriv(f, T, p); for(;;) { long nb0; while (!signe(df1)) { /* needs d >= p: pg = 0 can't happen */ pk *= pg; e = pk; f = FqX_frob_deflate(f, T, p); df1 = FqX_deriv(f, T, p); f3 = NULL; } f2 = f3? f3: FqX_gcd(f,df1, T,p); if (!degpol(f2)) u = f; else { g1 = FqX_div(f,f2, T,p); df2 = FqX_deriv(f2, T,p); if (gequal0(df2)) { u = g1; f3 = f2; } else { f3 = FqX_gcd(f2,df2, T,p); u = degpol(f3)? FqX_div(f2, f3, T,p): f2; u = FqX_div(g1, u, T,p); } } /* u is square-free (product of irreducibles of multiplicity e) */ N = degpol(u); if (N) { nb0 = lfact; gel(t,lfact) = FqX_normalize(u, T,p); if (N == 1) lfact++; else { if (!equaliu(p,2)) lfact += FqX_split_Berlekamp(&gel(t,lfact), T, p); else { GEN P = FqX_split_Trager(gel(t,lfact), T, p); if (P) { for (j = 1; j < lg(P); j++) gel(t,lfact++) = gel(P,j); } else { if (DEBUGLEVEL) pari_warn(warner, "FqX_split_Trager failed!"); lfact += FqX_sqf_split(&gel(t,lfact), q, T, p); } } } for (j = nb0; j < lfact; j++) E[j] = e; } if (!degpol(f2)) break; f = f2; df1 = df2; e += pk; } setlg(t, lfact); setlg(E, lfact); for (j=1; j>1); return gerepileupto(av, C); } static int zv_canon(GEN V) { long l = lg(V), j, k; for (j = 1; j < l && V[j] == 0; ++j); if (j < l && V[j] < 0) { for (k = j; k < l; ++k) V[k] = -V[k]; return -1; } return 1; } /********************************************************************/ /** **/ /** QFAUTO/QFISOM ported from B. Souvignier ISOM program **/ /** **/ /********************************************************************/ /* This is a port by Bill Allombert of the program ISOM by Bernt Souvignier which implement an algorithm published in W. PLESKEN, B. SOUVIGNIER, Computing Isometries of Lattices, Journal of Symbolic Computation, Volume 24, Issues 3-4, September 1997, Pages 327-334, ISSN 0747-7171, 10.1006/jsco.1996.0130. (http://www.sciencedirect.com/science/article/pii/S0747717196901303) We thanks Professor Souvignier for giving us permission to port his code. */ struct group { GEN ord; GEN ng; GEN nsg; GEN g; }; struct fingerprint { GEN diag; GEN per; GEN e; }; struct qfauto { long dim; GEN F, V, W, v; ulong p; }; struct qfcand { long cdep; GEN comb; GEN bacher_pol; }; static long possible(GEN F, GEN Ftr, GEN V, GEN W, GEN per, long I, long J) { long i, j, k, count; long n = lg(W)-1, f = lg(F)-1; count = 0; for (j = 1; j <= n; ++j) { GEN Wj = gel(W,j), Vj = gel(V,j); i = I+1; /* check the length of the vector */ for (k = 1; k <= f && i > I && Wj[k] == mael3(F,k,J,J); ++k) /* check the scalar products with the basis-vectors */ for (i = 1; i <= I; ++i) if (zv_dotproduct(Vj,gmael(Ftr,k,per[i])) != coeff(gel(F,k),J,per[i])) break; if (k == f+1 && i > I) ++count; /* the same for the negative vector */ i = I+1; for (k = 1; k <= f && i > I && Wj[k] == mael3(F,k,J,J); ++k) for (i = 1; i <= I ; ++i) if (zv_dotproduct(Vj,gmael(Ftr,k,per[i])) != -coeff(gel(F,k),J,per[i])) break; if (k == f+1 && i > I) ++count; } return count; } static void fingerprint(struct fingerprint *fp, struct qfauto *qf) { pari_sp av; GEN V=qf->V, W=qf->W, F=qf->F; GEN Mf; long i, j, k, min; long dim = qf->dim, n = lg(V)-1, f = lg(F)-1; GEN Ftr; fp->per = identity_perm(dim); fp->e = cgetg(dim+1, t_VECSMALL); fp->diag = cgetg(dim+1, t_VECSMALL); av = avma; Ftr = cgetg(f+1,t_VEC); for (i = 1; i <= f; ++i) gel(Ftr,i) = zm_transpose(gel(F,i)); Mf = zero_Flm_copy(dim, dim); /* the first row of the fingerprint has as entry nr. i the number of vectors, which have the same length as the i-th basis-vector with respect to every invariant form */ for (j = 1; j <= n; ++j) { GEN Wj = gel(W,j); for (i = 1; i <= dim; ++i) { for (k = 1; k <= f && Wj[k] == mael3(F,k,i,i); ++k); if (k == f+1) mael(Mf,1,i) += 2; } } for (i = 1; i <= dim-1; ++i) { /* a minimal entry != 0 in the i-th row is chosen */ min = i; for (j = i+1; j <= dim; ++j) { if (mael(Mf,i,fp->per[j]) < mael(Mf,i,fp->per[min])) min = j; } lswap(fp->per[i],fp->per[min]); /* the column below the minimal entry is set to 0 */ for (j = i+1; j <= dim; ++j) mael(Mf,j,fp->per[i]) = 0; /* compute the row i+1 of the fingerprint */ for (j = i+1; j <= dim; ++j) mael(Mf,i+1,fp->per[j]) = possible(F, Ftr, V, W, fp->per, i, fp->per[j]); } /* only the diagonal of f will be needed later */ for (i = 1; i <= dim; ++i) fp->diag[i] = mael(Mf,i,fp->per[i]); for (i = 1; i <= dim; ++i) { fp->e[i] = vecvecsmall_search(V,vecsmall_ei(dim,fp->per[i]),0); if (!fp->e[i]) pari_err_BUG("qfisom, standard basis vector not found"); } avma = av; } /* The Bacher-polynomial for v[I] with scalar product S is * defined as follows: let list be the vectors which have the same length as * v[I] and with scalar product S with v[I], for each vector w in list let n_w * be the number of pairs (y,z) of vectors in list, such that all scalar * products between w,y and z are S, then the Bacher-polynomial is the sum over * the w in list of the monomials X^n_w */ static GEN bacher(long I, long S, struct qfauto *qf) { pari_sp av=avma; GEN V=qf->V, W=qf->W, Fv=gel(qf->v,1); GEN list, listxy, counts, vI; long i, j, k, nlist, nxy; long n = lg(V)-1; long sum, mind, maxd; GEN coef; /* the Bacher-polynomials of v[I] and -v[I] are equal */ I = labs(I); vI = gel(V,I); /* list of vectors that have scalar product S with v[I] */ list = zero_Flv(2*n); nlist = 0; for (i = 1; i <= n; ++i) if (mael(W,i,1) == mael(W,I,1)) { long s = zv_dotproduct(vI, gel(Fv,i)); if (s == S) list[++nlist] = i; if (-s == S) list[++nlist] = -i; } /* there are nlist vectors that have scalar product S with v[I] */ sum = nlist; if (nlist==0) retmkvec2(mkvecsmall3(0,0,0),cgetg(1,t_VEC)); counts = cgetg(nlist+1, t_VECSMALL); listxy = cgetg(nlist+1, t_VECSMALL); for (i = 1; i <= nlist; ++i) { long S1; /* listxy is the list of the nxy vectors from list that have scalar product S with v[list[i]] */ for (j = 1; j <= nlist; ++j) listxy[j] = 0; nxy = 0; S1 = list[i] > 0 ? S : -S; for (j = 1; j <= nlist; ++j) { long S2 = list[j] > 0 ? S1 : -S1; /* note: for i > 0 is v[-i] = -v[i] */ if (zv_dotproduct(gel(V,labs(list[i])), gel(Fv,labs(list[j]))) == S2) listxy[++nxy] = list[j]; } /* counts[i] is the number of pairs for the vector v[list[i]] */ counts[i] = 0; for (j = 1; j <= nxy; ++j) { long S1 = listxy[j] > 0 ? S : -S; for (k = j+1; k <= nxy; ++k) { long S2 = listxy[k] > 0 ? S1 : -S1; long lj = labs(listxy[j]), lk = labs(listxy[k]); if (zv_dotproduct(gel(V,lj), gel(Fv,lk)) == S2) counts[i] += 1; } } } /* maxd is the maximal degree of the Bacher-polynomial, mind the minimal degree */ maxd = counts[1]; mind = counts[1]; for (i = 2; i <= nlist; ++i) { if (counts[i] > maxd) maxd = counts[i]; else if (counts[i] < mind) mind = counts[i]; } coef = zero_Flv(maxd - mind + 1); for (i = 1; i <= nlist; ++i) coef[1+counts[i] - mind] += 1; if (DEBUGLEVEL) err_printf("mind=%ld maxd=%ld sum=%ld\n",mind,maxd,sum); /* the Bacher-polynomial is now: sum from i=mind to maxd over coef[i - mind] * X^i */ return gerepilecopy(av, mkvec2(mkvecsmall3(sum, mind, maxd),coef)); } static GEN init_bacher(long bachdep, struct fingerprint *fp, struct qfauto *qf) { GEN z = cgetg(bachdep+1,t_VEC); long i; for (i=1;i<=bachdep;i++) { long bachscp = mael(qf->W,fp->e[i],1) / 2; gel(z,i) = bacher(fp->e[i], bachscp, qf); } return z; } /* 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) { pari_sp av = avma; GEN co, list, listxy, vI; long i, j, k; long nlist, nxy, count; long n = lg(V)-1; 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 */ nlist = 0; for (i = 1; i <= n && nlist <= sum; ++i) { if (mael(W,i,1) == mael(W,I,1)) { long s = zv_dotproduct(vI, gel(Fv,i)); if (s == S) { if (nlist < sum) list[nlist+1] = i; nlist++; } if (-s == S) { if (nlist < sum) list[nlist+1] = -i; nlist++; } } } if (nlist != sum) { /* the number of vectors with scalar product S is already different */ avma=av; return 0; } if (nlist == 0) { avma=av; return 1; } /* listxy is the list of the nxy vectors from list that have scalar product S with v[list[i]] */ listxy = cgetg(nlist+1,t_VECSMALL); co = zero_Flv(maxd - mind + 1); for (i = 1; i <= nlist; ++i) { long S1 = list[i] > 0 ? S : -S; for (j = 1; j <= nlist; ++j) listxy[j] = 0; nxy = 0; for (j = 1; j <= nlist; ++j) { long S2 = list[j] > 0 ? S1 : -S1; if (zv_dotproduct(gel(V,labs(list[i])), gel(Fv,labs(list[j]))) == S2) listxy[++nxy] = list[j]; } /* count is the number of pairs */ count = 0; for (j = 1; j <= nxy && count <= maxd; ++j) { long S1 = listxy[j] > 0 ? S : -S; for (k = j+1; k <= nxy && count <= maxd; ++k) { long S2 = listxy[k] > 0 ? S1 : -S1; long lj = labs(listxy[j]), lk = labs(listxy[k]); if (zv_dotproduct(gel(V,lj), gel(Fv,lk)) == S2) count++; } } if (count < mind || count > maxd || co[count-mind+1] >= coef[count-mind+1]) /* if the number of pairs is smaller than pol.mind or larger than pol.maxd or if the coefficient of X^count becomes now larger than the one in pol, then the Bacher-polynomials can not be equal */ { avma = av; return 0; } else co[count-mind+1]++; } /* the Bacher-polynomials are equal */ avma = av; return 1; } static GEN checkvecs(GEN V, GEN F, GEN norm) { long i, j, k; long n = lg(V)-1, f = lg(F)-1; GEN W = cgetg(n+1, t_MAT); j = 0; for (i = 1; i <= n; ++i) { GEN normvec = cgetg(f+1, t_VECSMALL); GEN Vi = gel(V,i); for (k = 1; k <= f; ++k) normvec[k] = scp(Vi, gel(F,k), Vi); if (!vecvecsmall_search(norm,normvec,0)) ++j; else { gel(V,i-j) = Vi; gel(W,i-j) = normvec; } } setlg(V, n+1-j); setlg(W, n+1-j); return W; } static long operate(long nr, GEN A, GEN V) { pari_sp av = avma; long im,eps; GEN w = zm_zc_mul(A,gel(V,labs(nr))); eps = zv_canon(w); if (nr < 0) eps = -eps; /* -w */ im = vecvecsmall_search(V,w,0); if (!im) pari_err_BUG("qfauto, image of vector not found"); avma = av; return eps*im; } static GEN orbit(GEN pt, long ipt, long npt, GEN H, GEN V) { long i, cnd, im; long n = lg(V)-1, nH = lg(H)-1, norb = npt+16, no = npt; GEN flag = zero_Flv(2*n+1)+n+1; /*We need negative indices*/ pari_sp av = avma; GEN orb = cgetg(norb+1,t_VECSMALL); for (i = 1; i <= npt; ++i) { orb[i] = pt[ipt+i]; flag[pt[ipt+i]] = 1; } for (cnd=1; cnd <= no; ++cnd) for (i = 1; i <= nH; ++i) { im = operate(orb[cnd], gel(H,i), V); if (flag[im] == 0) /* the image is a new point in the orbit */ { if (no==norb) { norb<<=1; orb = gerepileuptoleaf(av, vecsmall_lengthen(orb, norb)); } orb[++no] = im; flag[im] = 1; } } setlg(orb,no+1); return orb; } /* return the length of the orbit of pt under the first nG matrices in G */ static long orbitlen(long pt, long orblen, GEN G, long nG, GEN V) { pari_sp av = avma; long i, len, cnd; long n = lg(V)-1; GEN orb, flag; /* if flag[i + n+1] = 1, -n <= i <= n, then the point i is already in the orbit */ flag = zero_Flv(2*n + 1)+n+1; orb = zero_Flv(orblen); orb[1] = pt; flag[pt] = 1; len = 1; for(cnd = 1; cnd <= len && len < orblen; ++cnd) for (i = 1; i <= nG && len < orblen; ++i) { long im = operate(orb[cnd], gel(G,i), V); if (flag[im] == 0) /* the image is a new point in the orbit */ { orb[++len] = im; flag[im] = 1; } } avma = av; return len; } /* delete the elements in orb2 from orb1, an entry 0 marks the end of the * list, returns the length of orb1 */ static long orbdelete(GEN orb1, GEN orb2) { long i, j, len; long l1 = lg(orb1)-1; long l2 = lg(orb2)-1; for (i = 1; i <= l1 && orb1[i] != 0; ++i); len = i - 1; for (i = 1; i <= l2 && orb2[i] != 0; ++i) { long o2i = orb2[i]; for (j = 1; j <= len && orb1[j] != o2i; ++j); /* orb1[j] = orb2[i], hence delete orb1[j] from orb1 */ if (j <= len) { orb1[j] = orb1[len]; orb1[len--] = 0; } } return len; } static long orbsubtract(GEN Cs, GEN pt, long ipt, long npt, GEN H, GEN V, long *len) { pari_sp av = avma; long nC; GEN orb = orbit(pt, ipt, npt, H, V); if (len) *len = lg(orb)-1; nC = orbdelete(Cs, orb); avma = av; return nC; } /* Generates the matrix X which has as row per[i] the vector nr. x[i] from the * list V */ static GEN matgen(GEN x, GEN per, GEN V) { long i, j; long dim = lg(x)-1; GEN X = cgetg(dim+1,t_MAT); for (i = 1; i <= dim; ++i) { long xi = x[i]; GEN Xp = cgetg(dim+1,t_VECSMALL); for (j = 1; j <= dim; ++j) Xp[j] = xi > 0? mael(V,xi,j): -mael(V,-xi,j); gel(X,per[i]) = Xp; } return X; } /* x1 corresponds to an element X1 mapping some vector e on p1, x2 to an * element X2 mapping e on p2 and G is a generator mapping p1 on p2, then * S = X1*G*X2^-1 stabilizes e */ static GEN stabil(GEN x1, GEN x2, GEN per, GEN G, GEN V, ulong p) { pari_sp av = avma; long i; GEN x, XG, X2; long dim = lg(x1)-1; x = cgetg(dim+1,t_VECSMALL); for (i = 1; i <= dim; ++i) x[i] = operate(x1[i], G, V); /* XG is the composite mapping of the matrix corresponding to x1 and G */ XG = matgen(x, per, V); X2 = matgen(x2, per, V); return gerepileupto(av,zm_divmod(X2,XG,p)); } /* computes the orbit of fp.e[I] under the generators in G->g[I]...G->g[n-1] * and elements stabilizing fp.e[I], has some heuristic break conditions, the * generators in G->g[i] stabilize fp.e[0]...fp.e[i-1] but not fp.e[i], * G->ng[i] is the number of generators in G->g[i], the first G->nsg[i] of * which are elements which are obtained as stabilizer elements in * g[0],...,G->g[i-1]>, G->ord[i] is the orbit length of fp.e[i] under * g[i],...,G->g[n-1]> */ static void stab(long I, struct group *G, struct fingerprint *fp, GEN V, ulong p) { long len, cnd, tmplen; GEN orb, w, flag, H, Hj, S; long i, j, k, l, im, nH, nHj, fail; long Maxfail, Rest; long dim = lg(fp->diag)-1, n = lg(V)-1; /* Some heuristic break conditions for the computation of stabilizer elements: it would be too expensive to calculate all the stabilizer generators, which are obtained from the orbit, since this is highly redundant, on the other hand every new generator which enlarges the group is much cheaper than one obtained from the backtrack, after Maxfail subsequent stabilizer elements, that do not enlarge the group, Rest more elements are calculated even if they leave the group unchanged, since it turned out that this is often useful in the following steps, increasing the parameters will possibly decrease the number of generators for the group, but will increase the running time, there is no magic behind this heuristic, tuning might be appropriate */ for (Rest = 0, i = I; i <= dim; ++i) if (fp->diag[i] > 1 && G->ord[i] < fp->diag[i]) ++Rest; for (Maxfail = Rest, i = 1; i <= dim; ++i) if (fp->diag[i] > 1) ++Maxfail; for (nH = 0, i = I; i <= dim; ++i) nH += G->ng[i]; /* H are the generators of the group in which the stabilizer is computed */ H = cgetg(nH+1,t_MAT); Hj = cgetg(nH+2,t_MAT); k = 0; for (i = I; i <= dim; ++i) for (j = 1; j <= G->ng[i]; ++j) gel(H,++k) = gmael(G->g,i,j); /* in w[V.n+i] an element is stored that maps fp.e[I] on v[i] */ w = cgetg(2*n+2,t_VEC); /* orb contains the orbit of fp.e[I] */ orb = zero_Flv(2*n); /* if flag[i + V.n] = 1, then the point i is already in the orbit */ flag = zero_Flv(2*n+1); orb[1] = fp->e[I]; flag[orb[1]+n+1] = 1; gel(w,orb[1]+n+1) = cgetg(dim+1,t_VECSMALL); for (i = 1; i <= dim; ++i) mael(w,orb[1]+n+1,i) = fp->e[i]; cnd = 1; len = 1; /* fail is the number of successive failures */ fail = 0; while (cnd <= len && fail < Maxfail+Rest) { for (i = 1; i <= nH && fail < Maxfail+Rest; ++i) { if (fail >= Maxfail) /* there have already been Maxfail successive failures, now a random 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); } im = operate(orb[cnd], gel(H,i), V); if (flag[im+n+1] == 0) /* a new element is found, appended to the orbit and an element mapping fp.e[I] to im is stored in w[im+V.n] */ { GEN wim; orb[++len] = im; flag[im+n+1] = 1; wim = cgetg(dim+1,t_VECSMALL); gel(w,im+n+1) = wim; for (j = 1; j <= dim; ++j) wim[j] = operate(mael(w,orb[cnd]+n+1,j), gel(H,i), V); } else /* the image was already in the orbit */ { /* j is the first index where the images of the old and the new element mapping e[I] on im differ */ for (j = I; j <= dim; j++) if (operate(mael(w,orb[cnd]+n+1,j), gel(H,i), V) != mael(w,im+n+1,j)) break; if (j <= dim && (G->ord[j] < fp->diag[j] || fail >= Maxfail)) { GEN wo = gel(w,orb[cnd]+n+1); /* new stabilizer element S = w[orb[cnd]+V.n] * H[i] * (w[im+V.n])^-1 */ S = stabil(wo, gel(w,im+n+1), fp->per, gel(H,i), V, p); gel(Hj,1) = S; nHj = 1; for (k = j; k <= dim; ++k) for (l = 1; l <= G->ng[k]; ++l) gel(Hj,++nHj) = gmael(G->g,k,l); tmplen = orbitlen(fp->e[j], fp->diag[j], Hj, nHj, V); if (tmplen > G->ord[j] || fail >= Maxfail) /* the new stabilizer element S either enlarges the orbit of e[j] or it is one of the additional elements after MAXFAIL failures */ { GEN Ggj; G->ord[j] = tmplen; G->ng[j]++; G->nsg[j]++; /* allocate memory for the new generator */ gel(G->g,j) = vec_lengthen(gel(G->g,j),G->ng[j]); Ggj = gel(G->g,j); /* the new generator is inserted as stabilizer element nr. nsg[j]-1 */ for (k = G->ng[j]; k > G->nsg[j]; --k) gel(Ggj,k) = gel(Ggj,k-1); gel(Ggj,G->nsg[j]) = S; nH++; H = vec_lengthen(H, nH); Hj = vec_lengthen(Hj, nH+1); /* the new generator is appended to H */ gel(H,nH) = gel(Ggj,G->nsg[j]); /* the number of failures is reset to 0 */ if (fail < Maxfail) fail = 0; else ++fail; } else /*the new stabilizer element S does not enlarge the orbit of e[j]*/ ++fail; } else if ((j < dim && fail < Maxfail) || (j == dim && fail >= Maxfail)) ++fail; /* if S is the identity and fail < Maxfail, nothing is done */ } } if (fail < Maxfail) ++cnd; } } /* tests, whether x[1],...,x[I-1] is a partial automorphism, using scalar * product combinations and Bacher-polynomials depending on the chosen options, * puts the candidates for x[I] (i.e. the vectors vec such that the scalar * products of x[1],...,x[I-1],vec are correct) on CI, returns their number * (should be fp.diag[I]) */ static long qfisom_candidates_novec(GEN CI, long I, GEN x, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp) { pari_sp av = avma; long i, j, k, okp, okm, nr, fail; GEN vec; GEN F =qf->F, V=qff->V, W=qff->W, v=qff->v; long n = lg(V)-1, f = lg(F)-1; vec = cgetg(I,t_VECSMALL); /* CI is the list for the candidates */ for (i = 1; i <= fp->diag[I]; ++i) CI[i] = 0; nr = 0; fail = 0; for (j = 1; j <= n && fail == 0; ++j) { GEN Vj = gel(V,j), Wj = gel(W, j); okp = 0; okm = 0; for (i = 1; i <= f; ++i) { GEN FAiI = gmael(F,i,fp->per[I]); GEN FFvi = gel(v,i); /* vec is the vector of scalar products of V.v[j] with the first I base vectors x[0]...x[I-1] */ for (k = 1; k < I; ++k) { long xk = x[k]; if (xk > 0) vec[k] = zv_dotproduct(Vj, gel(FFvi,xk)); else vec[k] = -zv_dotproduct(Vj, gel(FFvi,-xk)); } for (k = 1; k < I && vec[k] == FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) /* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ ++okp; for (k = 1; k < I && vec[k] == -FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) /* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ ++okm; } if (okp == f) /* V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = j; else /* there are too many candidates */ fail = 1; } if (okm == f) /* -V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = -j; else /* there are too many candidates */ fail = 1; } } if (fail == 1) nr = 0; avma = av; return nr; } static long qfisom_candidates(GEN CI, long I, GEN x, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, struct qfcand *qfcand) { pari_sp av = avma; long i, j, k, okp, okm, nr, fail; GEN vec; GEN xvec, xbase, Fxbase, scpvec; long vj, rank, num; GEN com, list, trans, ccoef, cF; GEN F =qf->F, V=qff->V, W=qff->W, v=qff->v, FF= qff->F; long dim = qf->dim, n = lg(V)-1, f = lg(F)-1; long nc; 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; GEN bpolI = gel(qfcand->bacher_pol,I-1); if (bachcomp(bpolI, x[I-1], BACHSCP, V, W, gel(v,1)) == 0) return 0; } if (I==1 || DEP ==0) return qfisom_candidates_novec(CI,I,x,qf,qff,fp); vec = cgetg(I,t_VECSMALL); scpvec = cgetg(len+1,t_VECSMALL); com = gel(qfcand->comb,I-1); list=gel(com,1); trans = gel(com,2); ccoef = gel(com,3); cF=gel(com,4); rank = lg(trans)-1; nc = lg(list)-2; /* xvec is the list of vector sums which are computed with respect to the partial basis in x */ xvec = zero_Flm_copy(dim,nc+1); /* xbase should be a basis for the lattice generated by the vectors in xvec, it is obtained via the transformation matrix comb[I-1].trans */ xbase = cgetg(rank+1,t_MAT); for (i = 1; i <= rank; ++i) gel(xbase,i) = cgetg(dim+1,t_VECSMALL); /* Fxbase is the product of a form F with the base xbase */ Fxbase = cgetg(rank+1,t_MAT); for (i = 1; i <= rank; ++i) gel(Fxbase,i) = cgetg(dim+1,t_VECSMALL); /* CI is the list for the candidates */ for (i = 1; i <= fp->diag[I]; ++i) CI[i] = 0; nr = 0; fail = 0; for (j = 1; j <= n && fail == 0; ++j) { long sign; GEN Vj = gel(V,j), Wj = gel(W, j); okp = 0; okm = 0; for (k = 1; k <= len; ++k) scpvec[k] = 0; for (i = 1; i <= f; ++i) { GEN FAiI = gmael(F,i,fp->per[I]); GEN FFvi = gel(v,i); /* vec is the vector of scalar products of V.v[j] with the first I base vectors x[0]...x[I-1] */ for (k = 1; k < I; ++k) { long xk = x[k]; if (xk > 0) vec[k] = zv_dotproduct(Vj, gel(FFvi,xk)); else vec[k] = -zv_dotproduct(Vj, gel(FFvi,-xk)); } for (k = 1; k < I && vec[k] == FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) /* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ ++okp; for (k = 1; k < I && vec[k] == -FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) /* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ ++okm; for (k = I-1; k >= 1 && k > I-1-DEP; --k) scpvec[(i-1)*DEP+I-k] = vec[k]; } /* check, whether the scalar product combination scpvec is contained in the list comb[I-1].list */ if (!zv_equal0(scpvec)) { sign = zv_canon(scpvec); num = vecvecsmall_search(list,scpvec,0); if (!num) /* scpvec is not found, hence x[0]...x[I-1] is not a partial automorphism */ fail = 1; else /* scpvec is found and the vector is added to the corresponding vector sum */ { GEN xnum = gel(xvec,num); for (k = 1; k <= dim; ++k) xnum[k] += sign * Vj[k]; } } if (okp == f) /* V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = j; else /* there are too many candidates */ fail = 1; } if (okm == f) /* -V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = -j; else /* there are too many candidates */ fail = 1; } } if (fail == 1) nr = 0; if (nr == fp->diag[I]) { /* compute the basis of the lattice generated by the vectors in xvec via the transformation matrix comb[I-1].trans */ for (i = 1; i <= rank; ++i) { GEN comtri = gel(trans,i); for (j = 1; j <= dim; ++j) { long xbij = 0; for (k = 1; k <= nc+1; ++k) xbij += comtri[k] * mael(xvec,k,j); mael(xbase,i,j) = xbij; } } /* check, whether the base xbase has the right scalar products */ for (i = 1; i <= f && nr > 0; ++i) { for (j = 1; j <= rank; ++j) for (k = 1; k <= dim; ++k) mael(Fxbase,j,k) = zv_dotproduct(gmael(FF,i,k), gel(xbase,j)); for (j = 1; j <= rank && nr > 0; ++j) for (k = 1; k <= j && nr > 0; ++k) { if (zv_dotproduct(gel(xbase,j), gel(Fxbase,k)) != mael3(cF,i,j,k)) /* a scalar product is wrong */ nr = 0; } } for (i = 1; i <= nc+1 && nr > 0; ++i) { GEN comcoi = gel(ccoef,i); for (j = 1; j <= dim && nr > 0; ++j) { vj = 0; for (k = 1; k <= rank; ++k) vj += comcoi[k] * mael(xbase,k,j); if (vj != mael(xvec,i,j)) /* an entry is wrong */ nr = 0; } } } avma = av; return nr; } static long aut(long step, GEN x, GEN C, struct group *G, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { long dim = qf->dim; GEN orb = cgetg(2,t_VECSMALL); while (mael(C,step,1) != 0) { if (step < dim) { long nbc; /* choose the image of the base-vector nr. step */ gel(x,step) = gmael(C,step,1); /* check, whether x[0]...x[step] is a partial automorphism and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qf, fp, cand); if (nbc == fp->diag[step+1]) /* go deeper into the recursion */ if (aut(step+1, x, C, G, qf, fp, cand)) return 1; orb[1] = x[step]; /* delete the chosen vector from the list of candidates */ (void)orbdelete(gel(C,step), orb); } else { /* a new automorphism is found */ gel(x,dim) = gmael(C,dim,1); return 1; } } return 0; } /* search new automorphisms until on all levels representatives for all orbits * have been tested */ static void autom(struct group *G, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { long i, j, step, im, nC, nH, found, tries; GEN x, bad, H; long nbad; GEN V = qf->V; long dim = qf->dim, n = lg(V)-1; long STAB = 1; GEN C = cgetg(dim+1,t_VEC); /* C[i] is the list of candidates for the image of the i-th base-vector */ for (i = 1; i <= dim; ++i) gel(C,i) = cgetg(fp->diag[i]+1, t_VECSMALL); /* x is the new base i.e. x[i] is the index in V.v of the i-th base-vector */ x = cgetg(dim+1, t_VECSMALL); for (step = STAB; step <= dim; ++step) { if(DEBUGLEVEL) err_printf("QFAuto: Step %ld/%ld\n",step,dim); nH = 0; for (nH = 0, i = step; i <= dim; ++i) nH += G->ng[i]; H = cgetg(nH+1,t_VEC); for (nH = 0, i = step; i <= dim; ++i) for (j = 1; j <= G->ng[i]; ++j) gel(H,++nH) = gmael(G->g,i,j); bad = zero_Flv(2*n); nbad = 0; /* the first step base-vectors are fixed */ for (i = 1; i < step; ++i) x[i] = fp->e[i]; /* compute the candidates for x[step] */ if (fp->diag[step] > 1) /* if fp.diag[step] > 1 compute the candidates for x[step] */ nC = qfisom_candidates(gel(C,step), step, x, qf, qf, fp, cand); else /* if fp.diag[step] == 1, fp.e[step] is the only candidate */ { mael(C,step,1) = fp->e[step]; nC = 1; } /* delete the orbit of the step-th base-vector from the candidates */ nC = orbsubtract(gel(C,step), fp->e, step-1, 1, H, V, &(G->ord[step])); while (nC > 0 && (im = mael(C,step,1)) != 0) { found = 0; /* tries vector V.v[im] as image of the step-th base-vector */ x[step] = im; if (step < dim) { long nbc; /* check, whether x[0]...x[step] is a partial basis and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qf, fp, cand); if (nbc == fp->diag[step+1]) /* go into the recursion */ found = aut(step+1, x, C, G, qf, fp, cand); else found = 0; } else found = 1; if (found == 0) /* x[0]...x[step] can not be continued to an automorphism */ { /* delete the orbit of im from the candidates for x[step] */ nC = orbsubtract(gel(C,step),mkvecsmall(im), 0, 1, H, V, NULL); bad[++nbad] = im; } else /* a new generator has been found */ { GEN Gstep; ++G->ng[step]; /* append the new generator to G->g[step] */ Gstep = vec_lengthen(gel(G->g,step),G->ng[step]); gel(Gstep,G->ng[step]) = matgen(x, fp->per, V); gel(G->g,step) = Gstep; ++nH; H = cgetg(nH+1, t_VEC); for (nH = 0, i = step; i <= dim; ++i) for (j = 1; j <= G->ng[i]; ++j) gel(H,++nH) = gmael(G->g,i,j); nC = orbsubtract(gel(C,step), fp->e, step-1, 1, H, V, &(G->ord[step])); nC = orbsubtract(gel(C,step), bad, 0, nbad, H, V, NULL); } } /* test, whether on step STAB some generators may be omitted */ if (step == STAB) for (tries = G->nsg[step]; tries <= G->ng[step]; ++tries) { nH = 0; for (j = 1; j < tries; ++j) gel(H,++nH) = gmael(G->g,step,j); for (j = tries+1; j < G->ng[step]; ++j) gel(H,++nH) = gmael(G->g,step,j); for (i = step+1; i <= dim; ++i) for (j = 1; j <= G->ng[i]; ++j) gel(H,++nH) = gmael(G->g,i,j); if (orbitlen(fp->e[step], G->ord[step], H, nH, V) == G->ord[step]) /* the generator g[step][tries] can be omitted */ { G->ng[step]--; for (i = tries; i < G->ng[step]; ++i) gmael(G->g,step,i) = gmael(G->g,step,i+1); tries--; } } if (step < dim && G->ord[step] > 1) /* calculate stabilizer elements fixing the basis-vectors fp.e[0]...fp.e[step] */ stab(step, G, fp, V, qf->p); } } #define MAXENTRY (1L<<((BITS_IN_LONG-2)>>1)) #define MAXNORM (1L<<(BITS_IN_LONG-2)) static long zm_maxdiag(GEN A) { long dim = lg(A)-1; long max = coeff(A,1,1); long i; for (i = 2; i <= dim; ++i) if (coeff(A,i,i) > max) max = coeff(A,i,i); return max; } static GEN init_qfauto(GEN F, long max, struct qfauto *qf, GEN norm) { long i, j, k; GEN W, v; GEN M = minim(zm_to_ZM(gel(F,1)), stoi(max), NULL); GEN V = ZM_to_zm(gel(M, 3)); long n = lg(V)-1, f = lg(F)-1, dim = lg(gel(F,1))-1; for (i = 1; i <= n; ++i) { GEN Vi = gel(V,i); if (typ(Vi)!=t_VECSMALL) pari_err_TYPE("init_qfauto",Vi); zv_canon(Vi); for (k = 1; k <= dim; ++k) { long l = labs(Vi[k]); if (l > max) max = l; } } if (max > MAXENTRY) pari_err_OVERFLOW("qfisom [lattice too large]"); qf->p = unextprime(2*max+1); V = vecvecsmall_sort_uniq(V); if (!norm) { norm = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; ++i) { GEN Ni = cgetg(f+1,t_VECSMALL); for (k = 1; k <= f; ++k) Ni[k] = mael3(F,k,i,i); gel(norm,i) = Ni; } norm = vecvecsmall_sort_uniq(norm); } W = checkvecs(V, F, norm); v = cgetg(f+1,t_VEC); /* the product of the maximal entry in the short vectors with the maximal entry in v[i] should not exceed MAXNORM to avoid overflow */ max = MAXNORM / max; for (i = 1; i <= f; ++i) { GEN Fi = gel(F,i), vi; vi = cgetg(n+1,t_MAT); gel(v,i) = vi; for (j = 1; j <= n; ++j) { GEN Vj = gel(V,j); GEN vij = cgetg(dim+1, t_VECSMALL); gel(vi,j) = vij; for (k = 1; k <= dim; ++k) { vij[k] = zv_dotproduct(gel(Fi,k), Vj); if (labs(vij[k]) > max) pari_err_OVERFLOW("qfisom [lattice too large]"); } } } qf->dim = dim; qf->F = F; qf->V = V; qf->W = W; qf->v = v; return norm; } static void init_qfgroup(struct group *G, struct fingerprint *fp, struct qfauto *qf) { GEN H, M, V = qf->V; long nH; long i, j, k; long dim = qf->dim; G->ng = zero_Flv(dim+1); G->nsg = zero_Flv(dim+1); G->ord = cgetg(dim+1,t_VECSMALL); G->g = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; ++i) gel(G->g,i) = mkvec(gen_0); M = matid_Flm(dim); gmael(G->g,1,1) = M; G->ng[1] = 1; /* -Id is always an automorphism */ for (i = 1; i <= dim; ++i) mael(M,i,i) = -1; nH = 0; for (i = 1; i <= dim; ++i) nH += G->ng[i]; H = cgetg(nH+1,t_MAT); /* calculate the orbit lengths under the automorphisms known so far */ for (i = 1; i <= dim; ++i) { if (G->ng[i] > 0) { nH = 0; for (j = i; j <= dim; ++j) for (k = 1; k <= G->ng[j]; ++k) gel(H,++nH) = gmael(G->g,j,k); G->ord[i] = orbitlen(fp->e[i], fp->diag[i], H, nH, V); } else G->ord[i] = 1; } } /* calculates the scalar products of the vector w with the base vectors * v[b[I]] down to v[b[I-dep+1]] with respect to all invariant forms and puts * them on scpvec */ static GEN scpvector(GEN w, GEN b, long I, long dep, GEN v) { long i, j, n = lg(v)-1; GEN scpvec = zero_Flv(dep*n); for (i = I; i >= 1 && i > I-dep; --i) { long bi = b[i]; if (bi > 0) for (j = 1; j <= n; ++j) scpvec[1+(j-1)*dep + I-i] = zv_dotproduct(w, gmael(v,j,bi)); else for (j = 1; j <= n; ++j) scpvec[1+(j-1)*dep + I-i] = -zv_dotproduct(w, gmael(v,j,-bi)); } return scpvec; } /* computes the list of scalar product combinations of the vectors * in V.v with the basis-vectors in b */ static GEN scpvecs(GEN *pt_vec, long I, GEN b, long dep, struct qfauto *qf) { long i, j, nr, sign; GEN list, vec; GEN vecnr; GEN V = qf->V, F = qf->F, v = qf->v; long n = lg(V)-1; long dim = lg(gel(F,1))-1; long len = (lg(F)-1)*dep; /* the first vector in the list is the 0-vector and is not counted */ list = mkmat(zero_Flv(len)); vec = mkmat(zero_Flv(dim)); for (j = 1; j <= n; ++j) { GEN Vvj = gel(V,j); GEN scpvec = scpvector(Vvj, b, I, dep, v); if (zv_equal0(scpvec)) nr = -1; else { sign = zv_canon(scpvec); nr = vecvecsmall_search(list,scpvec,0); } /* scpvec is already in list */ if (nr > 0) { vecnr = gel(vec,nr); for (i = 1; i <= dim; ++i) vecnr[i] += sign * Vvj[i]; } /* scpvec is a new scalar product combination */ else if (nr==0) { nr = vecvecsmall_search(list,scpvec,1); list=vec_insert(list,nr,scpvec); vec=vec_insert(vec,nr,sign < 0 ? zv_neg(Vvj) : zv_copy(Vvj)); } } settyp(list,t_MAT); *pt_vec = vec; return list; } /* com->F[i] is the Gram-matrix of the basis b with respect to F.A[i] */ static GEN scpforms(GEN b, struct qfauto *qf) { long i, j, k; GEN F = qf->F; long n = lg(F)-1, dim = lg(gel(F,1))-1; long nb = lg(b)-1; GEN gram = cgetg(n+1, t_VEC); /* Fbi is the list of products of F.A[i] with the vectors in b */ GEN Fbi = cgetg(nb+1, t_MAT); for (j = 1; j <= nb; ++j) gel(Fbi, j) = cgetg(dim+1, t_VECSMALL); for (i = 1; i <= n; ++i) { GEN FAi = gel(F,i); gel(gram, i) = cgetg(nb+1, t_MAT); for (j = 1; j <= nb; ++j) for (k = 1; k <= dim; ++k) mael(Fbi,j,k) = zv_dotproduct(gel(FAi,k), gel(b,j)); for (j = 1; j <= nb; ++j) { GEN comFij = cgetg(nb+1, t_VECSMALL); for (k = 1; k <= nb; ++k) comFij[k] = zv_dotproduct(gel(b,j), gel(Fbi,k)); gmael(gram,i,j) = comFij; } } return gram; } static GEN gen_comb(long cdep, GEN A, GEN e, struct qfauto *qf, long lim) { long i, dim = lg(A)-1; GEN comb = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; ++i) { pari_sp av = avma; GEN trans, ccoef, cF, B, BI; GEN sumveclist, sumvecbase; GEN list = scpvecs(&sumveclist, i, e, cdep, qf); GEN M = zm_to_ZM(sumveclist); GEN T = lllgramint(qf_apply_ZM(A,M)); if (lim && lg(T)-1>=lim) return NULL; B = ZM_mul(M,T); BI = RgM_solve(B,NULL); sumvecbase = ZM_trunc_to_zm(B); trans = ZM_trunc_to_zm(T); ccoef = ZM_trunc_to_zm(RgM_mul(BI,M)); cF = scpforms(sumvecbase, qf); gel(comb,i) = gerepilecopy(av, mkvec4(list, trans, ccoef, cF)); } return comb; } static void init_comb(struct qfcand *cand, GEN A, GEN e, struct qfauto *qf) { long dim = lg(A)-1; GEN Am = zm_to_ZM(A); for (cand->cdep = 1; ; cand->cdep++) { cand->comb = gen_comb(cand->cdep, Am, e, qf, (dim+1)>>1); if (!cand->comb) break; } cand->cdep= maxss(1, cand->cdep-1); cand->comb = gen_comb(cand->cdep, Am, e, qf, 0); } static void init_flags(struct qfcand *cand, GEN A, struct fingerprint *fp, struct qfauto *qf, GEN flags) { if (!flags) { init_comb(cand, A, fp->e, qf); cand->bacher_pol = init_bacher(0, fp, qf); } else { long cdep, bach; if (typ(flags)!=t_VEC || lg(flags)!=3) pari_err_TYPE("qfisominit",flags); cdep = gtos(gel(flags,1)); bach = minss(gtos(gel(flags,2)),lg(fp->e)-1); if (cdep<0 || bach<0) pari_err_FLAG("qfisom"); cand->cdep = cdep; cand->comb = cdep ? gen_comb(cdep, zm_to_ZM(A), fp->e, qf, 0): NULL; cand->bacher_pol = init_bacher(bach, fp, qf); } } static GEN gen_group(struct group *G) { GEN V; long i, j, n=1, dim = lg(G->ord)-1; GEN o = gen_1; for (i = 1; i <= dim; ++i) o = muliu(o, G->ord[i]); for (i = 1; i <= dim; ++i) n += G->ng[i]-G->nsg[i]; V = cgetg(n, t_VEC); n = 1; for (i = 1; i <= dim; ++i) for (j=G->nsg[i]+1; j<=G->ng[i]; j++) gel(V,n++) = gmael(G->g,i,j); return mkvec2(o, V); } static long is_qfisom(GEN F) { return (lg(F)==6 && typ(F)==t_VEC && typ(gel(F,1))==t_VEC && typ(gel(F,3))==t_VEC && typ(gel(F,4))==t_VEC); } static GEN unpack_qfisominit(GEN F, GEN *norm, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { GEN QF = gel(F,3); qf->F = gel(QF,1); qf->V = gel(QF,2); qf->W = gel(QF,3); qf->v = gel(QF,4); qf->p = itou(gel(QF,5)); QF = gel(F,4); fp->diag = gel(QF,1); fp->per = gel(QF,2); fp->e = gel(QF,3); QF = gel(F,5); cand->cdep =itos(gel(QF,1)); cand->comb = gel(QF,2); cand->bacher_pol = gel(QF,3); *norm = gel(F,2); qf->dim = lg(gmael(F,1,1))-1; return gel(F,1); } static GEN init_qfisom(GEN F, struct fingerprint *fp, struct qfcand *cand, struct qfauto *qf, GEN flags, long *max) { GEN A, norm; if (is_qfisom(F)) { F = unpack_qfisominit(F, &norm, qf, fp, cand); A = gel(F,1); *max = zm_maxdiag(A); if (flags) init_flags(cand, A, fp, qf, flags); } else { if (lg(F)<2) pari_err_TYPE("qfisom",F); A = gel(F,1); if (lg(A)<2) pari_err_TYPE("qfisom",A); *max = zm_maxdiag(A); if (DEBUGLEVEL) err_printf("max=%ld\n",*max); norm=init_qfauto(F, *max, qf, NULL); fingerprint(fp, qf); if (DEBUGLEVEL) err_printf("fp=%Ps\n",fp->diag); init_flags(cand, A, fp, qf, flags); } return norm; } GEN qfauto(GEN F, GEN flags) { pari_sp av = avma; struct fingerprint fp; struct group G; struct qfcand cand; struct qfauto qf; long max; (void)init_qfisom(F, &fp, &cand, &qf, flags, &max); init_qfgroup(&G, &fp, &qf); autom(&G, &qf, &fp, &cand); return gerepilecopy(av, gen_group(&G)); } static GEN qf_to_zmV(GEN F) { return typ(F)==t_MAT ? (RgM_is_ZM(F) ? mkvec(ZM_to_zm(F)): NULL) : typ(F)==t_VEC ? (RgV_is_ZMV(F) ? ZMV_to_zmV(F): NULL) : NULL; } GEN qfauto0(GEN x, GEN flags) { pari_sp av = avma; GEN F, G; if (is_qfisom(x)) F = x; else { F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfauto",x); } G = qfauto(F, flags); return gerepilecopy(av, mkvec2(gel(G,1), zmV_to_ZMV(gel(G,2)))); } /* computes the orbit of V.v[pt] under the generators G[0],...,G[nG-1] and * elements stabilizing V.v[pt], which are stored in H, returns the number of * generators in H */ static GEN isostab(long pt, GEN G, GEN V, long Maxfail, ulong p) { pari_sp av = avma; long len, cnd, orblen, tmplen, rpt; GEN w, flag, orb; long i, im, nH, fail; long dim = lg(gel(V,1))-1, n = lg(V)-1, nG = lg(G)-1; GEN H; /* a heuristic break condition for the computation of stabilizer elements: it would be too expensive to calculate all the stabilizer generators, which are obtained from the orbit, since this is highly redundant, on the other hand every new generator which enlarges the group reduces the number of orbits and hence the number of candidates to be tested, after Maxfail subsequent stabilizer elements, that do not enlarge the group, the procedure stops, increasing Maxfail will possibly decrease the number of tests, but will increase the running time of the stabilizer computation there is no magic behind the heuristic, tuning might be appropriate */ /* H are the generators of the stabilizer of V.v[pt] */ H = cgetg(2,t_VEC); nH = 0; /* w[i+V.n] is a matrix that maps V.v[pt] on V.v[i] */ w = cgetg(2*n+2,t_MAT); orb = zero_Flv(2*n); /* orblen is the length of the orbit of a random vector in V.v */ orblen = 1; /* if flag[i+V.n] = 1, then the point i is already in the orbit */ flag = zero_Flv(2*n+1); orb[1] = pt; flag[orb[1]+n+1] = 1; /* w[pt+V.n] is the Identity */ gel(w,orb[1]+n+1) = matid_Flm(dim); cnd = 1; len = 1; /* fail is the number of successive failures */ fail = 0; while (cnd <= len && fail < Maxfail) { for (i = 1; i <= nG && fail < Maxfail; ++i) { im = operate(orb[cnd], gel(G,i), V); if (flag[im+n+1] == 0) /* a new element is found, appended to the orbit and an element mapping V.v[pt] to im is stored in w[im+V.n] */ { orb[++len] = im; flag[im+n+1] = 1; gel(w,im+n+1)= zm_mul(gel(G,i), gel(w,orb[cnd]+n+1)); } else /* the image was already in the orbit */ { GEN B = zm_mul(gel(G,i), gel(w,orb[cnd]+n+1)); /* check whether the old and the new element mapping pt on im differ */ 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); 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); tmplen = orbitlen(rpt, 2*n, H, nH+1, V); } if (tmplen > orblen) /* the new stabilizer element H[nH] enlarges the group generated by H */ { orblen = tmplen; /* allocate memory for the new generator */ H = vec_lengthen(H, (++nH)+1); fail = 0; } else /* the new stabilizer element does not enlarge the orbit of a random vector */ ++fail; } /* if H[nH] is the identity, nothing is done */ } } ++cnd; } setlg(H,nH+1); return gerepilecopy(av, H); } /* the heart of the program: the recursion */ static long iso(long step, GEN x, GEN C, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, GEN G, struct qfcand *cand) { int i, Maxfail; GEN H; long dim = qf->dim; long found = 0; while (mael(C,step,1) != 0 && found == 0) { if (step < dim) { long nbc; /* choose the image of the base-vector nr. step */ x[step] = mael(C,step,1); /* check whether x[0]...x[step] is a partial automorphism and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qff, fp, cand); if (nbc == fp->diag[step+1]) { /* go deeper into the recursion */ Maxfail = 0; /* determine the heuristic value of Maxfail for the break condition in isostab */ for (i = 1; i <= step; ++i) if (fp->diag[i] > 1) Maxfail += 1; for (i = step+1; i <= dim; ++i) if (fp->diag[i] > 1) Maxfail += 2; /* compute the stabilizer H of x[step] in G */ H = isostab(x[step], G, qff->V, Maxfail,qff->p); found = iso(step+1, x, C, qf, qff, fp, H, cand); } if (found == 1) return 1; /* delete the orbit of the chosen vector from the list of candidates */ orbsubtract(gel(C,step), x, step-1, 1, G, qff->V, NULL); } else { /* an isomorphism is found */ x[dim] = mael(C,dim,1); found = 1; } } return found; } /* search for an isometry */ static GEN isometry(struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, GEN G, struct qfcand *cand) { long i, found; GEN x; long dim = qf->dim; GEN C = cgetg(dim+1,t_VEC); /* C[i] is the list of candidates for the image of the i-th base-vector */ for (i = 1; i <= dim; ++i) gel(C,i) = cgetg(fp->diag[i]+1, t_VECSMALL); x = cgetg(dim+1, t_VECSMALL); /* compute the candidates for x[1] */ qfisom_candidates(gel(C,1), 1, x, qf, qff, fp, cand); found = iso(1, x, C, qf, qff, fp, G, cand); return found ? matgen(x, fp->per, qff->V): NULL; } GEN qfisominit(GEN F, GEN flags) { pari_sp av = avma; struct fingerprint fp; struct qfauto qf; struct qfcand cand; long max; GEN norm = init_qfisom(F, &fp, &cand, &qf, flags, &max); return gerepilecopy(av, mkvec5(F, norm, mkvec5(qf.F, qf.V, qf.W, qf.v, utoi(qf.p)), mkvec3(fp.diag, fp.per, fp.e), mkvec3(stoi(cand.cdep),cand.comb?cand.comb:cgetg(1,t_VEC), cand.bacher_pol))); } GEN qfisominit0(GEN x, GEN flags) { pari_sp av = avma; GEN F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfisom",x); return gerepileupto(av, qfisominit(F, flags)); } GEN qfisom(GEN F, GEN FF, GEN flags) { pari_sp av = avma; struct fingerprint fp; GEN G, res; struct qfauto qf, qff; struct qfcand cand; long max; GEN norm = init_qfisom(F, &fp, &cand, &qf, flags, &max); init_qfauto(FF, max, &qff, norm); if (lg(qf.W)!=lg(qff.W) || !zvV_equal(vecvecsmall_sort(qf.W), vecvecsmall_sort(qff.W))) { avma=av; return gen_0; } G = mkvec(scalar_Flm(-1, qff.dim)); res = isometry(&qf, &qff, &fp, G, &cand); if (!res) { avma=av; return gen_0; } return gerepilecopy(av, zm_to_ZM(res)); } GEN qfisom0(GEN x, GEN y, GEN flags) { pari_sp av = avma; GEN F, FF; if (is_qfisom(x)) F = x; else { F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfisom",x); } FF = qf_to_zmV(y); if (!FF) pari_err_TYPE("qfisom",y); return gerepileupto(av, qfisom(F, FF, flags)); } static GEN ZM_to_GAP(GEN M) { pari_sp ltop=avma; long rows = nbrows(M), cols = lg(M)-1; long i, j, c; GEN comma = strtoGENstr(", "); GEN bra = strtoGENstr("["); GEN ket = strtoGENstr("]"); GEN s = cgetg(2*rows*cols+2*rows+2,t_VEC); gel(s,1) = bra; c=2; for (i = 1; i <= rows; ++i) { if (i > 1) gel(s,c++) = comma; gel(s,c++) = bra; for (j = 1; j <= cols; ++j) { if (j > 1) gel(s,c++) = comma; gel(s,c++) = GENtoGENstr(gcoeff(M,i,j)); } gel(s,c++) = ket; } gel(s,c++) = ket; return gerepilecopy(ltop,shallowconcat1(s)); } GEN qfautoexport(GEN G, long flag) { pari_sp av = avma; long i, lgen, c = 2; GEN gen, str, comma = strtoGENstr(", "); if (typ(G)!=t_VEC || lg(G)!=3) pari_err_TYPE("qfautoexport", G); if (flag!=0 && flag!=1) pari_err_FLAG("qfautoexport"); gen = gel(G,2); lgen = lg(gen)-1; str = cgetg(2+2*lgen,t_VEC); /* in GAP or MAGMA the matrix group is called BG */ if (flag == 0) gel(str,1) = strtoGENstr("Group("); else { long dim = lg(gmael(gen,1,1))-1; gel(str,1) = gsprintf("MatrixGroup<%d, Integers() |",dim); } for(i = 1; i <= lgen; i++) { if (i!=1) gel(str,c++) = comma; gel(str,c++) = ZM_to_GAP(gel(gen,i)); } gel(str,c++) = strtoGENstr(flag ? ">":")"); return gerepilecopy(av, shallowconcat1(str)); } pari-2.7.5/src/basemath/alglin2.c0000644000175000017500000012103012413013142015141 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** LINEAR ALGEBRA **/ /** (second part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* CHARACTERISTIC POLYNOMIAL */ /* */ /*******************************************************************/ GEN charpoly0(GEN x, long v, long flag) { if (v<0) v = 0; switch(flag) { case 0: return caradj(x,v,NULL); case 1: return caract(x,v); case 2: return carhess(x,v); case 3: return carberkowitz(x,v); case 4: if (typ(x) != t_MAT) pari_err_TYPE("charpoly",x); RgM_check_ZM(x, "charpoly"); x = ZM_charpoly(x); setvarn(x, v); return x; case 5: return charpoly(x, v); } pari_err_FLAG("charpoly"); return NULL; /* not reached */ } /* characteristic pol. Easy cases. Return NULL in case it's not so easy. */ static GEN easychar(GEN x, long v) { pari_sp av; long lx; GEN p1; switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_PADIC: p1=cgetg(4,t_POL); p1[1]=evalsigne(1) | evalvarn(v); gel(p1,2) = gneg(x); gel(p1,3) = gen_1; return p1; case t_COMPLEX: case t_QUAD: p1 = cgetg(5,t_POL); p1[1] = evalsigne(1) | evalvarn(v); gel(p1,2) = gnorm(x); av = avma; gel(p1,3) = gerepileupto(av, gneg(gtrace(x))); gel(p1,4) = gen_1; return p1; case t_FFELT: { pari_sp ltop=avma; p1 = FpX_to_mod(FF_charpoly(x), FF_p_i(x)); setvarn(p1,v); return gerepileupto(ltop,p1); } case t_POLMOD: return RgXQ_charpoly(gel(x,2), gel(x,1), v); case t_MAT: lx=lg(x); if (lx==1) return pol_1(v); if (lgcols(x) != lx) break; return NULL; } pari_err_TYPE("easychar",x); return NULL; /* not reached */ } /* compute charpoly by mapping to Fp first, return lift to Z */ static GEN RgM_Fp_charpoly(GEN x, GEN p, long v) { GEN T; if (lgefint(p) == 3) { ulong pp = itou(p); T = Flm_charpoly(RgM_to_Flm(x, pp), pp); T = Flx_to_ZX(T); } else T = FpM_charpoly(RgM_to_FpM(x, p), p); setvarn(T, v); return T; } GEN charpoly(GEN x, long v) { GEN T, p = NULL; if ((T = easychar(x,v))) return T; if (RgM_is_ZM(x)) { T = ZM_charpoly(x); setvarn(T, v); } else if (RgM_is_FpM(x, &p) && BPSW_psp(p)) { pari_sp av = avma; T = RgM_Fp_charpoly(x,p,v); T = gerepileupto(av, FpX_to_mod(T,p)); } else if (isinexact(x)) T = carhess(x, v); else T = carberkowitz(x, v); return T; } /* We possibly worked with an "invalid" polynomial p, satisfying * varn(p) > gvar2(p). Fix this. */ static GEN fix_pol(pari_sp av, GEN p) { long w = gvar2(p), v = varn(p); if (w == v) pari_err_PRIORITY("charpoly", p, "=", w); if (varncmp(w,v) < 0) p = gerepileupto(av, poleval(p, pol_x(v))); return p; } GEN caract(GEN x, long v) { pari_sp av = avma; GEN T, C, x_k, Q; long k, n; if ((T = easychar(x,v))) return T; n = lg(x)-1; if (n == 1) return fix_pol(av, deg1pol(gen_1, gneg(gcoeff(x,1,1)), v)); x_k = pol_x(v); /* to be modified in place */ T = scalarpol(det(x), v); C = utoineg(n); Q = pol_x(v); for (k=1; k<=n; k++) { GEN mk = utoineg(k), d; gel(x_k,2) = mk; d = det(RgM_Rg_add_shallow(x, mk)); T = RgX_add(RgX_mul(T, x_k), RgX_Rg_mul(Q, gmul(C, d))); if (k == n) break; Q = RgX_mul(Q, x_k); C = diviuexact(mulsi(k-n,C), k+1); /* (-1)^k binomial(n,k) */ } return fix_pol(av, RgX_Rg_div(T, mpfact(n))); } /* C = charpoly(x, v) */ static GEN RgM_adj_from_char(GEN x, long v, GEN C) { if (varn(C) != v) /* problem with variable priorities */ { C = gdiv(gsub(C, gsubst(C, v, gen_0)), pol_x(v)); if (odd(lg(x))) C = RgX_neg(C); /* even dimension */ return gsubst(C, v, x); } else { C = RgX_shift_shallow(C, -1); if (odd(lg(x))) C = RgX_neg(C); /* even dimension */ return RgX_RgM_eval(C, x); } } /* assume x square matrice */ static GEN mattrace(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 = gadd(t, gcoeff(x,i,i)); return t; } static int bad_char(GEN q, long n) { forprime_t S; ulong p; if (!signe(q)) return 0; (void)u_forprime_init(&S, 2, n); while ((p = u_forprime_next(&S))) if (!umodiu(q, p)) return 1; return 0; } /* Using traces: return the characteristic polynomial of x (in variable v). * If py != NULL, the adjoint matrix is put there. */ GEN caradj(GEN x, long v, GEN *py) { pari_sp av, av0; long i, k, n; GEN T, y, t; if ((T = easychar(x, v))) { if (py) { if (typ(x) != t_MAT) pari_err_TYPE("matadjoint",x); *py = cgetg(1,t_MAT); } return T; } n = lg(x)-1; av0 = avma; T = cgetg(n+3,t_POL); T[1] = evalsigne(1) | evalvarn(v); gel(T,n+2) = gen_1; if (!n) { if (py) *py = cgetg(1,t_MAT); return T; } av = avma; t = gerepileupto(av, gneg(mattrace(x))); gel(T,n+1) = t; if (n == 1) { T = fix_pol(av0, T); if (py) *py = matid(1); return T; } if (n == 2) { GEN a = gcoeff(x,1,1), b = gcoeff(x,1,2); GEN c = gcoeff(x,2,1), d = gcoeff(x,2,2); av = avma; gel(T,2) = gerepileupto(av, gsub(gmul(a,d), gmul(b,c))); T = fix_pol(av0, T); if (py) { y = cgetg(3, t_MAT); gel(y,1) = mkcol2(gcopy(d), gneg(c)); gel(y,2) = mkcol2(gneg(b), gcopy(a)); *py = y; } return T; } /* l > 3 */ if (bad_char(residual_characteristic(x), n)) { /* n! not invertible in base ring */ T = charpoly(x, v); if (!py) return gerepileupto(av, T); *py = RgM_adj_from_char(x, v, T); gerepileall(av, 2, &T,py); return T; } av = avma; y = RgM_shallowcopy(x); for (i = 1; i <= n; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); for (k = 2; k < n; k++) { GEN y0 = y; y = RgM_mul(y, x); t = gdivgs(mattrace(y), -k); for (i = 1; i <= n; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); y = gclone(y); gel(T,n-k+2) = gerepilecopy(av, t); av = avma; if (k > 2) gunclone(y0); } t = gmul(gcoeff(x,1,1),gcoeff(y,1,1)); for (i=2; i<=n; i++) t = gadd(t, gmul(gcoeff(x,1,i),gcoeff(y,i,1))); gel(T,2) = gerepileupto(av, gneg(t)); T = fix_pol(av0, T); if (py) *py = odd(n)? gcopy(y): RgM_neg(y); gunclone(y); return T; } GEN adj(GEN x) { GEN y; (void)caradj(x, MAXVARN, &y); return y; } GEN adjsafe(GEN x) { const long v = MAXVARN; pari_sp av = avma; GEN C; 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)); } GEN matadjoint0(GEN x, long flag) { switch(flag) { case 0: return adj(x); case 1: return adjsafe(x); } pari_err_FLAG("matadjoint"); return NULL; /* not reached */ } /*******************************************************************/ /* */ /* MINIMAL POLYNOMIAL */ /* */ /*******************************************************************/ static GEN easymin(GEN x, long v) { pari_sp ltop=avma; GEN G, R, dR; if (typ(x)==t_POLMOD && !issquarefree(gel(x,1))) return NULL; R = easychar(x, v); if (!R) return R; dR=RgX_deriv(R); if (!lgpol(dR)) {avma=ltop; return NULL;} G=RgX_gcd(R,dR); G=RgX_Rg_div(G,leading_term(G)); return gerepileupto(ltop, RgX_div(R,G)); } GEN minpoly(GEN x, long v) { pari_sp ltop=avma; GEN P; if (v<0) v = 0; if (typ(x)==t_FFELT) { GEN p1 = FpX_to_mod(FF_minpoly(x), FF_p_i(x)); setvarn(p1,v); return gerepileupto(ltop,p1); } P=easymin(x,v); if (P) return P; if (typ(x)==t_POLMOD) { P = gcopy(RgXQ_minpoly_naive(gel(x,2), gel(x,1))); setvarn(P,v); return gerepileupto(ltop,P); } 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)); } /*******************************************************************/ /* */ /* HESSENBERG FORM */ /* */ /*******************************************************************/ GEN hess(GEN x) { pari_sp av = avma, lim; 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); for (m=2; m1) pari_warn(warnmem,"hess, m = %ld", m); gerepileall(av,2, &x, &t); } } } return gerepilecopy(av,x); } GEN Flm_hess(GEN x, ulong p) { long lx = lg(x), m, i, j; if (lx == 1) return cgetg(1,t_MAT); if (lgcols(x) != lx) pari_err_DIM("hess"); x = Flm_copy(x); for (m=2; m1) pari_warn(warnmem,"hess, m = %ld", m); gerepileall(av,2, &x, &t); } } } return gerepilecopy(av,x); } GEN carhess(GEN x, long v) { pari_sp av; long lx, r, i; GEN y, H; if ((H = easychar(x,v))) return H; lx = lg(x); av = avma; y = cgetg(lx+1, t_VEC); gel(y,1) = pol_1(v); H = hess(x); for (r = 1; r < lx; r++) { pari_sp av2 = avma; GEN z, a = gen_1, b = pol_0(v); for (i = r-1; i; i--) { a = gmul(a, gcoeff(H,i+1,i)); if (gequal0(a)) break; b = RgX_add(b, RgX_Rg_mul(gel(y,i), gmul(a,gcoeff(H,i,r)))); } z = RgX_sub(RgX_shift_shallow(gel(y,r), 1), RgX_Rg_mul(gel(y,r), gcoeff(H,r,r))); gel(y,r+1) = gerepileupto(av2, RgX_sub(z, b)); /* (X - H[r,r])y[r] - b */ } 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)) */ static double charpoly_bound(GEN M) { pari_sp av = avma; GEN s = real_0(LOWDEFAULTPREC), bin, B2 = itor(sqri(ZM_supnorm(M)), LOWDEFAULTPREC); long n = lg(M)-1, k; double d; bin = gen_1; for (k = n; k >= (n+1)>>1; k--) { GEN t = mulri(powruhalf(mulur(k, B2), k), bin); if (absr_cmp(t, s) > 0) s = t; bin = diviuexact(muliu(bin, k), n-k+1); } d = dbllog2(s); avma = av; return ceil(d); } GEN ZM_charpoly(GEN M) { pari_timer T; pari_sp av = avma; long l = lg(M), n = l-1, bit; GEN q = NULL, H = NULL, Hp; forprime_t S; ulong p; if (!n) return pol_1(0); bit = (long)charpoly_bound(M) + 1; if (DEBUGLEVEL>5) { err_printf("ZM_charpoly: bit-bound 2^%ld\n", bit); timer_start(&T); } 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; } } if (!p) pari_err_OVERFLOW("ZM_charpoly [ran out of primes]"); return gerepilecopy(av, H); } /*******************************************************************/ /* */ /* CHARACTERISTIC POLYNOMIAL (BERKOWITZ'S ALGORITHM) */ /* */ /*******************************************************************/ GEN carberkowitz(GEN x, long v) { long lx, i, j, k, r; GEN V, S, C, Q; pari_sp av0, av, lim; if ((V = easychar(x,v))) return V; lx = lg(x); av0 = avma; lim = stack_lim(av0,1); V = cgetg(lx+1, t_VEC); S = cgetg(lx+1, t_VEC); C = cgetg(lx+1, t_VEC); Q = cgetg(lx+1, t_VEC); av = avma; gel(C,1) = gen_m1; gel(V,1) = gen_m1; for (i=2;i<=lx; i++) gel(C,i) = gel(Q,i) = gel(S,i) = gel(V,i) = gen_0; gel(V,2) = gcoeff(x,1,1); for (r = 2; r < lx; r++) { pari_sp av2; GEN t; for (i = 1; i < r; i++) gel(S,i) = gcoeff(x,i,r); gel(C,2) = gcoeff(x,r,r); for (i = 1; i < r-1; i++) { 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,i+2) = gerepileupto(av2, t); for (j = 1; j < r; j++) { av2 = avma; t = gmul(gcoeff(x,j,1), gel(S,1)); for (k = 2; k < r; k++) t = gadd(t, gmul(gcoeff(x,j,k), gel(S,k))); gel(Q,j) = gerepileupto(av2, t); } for (j = 1; j < r; j++) gel(S,j) = gel(Q,j); } 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 (DEBUGMEM>1) pari_warn(warnmem,"carberkowitz"); gerepileall(av, 2, &C, &V); } for (i = 1; i <= r+1; i++) { av2 = avma; t = gmul(gel(C,i), gel(V,1)); for (j = 2; j <= minss(r,i); j++) t = gadd(t, gmul(gel(C,i+1-j), gel(V,j))); gel(Q,i) = gerepileupto(av2, t); } for (i = 1; i <= r+1; i++) gel(V,i) = gel(Q,i); } V = RgV_to_RgX(vecreverse(V), v); /* not gtopoly: fail if v > gvar(V) */ V = odd(lx)? gcopy(V): RgX_neg(V); return fix_pol(av0, V); } /*******************************************************************/ /* */ /* NORMS */ /* */ /*******************************************************************/ GEN gnorm(GEN x) { pari_sp av; long lx, i; GEN y; switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_FRAC: return sqrfrac(x); case t_COMPLEX: av = avma; return gerepileupto(av, cxnorm(x)); case t_QUAD: av = avma; return gerepileupto(av, quadnorm(x)); case t_POL: case t_SER: case t_RFRAC: av = avma; return gerepileupto(av, greal(gmul(gconj(x),x))); case t_FFELT: y = cgetg(3, t_INTMOD); gel(y,1) = FF_p(x); gel(y,2) = FF_norm(x); return y; case t_POLMOD: { GEN T = gel(x,1), a = gel(x,2); if (typ(a) != t_POL || varn(a) != varn(T)) return gpowgs(a, degpol(T)); return RgXQ_norm(a, T); } case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i 0) return quadnorm(q); /* imaginary */ if (!prec) pari_err_TYPE("gnorml2", q); return sqrr(quadtofp(q, prec)); } static GEN gnorml2_i(GEN x, long prec) { pari_sp av, lim; long i, lx; GEN s; switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_FRAC: return sqrfrac(x); case t_COMPLEX: av = avma; return gerepileupto(av, cxnorm(x)); case t_QUAD: av = avma; return gerepileupto(av, cxquadnorm(x,prec)); case t_POL: lx = lg(x)-1; x++; break; case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; default: pari_err_TYPE("gnorml2",x); return NULL; /* not reached */ } if (lx == 1) return gen_0; av = avma; lim = stack_lim(av,1); s = gnorml2(gel(x,1)); for (i=2; i1) pari_warn(warnmem,"gnorml2"); s = gerepileupto(av, s); } } return gerepileupto(av,s); } GEN gnorml2(GEN x) { return gnorml2_i(x, 0); } 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); long i, lx = lg(x); GEN s = gen_0; for (i=i0; i1) pari_warn(warnmem,"gnormlp, i = %ld", i); s = gerepileupto(av, s); } } return s; } /* (||x||_p)^p */ static GEN pnormlp(GEN x, GEN p, long prec) { switch(typ(x)) { case t_INT: case t_REAL: x = mpabs(x); break; case t_FRAC: x = absfrac(x); break; case t_COMPLEX: case t_QUAD: x = gabs(x,prec); break; case t_POL: return pnormlpvec(2, x, p, prec); case t_VEC: case t_COL: case t_MAT: return pnormlpvec(1, x, p, prec); default: pari_err_TYPE("gnormlp",x); } return gpow(x, p, prec); } GEN gnormlp(GEN x, GEN p, long prec) { pari_sp av = avma; if (!p) return gsupnorm(x, prec); if (gsigne(p) <= 0) pari_err_DOMAIN("normlp", "p", "<=", gen_0, p); if (is_scalar_t(typ(x))) return gabs(x, prec); if (typ(p) == t_INT) { ulong pp = itou_or_0(p); switch(pp) { case 1: return gnorml1(x, prec); case 2: x = gnorml2_i(x, prec); break; default: x = pnormlp(x, p, prec); break; } if (pp && typ(x) == t_INT && Z_ispowerall(x, pp, &x)) return gerepileuptoleaf(av, x); if (pp == 2) return gerepileupto(av, gsqrt(x, prec)); } else x = pnormlp(x, p, prec); x = gpow(x, ginv(p), prec); return gerepileupto(av, x); } GEN gnorml1(GEN x,long prec) { pari_sp av = avma; long lx,i; GEN s; switch(typ(x)) { case t_INT: case t_REAL: return mpabs(x); case t_FRAC: return absfrac(x); case t_COMPLEX: case t_QUAD: return gabs(x,prec); case t_POL: lx = lg(x); s = gen_0; for (i=2; i 0) *m = z; } /* compare |x| to *m or |x|^2 to *msq, whichever is easiest, and update * the pointed value if x is larger */ void gsupnorm_aux(GEN x, GEN *m, GEN *msq, long prec) { long i, lx; GEN z; switch(typ(x)) { case t_COMPLEX: z = cxnorm(x); store(z, msq); return; case t_QUAD: z = cxquadnorm(x,prec); store(z, msq); return; case t_INT: case t_REAL: z = mpabs(x); store(z,m); return; case t_FRAC: z = absfrac(x); store(z,m); return; case t_POL: lx = lg(x)-1; x++; break; case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; default: pari_err_TYPE("gsupnorm",x); return; /* not reached */ } for (i=1; i1) pari_warn(warnmem,"qfgaussred_positive"); b=gerepilecopy(av,b); } } return gerepilecopy(av,b); } /* Maximal pivot strategy: x is a suitable pivot if it is non zero and either * - an exact type, or * - it is maximal among remaining non-zero (t_REAL) pivots */ static int suitable(GEN x, long k, GEN *pp, long *pi) { long t = typ(x); switch(t) { case t_INT: return signe(x) != 0; case t_FRAC: return 1; case t_REAL: { GEN p = *pp; if (signe(x) && (!p || absr_cmp(p, x) < 0)) { *pp = x; *pi = k; } return 0; } default: return !gequal0(x); } } /* Gauss reduction (arbitrary symetric matrix, only the part above the * diagonal is considered). If signature is non-zero, return only the * signature, in which case gsigne() should be defined for elements of a. */ static GEN gaussred(GEN a, long signature) { GEN r, ak, al; pari_sp av, av1, lim; long n = lg(a), i, j, k, l, sp, sn, t; if (typ(a) != t_MAT) pari_err_TYPE("gaussred",a); if (n == 1) return signature? mkvec2(gen_0, gen_0): cgetg(1, t_MAT); if (lgcols(a) != n) pari_err_DIM("gaussred"); n--; av = avma; r = const_vecsmall(n, 1); av1= avma; lim = stack_lim(av1,1); a = RgM_shallowcopy(a); t = n; sp = sn = 0; while (t) { long pind = 0; GEN invp, p = NULL; k=1; while (k<=n && (!r[k] || !suitable(gcoeff(a,k,k), k, &p, &pind))) k++; if (k > n && p) k = pind; if (k <= n) { p = gcoeff(a,k,k); invp = ginv(p); /* != 0 */ if (signature) { /* skip if (!signature): gsigne may fail ! */ if (gsigne(p) > 0) sp++; else sn++; } r[k] = 0; t--; ak = row(a, k); for (i=1; i<=n; i++) gcoeff(a,k,i) = r[i]? gmul(gcoeff(a,k,i), invp): gen_0; for (i=1; i<=n; i++) if (r[i]) { GEN c = gel(ak,i); /* - p * a[k,i] */ if (gequal0(c)) continue; for (j=1; j<=n; j++) if (r[j]) gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gmul(c,gcoeff(a,k,j))); } gcoeff(a,k,k) = p; } else { /* all remaining diagonal coeffs are currently 0 */ for (k=1; k<=n; k++) if (r[k]) { l=k+1; while (l<=n && (!r[l] || !suitable(gcoeff(a,k,l), l, &p, &pind))) l++; if (l > n && p) l = pind; if (l > n) continue; p = gcoeff(a,k,l); invp = ginv(p); sp++; sn++; r[k] = r[l] = 0; t -= 2; ak = row(a, k); al = row(a, l); for (i=1; i<=n; i++) if (r[i]) { gcoeff(a,k,i) = gmul(gcoeff(a,k,i), invp); gcoeff(a,l,i) = gmul(gcoeff(a,l,i), invp); } else { gcoeff(a,k,i) = gen_0; gcoeff(a,l,i) = gen_0; } for (i=1; i<=n; i++) if (r[i]) { /* c = a[k,i] * p, d = a[l,i] * p; */ GEN c = gel(ak,i), d = gel(al,i); for (j=1; j<=n; j++) if (r[j]) gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gadd(gmul(gcoeff(a,l,j), c), gmul(gcoeff(a,k,j), d))); } for (i=1; i<=n; i++) if (r[i]) { GEN c = gcoeff(a,k,i), d = gcoeff(a,l,i); gcoeff(a,k,i) = gadd(c, d); gcoeff(a,l,i) = gsub(c, d); } gcoeff(a,k,l) = gen_1; 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(DEBUGMEM>1) pari_warn(warnmem,"gaussred"); a = gerepilecopy(av1, a); } break; } if (k > n) break; } } if (!signature) return gerepilecopy(av, a); avma = av; return mkvec2s(sp, sn); } GEN qfgaussred(GEN a) { return gaussred(a,0); } GEN qfsign(GEN a) { return gaussred(a,1); } /* x -= s(y+u*x) */ /* y += s(x-u*y), simultaneously */ static void rot(GEN x, GEN y, GEN s, GEN u) { GEN x1 = subrr(x, mulrr(s,addrr(y,mulrr(u,x)))); GEN y1 = addrr(y, mulrr(s,subrr(x,mulrr(u,y)))); affrr(x1,x); affrr(y1,y); } /* Diagonalization of a REAL symetric matrix. Return a vector [L, r]: * L = vector of eigenvalues * r = matrix of eigenvectors */ GEN jacobi(GEN a, long prec) { pari_sp av1; long de, e, e1, e2, i, j, p, q, l = lg(a); GEN c, ja, L, r, L2, r2, unr; if (typ(a) != t_MAT) pari_err_TYPE("jacobi",a); ja = cgetg(3,t_VEC); L = cgetg(l,t_COL); gel(ja,1) = L; r = cgetg(l,t_MAT); gel(ja,2) = r; if (l == 1) return ja; if (lgcols(a) != l) pari_err_DIM("jacobi"); e1 = HIGHEXPOBIT-1; for (j=1; j e2) { e2 = e; p = i; q = j; } } } a = c; unr = real_1(prec); de = prec2nbits(prec); /* e1 = min expo(a[i,i]) * e2 = max expo(a[i,j]), i != j */ while (e1-e2 < de) { pari_sp av2 = avma; GEN x, y, t, c, s, u; /* compute associated rotation in the plane formed by basis vectors number * p and q */ x = subrr(gel(L,q),gel(L,p)); if (signe(x)) { x = divrr(x, shiftr(gcoeff(a,p,q),1)); y = sqrtr(addrr(unr, sqrr(x))); t = invr((signe(x)>0)? addrr(x,y): subrr(x,y)); } else y = t = unr; c = sqrtr(addrr(unr,sqrr(t))); s = divrr(t,c); u = divrr(t,addrr(unr,c)); /* compute successive transforms of a and the matrix of accumulated * rotations (r) */ for (i=1; i e2) { e2=e; p=i; q=j; } } for (i=j+1; i e2) { e2=e; p=j; q=i; } } } avma = av2; } /* sort eigenvalues from smallest to largest */ c = indexsort(L); r2 = vecpermute(r, c); for (i=1; i ENTIERE **/ /** **/ /*************************************************************************/ GEN matrixqz0(GEN x,GEN p) { if (typ(x) != t_MAT) pari_err_TYPE("QM_minors_coprime",x); if (!p) return QM_minors_coprime(x,NULL); if (typ(p) != t_INT) pari_err_TYPE("QM_minors_coprime",p); if (signe(p)>=0) return QM_minors_coprime(x,p); if (equaliu(p,1)) return QM_ImZ_hnf(x); /* p = -1 */ if (equaliu(p,2)) return QM_ImQ_hnf(x); /* p = -2 */ pari_err_FLAG("QM_minors_coprime"); return NULL; /* not reached */ } GEN QM_minors_coprime(GEN x, GEN D) { pari_sp av = avma, av1, lim; long i, j, m, n, lP; GEN P, y; n = lg(x)-1; if (!n) return gcopy(x); m = nbrows(x); if (n > m) pari_err_DOMAIN("QM_minors_coprime","n",">",strtoGENstr("m"),x); y = x; x = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) { gel(x,j) = Q_primpart(gel(y,j)); RgV_check_ZV(gel(x,j), "QM_minors_coprime"); } /* x now a ZM */ if (n==m) { if (gequal0(ZM_det(x))) pari_err_DOMAIN("QM_minors_coprime", "rank(A)", "<",stoi(n),x); avma = av; return matid(n); } /* m > n */ if (!D || gequal0(D)) { pari_sp av2 = avma; D = ZM_detmult(shallowtrans(x)); 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); for (i=1; i < lP; i++) { GEN p = gel(P,i), pov2 = shifti(p, -1); for(;;) { GEN N, M = FpM_ker(x, p); long lM = lg(M); if (lM==1) break; M = FpM_center(M, p, pov2); N = ZM_Z_divexact(ZM_mul(x,M), p); for (j=1; j1) pari_warn(warnmem,"QM_minors_coprime, p = %Ps", p); x = gerepilecopy(av1, x); pov2 = shifti(p, -1); } } } return gerepilecopy(av, x); } static GEN RgC_Z_mul(GEN A, GEN u) { long s = signe(u); if (is_pm1(u)) return s > 0? A: RgC_neg(A); return s? gmul(u,A): zerocol(lg(A)-1); } /* u,v integral, A,B RgC */ static GEN RgC_lincomb(GEN u, GEN v, GEN A, GEN B) { if (!signe(u)) return RgC_Z_mul(B,v); if (!signe(v)) return RgC_Z_mul(A,u); return RgC_add(RgC_Z_mul(A,u), RgC_Z_mul(B,v)); } /* cf ZC_elem */ /* zero aj = Aij (!= 0) using ak = Aik (maybe 0), via linear combination of * A[j] and A[k] of determinant 1. */ static void QC_elem(GEN aj, GEN ak, GEN A, long j, long k) { GEN p1, u, v, d; if (gequal0(ak)) { swap(gel(A,j), gel(A,k)); return; } if (typ(aj) == t_INT) { if (typ(ak) != t_INT) { aj = mulii(aj, gel(ak,2)); ak = gel(ak,1); } } else { if (typ(ak) == t_INT) { ak = mulii(ak, gel(aj,2)); aj = gel(aj,1); } else { GEN daj = gel(aj,2), dak = gel(ak,2), D = gcdii(daj, dak); aj = gel(aj,1); ak = gel(ak,1); if (!is_pm1(D)) { daj = diviiexact(daj, D); dak = diviiexact(dak, D); } if (!is_pm1(dak)) aj = mulii(aj, dak); if (!is_pm1(daj)) ak = mulii(ak, daj); } } /* aj,ak were multiplied by their least common denominator */ d = bezout(aj,ak,&u,&v); /* frequent special case (u,v) = (1,0) or (0,1) */ if (!signe(u)) { /* ak | aj */ GEN c = negi(diviiexact(aj,ak)); gel(A,j) = RgC_lincomb(gen_1, c, gel(A,j), gel(A,k)); return; } if (!signe(v)) { /* aj | ak */ GEN c = negi(diviiexact(ak,aj)); gel(A,k) = RgC_lincomb(gen_1, c, gel(A,k), gel(A,j)); swap(gel(A,j), gel(A,k)); return; } if (!is_pm1(d)) { aj = diviiexact(aj,d); ak = diviiexact(ak,d); } p1 = gel(A,k); gel(A,k) = RgC_lincomb(u,v, gel(A,j),p1); gel(A,j) = RgC_lincomb(negi(aj),ak, p1,gel(A,j)); } static GEN QM_imZ_hnf_aux(GEN A) { pari_sp av = avma, lim = stack_lim(av,1); long i,j,k,n,m; GEN a; n = lg(A); if (n == 1) return cgetg(1,t_MAT); if (n == 2) { GEN c; A = Q_primitive_part(A, &c); if (!c) A = ZM_copy(A); else if ( isintzero(c) ) A = cgetg(1,t_MAT); return A; } m = lgcols(A); for (i=1; i1) pari_warn(warnmem,"QM_imZ_hnf_aux"); A = gerepilecopy(av,A); } } return ZM_hnf(A); } GEN QM_ImZ_hnf(GEN x) { pari_sp av = avma; return gerepileupto(av, QM_imZ_hnf_aux( RgM_shallowcopy(x) )); } GEN QM_ImQ_hnf(GEN x) { pari_sp av = avma, av1, lim; 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); for (k=1; k1) pari_warn(warnmem,"QM_ImQ_hnf"); x = gerepilecopy(av1,x); } } return gerepileupto(av, QM_imZ_hnf_aux(x)); } GEN intersect(GEN x, GEN y) { long j, lx = lg(x); pari_sp av; GEN z; if (typ(x)!=t_MAT) pari_err_TYPE("intersect",x); if (typ(y)!=t_MAT) pari_err_TYPE("intersect",y); if (lx==1 || lg(y)==1) return cgetg(1,t_MAT); av = avma; z = ker(shallowconcat(x,y)); for (j=lg(z)-1; j; j--) setlg(z[j], lx); return gerepileupto(av, RgM_mul(x,z)); } pari-2.7.5/src/basemath/RgX.c0000644000175000017500000015562712605245444014353 0ustar billbill/* 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" /*******************************************************************/ /* */ /* GENERIC */ /* */ /*******************************************************************/ /* Return optimal 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. */ long brent_kung_optpow(long d, long n, long m) { long p, r; long pold=1, rold=n*(d-1); for(p=2; p<=d; p++) { r = m*(p-1) + n*((d-1)/p); if (rone(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))) z = gerepileupto(av, z); } return ff->red(E,z); } /* Brent & Kung * (Fast algorithms for manipulating formal power series, JACM 25:581-595, 1978) * * V as output by FpXQ_powers(x,l,T,p). For optimal performance, l is as given * by brent_kung_optpow */ 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; long l = lg(V)-1; GEN z, u; if (d < 0) return ff->zero(E); if (d < l) return gerepileupto(av, gen_RgXQ_eval_powers(P,V,0,d,E,ff,cmul)); 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))) z = gerepileupto(av, z); } u = gen_RgXQ_eval_powers(P,V,0,d,E,ff,cmul); z = ff->add(E,u, ff->mul(E,z,gel(V,d+2))); if (DEBUGLEVEL>=8) { long cnt = 1 + (d - l) / (l-1); err_printf("RgX_RgXQV_eval: %ld RgXQ_mul [%ld]\n", cnt, l-1); } return gerepileupto(av, ff->red(E,z)); } GEN gen_bkeval(GEN Q, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)) { pari_sp av = avma; GEN z, V; long rtd; if (d < 0) return ff->zero(E); rtd = (long) sqrt((double)d); V = gen_powers(x,rtd,use_sqr,E,ff->sqr,ff->mul,ff->one); z = gen_bkeval_powers(Q, d, V, E, ff, cmul); return gerepileupto(av, z); } /*******************************************************************/ /* */ /* RgX */ /* */ /*******************************************************************/ long RgX_equal(GEN x, GEN y) { long i = lg(x); if (i != lg(y)) return 0; for (i--; i > 1; i--) if (!gequal(gel(x,i),gel(y,i))) return 0; return 1; } /* Returns 1 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN RgX_get_1(GEN x) { GEN p, T; long i, lx, tx = RgX_type(x, &p, &T, &lx); if (RgX_type_is_composite(tx)) RgX_type_decode(tx, &i /*junk*/, &tx); switch(tx) { case t_INTMOD: retmkintmod(gen_1, icopy(p)); case t_PADIC: return cvtop(gen_1, p, lx); case t_FFELT: return FF_1(T); default: return gen_1; } } /* Returns 0 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN RgX_get_0(GEN x) { GEN p, T; long i, lx, tx = RgX_type(x, &p, &T, &lx); if (RgX_type_is_composite(tx)) RgX_type_decode(tx, &i /*junk*/, &tx); switch(tx) { case t_INTMOD: retmkintmod(gen_0, icopy(p)); case t_PADIC: return cvtop(gen_0, p, lx); case t_FFELT: return FF_zero(T); default: return gen_0; } } GEN QX_ZXQV_eval(GEN P, GEN V, GEN dV) { long i, n = degpol(P); GEN z, dz, dP; if (n < 0) return gen_0; P = Q_remove_denom(P, &dP); z = gel(P,2); if (n == 0) return icopy(z); if (dV) z = mulii(dV, z); /* V[1] = dV */ z = ZX_Z_add_shallow(ZX_Z_mul(gel(V,2),gel(P,3)), z); for (i=2; i<=n; i++) z = ZX_add(ZX_Z_mul(gel(V,i+1),gel(P,2+i)), z); dz = mul_denom(dP, dV); return dz? RgX_Rg_div(z, dz): z; } /* Return P(h * x), not memory clean */ GEN RgX_unscale(GEN P, GEN h) { long i, l = lg(P); GEN hi = gen_1, Q = cgetg(l, t_POL); Q[1] = P[1]; if (l == 2) return Q; gel(Q,2) = gcopy(gel(P,2)); for (i=3; i=2; i--) { gel(Q,i) = gmul(gel(P,i), hi); if (i == 2) break; hi = gmul(hi,h); } Q[1] = P[1]; return Q; } /* A(X^d) --> A(X) */ GEN RgX_deflate(GEN x0, long d) { GEN z, y, x; long i,id, dy, dx = degpol(x0); if (d == 1 || dx <= 0) return leafcopy(x0); dy = dx/d; y = cgetg(dy+3, t_POL); y[1] = x0[1]; z = y + 2; x = x0+ 2; for (i=id=0; i<=dy; i++,id+=d) gel(z,i) = gel(x,id); return y; } /* return x0(X^d) */ GEN RgX_inflate(GEN x0, long d) { long i, id, dy, dx = degpol(x0); GEN x = x0 + 2, z, y; if (dx <= 0) return leafcopy(x0); dy = dx*d; y = cgetg(dy+3, t_POL); y[1] = x0[1]; z = y + 2; for (i=0; i<=dy; i++) gel(z,i) = gen_0; for (i=id=0; i<=dx; i++,id+=d) gel(z,id) = gel(x,i); return y; } /* return P(X + c) using destructive Horner, optimize for c = 1,-1 */ GEN RgX_translate(GEN P, GEN c) { pari_sp av = avma, lim; 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; k1) pari_warn(warnmem,"TR_POL(1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } else if (gequalm1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"TR_POL(-1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } else { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"TR_POL, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } return gerepilecopy(av, Q); } /* return P(X + c) using destructive Horner, optimize for c = 1,-1 */ GEN ZX_translate(GEN P, GEN c) { pari_sp av = avma, lim; 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; k1) pari_warn(warnmem,"ZX_translate(1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } else if (equalim1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"ZX_translate(-1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } else { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"ZX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } } return gerepilecopy(av, Q); } /* return lift( P(X + c) ) using Horner, c in R[y]/(T) */ GEN RgXQX_translate(GEN P, GEN c, GEN T) { pari_sp av = avma, lim; 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; k1) pari_warn(warnmem,"RgXQX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } return gerepilecopy(av, Q); } /********************************************************************/ /** **/ /** CONVERSIONS **/ /** (not memory clean) **/ /** **/ /********************************************************************/ /* to INT / FRAC / (POLMOD mod T), not memory clean because T not copied, * but everything else is */ static GEN QXQ_to_mod_copy(GEN x, GEN T) { long d; switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POL: d = degpol(x); if (d < 0) return gen_0; if (d == 0) return gcopy(gel(x,2)); return mkpolmod(RgX_copy(x), T); default: pari_err_TYPE("QXQ_to_mod",x); return NULL;/* not reached */ } } /* pure shallow version */ static GEN QXQ_to_mod(GEN x, GEN T) { long d; switch(typ(x)) { case t_INT: case t_FRAC: return x; case t_POL: d = degpol(x); if (d < 0) return gen_0; if (d == 0) return gel(x,2); return mkpolmod(x, T); default: pari_err_TYPE("QXQ_to_mod",x); return NULL;/* not reached */ } } /* T a ZX, z lifted from (Q[Y]/(T(Y)))[X], apply QXQ_to_mod_copy to all coeffs. * Not memory clean because T not copied, but everything else is */ static GEN QXQX_to_mod(GEN z, GEN T) { long i,l = lg(z); GEN x = cgetg(l,t_POL); for (i=2; i1; i--) if (! gequal0(gel(x,i))) break; /* _not_ isexactzero */ stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i != 1); return x; } GEN RgV_to_RgX(GEN x, long v) { long i, k = lg(x); GEN p; while (--k && gequal0(gel(x,k))); if (!k) return pol_0(v); i = k+2; p = cgetg(i,t_POL); p[1] = evalsigne(1) | evalvarn(v); x--; for (k=2; k N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i P(Y,X), n is an upper bound for deg_Y(P) */ GEN RgXY_swapspec(GEN x, long n, long w, long nx) { long j, ly = n+3; GEN y = cgetg(ly, t_POL); y[1] = evalsigne(1); for (j=2; j P(Y,X), n is an upper bound for deg_Y(P) */ GEN RgXY_swap(GEN x, long n, long w) { GEN z = RgXY_swapspec(x+2, n, w, lgpol(x)); setvarn(z, varn(x)); return z; } /* return (x % X^n). Shallow */ GEN RgX_modXn_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= 0) return RgX_shift(x, d); d = -d; v = RgX_val(x); if (v >= d) return RgX_shift(x, -d); av = avma; z = gred_rfrac_simple( RgX_shift_shallow(x, -v), monomial(gen_1, d - v, varn(x))); return gerepileupto(av, z); } long RgX_val(GEN x) { long i, lx = lg(x); if (lx == 2) return LONG_MAX; for (i = 2; i < lx; i++) if (!isexactzero(gel(x,i))) break; if (i == lx) i--; /* possible with non-rational zeros */ return i - 2; } long RgX_valrem(GEN x, GEN *Z) { long v, i, lx = lg(x); if (lx == 2) { *Z = pol_0(varn(x)); return LONG_MAX; } for (i = 2; i < lx; i++) if (!isexactzero(gel(x,i))) break; if (i == lx) i--; /* possible with non-rational zeros */ v = i - 2; *Z = RgX_shift_shallow(x, -v); return v; } long RgX_valrem_inexact(GEN x, GEN *Z) { long v; if (!signe(x)) { if (Z) *Z = pol_0(varn(x)); return LONG_MAX; } for (v = 0;; v++) if (!gequal0(gel(x,2+v))) break; if (Z) *Z = RgX_shift_shallow(x, -v); return v; } GEN RgXQC_red(GEN P, GEN T) { long i, l = lg(P); GEN Q = cgetg(l, t_COL); for (i=1; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz,t_POL) + 2; for (i=0; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz,t_POL) + 2; for (i=0; i= ny > 0, return x * y * t^v */ static GEN RgX_mulspec_basecase(GEN x, GEN y, long nx, long ny, long v) { long i, lz, nz; GEN z; x = RgXspec_kill0(x,nx); y = RgXspec_kill0(y,ny); lz = nx + ny + 1; nz = lz-2; lz += v; z = cgetg(lz, t_POL) + 2; /* x:y:z [i] = term of degree i */ for (i=0; i 0 */ GEN addmulXn(GEN x, GEN y, long d) { GEN xd, yd, zd; long a, lz, nx, ny; if (!signe(x)) return y; ny = lgpol(y); nx = lgpol(x); zd = (GEN)avma; x += 2; y += 2; a = ny-d; if (a <= 0) { lz = nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) gel(--zd,0) = gel(--xd,0); x = zd + a; while (zd > x) gel(--zd,0) = gen_0; } else { xd = new_chunk(d); yd = y+d; x = addpol(x,yd, nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) *--zd = *--yd; *--zd = evalsigne(1); *--zd = evaltyp(t_POL) | evallg(lz); return zd; } GEN addshiftpol(GEN x, GEN y, long d) { long v = varn(x); x = addmulXn(x,y,d); setvarn(x,v); return x; } /* as above, producing a clean malloc */ static GEN addmulXncopy(GEN x, GEN y, long d) { GEN xd, yd, zd; long a, lz, nx, ny; if (!signe(x)) return RgX_copy(y); nx = lgpol(x); ny = lgpol(y); zd = (GEN)avma; x += 2; y += 2; a = ny-d; if (a <= 0) { lz = nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) gel(--zd,0) = gcopy(gel(--xd,0)); x = zd + a; while (zd > x) gel(--zd,0) = gen_0; } else { xd = new_chunk(d); yd = y+d; x = addpolcopy(x,yd, nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) gel(--zd,0) = gcopy(gel(--yd,0)); *--zd = evalsigne(1); *--zd = evaltyp(t_POL) | evallg(lz); return zd; } /* return x * y mod t^n */ static GEN RgX_mullow_basecase(GEN x, GEN y, long n) { long i, lz = n+2, lx = lgpol(x), ly = lgpol(y); GEN z; if (lx < 0) return pol_0(varn(x)); if (ly < 0) return pol_0(varn(x)); z = cgetg(lz, t_POL) + 2; x+=2; if (lx > n) lx = n; y+=2; if (ly > n) ly = n; z[-1] = x[-1]; if (ly > lx) { swap(x,y); lswap(lx,ly); } x = RgXspec_kill0(x, lx); y = RgXspec_kill0(y, ly); /* x:y:z [i] = term of degree i */ for (i=0;i>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)); /* 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 */ /* deg(t m(t^2)) <= 2n1 - 1 <= n, truncate to < n */ if (2*degpol(m)+1 == n) m = normalizepol_lg(m, lg(m)-1); m = RgX_inflate(m,2); /* deg(t^2 h(t^2)) <= 2n0 <= n, truncate to < n */ if (2*degpol(h)+2 == n) h = normalizepol_lg(h, lg(h)-1); h = RgX_inflate(h,2); h = addmulXncopy(addmulXn(h,m,1), l,1); setvarn(h, varn(f)); return gerepileupto(av, h); } /* fast product (Karatsuba) of polynomials a,b. These are not real GENs, a+2, * b+2 were sent instead. na, nb = number of terms of a, b. * Only c, c0, c1, c2 are genuine GEN. */ GEN RgX_mulspec(GEN a, GEN b, long na, long nb) { GEN a0, c, c0; long n0, n0a, i, v = 0; pari_sp av; while (na && isrationalzero(gel(a,0))) { a++; na--; v++; } while (nb && isrationalzero(gel(b,0))) { b++; nb--; v++; } if (na < nb) swapspec(a,b, na,nb); if (!nb) return pol_0(0); if (nb < RgX_MUL_LIMIT) return RgX_mulspec_basecase(a,b,na,nb, v); RgX_shift_inplace_init(v); i = (na>>1); n0 = na-i; na = i; av = avma; a0 = a+n0; n0a = n0; while (n0a && isrationalzero(gel(a,n0a-1))) n0a--; if (nb > n0) { GEN b0,c1,c2; long n0b; nb -= n0; b0 = b+n0; n0b = n0; while (n0b && isrationalzero(gel(b,n0b-1))) n0b--; c = RgX_mulspec(a,b,n0a,n0b); c0 = RgX_mulspec(a0,b0, na,nb); c2 = addpol(a0,a, na,n0a); c1 = addpol(b0,b, nb,n0b); c1 = RgX_mulspec(c1+2,c2+2, lgpol(c1),lgpol(c2)); c2 = RgX_sub(c1, RgX_add(c0,c)); c0 = addmulXn(c0, c2, n0); } else { c = RgX_mulspec(a,b,n0a,nb); c0 = RgX_mulspec(a0,b,na,nb); } c0 = addmulXncopy(c0,c,n0); return RgX_shift_inplace(gerepileupto(av,c0), v); } INLINE GEN RgX_sqrspec_basecase_limb(GEN x, long a, long i) { pari_sp av = avma; GEN s = NULL; long j, l = (i+1)>>1; for (j=a; j>1); if (t) { t = gsqr(t); s = s? gadd(s, t): t; } } return s? gerepileupto(av,s): gen_0; } static GEN RgX_sqrspec_basecase(GEN x, long nx, long v) { long i, lz, nz; GEN z; if (!nx) return pol_0(0); x = RgXspec_kill0(x,nx); lz = (nx << 1) + 1, nz = lz-2; lz += v; z = cgetg(lz,t_POL) + 2; for (i=0; i n) lx = n; x = RgXspec_kill0(x,lx); z+=2;/* x:z [i] = term of degree i */ for (i=0;i>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)); /* 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 */ /* deg(t m(t^2)) <= 2n1 - 1 <= n, truncate to < n */ if (2*degpol(m)+1 == n) m = normalizepol_lg(m, lg(m)-1); m = RgX_inflate(m,2); /* deg(t^2 h(t^2)) <= 2n0 <= n, truncate to < n */ if (2*degpol(h)+2 == n) h = normalizepol_lg(h, lg(h)-1); h = RgX_inflate(h,2); h = addmulXncopy(addmulXn(h,m,1), l,1); setvarn(h, varn(f)); return gerepileupto(av, h); } GEN RgX_sqrspec(GEN a, long na) { GEN a0, c, c0, c1; long n0, n0a, i, v = 0; pari_sp av; while (na && isrationalzero(gel(a,0))) { a++; na--; v += 2; } if (na>1); n0 = na-i; na = i; av = avma; a0 = a+n0; n0a = n0; while (n0a && isrationalzero(gel(a,n0a-1))) n0a--; c = RgX_sqrspec(a,n0a); c0 = RgX_sqrspec(a0,na); c1 = gmul2n(RgX_mulspec(a0,a, na,n0a), 1); c0 = addmulXn(c0,c1, n0); c0 = addmulXncopy(c0,c,n0); return RgX_shift_inplace(gerepileupto(av,c0), v); } /* (X^a + A)(X^b + B) - X^(a+b), where deg A < a, deg B < b */ GEN RgX_mul_normalized(GEN A, long a, GEN B, long b) { GEN z = RgX_mul(A, B); if (a < b) z = addmulXn(addmulXn(A, B, b-a), z, a); else if (a > b) z = addmulXn(addmulXn(B, A, a-b), z, b); else z = addmulXn(RgX_add(A, B), z, a); setvarn(z,varn(A)); return z; } GEN RgX_mul(GEN x, GEN y) { GEN z = RgX_mulspec(y+2, x+2, lgpol(y), lgpol(x)); setvarn(z,varn(x)); return z; } GEN RgX_sqr(GEN x) { GEN z = RgX_sqrspec(x+2, lgpol(x)); setvarn(z,varn(x)); return z; } /*******************************************************************/ /* */ /* DIVISION */ /* */ /*******************************************************************/ GEN RgX_Rg_divexact(GEN x, GEN y) { long i, lx; GEN z; if (typ(y) == t_INT && is_pm1(y)) return signe(y) < 0 ? RgX_neg(x): RgX_copy(x); z = cgetg_copy(x, &lx); z[1] = x[1]; for (i=2; i1; i--) /* z[i] = a[i+1] + x*z[i+1] */ { GEN t = gadd(gel(a0--,0), gmul(x, gel(z0--,0))); gel(z0,0) = t; } if (r) *r = gadd(gel(a0,0), gmul(x, gel(z0,0))); return z; } /* Polynomial division x / y: * if z = ONLY_REM return remainder, otherwise return quotient * if z != NULL set *z to remainder * *z is the last object on stack (and thus can be disposed of with cgiv * instead of gerepile) */ /* assume, typ(x) = typ(y) = t_POL, same variable */ GEN RgX_divrem(GEN x, GEN y, GEN *pr) { pari_sp avy, av, av1; long dx,dy,dz,i,j,sx,lr; GEN z,p1,p2,rem,y_lead,mod; GEN (*f)(GEN,GEN); if (!signe(y)) pari_err_INV("RgX_divrem",y); dy = degpol(y); y_lead = gel(y,dy+2); if (gequal0(y_lead)) /* normalize denominator if leading term is 0 */ { pari_warn(warner,"normalizing a polynomial with 0 leading term"); for (dy--; dy>=0; dy--) { y_lead = gel(y,dy+2); if (!gequal0(y_lead)) break; } } if (!dy) /* y is constant */ { if (pr == ONLY_REM) return pol_0(varn(x)); z = RgX_Rg_div(x, y_lead); if (pr == ONLY_DIVIDES) return z; if (pr) *pr = pol_0(varn(x)); return z; } dx = degpol(x); if (dx < dy) { if (pr == ONLY_REM) return RgX_copy(x); if (pr == ONLY_DIVIDES) return signe(x)? NULL: pol_0(varn(x)); z = pol_0(varn(x)); if (pr) *pr = RgX_copy(x); return z; } /* x,y in R[X], y non constant */ av = avma; switch(typ(y_lead)) { case t_REAL: y_lead = ginv(y_lead); f = gmul; mod = NULL; break; case t_INTMOD: case t_POLMOD: y_lead = ginv(y_lead); f = gmul; mod = gmodulo(gen_1, gel(y_lead,1)); break; default: if (gequal1(y_lead)) y_lead = NULL; f = gdiv; mod = NULL; } if (y_lead == NULL) p2 = gel(x,dx+2); else { for(;;) { p2 = f(gel(x,dx+2),y_lead); p2 = simplify_shallow(p2); if (!isexactzero(p2) || (--dx < 0)) break; } if (dx < dy) /* leading coeff of x was in fact zero */ { if (pr == ONLY_DIVIDES) { avma = av; return (dx < 0)? pol_0(varn(x)) : NULL; } if (pr == ONLY_REM) { if (dx < 0) return gerepilecopy(av, scalarpol(p2, varn(x))); else { GEN t; avma = av; t = cgetg(dx + 3, t_POL); t[1] = x[1]; for (i = 2; i < dx + 3; i++) gel(t,i) = gcopy(gel(x,i)); return t; } } if (pr) /* cf ONLY_REM above */ { if (dx < 0) { p2 = gclone(p2); avma = av; z = pol_0(varn(x)); x = scalarpol(p2, varn(x)); gunclone(p2); } else { GEN t; avma = av; z = pol_0(varn(x)); t = cgetg(dx + 3, t_POL); t[1] = x[1]; for (i = 2; i < dx + 3; i++) gel(t,i) = gcopy(gel(x,i)); x = t; } *pr = x; } else { avma = av; z = pol_0(varn(x)); } return z; } } /* dx >= dy */ avy = avma; dz = dx-dy; z = cgetg(dz+3,t_POL); z[1] = x[1]; x += 2; z += 2; y += 2; gel(z,dz) = gcopy(p2); for (i=dx-1; i>=dy; i--) { av1=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); if (y_lead) p1 = simplify(f(p1,y_lead)); if (isrationalzero(p1)) { avma=av1; p1 = gen_0; } else p1 = avma==av1? gcopy(p1): gerepileupto(av1,p1); gel(z,i-dy) = p1; } if (!pr) return gerepileupto(av,z-2); rem = (GEN)avma; av1 = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); /* we always enter this loop at least once */ for (j=0; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); if (mod && avma==av1) p1 = gmul(p1,mod); if (!gequal0(p1)) { sx = 1; break; } /* remainder is non-zero */ if (!isexactzero(p1)) break; if (!i) break; avma=av1; } if (pr == ONLY_DIVIDES) { if (sx) { avma=av; return NULL; } avma = (pari_sp)rem; return gerepileupto(av,z-2); } lr=i+3; rem -= lr; if (avma==av1) { avma = (pari_sp)rem; p1 = gcopy(p1); } else p1 = gerepileupto((pari_sp)rem,p1); rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av1=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); if (mod && avma==av1) p1 = gmul(p1,mod); gel(rem,i) = avma==av1? gcopy(p1):gerepileupto(av1,p1); } rem -= 2; if (!sx) (void)normalizepol_lg(rem, lr); if (pr == ONLY_REM) return gerepileupto(av,rem); z -= 2; { GEN *gptr[2]; gptr[0]=&z; gptr[1]=&rem; gerepilemanysp(av,avy,gptr,2); *pr = rem; return z; } } /* x and y in (R[Y]/T)[X] (lifted), T in R[Y]. y preferably monic */ GEN RgXQX_divrem(GEN x, GEN y, GEN T, GEN *pr) { long vx, dx, dy, dz, i, j, sx, lr; pari_sp av0, av, tetpil; GEN z,p1,rem,lead; if (!signe(y)) pari_err_INV("RgXQX_divrem",y); vx = varn(x); dx = degpol(x); dy = degpol(y); if (dx < dy) { if (pr) { av0 = avma; x = RgXQX_red(x, T); if (pr == ONLY_DIVIDES) { avma=av0; return signe(x)? NULL: gen_0; } if (pr == ONLY_REM) return x; *pr = x; } return pol_0(vx); } lead = leading_term(y); if (!dy) /* y is constant */ { if (pr && pr != ONLY_DIVIDES) { if (pr == ONLY_REM) return pol_0(vx); *pr = pol_0(vx); } if (gequal1(lead)) return RgX_copy(x); av0 = avma; x = gmul(x, ginvmod(lead,T)); tetpil = avma; return gerepile(av0,tetpil,RgXQX_red(x,T)); } av0 = avma; dz = dx-dy; lead = gequal1(lead)? NULL: gclone(ginvmod(lead,T)); avma = av0; z = cgetg(dz+3,t_POL); z[1] = x[1]; x += 2; y += 2; z += 2; p1 = gel(x,dx); av = avma; gel(z,dz) = lead? gerepileupto(av, grem(gmul(p1,lead), T)): gcopy(p1); for (i=dx-1; i>=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); if (lead) p1 = gmul(grem(p1, T), lead); tetpil=avma; gel(z,i-dy) = gerepile(av,tetpil, grem(p1, T)); } if (!pr) { if (lead) gunclone(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); tetpil=avma; p1 = grem(p1, T); if (!gequal0(p1)) { sx = 1; break; } if (!i) break; avma=av; } if (pr == ONLY_DIVIDES) { if (lead) gunclone(lead); if (sx) { avma=av0; return NULL; } avma = (pari_sp)rem; return z-2; } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; p1 = gerepile((pari_sp)rem,tetpil,p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); tetpil=avma; gel(rem,i) = gerepile(av,tetpil, grem(p1, T)); } rem -= 2; if (lead) gunclone(lead); if (!sx) (void)normalizepol_lg(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } /*******************************************************************/ /* */ /* PSEUDO-DIVISION */ /* */ /*******************************************************************/ INLINE GEN rem(GEN c, GEN T) { if (T && typ(c) == t_POL && varn(c) == varn(T)) c = RgX_rem(c, T); return c; } /* x, y, are ZYX, lc(y) is an integer, T is a ZY */ int ZXQX_dvd(GEN x, GEN y, GEN T) { long dx, dy, dz, i, p, T_ismonic; pari_sp av = avma, av2, lim; GEN y_lead; if (!signe(y)) pari_err_INV("ZXQX_dvd",y); dy = degpol(y); y_lead = gel(y,dy+2); if (typ(y_lead) == t_POL) y_lead = gel(y_lead, 2); /* t_INT */ /* if monic, no point in using pseudo-division */ if (gequal1(y_lead)) return signe(RgXQX_rem(x, y, T)) == 0; T_ismonic = gequal1(leading_term(T)); dx = degpol(x); if (dx < dy) return !signe(x); (void)new_chunk(2); x = RgX_recip_shallow(x)+2; y = RgX_recip_shallow(y)+2; /* pay attention to sparse divisors */ 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); for (;;) { GEN m, x0 = gel(x,0), y0 = y_lead, cx = content(x0); x0 = gneg(x0); p--; m = gcdii(cx, y0); if (!equali1(m)) { x0 = gdiv(x0, m); y0 = diviiexact(y0, m); if (equali1(y0)) y0 = NULL; } for (i=1; i<=dy; i++) { GEN c = gel(x,i); if (y0) c = gmul(y0, c); if (gel(y,i)) c = gadd(c, gmul(x0,gel(y,i))); if (typ(c) == t_POL) c = T_ismonic ? ZX_rem(c, T): RgX_rem(c, T); gel(x,i) = c; } for ( ; i<=dx; i++) { GEN c = gel(x,i); if (y0) c = gmul(y0, c); if (typ(c) == t_POL) c = T_ismonic ? ZX_rem(c, T): RgX_rem(c, T); gel(x,i) = c; } do { x++; dx--; } while (dx >= 0 && !signe(gel(x,0))); if (dx < dy) break; if (low_stack(lim,stack_lim(av2,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ZXQX_dvd dx = %ld >= %ld",dx,dy); gerepilecoeffs(av2,x,dx+1); } } avma = av; return (dx < 0); } /* T either NULL or a t_POL. */ 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; GEN y_lead; if (!signe(y)) pari_err_INV("RgXQX_pseudorem",y); dy = degpol(y); y_lead = gel(y,dy+2); /* if monic, no point in using pseudo-division */ if (gequal1(y_lead)) return T? RgXQX_rem(x, y, T): RgX_rem(x, y); dx = degpol(x); if (dx < dy) return RgX_copy(x); (void)new_chunk(2); x = RgX_recip_shallow(x)+2; y = RgX_recip_shallow(y)+2; /* pay attention to sparse divisors */ 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); for (;;) { gel(x,0) = gneg(gel(x,0)); p--; for (i=1; i<=dy; i++) { GEN c = gmul(y_lead, gel(x,i)); if (gel(y,i)) c = gadd(c, gmul(gel(x,0),gel(y,i))); gel(x,i) = rem(c, T); } for ( ; i<=dx; i++) { GEN c = gmul(y_lead, gel(x,i)); gel(x,i) = rem(c, T); } do { x++; dx--; } while (dx >= 0 && gequal0(gel(x,0))); if (dx < dy) break; if (low_stack(lim,stack_lim(av2,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudorem dx = %ld >= %ld",dx,dy); gerepilecoeffs(av2,x,dx+1); } } if (dx < 0) return pol_0(vx); lx = dx+3; x -= 2; x[0] = evaltyp(t_POL) | evallg(lx); x[1] = evalsigne(1) | evalvarn(vx); x = RgX_recip_shallow(x); if (p) { /* multiply by y[0]^p [beware dummy vars from FpX_FpXY_resultant] */ GEN t = y_lead; if (T && typ(t) == t_POL && varn(t) == varn(T)) t = RgXQ_powu(t, p, T); else t = gpowgs(t, p); for (i=2; i= dy && gequal0(gel(x,0))) { x++; dx--; iz++; } if (dx < dy) break; if (low_stack(lim,stack_lim(av2,1))) { GEN X = x-2; if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudodivrem dx=%ld >= %ld",dx,dy); X[0] = evaltyp(t_POL)|evallg(dx+3); X[1] = z[1]; /* hack */ gerepileall(av2,2, &X, &z); x = X+2; } } while (dx >= 0 && gequal0(gel(x,0))) { x++; dx--; } if (dx < 0) x = pol_0(vx); else { lx = dx+3; x -= 2; x[0] = evaltyp(t_POL) | evallg(lx); x[1] = evalsigne(1) | evalvarn(vx); x = RgX_recip_shallow(x); } z = RgX_recip_shallow(z); r = x; if (p) { GEN c = gel(ypow,p); r = RgX_Rg_mul(r, c); if (T && typ(c) == t_POL && varn(c) == varn(T)) r = RgXQX_red(r, T); } gerepileall(av, 2, &z, &r); *ptr = r; return z; } GEN RgX_pseudodivrem(GEN x, GEN y, GEN *ptr) { return RgXQX_pseudodivrem(x,y,NULL,ptr); } GEN RgXQX_mul(GEN x, GEN y, GEN T) { return RgXQX_red(RgX_mul(x,y), T); } GEN RgX_Rg_mul(GEN y, GEN x) { long i, ly; GEN z = cgetg_copy(y, &ly); z[1] = y[1]; if (ly == 2) return z; for (i = 2; i < ly; i++) gel(z,i) = gmul(x,gel(y,i)); return normalizepol_lg(z,ly); } GEN RgX_muls(GEN y, long x) { long i, ly; GEN z = cgetg_copy(y, &ly); z[1] = y[1]; if (ly == 2) return z; for (i = 2; i < ly; i++) gel(z,i) = gmulsg(x,gel(y,i)); return normalizepol_lg(z,ly); } GEN RgXQX_RgXQ_mul(GEN x, GEN y, GEN T) { return RgXQX_red(RgX_Rg_mul(x,y), T); } GEN RgXQX_sqr(GEN x, GEN T) { return RgXQX_red(RgX_sqr(x), T); } static GEN _add(void *data, GEN x, GEN y) { (void)data; return RgX_add(x, y); } static GEN _sqr(void *data, GEN x) { return RgXQ_sqr(x, (GEN)data); } static GEN _mul(void *data, GEN x, GEN y) { return RgXQ_mul(x,y, (GEN)data); } static GEN _cmul(void *data, GEN P, long a, GEN x) { (void)data; return RgX_Rg_mul(x,gel(P,a+2)); } static GEN _one(void *data) { return pol_1(varn((GEN)data)); } static GEN _zero(void *data) { return pol_0(varn((GEN)data)); } static GEN _red(void *data, GEN x) { (void)data; return gcopy(x); } static struct bb_algebra RgXQ_algebra = { _red,_add,_mul,_sqr,_one,_zero }; GEN RgX_RgXQV_eval(GEN Q, GEN x, GEN T) { return gen_bkeval_powers(Q,degpol(Q),x,(void*)T,&RgXQ_algebra,_cmul); } GEN RgX_RgXQ_eval(GEN Q, GEN x, GEN T) { int use_sqr = (degpol(x)<<1) >= degpol(T); return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)T,&RgXQ_algebra,_cmul); } /* mod X^n */ struct modXn { long v; /* varn(X) */ long n; } ; static GEN _sqrXn(void *data, GEN x) { struct modXn *S = (struct modXn*)data; return RgX_sqrlow(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); } static GEN _oneXn(void *data) { struct modXn *S = (struct modXn*)data; return pol_1(S->v); } static GEN _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 }; /* Q(x) mod t^n, x in R[t], n >= 1 */ GEN RgX_modXn_eval(GEN Q, GEN x, long n) { long d = degpol(x); int use_sqr; struct modXn S; if (d == 1 && isrationalzero(gel(x,2))) { GEN y = RgX_unscale(Q, gel(x,3)); setvarn(y, varn(x)); return y; } 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); } /* x,T in Rg[X], n in N, compute lift(x^n mod T)) */ GEN RgXQ_powu(GEN x, ulong n, GEN T) { pari_sp av; GEN y; if (!n) return pol_1(varn(x)); if (n == 1) return RgX_copy(x); av = avma; y = gen_powu(x, n, (void*)T, &_sqr, &_mul); return gerepileupto(av, y); } /* x,T in Rg[X], n in N, compute lift(x^n mod T)) */ GEN RgXQ_pow(GEN x, GEN n, GEN T) { pari_sp av; long s = signe(n); GEN y; if (!s) return pol_1(varn(x)); if (is_pm1(n) == 1) return (s < 0)? RgXQ_inv(x, T): RgX_copy(x); av = avma; if (s < 0) x = RgXQ_inv(x, T); y = gen_pow(x, n, (void*)T, &_sqr, &_mul); return gerepileupto(av, y); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN RgXQ_powers(GEN x, long l, GEN T) { int use_sqr = (degpol(x)<<1) >= degpol(T); return gen_powers(x, l, use_sqr, (void *)T,_sqr,_mul,_one); } /* a in K = Q[X]/(T), returns [a^0, ..., a^n] */ GEN QXQ_powers(GEN a, long n, GEN T) { GEN den, v = RgXQ_powers(Q_remove_denom(a, &den), n, T); /* den*a integral; v[i+1] = (den*a)^i in K */ if (den) { /* restore denominators */ GEN d = den; long i; gel(v,2) = a; for (i=3; i<=n+1; i++) { d = mulii(d,den); gel(v,i) = RgX_Rg_div(gel(v,i), d); } } return v; } static GEN do_QXQ_eval(GEN v, long imin, GEN a, GEN T) { long l, i, m = degpol(T); GEN dz, z = Q_remove_denom(QXQ_powers(a, m-1, T), &dz); GEN V = cgetg_copy(v, &l); for (i = 1; i < imin; i++) V[i] = v[i]; for (i = imin; i < l; i++) { GEN c = gel(v,i); if (typ(c) == t_POL) c = QX_ZXQV_eval(c, z, dz); gel(V,i) = c; } return V; } /* [ s(a mod T) | s <- lift(v) ], a,T are QX, v a QXV */ GEN QXV_QXQ_eval(GEN v, GEN a, GEN T) { return do_QXQ_eval(v, 1, a, T); } GEN QXX_QXQ_eval(GEN v, GEN a, GEN T) { return normalizepol(do_QXQ_eval(v, 2, a, T)); } GEN RgXQ_matrix_pow(GEN y, long n, long m, GEN P) { return RgXV_to_RgM(RgXQ_powers(y,m-1,P),n); } GEN RgXQ_minpoly_naive(GEN y, GEN P) { pari_sp ltop=avma; long n=lgpol(P); GEN M=ker(RgXQ_matrix_pow(y,n,n,P)); M=content(RgM_to_RgXV(M,varn(P))); return gerepileupto(ltop,M); } GEN RgXQ_norm(GEN x, GEN T) { pari_sp av; long dx = degpol(x); GEN L, y; av = avma; y = resultant(T, x); L = leading_term(T); if (gequal1(L) || !signe(x)) return y; return gerepileupto(av, gdiv(y, gpowgs(L, dx))); } GEN RgX_blocks(GEN P, long n, long m) { GEN z = cgetg(m+1,t_VEC); long i,j, k=2, l = lg(P); for(i=1; i<=m; i++) { GEN zi = cgetg(n+2,t_POL); zi[1] = P[1]; gel(z,i) = zi; for(j=2; j>1)+1; n1 = n+1 - n0; /* n1 <= n0 <= n1+1 */ p0 = cgetg(n0+2, t_POL); p0[1] = evalvarn(v)|evalsigne(1); p1 = cgetg(n1+2, t_POL); p1[1] = evalvarn(v)|evalsigne(1); for (i=0; i=0 instead. */ /***********************************************************************/ /** **/ /** Conversion from Flx **/ /** **/ /***********************************************************************/ GEN Flx_to_ZX(GEN z) { long i, l = lg(z); GEN x = cgetg(l,t_POL); for (i=2; i1; i--) if (x[i]) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); return x; } GEN Flx_red(GEN z, ulong p) { long i, l = lg(z); GEN x = cgetg(l, t_VECSMALL); x[1] = z[1]; for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz, t_VECSMALL) + 2; for (i=0; ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (i=2; i=0 and a\x^(-n) if n<0 */ GEN Flx_shift(GEN a, long n) { long i, l = lg(a); GEN b; if (l==2 || !n) return Flx_copy(a); if (l+n<=2) return pol0_Flx(a[1]); b = cgetg(l+n, t_VECSMALL); b[1] = a[1]; if (n < 0) for (i=2-n; i 0, x > 0 and y >= 0 */ static GEN Flx_addshift(GEN x, GEN y, ulong p, long d) { GEN xd,yd,zd = (GEN)avma; long a,lz,ny = lgpol(y), nx = lgpol(x); long vs = x[1]; x += 2; y += 2; a = ny-d; if (a <= 0) { lz = (a>nx)? ny+2: nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) *--zd = *--xd; x = zd + a; while (zd > x) *--zd = 0; } else { xd = new_chunk(d); yd = y+d; x = Flx_addspec(x,yd,p, nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) *--zd = *--yd; *--zd = vs; *--zd = evaltyp(t_VECSMALL) | evallg(lz); return zd; } /* shift polynomial + gerepile */ /* Do not set evalvarn*/ static GEN Flx_shiftip(pari_sp av, GEN x, long v) { long i, lx = lg(x), ly; GEN y; if (!v || lx==2) return gerepileuptoleaf(av, x); ly = lx + v; /* result length */ (void)new_chunk(ly); /* check that result fits */ x += lx; y = (GEN)av; for (i = 2; i= ny > 0 */ static GEN Flx_mulspec_basecase(GEN x, GEN y, ulong p, long nx, long ny) { long i,lz,nz; GEN z; lz = nx+ny+1; nz = lz-2; z = cgetg(lz, t_VECSMALL) + 2; /* x:y:z [i] = term of degree i */ if (SMALL_ULONG(p)) { for (i=0; i>1UL; GEN V = cgetipos(2+n); GEN w; for (w = int_LSW(V), j=0; j+1=Flx_MUL_HALFMULII_LIMIT) return Flx_shiftip(av,Flx_mulspec_halfmulii(a,b,p,na,nb), v); break; case 1: if (na>=Flx_MUL_MULII_LIMIT) return Flx_shiftip(av,Flx_mulspec_mulii(a,b,p,na,nb), v); break; case 2: if (na>=Flx_MUL_MULII2_LIMIT) return Flx_shiftip(av,Flx_mulspec_mulii_inflate(a,b,2,p,na,nb), v); break; case 3: if (na>70) return Flx_shiftip(av,Flx_mulspec_mulii_inflate(a,b,3,p,na,nb), v); break; } if (nb < Flx_MUL_KARATSUBA_LIMIT) return Flx_shiftip(av,Flx_mulspec_basecase(a,b,p,na,nb), v); i=(na>>1); n0=na-i; na=i; a0=a+n0; n0a=n0; while (n0a && !a[n0a-1]) n0a--; if (nb > n0) { GEN b0,c1,c2; long n0b; nb -= n0; b0 = b+n0; n0b = n0; while (n0b && !b[n0b-1]) n0b--; c = Flx_mulspec(a,b,p,n0a,n0b); c0 = Flx_mulspec(a0,b0,p,na,nb); c2 = Flx_addspec(a0,a,p,na,n0a); c1 = Flx_addspec(b0,b,p,nb,n0b); c1 = Flx_mul(c1,c2,p); c2 = Flx_add(c0,c,p); c2 = Flx_neg_inplace(c2,p); c2 = Flx_add(c1,c2,p); c0 = Flx_addshift(c0,c2 ,p, n0); } else { c = Flx_mulspec(a,b,p,n0a,nb); c0 = Flx_mulspec(a0,b,p,na,nb); } c0 = Flx_addshift(c0,c,p,n0); return Flx_shiftip(av,c0, v); } GEN Flx_mul(GEN x, GEN y, ulong p) { GEN z = Flx_mulspec(x+2,y+2,p, lgpol(x),lgpol(y)); z[1] = x[1]; return z; } static GEN Flx_sqrspec_basecase(GEN x, ulong p, long nx) { long i, lz, nz; ulong p1; GEN z; if (!nx) return pol0_Flx(0); lz = (nx << 1) + 1, nz = lz-2; z = cgetg(lz, t_VECSMALL) + 2; if (SMALL_ULONG(p)) { z[0] = x[0]*x[0]%p; for (i=1; i>1); p1 <<= 1; if ((i&1) == 0) p1 += x[i>>1] * x[i>>1]; z[i] = p1 % p; } for ( ; i>1); p1 <<= 1; if ((i&1) == 0) p1 += x[i>>1] * x[i>>1]; z[i] = p1 % p; } } else { z[0] = Fl_sqr(x[0], p); for (i=1; i>1); p1 = Fl_add(p1, p1, p); if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr(x[i>>1], p), p); z[i] = p1; } for ( ; i>1); p1 = Fl_add(p1, p1, p); if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr(x[i>>1], p), p); z[i] = p1; } } z -= 2; return Flx_renormalize(z, lz); } static GEN Flx_sqrspec_sqri(GEN a, ulong p, long na) { GEN z=sqrispec(a,na); return int_to_Flx(z,p); } static GEN Flx_sqrspec_halfsqri(GEN a, ulong p, long na) { GEN z = sqri(Flx_to_int_halfspec(a,na)); return int_to_Flx_half(z,p); } static GEN Flx_sqrspec_sqri_inflate(GEN x, long N, ulong p, long nx) { pari_sp av = avma; GEN z = sqri(Flx_eval2BILspec(x,N,nx)); return gerepileupto(av, Z_mod2BIL_Flx(z, N, (nx-1)*2, p)); } static GEN Flx_sqrspec(GEN a, ulong p, long na) { GEN a0, c, c0; long n0, n0a, i, v = 0; pari_sp av; while (na && !a[0]) { a++; na--; v += 2; } if (!na) return pol0_Flx(0); av = avma; switch(maxlengthcoeffpol(p,na)) { case 0: if (na>=Flx_SQR_HALFSQRI_LIMIT) return Flx_shiftip(av, Flx_sqrspec_halfsqri(a,p,na), v); break; case 1: if (na>=Flx_SQR_SQRI_LIMIT) return Flx_shiftip(av, Flx_sqrspec_sqri(a,p,na), v); break; case 2: if (na>=Flx_SQR_SQRI2_LIMIT) return Flx_shiftip(av, Flx_sqrspec_sqri_inflate(a,2,p,na), v); break; case 3: if (na>70) return Flx_shiftip(av, Flx_sqrspec_sqri_inflate(a,3,p,na), v); break; } if (na < Flx_SQR_KARATSUBA_LIMIT) return Flx_shiftip(av, Flx_sqrspec_basecase(a,p,na), v); i=(na>>1); n0=na-i; na=i; a0=a+n0; n0a=n0; while (n0a && !a[n0a-1]) n0a--; c = Flx_sqrspec(a,p,n0a); c0= Flx_sqrspec(a0,p,na); if (p == 2) n0 *= 2; else { GEN c1, t = Flx_addspec(a0,a,p,na,n0a); t = Flx_sqr(t,p); c1= Flx_add(c0,c, p); c1= Flx_sub(t, c1, p); c0 = Flx_addshift(c0,c1,p,n0); } c0 = Flx_addshift(c0,c,p,n0); return Flx_shiftip(av,c0,v); } GEN Flx_sqr(GEN x, ulong p) { GEN z = Flx_sqrspec(x+2,p, lgpol(x)); z[1] = x[1]; return z; } GEN Flx_pow(GEN x, long n, ulong p) { GEN y = pol1_Flx(x[1]), z; long m; if (n == 0) return y; m = n; z = x; for (;;) { if (m&1) y = Flx_mul(y,z, p); m >>= 1; if (!m) return y; z = Flx_sqr(z, p); } } static GEN Flx_recipspec(GEN x, long l, long n) { long i; GEN z=cgetg(n+2,t_VECSMALL)+2; for(i=0; i=0; i--) if (x[i]) break; return i+1; } static GEN Flx_invBarrett_Newton(GEN T, ulong p) { long nold, lx, lz, lq, l = degpol(T), lQ; GEN q, y, z, x = zero_zv(l+1) + 2; ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ pari_sp av; y = T+2; q = Flx_recipspec(y,l+1,l+1); lQ = lgpol(q); q+=2; av = avma; /* We work on _spec_ Flx's, all the l[xzq12] below are lgpol's */ /* initialize */ x[0] = Fl_inv(q[0], p); if (lQ>1 && q[1]) { ulong u = q[1]; if (x[0] != 1) u = Fl_mul(u, Fl_sqr(x[0],p), p); x[1] = p - u; lx = 2; } else lx = 1; nold = 1; for (; mask > 1; avma = av) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = Flx_lgrenormalizespec(q, minss(lQ, lnew)); z = Flx_mulspec(x, q, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (z[i]) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = Flx_lgrenormalizespec (z+i, lz-i); z = Flx_mulspec(x, z+i, p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = Flx_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) y[i] = Fl_neg(z[i], p); } x -= 2; setlg(x, lx + 2); x[1] = T[1]; return x; } /* x/polrecip(T)+O(x^deg(T)) */ GEN Flx_invBarrett(GEN T, ulong p) { pari_sp ltop=avma; long l=lg(T); GEN r; if (l<5) return pol0_Flx(T[1]); if (l<=Flx_INVBARRETT_LIMIT) { ulong c = T[l-1]; if (c!=1) { ulong ci = Fl_inv(c,p); T=Flx_Fl_mul(T, ci, p); r=Flx_invBarrett_basecase(T,p); r=Flx_Fl_mul(r,ci,p); } else r=Flx_invBarrett_basecase(T,p); } else r = Flx_invBarrett_Newton(T,p); return gerepileuptoleaf(ltop, r); } 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; } /* separate from Flx_divrem for maximal speed. */ static GEN Flx_rem_basecase(GEN x, GEN y, ulong p) { pari_sp av; GEN z, c; long dx,dy,dz,i,j; ulong p1,inv; long vs=x[1]; dy = degpol(y); if (!dy) return pol0_Flx(x[1]); dx = degpol(x); dz = dx-dy; if (dz < 0) return Flx_copy(x); x += 2; y += 2; inv = y[dy]; if (inv != 1UL) inv = Fl_inv(inv,p); c = cgetg(dy+3, t_VECSMALL); c[1]=vs; c += 2; av=avma; z = cgetg(dz+3, t_VECSMALL); z[1]=vs; z += 2; if (SMALL_ULONG(p)) { z[dz] = (inv*x[dx]) % p; 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 += z[j]*y[i-j]; if (p1 & HIGHBIT) p1 %= p; } p1 %= p; z[i-dy] = p1? ((p - p1)*inv) % p: 0; } for (i=0; 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; } for (i=0; i=0 && !c[i]) i--; avma=av; return Flx_renormalize(c-2, i+3); } /* as FpX_divrem but working only on ulong types. * if relevant, *pr is the last object on stack */ static GEN Flx_divrem_basecase(GEN x, GEN y, ulong p, GEN *pr) { GEN z,q,c; long dx,dy,dz,i,j; ulong p1,inv; long sv=x[1]; dy = degpol(y); if (dy<0) pari_err_INV("Flx_divrem",y); if (pr == ONLY_REM) return Flx_rem_basecase(x, y, p); if (!dy) { if (pr && pr != ONLY_DIVIDES) *pr = pol0_Flx(sv); if (y[2] == 1UL) return Flx_copy(x); return Flx_Fl_mul(x, Fl_inv(y[2], p), p); } dx = degpol(x); dz = dx-dy; if (dz < 0) { q = pol0_Flx(sv); if (pr && pr != ONLY_DIVIDES) *pr = Flx_copy(x); return q; } x += 2; y += 2; z = cgetg(dz + 3, t_VECSMALL); z[1] = sv; z += 2; inv = (ulong)y[dy]; if (inv != 1UL) inv = Fl_inv(inv,p); if (SMALL_ULONG(p)) { z[dz] = (inv*x[dx]) % p; 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 += z[j]*y[i-j]; if (p1 & HIGHBIT) p1 %= p; } p1 %= p; z[i-dy] = p1? (long) ((p - p1)*inv) % p: 0; } } else { 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]; 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; } } q = Flx_renormalize(z-2, dz+3); if (!pr) return q; c = cgetg(dy + 3, t_VECSMALL); c[1] = sv; c += 2; if (SMALL_ULONG(p)) { for (i=0; i=0 && !c[i]) i--; c = Flx_renormalize(c-2, i+3); if (pr == ONLY_DIVIDES) { if (lg(c) != 2) return NULL; } else *pr = c; return q; } /* Compute x mod T where 2 <= degpol(T) <= l+1 <= 2*(degpol(T)-1) * and mg is the Barrett inverse of T. */ static GEN Flx_divrem_Barrettspec(GEN x, long l, GEN mg, GEN T, ulong p, GEN *pr) { GEN q, r; long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = Flx_lgrenormalizespec(T+2,lt); lmg = Flx_lgrenormalizespec(mg+2,lm); q = Flx_recipspec(x+lt,ld,ld); /* q = rec(x) lz<=ld*/ q = Flx_mulspec(q+2,mg+2,p,lgpol(q),lmg); /* q = rec(x) * mg lz<=ld+lm*/ q = Flx_recipspec(q+2,minss(ld,lgpol(q)),ld);/* q = rec (rec(x) * mg) lz<=ld*/ if (!pr) return q; r = Flx_mulspec(q+2,T+2,p,lgpol(q),lT); /* r = q*pol lz<=ld+lt*/ r = Flx_subspec(x,r+2,p,lt,minss(lt,lgpol(r)));/* r = x - q*pol lz<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN Flx_divrem_Barrett_noGC(GEN x, GEN mg, GEN T, ulong p, GEN *pr) { long l = lgpol(x), lt = degpol(T), lm = 2*lt-1; GEN q = NULL, r; long i; if (l <= lt) { if (pr == ONLY_REM) return Flx_copy(x); if (pr == ONLY_DIVIDES) return lgpol(x)? NULL: pol0_Flx(x[1]); if (pr) *pr = Flx_copy(x); return pol0_Flx(x[1]); } if (lt <= 1) return Flx_divrem_basecase(x,T,p,pr); if (pr != ONLY_REM && l>lm) q = zero_zv(l-lt+1); r = Flx_copy(x); while (l>lm) { GEN zr, zq = Flx_divrem_Barrettspec(r+2+l-lm,lm,mg,T,p,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) { GEN zq = Flx_divrem_Barrettspec(r+2,l,mg,T,p,&r); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i lt) r = Flx_divrem_Barrettspec(r+2,l,mg,T,p,ONLY_REM); else r = Flx_renormalize(r, l+2); r[1] = x[1]; return Flx_renormalize(r, lg(r)); } if (pr) { r[1] = x[1]; r = Flx_renormalize(r, lg(r)); } q[1] = x[1]; q = Flx_renormalize(q, lg(q)); if (pr == ONLY_DIVIDES) return lgpol(r)? NULL: q; if (pr) *pr = r; return q; } GEN Flx_divrem(GEN x, GEN T, ulong p, GEN *pr) { GEN B, y = get_Flx_red(T, &B); long dy = degpol(y), dx = degpol(x), d = dx-dy; if (pr==ONLY_REM) return Flx_rem(x, y, p); if (!B && d+3 < Flx_DIVREM_BARRETT_LIMIT) return Flx_divrem_basecase(x,y,p,pr); else { pari_sp av=avma; GEN mg = B? B: Flx_invBarrett(y, p); GEN q1 = Flx_divrem_Barrett_noGC(x,mg,y,p,pr); if (!q1) {avma=av; return NULL;} if (!pr || pr==ONLY_DIVIDES) return gerepileuptoleaf(av, q1); gerepileall(av,2,&q1,pr); return q1; } } GEN Flx_rem(GEN x, GEN T, ulong p) { GEN B, y = get_Flx_red(T, &B); long dy = degpol(y), dx = degpol(x), d = dx-dy; if (d < 0) return Flx_copy(x); if (!B && d+3 < Flx_REM_BARRETT_LIMIT) return Flx_rem_basecase(x,y,p); else { pari_sp av=avma; GEN mg = B ? B: Flx_invBarrett(y, p); GEN r = Flx_divrem_Barrett_noGC(x, mg, y, p, ONLY_REM); return gerepileuptoleaf(av, r); } } /* reduce T mod (X^n - 1, p). Shallow function */ GEN Flx_mod_Xnm1(GEN T, ulong n, ulong p) { long i, j, L = lg(T), l = n+2; GEN S; if (L <= l || n & ~LGBITS) return T; S = cgetg(l, t_VECSMALL); S[1] = T[1]; for (i = 2; i < l; i++) S[i] = T[i]; for (j = 2; i < L; i++) { S[j] = Fl_add(S[j], T[i], p); if (++j == l) j = 2; } return Flx_renormalize(S, l); } /* reduce T mod (X^n + 1, p). Shallow function */ GEN Flx_mod_Xn1(GEN T, ulong n, ulong p) { long i, j, L = lg(T), l = n+2; GEN S; if (L <= l || n & ~LGBITS) return T; S = cgetg(l, t_VECSMALL); S[1] = T[1]; for (i = 2; i < l; i++) S[i] = T[i]; for (j = 2; i < L; i++) { S[j] = Fl_sub(S[j], T[i], p); if (++j == l) j = 2; } return Flx_renormalize(S, l); } long Flx_val(GEN x) { long i, l=lg(x); if (l==2) return LONG_MAX; for (i=2; i>1; u1 = v = pol0_Flx(vx); u = v1 = pol1_Flx(vx); while (lgpol(b)>n) { GEN r, q = Flx_divrem(a,b,p, &r); 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 (DEBUGMEM>1) pari_warn(warnmem,"Flx_halfgcd (d = %ld)",degpol(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } return gerepilecopy(av, mkmat2(mkcol2(u,u1), mkcol2(v,v1))); } /* ux + vy */ static GEN Flx_addmulmul(GEN u, GEN v, GEN x, GEN y, ulong p) { return Flx_add(Flx_mul(u,x, p), Flx_mul(v,y, p), p); } static GEN FlxM_Flx_mul2(GEN M, GEN x, GEN y, ulong p) { GEN res = cgetg(3, t_COL); gel(res, 1) = Flx_addmulmul(gcoeff(M,1,1), gcoeff(M,1,2), x, y, p); gel(res, 2) = Flx_addmulmul(gcoeff(M,2,1), gcoeff(M,2,2), x, y, p); return res; } #if 0 static GEN FlxM_mul2_old(GEN M, GEN N, ulong p) { GEN res = cgetg(3, t_MAT); gel(res, 1) = FlxM_Flx_mul2(M,gcoeff(N,1,1),gcoeff(N,2,1),p); gel(res, 2) = FlxM_Flx_mul2(M,gcoeff(N,1,2),gcoeff(N,2,2),p); return res; } #endif /* A,B are 2x2 matrices, Flx entries. Return A x B using Strassen 7M formula */ static GEN FlxM_mul2(GEN A, GEN B, ulong p) { GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2); GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2); GEN M1 = Flx_mul(Flx_add(A11,A22, p), Flx_add(B11,B22, p), p); GEN M2 = Flx_mul(Flx_add(A21,A22, p), B11, p); GEN M3 = Flx_mul(A11, Flx_sub(B12,B22, p), p); GEN M4 = Flx_mul(A22, Flx_sub(B21,B11, p), p); GEN M5 = Flx_mul(Flx_add(A11,A12, p), B22, p); GEN M6 = Flx_mul(Flx_sub(A21,A11, p), Flx_add(B11,B12, p), p); GEN M7 = Flx_mul(Flx_sub(A12,A22, p), Flx_add(B21,B22, p), p); GEN T1 = Flx_add(M1,M4, p), T2 = Flx_sub(M7,M5, p); GEN T3 = Flx_sub(M1,M2, p), T4 = Flx_add(M3,M6, p); retmkmat2(mkcol2(Flx_add(T1,T2, p), Flx_add(M2,M4, p)), mkcol2(Flx_add(M3,M5, p), Flx_add(T3,T4, p))); } /* Return [0,1;1,-q]*M */ static GEN Flx_FlxM_qmul(GEN q, GEN M, ulong p) { GEN u, v, res = cgetg(3, t_MAT); u = Flx_sub(gcoeff(M,1,1), Flx_mul(gcoeff(M,2,1), q, p), p); gel(res,1) = mkcol2(gcoeff(M,2,1), u); v = Flx_sub(gcoeff(M,1,2), Flx_mul(gcoeff(M,2,2), q, p), p); gel(res,2) = mkcol2(gcoeff(M,2,2), v); return res; } static GEN matid2_FlxM(long v) { return mkmat2(mkcol2(pol1_Flx(v),pol0_Flx(v)), mkcol2(pol0_Flx(v),pol1_Flx(v))); } static GEN Flx_halfgcd_split(GEN x, GEN y, ulong p) { pari_sp av=avma; GEN R, S, V; GEN y1, r, q; long l = lgpol(x), n = l>>1, k; if (lgpol(y)<=n) return matid2_FlxM(x[1]); R = Flx_halfgcd(Flx_shift(x,-n),Flx_shift(y,-n),p); V = FlxM_Flx_mul2(R,x,y,p); y1 = gel(V,2); if (lgpol(y1)<=n) return gerepilecopy(av, R); q = Flx_divrem(gel(V,1), y1, p, &r); k = 2*n-degpol(y1); S = Flx_halfgcd(Flx_shift(y1,-k), Flx_shift(r,-k),p); return gerepileupto(av, FlxM_mul2(S,Flx_FlxM_qmul(q,R,p),p)); } /* Return M in GL_2(Fl[X]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ static GEN Flx_halfgcd_i(GEN x, GEN y, ulong p) { if (lg(x)<=Flx_HALFGCD_LIMIT) return Flx_halfgcd_basecase(x,y,p); return Flx_halfgcd_split(x,y,p); } GEN Flx_halfgcd(GEN x, GEN y, ulong p) { pari_sp av; GEN M,q,r; long lx=lgpol(x), ly=lgpol(y); if (!lx) { long v = x[1]; retmkmat2(mkcol2(pol0_Flx(v),pol1_Flx(v)), mkcol2(pol1_Flx(v),pol0_Flx(v))); } if (ly < lx) return Flx_halfgcd_i(x,y,p); av = avma; q = Flx_divrem(y,x,p,&r); M = Flx_halfgcd_i(x,r,p); gcoeff(M,1,1) = Flx_sub(gcoeff(M,1,1), Flx_mul(q, gcoeff(M,1,2), p), p); gcoeff(M,2,1) = Flx_sub(gcoeff(M,2,1), Flx_mul(q, gcoeff(M,2,2), p), p); return gerepilecopy(av, M); } /*Do not garbage collect*/ static GEN Flx_gcd_basecase(GEN a, GEN b, ulong p) { pari_sp av = avma, lim = stack_lim(av,2); 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 (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (d = %ld)",degpol(c)); gerepileall(av,2, &a,&b); } } return iter < 2 ? Flx_copy(a) : a; } GEN Flx_gcd(GEN x, GEN y, ulong p) { pari_sp av = avma, lim = stack_lim(av,2); if (!lgpol(x)) return Flx_copy(y); while (lg(y)>Flx_GCD_LIMIT) { GEN c; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = Flx_rem(x, y, p); x = y; y = r; } 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 (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileuptoleaf(av, Flx_gcd_basecase(x,y,p)); } int Flx_is_squarefree(GEN z, ulong p) { pari_sp av = avma; GEN d = Flx_gcd(z, Flx_deriv(z,p) , p); long res= (degpol(d) == 0); avma = av; return res; } static long Flx_is_smooth_squarefree(GEN f, long r, ulong p) { pari_sp av = avma; long i; GEN sx = polx_Flx(f[1]), a = sx; for(i=1;;i++) { if (degpol(f)<=r) {avma = av; return 1;} a = Flxq_pow(Flx_rem(a,f,p),utoi(p),f,p); if (Flx_equal(a, sx)) {avma = av; return 1;} if (i==r) {avma = av; return 0;} f = Flx_div(f, Flx_gcd(Flx_sub(a,sx,p),f,p),p); } } static long Flx_is_l_pow(GEN x, ulong p) { ulong i, lx = lgpol(x); for (i=1; i1) pari_warn(warnmem,"Flx_extgcd (d = %ld)",degpol(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = Flx_div(Flx_sub(d, Flx_mul(b,v,p), p), a, p); *ptv = v; return d; } static GEN Flx_extgcd_halfgcd(GEN x, GEN y, ulong p, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN u,v,R = matid2_FlxM(x[1]); while (lg(y)>Flx_EXTGCD_LIMIT) { GEN M, c; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = Flx_divrem(x, y, p, &r); x = y; y = r; R = Flx_FlxM_qmul(q, R, p); } M = Flx_halfgcd(x,y, p); c = FlxM_Flx_mul2(M, x,y, p); R = FlxM_mul2(M, R, p); x = gel(c,1); y = gel(c,2); gerepileall(av,3,&x,&y,&R); } y = Flx_extgcd_basecase(x,y,p,&u,&v); if (ptu) *ptu = Flx_addmulmul(u,v,gcoeff(R,1,1),gcoeff(R,2,1),p); *ptv = Flx_addmulmul(u,v,gcoeff(R,1,2),gcoeff(R,2,2),p); return y; } /* x and y in Z[X], return lift(gcd(x mod p, y mod p)). Set u and v st * ux + vy = gcd (mod p) */ GEN Flx_extgcd(GEN x, GEN y, ulong p, GEN *ptu, GEN *ptv) { GEN d; pari_sp ltop=avma; if (lg(y)>Flx_EXTGCD_LIMIT) d = Flx_extgcd_halfgcd(x, y, p, ptu, ptv); else d = Flx_extgcd_basecase(x, y, p, ptu, ptv); gerepileall(ltop,ptu?3:2,&d,ptv,ptu); return d; } ulong Flx_resultant(GEN a, GEN b, ulong p) { long da,db,dc,cnt; ulong lb, res = 1UL; pari_sp av; GEN c; if (lgpol(a)==0 || lgpol(b)==0) return 0; da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); if (both_odd(da,db)) res = p-res; } else if (!da) return 1; /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ cnt = 0; av = avma; while (db) { lb = b[db+2]; c = Flx_rem(a,b, p); a = b; b = c; dc = degpol(c); if (dc < 0) { avma = av; return 0; } if (both_odd(da,db)) res = p - res; if (lb != 1) res = Fl_mul(res, Fl_powu(lb, da - dc, p), p); if (++cnt == 100) { cnt = 0; gerepileall(av, 2, &a, &b); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } avma = av; return Fl_mul(res, Fl_powu(b[2], da, p), p); } /* If resultant is 0, *ptU and *ptU are not set */ ulong Flx_extresultant(GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV) { GEN z,q,u,v, x = a, y = b; ulong lb, res = 1UL; pari_sp av = avma; long dx, dy, dz; long vs=a[1]; dx = degpol(x); dy = degpol(y); if (dy > dx) { swap(x,y); lswap(dx,dy); pswap(ptU, ptV); a = x; b = y; if (both_odd(dx,dy)) res = p-res; } /* dx <= dy */ if (dx < 0) return 0; u = pol0_Flx(vs); v = pol1_Flx(vs); /* v = 1 */ while (dy) { /* b u = x (a), b v = y (a) */ lb = y[dy+2]; q = Flx_divrem(x,y, p, &z); x = y; y = z; /* (x,y) = (y, x - q y) */ dz = degpol(z); if (dz < 0) { avma = av; return 0; } z = Flx_sub(u, Flx_mul(q,v, p), p); u = v; v = z; /* (u,v) = (v, u - q v) */ if (both_odd(dx,dy)) res = p - res; if (lb != 1) res = Fl_mul(res, Fl_powu(lb, dx-dz, p), p); dx = dy; /* = degpol(x) */ dy = dz; /* = degpol(y) */ } res = Fl_mul(res, Fl_powu(y[2], dx, p), p); lb = Fl_mul(res, Fl_inv(y[2],p), p); v = gerepileuptoleaf(av, Flx_Fl_mul(v, lb, p)); av = avma; u = Flx_sub(Fl_to_Flx(res,vs), Flx_mul(b,v,p), p); u = gerepileuptoleaf(av, Flx_div(u,a,p)); /* = (res - b v) / a */ *ptU = u; *ptV = v; return res; } ulong Flx_eval(GEN x, ulong y, ulong p) { ulong p1,r; long j, 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=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; } } 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; } static GEN _Flx_mul(void *p, GEN a, GEN b) { return Flx_mul(a,b, *(ulong*)p); } /* compute prod (x - a[i]) */ GEN Flv_roots_to_pol(GEN a, ulong p, long vs) { long i,k,lx = lg(a); GEN p1; if (lx == 1) return pol1_Flx(vs); p1 = cgetg(lx, t_VEC); for (k=1,i=1; i1; i--) /* z[i] = (a[i+1] + x*z[i+1]) % p */ { ulong t = (*a0-- + x * *z0--) % p; *z0 = (long)t; } if (rem) *rem = (*a0 + x * *z0) % p; } else { for (i=l-3; i>1; i--) { ulong t = Fl_add((ulong)*a0--, Fl_mul(x, *z0--, p), p); *z0 = (long)t; } if (rem) *rem = Fl_add((ulong)*a0, Fl_mul(x, *z0, p), p); } return z; } /* u P(X) + v P(-X) */ static GEN Flx_even_odd_comb(GEN P, ulong u, ulong v, ulong p) { long i, l = lg(P); GEN y = cgetg(l,t_VECSMALL); y[1]=P[1]; for (i=2; iT, s->p); } static GEN _Flxq_add(void *E, GEN x, GEN y) { struct _Flxq *s = (struct _Flxq *)E; return Flx_add(x,y,s->p); } static GEN _Flxq_sqr(void *data, GEN x) { struct _Flxq *D = (struct _Flxq*)data; return Flxq_sqr(x, D->T, D->p); } static GEN _Flxq_mul(void *data, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)data; return Flxq_mul(x,y, D->T, D->p); } static GEN _Flxq_one(void *data) { struct _Flxq *D = (struct _Flxq*)data; return pol1_Flx(get_Flx_var(D->T)); } static GEN _Flxq_zero(void *data) { struct _Flxq *D = (struct _Flxq*)data; return pol0_Flx(get_Flx_var(D->T)); } static GEN _Flxq_cmul(void *data, GEN P, long a, GEN x) { struct _Flxq *D = (struct _Flxq*)data; return Flx_Fl_mul(x, P[a+2], D->p); } /* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL. */ GEN Flxq_powu(GEN x, ulong n, GEN T, ulong p) { pari_sp av = avma; struct _Flxq D; GEN y; switch(n) { case 0: return pol1_Flx(T[1]); case 1: return Flx_copy(x); case 2: return Flxq_sqr(x, T, p); } D.T = Flx_get_red(T, p); D.p = p; y = gen_powu_i(x, n, (void*)&D, &_Flxq_sqr, &_Flxq_mul); return gerepileuptoleaf(av, y); } /* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL. */ GEN Flxq_pow(GEN x, GEN n, GEN T, ulong p) { pari_sp av = avma; struct _Flxq D; GEN y; long s = signe(n); if (!s) return pol1_Flx(get_Flx_var(T)); if (s < 0) x = Flxq_inv(x,T,p); if (is_pm1(n)) return s < 0 ? x : Flx_copy(x); D.T = Flx_get_red(T, p); D.p = p; y = gen_pow_i(x, n, (void*)&D, &_Flxq_sqr, &_Flxq_mul); return gerepileuptoleaf(av, y); } /* Inverse of x in Z/lZ[X]/(T) or NULL if inverse doesn't exist * not stack clean. */ GEN 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); return Flx_Fl_mul(V, iz, p); } GEN Flxq_inv(GEN x,GEN T,ulong p) { pari_sp av=avma; GEN U = Flxq_invsafe(x, T, p); if (!U) pari_err_INV("Flxq_inv",Flx_to_ZX(x)); return gerepileuptoleaf(av, U); } GEN Flxq_div(GEN x,GEN y,GEN T,ulong p) { pari_sp av = avma; return gerepileuptoleaf(av, Flxq_mul(x,Flxq_inv(y,T,p),T,p)); } GEN Flxq_powers(GEN x, long l, GEN T, ulong p) { struct _Flxq D; int use_sqr = (degpol(x)<<1) >= get_Flx_degree(T); D.T = Flx_get_red(T, p); D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_Flxq_sqr, &_Flxq_mul, &_Flxq_one); } GEN 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); } static struct bb_algebra Flxq_algebra = { _Flxq_red,_Flxq_add,_Flxq_mul,_Flxq_sqr,_Flxq_one,_Flxq_zero}; GEN Flx_FlxqV_eval(GEN Q, GEN x, GEN T, ulong p) { struct _Flxq D; D.T = Flx_get_red(T, p); D.p=p; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&D,&Flxq_algebra,_Flxq_cmul); } GEN Flx_Flxq_eval(GEN Q, GEN x, GEN T, ulong p) { int use_sqr = (degpol(x)<<1) >= get_Flx_degree(T); struct _Flxq D; D.T = Flx_get_red(T, p); D.p=p; return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&D,&Flxq_algebra,_Flxq_cmul); } static GEN Flxq_autpow_sqr(void *E, GEN x) { struct _Flxq *D = (struct _Flxq*)E; return Flx_Flxq_eval(x, x, D->T, D->p); } static GEN Flxq_autpow_mul(void *E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)E; return Flx_Flxq_eval(x, y, D->T, D->p); } GEN Flxq_autpow(GEN x, ulong n, GEN T, ulong p) { struct _Flxq D; D.T = Flx_get_red(T, p); D.p = p; if (n==0) return polx_Flx(T[1]); if (n==1) return Flx_copy(x); return gen_powu(x,n,(void*)&D,Flxq_autpow_sqr,Flxq_autpow_mul); } static GEN Flxq_autsum_mul(void *E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)E; 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 = Flxq_powers(phi2,d,D->T,D->p); GEN phi3 = Flx_FlxqV_eval(phi1,V2,D->T,D->p); GEN aphi = Flx_FlxqV_eval(a1,V2,D->T,D->p); GEN a3 = Flxq_mul(aphi,a2,D->T,D->p); return mkvec2(phi3, a3); } static GEN Flxq_autsum_sqr(void *E, GEN x) { return Flxq_autsum_mul(E, x, x); } GEN Flxq_autsum(GEN x, ulong n, GEN T, ulong p) { struct _Flxq D; D.T = Flx_get_red(T, p); D.p = p; return gen_powu(x,n,(void*)&D,Flxq_autsum_sqr,Flxq_autsum_mul); } static long bounded_order(ulong p, GEN b, long k) { long i; GEN a=modii(utoi(p),b); for(i=1;i 1) z = gel(Flxq_autsum(mkvec2(autk, z), m, T, p), 2); if (!is_pm1(u)) z = Flxq_pow(z, u, T, p); if (signe(v)) z = Flxq_mul(z, Flxq_pow(x, v, T, p), T, p); } return gerepileupto(av,signe(n)>0 ? z : Flxq_inv(z,T,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; return Flxq_pow_Frobenius(x, n, D->aut, D->T, D->p); } static GEN _Flxq_rand(void *data) { pari_sp av=avma; struct _Flxq *D = (struct _Flxq*)data; GEN z; do { avma = av; z = random_Flx(get_Flx_degree(D->T),get_Flx_var(D->T),D->p); } while (lgpol(z)==0); return z; } static GEN Flxq_easylog(void* E, GEN a, GEN g, GEN ord) { struct _Flxq *f = (struct _Flxq *)E; 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) return NULL; return Flxq_log_index(a,g,ord,f->T,f->p); } int Flx_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; while (--l > 1) /* do not compare variables, V[1] */ if (V[l] != W[l]) return 0; return 1; } static const struct bb_group Flxq_star={_Flxq_mul,_Flxq_pow,_Flxq_rand,hash_GEN,Flx_equal,Flx_equal1,Flxq_easylog}; 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); } 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); } 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); if (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); } GEN Flxq_sqrt(GEN a, GEN T, ulong p) { return Flxq_sqrtn(a, gen_2, T, p, NULL); } /* assume T irreducible mod 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; } /* assume T irreducible mod p */ int Flxq_is2npower(GEN x, long n, GEN T, ulong p) { pari_sp av; GEN m; int z; if (n==1) return Flxq_issquare(x, T, p); if (lgpol(x) == 0 || p == 2) return 1; av = avma; m = shifti(subis(powuu(p, get_Flx_degree(T)), 1), -n); z = Flx_equal1(Flxq_pow(x, m, T, p)); avma = av; return z; } GEN Flxq_lroot_fast(GEN a, GEN sqx, GEN T, long p) { pari_sp av=avma; GEN A = Flx_splitting(a,p); return gerepileuptoleaf(av, FlxqV_dotproduct(A,sqx,T,p)); } GEN 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; 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); if (d==1 && a[2]==0 && a[3]==1) return gerepileuptoleaf(av, sqx); if (d>=p) { V = Flxq_powers(sqx,p-1,T,p); return gerepileuptoleaf(av, Flxq_lroot_fast(a,V,T,p)); } else return gerepileuptoleaf(av, Flx_Flxq_eval(a,sqx,T,p)); } ulong Flxq_norm(GEN x, GEN TB, ulong p) { GEN T = get_Flx_mod(TB); ulong y = Flx_resultant(T, x, p); ulong L = Flx_lead(T); if ( L==1 || lgpol(x)==0) return y; return Fl_div(y, Fl_powu(L, (ulong)degpol(x), p), p); } ulong Flxq_trace(GEN x, GEN TB, ulong p) { pari_sp av = avma; ulong t; GEN T = get_Flx_mod(TB); long n = degpol(T)-1; GEN z = Flxq_mul(x, Flx_deriv(T, p), TB, p); t = degpol(z) 3) { ulong t; (void)u_lvalrem(p_1, 2, &t); L = gel(factoru(t),1); for (i=lg(L)-1; i; i--) L[i] = p_1 / L[i]; } o = factor_pn_1(utoipos(p),f); L2 = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(L2); i++) { if (umodui(p_1, gel(L2,i)) == 0) continue; gel(L2,j++) = diviiexact(q, gel(L2,i)); } setlg(L2, j); F = Flxq_powu(polx_Flx(evalvarn(vT)), p, T, p); /* Frobenius */ for (av = avma;; avma = av) { ulong RES; GEN tt; g = random_Flx(f, vT, p); if (degpol(g) < 1) continue; if (p == 2) tt = g; else { ulong t = Flxq_norm(g, T, p); if (t == 1 || !is_gener_Fl(t, p, p_1, L)) continue; tt = Flxq_powu(g, p_1>>1, T, p); } RES = p_1; 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 (i == j) break; } if (!po) { avma = (pari_sp)g; g = gerepileuptoleaf(av0, g); } else { *po = mkvec2(subis(powuu(p,f), 1), o); gerepileall(av0, 2, &g, po); } return g; } static GEN _Flxq_neg(void *E, GEN x) { struct _Flxq *s = (struct _Flxq *)E; return Flx_neg(x,s->p); } static GEN _Flxq_rmul(void *E, GEN x, GEN y) { struct _Flxq *s = (struct _Flxq *)E; return Flx_mul(x,y,s->p); } static GEN _Flxq_inv(void *E, GEN x) { struct _Flxq *s = (struct _Flxq *)E; return Flxq_inv(x,s->T,s->p); } static int _Flxq_equal0(GEN x) { return lgpol(x)==0; } static GEN _Flxq_s(void *E, long x) { struct _Flxq *s = (struct _Flxq *)E; ulong u = x<0 ? s->p+x: (ulong)x; return Fl_to_Flx(u, get_Flx_var(s->T)); } static const struct bb_field Flxq_field={_Flxq_red,_Flxq_add,_Flxq_rmul,_Flxq_neg, _Flxq_inv,_Flxq_equal0,_Flxq_s}; const struct bb_field *get_Flxq_field(void **E, GEN T, ulong p) { GEN z = new_chunk(sizeof(struct _Flxq)); struct _Flxq *e = (struct _Flxq *) z; e->T = Flx_get_red(T, p); e->p = p; *E = (void*)e; return &Flxq_field; } /***********************************************************************/ /** **/ /** FlxV **/ /** **/ /***********************************************************************/ /* FlxV are t_VEC with Flx coefficients. */ GEN FlxV_Flc_mul(GEN V, GEN W, ulong p) { pari_sp ltop=avma; long i; GEN z = Flx_Fl_mul(gel(V,1),W[1],p); for(i=2;i1; i--) if (lgpol(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i!=1); return x; } GEN pol1_FlxX(long v, long sv) { GEN z = cgetg(3, t_POL); z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = pol1_Flx(sv); return z; } GEN polx_FlxX(long v, long sv) { GEN z = cgetg(4, t_POL); z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = pol0_Flx(sv); gel(z,3) = pol1_Flx(sv); return z; } /*Lift coefficient of B to constant Flx, to give a FlxY*/ GEN Fly_to_FlxY(GEN B, long sv) { long lb=lg(B); long i; GEN b=cgetg(lb,t_POL); b[1]=evalsigne(1)|(((ulong)B[1])&VARNBITS); for (i=2; i N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i P(Y,X), n-1 is the degree in Y */ GEN FlxX_swap(GEN x, long n, long ws) { long j, lx = lg(x), ly = n+3; GEN y = cgetg(ly, t_POL); y[1] = x[1]; for (j=2; j= n) pari_err_BUG("zxX_to_Kronecker, P is not reduced mod Q"); for (j=2; j < l; j++) y[k++] = c[j]; if (i == lp-1) break; for ( ; j < N; j++) y[k++] = 0; } y -= 2; y[1] = P[1]; setlg(y, k+2); return y; } GEN zxX_to_Kronecker(GEN P, GEN Q) { GEN z = zxX_to_Kronecker_spec(P+2, lg(P)-2, degpol(Q)); z[1] = P[1]; return z; } GEN FlxX_add(GEN x, GEN y, ulong p) { long i,lz; GEN z; long lx=lg(x); long ly=lg(y); if (ly>lx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_POL); z[1]=x[1]; for (i=2; i= ly) { z[1] = x[1]; for (i=2; i=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = Flx_sub(p1, Flx_mul(gel(z,j),gel(y,i-j),p),p); if (lead) p1 = Flx_mul(p1, lead,p); tetpil=avma; gel(z,i-dy) = gerepile(av,tetpil,Flx_rem(p1,T,p)); } if (!pr) { if (lead) gunclone(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = Flx_sub(p1, Flx_mul(gel(z,j),gel(y,i-j),p),p); tetpil=avma; p1 = Flx_rem(p1, T, p); if (lgpol(p1)) { sx = 1; break; } if (!i) break; avma=av; } if (pr == ONLY_DIVIDES) { if (lead) gunclone(lead); if (sx) { avma=av0; return NULL; } avma = (pari_sp)rem; return z-2; } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; p1 = gerepile((pari_sp)rem,tetpil,p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = Flx_sub(p1, Flx_mul(gel(z,j),gel(y,i-j),p), p); tetpil=avma; gel(rem,i) = gerepile(av,tetpil, Flx_rem(p1, T, p)); } rem -= 2; if (lead) gunclone(lead); if (!sx) (void)FlxX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } static GEN FlxqX_invBarrett_basecase(GEN T, GEN Q, ulong p) { long i, l=lg(T)-1, lr = l-1, k; long sv=Q[1]; GEN r=cgetg(lr,t_POL); r[1]=T[1]; gel(r,2) = pol1_Flx(sv); for (i=3;i=0; i--) if (lgpol(gel(x,i))) break; return i+1; } static GEN FlxqX_invBarrett_Newton(GEN S, GEN T, ulong p) { pari_sp av = avma; long nold, lx, lz, lq, l = degpol(S), i, lQ; GEN q, y, z, x = cgetg(l+2, t_POL) + 2; long dT = get_Flx_degree(T); ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1 && degpol(gel(q,1)) >= dT) gel(q,1) = Flx_rem(gel(q,1), T, p); if (lQ>1 && lgpol(gel(q,1))) { GEN u = gel(q, 1); if (!Flx_equal1(gel(x,0))) u = Flxq_mul(u, Flxq_sqr(gel(x,0), T,p), T,p); gel(x,1) = Flx_neg(u, p); lx = 2; } else lx = 1; nold = 1; for (; mask > 1; ) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = FlxX_lgrenormalizespec(q, minss(lQ,lnew)); z = FlxqX_mulspec(x, q, T, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (lgpol(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = FlxX_lgrenormalizespec (z+i, lz-i); z = FlxqX_mulspec(x, z+i, T,p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = FlxX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Flx_neg(gel(z,i), p); } x -= 2; setlg(x, lx + 2); x[1] = S[1]; return gerepilecopy(av, x); } static const long FlxqX_INVBARRETT_LIMIT = 5; /* x/polrecip(P)+O(x^n) */ GEN FlxqX_invBarrett(GEN T, GEN Q, ulong p) { pari_sp ltop=avma; long l=lg(T), v = varn(T); GEN r; GEN c = gel(T,l-1); if (l<5) return pol_0(v); if (l<=FlxqX_INVBARRETT_LIMIT) { if (!Flx_equal1(c)) { GEN ci = Flxq_inv(c,Q,p); T = FlxqX_Flxq_mul(T, ci, Q, p); r = FlxqX_invBarrett_basecase(T,Q,p); r = FlxqX_Flxq_mul(r,ci,Q,p); } else r = FlxqX_invBarrett_basecase(T,Q,p); } else r = FlxqX_invBarrett_Newton(T,Q,p); return gerepileupto(ltop, r); } GEN FlxqX_rem_Barrett(GEN x, GEN mg, GEN T, GEN Q, ulong p) { pari_sp ltop=avma; GEN z; long vs = get_Flx_var(Q); long l=lgpol(x); long lt=degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; if (l<=lt) return gcopy(x); ld = l-lt; lm = minss(ld, lgpol(mg)); lT = FlxX_lgrenormalizespec(T+2,lt); lmg = FlxX_lgrenormalizespec(mg+2,lm); z = FlxX_recipspec(x+2+lt,ld,ld,vs); /* z = rec(x) lz<=ld*/ z = FlxqX_mulspec(z+2,mg+2,Q,p,lgpol(z),lmg); /* z = rec(x) * mg lz<=ld+lm*/ z = FlxX_recipspec(z+2,minss(ld,lgpol(z)),ld,vs);/*z= rec(rec(x)*mg) lz<=ld*/ z = FlxqX_mulspec(z+2,T+2,Q,p,lgpol(z),lT); /* z*= pol lz<=ld+lt*/ z = FlxX_subspec(x+2,z+2,p,lt,minss(lt,lgpol(z)));/*z = x - z lz<=lt */ setvarn(z,varn(x)); return gerepileupto(ltop,z); } GEN FlxqX_gcd(GEN x, GEN y, GEN T, ulong p) { GEN a,b,c; pari_sp av0, av=avma; a = FlxqX_red(x, T, p); av0 = avma; b = FlxqX_red(y, T, p); while (signe(b)) { av0 = avma; c = FlxqX_rem(a,b,T,p); a=b; b=c; } avma = av0; return gerepileupto(av, a); } GEN FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p) { pari_sp btop, ltop = avma, st_lim; GEN U; if (!signe(P)) return gcopy(Q); if (!signe(Q)) return gcopy(P); btop = avma; st_lim = stack_lim(btop, 1); for(;;) { U = Flxq_invsafe(leading_term(Q), T, p); if (!U) { avma = ltop; return NULL; } 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 (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_safegcd"); gerepileall(btop, 2, &P,&Q); } swap(P, Q); } return gerepileupto(ltop, Q); } GEN FlxqX_extgcd(GEN a, GEN b, GEN T, ulong p, GEN *ptu, GEN *ptv) { GEN q, r, u, v, d, d1, v1; long vx = varn(a); pari_sp ltop=avma; d = a; d1 = b; v = pol_0(vx); v1 = pol1_FlxX(vx,get_Flx_var(T)); while (signe(d1)) { q = FlxqX_divrem(d,d1,T,p, &r); v = FlxX_sub(v, FlxqX_mul(q,v1, T,p), p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; } if (ptu) *ptu = FlxqX_div(FlxX_sub(d, FlxqX_mul(b,v, T,p), p), a, T,p); *ptv = v; gerepileall(ltop,ptu?3:2,&d,ptv,ptu); return d; } struct _FlxqX {ulong p; GEN T;}; static GEN _FlxqX_mul(void *data,GEN a,GEN b) { struct _FlxqX *d=(struct _FlxqX*)data; return FlxqX_mul(a,b,d->T,d->p); } static GEN _FlxqX_sqr(void *data,GEN a) { struct _FlxqX *d=(struct _FlxqX*)data; return FlxqX_sqr(a,d->T,d->p); } GEN FlxqX_pow(GEN V, long n, GEN T, ulong p) { struct _FlxqX d; d.p=p; d.T=T; return gen_powu(V, n, (void*)&d, &_FlxqX_sqr, &_FlxqX_mul); } GEN FlxqXV_prod(GEN V, GEN T, ulong p) { struct _FlxqX d; d.p=p; d.T=T; return divide_conquer_assoc(V, (void*)&d, &_FlxqX_mul); } GEN FlxqV_roots_to_pol(GEN V, GEN T, ulong p, long v) { pari_sp ltop = avma; long k, sv = get_Flx_var(T); GEN W = cgetg(lg(V),t_VEC); for(k=1; k < lg(V); k++) gel(W,k) = deg1pol_shallow(pol1_Flx(sv),Flx_neg(gel(V,k),p),v); return gerepileupto(ltop, FlxqXV_prod(W, T, p)); } /*******************************************************************/ /* */ /* (Fl[X]/T(X))[Y] / S(Y) */ /* */ /*******************************************************************/ GEN FlxqXQ_mul(GEN x, GEN y, GEN S, GEN T, ulong p) { return FlxqX_rem(FlxqX_mul(x,y,T,p),S,T,p); } GEN FlxqXQ_sqr(GEN x, GEN S, GEN T, ulong p) { return FlxqX_rem(FlxqX_sqr(x,T,p),S,T,p); } GEN FlxqXQ_invsafe(GEN x, GEN S, GEN T, ulong p) { GEN V, z = FlxqX_extgcd(S, x, T, p, NULL, &V); if (degpol(z)) return NULL; z = Flxq_invsafe(gel(z,2),T,p); if (!z) return NULL; return FlxqX_Flxq_mul(V, z, T, p); } GEN FlxqXQ_inv(GEN x, GEN S, GEN T,ulong p) { pari_sp av = avma; GEN U = FlxqXQ_invsafe(x, S, T, p); if (!U) pari_err_INV("FlxqXQ_inv",x); return gerepileupto(av, U); } GEN FlxqXQ_div(GEN x, GEN y, GEN S, GEN T, ulong p) { return FlxqXQ_mul(x, FlxqXQ_inv(y,S,T,p),S,T,p); } static GEN FlxqXQ_mul_mg(GEN x,GEN y,GEN mg, GEN S, GEN T,ulong p) { GEN z = FlxqX_mul(x,y,T,p); if (lg(S) > lg(z)) return z; return FlxqX_rem_Barrett(z, mg, S, T, p); } static GEN FlxqXQ_sqr_mg(GEN y,GEN mg,GEN S, GEN T,ulong p) { GEN z = FlxqX_sqr(y,T,p); if (lg(S) > lg(z)) return z; return FlxqX_rem_Barrett(z, mg, S, T, p); } typedef struct { GEN T, S, mg; ulong p; } FlxqXQ_muldata; static GEN _FlxqXQ_add(void *data, GEN x, GEN y) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxX_add(x,y, d->p); } static GEN _FlxqXQ_cmul(void *data, GEN P, long a, GEN x) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxX_Flx_mul(x,gel(P,a+2), d->p); } static GEN _FlxqXQ_red(void *data, GEN x) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxqX_red(x, d->T, d->p); } static GEN _FlxqXQ_mul(void *data, GEN x, GEN y) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxqXQ_mul_mg(x,y, d->mg, d->S,d->T, d->p); } static GEN _FlxqXQ_sqr(void *data, GEN x) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxqXQ_sqr_mg(x, d->mg, d->S,d->T, d->p); } static GEN _FlxqXQ_one(void *data) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return pol1_FlxX(varn(d->S),d->T[1]); } static GEN _FlxqXQ_zero(void *data) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return pol_0(varn(d->S)); } static struct bb_algebra FlxqXQ_algebra = { _FlxqXQ_red,_FlxqXQ_add,_FlxqXQ_mul,_FlxqXQ_sqr,_FlxqXQ_one,_FlxqXQ_zero }; /* x over Fq, return lift(x^n) mod S */ GEN FlxqXQ_pow(GEN x, GEN n, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; long s = signe(n); if (!s) return pol1_FlxX(varn(S),get_Flx_var(T)); if (s < 0) x = FlxqXQ_inv(x,S,T,p); if (is_pm1(n)) return s < 0 ? x : gcopy(x); if (degpol(x)>=degpol(S)) x = FlxqX_rem(x,S,T,p); D.mg = FlxqX_invBarrett(S,T,p); D.S = S; D.T = T; D.p = p; return gen_pow(x, n, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul); } GEN FlxqXQ_powers(GEN x, long l, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; int use_sqr; if (degpol(x)>=degpol(S)) x = FlxqX_rem(x,S,T,p); use_sqr = (degpol(x)<<1)>=degpol(S); D.mg = FlxqX_invBarrett(S,T,p); D.S = S; D.T = T; D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul,&_FlxqXQ_one); } GEN FlxqXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, ulong p) { return FlxXV_to_FlxM(FlxqXQ_powers(y,m-1,S,T,p), n, T[1]); } GEN FlxqX_FlxqXQV_eval(GEN P, GEN V, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; D.mg = FlxqX_invBarrett(S,T,p); D.S=S; D.T=T; D.p=p; return gen_bkeval_powers(P, degpol(P), V, (void*)&D, &FlxqXQ_algebra, _FlxqXQ_cmul); } GEN FlxqX_FlxqXQ_eval(GEN Q, GEN x, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; int use_sqr = (degpol(x)<<1) >= degpol(S); D.mg = FlxqX_invBarrett(S,T,p); D.S=S; D.T=T; D.p=p; return gen_bkeval(Q, degpol(Q), x, use_sqr, (void*)&D, &FlxqXQ_algebra, _FlxqXQ_cmul); } static GEN FlxqXQ_autpow_sqr(void * T, GEN x) { FlxqXQ_muldata *D = (FlxqXQ_muldata *)T; 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); return mkvec2(phi2, S2); } static GEN FlxqXQ_autpow_mul(void * T, GEN x, GEN y) { FlxqXQ_muldata *D = (FlxqXQ_muldata *)T; 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); return mkvec2(phi3, S3); } GEN FlxqXQV_autpow(GEN aut, long n, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; D.S=S; D.T=T; D.p=p; return gen_powu(aut,n,&D,FlxqXQ_autpow_sqr,FlxqXQ_autpow_mul); } static GEN FlxqXQ_autsum_mul(void * T, GEN x, GEN y) { FlxqXQ_muldata *D = (FlxqXQ_muldata *)T; 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 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); return mkvec3(phi3, S3, a3); } static GEN FlxqXQ_autsum_sqr(void * T, GEN x) { return FlxqXQ_autsum_mul(T,x,x); } GEN FlxqXQV_autsum(GEN aut, long n, GEN S, GEN T, ulong p) { FlxqXQ_muldata D; D.S=S; D.T=T; D.p=p; return gen_powu(aut,n,&D,FlxqXQ_autsum_sqr,FlxqXQ_autsum_mul); } /*******************************************************************/ /* */ /* FlxYqQ */ /* */ /*******************************************************************/ /*Preliminary implementation to speed up FpX_ffisom*/ typedef struct { GEN S, T; ulong p; } FlxYqq_muldata; /* reduce x in Fl[X, Y] in the algebra Fl[X, Y]/ (P(X),Q(Y)) */ static GEN FlxYqq_redswap(GEN x, GEN S, GEN T, ulong p) { pari_sp ltop=avma; long n = get_Flx_degree(S); long m = get_Flx_degree(T); long w = get_Flx_var(T); GEN V = FlxX_swap(x,m,w); V = FlxqX_red(V,S,p); V = FlxX_swap(V,n,w); return gerepilecopy(ltop,V); } static GEN FlxYqq_sqr(void *data, GEN x) { FlxYqq_muldata *D = (FlxYqq_muldata*)data; return FlxYqq_redswap(FlxqX_sqr(x, D->T, D->p),D->S,D->T,D->p); } static GEN FlxYqq_mul(void *data, GEN x, GEN y) { FlxYqq_muldata *D = (FlxYqq_muldata*)data; return FlxYqq_redswap(FlxqX_mul(x,y, D->T, D->p),D->S,D->T,D->p); } /* x in Z[X,Y], S in Z[X] over Fq = Z[Y]/(p,T); compute lift(x^n mod (S,T,p)) */ GEN FlxYqq_pow(GEN x, GEN n, GEN S, GEN T, ulong p) { pari_sp av = avma; FlxYqq_muldata D; GEN y; D.S = S; D.T = T; D.p = p; y = gen_pow(x, n, (void*)&D, &FlxYqq_sqr, &FlxYqq_mul); return gerepileupto(av, y); } pari-2.7.5/src/basemath/gen3.c0000644000175000017500000030242212601623017014462 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (third part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** PRINCIPAL VARIABLE NUMBER **/ /** **/ /********************************************************************/ long gvar(GEN x) { long i, v, w, lx; switch(typ(x)) { case t_POL: case t_SER: return varn(x); case t_POLMOD: return varn(gel(x,1)); case t_RFRAC: return varn(gel(x,2)); case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; case t_LIST: x = list_data(x); lx = x? lg(x): 1; break; default: return NO_VARIABLE; } v = NO_VARIABLE; for (i=1; i < lx; i++) { w = gvar(gel(x,i)); if (varncmp(w,v) < 0) v = w; } return v; } /* T main polynomial in R[X], A auxiliary in R[X] (possibly degree 0). * Guess and return the main variable of R */ static long var2_aux(GEN T, GEN A) { long a = gvar2(T); long b = (typ(A) == t_POL && varn(A) == varn(T))? gvar2(A): gvar(A); if (varncmp(a, b) > 0) a = b; return a; } static long var2_rfrac(GEN x) { return var2_aux(gel(x,2), gel(x,1)); } static long var2_polmod(GEN x) { return var2_aux(gel(x,1), gel(x,2)); } /* main variable of x, with the convention that the "natural" main * variable of a POLMOD is mute, so we want the next one. */ static long gvar9(GEN x) { return (typ(x) == t_POLMOD)? var2_polmod(x): gvar(x); } /* main variable of the ring over wich x is defined */ long gvar2(GEN x) { long i, v, w; switch(typ(x)) { case t_POLMOD: return var2_polmod(x); case t_POL: case t_SER: v = NO_VARIABLE; for (i=2; i < lg(x); i++) { w = gvar9(gel(x,i)); if (varncmp(w,v) < 0) v=w; } return v; case t_RFRAC: return var2_rfrac(x); case t_VEC: case t_COL: case t_MAT: v = NO_VARIABLE; for (i=1; i < lg(x); i++) { w = gvar2(gel(x,i)); if (varncmp(w,v)<0) v=w; } return v; } return NO_VARIABLE; } /*******************************************************************/ /* */ /* PRECISION OF SCALAR OBJECTS */ /* */ /*******************************************************************/ static long prec0(long e) { return (e < 0)? nbits2prec(-e): 2; } static long precREAL(GEN x) { return signe(x) ? realprec(x): prec0(expo(x)); } /* x t_REAL, y an exact non-complex type. Return precision(|x| + |y|) */ static long precrealexact(GEN x, GEN y) { long lx, ey = gexpo(y), ex, e; if (ey == -(long)HIGHEXPOBIT) return precREAL(x); ex = expo(x); e = ey - ex; if (!signe(x)) return prec0((e >= 0)? -e: ex); lx = realprec(x); return (e > 0)? lx + nbits2extraprec(e): lx; } static long precCOMPLEX(GEN z) { /* ~ precision(|x| + |y|) */ GEN x = gel(z,1), y = gel(z,2); long e, ex, ey, lz, lx, ly; if (typ(x) != t_REAL) { if (typ(y) != t_REAL) return 0; return precrealexact(y, x); } if (typ(y) != t_REAL) return precrealexact(x, y); /* x, y are t_REALs, cf addrr_sign */ ex = expo(x); ey = expo(y); e = ey - ex; if (!signe(x)) { if (!signe(y)) return prec0( minss(ex,ey) ); if (e <= 0) return prec0(ex); lz = nbits2prec(e); ly = realprec(y); if (lz > ly) lz = ly; return lz; } if (!signe(y)) { if (e >= 0) return prec0(ey); lz = nbits2prec(-e); lx = realprec(x); if (lz > lx) lz = lx; return lz; } if (e < 0) { swap(x, y); e = -e; } lx = realprec(x); ly = realprec(y); if (e) { long d = nbits2extraprec(e), l = ly-d; return (l > lx)? lx + d: ly; } return minss(lx, ly); } long precision(GEN z) { switch(typ(z)) { case t_REAL: return precREAL(z); case t_COMPLEX: return precCOMPLEX(z); } return 0; } long gprecision(GEN x) { long i, k, l; switch(typ(x)) { case t_REAL: return precREAL(x); case t_COMPLEX: return precCOMPLEX(x); case t_INT: case t_INTMOD: case t_FRAC: case t_FFELT: case t_PADIC: case t_QUAD: case t_POLMOD: return 0; case t_POL: k = LONG_MAX; for (i=lg(x)-1; i>1; i--) { l = gprecision(gel(x,i)); if (l && l0; i--) { l = gprecision(gel(x,i)); if (l && l=imin; i--) { t = padicprec_relative(gel(x,i)); if (t=imin; i--) { t = padicprec(gel(x,i),p); if (t= 0, * wrt to main variable if v < 0. */ long poldegree(GEN x, long v) { const long DEGREE0 = -LONG_MAX; long tx = typ(x), lx,w,i,d; if (is_scalar_t(tx)) return gequal0(x)? DEGREE0: 0; switch(tx) { case t_POL: if (!signe(x)) return DEGREE0; w = varn(x); if (v < 0 || v == w) return degpol(x); if (varncmp(v, w) < 0) return 0; lx = lg(x); d = DEGREE0; for (i=2; i d) d = e; } return d; case t_RFRAC: if (gequal0(gel(x,1))) return DEGREE0; return poldegree(gel(x,1),v) - poldegree(gel(x,2),v); } pari_err_TYPE("degree",x); return 0; /* not reached */ } /* assume v >= 0 and x is a POLYNOMIAL in v, return deg_v(x) */ long RgX_degree(GEN x, long v) { long tx = typ(x), lx, w, i, d; if (is_scalar_t(tx)) return gequal0(x)? -1: 0; switch(tx) { case t_POL: if (!signe(x)) return -1; w = varn(x); if (v == w) return degpol(x); if (varncmp(v, w) < 0) return 0; lx = lg(x); d = -1; for (i=2; i d) d = e; } return d; case t_RFRAC: w = varn(gel(x,2)); if (varncmp(v, w) < 0) return 0; if (RgX_degree(gel(x,2),v)) pari_err_TYPE("RgX_degree", x); return RgX_degree(gel(x,1),v); } pari_err_TYPE("RgX_degree",x); return 0; /* not reached */ } long degree(GEN x) { return poldegree(x,-1); } /* If v<0, leading coeff with respect to the main variable, otherwise wrt v. */ GEN pollead(GEN x, long v) { long l, tx = typ(x), w; pari_sp av; GEN xinit; if (is_scalar_t(tx)) return gcopy(x); w = varn(x); switch(tx) { case t_POL: if (v < 0 || v == w) { 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; 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))); } /* returns 1 if there's a real component in the structure, 0 otherwise */ int isinexactreal(GEN x) { long i; switch(typ(x)) { case t_REAL: return 1; case t_COMPLEX: return (typ(gel(x,1))==t_REAL || typ(gel(x,2))==t_REAL); case t_INT: case t_INTMOD: case t_FRAC: case t_FFELT: case t_PADIC: case t_QUAD: case t_QFR: case t_QFI: return 0; case t_RFRAC: case t_POLMOD: return isinexactreal(gel(x,1)) || isinexactreal(gel(x,2)); case t_POL: case t_SER: for (i=lg(x)-1; i>1; i--) if (isinexactreal(gel(x,i))) return 1; return 0; case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (isinexactreal(gel(x,i))) return 1; return 0; default: return 0; } } /* Check if x is approximately real with precision e */ int isrealappr(GEN x, long e) { long i; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 1; case t_COMPLEX: return (gexpo(gel(x,2)) < e); case t_POL: case t_SER: for (i=lg(x)-1; i>1; i--) if (! isrealappr(gel(x,i),e)) return 0; return 1; case t_RFRAC: case t_POLMOD: return isrealappr(gel(x,1),e) && isrealappr(gel(x,2),e); case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (! isrealappr(gel(x,i),e)) return 0; return 1; default: pari_err_TYPE("isrealappr",x); return 0; } } /* returns 1 if there's an inexact component in the structure, and * 0 otherwise. */ int isinexact(GEN x) { long lx, i; switch(typ(x)) { case t_REAL: case t_PADIC: case t_SER: return 1; case t_INT: case t_INTMOD: case t_FFELT: case t_FRAC: case t_QFR: case t_QFI: return 0; case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_POLMOD: return isinexact(gel(x,1)) || isinexact(gel(x,2)); case t_POL: for (i=lg(x)-1; i>1; i--) if (isinexact(gel(x,i))) return 1; return 0; case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (isinexact(gel(x,i))) return 1; return 0; case t_LIST: x = list_data(x); lx = x? lg(x): 1; for (i=1; i 0; } pari_err_TYPE("iscomplex",x); return 0; /* not reached */ } /*******************************************************************/ /* */ /* GENERIC REMAINDER */ /* */ /*******************************************************************/ /* euclidean quotient for scalars of admissible types */ static GEN _quot(GEN x, GEN y) { GEN q = gdiv(x,y), f = gfloor(q); if (gsigne(y) < 0 && !gequal(f,q)) f = gaddgs(f, 1); return f; } /* y t_REAL, x \ y */ static GEN _quotsr(long x, GEN y) { GEN q, f; if (!x) return gen_0; q = divsr(x,y); f = floorr(q); if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } /* x t_REAL, x \ y */ static GEN _quotrs(GEN x, long y) { GEN q = divrs(x,y), f = floorr(q); if (y < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } static GEN _quotri(GEN x, GEN y) { GEN q = divri(x,y), f = floorr(q); if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } /* y t_FRAC, x \ y */ static GEN _quotsf(long x, GEN y) { return truedivii(mulis(gel(y,2),x), gel(y,1)); } /* x t_FRAC, x \ y */ static GEN _quotfs(GEN x, long y) { return truedivii(gel(x,1),mulis(gel(x,2),y)); } /* x t_FRAC, y t_INT, x \ y */ static GEN _quotfi(GEN x, GEN y) { return truedivii(gel(x,1),mulii(gel(x,2),y)); } static GEN quot(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, _quot(x, y)); } static GEN quotrs(GEN x, long y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotrs(x,y)); } static GEN quotfs(GEN x, long s) { pari_sp av = avma; return gerepileuptoleaf(av, _quotfs(x,s)); } static GEN quotsr(long x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotsr(x, y)); } static GEN quotsf(long x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotsf(x, y)); } static GEN quotfi(GEN x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotfi(x, y)); } static GEN quotri(GEN x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotri(x, y)); } static GEN modrs(GEN x, long y) { pari_sp av = avma; GEN q = _quotrs(x,y); if (!signe(q)) { avma = av; return rcopy(x); } return gerepileuptoleaf(av, subri(x, mulis(q,y))); } static GEN modsr(long x, GEN y) { pari_sp av = avma; GEN q = _quotsr(x,y); if (!signe(q)) { avma = av; return stoi(x); } return gerepileuptoleaf(av, subsr(x, mulir(q,y))); } static GEN modsf(long x, GEN y) { pari_sp av = avma; return gerepileupto(av, gred_frac2(modii(mulis(gel(y,2),x), gel(y,1)), gel(y,2))); } /* assume y a t_REAL, x a t_INT, t_FRAC or t_REAL. * Return x mod y or NULL if accuracy error */ GEN modr_safe(GEN x, GEN y) { GEN q, f; long e; if (typ(x) == t_INT && !signe(x)) return gen_0; q = gdiv(x,y); /* t_REAL */ e = expo(q); if (e >= 0 && nbits2prec(e+1) > realprec(q)) return NULL; f = floorr(q); if (gsigne(y) < 0 && signe(subri(q,f))) f = addis(f, 1); return signe(f)? gsub(x, mulir(f,y)): x; } GEN gmod(GEN x, GEN y) { pari_sp av; long i, lx, ty, tx; GEN z; tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gmodsg(itos(x),y); ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gmodgs(x,itos(y)); if (is_matvec_t(tx)) { z = cgetg_copy(x, &lx); for (i=1; i 0) return gmul(x, gmodulsg(1,y)); if (vx == vy && tx == t_POLMOD) return grem(x,y); retmkpolmod(grem(x,y), RgX_copy(y)); } pari_err_TYPE2("%",x,y); return NULL; /* not reached */ } /*******************************************************************/ /* */ /* GENERIC EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ GEN gdivent(GEN x, GEN y) { long tx, ty; tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gdiventsg(itos(x),y); ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gdiventgs(x,itos(y)); if (is_matvec_t(tx)) { long i, lx; GEN z = cgetg_copy(x, &lx); for (i=1; i= 0) /* If 2*|r| >= |y| */ { long sz = signe(x)*signe(y); if (fl || sz > 0) q = gerepileuptoint(av, addis(q,sz)); } return q; } /* If x and y are not both scalars, same as gdivent. * Otherwise, compute the quotient x/y, rounded to the nearest integer * (towards +oo in case of tie). */ GEN gdivround(GEN x, GEN y) { pari_sp av; long tx=typ(x),ty=typ(y); GEN q,r; if (tx==t_INT && ty==t_INT) return diviiround(x,y); av = avma; if (is_rational_t(tx) && is_rational_t(ty)) { /* same as diviiround but less efficient */ pari_sp av1; int fl; q = quotrem(x,y,&r); av1 = avma; fl = gcmp(gmul2n(Q_abs(r),1), Q_abs(y)); avma = av1; cgiv(r); if (fl >= 0) /* If 2*|r| >= |y| */ { long sz = gsigne(y); if (fl || sz > 0) q = gerepileupto(av, gaddgs(q, sz)); } return q; } if (is_matvec_t(tx)) { long i, lx; GEN z = cgetg_copy(x, &lx); for (i=1; i t_POL, ignoring valp. INTERNAL ! */ GEN ser2pol_i(GEN x, long lx) { long i = lx-1; GEN y; while (i > 1 && isexactzero(gel(x,i))) i--; y = cgetg(i+1, t_POL); y[1] = x[1] & ~VALPBITS; for ( ; i > 1; i--) gel(y,i) = gel(x,i); return y; } /* T t_POL in var v, mod out by T components of x which are * t_POL/t_RFRAC in v. Recursively */ static GEN mod_r(GEN x, long v, GEN T) { long i, w, lx, tx = typ(x); GEN y; if (is_const_t(tx)) return x; switch(tx) { case t_POLMOD: w = varn(gel(x,1)); if (w == v) pari_err_PRIORITY("subst", gel(x,1), "=", v); if (varncmp(v, w) < 0) return x; return gmodulo(mod_r(gel(x,2),v,T), mod_r(gel(x,1),v,T)); case t_SER: w = varn(x); if (w == v) break; /* fail */ if (varncmp(v, w) < 0) 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); case t_POL: w = varn(x); if (w == v) return RgX_rem(x, T); if (varncmp(v, w) < 0) 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 normalizepol_lg(y, lx); case t_RFRAC: return gdiv(mod_r(gel(x,1),v,T), mod_r(gel(x,2),v,T)); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i = 1; i < lx; i++) gel(y,i) = mod_r(gel(x,i),v,T); return y; case t_LIST: y = listcreate(); list_data(y) = list_data(x)? mod_r(list_data(x),v,T): NULL; return y; } pari_err_TYPE("substpol",x); return NULL;/*not reached*/ } GEN gsubst_expr(GEN expr, GEN from, GEN to) { pari_sp av = avma; long w, v = fetch_var(); /* FIXME: Need fetch_var_low_priority() */ GEN y; from = simplify_shallow(from); switch (typ(from)) { case t_RFRAC: /* M= numerator(from) - t * denominator(from) */ y = gsub(gel(from,1), gmul(pol_x(v), gel(from,2))); break; default: y = gsub(from, pol_x(v)); /* M = from - t */ } w = gvar(from); if (varncmp(v,w) <= 0) pari_err_PRIORITY("subst", pol_x(v), "<=", w); y = gsubst(mod_r(expr, w, y), v, to); (void)delete_var(); return gerepileupto(av, y); } GEN gsubstpol(GEN x, GEN T, GEN y) { if (typ(T) == t_POL && RgX_is_monomial(T) && gequal1(leading_term(T))) { /* T = t^d */ long d = degpol(T), v = varn(T); pari_sp av = avma; GEN deflated = d == 1? x: gdeflate(x, v, d); if (deflated) return gerepileupto(av, gsubst(deflated, v, y)); avma = av; } return gsubst_expr(x,T,y); } static long checkdeflate(GEN x) { ulong d = 0, i, lx = (ulong)lg(x); for (i=3; i 0) return gcopy(x); av = avma; V = valp(x); lx = lg(x); if (lx == 2) return zeroser(v, V / d); y = ser2pol_i(x, lx); if (V % d != 0 || checkdeflate(y) % d != 0) { const char *s = stack_sprintf("valuation(x) %% %ld", d); pari_err_DOMAIN("gdeflate", s, "!=", gen_0,x); } y = poltoser(RgX_deflate(y, d), v, 1 + (lx-3)/d); setvalp(y, V/d); return gerepilecopy(av, y); } static GEN poldeflate(GEN x, long v, long d) { long vx = varn(x); pari_sp av; if (varncmp(vx, v) < 0) return vdeflate(x,v,d); if (varncmp(vx, v) > 0) return gcopy(x); av = avma; if (checkdeflate(x) % d != 0) return NULL; return gerepilecopy(av, RgX_deflate(x,d)); } static GEN listdeflate(GEN x, long v, long d) { GEN y = NULL, z = listcreate(); if (list_data(x)) { y = vdeflate(list_data(x),v,d); if (!y) return NULL; } list_data(z) = y; return z; } /* return NULL if substitution fails */ GEN gdeflate(GEN x, long v, long d) { if (d <= 0) pari_err_DOMAIN("gdeflate", "degree", "<=", gen_0,stoi(d)); switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT: case t_COMPLEX: case t_PADIC: case t_QUAD: return gcopy(x); case t_POL: return poldeflate(x,v,d); case t_SER: return serdeflate(x,v,d); case t_POLMOD: if (varncmp(varn(gel(x,1)), v) >= 0) return gcopy(x); /* fall through */ case t_RFRAC: case t_VEC: case t_COL: case t_MAT: return vdeflate(x,v,d); case t_LIST: return listdeflate(x,v,d); } pari_err_TYPE("gdeflate",x); return NULL; /* not reached */ } /* set *m to the largest d such that x0 = A(X^d); return A */ GEN RgX_deflate_max(GEN x, long *m) { *m = checkdeflate(x); return RgX_deflate(x, *m); } GEN RgX_RgM_eval_col(GEN x, GEN M, long c) { long i, n = lg(M)-1, lc = lg(x)-1; GEN z; if (signe(x)==0) return zerocol(n); z = Rg_col_ei(gel(x, lc), n, c); for (i=lc-1; i>=2; i--) { z = RgM_RgC_mul(M, z); gel(z,c) = gadd(gel(z,c), gel(x, i)); } return z; } GEN 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; GEN X, t, p1, p2, modp1, z; switch(ty) { case t_MAT: if (ly==1) return cgetg(1,t_MAT); if (ly == lgcols(y)) break; /* fall through */ case t_QFR: case t_QFI: case t_VEC: case t_COL: pari_err_TYPE2("substitution",x,y); break; /* not reached */ } if (is_scalar_t(tx)) { if (tx!=t_POLMOD || varncmp(v, varn(gel(x,1))) <= 0) { if (ty==t_MAT) return scalarmat(x,ly-1); return gcopy(x); } av=avma; p1=gsubst(gel(x,1),v,y); vx=varn(p1); p2=gsubst(gel(x,2),v,y); vy=gvar(p2); if (typ(p1)!=t_POL) pari_err_TYPE2("substitution",x,y); if (varncmp(vy, vx) >= 0) return gerepileupto(av, gmodulo(p2,p1)); modp1 = mkpolmod(gen_1,p1); lx = lg(p2); z = cgetg(lx,t_POL); z[1] = p2[1]; for (i=2; i 0) return ty == t_MAT? scalarmat(x,ly-1): RgX_copy(x); if (varncmp(vx, v) < 0) { av = avma; z = cgetg(lx, t_POL); z[1] = x[1]; for (i=2; i 0) return (ty==t_MAT)? scalarmat(x,ly-1): gcopy(x); ex = valp(x); if (varncmp(vx, v) < 0) { 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); 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(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i); z = gerepileupto(av2, z); } } if (ex) z = gmul(z, monomial(gen_1,ex,vx)); return gerepileupto(av, z); } switch(ty) /* here vx == v */ { case t_SER: vy = varn(y); ey = valp(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); for (i=lx-2; i>=2; i--) { z = gadd(gmul(y,z), gel(x,i)); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i); z = gerepileupto(av, z); } } if (ex) z = gmul(z, gpowgs(y,ex)); return gerepileupto(av,z); } l = (lx-2)*ey+2; if (ex) { if (l>ly) l = ly; } else if (lx != 3) { long l2; for (i = 3; i < lx; i++) if (!isexactzero(gel(x,i))) break; l2 = (i-2)*ey + (gequal0(y)? 2 : ly); if (l > l2) l = l2; } av = avma; lim=stack_lim(av,1); t = leafcopy(y); if (l < ly) setlg(t, l); z = scalarser(gel(x,2),varn(y),l-2); for (i=3,jb=ey; jb<=l-2; i++,jb+=ey) { if (i < lx) { for (j=jb+2; j1; j--) { p1 = gen_0; for (k=2; k1) pari_warn(warnmem,"gsubst"); gerepileall(av,2, &z,&t); } } if (!ex) return gerepilecopy(av,z); return gerepileupto(av, gmul(z,gpowgs(y, ex))); case t_POL: case t_RFRAC: { long n = lx-2; GEN cx; vy = gvar(y); ey = gval(y,vy); if (ey == LONG_MAX) return n? scalarser(gel(x,2),v,n): gcopy(x); if (ey < 1 || n == 0) return zeroser(vy, ey*(ex+n)); av = avma; n *= ey; 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 = RgX_to_ser(z, n+2); if (cx) z = gmul(z, cx); if (!ex && !cx) return gerepilecopy(av, z); if (ex) z = gmul(z, gpowgs(y,ex)); return gerepileupto(av, z); } default: if (isexactzero(y)) { if (ex < 0) pari_err_INV("gsubst",y); if (ex > 0) return gcopy(y); if (lx > 2) return gadd(gel(x,2), y); /*add maps to correct ring*/ } pari_err_TYPE2("substitution",x,y); } break; case t_RFRAC: av=avma; p1=gsubst(gel(x,1),v,y); p2=gsubst(gel(x,2),v,y); return gerepileupto(av, gdiv(p1,p2)); case t_VEC: case t_COL: case t_MAT: z = cgetg_copy(x, &lx); for (i=1; i 0) return RgX_get_0(x); if (varncmp(vx, v) == 0) return RgX_deriv(x); y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 0) return RgX_get_0(x); if (varncmp(vx, v) == 0) return derivser(x); y = cgetg_copy(x, &lx); y[1] = x[1]; for (j=2; j=2; i--) y = gadd(gmul(y,pol_x(vx)),diffop(gel(x,i),v,dv)); if (idx) y = gadd(y, gmul(gel(dv,idx),RgX_deriv(x))); return gerepileupto(av, y); case t_SER: if (signe(x)==0) return gen_0; 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 (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; } /* x + O(v^data) */ static GEN tayl_act(void *data, long v, GEN x) { return gadd(zeroser(v, (long)data), x); } static GEN integ_act(void *data, long v, GEN x) { (void)data; return integ(x,v); } GEN tayl(GEN x, long v, long precS) { long vx = gvar9(x); pari_sp av; if (varncmp(v, vx) <= 0) return gadd(zeroser(v,precS), x); av = avma; return gerepileupto(av, swapvar_act(x, vx, v, tayl_act, (void*)precS)); } GEN ggrando(GEN x, long n) { long m, v; switch(typ(x)) { case t_INT:/* bug 3 + O(1) */ if (signe(x) <= 0) pari_err_DOMAIN("O", "x", "<=", gen_0, x); if (!is_pm1(x)) return zeropadic(x,n); /* +/-1 = x^0 */ v = m = 0; break; case t_POL: if (!signe(x)) pari_err_DOMAIN("O", "x", "=", gen_0, x); v = varn(x); m = n * RgX_val(x); break; case t_RFRAC: if (gequal0(gel(x,1))) pari_err_DOMAIN("O", "x", "=", gen_0, x); v = gvar(x); m = n * gval(x,v); break; default: pari_err_TYPE("O", x); v = m = 0; /* not reached */ } return zeroser(v,m); } /*******************************************************************/ /* */ /* FORMAL INTEGRATION */ /* */ /*******************************************************************/ static GEN triv_integ(GEN x, long v) { long i, lx; GEN y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 0) y = gerepileuptoint(av, addui(1,y)); return y; case t_RFRAC: return gdeuc(gel(x,1),gel(x,2)); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i0? 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)); } GEN roundr_safe(GEN x) { long e1, 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); } GEN ground(GEN x) { GEN y; long i, lx; pari_sp av; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: case t_QUAD: return gcopy(x); case t_REAL: return roundr(x); case t_FRAC: return diviiround(gel(x,1), gel(x,2)); case t_POLMOD: y=cgetg(3,t_POLMOD); gel(y,1) = RgX_copy(gel(x,1)); gel(y,2) = ground(gel(x,2)); return y; case t_COMPLEX: av = avma; y = cgetg(3, t_COMPLEX); gel(y,2) = ground(gel(x,2)); if (!signe(gel(y,2))) { avma = av; return ground(gel(x,1)); } gel(y,1) = ground(gel(x,1)); return y; case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i= 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; } case t_FRAC: return diviiround(gel(x,1), gel(x,2)); case t_INTMOD: case t_QUAD: return gcopy(x); case t_COMPLEX: av = avma; y = cgetg(3, t_COMPLEX); gel(y,2) = grndtoi(gel(x,2), e); if (!signe(gel(y,2))) { avma = av; y = grndtoi(gel(x,1), &e1); } else gel(y,1) = grndtoi(gel(x,1), &e1); if (e1 > *e) *e = e1; return y; case t_POLMOD: y = cgetg(3,t_POLMOD); gel(y,1) = RgX_copy(gel(x,1)); gel(y,2) = grndtoi(gel(x,2), e); return y; case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i *e) *e = e1; } return normalizepol_lg(y, lx); case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i *e) *e = e1; } return normalize(y); case t_RFRAC: y = cgetg(3,t_RFRAC); gel(y,1) = grndtoi(gel(x,1),&e1); if (e1 > *e) *e = e1; gel(y,2) = grndtoi(gel(x,2),&e1); if (e1 > *e) *e = e1; return y; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i *e) *e = e1; } return y; } pari_err_TYPE("grndtoi",x); return NULL; /* not reached */ } /* trunc(x * 2^s). lindep() sanity checks rely on this function to return a * t_INT or fail when fed a non-t_COMPLEX input; so do not make this one * recursive [ or change the lindep call ] */ GEN gtrunc2n(GEN x, long s) { GEN z; switch(typ(x)) { case t_INT: return shifti(x, s); case t_REAL: return trunc2nr(x, s); case t_FRAC: { pari_sp av; GEN a = gel(x,1), b = gel(x,2), q; if (s == 0) return divii(a, b); av = avma; if (s < 0) q = divii(shifti(a, s), b); else { GEN r; q = dvmdii(a, b, &r); q = addii(shifti(q,s), divii(shifti(r,s), b)); } return gerepileuptoint(av, q); } case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,2) = gtrunc2n(gel(x,2), s); if (!signe(gel(z,2))) { avma = (pari_sp)(z + 3); return gtrunc2n(gel(x,1), s); } gel(z,1) = gtrunc2n(gel(x,1), s); return z; default: pari_err_TYPE("gtrunc2n",x); return NULL; /* not reached */ } } /* e = number of error bits on integral part */ GEN gcvtoi(GEN x, long *e) { long tx = typ(x), lx, e1; GEN y; if (tx == t_REAL) { long ex = expo(x); if (ex < 0) { *e = ex; return gen_0; } e1 = ex - bit_prec(x) + 1; y = mantissa2nr(x, e1); if (e1 <= 0) { pari_sp av = avma; e1 = expo(subri(x,y)); avma = av; } *e = e1; return y; } *e = -(long)HIGHEXPOBIT; if (is_matvec_t(tx)) { long i; y = cgetg_copy(x, &lx); for (i=1; i *e) *e = e1; } return y; } return gtrunc(x); } int isint(GEN n, GEN *ptk) { switch(typ(n)) { case t_INT: *ptk = n; return 1; case t_REAL: { pari_sp av0 = avma; GEN z = floorr(n); pari_sp av = avma; long s = signe(subri(n, z)); if (s) { avma = av0; return 0; } *ptk = z; avma = av; return 1; } case t_FRAC: return 0; case t_COMPLEX: return gequal0(gel(n,2)) && isint(gel(n,1),ptk); case t_QUAD: return gequal0(gel(n,3)) && isint(gel(n,2),ptk); default: pari_err_TYPE("isint",n); return 0; /* not reached */ } } int issmall(GEN n, long *ptk) { pari_sp av = avma; GEN z; long k; if (!isint(n, &z)) return 0; k = itos_or_0(z); avma = av; if (k || lgefint(z) == 2) { *ptk = k; return 1; } return 0; } /* smallest integer greater than any incarnations of the real x * Avoid "precision loss in truncation" */ GEN ceil_safe(GEN x) { pari_sp av = avma; long e, tx = typ(x); GEN y; if (is_rational_t(tx)) return gceil(x); y = gcvtoi(x,&e); if (gsigne(x) >= 0) { if (e < 0) e = 0; y = addii(y, int2n(e)); } return gerepileuptoint(av, y); } /* largest integer smaller than any incarnations of the real x * Avoid "precision loss in truncation" */ GEN floor_safe(GEN x) { pari_sp av = avma; long e, tx = typ(x); GEN y; if (is_rational_t(tx)) return gfloor(x); y = gcvtoi(x,&e); if (gsigne(x) <= 0) { if (e < 0) e = 0; y = subii(y, int2n(e)); } return gerepileuptoint(av, y); } GEN ser2rfrac_i(GEN x) { long e = valp(x); GEN a = ser2pol_i(x, lg(x)); if (e) { if (e > 0) a = RgX_shift_shallow(a, e); else a = gred_rfrac_simple(a, monomial(gen_1, -e, varn(a))); } return a; } static GEN ser2rfrac(GEN x) { pari_sp av = avma; return gerepilecopy(av, ser2rfrac_i(x)); } /* x t_PADIC, truncate to rational (t_INT/t_FRAC) */ GEN padic_to_Q(GEN x) { GEN u = gel(x,4), p; long v; if (!signe(u)) return gen_0; v = valp(x); if (!v) return icopy(u); p = gel(x,2); if (v>0) { pari_sp av = avma; return gerepileuptoint(av, mulii(u, powiu(p,v))); } retmkfrac(icopy(u), powiu(p,-v)); } GEN padic_to_Q_shallow(GEN x) { GEN u = gel(x,4), p; long v; if (!signe(u)) return gen_0; v = valp(x); if (!v) return u; p = gel(x,2); if (v>0) return mulii(powiu(p,v), u); return mkfrac(u, powiu(p,-v)); } GEN QpV_to_QV(GEN v) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) { GEN c = gel(v,i); switch(typ(c)) { case t_INT: case t_FRAC: break; case t_PADIC: c = padic_to_Q_shallow(c); break; default: pari_err_TYPE("padic_to_Q", v); } gel(w,i) = c; } return w; } GEN gtrunc(GEN x) { long i; GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_REAL: return truncr(x); case t_FRAC: return divii(gel(x,1),gel(x,2)); case t_PADIC: return padic_to_Q(x); case t_POL: return RgX_copy(x); case t_RFRAC: return gdeuc(gel(x,1),gel(x,2)); case t_SER: return ser2rfrac(x); case t_VEC: case t_COL: case t_MAT: { long lx; y = cgetg_copy(x, &lx); for (i=1; i INT, POL & SER */ /* */ /*******************************************************************/ /* return a_(n-1) B^(n-1) + ... + a_0, where B = 2^32. * The a_i are 32bits integers */ GEN mkintn(long n, ...) { va_list ap; GEN x, y; long i; #ifdef LONG_IS_64BIT long e = (n&1); n = (n+1) >> 1; #endif va_start(ap,n); x = cgetipos(n+2); y = int_MSW(x); for (i=0; i = 0; i--) gel(y,i) = va_arg(ap, GEN); va_end(ap); return normalizepol_lg(x, l); } /* return [a_1, ..., a_n] */ GEN mkvecn(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_VEC); for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN); va_end(ap); return x; } GEN mkcoln(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_COL); for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN); va_end(ap); return x; } GEN mkvecsmalln(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_VECSMALL); for (i=1; i <= n; i++) x[i] = va_arg(ap, long); va_end(ap); return x; } GEN scalarpol(GEN x, long v) { GEN y; if (isrationalzero(x)) return zeropol(v); y = cgetg(3,t_POL); y[1] = gequal0(x)? evalvarn(v) : evalvarn(v) | evalsigne(1); gel(y,2) = gcopy(x); return y; } GEN scalarpol_shallow(GEN x, long v) { GEN y; if (isrationalzero(x)) return zeropol(v); y = cgetg(3,t_POL); y[1] = gequal0(x)? evalvarn(v) : evalvarn(v) | evalsigne(1); gel(y,2) = x; return y; } /* x0 + x1*T, do not assume x1 != 0 */ GEN deg1pol(GEN x1, GEN x0,long v) { GEN x = cgetg(4,t_POL); x[1] = evalsigne(1) | evalvarn(v); gel(x,2) = x0 == gen_0? x0: gcopy(x0); /* gen_0 frequent */ gel(x,3) = gcopy(x1); return normalizepol_lg(x,4); } /* same, no copy */ GEN deg1pol_shallow(GEN x1, GEN x0,long v) { GEN x = cgetg(4,t_POL); x[1] = evalsigne(1) | evalvarn(v); gel(x,2) = x0; gel(x,3) = x1; return normalizepol_lg(x,4); } static GEN _gtopoly(GEN x, long v, int reverse) { long tx = typ(x); GEN y; if (v<0) v = 0; switch(tx) { case t_POL: if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); y = RgX_copy(x); break; case t_SER: if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); y = ser2rfrac(x); if (typ(y) != t_POL) pari_err_DOMAIN("gtopoly", "valuation", "<", gen_0, x); break; case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); long vb = varn(b); if (varncmp(vb, v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); if (typ(a) != t_POL || varn(a) != vb) return zeropol(v); y = RgX_div(a,b); break; } case t_VECSMALL: x = zv_to_ZV(x); /* fall through */ case t_QFR: case t_QFI: case t_VEC: case t_COL: case t_MAT: { long j, k, lx = lg(x); GEN z; if (tx == t_QFR) lx--; if (varncmp(gvar(x), v) <= 0) pari_err_PRIORITY("gtopoly", x, "<=", v); y = cgetg(lx+1, t_POL); y[1] = evalvarn(v); if (reverse) { x--; for (j=2; j<=lx; j++) gel(y,j) = gel(x,j); } else { for (j=2, k=lx; k>=2; j++) gel(y,j) = gel(x,--k); } z = RgX_copy(normalizepol_lg(y,lx+1)); settyp(y, t_VECSMALL);/* left on stack */ return z; } default: if (is_scalar_t(tx)) return scalarpol(x,v); pari_err_TYPE("gtopoly",x); return NULL; /* not reached */ } setvarn(y,v); return y; } GEN gtopolyrev(GEN x, long v) { return _gtopoly(x,v,1); } GEN gtopoly(GEN x, long v) { return _gtopoly(x,v,0); } GEN scalarser(GEN x, long v, long prec) { long i, l; GEN y; if (isrationalzero(x)) return zeroser(v, prec); l = prec + 2; y = cgetg(l, t_SER); y[1] = evalsigne(gequal0(x)? 0: 1) | _evalvalp(0) | evalvarn(v); gel(y,2) = gcopy(x); for (i=3; i 0) return scalarser(x, v, prec); if (varncmp(vx, v) < 0) return coefstoser(x, v, prec); y = RgX_to_ser(x, prec+2); setvarn(y, v); return y; } /* x a t_RFRAC. Not stack-clean */ GEN rfractoser(GEN x, long v, long prec) { GEN n = gel(x,1); if (is_scalar_t(typ(n))) n = scalarser(n, v, prec); else n = poltoser(n, v, prec); return gdiv(n, poltoser(gel(x,2), v, prec)); } GEN toser_i(GEN x) { switch(typ(x)) { case t_SER: return x; case t_POL: return RgX_to_ser(x, precdl+2); case t_RFRAC: return rfrac_to_ser(x, precdl+2); } return NULL; } GEN gtoser(GEN x, long v, long prec) { long tx=typ(x), i, j, l; pari_sp av; GEN y; if (v < 0) v = 0; if (tx == t_SER) { long vx = varn(x); if (varncmp(vx, v) < 0) y = coefstoser(x, v, prec); else if (varncmp(vx, v) > 0) y = scalarser(x, v, prec); else y = gcopy(x); return y; } if (is_scalar_t(tx)) return scalarser(x,v,prec); switch(tx) { case t_POL: if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtoser", x, "<", v); y = poltoser(x, v, prec); l = lg(y); for (i=2; i 0) return gtovecpost(x, n); return gtovecpre(x, -n); } GEN gtovec(GEN x) { long i, lx, tx = typ(x); GEN y; if (is_scalar_t(tx)) return mkveccopy(x); switch(tx) { case t_POL: lx=lg(x); y=cgetg(lx-1,t_VEC); for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,lx-i)); return y; case t_SER: lx=lg(x); y=cgetg(lx-1,t_VEC); x++; for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_RFRAC: return mkveccopy(x); case t_QFR: case t_QFI: case t_VEC: case t_COL: case t_MAT: lx=lg(x); y=cgetg(lx,t_VEC); for (i=1; i>1, i; for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i)); return y; } GEN gtovecrev(GEN x) { return gtovecrev0(x, 0); } GEN gtocol0(GEN x, long n) { GEN y; if (!n) return gtocol(x); y = gtovec0(x, n); settyp(y, t_COL); return y; } GEN gtocol(GEN x) { long lx, tx, i, j, h; GEN y; tx = typ(x); if (tx != t_MAT) { y = gtovec(x); settyp(y, t_COL); return y; } lx = lg(x); if (lx == 1) return cgetg(1, t_COL); h = lgcols(x); y = cgetg(h, t_COL); for (i = 1 ; i < h; i++) { gel(y,i) = cgetg(lx, t_VEC); for (j = 1; j < lx; j++) gmael(y,i,j) = gcopy(gcoeff(x,i,j)); } return y; } GEN gtocolrev0(GEN x, long n) { GEN y = gtocol0(x, n); long ly = lg(y), lim = ly>>1, i; for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i)); return y; } GEN gtocolrev(GEN x) { return gtocolrev0(x, 0); } static long Itos(GEN x) { if (typ(x) != t_INT) pari_err_TYPE("vectosmall",x); return itos(x); } static GEN gtovecsmallpost(GEN x, long n) { long i, imax, lx; GEN y = zero_Flv(n); switch(typ(x)) { case t_INT: y[1] = itos(x); return y; case t_POL: lx=lg(x); imax = minss(lx-2, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,lx-i)); return y; case t_SER: lx=lg(x); imax = minss(lx-2, n); x++; for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_VEC: case t_COL: lx=lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_LIST: x = list_data(x); lx = x? lg(x): 1; imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_VECSMALL: lx=lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = x[i]; return y; default: pari_err_TYPE("gtovecsmall",x); return NULL; /*notreached*/ } } static GEN gtovecsmallpre(GEN x, long n) { long i, imax, lx; GEN y = zero_Flv(n), y0; switch(typ(x)) { case t_INT: y[n] = itos(x); return y; case t_POL: lx=lg(x); y0 = init_vectopre(lx-2, n, y, &imax); for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,lx-i)); return y; case t_SER: lx=lg(x); x++; y0 = init_vectopre(lx-2, n, y, &imax); for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_VEC: case t_COL: lx=lg(x); y0 = init_vectopre(lx-1, n, y, &imax); for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_LIST: x = list_data(x); lx = x? lg(x): 1; y0 = init_vectopre(lx-1, n, y, &imax); for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_VECSMALL: lx=lg(x); y0 = init_vectopre(lx-1, n, y, &imax); for (i=1; i<=imax; i++) y0[i] = x[i]; return y; default: pari_err_TYPE("gtovecsmall",x); return NULL; /*notreached*/ } } GEN gtovecsmall0(GEN x, long n) { if (!n) return gtovecsmall(x); if (n > 0) return gtovecsmallpost(x, n); return gtovecsmallpre(x, -n); } GEN gtovecsmall(GEN x) { GEN V; long l, i; switch(typ(x)) { case t_INT: return mkvecsmall(itos(x)); case t_STR: { char *s = GSTR(x); l = strlen(s); V = cgetg(l+1, t_VECSMALL); s--; for (i=1; i<=l; i++) V[i] = (long)s[i]; return V; } case t_VECSMALL: return leafcopy(x); case t_LIST: x = list_data(x); if (!x) return cgetg(1, t_VECSMALL); /* fall through */ case t_VEC: case t_COL: l = lg(x); V = cgetg(l,t_VECSMALL); for(i=1; i= lx) pari_err_COMPONENT("", ">", utoi(lx-1), stoi(n)); return stoi(x[n]); } pari_err_TYPE("component [leaf]", x); } if (n < 1) pari_err_COMPONENT("", "<", gen_1, stoi(n)); if (tx == t_POL && (ulong)n+1 >= lx) return gen_0; if (tx == t_LIST) { tx = t_VEC; x = list_data(x); lx = (ulong)(x? lg(x): 1); } l = (ulong)lontyp[tx] + (ulong)n-1; /* beware overflow */ if (l >= lx) pari_err_COMPONENT("", ">", utoi(lx-1), utoi(l)); return gcopy(gel(x,l)); } /* assume v > varn(x), extract coeff of pol_x(v)^n */ static GEN multi_coeff(GEN x, long n, long v, long dx) { long i, lx = dx+3; GEN z = cgetg(lx, t_POL); z[1] = x[1]; for (i = 2; i < lx; i++) gel(z,i) = polcoeff_i(gel(x,i), n, v); z = normalizepol_lg(z, lx); switch(lg(z)) { case 2: z = gen_0; break; case 3: z = gel(z,2); break; } return z; } /* assume x a t_POL */ static GEN _polcoeff(GEN x, long n, long v) { long w, dx; dx = degpol(x); if (dx < 0) return gen_0; if (v < 0 || v == (w=varn(x))) return (n < 0 || n > dx)? gen_0: gel(x,n+2); if (varncmp(w,v) > 0) return n? gen_0: x; /* w < v */ return multi_coeff(x, n, v, dx); } /* assume x a t_SER */ static GEN _sercoeff(GEN x, long n, long v) { long w, dx = degpol(x), ex = valp(x), N = n - ex; GEN z; if (dx < 0) { if (N >= 0) pari_err_DOMAIN("polcoeff", "t_SER", "=", x, x); return gen_0; } if (v < 0 || v == (w=varn(x))) { if (N > dx) pari_err_DOMAIN("polcoeff", "degree", ">", stoi(dx+ex), stoi(n)); return (N < 0)? gen_0: gel(x,N+2); } if (varncmp(w,v) > 0) return N? gen_0: x; /* w < v */ z = multi_coeff(x, n, v, dx); if (ex) z = gmul(z, monomial(gen_1,ex, w)); return z; } /* assume x a t_RFRAC(n) */ static GEN _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); 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); n += degpol(Q); return gdiv(_polcoeff(P, n, v), leading_term(Q)); } GEN polcoeff_i(GEN x, long n, long v) { switch(typ(x)) { case t_POL: return _polcoeff(x,n,v); case t_SER: return _sercoeff(x,n,v); case t_RFRAC: return _rfraccoeff(x,n,v); default: return n? gen_0: x; } } /* with respect to the main variable if v<0, with respect to the variable v otherwise. v ignored if x is not a polynomial/series. */ GEN polcoeff0(GEN x, long n, long v) { long lx, tx = typ(x); pari_sp av; if (is_scalar_t(tx)) return n? gen_0: gcopy(x); av = avma; switch(tx) { case t_POL: x = _polcoeff(x,n,v); break; case t_SER: x = _sercoeff(x,n,v); break; case t_RFRAC: x = _rfraccoeff(x,n,v); break; case t_QFR: case t_QFI: case t_VEC: case t_COL: case t_MAT: if (n < 1) pari_err_COMPONENT("polcoeff","<",gen_1,stoi(n)); lx = lg(x); if (n >= lx) pari_err_COMPONENT("polcoeff",">",stoi(lx-1),stoi(n)); return gcopy(gel(x,n)); default: pari_err_TYPE("polcoeff", x); } if (x == gen_0) return x; if (avma == av) return gcopy(x); return gerepilecopy(av, x); } static GEN vecdenom(GEN v, long imin, long imax) { pari_sp av = avma; long i = imin; GEN s; if (imin > imax) return gen_1; s = denom(gel(v,i)); for (i++; i<=imax; i++) { GEN t = denom(gel(v,i)); if (t != gen_1) s = glcm(s,t); } return gerepileupto(av, s); } GEN denom(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FFELT: case t_PADIC: case t_SER: return gen_1; case t_FRAC: return icopy(gel(x,2)); case t_COMPLEX: return vecdenom(x,1,2); case t_QUAD: return vecdenom(x,2,3); case t_POLMOD: return denom(gel(x,2)); case t_RFRAC: return RgX_copy(gel(x,2)); case t_POL: return pol_1(varn(x)); case t_VEC: case t_COL: case t_MAT: return vecdenom(x, 1, lg(x)-1); } pari_err_TYPE("denom",x); return NULL; /* not reached */ } GEN numer(GEN x) { pari_sp av; switch(typ(x)) { case t_INT: case t_REAL: return mpcopy(x); case t_INTMOD: case t_FFELT: case t_PADIC: case t_SER: return gcopy(x); case t_POL: return RgX_copy(x); case t_FRAC: return icopy(gel(x,1)); case t_POLMOD: av = avma; return gerepileupto(av, gmodulo(numer(gel(x,2)), gel(x,1))); case t_RFRAC: return gcopy(gel(x,1)); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: av = avma; return gerepileupto(av, gmul(denom(x),x)); } pari_err_TYPE("numer",x); return NULL; /* not reached */ } /* Lift only intmods if v does not occur in x, lift with respect to main * variable of x if v < 0, with respect to variable v otherwise. */ GEN lift0(GEN x, long v) { long lx, i; GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: return v < 0? icopy(gel(x,2)): gcopy(x); case t_POLMOD: if (v < 0 || v == varn(gel(x,1))) return gcopy(gel(x,2)); y = cgetg(3, t_POLMOD); gel(y,1) = lift0(gel(x,1),v); gel(y,2) = lift0(gel(x,2),v); return y; case t_PADIC: return v < 0? padic_to_Q(x): gcopy(x); case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i=2; i--) gel(x,i) = lift_intern(gel(x,i)); return normalize(x); case t_POL: for (i = lg(x)-1; i>=2; i--) gel(x,i) = lift_intern(gel(x,i)); return normalizepol(x); case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: for (i = lg(x)-1; i>=1; i--) gel(x,i) = lift_intern(gel(x,i)); return x; default: return x; } } static GEN centerliftii(GEN x, GEN y) { pari_sp av = avma; long i = cmpii(shifti(x,1), y); avma = av; return (i > 0)? subii(x,y): icopy(x); } /* see lift0 */ GEN centerlift0(GEN x, long v) { return v < 0? centerlift(x): lift0(x,v); } GEN centerlift(GEN x) { long i, v, lx; GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: return centerliftii(gel(x,2), gel(x,1)); case t_POLMOD: return gcopy(gel(x,2)); case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i=0) { /* here p^v is an integer */ GEN z = centerliftii(gel(x,4), gel(x,3)); pari_sp av; if (!v) return z; av = avma; y = powiu(gel(x,2),v); return gerepileuptoint(av, mulii(y,z)); } y = cgetg(3,t_FRAC); gel(y,1) = centerliftii(gel(x,4), gel(x,3)); gel(y,2) = powiu(gel(x,2),-v); return y; default: return gcopy(x); } } /*******************************************************************/ /* */ /* REAL & IMAGINARY PARTS */ /* */ /*******************************************************************/ static GEN op_ReIm(GEN f(GEN), GEN x) { long lx, i, j; pari_sp av; GEN z; switch(typ(x)) { case t_POL: z = cgetg_copy(x, &lx); z[1] = x[1]; for (j=2; j=0? gen_1: gen_0; } GEN ggt(GEN x, GEN y) { return gcmp(x,y)>0? gen_1: gen_0; } GEN geq(GEN x, GEN y) { return _egal(x,y)? gen_1: gen_0; } GEN gne(GEN x, GEN y) { return _egal(x,y)? gen_0: gen_1; } GEN gnot(GEN x) { return gequal0(x)? gen_1: gen_0; } /*******************************************************************/ /* */ /* FORMAL SIMPLIFICATIONS */ /* */ /*******************************************************************/ GEN geval_gp(GEN x, GEN t) { long lx, i, tx = typ(x); pari_sp av; GEN y, z; if (is_const_t(tx)) return gcopy(x); switch(tx) { case t_STR: return localvars_read_str(GSTR(x),t); case t_POLMOD: av = avma; return gerepileupto(av, gmodulo(geval_gp(gel(x,2),t), geval_gp(gel(x,1),t))); case t_POL: lx=lg(x); if (lx==2) return gen_0; z = fetch_var_value(varn(x),t); if (!z) return RgX_copy(x); av = avma; y = geval_gp(gel(x,lx-1),t); for (i=lx-2; i>1; i--) y = gadd(geval_gp(gel(x,i),t), gmul(z,y)); return gerepileupto(av, y); case t_SER: pari_err_IMPL( "evaluation of a power series"); case t_RFRAC: av = avma; return gerepileupto(av, gdiv(geval_gp(gel(x,1),t), geval_gp(gel(x,2),t))); case t_QFR: case t_QFI: case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i 1 */ z = gmul(gcoeff(q,1,1), gsqr(gel(x,1))); for (i=2; i 2 */ xc = gconj(x); z = mulreal(gcoeff(q,2,1), gmul(gel(x,2),gel(xc,1))); for (i=3;i=imin; i--) p1 = gadd(gmul(p1,y),gel(x,i)); #endif /* specific attention to sparse polynomials */ for ( ; i>=imin; i=j-1) { for (j=i; isexactzero(gel(x,j)); j--) if (j==imin) { if (i!=j) y = gpowgs(y, i-j+1); return gerepileupto(av0, gmul(p1,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 (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i); p1 = gerepileupto(av0, p1); } } return gerepileupto(av0,p1); } p2 = gel(x,i); i--; r = gtrace(y); s = gneg_i(gnorm(y)); av = avma; for ( ; i>=imin; i--) { 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 (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i); gerepileall(av, 2, &p1, &p2); } } return gerepileupto(av0, gadd(p2, gmul(y,p1))); } pari-2.7.5/src/basemath/arith2.c0000644000175000017500000012237012502252164015022 0ustar billbill/* 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. */ /*********************************************************************/ /** **/ /** ARITHMETIC FUNCTIONS **/ /** (second part) **/ /** **/ /*********************************************************************/ #include "pari.h" #include "paripriv.h" static ulong _maxprime = 0; static ulong diffptrlen; /* Building/Rebuilding the diffptr table. The actual work is done by the * following two subroutines; the user entry point is the function * initprimes() below. initprimes1() is the old algorithm, called when * maxnum (size) is moderate. Must be called after pari_init_stack() )*/ static void initprimes1(ulong size, long *lenp, ulong *lastp, byteptr p1) { pari_sp av = avma; long k; byteptr q, r, s, p = (byteptr)stack_calloc(size+2), fin = p + size; for (r=q=p,k=1; r<=fin; ) { do { r+=k; k+=2; r+=k; } while (*++q); for (s=r; s<=fin; s+=k) *s = 1; } r = p1; *r++ = 2; *r++ = 1; /* 2 and 3 */ for (s=q=p+1; ; s=q) { do q++; while (*q); if (q > fin) break; *r++ = (unsigned char) ((q-s) << 1); } *r++ = 0; *lenp = r - p1; *lastp = ((s - p) << 1) + 1; avma = av; } /* Timing in ms (Athlon/850; reports 512K of secondary cache; looks like there is 64K of quickier cache too). arena| 30m 100m 300m 1000m 2000m <-- primelimit ================================================= 16K 1.1053 1.1407 1.2589 1.4368 1.6086 24K 1.0000 1.0625 1.1320 1.2443 1.3095 32K 1.0000 1.0469 1.0761 1.1336 1.1776 48K 1.0000 1.0000 1.0254 1.0445 1.0546 50K 1.0000 1.0000 1.0152 1.0345 1.0464 52K 1.0000 1.0000 1.0203 1.0273 1.0362 54K 1.0000 1.0000 1.0812 1.0216 1.0281 56K 1.0526 1.0000 1.0051 1.0144 1.0205 58K 1.0000 1.0000 1.0000 1.0086 1.0123 60K 0.9473 0.9844 1.0051 1.0014 1.0055 62K 1.0000 0.9844 0.9949 0.9971 0.9993 64K 1.0000 1.0000 1.0000 1.0000 1.0000 66K 1.2632 1.2187 1.2183 1.2055 1.1953 68K 1.4211 1.4844 1.4721 1.4425 1.4188 70K 1.7368 1.7188 1.7107 1.6767 1.6421 72K 1.9474 1.9531 1.9594 1.9023 1.8573 74K 2.2105 2.1875 2.1827 2.1207 2.0650 76K 2.4211 2.4219 2.4010 2.3305 2.2644 78K 2.5789 2.6250 2.6091 2.5330 2.4571 80K 2.8421 2.8125 2.8223 2.7213 2.6380 84K 3.1053 3.1875 3.1776 3.0819 2.9802 88K 3.5263 3.5312 3.5228 3.4124 3.2992 92K 3.7895 3.8438 3.8375 3.7213 3.5971 96K 4.0000 4.1093 4.1218 3.9986 3.9659 112K 4.3684 4.5781 4.5787 4.4583 4.6115 128K 4.7368 4.8750 4.9188 4.8075 4.8997 192K 5.5263 5.7188 5.8020 5.6911 5.7064 256K 6.0000 6.2187 6.3045 6.1954 6.1033 384K 6.7368 6.9531 7.0405 6.9181 6.7912 512K 7.3158 7.5156 7.6294 7.5000 7.4654 768K 9.1579 9.4531 9.6395 9.5014 9.1075 1024K 10.368 10.7497 10.9999 10.878 10.8201 1536K 12.579 13.3124 13.7660 13.747 13.4739 2048K 13.737 14.4839 15.0509 15.151 15.1282 3076K 14.789 15.5780 16.2993 16.513 16.3365 Now the same number relative to the model (1 + 0.36*sqrt(primelimit)/arena) * (arena <= 64 ? 1.05 : (arena-64)**0.38) [SLOW2_IN_ROOTS = 0.36, ALPHA = 0.38] arena| 30m 100m 300m 1000m 2000m <-- primelimit ================================================= 16K 1.014 0.9835 0.9942 0.9889 1.004 24K 0.9526 0.9758 0.9861 0.9942 0.981 32K 0.971 0.9939 0.9884 0.9849 0.9806 48K 0.9902 0.9825 0.996 0.9945 0.9885 50K 0.9917 0.9853 0.9906 0.9926 0.9907 52K 0.9932 0.9878 0.9999 0.9928 0.9903 54K 0.9945 0.9902 1.064 0.9939 0.9913 56K 1.048 0.9924 0.9925 0.993 0.9921 58K 0.9969 0.9945 0.9909 0.9932 0.9918 60K 0.9455 0.9809 0.9992 0.9915 0.9923 62K 0.9991 0.9827 0.9921 0.9924 0.9929 64K 1 1 1 1 1 66K 1.02 0.9849 0.9857 0.9772 0.9704 68K 0.8827 0.9232 0.9176 0.9025 0.8903 70K 0.9255 0.9177 0.9162 0.9029 0.8881 72K 0.9309 0.936 0.9429 0.9219 0.9052 74K 0.9715 0.9644 0.967 0.9477 0.9292 76K 0.9935 0.9975 0.9946 0.9751 0.9552 78K 0.9987 1.021 1.021 1.003 0.9819 80K 1.047 1.041 1.052 1.027 1.006 84K 1.052 1.086 1.092 1.075 1.053 88K 1.116 1.125 1.133 1.117 1.096 92K 1.132 1.156 1.167 1.155 1.134 96K 1.137 1.177 1.195 1.185 1.196 112K 1.067 1.13 1.148 1.15 1.217 128K 1.04 1.083 1.113 1.124 1.178 192K 0.9368 0.985 1.025 1.051 1.095 256K 0.8741 0.9224 0.9619 0.995 1.024 384K 0.8103 0.8533 0.8917 0.9282 0.9568 512K 0.7753 0.8135 0.8537 0.892 0.935 768K 0.8184 0.8638 0.9121 0.9586 0.9705 1024K 0.8241 0.8741 0.927 0.979 1.03 1536K 0.8505 0.9212 0.9882 1.056 1.096 2048K 0.8294 0.8954 0.9655 1.041 1.102 */ #ifndef SLOW2_IN_ROOTS /* SLOW2_IN_ROOTS below 3: some slowdown starts to be noticable * when things fit into the cache on Sparc. * The choice of 2.6 gives a slowdown of 1-2% on UltraSparcII, * but makes calculations for "maximum" of 436273009 * fit into 256K cache (still common for some architectures). * * One may change it when small caches become uncommon, but the gain * is not going to be very noticable... */ # ifdef i386 /* gcc defines this? */ # define SLOW2_IN_ROOTS 0.36 # else # define SLOW2_IN_ROOTS 2.6 # endif #endif #ifndef CACHE_ARENA # ifdef i386 /* gcc defines this? */ /* Due to smaller SLOW2_IN_ROOTS, smaller arena is OK; fit L1 cache */ # define CACHE_ARENA (63 * 1024UL) /* No slowdown even with 64K L1 cache */ # else # define CACHE_ARENA (200 * 1024UL) /* No slowdown even with 256K L2 cache */ # endif #endif #define CACHE_ALPHA (0.38) /* Cache performance model parameter */ #define CACHE_CUTOFF (0.018) /* Cache performance not smooth here */ static double slow2_in_roots = SLOW2_IN_ROOTS; typedef struct { ulong arena; double power; double cutoff; } cache_model_t; static cache_model_t cache_model = { CACHE_ARENA, CACHE_ALPHA, CACHE_CUTOFF }; /* Assume that some calculation requires a chunk of memory to be accessed often in more or less random fashion (as in sieving). Assume that the calculation can be done in steps by subdividing the chunk into smaller subchunks (arenas) and treating them separately. Assume that the overhead of subdivision is equivalent to the number of arenas. Find an optimal size of the arena taking into account the overhead of subdivision, and the overhead of arena not fitting into the cache. Assume that arenas of size slow2_in_roots slows down the calculation 2x (comparing to very big arenas; when cache hits do not matter). Since cache performance varies wildly with architecture, load, and wheather (especially with cache coloring enabled), use an idealized cache model based on benchmarks above. Assume that an independent region of FIXED_TO_CACHE bytes is accessed very often concurrently with the arena access. */ static ulong good_arena_size(ulong slow2_size, ulong total, ulong fixed_to_cache, cache_model_t *cache_model) { ulong asize, cache_arena = cache_model->arena; double Xmin, Xmax, A, B, C1, C2, D, V; double alpha = cache_model->power, cut_off = cache_model->cutoff; /* Estimated relative slowdown, with overhead = max((fixed_to_cache+arena)/cache_arena - 1, 0): 1 + slow2_size/arena due to initialization overhead; max(1, 4.63 * overhead^0.38 ) due to footprint > cache size. [The latter is hard to substantiate theoretically, but this function describes benchmarks pretty close; it does not hurt that one can minimize it explicitly too ;-). The switch between different choices of max() happens when overhead=0.018.] Thus the problem is minimizing (1 + slow2_size/arena)*overhead**0.29. This boils down to F=((X+A)/(X+B))X^alpha, X=overhead, B = (1 - fixed_to_cache/cache_arena), A = B + slow2_size/cache_arena, alpha = 0.38, and X>=0.018, X>-B. We need to find the rightmost root of (X+A)*(X+B) - alpha(A-B)X to the right of 0.018 (if such exists and is below Xmax). Then we manually check the remaining region [0, 0.018]. Since we cannot trust the purely-experimental cache-hit slowdown function, as a sanity check always prefer fitting into the cache (or "almost fitting") if F-law predicts that the larger value of the arena provides less than 10% speedup. */ /* The simplest case: we fit into cache */ if (total + fixed_to_cache <= cache_arena) return total; /* The simple case: fitting into cache doesn't slow us down more than 10% */ if (cache_arena - fixed_to_cache > 10 * slow2_size) { asize = cache_arena - fixed_to_cache; if (asize > total) asize = total; /* Automatically false... */ return asize; } /* Slowdown of not fitting into cache is significant. Try to optimize. Do not be afraid to spend some time on optimization - in trivial cases we do not reach this point; any gain we get should compensate the time spent on optimization. */ B = (1 - ((double)fixed_to_cache)/cache_arena); A = B + ((double)slow2_size)/cache_arena; C2 = A*B; C1 = (A + B - 1/alpha*(A - B))/2; D = C1*C1 - C2; if (D > 0) V = cut_off*cut_off + 2*C1*cut_off + C2; /* Value at CUT_OFF */ else V = 0; /* Peacify the warning */ Xmin = cut_off; Xmax = ((double)total - fixed_to_cache)/cache_arena; /* Two candidates */ if ( D <= 0 || (V >= 0 && C1 + cut_off >= 0) ) /* slowdown increasing */ Xmax = cut_off; /* Only one candidate */ else if (V >= 0 && /* slowdown concave down */ ((Xmax + C1) <= 0 || (Xmax*Xmax + 2*C1*Xmax + C2) <= 0)) /* DO NOTHING */; /* Keep both candidates */ else if (V <= 0 && (Xmax*Xmax + 2*C1*Xmax + C2) <= 0) /* slowdown decreasing */ Xmin = cut_off; /* Only one candidate */ else /* Now we know: 2 roots, the largest is in CUT_OFF..Xmax */ Xmax = sqrt(D) - C1; if (Xmax != Xmin) { /* Xmin == CUT_OFF; Check which one is better */ double v1 = (cut_off + A)/(cut_off + B); double v2 = 2.33 * (Xmax + A)/(Xmax + B) * pow(Xmax, alpha); if (1.1 * v2 >= v1) /* Prefer fitting into the cache if slowdown < 10% */ V = v1; else { Xmin = Xmax; V = v2; } } else if (B > 0) /* We need V */ V = 2.33 * (Xmin + A)/(Xmin + B) * pow(Xmin, alpha); if (B > 0 && 1.1 * V > A/B) /* Now Xmin is the minumum. Compare with 0 */ Xmin = 0; asize = (ulong)((1 + Xmin)*cache_arena - fixed_to_cache); if (asize > total) asize = total; /* May happen due to approximations */ return asize; } /* Use as in install(set_optimize,lLDG) \\ Through some M too? set_optimize(2,1) \\ disable dependence on limit \\ 1: how much cache usable, 2: slowdown of setup, 3: alpha, 4: cutoff \\ 2,3,4 are in units of 0.001 { time_primes_arena(ar,limit) = \\ ar = arena size in K set_optimize(1,floor(ar*1024)); default(primelimit, 200 000); \\ 100000 results in *larger* malloc()! gettime; default(primelimit, floor(limit)); if(ar >= 1, ar=floor(ar)); print("arena "ar"K => "gettime"ms"); } */ long set_optimize(long what, GEN g) { long ret = 0; switch (what) { case 1: ret = (long)cache_model.arena; break; case 2: ret = (long)(slow2_in_roots * 1000); break; case 3: ret = (long)(cache_model.power * 1000); break; case 4: ret = (long)(cache_model.cutoff * 1000); break; default: pari_err_BUG("set_optimize"); break; } if (g != NULL) { ulong val = itou(g); switch (what) { case 1: cache_model.arena = val; break; case 2: slow2_in_roots = (double)val / 1000.; break; case 3: cache_model.power = (double)val / 1000.; break; case 4: cache_model.cutoff = (double)val / 1000.; break; } } return ret; } /* s is odd; prime differences (starting from 5-3=2) start at known_primes[2], terminated by a 0 byte. Checks n odd numbers starting at 'start', setting bytes starting at data to 0 (composite) or 1 (prime) */ static void sieve_chunk(byteptr known_primes, ulong s, byteptr data, ulong n) { ulong p, cnt = n-1, start = s, delta = 1; byteptr q; memset(data, 0, n); start >>= 1; /* (start - 1)/2 */ start += n; /* Corresponds to the end */ /* data corresponds to start, q runs over primediffs */ for (q = known_primes + 1, p = 3; delta; delta = *++q, p += delta) { /* first odd number >= start > p and divisible by p = last odd number <= start + 2p - 2 and 0 (mod p) = p + last number <= start + p - 2 and 0 (mod 2p) = p + start+p-2 - (start+p-2) % 2p = start + 2(p - 1 - ((start-1)/2 + (p-1)/2) % p). */ long off = cnt - ((start+(p>>1)) % p); while (off >= 0) { data[off] = 1; off -= p; } } } /* assume maxnum <= 436273289 < 2^29 */ static void initprimes0(ulong maxnum, long *lenp, ulong *lastp, byteptr p1) { pari_sp av = avma; long alloced, psize; byteptr q, end, p, end1, plast, curdiff; ulong last, remains, curlow, rootnum, asize; ulong prime_above; byteptr p_prime_above; maxnum |= 1; /* make it odd. */ /* base case */ if (maxnum < 1ul<<17) { initprimes1(maxnum>>1, lenp, lastp, p1); return; } /* Checked to be enough up to 40e6, attained at 155893 */ rootnum = usqrt(maxnum) | 1; initprimes1(rootnum>>1, &psize, &last, p1); end1 = p1 + psize - 1; remains = (maxnum - last) >> 1; /* number of odd numbers to check */ /* we access primes array of psize too; but we access it consecutively, * thus we do not include it in fixed_to_cache */ asize = good_arena_size((ulong)(rootnum * slow2_in_roots), remains+1, 0, &cache_model) - 1; /* enough room on the stack ? */ alloced = (((byteptr)avma) <= ((byteptr)bot) + asize); if (alloced) p = (byteptr)pari_malloc(asize+1); else p = (byteptr)stack_malloc(asize+1); end = p + asize; /* the 0 sentinel goes at end. */ curlow = last + 2; /* First candidate: know primes up to last (odd). */ curdiff = end1; /* During each iteration p..end-1 represents a range of odd numbers. plast is a pointer which represents the last prime seen, it may point before p..end-1. */ plast = p - 1; p_prime_above = p1 + 2; prime_above = 3; while (remains) { /* cycle over arenas; performance not crucial */ unsigned char was_delta; if (asize > remains) { asize = remains; end = p + asize; } /* Fake the upper limit appropriate for the given arena */ while (prime_above*prime_above <= curlow + (asize << 1) && *p_prime_above) prime_above += *p_prime_above++; was_delta = *p_prime_above; *p_prime_above = 0; /* sentinel for sieve_chunk */ sieve_chunk(p1, curlow, p, asize); *p_prime_above = was_delta; /* restore */ p[asize] = 0; /* sentinel */ for (q = p; ; plast = q++) { /* q runs over addresses corresponding to primes */ while (*q) q++; /* use sentinel at end */ if (q >= end) break; *curdiff++ = (unsigned char)(q-plast) << 1; /* < 255 for q < 436273291 */ } plast -= asize; remains -= asize; curlow += (asize<<1); } last = curlow - ((p - plast) << 1); *curdiff++ = 0; /* sentinel */ *lenp = curdiff - p1; *lastp = last; if (alloced) pari_free(p); else avma = av; } ulong maxprime(void) { return diffptr ? _maxprime : 0; } void maxprime_check(ulong c) { if (_maxprime < c) pari_err_MAXPRIME(c); } /* We ensure 65302 <= maxnum <= 436273289: the LHS ensures modular function * have enough fast primes to work, the RHS ensures that p_{n+1} - p_n < 255 * (N.B. RHS would be incorrect since initprimes0 would make it odd, thereby * increasing it by 1) */ byteptr initprimes(ulong maxnum, long *lenp, ulong *lastp) { byteptr t; if (maxnum < 65537) maxnum = 65537; else if (maxnum > 436273289) maxnum = 436273289; t = (byteptr)pari_malloc((size_t) (1.09 * maxnum/log((double)maxnum)) + 146); initprimes0(maxnum, lenp, lastp, t); return (byteptr)pari_realloc(t, *lenp); } void initprimetable(ulong maxnum) { long len; ulong last; byteptr p = initprimes(maxnum, &len, &last), old = diffptr; diffptrlen = minss(diffptrlen, len); _maxprime = minss(_maxprime,last); /*Protect against ^C*/ diffptr = p; diffptrlen = len; _maxprime = last; if (old) free(old); } /* all init_primepointer_xx routines set *ptr to the corresponding place * in prime table */ /* smallest p >= a */ ulong init_primepointer_geq(ulong a, byteptr *pd) { ulong n, p; prime_table_next_p(a, pd, &p, &n); return p; } /* largest p < a */ ulong init_primepointer_lt(ulong a, byteptr *pd) { ulong n, p; prime_table_next_p(a, pd, &p, &n); PREC_PRIME_VIADIFF(p, *pd); return p; } /* largest p <= a */ ulong init_primepointer_leq(ulong a, byteptr *pd) { ulong n, p; prime_table_next_p(a, pd, &p, &n); if (p != a) PREC_PRIME_VIADIFF(p, *pd); return p; } /* smallest p > a */ ulong init_primepointer_gt(ulong a, byteptr *pd) { ulong n, p; prime_table_next_p(a, pd, &p, &n); if (p == a) NEXT_PRIME_VIADIFF(p, *pd); return p; } GEN boundfact(GEN n, ulong lim) { switch(typ(n)) { case t_INT: return Z_factor_limit(n,lim); case t_FRAC: { pari_sp av = avma; GEN a = Z_factor_limit(gel(n,1),lim); GEN b = Z_factor_limit(gel(n,2),lim); gel(b,2) = ZC_neg(gel(b,2)); return gerepilecopy(av, merge_factor_i(a,b)); } } pari_err_TYPE("boundfact",n); return NULL; /* not reached */ } /* NOT memory clean */ GEN Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pe) { long i, j, l = lg(L); GEN e = new_chunk(l), P = new_chunk(l); for (i = j = 1; i < l; i++) { ulong p = (ulong)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; } } } P[0] = evaltyp(t_VECSMALL) | evallg(j); *pP = P; e[0] = evaltyp(t_VECSMALL) | evallg(j); *pe = e; return N; } /***********************************************************************/ /** **/ /** SIMPLE FACTORISATIONS **/ /** **/ /***********************************************************************/ /* Factor n and output [p,e,c] where * p, e and c are vecsmall with n = prod{p[i]^e[i]} and c[i] = p[i]^e[i] */ GEN factoru_pow(ulong n) { GEN f = cgetg(4,t_VEC); pari_sp av = avma; GEN F, P, E, p, e, c; long i, l; /* enough room to store <= 15 * [p,e,p^e] (OK if n < 2^64) */ (void)new_chunk((15 + 1)*3); F = factoru(n); P = gel(F,1); E = gel(F,2); l = lg(P); avma = av; gel(f,1) = p = cgetg(l,t_VECSMALL); gel(f,2) = e = cgetg(l,t_VECSMALL); gel(f,3) = c = cgetg(l,t_VECSMALL); for(i = 1; i < l; i++) { p[i] = P[i]; e[i] = E[i]; c[i] = upowuu(p[i], e[i]); } return f; } static GEN factorlim(GEN n, ulong lim) { return lim? Z_factor_limit(n, lim): Z_factor(n); } /* factor p^n - 1, assuming p prime. If lim != 0, limit factorization to * primes <= lim */ GEN factor_pn_1_limit(GEN p, long n, ulong lim) { pari_sp av = avma; GEN A = factorlim(subiu(p,1), lim), d = divisorsu(n); long i, pp = itos_or_0(p); for(i=2; i 1) { if (B) { gel(B,1) = shallowconcat(gel(B,1), p); gel(B,2) = shallowconcat(gel(B,2), utoipos(e-1)); } else B = to_mat(p, e-1); } } avma = av; if (!B) return v? to_mat(gen_2, v): trivial_fact(); A = cgetg(3, t_MAT); P = gel(B,1); E = gel(B,2); l = lg(P); AP = cgetg(l+1, t_COL); gel(A,1) = AP; AP++; AE = cgetg(l+1, t_COL); gel(A,2) = AE; AE++; /* prepend "2^v" */ gel(AP,0) = gen_2; gel(AE,0) = utoipos(v); for (i = 1; i < l; i++) { gel(AP,i) = icopy(gel(P,i)); gel(AE,i) = icopy(gel(E,i)); } return A; } #endif /***********************************************************************/ /** **/ /** CHECK FACTORIZATION FOR ARITHMETIC FUNCTIONS **/ /** **/ /***********************************************************************/ static int RgV_is_ZVpos(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_INT || signe(c) <= 0) return 0; } return 1; } /* check whether v is a ZV with non-0 entries */ static int RgV_is_ZVnon0(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_INT || !signe(c)) return 0; } return 1; } /* check whether v is a ZV with non-zero entries OR exactly [0] */ static int RgV_is_ZV0(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); long s; if (typ(c) != t_INT) return 0; s = signe(c); if (!s) return (l == 2); } return 1; } static int is_Z_factor_i(GEN f) { return typ(f) == t_MAT && lg(f) == 3 && RgV_is_ZVpos(gel(f,2)); } int is_Z_factorpos(GEN f) { return is_Z_factor_i(f) && RgV_is_ZVpos(gel(f,1)); } int is_Z_factor(GEN f) { return is_Z_factor_i(f) && RgV_is_ZV0(gel(f,1)); } /* as is_Z_factorpos, also allow factor(0) */ int is_Z_factornon0(GEN f) { return is_Z_factor_i(f) && RgV_is_ZVnon0(gel(f,1)); } GEN clean_Z_factor(GEN f) { GEN P = gel(f,1); long n = lg(P)-1; if (n && equalim1(gel(P,1))) return mkmat2(vecslice(P,2,n), vecslice(gel(f,2),2,n)); return f; } /* n associated to a factorization of a positive integer: either N (t_INT) * a factorization matrix faN, or a t_VEC: [N, faN] */ GEN check_arith_pos(GEN n, const char *f) { switch(typ(n)) { case t_INT: if (signe(n) <= 0 ) pari_err_DOMAIN(f, "argument", "<=", gen_0, gen_0); return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factorpos(n)) break; return n; } pari_err_TYPE(f,n); return NULL; } /* n associated to a factorization of a non-0 integer */ GEN check_arith_non0(GEN n, const char *f) { switch(typ(n)) { case t_INT: if (!signe(n)) pari_err_DOMAIN(f, "argument", "=", gen_0, gen_0); return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factornon0(n)) break; return n; } pari_err_TYPE(f,n); return NULL; } /* n associated to a factorization of an integer */ GEN check_arith_all(GEN n, const char *f) { switch(typ(n)) { case t_INT: return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factor(n)) break; return n; } pari_err_TYPE(f,n); return NULL; } /***********************************************************************/ /** **/ /** MISCELLANEOUS ARITHMETIC FUNCTIONS **/ /** (ultimately depend on Z_factor()) **/ /** **/ /***********************************************************************/ /* set P,E from F. Check whether F is an integer and kill "factor" -1 */ static void set_fact_check(GEN F, GEN *pP, GEN *pE, int *isint) { GEN E, P; if (lg(F) != 3) pari_err_TYPE("divisors",F); P = gel(F,1); E = gel(F,2); RgV_check_ZV(E, "divisors"); *isint = RgV_is_ZV(P); if (*isint) { long i, l = lg(P); /* skip -1 */ if (l>1 && signe(gel(P,1)) < 0) { E++; P = vecslice(P,2,--l); } /* test for 0 */ for (i = 1; i < l; i++) if (!signe(gel(P,i)) && signe(gel(E,i))) pari_err_DOMAIN("divisors", "argument", "=", gen_0, F); } *pP = P; *pE = E; } static void set_fact(GEN F, GEN *pP, GEN *pE) { *pP = gel(F,1); *pE = gel(F,2); } int divisors_init(GEN n, GEN *pP, GEN *pE) { long i,l; GEN E, P, e; int isint; switch(typ(n)) { case t_INT: if (!signe(n)) pari_err_DOMAIN("divisors", "argument", "=", gen_0, gen_0); set_fact(absi_factor(n), &P,&E); isint = 1; break; case t_VEC: 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: set_fact_check(n, &P,&E, &isint); break; default: set_fact(factor(n), &P,&E); isint = 0; break; } l = lg(P); e = cgetg(l, t_VECSMALL); for (i=1; i> 1)); } return mkvec2(c,f); } GEN corepartial(GEN n, long all) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("corepartial",n); return gerepileuptoint(av, corefa(Z_factor_limit(n,all))); } GEN core2partial(GEN n, long all) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("core2partial",n); return gerepilecopy(av, core2fa(Z_factor_limit(n,all))); } static GEN core2_i(GEN n) { GEN f = core(n); if (!signe(f)) return mkvec2(gen_0, gen_1); switch(typ(n)) { case t_VEC: n = gel(n,1); break; case t_MAT: n = factorback(n); break; } return mkvec2(f, sqrtint(diviiexact(n, f))); } GEN core2(GEN n) { pari_sp av = avma; return gerepilecopy(av, core2_i(n)); } GEN core0(GEN n,long flag) { return flag? core2(n): core(n); } static long _mod4(GEN c) { long r, s = signe(c); if (!s) return 0; r = mod4(c); if (s < 0) r = 4-r; return r; } GEN coredisc(GEN n) { pari_sp av = avma; GEN c = core(n); if (_mod4(c)<=1) return c; /* c = 0 or 1 mod 4 */ return gerepileuptoint(av, shifti(c,2)); } GEN coredisc2(GEN n) { pari_sp av = avma; GEN y = core2_i(n); GEN c = gel(y,1), f = gel(y,2); if (_mod4(c)<=1) return gerepilecopy(av, y); y = cgetg(3,t_VEC); gel(y,1) = shifti(c,2); gel(y,2) = gmul2n(f,-1); return gerepileupto(av, y); } GEN coredisc0(GEN n,long flag) { return flag? coredisc2(n): coredisc(n); } long omega(GEN n) { pari_sp av = avma; GEN F, P; if ((F = check_arith_non0(n,"omega"))) { long n; P = gel(F,1); n = lg(P)-1; if (n && equalim1(gel(P,1))) n--; return n; } else if (lgefint(n) == 3) { if (n[2] == 1) return 0; F = factoru(n[2]); } else F = absi_factor(n); P = gel(F,1); avma = av; return lg(P)-1; } long bigomega(GEN n) { pari_sp av = avma; GEN F, E; if ((F = check_arith_non0(n,"bigomega"))) { GEN P = gel(F,1); long n = lg(P)-1; E = gel(F,2); if (n && equalim1(gel(P,1))) E = vecslice(E,2,n); E = ZV_to_zv(E); } else if (lgefint(n) == 3) { if (n[2] == 1) return 0; F = factoru(n[2]); E = gel(F,2); } else E = ZV_to_zv(gel(absi_factor(n), 2)); avma = av; return zv_sum(E); } /* assume f = factoru(n), possibly with 0 exponents. Return phi(n) */ ulong eulerphiu_fact(GEN f) { GEN P = gel(f,1), E = gel(f,2); long i, m = 1, l = lg(P); for (i = 1; i < l; i++) { ulong p = P[i], e = E[i]; if (!e) continue; if (p == 2) { if (e > 1) m <<= e-1; } else { m *= (p-1); if (e > 1) m *= upowuu(p, e-1); } } return m; } ulong eulerphiu(ulong n) { pari_sp av = avma; GEN F; if (!n) return 2; F = factoru(n); avma = av; return eulerphiu_fact(F); } GEN eulerphi(GEN n) { pari_sp av = avma; GEN Q, F, P, E; long i, l; if ((F = check_arith_all(n,"eulerphi"))) { F = clean_Z_factor(F); n = (typ(n) == t_VEC)? gel(n,1): factorback(F); if (lgefint(n) == 3) { ulong e; F = mkmat2(ZV_to_nv(gel(F,1)), ZV_to_nv(gel(F,2))); e = eulerphiu_fact(F); avma = av; return utoipos(e); } } else if (lgefint(n) == 3) return utoipos(eulerphiu((ulong)n[2])); else F = absi_factor(n); if (!signe(n)) return gen_2; P = gel(F,1); E = gel(F,2); l = lg(P); Q = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN p = gel(P,i), q; ulong v = itou(gel(E,i)); q = subiu(p,1); if (v != 1) q = mulii(q, v == 2? p: powiu(p, v-1)); gel(Q,i) = q; } return gerepileuptoint(av, ZV_prod(Q)); } static GEN numdiv_aux(GEN F) { GEN x, E = gel(F,2); long i, l = lg(E); x = cgetg(l, t_VECSMALL); for (i=1; i 1; v--) u = addsi(1, mului(p, u)); return u; } /* 1 + q + ... + q^v */ static GEN euler_sumdiv(GEN q, long v) { GEN u = addui(1, q); for (; v > 1; v--) u = addui(1, mulii(q, u)); return u; } static GEN u_euler_sumdivk(ulong p, long v, long k) { return euler_sumdiv(powuu(p,k), v); } static GEN euler_sumdivk(GEN p, long v, long k) { return euler_sumdiv(powiu(p,k), v); } static GEN sumdiv_aux(GEN F) { GEN x, P = gel(F,1), E = gel(F,2); long i, l = lg(P); x = cgetg(l, t_VEC); for (i=1; i 0) return gerepileuptoint(av, P); return gerepileupto(av, gdiv(P, powiu(n,k))); } /* K t_VECSMALL of k >= 0 */ GEN usumdivkvec(ulong n, GEN K) { pari_sp av = avma; GEN F = factoru(n), P = gel(F,1), E = gel(F,2), Z, S; long i,j, l = lg(P), lK = lg(K); Z = cgetg(l, t_VEC); S = cgetg(lK, t_VEC); for (j=1; j 1) return 0; return 1; } long uissquarefree(ulong n) { if (!n) return 0; return moebiusu(n)? 1: 0; } long Z_issquarefree(GEN n) { switch(lgefint(n)) { case 2: return 0; case 3: return uissquarefree(n[2]); } return moebius(n)? 1: 0; } long issquarefree(GEN x) { pari_sp av; GEN d; switch(typ(x)) { case t_INT: return Z_issquarefree(x); case t_POL: if (!signe(x)) return 0; av = avma; d = RgX_gcd(x, RgX_deriv(x)); avma = av; return (lg(d) == 3); default: pari_err_TYPE("issquarefree",x); return 0; /* not reached */ } } /*********************************************************************/ /** **/ /** DIGITS / SUM OF DIGITS **/ /** **/ /*********************************************************************/ 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, 12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11, 12,13,14,15,16,17,18,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, 12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11, 12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,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,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17, 9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15, 16,17,18,19,20,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,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11, 12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18, 19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,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,12,13,14,15,7,8,9,10,11, 12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10, 11,12,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17, 18,19,20,21,13,14,15,16,17,18,19,20,21,22,5,6,7,8,9,10,11,12,13,14,6,7,8,9, 10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9, 10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16, 17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14, 15,16,17,18,19,20,21,22,23,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,12,13,14, 15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13, 14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20, 21,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18, 19,20,21,22,23,24,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9, 10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16, 17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14, 15,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17,18,19,20,21, 22,23,24,25,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11, 12,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18, 19,20,21,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16, 17,18,19,20,21,22,23,24,16,17,18,19,20,21,22,23,24,25,17,18,19,20,21,22,23, 24,25,26,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12, 13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19, 20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17, 18,19,20,21,22,23,24,25,17,18,19,20,21,22,23,24,25,26,18,19,20,21,22,23,24, 25,26,27 }; ulong sumdigitsu(ulong n) { ulong s = 0; while (n) { s += DS[n % 1000]; n /= 1000; } return s; } /* res=array of 9-digits integers, return \sum_{0 <= i < l} sumdigits(res[i]) */ static ulong sumdigits_block(ulong *res, long l) { long s = sumdigitsu(*--res); while (--l > 0) s += sumdigitsu(*--res); return s; } GEN sumdigits(GEN n) { pari_sp av = avma; ulong s, *res; long l; if (typ(n) != t_INT) pari_err_TYPE("sumdigits", n); l = lgefint(n); switch(l) { case 2: return gen_0; case 3: return utoipos(sumdigitsu(n[2])); } res = convi(n, &l); if ((ulong)l < ULONG_MAX / 81) { s = sumdigits_block(res, l); avma = av; return utoipos(s); } else /* Huge. Overflows ulong */ { const long L = (long)(ULONG_MAX / 81); GEN S = gen_0; while (l > L) { S = addiu(S, sumdigits_block(res, L)); res += L; l -= L; } if (l) S = addiu(S, sumdigits_block(res, l)); return gerepileuptoint(av, S); } } 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) { pari_sp av=avma; long lz; 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 { ulong b = B[2]; z = zero_zv(lz); digits_dacsmall(x,b,lz,(ulong*)(z+1)); return gerepileupto(av,vecsmall_to_vec(z)); } } pari-2.7.5/src/basemath/rootpol.c0000644000175000017500000016274012516207407015341 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* ROOTS OF COMPLEX POLYNOMIALS */ /* (original code contributed by Xavier Gourdon, INRIA RR 1852) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" static const double pariINFINITY = 100000.; /********************************************************************/ /** **/ /** FAST ARITHMETIC over Z[i] **/ /** **/ /********************************************************************/ static THREAD long KARASQUARE_LIMIT, COOKSQUARE_LIMIT; /* fast sum of x,y: t_INT or t_COMPLEX(t_INT) */ static GEN addCC(GEN x, GEN y) { GEN z; if (typ(x) == t_INT) { if (typ(y) == t_INT) return addii(x,y); /* ty == t_COMPLEX */ z = cgetg(3,t_COMPLEX); gel(z,1) = addii(x, gel(y,1)); gel(z,2) = icopy(gel(y,2)); return z; } /* tx == t_COMPLEX */ z = cgetg(3,t_COMPLEX); if (typ(y) == t_INT) { gel(z,1) = addii(gel(x,1),y); gel(z,2) = icopy(gel(x,2)); return z; } /* ty == t_COMPLEX */ gel(z,1) = addii(gel(x,1),gel(y,1)); gel(z,2) = addii(gel(x,2),gel(y,2)); return z; } /* fast product of x,y: t_INT or t_COMPLEX(t_INT) */ static GEN mulCC(GEN x, GEN y) { GEN z; if (typ(x) == t_INT) { if (typ(y) == t_INT) return mulii(x,y); /* ty == t_COMPLEX */ z = cgetg(3,t_COMPLEX); gel(z,1) = mulii(x, gel(y,1)); gel(z,2) = mulii(x, gel(y,2)); return z; } /* tx == t_COMPLEX */ z = cgetg(3,t_COMPLEX); if (typ(y) == t_INT) { gel(z,1) = mulii(gel(x,1),y); gel(z,2) = mulii(gel(x,2),y); return z; } /* ty == t_COMPLEX */ { pari_sp av = avma, tetpil; GEN p1, p2; p1 = mulii(gel(x,1),gel(y,1)); p2 = mulii(gel(x,2),gel(y,2)); y = mulii(addii(gel(x,1),gel(x,2)), addii(gel(y,1),gel(y,2))); x = addii(p1,p2); tetpil = avma; gel(z,1) = subii(p1,p2); gel(z,2) = subii(y,x); gerepilecoeffssp(av,tetpil,z+1,2); return z; } } /* fast squaring x: t_INT or t_COMPLEX(t_INT) */ static GEN sqrCC(GEN x) { GEN z; if (typ(x) == t_INT) return sqri(x); /* tx == t_COMPLEX */ z = cgetg(3,t_COMPLEX); { pari_sp av = avma, tetpil; GEN y, p1, p2; p1 = sqri(gel(x,1)); p2 = sqri(gel(x,2)); y = sqri(addii(gel(x,1),gel(x,2))); x = addii(p1,p2); tetpil = avma; gel(z,1) = subii(p1,p2); gel(z,2) = subii(y,x); gerepilecoeffssp(av,tetpil,z+1,2); return z; } } static void set_karasquare_limit(long bit) { if (bit<600) { KARASQUARE_LIMIT=8; COOKSQUARE_LIMIT=400; } else if (bit<2000) { KARASQUARE_LIMIT=4; COOKSQUARE_LIMIT=200; } else if (bit<3000) { KARASQUARE_LIMIT=4; COOKSQUARE_LIMIT=125; } else if (bit<5000) { KARASQUARE_LIMIT=2; COOKSQUARE_LIMIT= 75; } else { KARASQUARE_LIMIT=1; COOKSQUARE_LIMIT= 50; } } /* assume lP > 0, lP = lgpol(P) */ static GEN CX_square_spec(GEN P, long lP) { GEN s, t; long i, j, l, nn, n = lP - 1; pari_sp av; nn = n<<1; s = cgetg(nn+3,t_POL); s[1] = evalsigne(1)|evalvarn(0); gel(s,2) = sqrCC(gel(P,0)); /* i = 0 */ for (i=1; i<=n; i++) { av = avma; l = (i+1)>>1; t = mulCC(gel(P,0), gel(P,i)); /* j = 0 */ for (j=1; j>1))); gel(s,i+2) = gerepileupto(av, t); } gel(s,nn+2) = sqrCC(gel(P,n)); /* i = nn */ for ( ; i>1; t = mulCC(gel(P,i-n),gel(P,n)); /* j = i-n */ for (j=i-n+1; j>1))); gel(s,i+2) = gerepileupto(av, t); } return normalizepol_lg(s, nn+3); } /* not stack clean */ static GEN RgX_addspec(GEN x, long nx, GEN y, long ny) { GEN z, t; long i; if (nx == ny) { z = cgetg(nx+2,t_POL); z[1] = evalsigne(1)|evalvarn(0); t = z+2; for (i=0; i < nx; i++) gel(t,i) = gadd(gel(x,i),gel(y,i)); return normalizepol_lg(z, nx+2); } if (ny < nx) { z = cgetg(nx+2,t_POL); z[1] = evalsigne(1)|evalvarn(0); t = z+2; for (i=0; i < ny; i++) gel(t,i) = gadd(gel(x,i),gel(y,i)); for ( ; i < nx; i++) gel(t,i) = gel(x,i); return normalizepol_lg(z, nx+2); } else { z = cgetg(ny+2,t_POL); z[1] = evalsigne(1)|evalvarn(0); t = z+2; for (i=0; i < nx; i++) gel(t,i) = gadd(gel(x,i),gel(y,i)); for ( ; i < ny; i++) gel(t,i) = gel(y,i); return normalizepol_lg(z, ny+2); } } /* nx = lgpol(x) */ static GEN RgX_s_mulspec(GEN x, long nx, long s) { GEN z, t; long i; if (!s || !nx) return pol_0(0); z = cgetg(nx+2, t_POL); z[1] = evalsigne(1)|evalvarn(0); t = z + 2; for (i=0; i < nx; i++) gel(t,i) = gmulgs(gel(x,i), s); return z; } /* nx = lgpol(x), return x << s. Inefficient if s = 0... */ static GEN RgX_shiftspec(GEN x, long nx, long s) { GEN z, t; long i; if (!nx) return pol_0(0); z = cgetg(nx+2, t_POL); z[1] = evalsigne(1)|evalvarn(0); t = z + 2; for (i=0; i < nx; i++) gel(t,i) = gmul2n(gel(x,i), s); return z; } /* spec function. nP = lgpol(P) */ static GEN karasquare(GEN P, long nP) { GEN Q, s0, s1, s2, a, t; long n0, n1, i, l, N, N0, N1, n = nP - 1; /* degree(P) */ pari_sp av; if (n <= KARASQUARE_LIMIT) return nP? CX_square_spec(P, nP): pol_0(0); av = avma; n0 = (n>>1) + 1; n1 = nP - n0; s0 = karasquare(P, n0); Q = P + n0; s2 = karasquare(Q, n1); s1 = RgX_addspec(P, n0, Q, n1); s1 = RgX_sub(karasquare(s1+2, lgpol(s1)), RgX_add(s0,s2)); N = (n<<1) + 1; a = cgetg(N + 2, t_POL); a[1] = evalsigne(1)|evalvarn(0); t = a+2; l = lgpol(s0); s0 += 2; N0 = n0<<1; for (i=0; i < l; i++) gel(t,i) = gel(s0,i); for ( ; i < N0; i++) gel(t,i) = gen_0; t = a+2 + N0; l = lgpol(s2); s2 += 2; N1 = N - N0; for (i=0; i < l; i++) gel(t,i) = gel(s2,i); for ( ; i < N1; i++) gel(t,i) = gen_0; t = a+2 + n0; l = lgpol(s1); s1 += 2; for (i=0; i < l; i++) gel(t,i) = gadd(gel(t,i), gel(s1,i)); return gerepilecopy(av, normalizepol_lg(a, N+2)); } /* spec function. nP = lgpol(P) */ static GEN cook_square(GEN P, long nP) { GEN Q, p0, p1, p2, p3, q, r, t, vp, vm; long n0, n3, i, j, n = nP - 1; pari_sp av; if (n <= COOKSQUARE_LIMIT) return nP? karasquare(P, nP): pol_0(0); av = avma; n0 = (n+1) >> 2; n3 = n+1 - 3*n0; p0 = P; p1 = p0+n0; p2 = p1+n0; p3 = p2+n0; /* lgpol(p0,p1,p2) = n0, lgpol(p3) = n3 */ q = cgetg(8,t_VEC) + 4; Q = cook_square(p0, n0); r = RgX_addspec(p0,n0, p2,n0); t = RgX_addspec(p1,n0, p3,n3); gel(q,-1) = RgX_sub(r,t); gel(q,1) = RgX_add(r,t); r = RgX_addspec(p0,n0, RgX_shiftspec(p2,n0, 2)+2,n0); t = gmul2n(RgX_addspec(p1,n0, RgX_shiftspec(p3,n3, 2)+2,n3), 1); gel(q,-2) = RgX_sub(r,t); gel(q,2) = RgX_add(r,t); r = RgX_addspec(p0,n0, RgX_s_mulspec(p2,n0, 9)+2,n0); t = gmulsg(3, RgX_addspec(p1,n0, RgX_s_mulspec(p3,n3, 9)+2,n3)); gel(q,-3) = RgX_sub(r,t); gel(q,3) = RgX_add(r,t); r = new_chunk(7); vp = cgetg(4,t_VEC); vm = cgetg(4,t_VEC); for (i=1; i<=3; i++) { GEN a = gel(q,i), b = gel(q,-i); a = cook_square(a+2, lgpol(a)); b = cook_square(b+2, lgpol(b)); gel(vp,i) = RgX_add(b, a); gel(vm,i) = RgX_sub(b, a); } gel(r,0) = Q; gel(r,1) = gdivgs(gsub(gsub(gmulgs(gel(vm,2),9),gel(vm,3)), gmulgs(gel(vm,1),45)), 60); gel(r,2) = gdivgs(gadd(gadd(gmulgs(gel(vp,1),270),gmulgs(Q,-490)), gadd(gmulgs(gel(vp,2),-27),gmulgs(gel(vp,3),2))), 360); gel(r,3) = gdivgs(gadd(gadd(gmulgs(gel(vm,1),13),gmulgs(gel(vm,2),-8)), gel(vm,3)), 48); gel(r,4) = gdivgs(gadd(gadd(gmulgs(Q,56),gmulgs(gel(vp,1),-39)), gsub(gmulgs(gel(vp,2),12),gel(vp,3))), 144); gel(r,5) = gdivgs(gsub(gadd(gmulgs(gel(vm,1),-5),gmulgs(gel(vm,2),4)), gel(vm,3)), 240); gel(r,6) = gdivgs(gadd(gadd(gmulgs(Q,-20),gmulgs(gel(vp,1),15)), gadd(gmulgs(gel(vp,2),-6),gel(vp,3))), 720); q = cgetg(2*n+3,t_POL); q[1] = evalsigne(1)|evalvarn(0); t = q+2; for (i=0; i<=2*n; i++) gel(t,i) = gen_0; for (i=0; i<=6; i++,t += n0) { GEN h = gel(r,i); long d = lgpol(h); h += 2; for (j=0; j>1)+1; n1 = n+1 - n0; /* n1 <= n0 <= n1+1 */ p0 = new_chunk(n0); p1 = new_chunk(n1); for (i=0; i 2^21, it is correct to 2 ulp */ static double mydbllog2i(GEN x) { #ifdef LONG_IS_64BIT const double W = 1/(4294967296. * 4294967296.); /* 2^-64 */ #else const double W = 1/4294967296.; /*2^-32*/ #endif GEN m; long lx = lgefint(x); double l; if (lx == 2) return -pariINFINITY; m = int_MSW(x); l = (double)(ulong)*m; if (lx == 3) return log2(l); l += ((double)(ulong)*int_precW(m)) * W; /* at least m = min(53,BIL) bits are correct in the mantissa, thus log2 * is correct with error < log(1 + 2^-m) ~ 2^-m. Adding the correct * exponent BIL(lx-3) causes 1ulp further round-off error */ return log2(l) + (double)(BITS_IN_LONG*(lx-3)); } /* return log(|x|) or -pariINFINITY */ static double mydbllogr(GEN x) { if (!signe(x)) return -pariINFINITY; return LOG2*dbllog2r(x); } /* return log2(|x|) or -pariINFINITY */ static double mydbllog2r(GEN x) { if (!signe(x)) return -pariINFINITY; return dbllog2r(x); } static double dbllog2mp(GEN x) { return typ(x) == t_INT? mydbllog2i(x): mydbllog2r(x); } double dbllog2(GEN z) { double x, y; switch(typ(z)) { case t_INT: return mydbllog2i(z); case t_REAL: return mydbllog2r(z); default: /*t_COMPLEX*/ x = dbllog2mp(gel(z,1)); y = dbllog2mp(gel(z,2)); if (fabs(x-y) > 10) return maxdd(x,y); return x + 0.5*log2(1 + exp2(2*(y-x))); } } static GEN /* beware overflow */ dblexp(double x) { return fabs(x) < 100.? dbltor(exp(x)): mpexp(dbltor(x)); } /* find s such that A_h <= 2^s <= 2 A_i for one h and all i < n = deg(p), * with A_i := (binom(n,i) lc(p) / p_i) ^ 1/(n-i), and p = sum p_i X^i */ static long findpower(GEN p) { double x, L, mins = pariINFINITY; long n = degpol(p),i; L = dbllog2(gel(p,n+2)); /* log2(lc * binom(n,i)) */ for (i=n-1; i>=0; i--) { L += log2((double)(i+1) / (double)(n-i)); x = dbllog2(gel(p,i+2)); if (x != -pariINFINITY) { double s = (L - x) / (double)(n-i); if (s < mins) mins = s; } } i = (long)ceil(mins); if (i - mins > 1 - 1e-12) i--; return i; } /* returns the exponent for logmodulus(), from the Newton diagram */ static long newton_polygon(GEN p, long k) { pari_sp av = avma; double *logcoef, slope; long n = degpol(p), i, j, h, l, *vertex; init_dalloc(); logcoef = (double*)stack_malloc((n+1)*sizeof(double)); vertex = (long*)new_chunk(n+1); /* vertex[i] = 1 if i a vertex of convex hull, 0 otherwise */ for (i=0; i<=n; i++) { logcoef[i] = dbllog2(gel(p,2+i)); vertex[i] = 0; } vertex[0] = 1; /* sentinel */ for (i=0; i < n; i=h) { slope = logcoef[i+1]-logcoef[i]; for (j = h = i+1; j<=n; j++) { double pij = (logcoef[j]-logcoef[i])/(double)(j-i); if (slope < pij) { slope = pij; h = j; } } vertex[h] = 1; } h = k; while (!vertex[h]) h++; l = k-1; while (!vertex[l]) l--; avma = av; return (long)floor((logcoef[h]-logcoef[l])/(double)(h-l) + 0.5); } /* change z into z*2^e, where z is real or complex of real */ static void myshiftrc(GEN z, long e) { if (typ(z)==t_COMPLEX) { if (signe(gel(z,1))) shiftr_inplace(gel(z,1), e); if (signe(gel(z,2))) shiftr_inplace(gel(z,2), e); } else if (signe(z)) shiftr_inplace(z, e); } /* return z*2^e, where z is integer or complex of integer (destroy z) */ static GEN myshiftic(GEN z, long e) { if (typ(z)==t_COMPLEX) { gel(z,1) = signe(gel(z,1))? mpshift(gel(z,1),e): gen_0; gel(z,2) = mpshift(gel(z,2),e); return z; } return signe(z)? mpshift(z,e): gen_0; } /* as real_1 with precision in bits, not in words */ static GEN myreal_1(long bit) { if (bit < 0) bit = 0; return real_1(nbits2prec(bit)); } static GEN RgX_gtofp_bit(GEN q, long bit) { if (bit < 0) bit = 0; return RgX_gtofp(q, nbits2prec(bit)); } static GEN mygprecrc(GEN x, long prec, long e) { GEN y; switch(typ(x)) { case t_REAL: return signe(x)? rtor(x, prec): real_0_bit(e); case t_COMPLEX: y = cgetg(3,t_COMPLEX); gel(y,1) = mygprecrc(gel(x,1),prec,e); gel(y,2) = mygprecrc(gel(x,2),prec,e); return y; default: return gcopy(x); } } /* gprec behaves badly with the zero for polynomials. The second parameter in mygprec is the precision in base 2 */ static GEN mygprec(GEN x, long bit) { long lx, i, e, prec; GEN y; if (bit < 0) bit = 0; /* should rarely happen */ e = gexpo(x) - bit; prec = nbits2prec(bit); switch(typ(x)) { case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i0; i--) { gel(r,i+2) = gmul(t, gel(q,i+2)); t = mulrr(t, iR); } gel(r,2) = gmul(t, gel(q,2)); return r; } /* change q in 2^(n*e) p(x*2^(-e)), n=deg(q) [ ~as above with R = 2^-e ]*/ static void homothetie2n(GEN p, long e) { if (e) { long i,n = lg(p)-1; for (i=2; i<=n; i++) myshiftrc(gel(p,i), (n-i)*e); } } /* return 2^f * 2^(n*e) p(x*2^(-e)), n=deg(q) */ static void homothetie_gauss(GEN p, long e, long f) { if (e || f) { long i, n = lg(p)-1; for (i=2; i<=n; i++) gel(p,i) = myshiftic(gel(p,i), f+(n-i)*e); } } /* Lower bound on the modulus of the largest root z_0 * k is set to an upper bound for #{z roots, |z-z_0| < eps} */ static double lower_bound(GEN p, long *k, double eps) { long n = degpol(p), i, j; pari_sp ltop = avma; GEN a, s, S, ilc; double r, R, rho; if (n < 4) { *k = n; return 0.; } S = cgetg(5,t_VEC); a = cgetg(5,t_VEC); ilc = gdiv(real_1(DEFAULTPREC), gel(p,n+2)); for (i=1; i<=4; i++) gel(a,i) = gmul(ilc,gel(p,n+2-i)); /* i = 1 split out from next loop for efficiency and initialization */ s = gel(a,1); gel(S,1) = gneg(s); /* Newton sum S_i */ rho = r = gtodouble(gabs(s,3)); R = r / n; for (i=2; i<=4; i++) { s = gmulsg(i,gel(a,i)); for (j=1; j 0.) { r = exp(log(r/n) / (double)i); if (r > R) R = r; } } if (R > 0. && eps < 1.2) *k = (long)floor((rho/R + n) / (1 + exp(-eps)*cos(eps))); else *k = n; avma = ltop; return R; } /* log of modulus of the largest root of p with relative error tau. Assume * P(0) != 0 and P non constant */ static double logmax_modulus(GEN p, double tau) { GEN r,q,aux,gunr; pari_sp av, ltop = avma; long i,k,n=degpol(p),nn,bit,M,e; double rho,eps, tau2 = (tau > 3.0)? 0.5: tau/6.; r = cgeti(BIGDEFAULTPREC); av = avma; eps = - 1/log(1.5*tau2); /* > 0 */ bit = (long) ((double) n*log2(1./tau2)+3*log2((double) n))+1; gunr = myreal_1(bit+2*n); aux = gdiv(gunr, gel(p,2+n)); q = RgX_Rg_mul(p, aux); gel(q,2+n) = gunr; e = findpower(q); homothetie2n(q,e); affsi(e, r); q = pol_to_gaussint(q, bit); M = (long) (log2( log(4.*n) / (2*tau2) )) + 2; nn = n; for (i=0,e=0;;) { /* nn = deg(q) */ rho = lower_bound(q, &k, eps); if (rho > exp2(-(double)e)) e = (long)-floor(log2(rho)); affii(shifti(addis(r,e), 1), r); if (++i == M) break; bit = (long) ((double)k * log2(1./tau2) + (double)(nn-k)*log2(1./eps) + 3*log2((double)nn)) + 1; homothetie_gauss(q, e, bit-(long)floor(dbllog2(gel(q,2+nn))+0.5)); nn -= RgX_valrem(q, &q); set_karasquare_limit(gexpo(q)); q = gerepileupto(av, graeffe(q)); tau2 *= 1.5; if (tau2 > 0.9) tau2 = 0.5; eps = -1/log(tau2); /* > 0 */ e = findpower(q); } if (!signe(r)) { avma = ltop; return 0.; } r = itor(r, DEFAULTPREC); shiftr_inplace(r, -M); avma = ltop; return -rtodbl(r) * LOG2; /* -log(2) sum e_i 2^-i */ } /* assume P non constant */ GEN logmax_modulus_bound(GEN P) { (void)RgX_valrem_inexact(P,&P); return lg(P)==3? gen_0: dblexp(logmax_modulus(P, 0.01) + 0.01); } /* log of modulus of the smallest root of p, with relative error tau */ static double logmin_modulus(GEN p, double tau) { pari_sp av = avma; double r; if (gequal0(gel(p,2))) return -pariINFINITY; r = - logmax_modulus(RgX_recip_shallow(p),tau); avma = av; return r; } /* return the log of the k-th modulus (ascending order) of p, rel. error tau*/ static double logmodulus(GEN p, long k, double tau) { GEN q; long i, kk = k, imax, n = degpol(p), nn, bit, e; pari_sp av, ltop=avma; double r, tau2 = tau/6; bit = (long)(n * (2. + log2(3.*n/tau2))); av = avma; q = gprec_w(p, nbits2prec(bit)); q = RgX_gtofp_bit(q, bit); e = newton_polygon(q,k); r = (double)e; homothetie2n(q,e); imax = (long)(log2(3./tau) + log2(log(4.*n)))+1; for (i=1; i 1.) tau2 = 1.; bit = 1 + (long)(nn*(2. + log2(3.*nn/tau2))); } avma = ltop; return -r * LOG2; } /* return the log of the k-th modulus r_k of p, rel. error tau, knowing that * rmin < r_k < rmax. This information helps because we may reduce precision * quicker */ static double logpre_modulus(GEN p, long k, double tau, double lrmin, double lrmax) { GEN q; long n = degpol(p), i, imax, imax2, bit; pari_sp ltop = avma, av; double lrho, aux, tau2 = tau/6.; aux = (lrmax - lrmin) / 2. + 4*tau2; imax = (long) log2(log((double)n)/ aux); if (imax <= 0) return logmodulus(p,k,tau); lrho = (lrmin + lrmax) / 2; av = avma; bit = (long)(n*(2. + aux / LOG2 - log2(tau2))); q = homothetie(p, lrho, bit); imax2 = (long)(log2(3./tau * log(4.*n))) + 1; if (imax > imax2) imax = imax2; for (i=0; i L) { L = d; k = i; } } return k; } /* Returns k such that r_k e^(-tau) < R < r_{k+1} e^tau. * Assume that l <= k <= n-l */ static long dual_modulus(GEN p, double lrho, double tau, long l) { long i, imax, delta_k = 0, n = degpol(p), nn, v2, v, bit, ll = l; double tau2 = tau * 7./8.; pari_sp av = avma; GEN q; bit = 6*n - 5*l + (long)(n*(-log2(tau2) + tau2 * 8./7.)); q = homothetie(p, lrho, bit); imax = (long)(log(log(2.*n)/tau2)/log(7./4.)+1); for (i=0; i>2; l2 = 2*l1; l3 = l1+l2; step4 = step<<2; fft(Omega,p, f, step4,l1); fft(Omega,p+step, f+l1,step4,l1); fft(Omega,p+(step<<1),f+l2,step4,l1); fft(Omega,p+3*step, f+l3,step4,l1); ff = cgetg(l+1,t_VEC); for (i=0; i>1), N4 = (N>>2), N8 = (N>>3); RU = (GEN*)cgetg(N+1,t_VEC); RU++; RU[0] = myreal_1(bit); RU[1] = z; for (i=1; i>1; RU[0] = gen_1; RU[1] = z; for (i=2; i l) pari_err_DIM("FFT"); if (n < l) { z = cgetg(l, t_VECSMALL); /* cf stackdummy */ for (i = 1; i < n; i++) z[i] = x[i]; for ( ; i < l; i++) gel(z,i) = gen_0; } else z = x; y = cgetg(l, t_VEC); fft(Omega+1, z+1, y+1, 1, l-1); return y; } /* returns 1 if p has only real coefficients, 0 else */ static int isreal(GEN p) { long i; for (i = lg(p)-1; i > 1; i--) if (typ(gel(p,i)) == t_COMPLEX) return 0; return 1; } /* x non complex */ static GEN abs_update_r(GEN x, double *mu) { GEN y = gtofp(x, DEFAULTPREC); double ly = mydbllogr(y); if (ly < *mu) *mu = ly; setabssign(y); return y; } /* return |x|, low accuracy. Set *mu = min(log(y), *mu) */ static GEN abs_update(GEN x, double *mu) { GEN y, xr, yr; double ly; if (typ(x) != t_COMPLEX) return abs_update_r(x, mu); xr = gel(x,1); yr = gel(x,2); if (gequal0(xr)) return abs_update_r(yr,mu); if (gequal0(yr)) return abs_update_r(xr,mu); /* have to treat 0 specially: 0E-10 + 1e-20 = 0E-10 */ xr = gtofp(xr, DEFAULTPREC); yr = gtofp(yr, DEFAULTPREC); y = sqrtr(addrr(sqrr(xr), sqrr(yr))); ly = mydbllogr(y); if (ly < *mu) *mu = ly; return y; } static void parameters(GEN p, long *LMAX, double *mu, double *gamma, int polreal, double param, double param2) { 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); bit = gexpo(p) + (long)param2+8; Lmax = 4; while (Lmax <= n) Lmax <<= 1; NN = (long)(param*3.14)+1; if (NN < Lmax) NN = Lmax; K = NN/Lmax; if (K & 1) K++; NN = Lmax*K; if (polreal) K = K/2+1; Omega = initRU(Lmax,bit); prim = RUgen(NN, bit); q = mygprec(p,bit) + 2; A = cgetg(Lmax+1,t_VEC); A++; pc= cgetg(Lmax+1,t_VEC); pc++; for (i=0; i <= n; i++) gel(pc,i)= gel(q,i); for ( ; i0 && i1) pari_warn(warnmem,"parameters"); gerepileall(av2,2, &g,&RU); } } *gamma = mydbllog2r(divru(g,NN)); *LMAX = Lmax; avma = av; } /* NN is a multiple of Lmax */ static void dft(GEN p, long k, long NN, long Lmax, long bit, GEN F, GEN H, long polreal) { GEN Omega, q, qd, pc, pd, A, B, C, RU, aux, U, W, prim, prim2; long n = degpol(p), i, j, K; pari_sp ltop; Omega = initRU(Lmax,bit); prim = RUgen(NN, bit); RU = cgetg(n+2,t_VEC); RU++; K = NN/Lmax; if (polreal) K = K/2+1; q = mygprec(p,bit); qd = RgX_deriv(q); A = cgetg(Lmax+1,t_VEC); A++; B = cgetg(Lmax+1,t_VEC); B++; C = cgetg(Lmax+1,t_VEC); C++; pc = cgetg(Lmax+1,t_VEC); pc++; pd = cgetg(Lmax+1,t_VEC); pd++; pc[0] = q[2]; for (i=n+1; i0 && i-bit && i1) pari_warn(warnmem,"refine_H"); gerepileall(ltop,2, &D,&H); } bit1 = -error + Sbit; aux = RgX_mul(mygprec(H,bit1), mygprec(D,bit1)); aux = RgX_rem(mygprec(aux,bit1), mygprec(F,bit1)); bit1 = -error*2 + Sbit; if (bit1 > bit2) bit1 = bit2; H = RgX_add(mygprec(H,bit1), aux); D = Rg_RgX_sub(gen_1, RgX_rem(RgX_mul(H,G),F)); error = gexpo(D); if (error < -bit1) error = -bit1; } if (error > -bit/2) return NULL; /* FAIL */ return gerepilecopy(ltop,H); } /* return 0 if fails, 1 else */ static long 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); FF = *F; GG = RgX_divrem(p, FF, &r); error = gexpo(r); if (error <= -bit) error = 1-bit; normF = gexpo(FF); normG = gexpo(GG); enh = gexpo(H); if (enh < 0) enh = 0; Sbit = normF + 2*normG + enh + (long)(4.*log2((double)n)+gamma) + 1; Sbit2 = enh + 2*(normF+normG) + (long)(2.*gamma+5.*log2((double)n)) + 1; bit2 = bit + Sbit; for (i=0; error>-bit && i= 2) { Sbit += n; Sbit2 += n; bit2 += n; } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"refine_F"); gerepileall(av,4, &FF,&GG,&r,&HH); } bit1 = -error + Sbit2; HH = refine_H(mygprec(FF,bit1), mygprec(GG,bit1), mygprec(HH,bit1), 1-error, Sbit2); if (!HH) return 0; /* FAIL */ bit1 = -error + Sbit; r = RgX_mul(mygprec(HH,bit1), mygprec(r,bit1)); f0 = RgX_rem(mygprec(r,bit1), mygprec(FF,bit1)); bit1 = -2*error + Sbit; if (bit1 > bit2) bit1 = bit2; FF = gadd(mygprec(FF,bit1),f0); bit1 = -3*error + Sbit; if (bit1 > bit2) bit1 = bit2; GG = RgX_divrem(mygprec(p,bit1), mygprec(FF,bit1), &r); error = gexpo(r); if (error < -bit1) error = -bit1; } if (error>-bit) return 0; /* FAIL */ *F = FF; *G = GG; return 1; } /* returns F and G from the unit circle U such that |p-FG|<2^(-bit) |cd|, where cd is the leading coefficient of p */ static void split_fromU(GEN p, long k, double delta, long bit, GEN *F, GEN *G, double param, double param2) { GEN pp, FF, GG, H; long n = degpol(p), NN, bit2, Lmax; int polreal = isreal(p); pari_sp ltop; double mu, gamma; pp = gdiv(p, gel(p,2+n)); parameters(pp, &Lmax,&mu,&gamma, polreal,param,param2); H = cgetg(k+2,t_POL); H[1] = p[1]; FF = cgetg(k+3,t_POL); FF[1]= p[1]; gel(FF,k+2) = gen_1; NN = (long)(0.5/delta); NN |= 1; if (NN < 2) NN = 2; NN *= Lmax; ltop = avma; for(;;) { bit2 = (long)(((double)NN*delta-mu)/LOG2) + gexpo(pp) + 8; dft(pp, k, NN, Lmax, bit2, FF, H, polreal); if (refine_F(pp,&FF,&GG,H,bit,gamma)) break; NN <<= 1; avma = ltop; } *G = gmul(GG,gel(p,2+n)); *F = FF; } static void optimize_split(GEN p, long k, double delta, long bit, GEN *F, GEN *G, double param, double param2) { long n = degpol(p); GEN FF, GG; if (k <= n/2) split_fromU(p,k,delta,bit,F,G,param,param2); else { split_fromU(RgX_recip_shallow(p),n-k,delta,bit,&FF,&GG,param,param2); *F = RgX_recip_shallow(GG); *G = RgX_recip_shallow(FF); } } /********************************************************************/ /** **/ /** SEARCH FOR SEPARATING CIRCLE **/ /** **/ /********************************************************************/ /* return p(2^e*x) *2^(-n*e) */ static void scalepol2n(GEN p, long e) { long i,n=lg(p)-1; for (i=2; i<=n; i++) gel(p,i) = gmul2n(gel(p,i),(i-n)*e); } /* returns p(x/R)*R^n */ static GEN scalepol(GEN p, GEN R, long bit) { GEN q,aux,gR; long i; aux = gR = mygprec(R,bit); q = mygprec(p,bit); for (i=lg(p)-2; i>=2; i--) { gel(q,i) = gmul(aux,gel(q,i)); aux = gmul(aux,gR); } return q; } /* return (conj(a)X-1)^n * p[ (X-a) / (conj(a)X-1) ] */ static GEN 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); z = mkpoln(2, ca, negr(myreal_1(bit))); r = scalarpol(gel(p,2+n), 0); for (i=n-1; ; i--) { r = addmulXn(r, gmul(ma,r), 1); /* r *= (X - a) */ 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(DEBUGMEM>1) pari_warn(warnmem,"conformal_pol"); gerepileall(av,2, &r,&z); } } } static const double UNDEF = -100000.; static double logradius(double *radii, GEN p, long k, double aux, double *delta) { long i, n = degpol(p); double lrho, lrmin, lrmax; if (k > 1) { i = k-1; while (i>0 && radii[i] == UNDEF) i--; lrmin = logpre_modulus(p,k,aux, radii[i], radii[k]); } else /* k=1 */ lrmin = logmin_modulus(p,aux); radii[k] = lrmin; if (k+1=1; i--) { if (radii[i] == UNDEF || radii[i] > lrho) radii[i] = lrho; else lrho = radii[i]; } lrho = radii[k+1]; for (i=k+1; i<=n; i++) { if (radii[i] == UNDEF || radii[i] < lrho) radii[i] = lrho; else lrho = radii[i]; } *delta = (lrmax - lrmin) / 2; if (*delta > 1.) *delta = 1.; return (lrmin + lrmax) / 2; } static void update_radius(long n, double *radii, double lrho, double *par, double *par2) { double t, param = 0., param2 = 0.; long i; for (i=1; i<=n; i++) { radii[i] -= lrho; t = fabs(rtodbl( invr(subsr(1, dblexp(radii[i]))) )); param += t; if (t > 1.) param2 += log2(t); } *par = param; *par2 = param2; } /* apply the conformal mapping then split from U */ static void conformal_mapping(double *radii, GEN ctr, GEN p, long k, long bit, double aux, GEN *F,GEN *G) { long bit2, n = degpol(p), i; pari_sp ltop = avma, av; GEN q, FF, GG, a, R; double lrho, delta, param, param2; /* n * (2.*log2(2.732)+log2(1.5)) + 1 */ bit2 = bit + (long)(n*3.4848775) + 1; a = sqrtr_abs( stor(3, 2*MEDDEFAULTPREC - 2) ); a = divrs(a, -6); a = gmul(mygprec(a,bit2), mygprec(ctr,bit2)); /* a = -ctr/2sqrt(3) */ av = avma; q = conformal_pol(mygprec(p,bit2), a, bit2); for (i=1; i<=n; i++) if (radii[i] != UNDEF) /* update array radii */ { pari_sp av2 = avma; GEN t, r = dblexp(radii[i]), r2 = sqrr(r); /* 2(r^2 - 1) / (r^2 - 3(r-1)) */ t = divrr(shiftr((subrs(r2,1)),1), subrr(r2, mulur(3,subrs(r,1)))); radii[i] = mydbllogr(addsr(1,t)) / 2; avma = av2; } lrho = logradius(radii, q,k,aux/10., &delta); update_radius(n, radii, lrho, ¶m, ¶m2); bit2 += (long)(n * fabs(lrho)/LOG2 + 1.); R = mygprec(dblexp(-lrho), bit2); q = scalepol(q,R,bit2); gerepileall(av,2, &q,&R); optimize_split(q,k,delta,bit2,&FF,&GG,param,param2); bit2 += n; R = invr(R); FF = scalepol(FF,R,bit2); GG = scalepol(GG,R,bit2); a = mygprec(a,bit2); FF = conformal_pol(FF,a,bit2); GG = conformal_pol(GG,a,bit2); a = invr(subsr(1, gnorm(a))); FF = RgX_Rg_mul(FF, powru(a,k)); GG = RgX_Rg_mul(GG, powru(a,n-k)); *F = mygprec(FF,bit+n); *G = mygprec(GG,bit+n); gerepileall(ltop,2, F,G); } /* split p, this time without scaling. returns in F and G two polynomials * such that |p-FG|< 2^(-bit)|p| */ static void split_2(GEN p, long bit, GEN ctr, double thickness, GEN *F, GEN *G) { GEN q, FF, GG, R; double aux, delta, param, param2; long n = degpol(p), i, j, k, bit2; double lrmin, lrmax, lrho, *radii; init_dalloc(); radii = (double*) stack_malloc((n+1) * sizeof(double)); for (i=2; i i+1) { if (i+j == n+1) lrho = (lrmin + lrmax) / 2; else { double kappa = 2. - log(1. + minss(i,n-j)) / log(1. + minss(j,n-i)); if (i+j < n+1) lrho = lrmax * kappa + lrmin; else lrho = lrmin * kappa + lrmax; lrho /= 1+kappa; } aux = (lrmax - lrmin) / (4*(j-i)); k = dual_modulus(p, lrho, aux, minss(i,n+1-j)); if (k-i < j-k-1 || (k-i == j-k-1 && 2*k > n)) { lrmax = lrho; j=k+1; radii[j] = lrho - aux; } else { lrmin = lrho; i=k; radii[i] = lrho + aux; } } aux = lrmax - lrmin; if (ctr) { lrho = (lrmax + lrmin) / 2; for (i=1; i<=n; i++) if (radii[i] != UNDEF) radii[i] -= lrho; bit2 = bit + (long)(n * fabs(lrho)/LOG2 + 1.); R = mygprec(dblexp(-lrho), bit2); q = scalepol(p,R,bit2); conformal_mapping(radii, ctr, q, k, bit2, aux, &FF, &GG); } else { lrho = logradius(radii, p, k, aux/10., &delta); update_radius(n, radii, lrho, ¶m, ¶m2); bit2 = bit + (long)(n * fabs(lrho)/LOG2 + 1.); R = mygprec(dblexp(-lrho), bit2); q = scalepol(p,R,bit2); optimize_split(q, k, delta, bit2, &FF, &GG, param, param2); } bit += n; bit2 += n; R = invr(mygprec(R,bit2)); *F = mygprec(scalepol(FF,R,bit2), bit); *G = mygprec(scalepol(GG,R,bit2), bit); } /* procedure corresponding to steps 5,6,.. page 44 in RR n. 1852 */ /* put in F and G two polynomial such that |p-FG|<2^(-bit)|p| * where the maximum modulus of the roots of p is <=1. * Assume sum of roots is 0. */ static void split_1(GEN p, long bit, GEN *F, GEN *G) { long i, imax, n = degpol(p), polreal = isreal(p), ep = gexpo(p), bit2 = bit+n; GEN TWO, ctr, q, qq, FF, GG, v, gr, r, newq; double lrmin, lrmax, lthick; const double LOG3 = 1.098613; lrmax = logmax_modulus(p, 0.01); gr = mygprec(dblexp(-lrmax), bit2); q = scalepol(p,gr,bit2); bit2 = bit + gexpo(q) - ep + (long)((double)n*2.*log2(3.)+1); TWO = myreal_1(bit2); setexpo(TWO,1); v = cgetg(5,t_VEC); gel(v,1) = TWO; gel(v,2) = negr(TWO); gel(v,3) = mkcomplex(gen_0, gel(v,1)); gel(v,4) = mkcomplex(gen_0, gel(v,2)); q = mygprec(q,bit2); lthick = 0; newq = ctr = NULL; /* -Wall */ imax = polreal? 3: 4; for (i=1; i<=imax; i++) { qq = RgX_translate(q, gel(v,i)); lrmin = logmin_modulus(qq,0.05); if (LOG3 > lrmin + lthick) { double lquo = logmax_modulus(qq,0.05) - lrmin; if (lquo > lthick) { lthick = lquo; newq = qq; ctr = gel(v,i); } } if (lthick > LOG2) break; if (polreal && i==2 && lthick > LOG3 - LOG2) break; } bit2 = bit + gexpo(newq) - ep + (long)(n*LOG3/LOG2 + 1); split_2(newq, bit2, ctr, lthick, &FF, &GG); r = gneg(mygprec(ctr,bit2)); FF = RgX_translate(FF,r); GG = RgX_translate(GG,r); gr = invr(gr); bit2 = bit - ep + gexpo(FF)+gexpo(GG); *F = scalepol(FF,gr,bit2); *G = scalepol(GG,gr,bit2); } /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P|, where the maximum modulus of the roots of p is < 0.5 */ static int split_0_2(GEN p, long bit, GEN *F, GEN *G) { GEN q, b, FF, GG; long n = degpol(p), k, bit2, eq; double aux = dbllog2(gel(p,n+1)) - dbllog2(gel(p,n+2)); /* beware double overflow */ if (aux >= 0 && (aux > 1e4 || exp2(aux) > 2.5*n)) return 0; aux = (aux < -300)? 0.: n*log2(1 + exp2(aux)/(double)n); bit2 = bit+1 + (long)(log2((double)n) + aux); q = mygprec(p,bit2); b = gdivgs(gdiv(gel(q,n+1),gel(q,n+2)),-n); q = RgX_translate(q,b); gel(q,n+1) = gen_0; eq = gexpo(q); k = 0; while (k <= n/2 && (- gexpo(gel(q,k+2)) > bit2 + 2*(n-k) + eq || gequal0(gel(q,k+2)))) k++; if (k > 0) { if (k > n/2) k = n/2; bit2 += k<<1; FF = monomial(myreal_1(bit2), k, 0); GG = RgX_shift_shallow(q, -k); } else { split_1(q,bit2,&FF,&GG); bit2 = bit + gexpo(FF) + gexpo(GG) - gexpo(p) + (long)aux+1; FF = mygprec(FF,bit2); } GG = mygprec(GG,bit2); b = mygprec(gneg(b),bit2); *F = RgX_translate(FF, b); *G = RgX_translate(GG, b); return 1; } /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P|. * Assume max_modulus(p) < 2 */ static void split_0_1(GEN p, long bit, GEN *F, GEN *G) { GEN FF, GG; long n, bit2, normp; if (split_0_2(p,bit,F,G)) return; normp = gexpo(p); scalepol2n(p,2); /* p := 4^(-n) p(4*x) */ n = degpol(p); bit2 = bit + 2*n + gexpo(p) - normp; split_1(mygprec(p,bit2), bit2,&FF,&GG); scalepol2n(FF,-2); scalepol2n(GG,-2); bit2 = bit + gexpo(FF) + gexpo(GG) - normp; *F = mygprec(FF,bit2); *G = mygprec(GG,bit2); } /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P| */ static void split_0(GEN p, long bit, GEN *F, GEN *G) { const double LOG1_9 = 0.6418539; long n = degpol(p), k = 0; GEN q; while (gexpo(gel(p,k+2)) < -bit && k <= n/2) k++; if (k > 0) { if (k > n/2) k = n/2; *F = monomial(myreal_1(bit), k, 0); *G = RgX_shift_shallow(p, -k); } else { double lr = logmax_modulus(p, 0.05); if (lr < LOG1_9) split_0_1(p, bit, F, G); else { q = RgX_recip_shallow(p); lr = logmax_modulus(q,0.05); if (lr < LOG1_9) { split_0_1(q, bit, F, G); *F = RgX_recip_shallow(*F); *G = RgX_recip_shallow(*G); } else split_2(p,bit,NULL, 1.2837,F,G); } } } /********************************************************************/ /** **/ /** ERROR ESTIMATE FOR THE ROOTS **/ /** **/ /********************************************************************/ static GEN root_error(long n, long k, GEN roots_pol, long err, GEN shatzle) { GEN rho, d, eps, epsbis, eps2, aux, rap = NULL; long i, j; d = cgetg(n+1,t_VEC); for (i=1; i<=n; i++) { if (i!=k) { aux = gsub(gel(roots_pol,i), gel(roots_pol,k)); gel(d,i) = gabs(mygprec(aux,31), DEFAULTPREC); } } rho = gabs(mygprec(gel(roots_pol,k),31), DEFAULTPREC); if (expo(rho) < 0) rho = real_1(DEFAULTPREC); eps = mulrr(rho, shatzle); aux = shiftr(powru(rho,n), err); for (j=1; j<=2 || (j<=5 && cmprr(rap, dbltor(1.2)) > 0); j++) { GEN prod = NULL; /* 1. */ long m = n; epsbis = mulrr(eps, dbltor(1.25)); for (i=1; i<=n; i++) { if (i != k && cmprr(gel(d,i),epsbis) > 0) { GEN dif = subrr(gel(d,i),eps); prod = prod? mulrr(prod, dif): dif; m--; } } eps2 = prod? divrr(aux, prod): aux; if (m > 1) eps2 = sqrtnr(shiftr(eps2, 2*m-2), m); rap = divrr(eps,eps2); eps = eps2; } return eps; } /* round a complex or real number x to an absolute value of 2^(-bit) */ static GEN mygprec_absolute(GEN x, long bit) { long e; GEN y; switch(typ(x)) { case t_REAL: e = expo(x) + bit; return (e <= 0 || !signe(x))? real_0_bit(-bit): rtor(x, nbits2prec(e)); case t_COMPLEX: if (gexpo(gel(x,2)) < -bit) return mygprec_absolute(gel(x,1),bit); y = cgetg(3,t_COMPLEX); gel(y,1) = mygprec_absolute(gel(x,1),bit); gel(y,2) = mygprec_absolute(gel(x,2),bit); return y; default: return x; } } static long a_posteriori_errors(GEN p, GEN roots_pol, long err) { long i, n = degpol(p), e_max = -(long)EXPOBITS; GEN sigma, shatzle; err += (long)log2((double)n) + 1; if (err > -2) return 0; sigma = real2n(-err, LOWDEFAULTPREC); /* 2 / ((s - 1)^(1/n) - 1) */ shatzle = divur(2, subrs(sqrtnr(subrs(sigma,1),n), 1)); for (i=1; i<=n; i++) { pari_sp av = avma; GEN x = root_error(n,i,roots_pol,err,shatzle); long e = gexpo(x); avma = av; if (e > e_max) e_max = e; gel(roots_pol,i) = mygprec_absolute(gel(roots_pol,i), -e); } return e_max; } /********************************************************************/ /** **/ /** MAIN **/ /** **/ /********************************************************************/ static GEN append_clone(GEN r, GEN a) { a = gclone(a); vectrunc_append(r, a); return a; } /* put roots in placeholder roots_pol so that |P - L_1...L_n| < 2^(-bit)|P| * returns prod (x-roots_pol[i]) */ static GEN split_complete(GEN p, long bit, GEN roots_pol) { long n = degpol(p); pari_sp ltop; GEN p1, F, G, a, b, m1, m2; if (n == 1) { a = gneg_i(gdiv(gel(p,2), gel(p,3))); (void)append_clone(roots_pol,a); return p; } ltop = avma; if (n == 2) { F = gsub(gsqr(gel(p,3)), gmul2n(gmul(gel(p,2),gel(p,4)), 2)); F = gsqrt(F, nbits2prec(bit)); p1 = ginv(gmul2n(gel(p,4),1)); a = gneg_i(gmul(gadd(F,gel(p,3)), p1)); b = gmul(gsub(F,gel(p,3)), p1); a = append_clone(roots_pol,a); b = append_clone(roots_pol,b); avma = ltop; a = mygprec(a, 3*bit); b = mygprec(b, 3*bit); return gmul(gel(p,4), mkpoln(3, gen_1, gneg(gadd(a,b)), gmul(a,b))); } split_0(p,bit,&F,&G); m1 = split_complete(F,bit,roots_pol); m2 = split_complete(G,bit,roots_pol); return gerepileupto(ltop, gmul(m1,m2)); } static GEN quickabs(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_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. */ if (isintzero(a)) return cxcompotor(b, prec); if (isintzero(b)) return cxcompotor(a, prec); a = cxcompotor(a, prec); b = cxcompotor(b, prec); return sqrtr(addrr(sqrr(a), sqrr(b))); } default: pari_err_TYPE("quickabs",x); return NULL;/*not reached*/ } } /* bound ln |largest root of p| */ double cauchy_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 y = gel(p,i+2); double L; if (gequal0(y)) continue; L = mydbllogr(mulrr(quickabs(y), invlc)) / (n-i); if (L > Lmax) Lmax = L; } avma = av; return Lmax + LOG2; } static GEN mygprecrc_special(GEN x, long prec, long e) { GEN y; switch(typ(x)) { case t_REAL: if (!signe(x)) return real_0_bit(minss(e, expo(x))); return (prec > realprec(x))? rtor(x, prec): x; case t_COMPLEX: y = cgetg(3,t_COMPLEX); gel(y,1) = mygprecrc_special(gel(x,1),prec,e); gel(y,2) = mygprecrc_special(gel(x,2),prec,e); return y; default: return x; } } /* like mygprec but keep at least the same precision as before */ static GEN mygprec_special(GEN x, long bit) { long lx, i, e, prec; GEN y; if (bit < 0) bit = 0; /* should not happen */ e = gexpo(x) - bit; prec = nbits2prec(bit); switch(typ(x)) { case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 1; i--) if (!gequal0( gel(x,i) )) break; if (i == n) return x; pari_warn(warner,"normalizing a polynomial with 0 leading term"); if (i == 1) pari_err_ROOTS0("roots"); y = cgetg(i+1, t_POL); y[1] = x[1]; for (; i > 1; i--) gel(y,i) = gel(x,i); return y; } static GEN all_roots(GEN p, long bit) { GEN lc, pd, q, roots_pol, m; long bit0, bit2, i, e, h, n = degpol(p); 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; bit0 = bit + gexpo(pd) - gexpo(lc) + (long)log2(n/h)+1+e; bit2 = bit0; e = 0; for (av=avma,i=1;; i++,avma=av) { roots_pol = vectrunc_init(n+1); bit2 += e + (n << i); q = RgX_gtofp_bit(mygprec(pd,bit2), bit2); q[1] = evalsigne(1)|evalvarn(0); m = split_complete(q,bit2,roots_pol); roots_pol = fix_roots(roots_pol, &m, h, bit2); q = mygprec_special(p,bit2); lc = leading_term(q); q[1] = evalsigne(1)|evalvarn(0); if (h > 1) m = gmul(m,lc); e = gexpo(gsub(q, m)) - gexpo(lc) + (long)log2((double)n) + 1; if (e < -2*bit2) e = -2*bit2; /* avoid e = -pariINFINITY */ if (e < 0) { e = bit + a_posteriori_errors(p,roots_pol,e); if (e < 0) return roots_pol; } if (DEBUGLEVEL > 7) err_printf("all_roots: restarting, i = %ld, e = %ld\n", i,e); } } INLINE int isexactscalar(GEN x) { long tx = typ(x); return is_rational_t(tx); } static int isexactpol(GEN p) { long i,n = degpol(p); for (i=0; i<=n; i++) if (!isexactscalar(gel(p,i+2))) return 0; return 1; } static long isvalidcoeff(GEN x) { switch (typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 1; case t_COMPLEX: return isvalidcoeff(gel(x,1)) && isvalidcoeff(gel(x,2)); } return 0; } static void checkvalidpol(GEN p) { long i,n = lg(p); for (i=2; i= e) return -1; /* |Im x| ~ |Im y| ~ 0 */ } else if (!syi) { if (sxi && expo(xi) >= e) return 1; /* |Im x| ~ |Im y| ~ 0 */ } else { long sz; z = addrr_sign(xi, 1, yi, -1); sz = signe(z); if (sz && expo(z) >= e) return (int)sz; } /* |Im x| ~ |Im y|, sort according to real parts */ z = subrr(xr, yr); if (expo(z) >= e) return (int)signe(z); /* Re x ~ Re y. Place negative absolute value before positive */ return (int) (sxi - syi); } static GEN clean_roots(GEN L, long l, long bit, long clean) { long i, n = lg(L), ex = 5 - bit; GEN res = cgetg(n,t_COL); for (i=1; i1) pari_warn(warnmem,"sum"); p = gerepileupto(av, p); } } return gerepileupto(av, p); } /*******************************************************************/ /* */ /* TRANSPOSE */ /* */ /*******************************************************************/ /* A[x0,]~ */ static GEN row_transpose(GEN A, long x0) { long i, lB = lg(A); GEN B = cgetg(lB, t_COL); for (i=1; imax) return 0; } if (*s == '.') { s++; if (*s != '.') return 0; do s++; while (isspace((int)*s)); if (*s) { *b = str_to_long(s, &s); if (*b < 0) *b += lx; if (*b<1 || *b>max || *s) return 0; } return 1; } if (*s) return 0; *b = *a; return 1; } static int extract_selector_ok(long lx, GEN L) { long i, l; switch (typ(L)) { case t_INT: { long maxj; if (!signe(L)) return 1; l = lgefint(L)-1; maxj = BITS_IN_LONG - bfffo(*int_MSW(L)); return ((l-2) * BITS_IN_LONG + maxj < lx); } case t_STR: { long first, last, cmpl; return get_range(GSTR(L), &first, &last, &cmpl, lx); } case t_VEC: case t_COL: l = lg(L); for (i=1; i=lx || j<=0) return 0; } return 1; case t_VECSMALL: l = lg(L); for (i=1; i=lx || j<=0) return 0; } return 1; } return 0; } GEN shallowextract(GEN x, GEN L) { long i,j, tl = typ(L), tx = typ(x), lx = lg(x); GEN y; switch(tx) { case t_VEC: case t_COL: case t_MAT: case t_VECSMALL: break; default: pari_err_TYPE("extract",x); } if (tl==t_INT) { /* extract components of x as per the bits of mask L */ long k, l, ix, iy, maxj; GEN Ld; if (!signe(L)) return cgetg(1,tx); y = new_chunk(lx); l = lgefint(L)-1; ix = iy = 1; maxj = BITS_IN_LONG - bfffo(*int_MSW(L)); if ((l-2) * BITS_IN_LONG + maxj >= lx) pari_err_TYPE("vecextract [mask too large]", L); for (k = 2, Ld = int_LSW(L); k < l; k++, Ld = int_nextW(Ld)) { ulong B = *Ld; for (j = 0; j < BITS_IN_LONG; j++, B >>= 1, ix++) if (B & 1) y[iy++] = x[ix]; } { /* k = l */ ulong B = *Ld; for (j = 0; j < maxj; j++, B >>= 1, ix++) if (B & 1) y[iy++] = x[ix]; } y[0] = evaltyp(tx) | evallg(iy); return y; } if (tl==t_STR) { char *s = GSTR(L); long first, last, cmpl, d; if (! get_range(s, &first, &last, &cmpl, lx)) pari_err_TYPE("vecextract [incorrect range]", L); if (lx == 1) return cgetg(1,tx); d = last - first; if (cmpl) { if (d >= 0) { y = cgetg(lx - (1+d),tx); for (j=1; jfirst; i--,j++) gel(y,j) = gel(x,i); for (i=last-1; i>0; i--,j++) gel(y,j) = gel(x,i); } } else { if (d >= 0) { y = cgetg(d+2,tx); for (i=first,j=1; i<=last; i++,j++) gel(y,j) = gel(x,i); } else { y = cgetg(2-d,tx); for (i=first,j=1; i>=last; i--,j++) gel(y,j) = gel(x,i); } } return y; } if (is_vec_t(tl)) { long ll=lg(L); y=cgetg(ll,tx); for (i=1; i=",stoi(lx),stoi(j)); gel(y,i) = gel(x,j); } return y; } if (tl == t_VECSMALL) { long ll=lg(L); y=cgetg(ll,tx); for (i=1; i=",stoi(lx),stoi(j)); gel(y,i) = gel(x,j); } return y; } pari_err_TYPE("vecextract [mask]", L); return NULL; /* not reached */ } /* does the component selector l select 0 component ? */ static int select_0(GEN l) { switch(typ(l)) { case t_INT: return (!signe(l)); case t_VEC: case t_COL: case t_VECSMALL: return (lg(l) == 1); } return 0; } GEN extract0(GEN x, GEN l1, GEN l2) { pari_sp av = avma, av2; GEN y; if (! l2) { y = shallowextract(x, l1); if (lg(y) == 1 || typ(y) == t_VECSMALL) return y; av2 = avma; y = gcopy(y); } else { if (typ(x) != t_MAT) pari_err_TYPE("extract",x); y = shallowextract(x,l2); if (select_0(l1)) { avma = av; return zeromat(0, lg(y)-1); } if (lg(y) == 1 && lg(x) > 1) { if (!extract_selector_ok(lgcols(x), l1)) pari_err_TYPE("vecextract [incorrect mask]", l1); avma = av; return cgetg(1, t_MAT); } y = shallowextract(shallowtrans(y), l1); av2 = avma; y = gtrans(y); } stackdummy(av, av2); return y; } static long vecslice_parse_arg(long lA, long *y1, long *y2, long *skip) { *skip=0; if (!*y1) { if (*y2) { if (*y2<0) *y2 += lA; if (*y2<=0 || *y2>=lA) pari_err_DIM("_[..]"); *skip=*y2; } *y1 = 1; *y2 = lA-1; } else if (!*y2) *y2 = *y1; if (*y1<0) *y1 += lA; if (*y2<0) *y2 += lA; if (*y1<=0 || *y1>*y2 || *y2>=lA) pari_err_DIM("_[..]"); return *y2 - *y1 + 2 - !!*skip; } static GEN vecslice_i(GEN A, long t, long lB, long y1, long skip) { GEN B = cgetg(lB, t); long i; for (i=1; i 1 */ rlB = vecslice_parse_arg(lg(gel(A,1)), &x1, &x2, &rskip); t = typ(gel(A,1)); if (is_row) return t == t_COL ? rowslice_i(A, lB, x1, y1, skip): rowsmallslice_i(A, lB, x1, y1, skip); slice = t == t_COL? &vecslice_i: &vecsmallslice_i; B = cgetg(lB, t_MAT); for (i=1; i0) return cgetg(1,t_VEC); l = itos(subii(b,a))+1; a = setloop(a); y = cgetg(l+1, t_VEC); for (i=1; i<=l; a = incloop(a), i++) gel(y,i) = icopy(a); return y; } GEN vecrangess(long a, long b) { GEN y; long i, l; if (a>b) return cgetg(1,t_VEC); l = b-a+1; y = cgetg(l+1, t_VEC); for (i=1; i<=l; a++, i++) gel(y,i) = stoi(a); return y; } GEN genindexselect(void *E, long (*f)(void* E, GEN x), GEN A) { long l, i, lv; GEN v, z; pari_sp av; clone_lock(A); switch(typ(A)) { case t_LIST: z = list_data(A); l = z? lg(z): 1; break; case t_VEC: case t_COL: case t_MAT: l = lg(A); z = A; break; default: pari_err_TYPE("select",A); return NULL;/*not reached*/ } v = cgetg(l, t_VECSMALL); av = avma; for (i = lv = 1; i < l; i++) { if (f(E, gel(z,i))) v[lv++] = i; avma = av; } clone_unlock(A); fixlg(v, lv); return v; } static GEN extract_copy(GEN A, GEN v) { long i, l = lg(v); GEN B = cgetg(l, typ(A)); for (i = 1; i < l; i++) gel(B,i) = gcopy(gel(A,v[i])); return B; } /* as genselect, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */ GEN vecselect(void *E, long (*f)(void* E, GEN x), GEN A) { GEN v; clone_lock(A); v = genindexselect(E, f, A); A = extract_copy(A, v); settyp(A, t_VEC); clone_unlock(A); return A; } GEN genselect(void *E, long (*f)(void* E, GEN x), GEN A) { GEN y, z, v;/* v left on stack for efficiency */ clone_lock(A); switch(typ(A)) { case t_LIST: z = list_data(A); if (!z) y = listcreate(); else { GEN B; y = cgetg(3, t_LIST); v = genindexselect(E, f, z); B = extract_copy(z, v); list_nmax(y) = lg(B)-1; list_data(y) = B; } break; case t_VEC: case t_COL: case t_MAT: v = genindexselect(E, f, A); y = extract_copy(A, v); break; default: pari_err_TYPE("select",A); return NULL;/*not reached*/ } clone_unlock(A); return y; } GEN select0(GEN f, GEN x, long flag) { if (typ(f) != t_CLOSURE || closure_arity(f) < 1) pari_err_TYPE("select", f); switch(flag) { case 0: return genselect((void *) f, gp_callbool, x); case 1: return genindexselect((void *) f, gp_callbool, x); default: pari_err_FLAG("select"); return NULL;/*not reached*/ } } GEN parselect(GEN C, GEN D, long flag) { pari_sp av, av2; 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); if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D); V = cgetg(l, t_VECSMALL); av = avma; worker = strtoclosure("_parapply_worker", 1, C); av2 = avma; mt_queue_start(&pt, worker); for (i=1; i 0) x = scalarpol(x,v); x = RgX_nffix("eltreltoabs", T, x, 1); /* Mod(X - k a, pol(X)), a root of the polynomial defining base */ teta = gadd(pol_x(v), gmulsg(-k,a)); s = gen_0; for (i=lg(x)-1; i>1; i--) { GEN c = gel(x,i); if (typ(c) == t_POL) c = RgX_RgXQ_eval(c, a, pol); s = RgX_rem(gadd(c, gmul(teta,s)), pol); } return gerepileupto(av, s); } GEN rnfeltreltoabs(GEN rnf,GEN x) { const char *f = "rnfeltreltoabs"; GEN pol; checkrnf(rnf); pol = rnf_get_polabs(rnf); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: if (RgX_equal_var(gel(x,1), pol)) { /* already in 'abs' form, unless possibly if nf = Q */ if (rnf_get_nfdegree(rnf) == 1) { GEN y = gel(x,2); pari_sp av = avma; y = simplify_shallow(liftpol_shallow(y)); return gerepilecopy(av, mkpolmod(y, pol)); } return gcopy(x); } x = polmod_nffix(f,rnf,x,0); if (typ(x) == t_POLMOD) return rnfeltup(rnf,x); retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), RgX_copy(pol)); case t_POL: if (varn(x) == rnf_get_nfvarn(rnf)) return rnfeltup(rnf,x); retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), RgX_copy(pol)); } pari_err_TYPE(f,x); return NULL; } GEN eltabstorel_lift(GEN rnfeq, GEN P) { GEN k, T = gel(rnfeq,4), relpol = gel(rnfeq,5); if (is_scalar_t(typ(P))) return P; k = gel(rnfeq,3); P = lift_intern(P); if (signe(k)) P = RgXQX_translate(P, deg1pol_shallow(k, gen_0, varn(T)), T); P = RgXQX_rem(P, relpol, T); return QXQX_to_mod_shallow(P, T); } /* rnfeq = [pol,a,k,T,relpol], P a t_POL or scalar * Return Mod(P(x + k Mod(y, T(y))), pol(x)) */ GEN eltabstorel(GEN rnfeq, GEN P) { GEN T = gel(rnfeq,4), relpol = gel(rnfeq,5); return mkpolmod(eltabstorel_lift(rnfeq,P), QXQX_to_mod_shallow(relpol,T)); } GEN rnfeltabstorel(GEN rnf,GEN x) { const char *f = "rnfeltabstorel"; pari_sp av = avma; GEN pol, T, P; checkrnf(rnf); T = rnf_get_nfpol(rnf); P = rnf_get_pol(rnf); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: if (RgX_equal_var(P, gel(x,1))) { x = polmod_nffix(f, rnf, x, 0); return gerepilecopy(av, mkpolmod(x,P)); } if (RgX_equal_var(T, gel(x,1))) { x = Rg_nffix(f, T, x, 0); goto END; } pol = rnf_get_polabs(rnf); if (!RgX_equal_var(pol, gel(x,1))) pari_err_MODULUS(f, gel(x,1),pol); x = gel(x,2); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POL: break; default: pari_err_TYPE(f, x); } break; case t_POL: pol = rnf_get_polabs(rnf); break; default: pari_err_TYPE(f,x); return NULL; } if (!RgX_is_QX(x)) pari_err_TYPE(f,x); if (varn(x) != varn(pol)) { if (varn(x) == varn(T)) { x = Rg_nffix(f,T,x,0); goto END; } pari_err_VAR(f, x,pol); } switch(lg(x)) { case 2: avma = av; return gen_0; case 3: return gerepilecopy(av, gel(x,2)); } 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) { GEN W=gel(x,1), I=gel(x,2), rnfeq = rnf_get_map(rnf), polabs = gel(rnfeq,1); long i, j, k, m, N = lg(W)-1; GEN zknf, czknf, M; if (!N) return cgetg(1, t_VEC); rnf_get_nfzk(rnf, &zknf,&czknf); m = rnf_get_nfdegree(rnf); M = cgetg(N*m+1, t_VEC); for (k=i=1; i<=N; i++) { GEN c0, cid, w = gel(W,i), id = gel(I,i); if (lg(id) == 1) continue; /* must be a t_MAT */ id = Q_primitive_part(id, &cid); w = Q_primitive_part(eltreltoabs(rnfeq,w), &c0); c0 = mul_content(c0, mul_content(cid,czknf)); if (typ(id) == t_INT) for (j=1; j<=m; j++) { GEN z = RgX_rem(gmul(w, gel(zknf,j)), polabs); if (c0) z = RgX_Rg_mul(z, c0); gel(M,k++) = z; } else for (j=1; j<=m; j++) { GEN c, z = Q_primitive_part(RgV_RgC_mul(zknf,gel(id,j)), &c); z = RgX_rem(gmul(w, z), polabs); c = mul_content(c, c0); if (c) z = RgX_Rg_mul(z, c); gel(M,k++) = z; } } setlg(M, k); return M; } /* Z-basis for absolute maximal order, as a t_MAT */ GEN rnf_basM(GEN rnf) { GEN M, d, pol = rnf_get_polabs(rnf); long n = degpol(pol); /* t_VEC of t_POL */ M = Q_remove_denom(modulereltoabs(rnf, rnf_get_zk(rnf)), &d); if (d) { M = ZM_hnfmodall(RgXV_to_RgM(M,n), d, hnf_MODID|hnf_CENTER); M = RgM_Rg_div(M, d); } else M = matid(n); 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; } static GEN makenorms(GEN rnf) { GEN f = rnf_get_index(rnf); return typ(f) == t_INT? gen_1: RgM_det_triangular(f); } #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); } void nf_nfzk(GEN nf, GEN rnfeq, GEN *zknf, GEN *czknf) { GEN pol = gel(rnfeq,1), a = gel(rnfeq,2); GEN zk = QXV_QXQ_eval(nf_get_zk(nf), a, pol); *zknf = Q_primitive_part(zk, czknf); if (!*czknf) *czknf = gen_1; } GEN rnfinit(GEN nf, GEN polrel) { pari_sp av = avma; GEN rnf, bas, D,d,f, B, rnfeq, basnf,cobasnf; nf = checknf(nf); bas = rnfallbase(nf,&polrel, &D,&d, &f); B = matbasistoalg(nf,gel(bas,1)); 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); gel(rnf,1) = polrel; gel(rnf,2) = mkvec2(basnf, cobasnf); gel(rnf,3) = mkvec2(D, d); gel(rnf,4) = f; 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,10)= nf; gel(rnf,11)= rnfeq; gel(rnf,12)= zerovec(2); return gerepilecopy(av, rnf); } GEN rnfeltup(GEN rnf, GEN x) { pari_sp av = avma; GEN zknf, czknf; checkrnf(rnf); if (typ(x) == t_POLMOD && RgX_equal_var(gel(x,1), rnf_get_polabs(rnf))) return gcopy(x); rnf_get_nfzk(rnf, &zknf, &czknf); x = nfeltup(rnf_get_nf(rnf), x, zknf, czknf); if (typ(x) == t_POL) x = mkpolmod(x, rnf_get_polabs(rnf)); return gerepilecopy(av, x); } GEN nfeltup(GEN nf, GEN x, GEN zknf, GEN czknf) { GEN c; x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) return x; x = Q_primitive_part(x, &c); if (!RgV_is_ZV(x)) pari_err_TYPE("rnfeltup", x); c = mul_content(c, czknf); x = RgV_RgC_mul(zknf, x); if (c) x = RgX_Rg_mul(x, c); return x; } static void fail(const char *f, GEN x) { pari_err_DOMAIN(f,"element","not in", strtoGENstr("the base field"),x); } GEN rnfeltdown(GEN rnf,GEN x) { const char *f = "rnfeltdown"; pari_sp av = avma; GEN z, T; long v; checkrnf(rnf); T = rnf_get_nfpol(rnf); v = varn(T); switch(typ(x)) { /* directly belonging to base field ? */ case t_INT: return icopy(x); case t_FRAC:return gcopy(x); case t_POLMOD: if (RgX_equal_var(gel(x,1), rnf_get_polabs(rnf))) break; x = polmod_nffix(f,rnf,x,0); /* x was defined mod the relative polynomial & non constant => fail */ if (typ(x) == t_POL) fail(f,x); return gerepilecopy(av, x); case t_POL: if (varn(x) != v) break; x = Rg_nffix(f,T,x,0); return gerepilecopy(av, x); } /* x defined mod the absolute equation */ z = rnfeltabstorel(rnf,x); switch(typ(z)) { case t_INT: case t_FRAC: return z; } /* typ(z) = t_POLMOD, varn of both components is rnf_get_varn(rnf) */ z = gel(z,2); if (typ(z) == t_POL) { if (lg(z) != 3) fail(f,x); z = gel(z,2); } return gerepilecopy(av, z); } /* vector of rnf elt -> matrix of nf elts */ static GEN rnfV_to_nfM(GEN rnf, GEN x) { long i, l = lg(x); GEN y = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(y,i) = rnfalgtobasis(rnf,gel(x,i)); return y; } static GEN rnfprincipaltohnf(GEN rnf,GEN x) { pari_sp av = avma; GEN bas = rnf_get_zk(rnf), nf = rnf_get_nf(rnf); x = rnfbasistoalg(rnf,x); x = gmul(x, gmodulo(gel(bas,1), rnf_get_pol(rnf))); return gerepileupto(av, nfhnf(nf, mkvec2(rnfV_to_nfM(rnf,x), gel(bas,2)))); } /* pseudo-basis for the 0 ideal */ static GEN rnfideal0() { retmkvec2(cgetg(1,t_MAT),cgetg(1,t_VEC)); } GEN rnfidealhnf(GEN rnf, GEN x) { GEN z, nf, bas; checkrnf(rnf); nf = rnf_get_nf(rnf); switch(typ(x)) { case t_INT: case t_FRAC: if (isintzero(x)) return rnfideal0(); bas = rnf_get_zk(rnf); z = cgetg(3,t_VEC); gel(z,1) = matid(rnf_get_degree(rnf)); gel(z,2) = gmul(x, gel(bas,2)); return z; case t_VEC: if (lg(x) == 3 && typ(gel(x,1)) == t_MAT) return nfhnf(nf, x); return rnfidealabstorel(rnf, x); case t_POLMOD: case t_POL: case t_COL: return rnfprincipaltohnf(rnf,x); } pari_err_TYPE("rnfidealhnf",x); return NULL; /* not reached */ } GEN prodid(GEN nf, GEN I) { long i, l = lg(I); GEN z; if (l == 1) return matid(nf_get_degree(nf)); z = gel(I,1); for (i=2; i vector of 2 generators (relative polmods) */ GEN rnfidealtwoelement(GEN rnf, GEN x) { pari_sp av = avma; GEN y, cy, z, NF; y = rnfidealreltoabs(rnf,x); NF = check_and_build_nfabs(rnf); y = matalgtobasis(NF, y); settyp(y, t_MAT); y = Q_primitive_part(y, &cy); y = ZM_hnf(y); if (lg(y) == 1) { avma = av; return mkvec2(gen_0, gen_0); } y = idealtwoelt(NF, y); if (cy) y = RgV_Rg_mul(y, cy); z = rnfeltabstorel(rnf, coltoliftalg(NF, gel(y,2))); return gerepilecopy(av, mkvec2(gel(y,1), z)); } GEN rnfidealmul(GEN rnf,GEN x,GEN y) { pari_sp av = avma; GEN nf, z, x1, x2, p1, p2, bas; y = rnfidealtwoelement(rnf,y); if (isintzero(gel(y,1))) { avma = av; return rnfideal0(); } nf = rnf_get_nf(rnf); bas = rnf_get_zk(rnf); x = rnfidealhnf(rnf,x); x1 = gmodulo(gmul(gel(bas,1), matbasistoalg(nf,gel(x,1))), rnf_get_pol(rnf)); x2 = gel(x,2); p1 = gmul(gel(y,1), gel(x,1)); p2 = rnfV_to_nfM(rnf, gmul(gel(y,2), x1)); z = mkvec2(shallowconcat(p1, p2), shallowconcat(x2, x2)); 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) { long lA, lB; GEN nf, C; A = get_nfpol(A, &nf); lA = lg(A); if (!nf) { if (lA<=3) pari_err_CONSTPOL("rnfequation"); RgX_check_ZX(A,"rnfequation"); } B = RgX_nffix("rnfequation", A,B,1); lB = lg(B); if (lB<=3) pari_err_CONSTPOL("rnfequation"); B = Q_primpart(B); if (!nfissquarefree(A,B)) pari_err_DOMAIN("rnfequation","issquarefree(B)","=",gen_0,B); *pk = 0; C = ZX_ZXY_resultant_all(A, B, pk, pLPRS); if (gsigne(leading_term(C)) < 0) C = RgX_neg(C); *pk = -*pk; return Q_primpart(C); } GEN rnfequation0(GEN A, GEN B, long flall) { pari_sp av = avma; GEN LPRS, C; long k; C = rnfequationall(A, B, &k, flall? &LPRS: NULL); if (flall) { /* a,b,c root of A,B,C = compositum, c = b + k a */ GEN a, mH0 = RgX_neg(gel(LPRS,1)), H1 = gel(LPRS,2); a = RgXQ_mul(mH0, QXQ_inv(H1, C), C); C = mkvec3(C, mkpolmod(a, C), stoi(k)); } return gerepilecopy(av, C); } GEN rnfequation(GEN nf, GEN pol) { return rnfequation0(nf,pol,0); } GEN rnfequation2(GEN nf, GEN pol) { return rnfequation0(nf,pol,1); } GEN nf_rnfeq(GEN nf, GEN relpol) { GEN pol, a, k, junk, eq; relpol = liftpol_shallow(relpol); eq = rnfequation2(nf, relpol); pol = gel(eq,1); a = gel(eq,2); if (typ(a) == t_POLMOD) a = gel(a,2); k = gel(eq,3); return mkvec5(pol,a,k,get_nfpol(nf, &junk),relpol); } /* only allow abstorel */ GEN nf_rnfeqsimple(GEN nf, GEN relpol) { long sa; GEN junk, pol = rnfequationall(nf, relpol, &sa, NULL); return mkvec5(pol,gen_0/*dummy*/,stoi(sa),get_nfpol(nf, &junk),relpol); } static GEN nftau(long r1, GEN x) { long i, l = lg(x); GEN s = r1? gel(x,1): gmul2n(real_i(gel(x,1)),1); for (i=2; i<=r1; i++) s = gadd(s, gel(x,i)); for ( ; i < l; i++) s = gadd(s, gmul2n(real_i(gel(x,i)),1)); return s; } static GEN initmat(long l) { GEN x = cgetg(l, t_MAT); long i; for (i = 1; i < l; i++) gel(x,i) = cgetg(l, t_COL); return x; } static GEN nftocomplex(GEN nf, GEN x) { GEN M = nf_get_M(nf); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return const_col(nbrows(M), x); return RgM_RgC_mul(M, x); } /* assume x a square t_MAT, return a t_VEC of embeddings of its columns */ static GEN mattocomplex(GEN nf, GEN x) { long i,j, l = lg(x); GEN v = cgetg(l, t_VEC); for (j=1; j= 0) return NULL; /* precision problem */ m = ZM_ZC_mul(x, m); if (cx) m = RgC_Rg_mul(m, cx); return gerepileupto(av, m); } static int RED(long k, long l, GEN U, GEN mu, GEN MC, GEN nf, GEN I, GEN *Ik_inv) { GEN x, xc, ideal; long i; if (!*Ik_inv) *Ik_inv = idealinv(nf, gel(I,k)); ideal = idealmul(nf,gel(I,l), *Ik_inv); x = findmin(nf, ideal, gcoeff(mu,k,l)); if (!x) return 0; if (gequal0(x)) return 1; xc = nftocomplex(nf,x); gel(MC,k) = gsub(gel(MC,k), vecmul(xc,gel(MC,l))); gel(U,k) = gsub(gel(U,k), gmul(coltoalg(nf,x), gel(U,l))); gcoeff(mu,k,l) = gsub(gcoeff(mu,k,l), xc); for (i=1; i 0) return 0; swap(gel(MC,k-1),gel(MC,k)); swap(gel(h,k-1), gel(h,k)); swap(gel(I,k-1), gel(I,k)); for (j=1; j<=k-2; j++) swap(gcoeff(mu,k-1,j),gcoeff(mu,k,j)); muf = gcoeff(mu,k,k-1); mufc = gconj(muf); Bf = gadd(gel(B,k), vecmul(real_i(vecmul(muf,mufc)), gel(B,k-1))); if (check_0(Bf)) return 1; /* precision problem */ p1 = vecdiv(gel(B,k-1),Bf); gcoeff(mu,k,k-1) = vecmul(mufc,p1); temp = gel(MCS,k-1); gel(MCS,k-1) = gadd(gel(MCS,k), vecmul(muf,gel(MCS,k-1))); gel(MCS,k) = gsub(vecmul(vecdiv(gel(B,k),Bf), temp), vecmul(gcoeff(mu,k,k-1), gel(MCS,k))); gel(B,k) = vecmul(gel(B,k),p1); gel(B,k-1) = Bf; for (i=k+1; i<=kmax; i++) { temp = gcoeff(mu,i,k); gcoeff(mu,i,k) = gsub(gcoeff(mu,i,k-1), vecmul(muf, gcoeff(mu,i,k))); gcoeff(mu,i,k-1) = gadd(temp, vecmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k))); } return 1; } static GEN rel_T2(GEN nf, GEN pol, long lx, long prec) { long ru, i, j, k, l; GEN T2, s, unro, roorder, powreorder; roorder = nf_all_roots(nf, pol, prec); if (!roorder) return NULL; ru = lg(roorder); unro = cgetg(lx,t_COL); for (i=1; i kmax) { /* Incremental Gram-Schmidt */ kmax = k; gel(MCS,k) = gel(MC,k); for (j=1; j 2) k--; } else { for (l=k-2; l; l--) if (!RED(k, l, h, mu, MC, nf, I, &Ik_inv)) goto PRECPB; k++; } if (low_stack(lim, stack_lim(av,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"rnflllgram"); gerepileall(av, H?10:9, &nf,&mth,&h,&MPOL,&B,&MC,&MCS,&mu,&I,&H); } } while (k < lx); MPOL = gmul(MPOL,h); if (H) h = gmul(H, h); if (DEBUGLEVEL) err_printf("\n"); MPOL = RgM_to_nfM(nf,MPOL); h = RgM_to_nfM(nf,h); return gerepilecopy(av, mkvec2(mkvec2(MPOL,I), h)); } GEN rnfpolred(GEN nf, GEN pol, long prec) { pari_sp av = avma; long i, j, n, v = varn(pol); GEN id, w, I, O, bnf, nfpol; if (typ(pol)!=t_POL) pari_err_TYPE("rnfpolred",pol); bnf = nf; nf = checknf(bnf); bnf = (nf == bnf)? NULL: checkbnf(bnf); if (degpol(pol) <= 1) { w = cgetg(2, t_VEC); gel(w,1) = pol_x(v); return w; } nfpol = nf_get_pol(nf); id = rnfpseudobasis(nf,pol); if (bnf && is_pm1( bnf_get_no(bnf) )) /* if bnf is principal */ { GEN newI, newO; O = gel(id,1); I = gel(id,2); n = lg(I)-1; newI = cgetg(n+1,t_VEC); newO = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) { GEN al = gen_if_principal(bnf,gel(I,j)); gel(newI,j) = gen_1; gel(newO,j) = nfC_nf_mul(nf, gel(O,j), al); } id = mkvec2(newO, newI); } id = gel(rnflllgram(nf,pol,id,prec),1); O = gel(id,1); I = gel(id,2); n = lg(I)-1; w = cgetg(n+1,t_VEC); pol = lift(pol); for (j=1; j<=n; j++) { GEN newpol, L, a, Ij = gel(I,j); a = RgC_Rg_mul(gel(O,j), (typ(Ij) == t_MAT)? gcoeff(Ij,1,1): Ij); for (i=n; i; i--) { GEN c = gel(a,i); if (typ(c) == t_COL) gel(a,i) = coltoliftalg(nf, c); } a = RgV_to_RgX(a, v); newpol = RgXQX_red(RgXQ_charpoly(a, pol, v), nfpol); newpol = Q_primpart(newpol); (void)nfgcd_all(newpol, RgX_deriv(newpol), nfpol, nf_get_index(nf), &newpol); L = leading_term(newpol); gel(w,j) = (typ(L) == t_POL)? RgXQX_div(newpol, L, nfpol) : RgX_Rg_div(newpol, L); } return gerepilecopy(av,w); } pari-2.7.5/src/basemath/bb_group.c0000644000175000017500000006163612405547147015451 0ustar billbill/* 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. */ /***********************************************************************/ /** **/ /** GENERIC ALGORITHMS ON BLACKBOX GROUP **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #undef pow /* AIX: pow(a,b) is a macro, wrongly expanded on grp->pow(a,b,c) */ /***********************************************************************/ /** **/ /** POWERING **/ /** **/ /***********************************************************************/ /* return (n>>(i+1-l)) & ((1<=l) return (w>>(r-l))&((1UL<>= (BITS_IN_LONG-lr); return (w<=0) { if (e > l+1) e = l+1; w = (n>>(l+1-e)) & ((1UL<>(v+1))); if (z) { for (i=1; i<=e-v; i++) z = sqr(E, z); z = mul(E, z, tw); } else z = tw; for (i=1; i<=v; i++) z = sqr(E, z); while (l>=0) { if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"sliding_window_powu (%ld)", l); z = gerepilecopy(av, z); } if (n&(1UL<=0) { if (e > l+1) e = l+1; w = int_block(n,l,e); v = vals(w); l-=e; tw = gel(tab, 1+(w>>(v+1))); if (z) { for (i=1; i<=e-v; i++) z = sqr(E, z); z = mul(E, z, tw); } else z = tw; for (i=1; i<=v; i++) z = sqr(E, z); while (l>=0) { if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"sliding_window_pow (%ld)", l); z = gerepilecopy(av, z); } if (int_bit(n,l)) break; z = sqr(E, z); l--; } } return z; } /* assume n != 0, t_INT. Compute x^|n| using leftright binary powering */ 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); GEN y; int j; if (n == 1) return gcopy(x); y = x; j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { 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 (DEBUGMEM>1) pari_warn(warnmem,"leftright_powu (%d)", j); y = gerepilecopy(av, y); } } return y; } GEN gen_powu_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { long l; if (n == 1) return gcopy(x); l = expu(n); if (l<=8) return leftright_binary_powu(x, n, E, sqr, mul); else return sliding_window_powu(x, n, l<=24? 2: 3, E, sqr, mul); } GEN gen_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma; if (n == 1) return gcopy(x); return gerepilecopy(av, gen_powu_i(x,n,E,sqr,mul)); } GEN 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); l = expi(n); if (l<=64) e = 3; else if (l<=160) e = 4; else if (l<=384) e = 5; else if (l<=896) e = 6; else e = 7; return sliding_window_pow(x, n, e, E, sqr, mul); } GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma; return gerepilecopy(av, gen_pow_i(x,n,E,sqr,mul)); } /* assume n > 0. Compute x^n using left-right binary powering */ 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); GEN y; int j; if (n == 1) return gcopy(x); y = x; j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { 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 (DEBUGMEM>1) pari_warn(warnmem,"gen_powu_fold (%d)", j); y = gerepilecopy(av, y); } } return y; } GEN gen_powu_fold(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { pari_sp av = avma; if (n == 1) return gcopy(x); return gerepilecopy(av, gen_powu_fold_i(x,n,E,sqr,msqr)); } /* assume N != 0, t_INT. Compute x^|N| using left-right binary powering */ GEN gen_pow_fold_i(GEN x, GEN N, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { long ln = lgefint(N); if (ln == 3) return gen_powu_fold_i(x, N[2], E, sqr, msqr); else { GEN nd = int_MSW(N), y = x; ulong n = *nd; long i; int j = 1+bfffo(n); pari_sp av = avma, lim = stack_lim(av, 1); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (i=ln-2;;) { for (; j; n<<=1,j--) { 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 (DEBUGMEM>1) pari_warn(warnmem,"gen_pow_fold (%d)", j); y = gerepilecopy(av, y); } } if (--i == 0) return y; nd = int_precW(nd); n = *nd; j = BITS_IN_LONG; } } } GEN gen_pow_fold(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { pari_sp av = avma; return gerepilecopy(av, gen_pow_fold_i(x,n,E,sqr,msqr)); } GEN gen_powers(GEN x, long l, int use_sqr, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN), GEN (*one)(void*)) { long i; GEN V = cgetg(l+2,t_VEC); gel(V,1) = one(E); if (l==0) return V; gel(V,2) = gcopy(x); if (l==1) return V; gel(V,3) = sqr(E,x); if (use_sqr) for(i = 4; i < l+2; i++) gel(V,i) = (i&1)? sqr(E,gel(V, (i+1)>>1)) : mul(E,gel(V, i-1),x); else for(i = 4; i < l+2; i++) gel(V,i) = mul(E,gel(V,i-1),x); return V; } /***********************************************************************/ /** **/ /** DISCRETE LOGARITHM **/ /** **/ /***********************************************************************/ static GEN iter_rho(GEN x, GEN g, GEN q, GEN A, ulong h, void *E, const struct bb_group *grp) { GEN a = gel(A,1); switch((h|grp->hash(a))%3UL) { case 0: return mkvec3(grp->pow(E,a,gen_2),Fp_mulu(gel(A,2),2,q), Fp_mulu(gel(A,3),2,q)); case 1: return mkvec3(grp->mul(E,a,x),addis(gel(A,2),1),gel(A,3)); case 2: return mkvec3(grp->mul(E,a,g),gel(A,2),addis(gel(A,3),1)); } return NULL; } /*Generic Pollard rho discrete log algorithm*/ 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); GEN A, B, l, sqrt4q = sqrti(shifti(q,4)); ulong i, h = 0, imax = itou_or_0(sqrt4q); if (!imax) imax = ULONG_MAX; do { rho_restart: A = B = mkvec3(x,gen_1,gen_0); i=0; do { if (i>imax) { h++; if (DEBUGLEVEL) pari_warn(warner,"changing Pollard rho hash seed to %ld",h); goto rho_restart; } 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(DEBUGMEM>1) pari_warn(warnmem,"gen_Pollard_log"); gerepileall(av, 2, &A, &B); } i++; } while (!grp->equal(gel(A,1), gel(B,1))); gel(A,2) = modii(gel(A,2), q); gel(B,2) = modii(gel(B,2), q); h++; } while (equalii(gel(A,2), gel(B,2))); l = Fp_div(Fp_sub(gel(B,3), gel(A,3),q),Fp_sub(gel(A,2), gel(B,2), q), q); return gerepileuptoint(av, l); } /*Generic Shanks baby-step/giant-step algorithm*/ static GEN gen_Shanks_log(GEN x, GEN g0,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; p1 = sqrti(q); if (cmpiu(p1,LGBITS) >= 0) 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); 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))) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, baby = %ld", i); p1 = gerepileupto(av1, p1); } } 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); for (k=1; k<= lbaby; k++) { long h = grp->hash(p1); long 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); } } p1 = grp->mul(E,p1,giant); if (low_stack(lim, stack_lim(av1,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, giant = %ld", k); p1 = gerepileupto(av1, p1); } } avma = av; return cgetg(1, t_VEC); /* no solution */ } /*Generic discrete logarithme in a group of prime order p*/ GEN gen_plog(GEN x, GEN g, GEN p, void *E, const struct bb_group *grp) { if (grp->easylog) { GEN e = grp->easylog(E, x, g, p); if (e) return e; } if (grp->equal1(x)) return gen_0; if (grp->equal(x,g)) return gen_1; if (expi(p)<32) return gen_Shanks_log(x,g,p,E,grp); return gen_Pollard_log(x, g, p, E, grp); } GEN dlog_get_ordfa(GEN o) { if (!o) return NULL; switch(typ(o)) { case t_INT: if (signe(o) > 0) return mkvec2(o, Z_factor(o)); break; case t_MAT: if (is_Z_factorpos(o)) return mkvec2(factorback(o), o); break; case t_VEC: if (lg(o) == 3 && signe(gel(o,1)) > 0 && is_Z_factorpos(gel(o,2))) return o; break; } pari_err_TYPE("generic discrete logarithm (order factorization)",o); return NULL; /* not reached */ } GEN dlog_get_ord(GEN o) { if (!o) return NULL; switch(typ(o)) { case t_INT: if (signe(o) > 0) return o; break; case t_MAT: o = factorback(o); if (typ(o) == t_INT && signe(o) > 0) return o; break; case t_VEC: if (lg(o) != 3) break; o = gel(o,1); if (typ(o) == t_INT && signe(o) > 0) return o; break; } pari_err_TYPE("generic discrete logarithm (order factorization)",o); return NULL; /* not reached */ } /* grp->easylog() is an optional trapdoor function that catch easy logarithms*/ /* Generic Pohlig-Hellman discrete logarithm*/ /* smallest integer n such that g^n=a. Assume g has order ord */ GEN gen_PH_log(GEN a, GEN g, GEN ord, void *E, const struct bb_group *grp) { pari_sp av = avma; GEN v,t0,a0,b,q,g_q,n_q,ginv0,qj,ginv; GEN fa, ex; long e,i,j,l; if (grp->equal(g, a)) /* frequent special case */ return grp->equal1(g)? gen_0: gen_1; if (grp->easylog) { GEN e = grp->easylog(E, a, g, ord); if (e) return e; } v = dlog_get_ordfa(ord); ord= gel(v,1); fa = gel(v,2); ex = gel(fa,2); fa = gel(fa,1); l = lg(fa); ginv = grp->pow(E,g,gen_m1); v = cgetg(l, t_VEC); for (i=1; i5) err_printf("Pohlig-Hellman: DL mod %Ps^%ld\n",q,e); qj = new_chunk(e+1); gel(qj,0) = gen_1; gel(qj,1) = q; for (j=2; j<=e; j++) gel(qj,j) = mulii(gel(qj,j-1), q); t0 = diviiexact(ord, gel(qj,e)); a0 = grp->pow(E, a, t0); ginv0 = grp->pow(E, ginv, t0); /* order q^e */ if (grp->equal1(ginv0)) { gel(v,i) = mkintmod(gen_0, gen_1); continue; } do { g_q = grp->pow(E,g, mulii(t0, gel(qj,--e))); /* order q */ } while (grp->equal1(g_q)); n_q = gen_0; for (j=0;; j++) { /* n_q = sum_{ipow(E,a0, gel(qj,e-j)); /* early abort: cheap and very effective */ if (j == 0 && !grp->equal1(grp->pow(E,b,q))) { avma = av; return cgetg(1, t_VEC); } b = gen_plog(b, g_q, q, E, grp); if (typ(b) != t_INT) { avma = av; return cgetg(1, t_VEC); } n_q = addii(n_q, mulii(b, gel(qj,j))); if (j == e) break; a0 = grp->mul(E,a0, grp->pow(E,ginv0, b)); ginv0 = grp->pow(E,ginv0, q); } gel(v,i) = mkintmod(n_q, gel(qj,e+1)); } return gerepileuptoint(av, lift(chinese1_coprime_Z(v))); } /***********************************************************************/ /** **/ /** ORDER OF AN ELEMENT **/ /** **/ /***********************************************************************/ /*Find the exact order of a assuming a^o==1*/ GEN gen_order(GEN a, GEN o, void *E, const struct bb_group *grp) { 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 = grp->pow(E, a, t); } if (grp->equal1(y)) o = t; else { for (j = 1; j < e; j++) { y = grp->pow(E, y, p); if (grp->equal1(y)) break; } if (j < e) { if (j > 1) p = powiu(p, j); o = mulii(t, p); } } } return gerepilecopy(av, o); } /*Find the exact order of a assuming a^o==1, return [order,factor(order)] */ GEN gen_factored_order(GEN a, GEN o, void *E, const struct bb_group *grp) { pari_sp av = avma; long i, l, ind; GEN m, F, P; m = dlog_get_ordfa(o); if (!m) pari_err_TYPE("gen_factored_order [missing order]",a); o = gel(m,1); m = gel(m,2); l = lgcols(m); P = cgetg(l, t_COL); ind = 1; F = cgetg(l, t_COL); 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 = grp->pow(E, a, t); } if (grp->equal1(y)) o = t; else { for (j = 1; j < e; j++) { y = grp->pow(E, y, p); if (grp->equal1(y)) break; } gel(P,ind) = p; gel(F,ind) = utoipos(j); if (j < e) { if (j > 1) p = powiu(p, j); o = mulii(t, p); } ind++; } } setlg(P, ind); setlg(F, ind); return gerepilecopy(av, mkvec2(o, mkmat2(P,F))); } /* E has order o[1], ..., or o[#o], draw random points until all solutions * but one are eliminated */ GEN gen_select_order(GEN o, void *E, const struct bb_group *grp) { pari_sp ltop = avma, btop; GEN lastgood, so, vo; long lo = lg(o), nbo=lo-1; if (nbo == 1) return icopy(gel(o,1)); so = ZV_indexsort(o); /* minimize max( o[i+1] - o[i] ) */ vo = zero_zv(lo); lastgood = gel(o, so[nbo]); btop = avma; for(;;) { GEN lasto = gen_0; GEN P = grp->rand(E), t = mkvec(gen_0); long i; for (i = 1; i < lo; i++) { GEN newo = gel(o, so[i]); if (vo[i]) continue; t = grp->mul(E,t, grp->pow(E, P, subii(newo,lasto)));/*P^o[i]*/ lasto = newo; if (!grp->equal1(t)) { if (--nbo == 1) { avma=ltop; return icopy(lastgood); } vo[i] = 1; } else lastgood = lasto; } avma = btop; } } /*******************************************************************/ /* */ /* n-th ROOT */ /* */ /*******************************************************************/ /* Assume l is prime. Return a generator of the l-th Sylow and set *zeta to an element * of order l. * * q = l^e*r, e>=1, (r,l)=1 * UNCLEAN */ static GEN gen_lgener(GEN l, long e, GEN r,GEN *zeta, void *E, const struct bb_group *grp) { const pari_sp av1 = avma; GEN m, m1; long i; for (;; avma = av1) { m1 = m = grp->pow(E, grp->rand(E), r); if (grp->equal1(m)) continue; for (i=1; ipow(E,m,l); if (grp->equal1(m)) break; } if (i==e) break; } *zeta = m; return m1; } /* Let G be a cyclic group of order o>1. Returns a (random) generator */ GEN gen_gener(GEN o, void *E, const struct bb_group *grp) { pari_sp ltop = avma, av, lim; 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); for (i = 1; i < lpr; i++) { GEN l = gcoeff(pr,i,1); long e = itos(gcoeff(pr,i,2)); 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))) { /* n can have lots of prime factors*/ if(DEBUGMEM>1) pari_warn(warnmem,"gen_gener"); z = gerepileupto(av, z); } } return gerepileupto(ltop, z); } /* solve x^l = a , l prime in G of order q. * * q = (l^e)*r, e >= 1, (r,l) = 1 * y is not an l-th power, hence generates the l-Sylow of G * m = y^(q/l) != 1 */ 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; long k; GEN p1, u1, u2, v, w, z, dl; (void)bezout(r,l,&u1,&u2); 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; p1 = w; do { z = p1; p1 = grp->pow(E,p1,l); k++; } while(!grp->equal1(p1)); if (k==e) { avma = av; return NULL; } dl = gen_plog(z,m,l,E,grp); if (typ(dl) != t_INT) { avma = av; return NULL; } dl = negi(dl); p1 = grp->pow(E, grp->pow(E,y, dl), powiu(l,e-k-1)); m = grp->pow(E,m,dl); e = k; 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(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_sqrtl"); gerepileall(av,4, &y,&v,&w,&m); } } return gerepilecopy(av, v); } /* Return one solution of x^n = a in a cyclic group of order q * * 1) If there is no solution, return NULL. * * 2) If there is a solution, there are exactly m of them [m = gcd(q-1,n)]. * If zetan!=NULL, *zetan is set to a primitive m-th root of unity so that * the set of solutions is { x*zetan^k; k=0..m-1 } */ GEN gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group *grp) { pari_sp ltop = avma, lim; GEN m, u1, u2, z; int is_1; if (is_pm1(n)) { if (zetan) *zetan = grp->pow(E,a,gen_0); return signe(n) < 0? grp->pow(E,a,gen_m1): gcopy(a); } is_1 = grp->equal1(a); if (is_1 && !zetan) return gcopy(a); 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); long i, j, e; GEN r, zeta, y, l; pari_sp av1 = avma; for (i = nbrows(F); i; i--) { l = gcoeff(F,i,1); j = itos(gcoeff(F,i,2)); e = Z_pvalrem(q,l,&r); y = gen_lgener(l,e,r,&zeta,E,grp); if (zetan) z = grp->mul(E,z, grp->pow(E,y,powiu(l,e-j))); if (!is_1) { do { a = gen_Shanks_sqrtl(a,l,e,r,y,zeta,E,grp); if (!a) { avma = ltop; return NULL;} } while (--j); } if (low_stack(lim, stack_lim(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); } } } if (!equalii(m, n)) a = grp->pow(E,a,modii(u1,q)); if (zetan) { *zetan = z; gerepileall(ltop,2,&a,zetan); } else /* is_1 is 0: a was modified above -> gerepileupto valid */ a = gerepileupto(ltop, a); return a; } /*******************************************************************/ /* */ /* structure of groups with pairing */ /* */ /*******************************************************************/ static GEN ellgroup_d2(GEN N, GEN d) { GEN r = gcdii(N, d); GEN F1 = gel(Z_factor(r), 1); long i, j, l1 = lg(F1); GEN F = cgetg(3, t_MAT); gel(F,1) = cgetg(l1, t_COL); gel(F,2) = cgetg(l1, t_COL); for (i = 1, j = 1; i < l1; ++i) { long v = Z_pval(N, gel(F1, i)); if (v<=1) continue; gcoeff(F, j , 1) = gel(F1, i); gcoeff(F, j++, 2) = stoi(v); } setlg(F[1],j); setlg(F[2],j); return j==1 ? NULL : mkvec2(factorback(F), F); } GEN gen_ellgroup(GEN N, GEN d, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)) { pari_sp av = avma; GEN N0, N1, F; if (pt_m) *pt_m = gen_1; if (is_pm1(N)) return cgetg(1,t_VEC); F = ellgroup_d2(N, d); if (!F) {avma = av; return mkveccopy(N);} N0 = gel(F,1); N1 = diviiexact(N, N0); while(1) { pari_sp av2 = avma; GEN P, Q, d, s, t, m; P = grp->pow(E,grp->rand(E), N1); s = gen_order(P, F, E, grp); if (equalii(s, N0)) {avma = av; return mkveccopy(N);} Q = grp->pow(E,grp->rand(E), N1); t = gen_order(Q, F, E, grp); if (equalii(t, N0)) {avma = av; return mkveccopy(N);} m = lcmii(s, t); d = pairorder(E, P, Q, m, F); /* structure is [N/d, d] iff m d == N0. Note that N/d = N1 m */ if (is_pm1(d) && equalii(m, N0)) {avma = av; return mkveccopy(N);} if (equalii(mulii(m, d), N0)) { GEN g = mkvec2(mulii(N1,m), d); if (pt_m) *pt_m = m; gerepileall(av,pt_m?2:1,&g,pt_m); return g; } avma = av2; } } GEN gen_ellgens(GEN D1, GEN d2, GEN m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)) { pari_sp ltop = avma, av; GEN F, d1, dm; GEN P, Q, d, s; F = dlog_get_ordfa(D1); d1 = gel(F, 1), dm = diviiexact(d1,m); av = avma; do { avma = av; P = grp->rand(E); s = gen_order(P, F, E, grp); } while (!equalii(s, d1)); av = avma; do { avma = av; Q = grp->rand(E); d = pairorder(E, grp->pow(E, P, dm), grp->pow(E, Q, dm), m, F); } while (!equalii(d, d2)); return gerepilecopy(ltop, mkvec2(P,Q)); } pari-2.7.5/src/basemath/concat.c0000644000175000017500000003254612366172547015123 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* CONCATENATION */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* assume A or B is a t_LIST */ static GEN listconcat(GEN A, GEN B) { long i, l1, lx; GEN L, z, L1, L2; if (typ(A) != t_LIST) { L2 = list_data(B); if (!L2) return mklistcopy(A); lx = lg(L2) + 1; z = listcreate(); list_data(z) = L = cgetg(lx, t_VEC); for (i = 2; i < lx; i++) gel(L,i) = gcopy(gel(L2,i-1)); gel(L,1) = gcopy(A); return z; } else if (typ(B) != t_LIST) { L1 = list_data(A); if (!L1) return mklistcopy(B); lx = lg(L1) + 1; z = listcreate(); list_data(z) = L = cgetg(lx, t_VEC); for (i = 1; i < lx-1; i++) gel(L,i) = gcopy(gel(L1,i)); gel(L,i) = gcopy(B); return z; } /* A, B both t_LISTs */ L1 = list_data(A); if (!L1) return listcopy(B); L2 = list_data(B); if (!L2) return listcopy(A); l1 = lg(L1); lx = l1-1 + lg(L2); z = cgetg(3, t_LIST); list_nmax(z) = 0; list_data(z) = L = cgetg(lx, t_VEC); L2 -= l1-1; for (i=1; i=3) break; return (ly==1)? x: shallowconcat(x,gel(y,1)); case t_MAT: z=cgetg(ly,t_MAT); if (lx != ly) break; for (i=1; i=3) break; return (ly==1)? x: shallowconcat(x, gel(y,1)); case t_MAT: if (lx != lgcols(y)) break; z=cgetg(ly+1,t_MAT); gel(z,1) = x; for (i=2; i<=ly; i++) gel(z,i) = gel(y,i-1); return z; } break; case t_MAT: switch(ty) { case t_VEC: z=cgetg(lx, t_MAT); if (ly != lx) break; for (i=1; i= y1; y--) { GEN c = gel(y,0); long nc = lg(c)-1; if (nc == 0) continue; if (h != lgcols(c)) { if (h) err_cat(gel(y2,0), c); h = lgcols(c); } L += nc; z = new_chunk(nc) - 1; for (i=1; i<=nc; i++) gel(z,i) = gel(c,i); } z = new_chunk(1); *z = evaltyp(t_MAT) | evallg(L); return z; } static GEN catmanySTR(GEN y1, GEN y2) { long L = 1; /* final \0 */ GEN z, y; char *s; for (y = y1; y <= y2; y++) { char *c = GSTR( gel(y,0) ); L += strlen(c); } z = cgetg(nchar2nlong(L)+1, t_STR); s = GSTR(z); for (y = y1; y <= y2; y++) { char *c = GSTR( gel(y,0) ); long nc = strlen(c); if (nc) { (void)strncpy(s, c, nc); s += nc; } } *s = 0; return z; } /* all entries in y have the same type t = t_VEC, COL, MAT or VECSMALL * concatenate y[k1..k2], with yi = y + ki, k1 <= k2 */ static GEN catmany(GEN y1, GEN y2, long t) { long i, L; GEN z, y; if (y1 == y2) return gel(y1,0); if (t == t_MAT) return catmanyMAT(y1, y2); if (t == t_STR) return catmanySTR(y1, y2); L = 1; for (y = y2; y >= y1; y--) { GEN c = gel(y,0); long nc = lg(c)-1; if (nc == 0) continue; L += nc; z = new_chunk(nc) - 1; for (i=1; i<=nc; i++) gel(z,i) = gel(c,i); } z = new_chunk(1); *z = evaltyp(t) | evallg(L); return z; } GEN shallowconcat1(GEN x) { pari_sp av = avma, lim = stack_lim(av, 3); long lx, t, i; GEN z; switch(typ(x)) { case t_VEC: lx = lg(x); if (lx==1) pari_err_DOMAIN("concat","vector","=",x,x); break; case t_LIST: if (!list_data(x)) pari_err_DOMAIN("concat","vector","=",x,x); x = list_data(x); lx = lg(x); break; default: pari_err_TYPE("concat",x); return NULL; /* not reached */ } if (lx==2) return gel(x,1); z = gel(x,1); t = typ(z); i = 2; if (is_matvec_t(t) || t == t_VECSMALL || t == t_STR) { /* detect a "homogeneous" object: catmany is faster */ for (; i1) pari_warn(warnmem,"concat: i = %ld", i); z = gerepilecopy(av, z); } } return z; } GEN concat1(GEN x) { pari_sp av = avma; return gerepilecopy(av, shallowconcat1(x)); } /* fill M[xoff+i, yoff+j] with the contents of c ( c * Id_n if scalar ) */ static void matfill(GEN M, GEN c, long xoff, long yoff, long n) { long i, j, h, l; l = lg(c); if (l == 1) return; switch(typ(c)) { case t_VEC: for (i = 1; i < l; i++) gcoeff(M,xoff+1,yoff+i) = gel(c,i); break; case t_COL: for (i = 1; i < l; i++) gcoeff(M,xoff+i,yoff+1) = gel(c,i); break; case t_MAT: h = lgcols(c); for (j = 1; j < l; j++) for (i = 1; i < h; i++) gcoeff(M,xoff+i,yoff+j) = gcoeff(c,i,j); break; default: for (i = 1; i <= n; i++) gcoeff(M, xoff+i, yoff+i) = c; break; } } static GEN _matsize(GEN x) { long t = typ(x), L = lg(x) - 1; switch(t) { /* matsize */ case t_VEC: return mkvecsmall2(1, L); case t_COL: return mkvecsmall2(L, 1); case t_MAT: return mkvecsmall2(L? nbrows(x): 0, L); default: if (is_noncalc_t(t)) pari_err_TYPE("_matsize", x); return mkvecsmall2(1, 1); } } GEN shallowmatconcat(GEN v) { long i, j, h, l = lg(v), L = 0, H = 0; GEN M, maxh, maxl; if (l == 1) return cgetg(1,t_MAT); switch(typ(v)) { case t_VEC: for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); H = maxss(H, s[1]); L += s[2]; } M = zeromatcopy(H, L); L = 0; for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); matfill(M, c, 0, L, 1); L += s[2]; } return M; case t_COL: for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); H += s[1]; L = maxss(L, s[2]); } M = zeromatcopy(H, L); H = 0; for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); matfill(M, c, H, 0, 1); H += s[1]; } return M; case t_MAT: h = lgcols(v); maxh = zero_zv(h-1); maxl = zero_zv(l-1); for (j = 1; j < l; j++) for (i = 1; i < h; i++) { GEN c = gcoeff(v,i,j); GEN s = _matsize(c); if (s[1] > maxh[i]) maxh[i] = s[1]; if (s[2] > maxl[j]) maxl[j] = s[2]; } for (i = 1, H = 0; i < h; i++) H += maxh[i]; for (j = 1, L = 0; j < l; j++) L += maxl[j]; M = zeromatcopy(H, L); for (j = 1, L = 0; j < l; j++) { for (i = 1, H = 0; i < h; i++) { GEN c = gcoeff(v,i,j); matfill(M, c, H, L, minss(maxh[i], maxl[j])); H += maxh[i]; } L += maxl[j]; } return M; default: pari_err_TYPE("shallowmatconcat", v); return NULL; } } GEN matconcat(GEN v) { pari_sp av = avma; return gerepilecopy(av, shallowmatconcat(v)); } GEN concat(GEN x, GEN y) { long tx, lx,ty,ly,i; GEN z,p1; if (!y) return concat1(x); tx = typ(x); ty = typ(y); if (tx==t_STR || ty==t_STR) { pari_sp av = avma; return gerepileuptoleaf(av, strconcat(x,y)); } if (tx==t_LIST || ty==t_LIST) return listconcat(x,y); lx=lg(x); ly=lg(y); if (tx==t_MAT && lx==1) { if (ty!=t_VEC) return gtomat(y); if (ly==1) return cgetg(1, t_MAT); err_cat(x,y); } if (ty==t_MAT && ly==1) { if (tx!=t_VEC) return gtomat(x); if (lx==1) return cgetg(1, t_MAT); err_cat(x,y); } if (tx == ty) { if (tx == t_MAT && lgcols(x) != lgcols(y)) err_cat(x,y); if (!is_matvec_t(tx)) { if (tx != t_VECSMALL) return mkvec2copy(x, y); z = cgetg(lx+ly-1,t_VECSMALL); for (i=1; i=3) break; return (ly==1)? gcopy(x): concat(x,gel(y,1)); case t_MAT: z=cgetg(ly,t_MAT); if (lx != ly) break; for (i=1; i=3) break; return (ly==1)? gcopy(x): concat(x,gel(y,1)); case t_MAT: if (lx != lgcols(y)) break; z=cgetg(ly+1,t_MAT); gel(z,1) = gcopy(x); for (i=2; i<=ly; i++) gel(z,i) = gcopy(gel(y,i-1)); return z; } break; case t_MAT: switch(ty) { case t_VEC: z=cgetg(lx,t_MAT); if (ly != lx) break; for (i=1; i 0) /* x "scalar" */ { if (!degpol(y)) /* constant t_POL, treat as scalar */ { y = gel(y,2); if (!pr || pr == ONLY_DIVIDES) gdiv(x,y); z = rem_scal_scal(x,y); if (pr == ONLY_REM) return z; *pr = z; return gdiv(x,y); } if (!signe(y)) pari_err_INV("poldivrem",y); if (!pr || pr == ONLY_DIVIDES) return gequal0(x)? RgX_get_0(y): NULL; z = gmul(x, RgX_get_1(y)); if (pr == ONLY_REM) return z; *pr = z; return RgX_get_0(y); } return RgX_divrem(x,y,pr); } GEN gdeuc(GEN x, GEN y) { const char *f = "euclidean division"; long tx = typ(x), ty = typ(y), vx = gvar(x), vy = gvar(y); if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err_TYPE2(f,x,y); if (vx == vy && ((tx==t_POLMOD) ^ (ty==t_POLMOD))) pari_err_TYPE2(f,x,y); if (ty != t_POL || varncmp(vx, vy) < 0) return gdiv(x,y); /* y "scalar" */ if (tx != t_POL || varncmp(vx, vy) > 0) { /* x "scalar" */ if (!signe(y)) pari_err_INV("gdeuc",y); if (!degpol(y)) return gdiv(x, gel(y,2)); /* constant */ return RgX_get_0(y); } return RgX_div(x,y); } GEN grem(GEN x, GEN y) { const char *f = "euclidean division"; long tx = typ(x), ty = typ(y), vx = gvar(x), vy = gvar(y); if (ty == t_POL) { if (varncmp(vx,vy) >= 0) { pari_sp av; GEN z; if (!signe(y)) pari_err_INV("grem",y); if (vx != vy) return rem_scal_pol(x,y); switch(tx) { case t_POLMOD: return polmod_mod(x,y); case t_POL: return RgX_rem(x,y); case t_RFRAC: av = avma; z = gmul(gel(x,1), RgXQ_inv(gel(x,2),y)); return gerepileupto(av, grem(z,y)); case t_SER: if (RgX_is_monomial(y)) { if (lg(x)-2 + valp(x) < degpol(y)) pari_err_OP("%",x,y); av = avma; return gerepileupto(av, gmod(ser2rfrac_i(x), y)); } default: pari_err_TYPE2("%",x,y); } } else switch(tx) { case t_POL: case t_RFRAC: return rem_pol_scal(x,y); default: pari_err_TYPE2("%",x,y); } } if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err_TYPE2(f,x,y); if (vx == vy && ty==t_POLMOD) pari_err_TYPE2(f,x,y); if (tx != t_POL || varncmp(vx,vy) > 0) { /* x a "scalar" */ if (ty != t_POL || varncmp(vx, vy) < 0) return rem_scal_scal(x,y); return rem_scal_pol(x,y); } if (ty != t_POL || varncmp(vx, vy) < 0) /* y a "scalar" */ return rem_pol_scal(x,y); return RgX_rem(x,y); } /*******************************************************************/ /* */ /* CONVERSIONS RELATED TO p-ADICS */ /* */ /*******************************************************************/ /* x t_PADIC, p a prime or NULL (unset). Consistency check */ static void check_padic_p(GEN x, GEN p) { GEN q = gel(x,2); if (p && !equalii(p, q)) pari_err_MODULUS("Zp_to_Z", p,q); } /* shallow */ static GEN Zp_to_Z(GEN x, GEN p) { switch(typ(x)) { case t_INT: break; case t_PADIC: check_padic_p(x, p); x = gtrunc(x); break; default: pari_err_TYPE("Zp_to_Z",x); } return x; } /* shallow */ static GEN ZpX_to_ZX(GEN f, GEN p) { long i, l = lg(f); GEN F = cgetg_copy(f, &l); F[1] = f[1]; for (i=2; i= prec */ GEN ZX_Zp_root(GEN f, GEN a, GEN p, long prec) { GEN z, R, a0 = modii(a, p); long i, j, k, v; if (signe(FpX_eval(FpX_deriv(f, p), a0, p))) { /* simple zero mod p, go all the way to p^prec */ if (prec > 1) a0 = ZpX_liftroot(f, a0, p, prec); return mkcol(a0); } 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)); z = cgetg(degpol(f)+1,t_COL); R = FpX_roots(f, p); for (j=i=1; i 0) f = RgX_div(f,z); T = gel(a,1); a = gel(a,2); p = NULL; prec = LONG_MAX; getprec(a, &prec, &p); getprec(T, &prec, &p); if (!p) pari_err_TYPE("padicappr",T); f = QpXQX_to_ZXY(f, p); a = QpX_to_ZX(a,p); T = QpX_to_ZX(T,p); z = ZXY_ZpQ_root(f, a, T, p, prec); return gerepilecopy(av, ZXV_to_ZpXQV(z, T, p, prec)); } /*******************************************************************/ /* */ /* FACTORIZATION in Zp[X], using ROUND4 */ /* */ /*******************************************************************/ int cmp_padic(GEN x, GEN y) { long vx, vy; if (x == gen_0) return -1; if (y == gen_0) return 1; vx = valp(x); vy = valp(y); if (vx < vy) return 1; if (vx > vy) return -1; return cmpii(gel(x,4), gel(y,4)); } static int expo_is_squarefree(GEN e) { long i, l = lg(e); for (i=1; i 0 */ GEN ZX_monic_factorpadic(GEN f, GEN p, long prec) { GEN w, poly, p1, p2, ex, P, E; long n=degpol(f), i, k, j; if (n==1) return mkmat2(mkcol(f), mkcol(gen_1)); poly = ZX_squff(f,&ex); P = cgetg(n+1,t_COL); E = cgetg(n+1,t_COL); n = lg(poly); for (j=i=1; i 2, T ZX, p prime, x t_INT */ static long lemma6(GEN T, GEN p, long nu, GEN x) { long la, mu; pari_sp av = avma; GEN gpx, gx = poleval(T, x); if (Zp_issquare(gx, p)) { avma = av; return 1; } la = Z_pval(gx, p); gpx = poleval(ZX_deriv(T), x); mu = signe(gpx)? Z_pval(gpx,p) : la+nu+1; /* mu = +oo */ avma = av; if (la > mu<<1) return 1; if (la >= nu<<1 && mu >= nu) return 0; return -1; } /* p = 2, T ZX, x t_INT: return 1 = yes, -1 = no, 0 = inconclusive */ static long lemma7(GEN T, long nu, GEN x) { long odd4, la, mu; pari_sp av = avma; GEN gpx, oddgx, gx = poleval(T, x); if (Zp_issquare(gx,gen_2)) return 1; gpx = poleval(ZX_deriv(T), x); la = Z_lvalrem(gx, 2, &oddgx); odd4 = umodiu(oddgx,4); avma = av; mu = vali(gpx); if (mu < 0) mu = la+nu+1; /* mu = +oo */ if (la > mu<<1) return 1; if (nu > mu) { long mnl = mu+nu-la; if (odd(la)) return -1; if (mnl==1) return 1; if (mnl==2 && odd4==1) return 1; } else { long nu2 = nu << 1; if (la >= nu2) return 0; if (la == nu2 - 2 && odd4==1) return 0; } return -1; } /* T a ZX, p a prime, pnu = p^nu, x0 t_INT */ static long zpsol(GEN T, GEN p, long nu, GEN pnu, GEN x0) { long i, res; pari_sp av = avma; GEN x, pnup; res = equaliu(p,2)? lemma7(T,nu,x0): lemma6(T,p,nu,x0); if (res== 1) return 1; if (res==-1) return 0; x = x0; pnup = mulii(pnu,p); for (i=0; i < itos(p); i++) { x = addii(x,pnu); if (zpsol(T,p,nu+1,pnup,x)) { avma = av; return 1; } } avma = av; return 0; } /* return 1 if equation y^2=T(x) has a rational p-adic solution (possibly * infinite), 0 otherwise. */ long hyperell_locally_soluble(GEN T,GEN p) { pari_sp av = avma; long res; if (typ(T)!=t_POL) pari_err_TYPE("zpsoluble",T); if (typ(p)!=t_INT) pari_err_TYPE("zpsoluble",p); RgX_check_ZX(T, "zpsoluble"); res = zpsol(T,p,0,gen_1,gen_0) || zpsol(RgX_recip_shallow(T), p, 1, p, gen_0); avma = av; return res; } /* is t a square in (O_K/pr) ? Assume v_pr(t) = 0 */ static long quad_char(GEN nf, GEN t, GEN pr) { GEN ord, ordp, T, p, modpr = zk_to_Fq_init(nf, &pr,&T,&p); t = nf_to_Fq(nf,t,modpr); if (T) { ord = subis( pr_norm(pr), 1 ); /* |(O_K / pr)^*| */ ordp= subis( p, 1); /* |F_p^*| */ t = Fq_pow(t, diviiexact(ord, ordp), T,p); /* in F_p^* */ if (typ(t) == t_POL) { if (degpol(t)) pari_err_BUG("nfhilbertp"); t = gel(t,2); } } return kronecker(t, p); } /* quad_char(x), x in Z, non-zero mod p */ static long Z_quad_char(GEN x, GEN pr) { long f = pr_get_f(pr); if (!odd(f)) return 1; return kronecker(x, pr_get_p(pr)); } /* (pr,2) = 1. return 1 if x in Z_K is a square in Z_{K_pr}, 0 otherwise. * modpr = zkmodprinit(nf,pr) */ static long psquarenf(GEN nf,GEN x,GEN pr,GEN modpr) { pari_sp av = avma; GEN p = pr_get_p(pr); long v; x = nf_to_scalar_or_basis(nf, x); if (typ(x) == t_INT) { if (!signe(x)) return 1; v = Z_pvalrem(x, p, &x) * pr_get_e(pr); if (v&1) return 0; v = (Z_quad_char(x, pr) == 1); } else { v = ZC_nfvalrem(nf, x, pr, &x); if (v&1) return 0; v = (quad_char(nf, x, modpr) == 1); } avma = av; return v; } /* Is x a square in (ZK / pr^(1+2e))^* ? pr | 2 */ static long check2(GEN nf, GEN x, GEN zinit) { GEN zlog = ideallog(nf, x, zinit); long i, l = lg(zlog); for (i=1; i 1) */ if (mpodd(gel(zlog,i))) return 0; return 1; } /* pr | 2. Return 1 if x in Z_K is square in Z_{K_pr}, 0 otherwise */ static int psquare2nf_i(GEN nf,GEN x,GEN pr,GEN zinit) { long v = nfvalrem(nf, x, pr, &x); /* now (x,pr) = 1 */ return v == LONG_MAX || (!odd(v) && check2(nf,x,zinit)); } static int psquare2nf(GEN nf,GEN x,GEN pr,GEN zinit) { pari_sp av = avma; long v = psquare2nf_i(nf,x,pr,zinit); avma = av; return v; } /* pr above an odd prime */ static long lemma6nf(GEN nf, GEN T, GEN pr, long nu, GEN x, GEN modpr) { pari_sp av = avma; long la, mu; GEN gpx, gx = nfpoleval(nf, T, x); if (psquarenf(nf,gx,pr,modpr)) return 1; la = nfval(nf,gx,pr); gpx = nfpoleval(nf, RgX_deriv(T), x); mu = gequal0(gpx)? la+nu+1: nfval(nf,gpx,pr); avma = av; if (la > (mu<<1)) return 1; if (la >= (nu<<1) && mu >= nu) return 0; return -1; } /* pr above 2 */ static long lemma7nf(GEN nf, GEN T, GEN pr, long nu, GEN x, GEN zinit) { long res, la, mu, q; GEN gpx, gx = nfpoleval(nf, T, x); if (psquare2nf(nf,gx,pr,zinit)) return 1; gpx = nfpoleval(nf, RgX_deriv(T), x); /* gx /= pi^la, pi a pr-uniformizer */ la = ZC_nfvalrem(nf, gx, pr, &gx); mu = gequal0(gpx)? la+nu+1: nfval(nf,gpx,pr); if (la > (mu<<1)) return 1; if (nu > mu) { if (la&1) return -1; q = mu+nu-la; res = 1; } else { long nu2 = nu<<1; if (la >= nu2) return 0; if (odd(la)) return -1; q = nu2-la; res = 0; } if (q > pr_get_e(pr)<<1) return -1; if (q == 1) return res; /* is gx a square mod pi^q ? FIXME : highly inefficient */ zinit = zidealstarinit(nf, idealpows(nf,pr,q)); if (!check2(nf, gx, zinit)) res = -1; return res; } /* zinit either a bid (pr | 2) or a modpr structure (pr | p odd). pnu = pi^nu, pi a uniformizer */ static long zpsolnf(GEN nf,GEN T,GEN pr,long nu,GEN pnu,GEN x0,GEN repr,GEN zinit) { long i, res; pari_sp av = avma; GEN pnup; res = typ(zinit) == t_VEC? lemma7nf(nf,T,pr,nu,x0,zinit) : lemma6nf(nf,T,pr,nu,x0,zinit); avma = av; if (res== 1) return 1; if (res==-1) return 0; pnup = nfmul(nf, pnu, pr_get_gen(pr)); nu++; for (i=1; i 1) { GEN H = idealhnf_two(nf,pr); for (i = k = 2; k <= f; i++) { if (is_pm1(gcoeff(H,i,i))) continue; perm[k++] = i; } } rep = cgetg(pf+1,t_VEC); gel(rep,1) = zerocol(N); for (pi=i=1; i<=f; i++,pi*=p) { long t = perm[i]; for (j=1; j3) err_printf("nfhilbert not soluble at real place %ld\n",i); avma = av; return -1; } /* local solutions in finite completions ? (pr | 2ab) * primes above 2 are toughest. Try the others first */ Sa = idealfactor(nf, a); Sb = idealfactor(nf, b); S2 = idealfactor(nf, gen_2); S = merge_factor(Sa, Sb, (void*)&cmp_prime_ideal, &cmp_nodata); S = merge_factor(S, S2, (void*)&cmp_prime_ideal, &cmp_nodata); S = gel(S,1); /* product of all hilbertp is 1 ==> remove one prime (above 2!) */ for (i=lg(S)-1; i>1; i--) if (nfhilbertp(nf,a,b,gel(S,i)) < 0) { if (DEBUGLEVEL>3) err_printf("nfhilbert not soluble at finite place %Ps\n",S[i]); avma = av; return -1; } avma = av; return 1; } long nfhilbert0(GEN nf,GEN a,GEN b,GEN p) { nf = checknf(nf); if (p) { checkprid(p); if (gequal0(a)) pari_err_DOMAIN("nfhilbert", "a", "=", gen_0, a); if (gequal0(b)) pari_err_DOMAIN("nfhilbert", "b", "=", gen_0, b); return nfhilbertp(nf,a,b,p); } return nfhilbert(nf,a,b); } /* S a list of prime ideal in idealprimedec format. Return res: * res[1] = generators of (S-units / units), as polynomials * res[2] = [perm, HB, den], for bnfissunit * res[3] = [] (was: log. embeddings of res[1]) * res[4] = S-regulator ( = R * det(res[2]) * \prod log(Norm(S[i]))) * res[5] = S class group * res[6] = S */ GEN bnfsunit(GEN bnf,GEN S,long prec) { pari_sp av = avma; long i,j,ls; GEN p1,nf,gen,M,U,H; GEN sunit,card,sreg,res,pow; if (!is_vec_t(typ(S))) pari_err_TYPE("bnfsunit",S); bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); gen = bnf_get_gen(bnf); sreg = bnf_get_reg(bnf); res=cgetg(7,t_VEC); gel(res,1) = gel(res,2) = gel(res,3) = cgetg(1,t_VEC); gel(res,4) = sreg; gel(res,5) = bnf_get_clgp(bnf); gel(res,6) = S; ls=lg(S); /* M = relation matrix for the S class group (in terms of the class group * generators given by gen) * 1) ideals in S */ M = cgetg(ls,t_MAT); for (i=1; i 1) { /* non trivial (rare!) */ GEN A, u, D = ZM_snfall_i(H, &u, NULL, 1); card = detcyc(D, &i); setlg(D,i); A = cgetg(i,t_VEC); pow = ZM_inv(u,gen_1); for(i--; i; i--) gel(A,i) = idealfactorback(nf, gen, gel(pow,i), 1); gel(res,5) = mkvec3(card, D, A); } /* S-units */ if (ls>1) { GEN den, Sperm, perm, dep, B, A, U1 = U; long lH, lB; /* U1 = upper left corner of U, invertible. S * U1 = principal ideals * whose generators generate the S-units */ setlg(U1,ls); p1 = cgetg(ls, t_MAT); /* p1 is junk for mathnfspec */ for (i=1; i 1 && lgcols(dep) > 1) pari_err_BUG("bnfsunit"); /* [ H B ] [ H^-1 - H^-1 B ] * perm o HNF(U1) = [ 0 Id ], inverse = [ 0 Id ] * (permute the rows) * S * HNF(U1) = _integral_ generators for S-units = sunit */ Sperm = cgetg(ls, t_VEC); sunit = cgetg(ls, t_VEC); for (i=1; i 1) *px = famat_mul(xp, to_famat_shallow(xb, gen_1)); return v; } /* Analog to bnfisunit, for S-units. Let v the result * If x not an S-unit, v = []~, else * x = \prod_{i=0}^r e_i^v[i] * prod{i=r+1}^{r+s} s_i^v[i] * where the e_i are the field units (cf bnfisunit), and the s_i are * the S-units computed by bnfsunit (in the same order) */ GEN bnfissunit(GEN bnf,GEN bnfS,GEN x) { pari_sp av = avma; GEN v, w, nf; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if (typ(bnfS)!=t_VEC || lg(bnfS)!=7) pari_err_TYPE("bnfissunit",bnfS); x = nf_to_scalar_or_alg(nf,x); v = NULL; if ( (w = make_unit(nf, bnfS, &x)) ) v = bnfisunit(bnf, x); if (!v || lg(v) == 1) { avma = av; return cgetg(1,t_COL); } return gerepileupto(av, concat(v, w)); } static void pr_append(GEN nf, GEN rel, GEN p, GEN *prod, GEN *S1, GEN *S2) { if (dvdii(*prod, p)) return; *prod = mulii(*prod, p); *S1 = shallowconcat(*S1, idealprimedec(nf,p)); *S2 = shallowconcat(*S2, idealprimedec(rel,p)); } /* N a t_INT */ static void Zfa_pr_append(GEN nf,GEN rel,GEN N,GEN *prod,GEN *S1,GEN *S2) { if (!is_pm1(N)) { GEN v = gel(Z_factor(N),1); long i, l = lg(v); for (i=1; i 2) pari_err_FLAG("rnfisnorminit"); T = get_bnfpol(T, &bnf, &nf); if (!bnf) bnf = Buchall(nf? nf: T, nf_FORCE, DEFAULTPREC); if (!nf) nf = bnf_get_nf(bnf); relpol = get_bnfpol(relpol, &bnfabs, &nfabs); if (!gequal1(leading_term(relpol))) pari_err_IMPL("non monic relative equation"); drel = degpol(relpol); if (drel <= 2) galois = 1; relpol = RgX_nffix("rnfisnorminit", T, relpol, 1); if (nf_get_degree(nf) == 1) /* over Q */ rnfeq = mkvec5(relpol,gen_0,gen_0,T,relpol); else if (galois == 2) /* needs eltup+abstorel */ rnfeq = nf_rnfeq(nf, relpol); else /* needs abstorel */ rnfeq = nf_rnfeqsimple(nf, relpol); polabs = gel(rnfeq,1); k = gel(rnfeq,3); if (!bnfabs || !gequal0(k)) bnfabs = Buchall(polabs, nf_FORCE, nf_get_prec(nf)); if (!nfabs) nfabs = bnf_get_nf(bnfabs); 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); } prod = gen_1; S1 = S2 = cgetg(1, t_VEC); cyc = bnf_get_cyc(bnfabs); gen = bnf_get_gen(bnfabs); l = lg(cyc); for(i=1; i answer is unconditional) * if flag>0 add to S all primes dividing p <= flag * if flag<0 add to S all primes dividing abs(flag) * answer is a vector v = [a,b] such that * x = N(a)*b and x is a norm iff b = 1 [assuming S large enough] */ GEN rnfisnorm(GEN T, GEN x, long flag) { pari_sp av = avma; GEN bnf, rel, relpol, rnfeq, nfpol; GEN nf, aux, H, U, Y, M, A, bnfS, sunitrel, futu, prod, S1, S2; long L, i, drel, itu; if (typ(T) != t_VEC || lg(T) != 9) pari_err_TYPE("rnfisnorm [please apply rnfisnorminit()]", T); bnf = gel(T,1); rel = gel(T,2); relpol = gel(T,3); rnfeq = gel(T,4); drel = degpol(relpol); bnf = checkbnf(bnf); rel = checkbnf(rel); nf = bnf_get_nf(bnf); x = nf_to_scalar_or_alg(nf,x); if (gequal0(x)) { avma = av; return mkvec2(gen_0, gen_1); } if (gequal1(x)) { avma = av; return mkvec2(gen_1, gen_1); } if (gequalm1(x) && odd(drel)) { avma = av; return mkvec2(gen_m1, gen_1); } /* build set T of ideals involved in the solutions */ nfpol = nf_get_pol(nf); prod = gel(T,5); S1 = gel(T,6); S2 = gel(T,7); if (flag && !gequal0(gel(T,8))) pari_warn(warner,"useless flag in rnfisnorm: the extension is Galois"); if (flag > 0) { forprime_t T; ulong p; u_forprime_init(&T, 2, flag); while ( (p = u_forprime_next(&T)) ) pr_append(nf,rel, utoipos(p),&prod,&S1,&S2); } else if (flag < 0) Zfa_pr_append(nf,rel, utoipos(-flag),&prod,&S1,&S2); /* overkill: prime ideals dividing x would be enough */ fa_pr_append(nf,rel,idealnorm(nf,x), &prod,&S1,&S2); /* computation on T-units */ futu = shallowconcat(bnf_get_fu(rel), bnf_get_tuU(rel)); bnfS = bnfsunit(bnf,S1,LOWDEFAULTPREC); sunitrel = shallowconcat(futu, gel(bnfsunit(rel,S2,LOWDEFAULTPREC), 1)); A = lift_intern(bnfissunit(bnf,bnfS,x)); L = lg(sunitrel); itu = lg(nf_get_roots(nf))-1; /* index of torsion unit in bnfsunit(nf) output */ M = cgetg(L+1,t_MAT); for (i=1; i1) pari_warn(warnmem,"hnffinal, i = %ld",i); gerepileall(av, 2, &Cnew, &B); } } p1 = cgetg(lnz+1,t_VEC); p2 = perm + nlze; for (i1=0, j1=lnz-s, i=1; i<=lnz; i++) /* push the 1 rows down */ if (diagH1[i]) gel(p1,++j1) = gel(p2,i); else gel(p2,++i1) = gel(p2,i); for (i=i1+1; i<=lnz; i++) gel(p2,i) = gel(p1,i); /* s = # extra redundant generators taken from H * zc col-s co zc = col - lnz * [ 0 |dep | ] i = nlze + lnz - s = lig - s * nlze [--------| B' ] * [ 0 | H' | ] H' = H minus the s rows with a 1 on diagonal * i [--------|-----] lig-s (= "1-rows") * [ 0 | Id ] * [ | ] li */ lig -= s; col -= s; lnz -= s; Hnew = cgetg(lnz+1,t_MAT); depnew = cgetg(lnz+1,t_MAT); /* only used if nlze > 0 */ Bnew = cgetg(co-col,t_MAT); C = shallowcopy(Cnew); for (j=1,i1=j1=0; j<=lnz+s; j++) { GEN z = gel(H,j); if (diagH1[j]) { /* hit exactly s times */ i1++; C[i1+col] = Cnew[j+zc]; p1 = cgetg(lig+1,t_COL); gel(Bnew,i1) = p1; for (i=1; i<=nlze; i++) gel(p1,i) = gcoeff(dep,i,j); p1 += nlze; } else { j1++; C[j1+zc] = Cnew[j+zc]; p1 = cgetg(lnz+1,t_COL); gel(Hnew,j1) = p1; depnew[j1] = dep[j]; } for (i=k=1; k<=lnz; i++) if (!diagH1[i]) p1[k++] = z[i]; } for (j=s+1; j 6) err_printf("matgen = %Ps\n", zm_to_ZM( rowpermute(mat, perm) )); avma = av; } static GEN col_dup(long l, GEN col) { GEN c = new_chunk(l); memcpy(c,col,l * sizeof(long)); return c; } /* HNF reduce a relation matrix (column operations + row permutation) ** Input: ** mat = (li-1) x (co-1) matrix of long ** C = r x (co-1) matrix of GEN ** perm= permutation vector (length li-1), indexing the rows of mat: easier ** to maintain perm than to copy rows. For columns we can do it directly ** using e.g. swap(mat[i], mat[j]) ** k0 = integer. The k0 first lines of mat are dense, the others are sparse. ** Output: cf ASCII art in the function body ** ** row permutations applied to perm ** column operations applied to C. IN PLACE **/ GEN hnfspec_i(GEN mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0) { pari_sp av, lim; 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; const long li = lg(perm); /* = lgcols(mat0) */ const long CO = lg(mat0); n = 0; /* -Wall */ C = *ptC; co = CO; if (co > 300 && co > 1.5 * li) { /* treat the rest at the end */ co = (long)(1.2 * li); setlg(C, co); } if (DEBUGLEVEL>5) { err_printf("Entering hnfspec\n"); p_mat(mat0,perm,0); } matt = cgetg(co, t_MAT); /* dense part of mat (top) */ mat = cgetg(co, t_MAT); for (j = 1; j < co; j++) { GEN matj = col_dup(li, gel(mat0,j)); 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); i = lig = li-1; col = co-1; lk0 = k0; T = (k0 || (lg(C) > 1 && lgcols(C) > 1))? matid(col): NULL; /* Look for lines with a single non-0 entry, equal to 1 in absolute value */ while (i > lk0 && col) switch( count(mat,perm[i],col,&n) ) { case 0: /* move zero lines between k0+1 and lk0 */ lk0++; lswap(perm[i], perm[lk0]); i = lig; continue; case 1: /* move trivial generator between lig+1 and li */ lswap(perm[i], perm[lig]); if (T) swap(gel(T,n), gel(T,col)); swap(gel(mat,n), gel(mat,col)); p = gel(mat,col); if (p[perm[lig]] < 0) /* = -1 */ { /* convert relation -g = 0 to g = 0 */ for (i=lk0+1; i5) { err_printf(" after phase1:\n"); p_mat(mat,perm,0); } #define absmax(s,z) {long _z; _z = labs(z); if (_z > s) s = _z;} /* Get rid of all lines containing only 0 and +/- 1, keeping track of column * operations in T. Leave the rows 1..lk0 alone [up to k0, coefficient * explosion, between k0+1 and lk0, row is 0] */ s = 0; while (lig > lk0 && col && s < (long)(HIGHBIT>>1)) { for (i=lig; i>lk0; i--) if (count(mat,perm[i],col,&n) > 0) break; if (i == lk0) break; /* only 0, +/- 1 entries, at least 2 of them non-zero */ lswap(perm[i], perm[lig]); swap(gel(mat,n), gel(mat,col)); p = gel(mat,col); if (T) swap(gel(T,n), gel(T,col)); if (p[perm[lig]] < 0) { for (i=lk0+1; i<=lig; i++) p[perm[i]] = -p[perm[i]]; if (T) ZV_togglesign(gel(T,col)); } for (j=1; j1) pari_warn(warnmem,"hnfspec[1]"); if (T) T = gerepilecopy(av, T); else avma = av; } } /* As above with lines containing a +/- 1 (no other assumption). * Stop when single precision becomes dangerous */ vmax = cgetg(co,t_VECSMALL); for (j=1; j<=col; j++) { GEN matj = gel(mat,j); for (s=0, i=lk0+1; i<=lig; i++) absmax(s, matj[i]); vmax[j] = s; } while (lig > lk0 && col) { for (i=lig; i>lk0; i--) if ( (n = count2(mat,perm[i],col)) ) break; if (i == lk0) break; lswap(vmax[n], vmax[col]); lswap(perm[i], perm[lig]); swap(gel(mat,n), gel(mat,col)); p = gel(mat,col); if (T) swap(gel(T,n), gel(T,col)); if (p[perm[lig]] < 0) { for (i=lk0+1; i<=lig; i++) p[perm[i]] = -p[perm[i]]; if (T) ZV_togglesign(gel(T,col)); } for (j=1; j= (HIGHBIT-vmax[j]) / vmax[col]) goto END2; for (s=0, i=lk0+1; i<=lig; i++) absmax(s, matj[perm[i]] -= t*p[perm[i]]); vmax[j] = s; if (T) ZC_lincomb1_inplace(gel(T,j), gel(T,col), stoi(-t)); } lig--; col--; if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"hnfspec[2]"); gerepileall(av, T? 2: 1, &vmax, &T); } } END2: /* clean up mat: remove everything to the right of the 1s on diagonal */ /* go multiprecision first */ matb = cgetg(co,t_MAT); /* bottom part (complement of matt) */ for (j=1; j5) { err_printf(" after phase2:\n"); p_mat(mat,perm,lk0); } for (i=li-2; i>lig; i--) { long h, i0 = i - k0, k = i + co-li; GEN Bk = gel(matb,k); for (j=k+1; j 0) /* v = 1 */ { for (h=1; h1) pari_warn(warnmem,"hnfspec[3], (i,j) = %ld,%ld", i,j); for (h=1; h5) err_printf(" matb cleaned up (using Id block)\n"); nlze = lk0 - k0; /* # of 0 rows */ lnz = lig-nlze+1; /* 1 + # of non-0 rows (!= 0...0 1 0 ... 0) */ if (T) matt = ZM_mul(matt,T); /* update top rows */ extramat = cgetg(col+1,t_MAT); /* = new C minus the 0 rows */ for (j=1; j<=col; j++) { GEN z = gel(matt,j); GEN t = (gel(matb,j)) + nlze - k0; p2=cgetg(lnz,t_COL); gel(extramat,j) = p2; for (i=1; i<=k0; i++) gel(p2,i) = gel(z,i); /* top k0 rows */ for ( ; i co) { /* treat the rest, N cols at a time (hnflll slow otherwise) */ const long N = 300; long a, L = CO - co, l = minss(L, N); /* L columns to add */ GEN CC = *ptC, m0 = mat0; setlg(CC, CO); /* restore */ CC += co-1; m0 += co-1; for (a = l;;) { GEN MAT, emb; gerepileall(av, 4, &H,&C,ptB,ptdep); MAT = cgetg(l + 1, t_MAT); emb = cgetg(l + 1, typ(C)); for (j = 1 ; j <= l; j++) { gel(MAT,j) = gel(m0,j); emb[j] = CC[j]; } H = hnfadd_i(H, perm, ptdep, ptB, &C, MAT, emb); if (a == L) break; CC += l; m0 += l; a += l; if (a > L) { l = L - (a - l); a = L; } } } *ptC = C; return H; } GEN hnfspec(GEN mat, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0) { pari_sp av = avma; GEN H = hnfspec_i(mat, perm, ptdep, ptB, ptC, k0); gerepileall(av, 4, ptC, ptdep, ptB, &H); return H; } /* HNF reduce x, apply same transforms to C */ GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC) { long i,j,k,ly,lx = lg(x); GEN z, perm; if (lx == 1) return cgetg(1, t_MAT); ly = lgcols(x); *ptperm = perm = identity_perm(ly-1); z = cgetg(lx,t_MAT); for (i=1; i 1 && lgcols(*ptC) > 1) pari_err_IMPL("mathnfspec with large entries"); x = ZM_hnf(x); lx = lg(x); j = ly; k = 0; for (i=1; i5) err_printf(" 1st phase done\n"); permpro = ZM_imagecomplspec(extramat, &nlze); extramat = rowpermute(extramat, permpro); *ptB = rowpermute(B, permpro); permpro = vecpermute(perm, permpro); for (i=1; i<=lig; i++) perm[i] = permpro[i]; /* perm o= permpro */ *ptdep = rowslice(extramat, 1, nlze); matb = rowslice(extramat, nlze+1, lig); if (DEBUGLEVEL>5) err_printf(" 2nd phase done\n"); H = hnffinal(matb,perm,ptdep,ptB,&Cnew); *ptC = shallowconcat(vecslice(C, 1, col-lH), Cnew); return H; } GEN hnfadd(GEN H, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, /* cf hnfspec */ GEN extramat,GEN extraC) { pari_sp av = avma; H = hnfadd_i(H, perm, ptdep, ptB, ptC, ZM_to_zm(extramat), extraC); gerepileall(av, 4, ptC, ptdep, ptB, &H); return H; } /* zero aj = Aij (!= 0) using ak = Aik (maybe 0), via linear combination of * A[j] and A[k] of determinant 1. If U != NULL, likewise update its columns */ static void ZC_elem(GEN aj, GEN ak, GEN A, GEN U, long j, long k) { GEN p1,u,v,d; if (!signe(ak)) { swap(gel(A,j), gel(A,k)); if (U) swap(gel(U,j), gel(U,k)); return; } d = bezout(aj,ak,&u,&v); /* frequent special case (u,v) = (1,0) or (0,1) */ if (!signe(u)) { /* ak | aj */ p1 = diviiexact(aj,ak); togglesign(p1); ZC_lincomb1_inplace(gel(A,j), gel(A,k), p1); if (U) ZC_lincomb1_inplace(gel(U,j), gel(U,k), p1); return; } if (!signe(v)) { /* aj | ak */ p1 = diviiexact(ak,aj); togglesign(p1); ZC_lincomb1_inplace(gel(A,k), gel(A,j), p1); swap(gel(A,j), gel(A,k)); if (U) { ZC_lincomb1_inplace(gel(U,k), gel(U,j), p1); swap(gel(U,j), gel(U,k)); } return; } if (!is_pm1(d)) { aj = diviiexact(aj, d); ak = diviiexact(ak, d); } p1 = gel(A,k); aj = negi(aj); /* NOT togglesign */ gel(A,k) = ZC_lincomb(u,v, gel(A,j),p1); gel(A,j) = ZC_lincomb(aj,ak, p1,gel(A,j)); if (U) { p1 = gel(U,k); gel(U,k) = ZC_lincomb(u,v, gel(U,j),p1); gel(U,j) = ZC_lincomb(aj,ak, p1,gel(U,j)); } } INLINE int is_RgX(GEN a, long v) { return typ(a) == t_POL && varn(a)==v; } /* set u,v such that au + bv = gcd(a,b), divide a,b by the gcd */ static GEN gbezout_step(GEN *pa, GEN *pb, GEN *pu, GEN *pv, long vx) { GEN a = *pa, b = *pb, d; if (gequal0(a)) { *pa = gen_0; *pu = gen_0; *pb = gen_1; *pv = gen_1; return b; } a = is_RgX(a,vx)? RgX_renormalize(a): scalarpol(a, vx); b = is_RgX(b,vx)? RgX_renormalize(b): scalarpol(b, vx); d = RgX_extgcd(a,b, pu,pv); if (degpol(d)) { a = RgX_div(a, d); b = RgX_div(b, d); } else if (typ(gel(d,2)) == t_REAL && lg(gel(d,2)) <= 3) #if 1 { /* possible accuracy problem */ GEN D = RgX_gcd_simple(a,b); if (degpol(D)) { D = RgX_Rg_div(D, leading_term(D)); a = RgX_div(a, D); b = RgX_div(b, D); d = RgX_extgcd(a,b, pu,pv); /* retry now */ d = RgX_mul(d, D); } } #else { /* less stable */ d = RgX_extgcd_simple(a,b, pu,pv); if (degpol(d)) { a = RgX_div(a, d); b = RgX_div(b, d); } } #endif *pa = a; *pb = b; return d; } static GEN col_mul(GEN x, GEN c) { if (typ(x) == t_INT) { long s = signe(x); if (!s) return NULL; if (is_pm1(x)) return (s > 0)? c: RgC_neg(c); } return RgC_Rg_mul(c, x); } static void do_zero(GEN x) { long i, lx = lg(x); for (i=1; i (long)BITS_IN_LONG)) { T = normalizepol_lg(T, lg(T)-1); if (!signe(T)) { *pd = gen_1; return T; } d = leading_term(T); } *pd = d; return RgX_Rg_div(T, d); } /* reduce A[i,j] mod A[i,j0] for j=j0+1... via column operations */ static void 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); if (degpol(T) == 0) { d = gel(T,2); T = gen_1; } } else { d = T; T = gen_1; } if (U && !gequal1(d)) gel(U,j0) = RgC_Rg_div(gel(U,j0), d); gcoeff(A,i,j0) = T; for (j=j0+1; j 0. Return Au * in Z^n (v in Z^n not computed), such that Au + Bv = [1, 0, ..., 0] */ GEN hnfmerge_get_1(GEN A, GEN B) { pari_sp av = avma; long j, k, c, l = lg(A), lb; GEN b, t, U = cgetg(l + 1, t_MAT), C = cgetg(l + 1, t_VEC); t = NULL; /* -Wall */ b = gcoeff(B,1,1); lb = lgefint(b); if (!signe(b)) { if (!is_pm1(gcoeff(A,1,1))) return NULL; return scalarcol_shallow(gen_1, l-1); } for (j = 1; j < l; j++) { c = j+1; gel(U,j) = col_ei(l-1, j); gel(U,c) = zerocol(l-1); /* dummy */ gel(C,j) = vecslice(gel(A,j), 1,j); gel(C,c) = vecslice(gel(B,j), 1,j); for (k = j; k > 0; k--) { t = gcoeff(C,k,c); if (gequal0(t)) continue; setlg(C[c], k+1); ZC_elem(t, gcoeff(C,k,k), C, U, c, k); if (lgefint(gcoeff(C,k,k)) > lb) gel(C,k) = FpC_red(gel(C,k), b); if (j > 4) { GEN u = gel(U,k); long h; for (h=1; h lb) gel(u,h) = remii(gel(u,h), b); } } if (j == 1) t = gcoeff(C,1,1); else { GEN u; t = bezout(gcoeff(C,1,1), b, &u, NULL); /* >= 0 */ if (signe(u) && !equali1(u)) gel(U,1) = ZC_Z_mul(gel(U,1), u); gcoeff(C,1,1) = t; } if (equali1(t)) break; } if (j >= l) return NULL; return gerepileupto(av, ZM_ZC_mul(A,gel(U,1))); } /* remove the first r columns */ static void remove_0cols(long r, GEN *pA, GEN *pB, long remove) { GEN A = *pA, B = *pB; long l = lg(A); A += r; A[0] = evaltyp(t_MAT) | evallg(l-r); if (B && remove == 2) { B += r; B[0] = A[0]; } *pA = A; *pB = B; } /* Inefficient compared to hnfall. 'remove' = throw away lin.dep columns */ static GEN hnf_i(GEN A, int remove) { pari_sp av0 = avma, av, lim; 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); A = RgM_shallowcopy(A); def = n; ldef = (m>n)? m-n: 0; for (li=m; li>ldef; li--) { for (j=def-1; j; j--) { GEN a = gcoeff(A,li,j); if (!signe(a)) continue; /* 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 (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnf[1]. li=%ld",li); A = gerepilecopy(av, A); } } s = signe(gcoeff(A,li,def)); if (s) { if (s < 0) ZV_neg_inplace(gel(A,def)); ZM_reduce(A, NULL, li,def); def--; } else if (ldef) ldef--; if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnf[2]. li=%ld",li); A = gerepilecopy(av, A); } } /* rank A = n - def */ if (remove) { GEN B = NULL; remove_0cols(def, &A, &B, remove); } return gerepileupto(av0, ZM_copy(A)); } GEN ZM_hnf(GEN x) { return lg(x) > 8? ZM_hnfall(x, NULL, 1): hnf_i(x, 1); } /* u*z[1..k] mod p, in place */ static void FpV_Fp_mul_part_ip(GEN z, GEN u, GEN p, long k) { long i; if (is_pm1(u)) { if (signe(u) > 0) { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = modii(gel(z,i), p); } else { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = modii(negi(gel(z,i)), p); } } else { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = Fp_mul(u,gel(z,i), p); } } static void FpV_red_part_ipvec(GEN z, GEN p, long k) { long i; for (i = 1; i <= k; i++) gel(z,i) = modii(gel(z,i), gel(p,i)); } /* return x * U, in echelon form (mod p^m), where (det(U),p) = 1. * If early_abort is set, return NULL as soon as one pivot is 0 (mod p^m) */ GEN ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm) { pari_sp av0 = avma, av, lim; 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); x = RgM_shallowcopy(x); m = Z_pval(pm, p); ldef = (li > co)? li - co: 0; for (def = co-1,i = li-1; i > ldef; i--) { long vmin = LONG_MAX, kmin = 0; GEN umin = gen_0, pvmin, q; for (k = 1; k <= def; k++) { GEN u = gcoeff(x,i,k); long v; if (!signe(u)) continue; v = Z_pvalrem(u, p, &u); if (v >= m) gcoeff(x,i,k) = gen_0; else if (v < vmin) { vmin = v; kmin = k; umin = u; if (!vmin) break; } } if (!kmin) { if (early_abort) return NULL; gcoeff(x,i,def) = gen_0; ldef--; if (ldef < 0) ldef = 0; continue; } if (kmin != def) swap(gel(x,def), gel(x,kmin)); q = vmin? powiu(p, m-vmin): pm; /* pivot has valuation vmin */ umin = modii(umin, q); if (!equali1(umin)) FpV_Fp_mul_part_ip(gel(x,def), Fp_inv(umin,q), pm, i-1); gcoeff(x, i, def) = pvmin = powiu(p, vmin); for (j = def-1; j; j--) { /* zero x[i, 1..def-1] using x[i,def] = pvmin */ GEN t, a = gcoeff(x,i,j) = modii(gcoeff(x,i,j), pm); if (!signe(a)) continue; 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 (DEBUGMEM>1) pari_warn(warnmem,"ZpM_echelon. i=%ld",i); x = gerepilecopy(av, x); pvmin = gcoeff(x,i,def); } } def--; } if (co > li) { x += co - li; x[0] = evaltyp(t_MAT) | evallg(li); } return gerepilecopy(av0, x); } GEN zlm_echelon(GEN x, long early_abort, ulong p, ulong pm) { pari_sp av0 = avma; long li, co, i, j, k, def, ldef; ulong m; co = lg(x); if (co == 1) return cgetg(1,t_MAT); li = lgcols(x); x = Flm_copy(x); m = u_lval(pm, p); ldef = (li > co)? li - co: 0; for (def = co-1,i = li-1; i > ldef; i--) { long vmin = LONG_MAX, kmin = 0; ulong umin = 0, pvmin, q; for (k = 1; k <= def; k++) { ulong u = ucoeff(x,i,k); long v; if (!u) continue; v = u_lvalrem(u, p, &u); if (v >= (long) m) ucoeff(x,i,k) = 0; else if (v < vmin) { vmin = v; kmin = k; umin = u; if (!vmin) break; } } if (!kmin) { if (early_abort) return NULL; ucoeff(x,i,def) = 0; ldef--; if (ldef < 0) ldef = 0; continue; } if (kmin != def) swap(gel(x,def), gel(x,kmin)); q = vmin? upowuu(p, m-vmin): pm; /* pivot has valuation vmin */ umin %= q; if (umin != 1) Flc_Fl_mul_part_inplace(gel(x,def), Fl_inv(umin,q), pm, i-1); ucoeff(x, i, def) = pvmin = upowuu(p, vmin); for (j = def-1; j; j--) { /* zero x[i, 1..def-1] using x[i,def] = pvmin */ ulong t, a = ucoeff(x,i,j); if (!a) continue; t = Fl_neg(a / pvmin, q); Flc_lincomb1_inplace(gel(x,j), gel(x,def), t, pm); } def--; } if (co > li) { x += co - li; x[0] = evaltyp(t_MAT) | evallg(li); } return gerepilecopy(av0, x); } /* dm = multiple of diag element (usually detint(x)) * flag & hnf_MODID: reduce mod dm * matid [ otherwise as above ]. * flag & hnf_PART: don't reduce once diagonal is known; */ /* x a ZM, dm a t_INT */ GEN ZM_hnfmodall_i(GEN x, GEN dm, long flag) { pari_sp av, lim; const long center = (flag & hnf_CENTER); long moddiag = (flag & hnf_MODID); long li, co, i, j, k, def, ldef; GEN a, b, p1, p2, u, dm2, LDM; co = lg(x); if (co == 1) return cgetg(1,t_MAT); li = lgcols(x); if (li == 1) return cgetg(1,t_MAT); if (typ(dm) == t_INT) { long ldm = lgefint(dm); dm2 = shifti(dm, -1); dm = const_vec(li-1,dm); dm2= const_vec(li-1,dm2); LDM= const_vecsmall(li-1,ldm); } else { if (lg(dm) != li) pari_err_DIM("ZM_hnfmod"); moddiag = 1; dm2 = cgetg(li, t_VEC); LDM = cgetg(li, t_VECSMALL); for (i=1; i co) { ldef = li - co; if (!moddiag) pari_err_DOMAIN("ZM_hnfmod","nb lines",">", strtoGENstr("nb columns"), x); } for (def = co-1,i = li-1; i > ldef; i--,def--) { GEN d = gel(dm,i), d2 = gel(dm2,i); gcoeff(x,i,def) = centermodii(gcoeff(x,i,def), d,d2); for (j = def-1; j; j--) { gcoeff(x,i,j) = centermodii(gcoeff(x,i,j), d,d2); a = gcoeff(x,i,j); if (!signe(a)) continue; k = (j==1)? def: j-1; gcoeff(x,i,k) = centermodii(gcoeff(x,i,k), d,d2); ZC_elem(a,gcoeff(x,i,k), x,NULL, j,k); p1 = gel(x,j); p2 = gel(x,k); /* prevent coeffs explosion: reduce mod dm when lg() > ldm */ for (k = 1; k < i; k++) { if (lgefint(gel(p1,k)) > LDM[k]) gel(p1,k) = centermodii(gel(p1,k), gel(dm,k),gel(dm2,k)); 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 (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[1]. i=%ld",i); x = gerepilecopy(av, x); } } if (moddiag && !signe(gcoeff(x,i,def))) { /* missing pivot on line i, insert column */ GEN a = cgetg(co + 1, t_MAT); for (k = 1; k <= def; k++) gel(a,k) = gel(x,k); gel(a,k++) = Rg_col_ei(gel(dm,i), li-1, i); for ( ; k <= co; k++) gel(a,k) = gel(x,k-1); ldef--; if (ldef < 0) ldef = 0; co++; def++; x = a; } } if (co < li) { /* implies moddiag, add missing diag(dm) components */ GEN a = cgetg(li+1, t_MAT); for (k = 1; k <= li-co; k++) gel(a,k) = Rg_col_ei(gel(dm,k), li-1, k); for (i = 1; i < co; i++) gel(a,k-1+i) = gel(x,i); gel(a,li) = zerocol(li-1); x = a; } else { x += co - li; x[0] = evaltyp(t_MAT) | evallg(li); /* kill 0 columns */ } if (moddiag) { /* one column extra: an accumulator, discarded at the end */ if (lg(x) == li) x = shallowconcat(x, zerocol(li-1)); /* add up missing diag(dm) components */ for (i = li-1; i > 0; i--) { gcoeff(x, i, li) = gel(dm,i); for (j = i; j > 0; j--) { GEN a = gcoeff(x, j, li); if (!signe(a)) continue; 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 (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[2]. i=%ld", i); x = gerepilecopy(av, x); } } } } else { b = gel(dm,1); for (i = li-1; i > 0; i--) { GEN d = bezout(gcoeff(x,i,i),b, &u,NULL); gcoeff(x,i,i) = d; FpV_Fp_mul_part_ip(gel(x,i), u, b, i-1); if (i > 1) b = diviiexact(b,d); } } x[0] = evaltyp(t_MAT) | evallg(li); /* kill 0 columns / discard accumulator */ if (flag & hnf_PART) return x; if (!moddiag) { /* compute optimal value for dm */ b = cgetg(li, t_VEC); gel(b,1) = gcoeff(x,1,1); for (i = 2; i < li; i++) gel(b,i) = mulii(gel(b,i-1), gcoeff(x,i,i)); dm = b; } for (i = li-1; i > 0; i--) { GEN diag = gcoeff(x,i,i); if (signe(diag) < 0) { gel(x,i) = ZC_neg(gel(x,i)); diag = gcoeff(x,i,i); } for (j = i+1; j < li; j++) { b = gcoeff(x,i,j); b = center? diviiround(b,diag): truedivii(b, diag); if (!signe(b)) continue; togglesign(b); ZC_lincomb1_inplace(gel(x,j), gel(x,i),b); p1 = gel(x,j); for (k=1; k LDM[k]) gel(p1,k) = remii(gel(p1,k), gel(dm,i)); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[3]. i=%ld", i); gerepileall(av, 2, &x, &dm); diag = gcoeff(x,i,i); } } } return x; } GEN ZM_hnfmodall(GEN x, GEN dm, long flag) { pari_sp av = avma; return gerepilecopy(av, ZM_hnfmodall_i(x, dm, flag)); } GEN ZM_hnfmod(GEN x, GEN d) { return ZM_hnfmodall(x,d,0); } GEN ZM_hnfmodid(GEN x, GEN d) { return ZM_hnfmodall(x,d,hnf_MODID); } static GEN allhnfmod(GEN x, GEN dm, int flag) { if (typ(x)!=t_MAT) pari_err_TYPE("allhnfmod",x); RgM_check_ZM(x, "allhnfmod"); if (isintzero(dm)) return ZM_hnf(x); return ZM_hnfmodall(x, dm, flag); } GEN hnfmod(GEN x, GEN d) { if (typ(d) != t_INT) pari_err_TYPE("mathnfmod",d); return allhnfmod(x, d, 0); } GEN hnfmodid(GEN x, GEN d) { switch(typ(d)) { case t_INT: break; case t_VEC: case t_COL: if (RgV_is_ZV(d)) break; default: pari_err_TYPE("mathnfmodid",d); } return allhnfmod(x, d, hnf_MODID); } /* M a ZM in HNF. Normalize with *centered* residues */ GEN ZM_hnfcenter(GEN M) { long i, j, k, N = lg(M)-1; pari_sp av = avma, lim = stack_lim(av,1); for (j=N-1; j>0; j--) /* skip last line */ { GEN Mj = gel(M,j), a = gel(Mj,j); for (k = j+1; k <= N; k++) { GEN Mk = gel(M,k), q = diviiround(gel(Mk,j), a); long s = signe(q); if (!s) continue; if (is_pm1(q)) { if (s < 0) for (i = 1; i <= j; i++) gel(Mk,i) = addii(gel(Mk,i), gel(Mj,i)); else for (i = 1; i <= j; i++) gel(Mk,i) = subii(gel(Mk,i), gel(Mj,i)); } 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 (DEBUGMEM) pari_warn(warnmem,"ZM_hnfcenter, j = %ld",j); M = gerepilecopy(av, M); } } } return M; } /***********************************************************************/ /* */ /* HNFLLL (Havas, Majewski, Mathews) */ /* */ /***********************************************************************/ static void Minus(long j, GEN lambda) { long k, n = lg(lambda); for (k=1 ; k 0) q = diviiround(gcoeff(lambda,j,k), gel(D,j)); else return; if (signe(q)) { GEN Lk = gel(lambda,k), Lj = gel(lambda,j); togglesign_safe(&q); if (*row0) ZC_lincomb1_inplace(gel(A,k),gel(A,j),q); if (B) ZC_lincomb1_inplace(gel(B,k),gel(B,j),q); gel(Lk,j) = addii(gel(Lk,j), mulii(q,gel(D,j))); if (is_pm1(q)) { if (signe(q) > 0) { for (i=1; i>1 : if h = 2i even, no need to swap c[i] and itself */ for (i=(h-1)>>1; i; i--) swap(gel(c,i), gel(c,h-i)); } return A; } GEN ZM_hnflll(GEN A, GEN *ptB, int remove) { pari_sp av = avma, lim = stack_lim(av,3); #ifdef HNFLLL_QUALITY const long m1 = 1, n1 = 1; /* alpha = m1/n1. Maybe 3/4 here ? */ #endif long n, k, kmax; GEN B, lambda, D; n = lg(A); A = reverse_rows(ZM_copy(A)); /* ZM_copy for in place findi_normalize() */ B = ptB? matid(n-1): NULL; D = const_vec(n, gen_1) + 1; lambda = zeromatcopy(n-1,n-1); k = kmax = 2; while (k < n) { long row0, row1; int do_swap; reduce2(A,B,k,k-1,&row0,&row1,lambda,D); if (row0) do_swap = (!row1 || row0 <= row1); else if (!row1) { /* row0 == row1 == 0 */ pari_sp av1 = avma; GEN z = addii(mulii(gel(D,k-2),gel(D,k)), sqri(gcoeff(lambda,k-1,k))); #ifdef HNFLLL_QUALITY do_swap = (cmpii(mului(n1,z), mului(m1,sqri(gel(D,k-1)))) < 0); #else /* assume m1 = n1 = 1 */ do_swap = (cmpii(z, sqri(gel(D,k-1))) < 0); #endif avma = av1; } else do_swap = 0; if (do_swap) { hnfswap(A,B,k,lambda,D); if (k > 2) k--; } else { long i; for (i=k-2; i; i--) { long row0, row1; reduce2(A,B,k,i,&row0,&row1,lambda,D); if (low_stack(lim, stack_lim(av,3))) { GEN b = D-1; if (DEBUGMEM) pari_warn(warnmem,"hnflll (reducing), kmax = %ld",kmax); gerepileall(av, B? 4: 3, &A, &lambda, &b, &B); D = b+1; } } if (++k > kmax) kmax = k; } if (low_stack(lim, stack_lim(av,3))) { GEN b = D-1; if (DEBUGMEM) pari_warn(warnmem,"hnflll, kmax = %ld / %ld",kmax,n-1); gerepileall(av, B? 4: 3, &A, &lambda, &b, &B); D = b+1; } } /* handle trivial case: return negative diag coefficient otherwise */ if (n == 2) (void)findi_normalize(gel(A,1), B,1,lambda); A = reverse_rows(A); if (remove) { long i; for (i = 1; i < n; i++) if (!ZV_equal0(gel(A,i))) break; remove_0cols(i-1, &A, &B, remove); } gerepileall(av, B? 2: 1, &A, &B); if (B) *ptB = B; return A; } GEN hnflll(GEN x) { GEN z = cgetg(3, t_VEC); gel(z,1) = ZM_hnflll(x, &gel(z,2), 1); return z; } /* Variation on HNFLLL: Extended GCD */ static void reduce1(GEN A, GEN B, long k, long j, GEN lambda, GEN D) { GEN q; long i; if (signe(gel(A,j))) q = diviiround(gel(A,k),gel(A,j)); else if (absi_cmp(shifti(gcoeff(lambda,j,k), 1), gel(D,j)) > 0) q = diviiround(gcoeff(lambda,j,k), gel(D,j)); else return; if (signe(q)) { GEN Lk = gel(lambda,k), Lj = gel(lambda,j); togglesign_safe(&q); gel(A,k) = addii(gel(A,k), mulii(q,gel(A,j))); ZC_lincomb1_inplace(gel(B,k),gel(B,j),q); gel(Lk,j) = addii(gel(Lk,j), mulii(q,gel(D,j))); for (i=1; i 2) k--; } else { long i; for (i=k-2; i; i--) reduce1(A,B,k,i,lambda,D); k++; } } if (signe(gel(A,n-1)) < 0) { gel(A,n-1) = negi(gel(A,n-1)); ZV_togglesign(gel(B,n-1)); } return mkvec2(gel(A,n-1), B); } GEN ZV_gcdext(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 */ static GEN ZV_hnfgcdext(GEN A) { pari_sp av = avma; GEN z; if (lg(A) == 1) retmkvec2(cgetg(1,t_MAT),cgetg(1,t_MAT)); z = ZV_gcdext_i(A); gel(z,1) = mkmat(mkcol(gel(z,1))); return gerepilecopy(av, z); } /* HNF with permutation. */ GEN ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm) { GEN U, c, l, perm, d, p, q, b; pari_sp av = avma, av1, lim; long r, t, i, j, j1, k, m, n; n = lg(A)-1; if (!n) { if (ptU) *ptU = cgetg(1,t_MAT); if (ptperm) *ptperm = cgetg(1,t_VEC); return cgetg(1, t_MAT); } m = nbrows(A); c = zero_zv(m); l = zero_zv(n); perm = cgetg(m+1, t_VECSMALL); av1 = avma; lim = stack_lim(av1,1); A = RgM_shallowcopy(A); U = ptU? matid(n): NULL; /* U base change matrix : A0*U = A all along */ for (r=0, k=1; k <= n; k++) { for (j=1; j 0) { p = q; t = i; } } perm[++r] = l[k] = t; c[t] = k; if (signe(p) < 0) { ZV_neg_inplace(gel(A,k)); if (U) ZV_togglesign(gel(U,k)); p = gcoeff(A,t,k); } /* p > 0 */ for (j=1; j1) pari_warn(warnmem,"hnfperm"); gerepileall(av1, U? 2: 1, &A, &U); } } if (r < m) { for (i=1,k=r; i<=m; i++) if (!c[i]) perm[++k] = i; } /* We have A0*U=A, U in Gl(n,Z) * basis for Im(A): columns of A s.t l[j]>0 (r cols) * basis for Ker(A): columns of U s.t l[j]=0 (n-r cols) */ p = cgetg(r+1,t_MAT); for (i=1; i<=m/2; i++) lswap(perm[i], perm[m+1-i]); if (U) { GEN u = cgetg(n+1,t_MAT); for (t=1,k=r,j=1; j<=n; j++) if (l[j]) { u[k + n-r] = U[j]; gel(p,k--) = vecpermute(gel(A,j), perm); } else u[t++] = U[j]; *ptU = u; if (ptperm) *ptperm = perm; gerepileall(av, ptperm? 3: 2, &p, ptU, ptperm); } else { for (k=r,j=1; j<=n; j++) if (l[j]) gel(p,k--) = vecpermute(gel(A,j), perm); if (ptperm) *ptperm = perm; gerepileall(av, ptperm? 2: 1, &p, ptperm); } return p; } GEN hnfperm(GEN A) { GEN y = cgetg(4, t_VEC); gel(y,1) = ZM_hnfperm(A, &gel(y,2), &gel(y,3)); return y; } /* Hermite Normal Form, with base change matrix if ptB != NULL. * If 'remove' = 1, remove 0 columns (do NOT update *ptB accordingly) * If 'remove' = 2, remove 0 columns and update *ptB accordingly */ GEN ZM_hnfall(GEN A, GEN *ptB, long remove) { pari_sp av = avma, av1, lim; long m, n, r, i, j, k, li; GEN B, c, h, a; RgM_dimensions(A, &m,&n); if (!n) { if (ptB) *ptB = cgetg(1,t_MAT); return cgetg(1,t_MAT); } c = zero_zv(m); h = const_vecsmall(n, m); av1 = avma; lim = stack_lim(av1,1); A = RgM_shallowcopy(A); B = ptB? matid(n): NULL; r = n+1; for (li=m; li; li--) { for (j=1; jli; i--) { a = gcoeff(A,i,j); k = c[i]; /* 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 (DEBUGMEM>1) pari_warn(warnmem,"hnfall[1], li = %ld", li); gerepileall(av1, B? 2: 1, &A, &B); } } if (signe( gcoeff(A,li,j) )) break; h[j] = li-1; } if (j == r) continue; r--; if (j < r) /* A[j] != 0 */ { swap(gel(A,j), gel(A,r)); if (B) swap(gel(B,j), gel(B,r)); h[j] = h[r]; h[r] = li; c[li] = r; } if (signe(gcoeff(A,li,r)) < 0) { ZV_neg_inplace(gel(A,r)); if (B) ZV_togglesign(gel(B,r)); } ZM_reduce(A,B, li,r); if (low_stack(lim, stack_lim(av1,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"hnfall[2], li = %ld", li); gerepileall(av1, B? 2: 1, &A, &B); } } if (DEBUGLEVEL>5) err_printf("\nhnfall, final phase: "); r--; /* first r cols are in the image the n-r (independent) last ones */ for (j=1; j<=r; j++) for (i=h[j]; i; i--) { a = gcoeff(A,i,j); 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 (DEBUGMEM>1) pari_warn(warnmem,"hnfall[3], j = %ld", j); gerepileall(av1, B? 2: 1, &A, &B); } } if (DEBUGLEVEL>5) err_printf("\n"); if (remove) remove_0cols(r, &A, &B, remove); gerepileall(av, B? 2: 1, &A, &B); if (B) *ptB = B; return A; } GEN hnfall(GEN x) { GEN z = cgetg(3, t_VEC); gel(z,1) = ZM_hnfall(x, (GEN*)(z+2), 1); return z; } GEN hnf(GEN x) { return mathnf0(x,0); } /* C = A^(-1)(tB) where A, B, C are integral, A is upper triangular, t t_INT */ GEN hnf_divscale(GEN A, GEN B, GEN t) { long n = lg(A)-1, i,j,k; GEN m, c = cgetg(n+1,t_MAT); if (!n) return c; for (k=1; k<=n; k++) { GEN u = cgetg(n+1, t_COL), b = gel(B,k); pari_sp av = avma; gel(c,k) = u; m = mulii(gel(b,n),t); gel(u,n) = gerepileuptoint(av, diviiexact(m, gcoeff(A,n,n))); for (i=n-1; i>0; i--) { av = avma; m = mulii(gel(b,i),t); for (j=i+1; j<=n; j++) m = subii(m, mulii(gcoeff(A,i,j),gel(u,j))); gel(u,i) = gerepileuptoint(av, diviiexact(m, gcoeff(A,i,i))); } } return c; } /* A, B integral upper HNF. A^(-1) B integral ? */ int hnfdivide(GEN A, GEN B) { pari_sp av = avma; long n = lg(A)-1, i,j,k; GEN u, b, m, r; if (!n) return 1; if (lg(B)-1 != n) pari_err_DIM("hnfdivide"); u = cgetg(n+1, t_COL); for (k=1; k<=n; k++) { b = gel(B,k); m = gel(b,k); gel(u,k) = dvmdii(m, gcoeff(A,k,k), &r); if (r != gen_0) { avma = av; return 0; } for (i=k-1; i>0; i--) { m = gel(b,i); for (j=i+1; j<=k; j++) m = subii(m, mulii(gcoeff(A,i,j),gel(u,j))); m = dvmdii(m, gcoeff(A,i,i), &r); if (r != gen_0) { avma = av; return 0; } gel(u,i) = m; } } avma = av; return 1; } /* A upper HNF, b integral vector. Return A^(-1) b if integral, * NULL otherwise. Assume #A[,1] = #b. */ GEN hnf_invimage(GEN A, GEN b) { pari_sp av = avma; long n = lg(A)-1, m, i, k; GEN u, r; if (!n) return NULL; m = nbrows(A); /* m >= n */ u = cgetg(n+1, t_COL); for (i = n, k = m; k > 0; k--) { pari_sp av2 = avma; long j; GEN t = gel(b,k), Aki = gcoeff(A,k,i); if (typ(t) != t_INT) pari_err_TYPE("hnf_invimage",t); for (j=i+1; j<=n; j++) t = subii(t, mulii(gcoeff(A,k,j),gel(u,j))); if (!signe(Aki)) { if (signe(t)) { avma = av;return NULL; } avma = av2; gel(u,i) = gen_0; continue; } t = dvmdii(t, Aki, &r); if (r != gen_0) { avma = av; return NULL; } gel(u,i) = gerepileuptoint(av2, t); if (--i == 0) break; } /* If there is a solution, it must be u. Check remaining equations */ for (; k > 0; k--) { pari_sp av2 = avma; long j; GEN t = gel(b,k); if (typ(t) != t_INT) pari_err_TYPE("hnf_invimage",t); for (j=1; j<=n; j++) t = subii(t, mulii(gcoeff(A,k,j),gel(u,j))); if (signe(t)) { avma = av;return NULL; } avma = av2; } return u; } /* A upper HNF, B integral matrix or column. Return A^(-1) B if integral, * NULL otherwise */ GEN hnf_solve(GEN A, GEN B) { pari_sp av; long i, l; GEN C; if (typ(B) == t_COL) return hnf_invimage(A, B); av = avma; C = cgetg_copy(B, &l); for (i = 1; i < l; i++) { GEN c = hnf_invimage(A, gel(B,i)); if (!c) { avma = av; return NULL; } gel(C,i) = c; } return C; } /***************************************************************/ /** **/ /** SMITH NORMAL FORM REDUCTION **/ /** **/ /***************************************************************/ static GEN trivsmith(long all) { GEN z; if (!all) return cgetg(1,t_VEC); z=cgetg(4,t_VEC); gel(z,1) = cgetg(1,t_MAT); gel(z,2) = cgetg(1,t_MAT); gel(z,3) = cgetg(1,t_MAT); return z; } static void snf_pile(pari_sp av, GEN *x, GEN *U, GEN *V) { GEN *gptr[3]; int c = 1; gptr[0]=x; if (*U) gptr[c++] = U; if (*V) gptr[c++] = V; gerepilemany(av,gptr,c); } static GEN bezout_step(GEN *pa, GEN *pb, GEN *pu, GEN *pv) { GEN a = *pa, b = *pb, d; if (absi_equal(a,b)) { long sa = signe(a), sb = signe(b); *pv = gen_0; if (sb == sa) { *pa = *pb = gen_1; if (sa > 0) {*pu=gen_1; return a;} else {*pu=gen_m1; return absi(a);} } if (sa > 0) { *pa = *pu = gen_1; *pb = gen_m1; return a; } *pa = *pu = gen_m1; *pb = gen_1; return b; } d = bezout(a,b, pu,pv); *pa = diviiexact(a, d); *pb = diviiexact(b, d); return d; } static int negcmpii(void *E, GEN x, GEN y) { (void)E; return -cmpii(x,y); } /* does b = x[i,i] divide all entries in x[1..i-1,1..i-1] ? If so, return 0; * else return the index of a problematic row */ static long ZM_snf_no_divide(GEN x, long i) { GEN b = gcoeff(x,i,i); long j, k; if (!signe(b)) { /* impossible in the current implementation : x square of maximal rank */ for (k = 1; k < i; k++) for (j = 1; j < i; j++) if (signe(gcoeff(x,k,j))) return k; return 0; } if (is_pm1(b)) return 0; for (k=1; k7) err_printf("starting SNF loop"); for (i=n; i>1; i--) { if (DEBUGLEVEL>7) err_printf("\ni = %ld: ",i); for(;;) { int c = 0; GEN a, b; for (j=i-1; j>=1; j--) { 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 (DEBUGMEM>1) pari_warn(warnmem,"[1]: ZM_snfall i = %ld", i); snf_pile(av, &x,&U,&V); } } if (DEBUGLEVEL>7) err_printf("; "); for (j=i-1; j>=1; j--) { GEN d; b = gcoeff(x,j,i); if (!signe(b)) continue; a = gcoeff(x,i,i); d = bezout_step(&a, &b, &u, &v); for (k = 1; k < i; k++) { GEN t = addii(mulii(u,gcoeff(x,i,k)),mulii(v,gcoeff(x,j,k))); gcoeff(x,j,k) = subii(mulii(a,gcoeff(x,j,k)), mulii(b,gcoeff(x,i,k))); gcoeff(x,i,k) = t; } 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 (DEBUGMEM>1) pari_warn(warnmem,"[2]: ZM_snfall, i = %ld", i); snf_pile(av, &x,&U,&V); } c = 1; } if (!c) { k = ZM_snf_no_divide(x, i); if (!k) break; /* x[k,j] != 0 mod b */ for (j=1; j<=i; j++) 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 (DEBUGMEM>1) pari_warn(warnmem,"[3]: ZM_snfall"); snf_pile(av, &x,&U,&V); } } } if (DEBUGLEVEL>7) err_printf("\n"); for (k=1; k<=n; k++) if (signe(gcoeff(x,k,k)) < 0) { if (V) ZV_togglesign(gel(V,k)); togglesign(gcoeff(x,k,k)); } THEEND: if (return_vec) { long l = lg(x)-1; if (typ(x) == t_MAT) x = RgM_diagonal_shallow(x); if (m0 > l) x = shallowconcat(zerovec(m0-l), x); } if (V0) { if (!return_vec) x = shallowconcat(zeromat(m,n0-n), x); if (V) V = shallowconcat(V0, V); } if (U) { U = shallowtrans(U); if (perm) U = vecpermute(U, perm_inv(perm)); } snf_pile(av0, &x,&U,&V); if (ptU) *ptU = U; if (ptV) *ptV = V; return x; } GEN ZM_snfall(GEN x, GEN *U, GEN *V) { return ZM_snfall_i(x, U, V, 0); } GEN ZM_snf(GEN x) { return ZM_snfall_i(x, NULL,NULL, 1); } GEN smith(GEN x) { if (typ(x)!=t_MAT) pari_err_TYPE("smith",x); RgM_check_ZM(x, "smith"); return ZM_snfall_i(x, NULL,NULL, 1); } GEN smithall(GEN x) { GEN z = cgetg(4, t_VEC); if (typ(x)!=t_MAT) pari_err_TYPE("smithall",x); RgM_check_ZM(x, "smithall"); gel(z,3) = ZM_snfall_i(x, (GEN*)(z+1),(GEN*)(z+2), 0); return z; } void ZM_snfclean(GEN d, GEN u, GEN v) { long i, c, l = lg(d); if (typ(d) == t_VEC) for (c=1; c l) { /* D = vconcat(zero matrix, diagonal matrix) */ for (c=1+h-l, d=1; c 1) { if (h > l) { for (i=1+h-l, j=1; i 16 + gexpo(b) - prec2nbits(gprecision(r))) ) return k; } return 0; } /* Hermite Normal Form, with base change matrix if ptB != NULL. * If 'remove' = 1, remove 0 columns (do NOT update *ptB accordingly) * If 'remove' = 2, remove 0 columns and update *ptB accordingly */ GEN RgM_hnfall(GEN A, GEN *pB, long remove) { pari_sp av, lim; long li, j, k, m, n, def, ldef; GEN B; long vx = gvar(A); n = lg(A)-1; if (vx==NO_VARIABLE || !n) { RgM_check_ZM(A, "mathnf0"); return ZM_hnfall(A, pB, remove); } m = nbrows(A); av = avma; lim = stack_lim(av,1); A = RgM_shallowcopy(A); B = pB? matid(n): NULL; def = n; ldef = (m>n)? m-n: 0; for (li=m; li>ldef; li--) { GEN T; for (j=def-1; j; j--) { GEN a = gcoeff(A,li,j); if (gequal0(a)) continue; k = (j==1)? def: j-1; RgC_elem(a,gcoeff(A,li,k), A,B, j,k, li, vx); } T = gcoeff(A,li,def); if (gequal0(T)) { if (ldef) ldef--; } else { GEN d; gcoeff(A,li,def) = RgX_normalize(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 (DEBUGMEM>1) pari_warn(warnmem,"ghnfall"); gerepileall(av, B? 2: 1, &A, &B); } } /* rank A = n - def */ if (remove) remove_0cols(def, &A, &B, remove); gerepileall(av, B? 2: 1, &A, &B); if (B) *pB = B; return A; } static GEN gsmithall_i(GEN x,long all) { pari_sp av, lim; long i, j, k, n; GEN z, u, v, U, V; long vx = gvar(x); if (typ(x)!=t_MAT) pari_err_TYPE("gsmithall",x); if (vx==NO_VARIABLE) return all? smithall(x): smith(x); 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); x = RgM_shallowcopy(x); if (all) { U = matid(n); V = matid(n); } for (i=n; i>=2; i--) { for(;;) { GEN a, b, d; int c = 0; for (j=i-1; j>=1; j--) { b = gcoeff(x,i,j); if (gequal0(b)) continue; a = gcoeff(x,i,i); d = gbezout_step(&b, &a, &v, &u, vx); for (k = 1; k < i; k++) { GEN t = gadd(gmul(u,gcoeff(x,k,i)),gmul(v,gcoeff(x,k,j))); gcoeff(x,k,j) = gsub(gmul(a,gcoeff(x,k,j)),gmul(b,gcoeff(x,k,i))); gcoeff(x,k,i) = t; } gcoeff(x,i,j) = gen_0; gcoeff(x,i,i) = d; if (all) update(u,v,a,b,(GEN*)(V+i),(GEN*)(V+j)); } for (j=i-1; j>=1; j--) { b = gcoeff(x,j,i); if (gequal0(b)) continue; a = gcoeff(x,i,i); d = gbezout_step(&b, &a, &v, &u, vx); for (k = 1; k < i; k++) { GEN t = gadd(gmul(u,gcoeff(x,i,k)),gmul(v,gcoeff(x,j,k))); gcoeff(x,j,k) = gsub(gmul(a,gcoeff(x,j,k)),gmul(b,gcoeff(x,i,k))); gcoeff(x,i,k) = t; } gcoeff(x,j,i) = gen_0; gcoeff(x,i,i) = d; if (all) update(u,v,a,b,(GEN*)(U+i),(GEN*)(U+j)); c = 1; } if (!c) { k = gsnf_no_divide(x, i, vx); if (!k) break; for (j=1; j<=i; j++) 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 (DEBUGMEM>1) pari_warn(warnmem,"gsmithall"); gerepileall(av, all? 3: 1, &x, &U, &V); } } } for (k=1; k<=n; k++) { 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 (all && !gequal1(d)) gel(V,k) = RgC_Rg_div(gel(V,k), d); gcoeff(x,k,k) = T; } z = all? mkvec3(shallowtrans(U), V, x): RgM_diagonal_shallow(x); return gerepilecopy(av, z); } GEN matsnf0(GEN x,long flag) { pari_sp av = avma; if (flag > 7) pari_err_FLAG("matsnf"); if (typ(x) == t_VEC && flag & 4) return smithclean(x); if (flag & 2) x = flag&1 ? gsmithall(x): gsmith(x); else x = flag&1 ? smithall(x): smith(x); if (flag & 4) x = gerepileupto(av, smithclean(x)); return x; } GEN gsmith(GEN x) { return gsmithall_i(x,0); } GEN gsmithall(GEN x) { return gsmithall_i(x,1); } /* H relation matrix among row of generators g in HNF. Let URV = D its SNF, * newU R newV = newD its clean SNF (no 1 in Dnew). Return the diagonal of * newD, newU and newUi such that 1/U = (newUi, ?). * Rationale: let (G,0) = g Ui be the new generators then * 0 = G U R --> G D = 0, g = G newU and G = g newUi */ GEN ZM_snf_group(GEN H, GEN *newU, GEN *newUi) { GEN D = ZM_snfall_i(H, newU, newUi, 1); long i, j, l; ZM_snfclean(D, newU? *newU: NULL, newUi? *newUi: NULL); l = lg(D); if (newU) { GEN U = *newU; for (i = 1; i < l; i++) { GEN d = gel(D,i), d2 = shifti(d, 1); for (j = 1; j < lg(U); j++) gcoeff(U,i,j) = centermodii(gcoeff(U,i,j), d, d2); } *newU = U; } if (newUi) { /* UHV=D -> U^-1 = HVD^-1 -> U^-1 = H(VD^-1 mod 1) mod H */ if (l > 1) { /* Ui = ZM_inv(U, gen_1); setlg(Ui, l); */ GEN V = FpM_red(*newUi, gel(D,1)); GEN Ui = ZM_mul(H, V); for (i = 1; i < l; i++) gel(Ui,i) = ZC_Z_divexact(gel(Ui,i), gel(D,i)); *newUi = ZM_hnfrem(Ui, H); } } 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 n) pari_err_PREC("matfrobenius"); for (j=0; j n) pari_err_PREC("matfrobenius"); gcoeff(M,k,i) = gen_1; for (j=1; j2) 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)); } pari-2.7.5/src/basemath/ZX.c0000644000175000017500000004463512405547147014213 0ustar billbill/* Copyright (C) 2007 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" /*******************************************************************/ /* */ /* ZX */ /* */ /*******************************************************************/ void RgX_check_QX(GEN x, const char *s) { if (!RgX_is_QX(x)) pari_err_TYPE(stack_strcat(s," [not in Q[X]]"), x); } void RgX_check_ZX(GEN x, const char *s) { if (!RgX_is_ZX(x)) pari_err_TYPE(stack_strcat(s," [not in Z[X]]"), x); } long ZX_max_lg(GEN x) { long i, prec = 0, lx = lg(x); for (i=2; i prec) prec = l; } return prec; } GEN ZX_add(GEN x, GEN y) { long lx,ly,i; GEN z; lx = lg(x); ly = lg(y); if (lx < ly) swapspec(x,y, lx,ly); z = cgetg(lx,t_POL); z[1] = x[1]; for (i=2; i= ly) { z = cgetg(lx,t_POL); z[1] = x[1]; for (i=2; i=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); } } Q[1] = P[1]; return Q; } /* Return h^(deg(P)-1) P(x / h), P!=0, h=lt(P), memory unclean; monic result */ GEN ZX_rescale_lt(GEN P) { long l = lg(P); GEN Q = cgetg(l,t_POL); gel(Q,l-1) = gen_1; if (l != 3) { long i = l-1; GEN h = gel(P,i), hi = h; i--; gel(Q,i) = gel(P,i); if (l != 4) { i--; gel(Q,i) = mulii(gel(P,i), h); } for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); } } Q[1] = P[1]; return Q; } /*Eval x in 2^(k*BIL) in linear time*/ static GEN ZX_eval2BILspec(GEN x, long k, long nx) { long i,j, lz = k*nx, ki; GEN pz = cgetipos(2+lz); GEN nz = cgetipos(2+lz); for(i=0; i < lz; i++) { *int_W(pz,i) = 0UL; *int_W(nz,i) = 0UL; } for(i=0, ki=0; i 0) for (j=0; j m) m = e; } return m; } static GEN Z_mod2BIL_ZX(GEN x, long bs, long d, long vx) { long i, offset, lm = lgefint(x)-2, l = d+vx+3, sx = signe(x); GEN s1 = int2n(bs*BITS_IN_LONG), pol = cgetg(l, t_POL); int carry = 0; for (i=0; i>1; for (j=a; j>1); if (signe(t)) s = addii(s, sqri(t)); } return gerepileuptoint(av,s); } static GEN ZX_sqrspec_basecase(GEN x, long nx, long v) { long i, lz, nz; GEN z; lz = (nx << 1) + 1; nz = lz-2; lz += v; z = cgetg(lz,t_POL); z[1] = evalsigne(1); z += 2; for (i=0; i=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); gel(z,i-dy) = avma == av? icopy(p1): gerepileuptoint(av, p1); } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); if (signe(p1)) { sx = 1; break; } if (!i) break; avma=av; } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; p1 = gerepileuptoint((pari_sp)rem, p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); gel(rem,i) = avma == av? icopy(p1): gerepileuptoint(av, p1); } rem -= 2; if (!sx) (void)ZX_renormalize(rem, lr); return gerepileupto(av0,rem); } /* return x(1) */ GEN ZX_eval1(GEN x) { pari_sp av = avma; long i = lg(x)-1; GEN s; if (i < 2) return gen_0; s = gel(x,i); i--; if (i == 1) return icopy(s); for ( ; i>=2; i--) { GEN c = gel(x,i); if (signe(c)) s = addii(s, c); } return gerepileuptoint(av,s); } /* reduce T mod X^n - 1. Shallow function */ GEN ZX_mod_Xnm1(GEN T, ulong n) { long i, j, L = lg(T), l = n+2; GEN S; if (L <= l) return T; S = cgetg(l, t_POL); S[1] = T[1]; for (i = 2; i < l; i++) gel(S,i) = gel(T,i); for (j = 2; i < L; i++) { gel(S,j) = addii(gel(S,j), gel(T,i)); if (++j == l) j = 2; } return normalizepol_lg(S, l); } /*******************************************************************/ /* */ /* ZXV */ /* */ /*******************************************************************/ int ZXV_equal(GEN V, GEN W) { long l = lg(V); if (l!=lg(W)) return 0; while (--l > 0) if (!ZX_equal(gel(V,l), gel(W,l))) return 0; return 1; } GEN ZXV_Z_mul(GEN y, GEN x) { long i, l; GEN z = cgetg_copy(y, &l); for(i=1; i1; k--) { GEN t = gel(x,k); switch(typ(t)) { case t_INT: break; case t_POL: if (RgX_is_ZX(t)) break; /* fall through */ default: pari_err_TYPE(stack_strcat(s, " not in Z[X,Y]"),x); } } } /*Renormalize (in place) polynomial with t_INT or ZX coefficients.*/ GEN ZXX_renormalize(GEN x, long lx) { long i; for (i = lx-1; i>1; i--) if (signe(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + (i+1))); setlg(x, i+1); setsigne(x, i!=1); return x; } long ZXX_max_lg(GEN x) { long i, prec = 0, lx = lg(x); for (i=2; i prec) prec = l; } return prec; } GEN ZXX_Z_divexact(GEN y, GEN x) { long i, l = lg(y); GEN z = cgetg(l,t_POL); z[1] = y[1]; for(i=2; i ZX: * P(X,Y) = sum_{0<=i= n) pari_err_BUG("ZXX_to_Kronecker, P is not reduced mod Q"); for (j=2; j < l; j++) gel(y,k++) = gel(c,j); } if (i == lP-1) break; for ( ; j < N; j++) gel(y,k++) = gen_0; } y-=2; setlg(y, k+2); y[1] = evalsigne(1); return y; } GEN ZXX_to_Kronecker(GEN P, long n) { GEN z = ZXX_to_Kronecker_spec(P+2, lgpol(P), n); setvarn(z,varn(P)); return z; } pari-2.7.5/src/basemath/Hensel.c0000644000175000017500000005470112405547147015063 0ustar billbill/* 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" /***********************************************************************/ /** **/ /** QUADRATIC HENSEL LIFT (adapted from V. Shoup's NTL) **/ /** **/ /***********************************************************************/ /* Setup for divide/conquer quadratic Hensel lift * a = set of k t_POL in Z[X] = factors over Fp (T=NULL) or Fp[Y]/(T) * V = set of products of factors built as follows * 1) V[1..k] = initial a * 2) iterate: * append to V the two smallest factors (minimal degree) in a, remove them * from a and replace them by their product [net loss for a = 1 factor] * * W = bezout coeffs W[i]V[i] + W[i+1]V[i+1] = 1 * * link[i] = -j if V[i] = a[j] * j if V[i] = V[j] * V[j+1] * Arrays (link, V, W) pre-allocated for 2k - 2 elements */ static void BuildTree(GEN link, GEN V, GEN W, GEN a, GEN T, GEN p) { long k = lg(a)-1; long i, j, s, minp, mind; for (i=1; i<=k; i++) { gel(V,i) = gel(a,i); link[i] = -i; } for (j=1; j <= 2*k-5; j+=2,i++) { minp = j; mind = degpol(gel(V,j)); for (s=j+1; s 0) pari_err_COPRIME("BuildTree", gel(V,j), gel(V,j+1)); d = gel(d,2); if (!gequal1(d)) { if (typ(d)==t_POL) { d = FpXQ_inv(d, T, p); u = FqX_Fq_mul(u, d, T, p); v = FqX_Fq_mul(v, d, T, p); } else { d = Fp_inv(d, p); u = FqX_Fp_mul(u, d, T,p); v = FqX_Fp_mul(v, d, T,p); } } gel(W,j) = u; gel(W,j+1) = v; } } /* au + bv = 1 (p0), ab = f (p0). Lift mod p1 = p0 pd (<= p0^2). * If noinv is set, don't lift the inverses u and v */ static void ZpX_HenselLift(GEN V, GEN W, long j, GEN f, GEN pd, GEN p0, GEN p1, int noinv) { pari_sp av = avma; long space = lg(f) * lgefint(p1); GEN a2, b2, g, z, s, t; GEN a = gel(V,j), b = gel(V,j+1); GEN u = gel(W,j), v = gel(W,j+1); (void)new_chunk(space); /* HACK */ g = ZX_sub(f, ZX_mul(a,b)); g = ZX_Z_divexact(g, p0); g = FpX_red(g, pd); z = FpX_mul(v,g, pd); t = FpX_divrem(z,a, pd, &s); t = ZX_add(ZX_mul(u,g), ZX_mul(t,b)); t = FpX_red(t, pd); t = ZX_Z_mul(t,p0); s = ZX_Z_mul(s,p0); avma = av; a2 = ZX_add(a,s); b2 = ZX_add(b,t); /* already reduced mod p1 = pd p0 */ gel(V,j) = a2; gel(V,j+1) = b2; if (noinv) return; av = avma; (void)new_chunk(space); /* HACK */ g = ZX_add(ZX_mul(u,a2), ZX_mul(v,b2)); g = Z_ZX_sub(gen_1, g); g = ZX_Z_divexact(g, p0); g = FpX_red(g, pd); z = FpX_mul(v,g, pd); t = FpX_divrem(z,a, pd, &s); t = ZX_add(ZX_mul(u,g), ZX_mul(t,b)); t = FpX_red(t, pd); t = ZX_Z_mul(t,p0); s = ZX_Z_mul(s,p0); avma = av; gel(W,j) = ZX_add(u,t); gel(W,j+1) = ZX_add(v,s); } static void ZpXQ_HenselLift(GEN V, GEN W, long j, GEN f, GEN Td, GEN T1, GEN pd, GEN p0, GEN p1, int noinv) { pari_sp av = avma; const long n = degpol(T1), vT = varn(T1); long space = lg(f) * lgefint(p1) * lg(T1); GEN a2, b2, g, z, s, t; GEN a = gel(V,j), b = gel(V,j+1); GEN u = gel(W,j), v = gel(W,j+1); (void)new_chunk(space); /* HACK */ g = RgX_sub(f, Kronecker_to_ZXX(ZXX_mul_Kronecker(a,b,n), n, vT)); g = FpXQX_red(g, T1, p1); g = RgX_Rg_divexact(g, p0); z = FpXQX_mul(v,g, Td,pd); t = FpXQX_divrem(z,a, Td,pd, &s); t = ZX_add(ZXX_mul_Kronecker(u,g,n), ZXX_mul_Kronecker(t,b,n)); t = Kronecker_to_ZXX(t, n, vT); t = FpXQX_red(t, Td, pd); t = RgX_Rg_mul(t,p0); s = RgX_Rg_mul(s,p0); avma = av; a2 = RgX_add(a,s); b2 = RgX_add(b,t); /* already reduced mod p1 = pd p0 */ gel(V,j) = a2; gel(V,j+1) = b2; if (noinv) return; av = avma; (void)new_chunk(space); /* HACK */ g = ZX_add(ZXX_mul_Kronecker(u,a2,n), ZXX_mul_Kronecker(v,b2,n)); g = Kronecker_to_ZXX(g, n, vT); g = Rg_RgX_sub(gen_1, g); g = FpXQX_red(g, T1, p1); g = RgX_Rg_divexact(g, p0); z = FpXQX_mul(v,g, Td,pd); t = FpXQX_divrem(z,a, Td,pd, &s); t = ZX_add(ZXX_mul_Kronecker(u,g,n), ZXX_mul_Kronecker(t,b,n)); t = Kronecker_to_ZXX(t, n, vT); t = FpXQX_red(t, Td, pd); t = RgX_Rg_mul(t,p0); s = RgX_Rg_mul(s,p0); avma = av; gel(W,j) = RgX_add(u,t); gel(W,j+1) = RgX_add(v,s); } /* v list of factors, w list of inverses. f = v[j] v[j+1] * Lift v[j] and v[j+1] mod p0 pd (possibly mod T), then all their divisors */ static void ZpX_RecTreeLift(GEN link, GEN v, GEN w, GEN pd, GEN p0, GEN p1, GEN f, long j, int noinv) { if (j < 0) return; ZpX_HenselLift(v, w, j, f, pd, p0,p1, noinv); ZpX_RecTreeLift(link, v, w, pd, p0,p1, gel(v,j) , link[j ], noinv); ZpX_RecTreeLift(link, v, w, pd, p0,p1, gel(v,j+1), link[j+1], noinv); } static void ZpXQ_RecTreeLift(GEN link, GEN v, GEN w, GEN Td, GEN T1, GEN pd, GEN p0, GEN p1, GEN f, long j, int noinv) { if (j < 0) return; ZpXQ_HenselLift(v, w, j, f, Td,T1, pd, p0,p1, noinv); ZpXQ_RecTreeLift(link, v, w, Td,T1, pd, p0,p1, gel(v,j) , link[j ], noinv); ZpXQ_RecTreeLift(link, v, w, Td,T1, pd, p0,p1, gel(v,j+1), link[j+1], noinv); } /* Assume n > 0. We want to go to accuracy n, starting from accuracy 1, using * a quadratically convergent algorithm. Goal: 9 -> 1,2,3,5,9 instead of * 1,2,4,8,9 (sequence of accuracies). * * Let a0 = 1, a1 = 2, a2, ... ak = n, the sequence of accuracies. To obtain * it, work backwards: * a(k) = n, a(i-1) = (a(i) + 1) \ 2, * but we do not want to store a(i) explicitly, even as a t_VECSMALL, since * this would leave an object on the stack. We store a(i) implicitly in a * MASK: let a(0) = 1, if the i-bit of MASK is set, set a(i+1) = 2 a(i) - 1, * and 2a(i) otherwise. * * In fact, we do something a little more complicated to simplify the * function interface and avoid returning k and MASK separately: we return * MASK + 2^(k+1), so the highest bit of the mask indicates the length of the * sequence, and the following ones are as above. */ ulong quadratic_prec_mask(long n) { long a = n, i; ulong mask = 0; for(i = 1;; i++, mask <<= 1) { mask |= (a&1); a = (a+1)>>1; if (a==1) return mask | (1UL << i); } } /* Lift to precision p^e0. * a = modular factors of f mod (p,T) [possibly T=NULL] * OR a TreeLift structure [e, link, v, w]: go on lifting * flag = 0: standard. * flag = 1: return TreeLift structure */ static GEN MultiLift(GEN f, GEN a, GEN T, GEN p, long e0, long flag) { long i, eold, e, k = lg(a) - 1; GEN E, v, w, link, penew, Tnew; ulong mask; pari_timer Ti; if (k < 2) pari_err_DOMAIN("MultiLift", "#(modular factors)", "<", gen_2,a); if (e0 < 1) pari_err_DOMAIN("MultiLift", "precision", "<", gen_1,stoi(e0)); if (e0 == 1) return a; if (DEBUGLEVEL > 3) timer_start(&Ti); if (typ(gel(a,1)) == t_INT) { /* a = TreeLift structure */ e = itos(gel(a,1)); link = gel(a,2); v = gel(a,3); w = gel(a,4); } else { e = 1; v = cgetg(2*k-2 + 1, t_VEC); w = cgetg(2*k-2 + 1, t_VEC); link=cgetg(2*k-2 + 1, t_VECSMALL); BuildTree(link, v, w, a, T? FpX_red(T,p): NULL, p); if (DEBUGLEVEL > 3) timer_printf(&Ti, "building tree"); } mask = quadratic_prec_mask(e0); eold = 1; penew = NULL; Tnew = NULL; while (mask > 1) { long enew = eold << 1; if (mask & 1) enew--; mask >>= 1; if (enew >= e) { /* mask == 1: last iteration */ GEN peold = penew? penew: powiu(p, eold); GEN Td = NULL, pd; long d = enew - eold; /* = eold or eold-1 */ /* lift from p^eold to p^enew */ pd = (d == eold)? peold: diviiexact(peold, p); /* p^d */ penew = mulii(peold,pd); if (T) { if (Tnew) Td = (d == eold)? Tnew: FpX_red(Tnew,pd); else Td = FpX_red(T, peold); Tnew = FpX_red(T, penew); ZpXQ_RecTreeLift(link, v, w, Td, Tnew, pd, peold, penew, f, lgpol(v), (flag == 0 && mask == 1)); } else ZpX_RecTreeLift(link, v, w, pd, peold, penew, f, lgpol(v), (flag == 0 && mask == 1)); if (DEBUGLEVEL > 3) timer_printf(&Ti, "lifting to prec %ld", enew); } eold = enew; } if (flag) E = mkvec4(utoipos(e0), link, v, w); else { E = cgetg(k+1, t_VEC); for (i = 1; i <= 2*k-2; i++) { long t = link[i]; if (t < 0) gel(E,-t) = gel(v,i); } } return E; } /* Q list of (coprime, monic) factors of pol mod (T,p). Lift mod p^e = pe. * T may be NULL */ GEN ZpX_liftfact(GEN pol, GEN Q, GEN T, GEN p, long e, GEN pe) { pari_sp av = avma; if (lg(Q) == 2) return mkvec(pol); pol = FqX_normalize(pol, T, pe); return gerepilecopy(av, MultiLift(pol, Q, T, p, e, 0)); } /* U = NULL treated as 1 */ static void BezoutPropagate(GEN link, GEN v, GEN w, GEN pe, GEN U, GEN f, long j) { GEN Q, R; if (j < 0) return; Q = FpX_mul(gel(v,j), gel(w,j), pe); if (U) { Q = FpXQ_mul(Q, U, f, pe); R = FpX_sub(U, Q, pe); } else R = Fp_FpX_sub(gen_1, Q, pe); gel(w,j+1) = Q; /* 0 mod U v[j], 1 mod (1-U) v[j+1] */ gel(w,j) = R; /* 1 mod U v[j], 0 mod (1-U) v[j+1] */ BezoutPropagate(link, v, w, pe, R, f, link[j ]); BezoutPropagate(link, v, w, pe, Q, f, link[j+1]); } /* as above, but return the Bezout coefficients for the lifted modular factors * U[i] = 1 mod Qlift[i] * 0 mod Qlift[j], j != i */ GEN bezout_lift_fact(GEN pol, GEN Q, GEN p, long e) { pari_sp av = avma; GEN E, link, v, w, pe; long i, k = lg(Q)-1; if (k == 1) return mkvec(pol); pe = powiu(p, e); pol = FpX_normalize(pol, pe); E = MultiLift(pol, Q, NULL, p, e, 1); link = gel(E,2); v = gel(E,3); w = gel(E,4); BezoutPropagate(link, v, w, pe, NULL, pol, lgpol(v)); E = cgetg(k+1, t_VEC); for (i = 1; i <= 2*k-2; i++) { long t = link[i]; if (t < 0) E[-t] = w[i]; } return gerepilecopy(av, E); } /* Front-end for ZpX_liftfact: lift the factorization of pol mod p given by L to p^N (if possible) */ GEN polhensellift(GEN pol, GEN L, GEN p, long N) { GEN T = NULL; long i, l, t; pari_sp av = avma; if (typ(pol) != t_POL) pari_err_TYPE("polhensellift",pol); RgX_check_ZXX(pol, "polhensellift"); if (!is_vec_t(typ(L)) || lg(L) < 3) pari_err_TYPE("polhensellift",L); t = typ(p); if (t == t_VEC) /* [p, T] */ { T = gel(p,2); if (typ(T) != t_POL) pari_err_TYPE("polhensellift",pol); RgX_check_ZX(T, "polhensellift"); p = gel(p,1); t = typ(p); } if (t != t_INT) pari_err_TYPE("polhensellift",p); if (N < 1) pari_err_DOMAIN("polhensellift", "precision", "<", gen_1,stoi(N)); l = lg(L); L = leafcopy(L); for (i = 1; i < l; i++) { if (typ(gel(L,i)) != t_POL) gel(L,i) = scalar_ZX_shallow(gel(L,i), varn(pol)); RgX_check_ZXX(gel(L,i), "polhensellift"); } return gerepilecopy(av, ZpX_liftfact(pol, L, T, p, N, powiu(p,N))); } /*************************************************************************/ /* rootpadicfast */ /*************************************************************************/ /* SPEC: * p is a t_INT > 1, e >= 1 * f is a ZX with leading term prime to p. * a is a simple root mod l for all l|p. * Return roots of f mod p^e, as integers (implicitly mod p^e) * STANDARD USE: p is a prime power */ GEN ZpX_liftroot(GEN f, GEN a, GEN p, long e) { pari_sp av = avma; GEN q = p, fr, W; ulong mask; a = modii(a,q); if (e == 1) return a; mask = quadratic_prec_mask(e); fr = FpX_red(f,q); W = Fp_inv(FpX_eval(ZX_deriv(fr), a, q), q); /* 1/f'(a) mod p */ for(;;) { q = sqri(q); if (mask & 1) q = diviiexact(q, p); mask >>= 1; fr = FpX_red(f,q); a = Fp_sub(a, Fp_mul(W, FpX_eval(fr, a,q), q), q); if (mask == 1) return gerepileuptoint(av, a); W = Fp_sub(shifti(W,1), Fp_mul(Fp_sqr(W,q), FpX_eval(ZX_deriv(fr),a,q), q), q); } } 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; 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; mask = quadratic_prec_mask(e-v); Tq = FpXT_red(T, qv); 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); for (;;) { GEN u, fa, qv, q2v, q2, Tq2; 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 = FqX_eval(fr, a, Tq, qv); fa = typ(fa)==t_INT? diviiexact(fa,q2v): ZX_Z_divexact(fa, q2v); a = Fq_sub(a, ZX_Z_mul(Fq_mul(W, fa, Tq2, q2v), q2), Tq, qv); if (mask == 1) return gerepileupto(av, a); 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(DEBUGMEM>1) pari_warn(warnmem,"ZpXQX_liftroot, e = %ld", e); gerepileall(av2, 3, &a, &W, &q); } } } 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>= 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. */ 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); 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); q = p; for(;;) { q = sqri(q); if (mask & 1) q = diviiexact(q, p); mask >>= 1; if (lgefint(q) == 3 && lgefint(n) == 3) { ulong Q = (ulong)q[2], N = (ulong)n[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_powu(A,N,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_mul(N,Fl_powu(A, N-1, Q), Q), Q), Q); w = utoi(W); } else { /* a -= w (a^n - b) */ 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)); } } return gerepileuptoint(ltop,a); } /* 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) { pari_sp av = avma; long vT = get_FpX_var(T); GEN bn, bdi; GEN bd = ZX_Z_add(x, gen_1); if (equaliu(p,2)) /*For p=2, we need to simplify by 2*/ { bn = ZX_shifti(x,-(k+1)); bdi= ZpXQ_invlift(ZX_shifti(bd ,-1), pol_1(vT), T, p, e); } else { bn = ZX_Z_divexact(ZX_Z_sub(x, gen_1),powiu(p,k)); bdi= ZpXQ_invlift(bd, scalarpol(Fp_inv(gen_2,p),vT), T, p, e); } return gerepileupto(av, FpXQ_mul(bn, bdi, T, pe)); } /* Assume p odd, a = 1 [p], return log(a) */ GEN ZpXQ_log(GEN a, GEN T, GEN p, long N) { pari_sp av = avma; pari_timer ti; long is2 = equaliu(p,2); ulong pp = is2 ? 0: itou_or_0(p); double lp = is2 ? 1: pp ? log2(pp): expi(p); long k = maxss(1 , (long) .5+pow((double)(N>>1)/(lp*lp), 1./3)); GEN ak, s, b, pol; long e = is2 ? N-1: N; long i, l = (e-2)/(2*(k+is2)); GEN pe = powiu(p,e); GEN TNk, pNk = powiu(p,N+k); if( DEBUGLEVEL>=3) timer_start(&ti); TNk = FpX_get_red(get_FpX_mod(T), pNk); ak = FpXQ_pow(a, powiu(p,k), TNk, pNk); if( DEBUGLEVEL>=3) timer_printf(&ti,"FpXQ_pow(%ld)",k); b = ZpXQ_log_to_ath(ak, k, T, p, e, pe); if( DEBUGLEVEL>=3) timer_printf(&ti,"ZpXQ_log_to_ath"); pol= cgetg(l+3,t_POL); pol[1] = evalsigne(1)|evalvarn(0); for(i=0; i<=l; i++) { GEN g; ulong z = 2*i+1; if (pp) { long w = u_lvalrem(z, pp, &z); g = powuu(pp,2*i*k-w); } else g = powiu(p,2*i*k); gel(pol,i+2) = Fp_div(g, utoi(z),pe); } if( DEBUGLEVEL>=3) timer_printf(&ti,"pol(%ld)",l); s = FpX_FpXQ_eval(pol, FpXQ_sqr(b, T, pe), T, pe); if( DEBUGLEVEL>=3) timer_printf(&ti,"FpX_FpXQ_eval"); s = ZX_shifti(FpXQ_mul(b, s, T, pe), 1); return gerepileupto(av, is2? s: FpX_red(s, pe)); } /***********************************************************************/ /** **/ /** Generic quadratic hensel lift over Zp[X] **/ /** **/ /***********************************************************************/ /* q = p^N */ GEN gen_ZpX_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)) { pari_sp av = avma; long N2, M; GEN VN2, V2, VM, bil; GEN q2, qM; V = FpX_red(V, q); if (N == 1) return invl(E, V); N2 = (N + 1)>>1; M = N - N2; F = FpXT_red(F, q); qM = powiu(p, M); q2 = M == N2? qM: mulii(qM, p); /* q2 = p^N2, qM = p^M, q = q2 * qM */ VN2 = gen_ZpX_Dixon(F, V, q2, p, N2, E, lin, invl); bil = lin(E, F, VN2, q); V2 = ZX_Z_divexact(ZX_sub(V, bil), q2); VM = gen_ZpX_Dixon(F, V2, qM, p, M, E, lin, invl); return gerepileupto(av, FpX_red(ZX_add(VN2, ZX_Z_mul(VM, q2)), q)); } GEN 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; 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); while (mask > 1) { GEN qM, q2, v, V; N2 = N; N <<= 1; q2 = q; if (mask&1UL) { /* can never happen when q2 = p */ N--; M = N2-1; qM = diviiexact(q2,p); /* > 1 */ q = mulii(qM,q2); } else { M = N2; qM = q2; q = sqri(q2); } /* q2 = p^N2, qM = p^M, q = p^N = q2 * qM */ mask >>= 1; 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(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpX_Newton"); gerepileall(av, 2, &x, &q); } } return gerepileupto(ltop, x); } struct _ZpXQ_inv { GEN T, a, p ,n; }; static GEN _inv_invd(void *E, GEN V, GEN v, GEN q, long M/*unused*/) { struct _ZpXQ_inv *d = (struct _ZpXQ_inv *) E; GEN Tq = FpXT_red(d->T, q); (void)M; return FpXQ_mul(V, gel(v,2), Tq, q); } static GEN _inv_eval(void *E, GEN x, GEN q) { struct _ZpXQ_inv *d = (struct _ZpXQ_inv *) E; GEN Tq = FpXT_red(d->T, q); GEN f = FpX_Fp_sub(FpXQ_mul(x, FpX_red(d->a, q), Tq, q), gen_1, q); return mkvec2(f, x); } GEN ZpXQ_invlift(GEN a, GEN x, GEN T, GEN p, long e) { struct _ZpXQ_inv d; d.a = a; d.T = T; d.p = p; return gen_ZpX_Newton(x, p, e, &d, _inv_eval, _inv_invd); } GEN ZpXQ_inv(GEN a, GEN T, GEN p, long e) { pari_sp av=avma; GEN ai; if (lgefint(p)==3) { ulong pp = p[2]; ai = Flx_to_ZX(Flxq_inv(ZX_to_Flx(a,pp), ZXT_to_FlxT(T, pp), pp)); } else ai = FpXQ_inv(FpX_red(a,p), FpXT_red(T,p),p); return gerepileupto(av, ZpXQ_invlift(a, ai, T, p, e)); } struct _ZpXQ_sqrtn { GEN T, a, n, ai; }; static GEN _sqrtn_invd(void *E, GEN V, GEN v, GEN q, long M) { struct _ZpXQ_sqrtn *d = (struct _ZpXQ_sqrtn *) E; GEN Tq = FpX_red(d->T, q), aiq = FpX_red(d->ai, q); (void)M; return FpXQ_mul(FpXQ_mul(V, gel(v,2), Tq, q), aiq, Tq, q); } static GEN _sqrtn_eval(void *E, GEN x, GEN q) { struct _ZpXQ_sqrtn *d = (struct _ZpXQ_sqrtn *) E; GEN Tq = FpX_red(d->T, q); GEN f = FpX_sub(FpXQ_pow(x, d->n, Tq, q), d->a, q); return mkvec2(f, x); } GEN ZpXQ_sqrtnlift(GEN a, GEN n, GEN x, GEN T, GEN p, long e) { struct _ZpXQ_sqrtn d; d.a = a; d.T = T; d.n = n; 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); } pari-2.7.5/src/basemath/QX_factor.c0000644000175000017500000011163012413013142015504 0ustar billbill/* 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" /* x,y two ZX, y non constant. Return q = x/y if y divides x in Z[X] and NULL * otherwise. If not NULL, B is a t_INT upper bound for ||q||_oo. */ static GEN ZX_divides_i(GEN x, GEN y, GEN B) { long dx, dy, dz, i, j; pari_sp av; GEN z,p1,y_lead; dy=degpol(y); dx=degpol(x); dz=dx-dy; if (dz<0) return NULL; z=cgetg(dz+3,t_POL); z[1] = x[1]; x += 2; y += 2; z += 2; y_lead = gel(y,dy); if (equali1(y_lead)) y_lead = NULL; p1 = gel(x,dx); if (y_lead) { GEN r; p1 = dvmdii(p1,y_lead, &r); if (r != gen_0) return NULL; } else p1 = icopy(p1); gel(z,dz) = p1; for (i=dx-1; i>=dy; i--) { av = avma; p1 = gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); if (y_lead) { GEN r; p1 = dvmdii(p1,y_lead, &r); if (r != gen_0) return NULL; } if (B && absi_cmp(p1, B) > 0) return NULL; p1 = gerepileuptoint(av, p1); gel(z,i-dy) = p1; } av = avma; for (; i >= 0; i--) { p1 = gel(x,i); /* we always enter this loop at least once */ for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); if (signe(p1)) return NULL; avma = av; } return z - 2; } static GEN ZX_divides(GEN x, GEN y) { return ZX_divides_i(x,y,NULL); } #if 0 /* cf Beauzamy et al: upper bound for * lc(x) * [2^(5/8) / pi^(3/8)] e^(1/4n) 2^(n/2) sqrt([x]_2)/ n^(3/8) * where [x]_2 = sqrt(\sum_i=0^n x[i]^2 / binomial(n,i)). One factor has * all coeffs less than then bound */ static GEN two_factor_bound(GEN x) { long i, j, n = lg(x) - 3; pari_sp av = avma; GEN *invbin, c, r = cgetr(3), z; x += 2; invbin = (GEN*)new_chunk(n+1); z = real_1(LOWDEFAULTPREC); /* invbin[i] = 1 / binomial(n, i) */ for (i=0,j=n; j >= i; i++,j--) { invbin[i] = invbin[j] = z; z = divru(mulru(z, i+1), n-i); } z = invbin[0]; /* = 1 */ for (i=0; i<=n; i++) { c = gel(x,i); if (!signe(c)) continue; affir(c, r); z = addrr(z, mulrr(sqrr(r), invbin[i])); } z = shiftr(sqrtr(z), n); z = divrr(z, dbltor(pow((double)n, 0.75))); z = roundr_safe(sqrtr(z)); z = mulii(z, absi(gel(x,n))); return gerepileuptoint(av, shifti(z, 1)); } #endif /* A | S ==> |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S) */ static GEN Mignotte_bound(GEN S) { long i, d = degpol(S); GEN C, N2, t, binlS, lS = leading_term(S), bin = vecbinome(d-1); N2 = sqrtr(RgX_fpnorml2(S,DEFAULTPREC)); binlS = is_pm1(lS)? bin: ZC_Z_mul(bin, lS); /* i = 0 */ C = gel(binlS,1); /* i = d */ t = N2; if (gcmp(C, t) < 0) C = t; for (i = 1; i < d; i++) { t = addri(mulir(gel(bin,i), N2), gel(binlS,i+1)); if (mpcmp(C, t) < 0) C = t; } return C; } /* A | S ==> |a_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2^2, * where [P]_2 is Bombieri's 2-norm */ static GEN Beauzamy_bound(GEN S) { const long prec = DEFAULTPREC; long i, d = degpol(S); GEN bin, lS, s, C; bin = vecbinome(d); s = real_0(prec); for (i=0; i<=d; i++) { GEN c = gel(S,i+2); if (gequal0(c)) continue; /* s += P_i^2 / binomial(d,i) */ s = addrr(s, divri(itor(sqri(c), prec), gel(bin,i+1))); } /* s = [S]_2^2 */ C = powruhalf(stor(3,prec), 3 + 2*d); /* 3^{3/2 + d} */ C = divrr(mulrr(C, s), mulur(4*d, mppi(prec))); lS = absi(leading_term(S)); return mulir(lS, sqrtr(C)); } static GEN factor_bound(GEN S) { pari_sp av = avma; GEN a = Mignotte_bound(S); GEN b = Beauzamy_bound(S); if (DEBUGLEVEL>2) { err_printf("Mignotte bound: %Ps\n",a); err_printf("Beauzamy bound: %Ps\n",b); } return gerepileupto(av, ceil_safe(gmin(a, b))); } /* Naive recombination of modular factors: combine up to maxK modular * factors, degree <= klim * * target = polynomial we want to factor * famod = array of modular factors. Product should be congruent to * target/lc(target) modulo p^a * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */ static GEN cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b, long klim, long *pmaxK, int *done) { long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1; ulong spa_b, spa_bs2, Sbound; GEN lc, lcpol, pa = powiu(p,a), pas2 = shifti(pa,-1); GEN trace1 = cgetg(lfamod+1, t_VECSMALL); GEN trace2 = cgetg(lfamod+1, t_VECSMALL); GEN ind = cgetg(lfamod+1, t_VECSMALL); GEN deg = cgetg(lfamod+1, t_VECSMALL); GEN degsofar = cgetg(lfamod+1, t_VECSMALL); GEN listmod = cgetg(lfamod+1, t_VEC); GEN fa = cgetg(lfamod+1, t_VEC); *pmaxK = cmbf_maxK(lfamod); lc = absi(leading_term(pol)); if (is_pm1(lc)) lc = NULL; lcpol = lc? ZX_Z_mul(pol, lc): pol; { GEN pa_b,pa_bs2,pb, lc2 = lc? sqri(lc): NULL; pa_b = powiu(p, a-b); /* < 2^31 */ pa_bs2 = shifti(pa_b,-1); pb= powiu(p, b); for (i=1; i <= lfamod; i++) { GEN T1,T2, P = gel(famod,i); long d = degpol(P); deg[i] = d; P += 2; T1 = gel(P,d-1);/* = - S_1 */ T2 = sqri(T1); if (d > 1) T2 = subii(T2, shifti(gel(P,d-2),1)); T2 = modii(T2, pa); /* = S_2 Newton sum */ if (lc) { T1 = Fp_mul(lc, T1, pa); T2 = Fp_mul(lc2,T2, pa); } trace1[i] = itou(diviiround(T1, pb)); trace2[i] = itou(diviiround(T2, pb)); } spa_b = (ulong) pa_b[2]; /* < 2^31 */ spa_bs2 = (ulong)pa_bs2[2]; /* < 2^31 */ } degsofar[0] = 0; /* sentinel */ /* ind runs through strictly increasing sequences of length K, * 1 <= ind[i] <= lfamod */ nextK: if (K > *pmaxK || 2*K > lfamod) goto END; if (DEBUGLEVEL > 3) err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K)); setlg(ind, K+1); ind[1] = 1; Sbound = (ulong) ((K+1)>>1); i = 1; curdeg = deg[ind[1]]; for(;;) { /* try all combinations of K factors */ for (j = i; j < K; j++) { degsofar[j] = curdeg; ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]]; } if (curdeg <= klim) /* trial divide */ { GEN y, q, list; pari_sp av; ulong t; /* d - 1 test */ for (t=trace1[ind[1]],i=2; i<=K; i++) t = Fl_add(t, trace1[ind[i]], spa_b); if (t > spa_bs2) t = spa_b - t; if (t > Sbound) { if (DEBUGLEVEL>6) err_printf("."); goto NEXT; } /* d - 2 test */ for (t=trace2[ind[1]],i=2; i<=K; i++) t = Fl_add(t, trace2[ind[i]], spa_b); if (t > spa_bs2) t = spa_b - t; if (t > Sbound) { if (DEBUGLEVEL>6) err_printf("|"); goto NEXT; } av = avma; /* check trailing coeff */ y = lc; for (i=1; i<=K; i++) { GEN q = constant_term(gel(famod,ind[i])); if (y) q = mulii(y, q); y = centermodii(q, pa, pas2); } if (!signe(y) || remii(constant_term(lcpol), y) != gen_0) { if (DEBUGLEVEL>3) err_printf("T"); avma = av; goto NEXT; } y = lc; /* full computation */ for (i=1; i<=K; i++) { GEN q = gel(famod,ind[i]); if (y) q = gmul(y, q); y = centermod_i(q, pa, pas2); } /* y is the candidate factor */ if (! (q = ZX_divides_i(lcpol,y,bound)) ) { if (DEBUGLEVEL>3) err_printf("*"); avma = av; goto NEXT; } /* found a factor */ list = cgetg(K+1, t_VEC); gel(listmod,cnt) = list; for (i=1; i<=K; i++) list[i] = famod[ind[i]]; y = Q_primpart(y); gel(fa,cnt++) = y; /* fix up pol */ pol = q; if (lc) pol = Q_div_to_int(pol, leading_term(y)); for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { gel(famod,k) = gel(famod,i); trace1[k] = trace1[i]; trace2[k] = trace2[i]; deg[k] = deg[i]; k++; } } lfamod -= K; *pmaxK = cmbf_maxK(lfamod); if (lfamod < 2*K) goto END; i = 1; curdeg = deg[ind[1]]; bound = factor_bound(pol); if (lc) lc = absi(leading_term(pol)); lcpol = lc? ZX_Z_mul(pol, lc): pol; if (DEBUGLEVEL>3) err_printf("\nfound factor %Ps\nremaining modular factor(s): %ld\n", y, lfamod); continue; } NEXT: for (i = K+1;;) { if (--i == 0) { K++; goto nextK; } if (++ind[i] <= lfamod - K + i) { curdeg = degsofar[i-1] + deg[ind[i]]; if (curdeg <= klim) break; } } } END: *done = 1; if (degpol(pol) > 0) { /* leftover factor */ if (signe(leading_term(pol)) < 0) pol = ZX_neg(pol); if (lfamod >= 2*K) *done = 0; setlg(famod, lfamod+1); gel(listmod,cnt) = leafcopy(famod); gel(fa,cnt++) = pol; } if (DEBUGLEVEL>6) err_printf("\n"); setlg(listmod, cnt); setlg(fa, cnt); return mkvec2(fa, listmod); } void factor_quad(GEN x, GEN res, long *ptcnt) { GEN a = gel(x,4), b = gel(x,3), c = gel(x,2), d, u, z1, z2, t; GEN D = subii(sqri(b), shifti(mulii(a,c), 2)); long v, cnt = *ptcnt; if (!Z_issquareall(D, &d)) { gel(res,cnt++) = x; *ptcnt = cnt; return; } t = shifti(negi(addii(b, d)), -1); z1 = gdiv(t, a); u = denom(z1); z2 = gdiv(addii(t, d), a); v = varn(x); gel(res,cnt++) = gmul(u, gsub(pol_x(v), z1)); u = diviiexact(a, u); gel(res,cnt++) = gmul(u, gsub(pol_x(v), z2)); *ptcnt = cnt; } /* recombination of modular factors: van Hoeij's algorithm */ /* Q in Z[X], return Q(2^n) */ static GEN shifteval(GEN Q, long n) { long i, l = lg(Q); GEN s; if (!signe(Q)) return gen_0; s = gel(Q,l-1); for (i = l-2; i > 1; i--) s = addii(gel(Q,i), shifti(s, n)); return s; } /* return integer y such that all |a| <= y if P(a) = 0 */ static GEN root_bound(GEN P0) { GEN Q = leafcopy(P0), lP = absi(leading_term(Q)), x,y,z; long k, d = degpol(Q); /* 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); for ( ; k >= 0; k--) { pari_sp av = avma; /* y = 2^k; Q(y) >= lP y^d ? */ if (cmpii(shifteval(Q,k), shifti(lP, d*k)) >= 0) break; avma = av; } if (k < 0) k = 0; x = int2n(k); y = int2n(k+1); for(k=0; ; k++) { z = shifti(addii(x,y), -1); if (equalii(x,z) || k > 5) break; if (cmpii(poleval(Q,z), mulii(lP, powiu(z, d))) < 0) y = z; else x = z; } return y; } GEN special_pivot(GEN x) { GEN t, perm, H = ZM_hnfperm(x,NULL,&perm); long i,j, l = lg(H), h = lgcols(H); for (i=1; i 1) gel(V,1) = RgX_Rg_mul(gel(V,1), lt); setlg(V, i); return T? FpXQXV_prod(V, T, N): FpXV_prod(V,N); } static GEN chk_factors(GEN P, GEN M_L, GEN bound, GEN famod, GEN pa) { long i, r; GEN pol = P, list, piv, y, ltpol, lt, paov2; piv = special_pivot(M_L); if (!piv) return NULL; if (DEBUGLEVEL>7) err_printf("special_pivot output:\n%Ps\n",piv); r = lg(piv)-1; list = cgetg(r+1, t_VEC); lt = absi(leading_term(pol)); if (is_pm1(lt)) lt = NULL; ltpol = lt? ZX_Z_mul(pol, lt): pol; paov2 = shifti(pa,-1); for (i = 1;;) { if (DEBUGLEVEL) err_printf("LLL_cmbf: checking factor %ld\n",i); y = chk_factors_get(lt, famod, gel(piv,i), NULL, pa); y = FpX_center(y, pa, paov2); if (! (pol = ZX_divides_i(ltpol,y,bound)) ) return NULL; if (lt) y = Q_primpart(y); gel(list,i) = y; if (++i >= r) break; if (lt) { pol = ZX_Z_divexact(pol, leading_term(y)); lt = absi(leading_term(pol)); ltpol = ZX_Z_mul(pol, lt); } else ltpol = pol; } y = Q_primpart(pol); gel(list,i) = y; return list; } GEN LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, long *ti_LLL) { GEN norm, u; long i, R; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); u = ZM_lll_norms(m, final? 0.999: 0.75, LLL_INPLACE, &norm); if (DEBUGLEVEL>2) *ti_LLL += timer_delay(&T); for (R=lg(m)-1; R > 0; R--) if (cmprr(gel(norm,R), Bnorm) < 0) break; for (i=1; i<=R; i++) setlg(u[i], n0+1); if (R <= 1) { if (!R) pari_err_BUG("LLL_cmbf [no factor]"); return NULL; /* irreducible */ } setlg(u, R+1); return u; } static ulong next2pow(ulong a) { ulong b = 1; while (b < a) b <<= 1; return b; } /* Recombination phase of Berlekamp-Zassenhaus algorithm using a variant of * van Hoeij's knapsack * * P = squarefree in Z[X]. * famod = array of (lifted) modular factors mod p^a * bound = Mignotte bound for the size of divisors of P (for the sup norm) * previously recombined all set of factors with less than rec elts */ static GEN LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec) { const long N0 = 1; /* # of traces added at each step */ double BitPerFactor = 0.4; /* nb bits in p^(a-b) / modular factor */ long i,j,tmax,n0,C, dP = degpol(P); 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; long ti_LLL = 0, ti_CF = 0; lP = absi(leading_term(P)); if (is_pm1(lP)) lP = NULL; Br = root_bound(P); if (lP) Br = mulii(lP, Br); logBr = gtodouble(glog(Br, DEFAULTPREC)) / logp; n0 = lg(famod) - 1; C = (long)ceil( sqrt(N0 * n0 / 4.) ); /* > 1 */ Bnorm = dbltor(n0 * (C*C + N0*n0/4.) * 1.00001); ZERO = zeromat(n0, N0); av = avma; lim = stack_lim(av, 1); TT = cgetg(n0+1, t_VEC); Tra = cgetg(n0+1, t_MAT); for (i=1; i<=n0; i++) { TT[i] = 0; gel(Tra,i) = cgetg(N0+1, t_COL); } CM_L = scalarmat_s(C, n0); /* tmax = current number of traces used (and computed so far) */ for (tmax = 0;; tmax += N0) { long b, bmin, bgood, delta, tnew = tmax + N0, r = lg(CM_L)-1; GEN M_L, q, CM_Lp, oldCM_L; int first = 1; pari_timer ti2, TI; bmin = (long)ceil(b0 + tnew*logBr); if (DEBUGLEVEL>2) err_printf("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n", r, tmax, bmin); /* compute Newton sums (possibly relifting first) */ if (a <= bmin) { a = (long)ceil(bmin + 3*N0*logBr) + 1; /* enough for 3 more rounds */ a = (long)next2pow((ulong)a); pa = powiu(p,a); famod = ZpX_liftfact(P,famod,NULL,p,a,pa); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN p1 = gel(Tra,i); GEN p2 = polsym_gen(gel(famod,i), gel(TT,i), tnew, NULL, pa); gel(TT,i) = p2; p2 += 1+tmax; /* ignore traces number 0...tmax */ for (j=1; j<=N0; j++) gel(p1,j) = gel(p2,j); if (lP) { /* make Newton sums integral */ GEN lPpow = powiu(lP, tmax); for (j=1; j<=N0; j++) { lPpow = mulii(lPpow,lP); gel(p1,j) = mulii(gel(p1,j), lPpow); } } } /* compute truncation parameter */ if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); } oldCM_L = CM_L; av2 = avma; delta = b = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); T2 = centermod( ZM_mul(Tra, M_L), pa ); if (first) { /* initialize lattice, using few p-adic digits for traces */ double t = gexpo(T2) - maxdd(32.0, BitPerFactor*r); bgood = (long) (t * LOGp2); b = maxss(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ long b0 = (long)(gexpo(T2) * LOGp2); if (b0 < b) b = b0; b = maxss(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } q = powiu(p, b); m = vconcat( CM_L, gdivround(T2, q) ); if (first) { GEN P1 = scalarmat(powiu(p, a-b), N0); first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' p^(a-b) I_N0 ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI)); if (!CM_L) { list = mkvec(P); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) timer_printf(&ti2, "for this block of traces"); i = lg(CM_L) - 1; if (i == r && ZM_equal(CM_L, oldCM_L)) { CM_L = oldCM_L; avma = av2; continue; } CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */ if (lg(CM_Lp) != lg(CM_L)) { if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n"); CM_L = ZM_hnf(CM_L); } if (i <= r && i*rec < n0) { pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); list = chk_factors(P, Q_div_to_int(CM_L,utoipos(C)), bound, famod, pa); if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti); if (list) break; 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(DEBUGMEM>1) pari_warn(warnmem,"LLL_cmbf"); gerepileall(av, 5, &CM_L, &TT, &Tra, &famod, &pa); } } if (DEBUGLEVEL>2) err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF); return list; } /* Find a,b minimal such that A < q^a, B < q^b, 1 << q^(a-b) < 2^31 */ static int cmbf_precs(GEN q, GEN A, GEN B, long *pta, long *ptb, GEN *qa, GEN *qb) { long a,b,amin,d = (long)(31 * LOG2/gtodouble(glog(q,DEFAULTPREC)) - 1e-5); int fl = 0; b = logint(B, q, qb); amin = b + d; if (gcmp(powiu(q, amin), A) <= 0) { a = logint(A, q, qa); b = a - d; *qb = powiu(q, b); } else { /* not enough room */ a = amin; *qa = powiu(q, a); fl = 1; } if (DEBUGLEVEL > 3) { err_printf("S_2 bound: %Ps^%ld\n", q,b); err_printf("coeff bound: %Ps^%ld\n", q,a); } *pta = a; *ptb = b; return fl; } /* use van Hoeij's knapsack algorithm */ static GEN combine_factors(GEN target, GEN famod, GEN p, long klim) { GEN la, B, A, res, L, pa, pb, listmod; long a,b, l, maxK, n = degpol(target); int done; pari_timer T; A = factor_bound(target); la = absi(leading_term(target)); B = mului(n, sqri(mulii(la, root_bound(target)))); /* = bound for S_2 */ (void)cmbf_precs(p, A, B, &a, &b, &pa, &pb); if (DEBUGLEVEL>2) timer_start(&T); famod = ZpX_liftfact(target,famod,NULL,p,a,pa); if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,a); L = cmbf(target, famod, A, p, a, b, klim, &maxK, &done); if (DEBUGLEVEL>2) timer_printf(&T, "Naive recombination"); res = gel(L,1); listmod = gel(L,2); l = lg(listmod)-1; famod = gel(listmod,l); if (maxK > 0 && lg(famod)-1 > 2*maxK) { if (l!=1) A = factor_bound(gel(res,l)); if (DEBUGLEVEL > 4) err_printf("last factor still to be checked\n"); L = LLL_cmbf(gel(res,l), famod, p, pa, A, a, maxK); if (DEBUGLEVEL>2) timer_printf(&T,"Knapsack"); /* remove last elt, possibly unfactored. Add all new ones. */ setlg(res, l); res = shallowconcat(res, L); } return res; } /* Assume 'a' a squarefree ZX; return 0 if no root (fl=1) / irreducible (fl=0). * Otherwise return prime p such that a mod p has fewest roots / factors */ static ulong pick_prime(GEN a, long fl, pari_timer *T) { pari_sp av = avma, av1; const long MAXNP = 7, da = degpol(a); long nmax = da+1, np; ulong chosenp = 0; GEN lead = gel(a,da+2); forprime_t S; if (equali1(lead)) lead = NULL; u_forprime_init(&S, 2, ULONG_MAX); av1 = avma; for (np = 0; np < MAXNP; avma = av1) { ulong p = u_forprime_next(&S); long nfacp; GEN z; if (!p) pari_err_OVERFLOW("DDF [out of small primes]"); if (lead && !umodiu(lead,p)) continue; z = ZX_to_Flx(a, p); if (!Flx_is_squarefree(z, p)) continue; if (fl) { nfacp = Flx_nbroots(z, p); if (!nfacp) { chosenp = 0; break; } /* no root */ } else { nfacp = Flx_nbfact(z, p); if (nfacp == 1) { chosenp = 0; break; } /* irreducible */ } if (DEBUGLEVEL>4) err_printf("...tried prime %3lu (%-3ld %s). Time = %ld\n", p, nfacp, fl? "roots": "factors", timer_delay(T)); if (nfacp < nmax) { nmax = nfacp; chosenp = p; if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */ } np++; } avma = av; return chosenp; } /* Assume pol squarefree mod p; return vector of rational roots of a */ static GEN DDF_roots(GEN A) { GEN p, Ap, lc, lcpol, z, pe, pes2, bound; long i, m, e, lz, v = varn(A); ulong pp; pari_sp av, lim; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); pp = pick_prime(A, 1, &T); if (!pp) return cgetg(1,t_VEC); /* no root */ p = utoipos(pp); lc = leading_term(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); 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); } if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e); for (m=1, i=1; i <= lz; i++) { GEN q, r, y = gel(z,i); if (lc) y = ZX_Z_mul(y, lc); y = centermod_i(y, pe, pes2); if (! (q = ZX_divides(lcpol, y)) ) continue; lcpol = A = q; r = negi( constant_term(y) ); if (lc) { r = gdiv(r,lc); A = Q_primpart(A); lc = absi( 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 (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m); gerepileall(av, lc? 4:2, &z, &A, &lc, &lcpol); } } if (DEBUGLEVEL>2) timer_printf(&T, "Recombination"); z[0] = evaltyp(t_VEC) | evallg(m); return z; } /* Assume a squarefree ZX, deg(a) > 0, return rational factors. * In fact, a(0) != 0 but we don't use this */ static GEN DDF(GEN a) { GEN ap, prime, famod, z; long ti = 0; ulong p = 0; pari_sp av = avma; pari_timer T, T2; if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); } p = pick_prime(a, 0, &T2); if (!p) return mkvec(a); prime = utoipos(p); ap = Flx_normalize(ZX_to_Flx(a, p), p); famod = gel(Flx_factor(ap, p), 1); if (DEBUGLEVEL>2) { if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %lu", p); ti = timer_delay(&T); err_printf("Time setup: %ld\n", ti); } z = combine_factors(a, FlxV_to_ZXV(famod), prime, degpol(a)-1); if (DEBUGLEVEL>2) err_printf("Total Time: %ld\n===========\n", ti + timer_delay(&T)); return gerepilecopy(av, z); } /* Distinct Degree Factorization (deflating first) * Assume x squarefree, degree(x) > 0, x(0) != 0 */ GEN ZX_DDF(GEN x) { GEN L; long m; x = RgX_deflate_max(x, &m); L = DDF(x); if (m > 1) { GEN e, v, fa = factoru(m); long i,j,k, l; e = gel(fa,2); k = 0; fa= gel(fa,1); l = lg(fa); for (i=1; i ggcd). Return (P), set *ex = (e) */ GEN ZX_squff(GEN f, GEN *ex) { GEN T, V, P, e; long i, k, n, val; if (signe(leading_term(f)) < 0) f = gneg_i(f); val = ZX_valrem(f, &f); n = 1 + degpol(f); if (val) n++; e = cgetg(n,t_VECSMALL); P = cgetg(n,t_COL); T = ZX_gcd_all(f, ZX_deriv(f), &V); for (k=i=1;; k++) { pari_sp av = avma; GEN W = ZX_gcd_all(T,V, &T); long dW = degpol(W); /* W = prod P^e, e > k; V = prod P^e, e >= k */ if (dW == degpol(V)) /* V | T */ { GEN U; if (!dW) { avma = av; break; } while ( (U = ZX_divides(T, V)) ) { k++; T = U; } T = gerepileupto(av, T); } else { gel(P,i) = Q_primpart(RgX_div(V,W)); e[i] = k; i++; if (!dW) break; V = W; } } if (val) { gel(P,i) = pol_x(varn(f)); e[i] = val; i++;} setlg(P,i); setlg(e,i); *ex = e; return P; } GEN fact_from_DDF(GEN fa, GEN e, long n) { GEN v,w, y = cgetg(3, t_MAT); long i,j,k, l = lg(fa); v = cgetg(n+1,t_COL); gel(y,1) = v; w = cgetg(n+1,t_COL); gel(y,2) = w; for (k=i=1; i 0) m = x; } m = divii(m, gel(p,n)); return gerepileuptoint(av, addis(absi(m),1)); } #endif /* A, B in Z[X] */ GEN 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; forprime_t S; if (!signe(A)) { if (Anew) *Anew = pol_0(vA); return ZX_copy(B); } if (!signe(B)) { if (Anew) *Anew = pol_1(vA); return ZX_copy(A); } valA = ZX_valrem(A, &A); valX = minss(valA, ZX_valrem(B, &B)); ltop = avma; n = 1 + minss(degpol(A), degpol(B)); /* > degree(gcd) */ g = gcdii(leading_term(A), leading_term(B)); /* multiple of lead(gcd) */ if (is_pm1(g)) { g = NULL; Ag = A; Bg = B; } else { Ag = ZX_Z_mul(A,g); Bg = ZX_Z_mul(B,g); } init_modular(&S); av = avma; avlim = stack_lim(av, 1); R = NULL;/*-Wall*/ H = NULL; while ((p = u_forprime_next(&S))) { if (g && !umodiu(g,p)) continue; a = ZX_to_Flx(A, p); b = ZX_to_Flx(B, p); Hp = Flx_gcd(a,b, p); m = degpol(Hp); if (m == 0) { /* coprime. DONE */ avma = ltop; if (Anew) { if (valA != valX) A = RgX_shift(A, valA - valX); *Anew = A; } return monomial(gen_1, valX, vA); } if (m > n) continue; /* p | Res(A/G, B/G). Discard */ if (!g) /* make sure lead(H) = g mod p */ Hp = Flx_normalize(Hp, p); else { ulong t = Fl_mul(umodiu(g, p), Fl_inv(Hp[m+2],p), p); Hp = Flx_Fl_mul(Hp, t, p); } if (m < n) { /* First time or degree drop [all previous p were as above; restart]. */ H = ZX_init_CRT(Hp,p,vA); 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 (DEBUGMEM>1) pari_warn(warnmem,"QX_gcd"); gerepileall(av, 3, &H, &q, &Hp); } if (!ZX_incremental_CRT(&H, Hp, &q, p)) continue; /* H stable: check divisibility */ if (!ZX_divides(Bg, H)) continue; R = ZX_divides(Ag, H); if (R) break; } if (!p) pari_err_OVERFLOW("ZX_gcd_all [ran out of primes]"); if (Anew) { A = R; if (valA != valX) A = RgX_shift(A, valA - valX); *Anew = A; } return valX ? RgX_shift(H, valX): H; } GEN ZX_gcd(GEN A, GEN B) { return ZX_gcd_all(A,B,NULL); } static GEN _gcd(GEN a, GEN b) { if (!a) a = gen_1; if (!b) b = gen_1; return Q_gcd(a,b); } /* A0 and B0 in Q[X] */ GEN QX_gcd(GEN A0, GEN B0) { GEN a, b, D; pari_sp av = avma, av2; D = ZX_gcd(Q_primitive_part(A0, &a), Q_primitive_part(B0, &b)); av2 = avma; a = _gcd(a,b); if (isint1(a)) avma = av2; else D = RgX_Rg_mul(D, a); return gerepileupto(av, D); } /***************************************************************************** * Variants of the Bradford-Davenport algorithm: look for cyclotomic * * factors, and decide whether a ZX is cyclotomic or a product of cyclotomic * *****************************************************************************/ /* f of degree 1, return a cyclotomic factor (Phi_1 or Phi_2) or NULL */ static GEN BD_deg1(GEN f) { GEN a = gel(f,3), b = gel(f,2); /* f = ax + b */ if (!absi_equal(a,b)) return NULL; return polcyclo((signe(a) == signe(b))? 2: 1, varn(f)); } /* f a squarefree ZX; not divisible by any Phi_n, n even */ static GEN BD_odd(GEN f) { while(degpol(f) > 1) { GEN f1 = ZX_graeffe(f); /* contain all cyclotomic divisors of f */ if (ZX_equal(f1, f)) return f; /* product of cyclotomics */ f = ZX_gcd(f, f1); } if (degpol(f) == 1) return BD_deg1(f); return NULL; /* no cyclotomic divisor */ } static GEN myconcat(GEN v, GEN x) { if (typ(x) != t_VEC) x = mkvec(x); if (!v) return x; return shallowconcat(v, x); } /* Bradford-Davenport algorithm. * f a squarefree ZX of degree > 0, return NULL or a vector of coprime * cyclotomic factors of f [ possibly reducible ] */ static GEN BD(GEN f) { GEN G = NULL, Gs = NULL, Gp = NULL, Gi = NULL; GEN fs2, fp, f2, f1, fe, fo, fe1, fo1; RgX_even_odd(f, &fe, &fo); fe1 = ZX_eval1(fe); fo1 = ZX_eval1(fo); if (absi_equal(fe1, fo1)) /* f(1) = 0 or f(-1) = 0 */ { long i, v = varn(f); if (!signe(fe1)) G = mkvec2(polcyclo(1, v), polcyclo(2, v)); /* both 0 */ else if (signe(fe1) == signe(fo1)) G = mkvec(polcyclo(2, v)); /*f(-1) = 0*/ else G = mkvec(polcyclo(1, v)); /*f(1) = 0*/ for (i = lg(G)-1; i; i--) f = RgX_div(f, gel(G,i)); } /* f no longer divisible by Phi_1 or Phi_2 */ if (degpol(f) <= 1) return G; f1 = ZX_graeffe(f); /* has at most square factors */ if (ZX_equal(f1, f)) return myconcat(G,f); /* f = product of Phi_n, n odd */ fs2 = ZX_gcd_all(f1, ZX_deriv(f1), &f2); /* fs2 squarefree */ if (degpol(fs2)) { /* fs contains all Phi_n | f, 4 | n; and only those */ /* In that case, Graeffe(Phi_n) = Phi_{n/2}^2, and Phi_n = Phi_{n/2}(x^2) */ GEN fs = RgX_inflate(fs2, 2); (void)ZX_gcd_all(f, fs, &f); /* remove those Phi_n | f, 4 | n */ Gs = BD(fs2); if (Gs) { long i; for (i = lg(Gs)-1; i; i--) gel(Gs,i) = RgX_inflate(gel(Gs,i), 2); /* prod Gs[i] is the product of all Phi_n | f, 4 | n */ G = myconcat(G, Gs); } /* f2 = f1 / fs2 */ f1 = RgX_div(f2, fs2); /* f1 / fs2^2 */ } fp = ZX_gcd(f, f1); /* contains all Phi_n | f, n > 1 odd; and only those */ if (degpol(fp)) { Gp = BD_odd(fp); /* Gp is the product of all Phi_n | f, n odd */ if (Gp) G = myconcat(G, Gp); f = RgX_div(f, fp); } if (degpol(f)) { /* contains all Phi_n originally dividing f, n = 2 mod 4, n > 2; * and only those * In that case, Graeffe(Phi_n) = Phi_{n/2}, and Phi_n = Phi_{n/2}(-x) */ Gi = BD_odd(ZX_unscale(f, gen_m1)); if (Gi) { /* N.B. Phi_2 does not divide f */ Gi = ZX_unscale(Gi, gen_m1); /* Gi is the product of all Phi_n | f, n = 2 mod 4 */ G = myconcat(G, Gi); } } return G; } /* Let f be a non-zero QX, return the (squarefree) product of cyclotomic * divisors of f */ GEN polcyclofactors(GEN f) { pari_sp av = avma; if (typ(f) != t_POL) pari_err_TYPE("polcyclofactors",f); (void)RgX_valrem(f, &f); f = Q_primpart(f); if (!RgX_is_ZX(f) || !signe(f)) pari_err_TYPE("polcyclofactors",f); if (degpol(f)) { (void)ZX_gcd_all(f, ZX_deriv(f), &f); f = BD(f); if (f) return gerepilecopy(av, f); } avma = av; return cgetg(1,t_VEC); } /* return t*x mod T(x), T a monic ZX. Assume deg(t) < deg(T) */ static GEN ZXQ_mul_by_X(GEN t, GEN T) { GEN lt; t = RgX_shift_shallow(t, 1); if (degpol(t) < degpol(T)) return t; lt = leading_term(t); if (is_pm1(lt)) return signe(lt) > 0 ? ZX_sub(t, T): ZX_add(t, T); return ZX_sub(t, ZX_Z_mul(T, leading_term(t))); } /* f a product of Phi_n, all n odd; deg f > 1. Is it irreducible ? */ static long BD_odd_iscyclo(GEN f) { pari_sp av, lim; long d, e, n, bound; GEN t; f = RgX_deflate_max(f, &e); av = avma; lim = stack_lim(av,1); /* 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 */ d = degpol(f); /* = phi(n) */ /* Let e > 0, g multiplicative such that g(p) = p / (p-1)^(1+e) < 1 iff p < (p-1)^(1+e) For all squarefree odd n, we have g(n) < C, hence n < C phi(n)^(1+e), where C = \prod_{p odd | p > (p-1)^(1+e)} g(p) For e = 1/10, we obtain p = 3, 5 and C < 1.523 For e = 1/100, we obtain p = 3, 5, ..., 29 and C < 2.573 In fact, for n <= 10^7 odd & squarefree, we have n < 2.92 * phi(n) By the above, n<10^7 covers all d <= (10^7/2.573)^(1/(1+1/100)) < 3344391. */ if (d <= 3344391) bound = (long)(2.92 * d); else bound = (long)(2.573 * pow(d,1.01)); /* IF f = Phi_n, n squarefree odd, then n <= bound */ t = monomial(gen_1, d-1, varn(f)); for (n = d; n <= bound; n++) { 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(DEBUGMEM>1) pari_warn(warnmem,"BD_odd_iscyclo"); t = gerepilecopy(av, t); } } if (n > bound || eulerphiu(n) != (ulong)d) return 0; if (e > 1) return (ucoprime_part(e, n) == 1)? e * n : 0; return n; } /* Checks if f, monic squarefree ZX with |constant coeff| = 1, is a cyclotomic * polynomial. Returns n if f = Phi_n, and 0 otherwise */ static long BD_iscyclo(GEN f) { pari_sp av = avma; GEN f2, fn, f1; if (degpol(f) == 1) return isint1(gel(f,2))? 2: 1; f1 = ZX_graeffe(f); /* f = product of Phi_n, n odd */ if (ZX_equal(f, f1)) { avma = av; return BD_odd_iscyclo(f); } fn = ZX_unscale(f, gen_m1); /* f(-x) */ /* f = product of Phi_n, n = 2 mod 4 */ if (ZX_equal(f1, fn)) return 2*BD_odd_iscyclo(fn); if (issquareall(f1, &f2)) { GEN lt = leading_term(f2); long c; if (signe(lt) < 0) f2 = ZX_neg(f2); c = BD_iscyclo(f2); return odd(c)? 0: 2*c; } avma = av; return 0; } long poliscyclo(GEN f) { pari_sp av = avma; long d = degpol(f); if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", 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; if (degpol(ZX_gcd(f, ZX_deriv(f)))) { avma = av; return 0; } return BD_iscyclo(f); } long poliscycloprod(GEN f) { pari_sp av = avma; long i, d = degpol(f); if (typ(f) != t_POL) pari_err_TYPE("poliscycloprod",f); if (!RgX_is_ZX(f)) return 0; if (!equali1(leading_term(f)) || !is_pm1(constant_term(f))) return 0; if (d < 2) return (d == 1); if ( degpol(ZX_gcd_all(f, ZX_deriv(f), &f)) ) { d = degpol(f); if (d == 1) return 1; } f = BD(f); if (!f) return 0; for (i = lg(f)-1; i; i--) d -= degpol(gel(f,i)); avma = av; return d == 0; } pari-2.7.5/src/basemath/alglin1.c0000644000175000017500000031005412526647431015171 0ustar billbill/* Copyright (C) 2000, 2012 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. */ /********************************************************************/ /** **/ /** LINEAR ALGEBRA **/ /** (first part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* GEREPILE */ /* */ /*******************************************************************/ static void gerepile_mat(pari_sp av, pari_sp tetpil, GEN x, long k, long m, long n, long t) { pari_sp A; long u, i; size_t dec; (void)gerepile(av,tetpil,NULL); dec = av-tetpil; for (u=t+1; u<=m; u++) { A = (pari_sp)coeff(x,u,k); if (A < av && A >= bot) coeff(x,u,k) += dec; } for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) { A = (pari_sp)coeff(x,u,i); if (A < av && A >= bot) coeff(x,u,i) += dec; } } static void gen_gerepile_gauss_ker(GEN x, long k, long t, pari_sp av, void *E, GEN (*copy)(void*, GEN)) { pari_sp tetpil = avma; long u,i, n = lg(x)-1, m = n? nbrows(x): 0; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) gcoeff(x,u,k) = copy(E,gcoeff(x,u,k)); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) gcoeff(x,u,i) = copy(E,gcoeff(x,u,i)); gerepile_mat(av,tetpil,x,k,m,n,t); } /* special gerepile for huge matrices */ #define COPY(x) {\ GEN _t = (x); if (!is_universal_constant(_t)) x = gcopy(_t); \ } INLINE GEN _copy(void *E, GEN x) { (void) E; COPY(x); return x; } static void gerepile_gauss_ker(GEN x, long k, long t, pari_sp av) { 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; long u,i, n = lg(x)-1, m = n? nbrows(x): 0; size_t dec; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) if (u==j || !c[u]) COPY(gcoeff(x,u,k)); for (u=1; u<=m; u++) if (u==j || !c[u]) for (i=k+1; i<=n; i++) COPY(gcoeff(x,u,i)); (void)gerepile(av,tetpil,NULL); dec = av-tetpil; for (u=t+1; u<=m; u++) if (u==j || !c[u]) { A=(pari_sp)coeff(x,u,k); if (A=bot) coeff(x,u,k)+=dec; } for (u=1; u<=m; u++) if (u==j || !c[u]) for (i=k+1; i<=n; i++) { A=(pari_sp)coeff(x,u,i); if (A=bot) coeff(x,u,i)+=dec; } } /*******************************************************************/ /* */ /* GENERIC */ /* */ /*******************************************************************/ GEN gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff) { pari_sp av0 = avma, av, lim, tetpil; GEN y, c, d; long i, j, k, r, t, n, m; n=lg(x)-1; if (!n) return cgetg(1,t_MAT); m=nbrows(x); r=0; x = RgM_shallowcopy(x); c = zero_zv(m); d=new_chunk(n+1); av=avma; lim=stack_lim(av,1); for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { gcoeff(x,j,k) = ff->red(E, gcoeff(x,j,k)); if (!ff->equal0(gcoeff(x,j,k))) break; } if (j>m) { if (deplin) { GEN c = cgetg(n+1, t_COL), g0 = ff->s(E,0), g1=ff->s(E,1); for (i=1; ired(E, gcoeff(x,d[i],k)); gel(c,k) = g1; for (i=k+1; i<=n; i++) gel(c,i) = g0; return gerepileupto(av0, c); } r++; d[k]=0; for(j=1; jneg(E,ff->inv(E,gcoeff(x,j,k))); c[j] = k; d[k] = j; gcoeff(x,j,k) = ff->s(E,-1); for (i=k+1; i<=n; i++) gcoeff(x,j,i) = ff->red(E,ff->mul(E,piv,gcoeff(x,j,i))); for (t=1; t<=m; t++) { if (t==j) continue; piv = ff->red(E,gcoeff(x,t,k)); if (ff->equal0(piv)) continue; 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))) gen_gerepile_gauss_ker(x,k,t,av,E,ff->red); } } } if (deplin) { avma = av0; return NULL; } tetpil=avma; y=cgetg(r+1,t_MAT); for (j=k=1; j<=r; j++,k++) { GEN C = cgetg(n+1,t_COL); GEN g0 = ff->s(E,0), g1 = ff->s(E,1); gel(y,j) = C; while (d[k]) k++; for (i=1; ired(E,p1); gunclone(p1); } else gel(C,i) = g0; gel(C,k) = g1; for (i=k+1; i<=n; i++) gel(C,i) = g0; } return gerepile(av0,tetpil,y); } GEN gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff) { pari_sp av, lim; GEN c, d; long i, j, k, r, t, m, n = lg(x)-1; if (!n) { *rr = 0; return NULL; } m=nbrows(x); r=0; d = cgetg(n+1, t_VECSMALL); x = RgM_shallowcopy(x); c = zero_zv(m); av=avma; lim=stack_lim(av,1); for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { gcoeff(x,j,k) = ff->red(E,gcoeff(x,j,k)); if (!ff->equal0(gcoeff(x,j,k))) break; } if (j>m) { r++; d[k]=0; } else { GEN piv = ff->neg(E,ff->inv(E,gcoeff(x,j,k))); GEN g0 = ff->s(E,0); c[j] = k; d[k] = j; for (i=k+1; i<=n; i++) gcoeff(x,j,i) = ff->red(E,ff->mul(E,piv,gcoeff(x,j,i))); for (t=1; t<=m; t++) { if (c[t]) continue; /* already a pivot on that line */ piv = ff->red(E,gcoeff(x,t,k)); if (ff->equal0(piv)) continue; 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))) gerepile_gauss(x,k,t,av,j,c); } for (i=k; i<=n; i++) gcoeff(x,j,i) = g0; /* dummy */ } } *rr = r; avma = (pari_sp)d; return d; } GEN gen_det(GEN a, void *E, const struct bb_field *ff) { pari_sp av = avma, lim = stack_lim(av,1); long i,j,k, s = 1, nbco = lg(a)-1; GEN q, x = ff->s(E,1); a = RgM_shallowcopy(a); for (i=1; ired(E,gcoeff(a,k,i)); if (!ff->equal0(gcoeff(a,k,i))) break; } if (k > nbco) return gerepileupto(av, gcoeff(a,i,i)); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); s = -s; } q = gcoeff(a,i,i); x = ff->red(E,ff->mul(E,x,q)); q = ff->inv(E,q); for (k=i+1; k<=nbco; k++) { GEN m = ff->red(E,gcoeff(a,i,k)); if (ff->equal0(m)) continue; m = ff->neg(E, ff->mul(E,m, q)); 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(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,4, &a,&x,&q,&m); } } } } if (s < 0) x = ff->neg(E,x); return gerepileupto(av, ff->red(E,ff->mul(E, x, gcoeff(a,nbco,nbco)))); } INLINE void _gen_addmul(GEN b, long k, long i, GEN m, void *E, const struct bb_field *ff) { gel(b,i) = ff->red(E,gel(b,i)); gel(b,k) = ff->add(E,gel(b,k), ff->mul(E,m, gel(b,i))); } static GEN _gen_get_col(GEN a, GEN b, long li, void *E, const struct bb_field *ff) { GEN u = cgetg(li+1,t_COL); pari_sp av = avma; long i, j; gel(u,li) = gerepileupto(av, ff->red(E,ff->mul(E,gel(b,li), gcoeff(a,li,li)))); for (i=li-1; i>0; i--) { pari_sp av = avma; GEN m = gel(b,i); for (j=i+1; j<=li; j++) m = ff->add(E,m, ff->neg(E,ff->mul(E,gcoeff(a,i,j), gel(u,j)))); m = ff->red(E, m); gel(u,i) = gerepileupto(av, ff->red(E,ff->mul(E,m, gcoeff(a,i,i)))); } return u; } GEN 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); a = RgM_shallowcopy(a); b = RgM_shallowcopy(b); aco = lg(a)-1; bco = lg(b)-1; li = nbrows(a); for (i=1; i<=aco; i++) { GEN invpiv; for (k = i; k <= li; k++) { GEN piv = ff->red(E,gcoeff(a,k,i)); if (!ff->equal0(piv)) { gcoeff(a,k,i) = ff->inv(E,piv); break; } gcoeff(a,k,i) = g0; } /* found a pivot on line k */ if (k > li) return NULL; if (k != i) { /* swap lines so that k = i */ for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } if (i == aco) break; invpiv = gcoeff(a,i,i); /* 1/piv mod p */ for (k=i+1; k<=li; k++) { GEN m = ff->red(E,gcoeff(a,k,i)); gcoeff(a,k,i) = g0; if (ff->equal0(m)) continue; m = ff->red(E,ff->neg(E,ff->mul(E,m, invpiv))); 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(DEBUGMEM>1) pari_warn(warnmem,"gen_Gauss. i=%ld",i); gerepileall(av,2, &a,&b); } } if(DEBUGLEVEL>4) err_printf("Solving the triangular system\n"); u = cgetg(bco+1,t_MAT); for (j=1; j<=bco; j++) gel(u,j) = _gen_get_col(a, gel(b,j), aco, E, ff); return u; } /* compatible t_MAT * t_COL, lgA = lg(A) = lg(B) > 1, l = lgcols(A) */ static GEN gen_matcolmul_i(GEN A, GEN B, ulong lgA, ulong l, void *E, const struct bb_field *ff) { GEN C = cgetg(l, t_COL); ulong i; for (i = 1; i < l; i++) { pari_sp av = avma; GEN e = ff->mul(E, gcoeff(A, i, 1), gel(B, 1)); ulong k; for(k = 2; k < lgA; k++) e = ff->add(E, e, ff->mul(E, gcoeff(A, i, k), gel(B, k))); gel(C, i) = gerepileupto(av, ff->red(E, e)); } return C; } GEN gen_matcolmul(GEN A, GEN B, void *E, const struct bb_field *ff) { ulong lgA = lg(A); if (lgA != lg(B)) pari_err_OP("operation 'gen_matcolmul'", A, B); if (lgA == 1) return cgetg(1, t_COL); return gen_matcolmul_i(A, B, lgA, lgcols(A), E, ff); } GEN gen_matmul(GEN A, GEN B, void *E, const struct bb_field *ff) { ulong j, l, lgA, lgB = lg(B); GEN C; if (lgB == 1) return cgetg(1, t_MAT); lgA = lg(A); if (lgA != (ulong)lgcols(B)) pari_err_OP("operation 'gen_matmul'", A, B); if (lgA == 1) return zeromat(0, lgB - 1); l = lgcols(A); C = cgetg(lgB, t_MAT); for(j = 1; j < lgB; j++) gel(C, j) = gen_matcolmul_i(A, gel(B, j), lgA, l, E, ff); return C; } static GEN image_from_pivot(GEN x, GEN d, long r) { GEN y; long j, k; if (!d) return gcopy(x); /* d left on stack for efficiency */ r = lg(x)-1 - r; /* = dim Im(x) */ y = cgetg(r+1,t_MAT); for (j=k=1; j<=r; k++) if (d[k]) gel(y,j++) = gcopy(gel(x,k)); return y; } /*******************************************************************/ /* */ /* LINEAR ALGEBRA MODULO P */ /* */ /*******************************************************************/ static long F2v_find_nonzero(GEN x0, GEN mask0, long l, long m) { ulong *x = (ulong *)x0+2, *mask = (ulong *)mask0+2, e; long i, j; for (i = 0; i < l; i++) { e = *x++ & *mask++; if (e) for (j = 1; ; j++, e >>= 1) if (e & 1uL) return i*BITS_IN_LONG+j; } return m+1; } /* in place, destroy x */ GEN F2m_ker_sp(GEN x, long deplin) { GEN y, c, d; long i, j, k, l, r, m, n; n = lg(x)-1; m = mael(x,1,1); r=0; d = cgetg(n+1, t_VECSMALL); c = zero_F2v(m); l = lg(c)-1; for (i = 2; i <= l; i++) c[i] = -1; if (remsBIL(m)) c[l] = (1uL<m) { if (deplin) { GEN c = zero_F2v(n); for (i=1; i m) { if (deplin) { c = cgetg(n+1, t_VECSMALL); for (i=1; i nbco) return ucoeff(a,i,i); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) lswap(ucoeff(a,i,j), ucoeff(a,k,j)); s = -s; } q = ucoeff(a,i,i); if (x & HIGHMASK) x %= p; x *= q; q = Fl_inv(q,p); for (k=i+1; k<=nbco; k++) { ulong m = ucoeff(a,i,k) % p; if (!m) continue; m = p - ((m*q)%p); for (j=i+1; j<=nbco; j++) { ulong c = ucoeff(a,j,k); if (c & HIGHMASK) c %= p; ucoeff(a,j,k) = c + m*ucoeff(a,j,i); } } } if (x & HIGHMASK) x %= p; q = ucoeff(a,nbco,nbco); if (q & HIGHMASK) q %= p; x = (x*q) % p; if (s < 0 && x) x = p - x; return x; } /* in place, destroy a */ ulong Flm_det_sp(GEN a, ulong p) { long i,j,k, s = 1, nbco = lg(a)-1; ulong q, x = 1; if (SMALL_ULONG(p)) return Flm_det_sp_OK(a, nbco, p); for (i=1; i nbco) return ucoeff(a,i,i); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) lswap(ucoeff(a,i,j), ucoeff(a,k,j)); s = -s; } q = ucoeff(a,i,i); x = Fl_mul(x,q,p); q = Fl_inv(q,p); for (k=i+1; k<=nbco; k++) { ulong m = ucoeff(a,i,k); if (!m) continue; m = Fl_mul(m, q, p); for (j=i+1; j<=nbco; j++) ucoeff(a,j,k) = Fl_sub(ucoeff(a,j,k), Fl_mul(m,ucoeff(a,j,i), p), p); } } if (s < 0) x = Fl_neg(x, p); return Fl_mul(x, ucoeff(a,nbco,nbco), p); } ulong Flm_det(GEN x, ulong p) { pari_sp av = avma; ulong d = Flm_det_sp(Flm_copy(x), p); avma = av; return d; } static GEN FpM_init(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = (ulong)p[2]; return (*pp==2)? ZM_to_F2m(a): ZM_to_Flm(a, *pp); } *pp = 0; return a; } GEN RgM_Fp_init(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = (ulong)p[2]; return (*pp==2)? RgM_to_F2m(a): RgM_to_Flm(a, *pp); } *pp = 0; return RgM_to_FpM(a,p); } static GEN FpM_det_gen(GEN a, GEN p) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_det(a, E, S); } GEN FpM_det(GEN a, GEN p) { pari_sp av = avma; ulong pp, d; a = FpM_init(a, p, &pp); switch(pp) { case 0: return FpM_det_gen(a, p); case 2: d = F2m_det_sp(a); break; default:d = Flm_det_sp(a,pp); break; } avma = av; return utoi(d); } /* Destroy x */ static GEN F2m_gauss_pivot(GEN x, long *rr) { GEN c, d; long i, j, k, l, r, m, n; n = lg(x)-1; if (!n) { *rr=0; return NULL; } m = mael(x,1,1); r=0; d = cgetg(n+1, t_VECSMALL); c = zero_F2v(m); l = lg(c)-1; for (i = 2; i <= l; i++) c[i] = -1; if (remsBIL(m)) c[l] = (1uL<m) { r++; d[k] = 0; } else { F2v_clear(c,j); d[k] = j; for (i=k+1; i<=n; i++) { GEN xi = gel(x,i); if (F2v_coeff(xi,j)) F2v_add_inplace(xi, xk); } } } *rr = r; avma = (pari_sp)d; return d; } /* Destroy x */ static GEN Flm_gauss_pivot(GEN x, ulong p, long *rr) { GEN c,d; long i,j,k,r,t,n,m; n=lg(x)-1; if (!n) { *rr=0; return NULL; } m=nbrows(x); r=0; d=cgetg(n+1,t_VECSMALL); c = zero_zv(m); for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { ucoeff(x,j,k) %= p; if (ucoeff(x,j,k)) break; } if (j>m) { r++; d[k]=0; } else { ulong piv = p - Fl_inv(ucoeff(x,j,k), p); c[j]=k; d[k]=j; for (i=k+1; i<=n; i++) ucoeff(x,j,i) = Fl_mul(piv, ucoeff(x,j,i), p); for (t=1; t<=m; t++) if (!c[t]) /* no pivot on that line yet */ { piv = ucoeff(x,t,k); if (piv) { ucoeff(x,t,k) = 0; for (i=k+1; i<=n; i++) ucoeff(x,t,i) = Fl_add(ucoeff(x,t,i), Fl_mul(piv,ucoeff(x,j,i),p),p); } } for (i=k; i<=n; i++) ucoeff(x,j,i) = 0; /* dummy */ } } *rr = r; avma = (pari_sp)d; return d; } static GEN FpM_gauss_pivot_gen(GEN x, GEN p, long *rr) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_Gauss_pivot(x, rr, E, S); } static GEN FpM_gauss_pivot(GEN x, GEN p, long *rr) { ulong pp; if (lg(x)==1) { *rr = 0; return NULL; } x = FpM_init(x, p, &pp); switch(pp) { case 0: return FpM_gauss_pivot_gen(x, p, rr); case 2: return F2m_gauss_pivot(x, rr); default:return Flm_gauss_pivot(x, pp, rr); } } GEN FpM_image(GEN x, GEN p) { long r; GEN d = FpM_gauss_pivot(x,p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN Flm_image(GEN x, ulong p) { long r; GEN d = Flm_gauss_pivot(Flm_copy(x),p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN F2m_image(GEN x) { long r; GEN d = F2m_gauss_pivot(F2m_copy(x),&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } long FpM_rank(GEN x, GEN p) { pari_sp av = avma; long r; (void)FpM_gauss_pivot(x,p,&r); avma = av; return lg(x)-1 - r; } long Flm_rank(GEN x, ulong p) { pari_sp av = avma; long r; (void)Flm_gauss_pivot(Flm_copy(x),p,&r); avma = av; return lg(x)-1 - r; } long F2m_rank(GEN x) { pari_sp av = avma; long r; (void)F2m_gauss_pivot(F2m_copy(x),&r); avma = av; return lg(x)-1 - r; } static GEN FlxqM_gauss_pivot(GEN x, GEN T, ulong p, long *rr) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_Gauss_pivot(x, rr, E, S); } GEN FlxqM_image(GEN x, GEN T, ulong p) { long r; GEN d = FlxqM_gauss_pivot(x,T,p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } long FlxqM_rank(GEN x, GEN T, ulong p) { pari_sp av = avma; long r; (void)FlxqM_gauss_pivot(x,T,p,&r); avma = av; return lg(x)-1 - r; } GEN FlxqM_det(GEN a, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_det(a, E, S); } GEN FlxqM_FlxqC_mul(GEN A, GEN B, GEN T, unsigned long p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_matcolmul(A, B, E, ff); } 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); return gen_matmul(A, B, E, ff); } GEN F2xqM_det(GEN a, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_det(a, E, S); } static GEN F2xqM_gauss_gen(GEN a, GEN b, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_Gauss(a, b, E, S); } 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 (!u) { avma = av; return NULL; } return gerepilecopy(av, u); } GEN F2xqM_F2xqC_mul(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_matcolmul(A, B, E, ff); } GEN F2xqM_mul(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_matmul(A, B, E, ff); } static GEN FqM_gauss_pivot_gen(GEN x, GEN T, GEN p, long *rr) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_Gauss_pivot(x, rr, E, S); } static GEN FqM_gauss_pivot(GEN x, GEN T, GEN p, long *rr) { if (lg(x)==1) { *rr = 0; return NULL; } if (!T) return FpM_gauss_pivot(x, p, rr); if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = (ulong)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; } return FqM_gauss_pivot_gen(x, T, p, rr); } GEN FqM_image(GEN x, GEN T, GEN p) { long r; GEN d = FqM_gauss_pivot(x,T,p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } long FqM_rank(GEN x, GEN T, GEN p) { pari_sp av = avma; long r; (void)FqM_gauss_pivot(x,T,p,&r); avma = av; return lg(x)-1 - r; } GEN FqM_det(GEN x, GEN T, GEN p) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_det(x, E, S); } GEN FqM_FqC_mul(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); return gen_matcolmul(A, B, E, ff); } GEN FqM_mul(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); return gen_matmul(A, B, E, ff); } static GEN FpM_ker_gen(GEN x, GEN p, long deplin) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_ker(x, deplin, E, S); } static GEN FpM_ker_i(GEN x, GEN p, long deplin) { pari_sp av = avma; ulong pp; GEN y; if (lg(x)==1) return cgetg(1,t_MAT); x = FpM_init(x, p, &pp); switch(pp) { case 0: return FpM_ker_gen(x,p,deplin); case 2: y = F2m_ker_sp(x, deplin); if (!y) return y; y = deplin? F2c_to_ZC(y): F2m_to_ZM(y); return gerepileupto(av, y); default: y = Flm_ker_sp(x, pp, deplin); if (!y) return y; y = deplin? Flc_to_ZC(y): Flm_to_ZM(y); return gerepileupto(av, y); } } GEN FpM_ker(GEN x, GEN p) { return FpM_ker_i(x,p,0); } GEN FpM_deplin(GEN x, GEN p) { return FpM_ker_i(x,p,1); } static GEN FqM_ker_gen(GEN x, GEN T, GEN p, long deplin) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_ker(x,deplin,E,S); } static GEN FqM_ker_i(GEN x, GEN T, GEN p, long deplin) { if (!T) return FpM_ker_i(x,p,deplin); if (lg(x)==1) return cgetg(1,t_MAT); if (lgefint(p)==3) { pari_sp ltop=avma; ulong l= p[2]; GEN Ml = FqM_to_FlxM(x, T, p); GEN Tl = ZXT_to_FlxT(T,l); GEN p1 = FlxM_to_ZXM(FlxqM_ker(Ml,Tl,l)); return gerepileupto(ltop,p1); } return FqM_ker_gen(x, T, p, deplin); } GEN FqM_ker(GEN x, GEN T, GEN p) { return FqM_ker_i(x,T,p,0); } GEN FqM_deplin(GEN x, GEN T, GEN p) { return FqM_ker_i(x,T,p,1); } static GEN FlxqM_ker_i(GEN x, GEN T, ulong p, long deplin) { const struct bb_field *ff; void *E; if (lg(x)==1) return cgetg(1,t_MAT); ff=get_Flxq_field(&E,T,p); return gen_ker(x,deplin, E, ff); } GEN FlxqM_ker(GEN x, GEN T, ulong p) { return FlxqM_ker_i(x, T, p, 0); } static GEN F2xqM_ker_i(GEN x, GEN T, long deplin) { const struct bb_field *ff; void *E; if (lg(x)==1) return cgetg(1,t_MAT); ff = get_F2xq_field(&E,T); return gen_ker(x,deplin, E, ff); } GEN F2xqM_ker(GEN x, GEN T) { return F2xqM_ker_i(x, T, 0); } static GEN F2xqM_gauss_pivot(GEN x, GEN T, long *rr) { void *E; const struct bb_field *S = get_F2xq_field(&E,T); return gen_Gauss_pivot(x, rr, E, S); } GEN F2xqM_image(GEN x, GEN T) { long r; GEN d = F2xqM_gauss_pivot(x,T,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } long F2xqM_rank(GEN x, GEN T) { pari_sp av = avma; long r; (void)F2xqM_gauss_pivot(x,T,&r); avma = av; return lg(x)-1 - r; } /*******************************************************************/ /* */ /* Solve A*X=B (Gauss pivot) */ /* */ /*******************************************************************/ /* x ~ 0 compared to reference y */ int approx_0(GEN x, GEN y) { long tx = typ(x); if (tx == t_COMPLEX) return approx_0(gel(x,1), y) && approx_0(gel(x,2), y); return gequal0(x) || (tx == t_REAL && gexpo(y) - gexpo(x) > bit_prec(x)); } /* x a column, x0 same column in the original input matrix (for reference), * c list of pivots so far */ static long gauss_get_pivot_max(GEN X, GEN X0, long ix, GEN c) { GEN p, r, x = gel(X,ix), x0 = gel(X0,ix); long i, k = 0, ex = - (long)HIGHEXPOBIT, lx = lg(x); if (c) { for (i=1; i ex) { ex = e; k = i; } } } else { for (i=ix; i ex) { ex = e; k = i; } } } if (!k) return lx; p = gel(x,k); r = gel(x0,k); if (isrationalzero(r)) r = x0; return approx_0(p, r)? lx: k; } static long gauss_get_pivot_padic(GEN X, GEN p, long ix, GEN c) { GEN x = gel(X, ix); long i, k = 0, ex = (long)HIGHVALPBIT, lx = lg(x); if (c) { for (i=1; i0; i--) { pari_sp av = avma; GEN m = gel(b,i); for (j=i+1; j<=li; j++) m = gsub(m, gmul(gcoeff(a,i,j), gel(u,j))); gel(u,i) = gerepileupto(av, gdiv(m, gcoeff(a,i,i))); } return u; } /* assume 0 <= a[i,j] < p */ static GEN Fl_get_col_OK(GEN a, GEN b, long li, ulong p) { GEN u = cgetg(li+1,t_VECSMALL); ulong m = uel(b,li) % p; long i,j; uel(u,li) = (m * ucoeff(a,li,li)) % p; for (i = li-1; i > 0; i--) { m = p - uel(b,i)%p; for (j = i+1; j <= li; j++) { if (m & HIGHBIT) m %= p; m += ucoeff(a,i,j) * uel(u,j); /* 0 <= u[j] < p */ } m %= p; if (m) m = ((p-m) * ucoeff(a,i,i)) % p; u[i] = m; } return u; } 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; long i,j; 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); if (m) m = Fl_mul(m, ucoeff(a,i,i), p); u[i] = m; } return u; } /* bk -= m * bi */ static void _submul(GEN b, long k, long i, GEN m) { gel(b,k) = gsub(gel(b,k), gmul(m, gel(b,i))); } static int init_gauss(GEN a, GEN *b, long *aco, long *li, int *iscol) { *iscol = *b ? (typ(*b) == t_COL): 0; *aco = lg(a) - 1; if (!*aco) /* a empty */ { if (*b && lg(*b) != 1) pari_err_DIM("gauss"); *li = 0; return 0; } *li = nbrows(a); if (*li < *aco) pari_err_INV("gauss [no left inverse]", a); if (*b) { if (*li != *aco) pari_err_DIM("gauss"); switch(typ(*b)) { case t_MAT: if (lg(*b) == 1) return 0; *b = RgM_shallowcopy(*b); break; case t_COL: *b = mkmat( leafcopy(*b) ); break; default: pari_err_TYPE("gauss",*b); } if (nbrows(*b) != *li) pari_err_DIM("gauss"); } else *b = matid(*li); return 1; } static int is_modular_solve(GEN a, GEN b, GEN *u) { GEN p = NULL; ulong pp; if (!RgM_is_FpM(a, &p) || !p) return 0; if (!b) { a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: a = FpM_inv(a,p); if (a) a = FpM_to_mod(a, p); break; case 2: a = F2m_inv(a); if (a) a = F2m_to_mod(a); break; default: a = Flm_inv(a,pp); if (a) a = Flm_to_mod(a, pp); } } else switch(typ(b)) { case t_COL: if (!RgV_is_FpV(b, &p)) return 0; a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: b = RgC_to_FpC(b, p); a = FpM_FpC_gauss(a,b,p); if (a) a = FpC_to_mod(a, p); break; case 2: b = RgV_to_F2v(b); a = F2m_F2c_gauss(a,b); if (a) a = F2c_to_mod(a); break; default: b = RgC_to_Flc(b, pp); a = Flm_Flc_gauss(a,b,pp); if (a) a = Flc_to_mod(a, pp); break; } break; case t_MAT: if (!RgM_is_FpM(b, &p)) return 0; a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: b = RgM_to_FpM(b, p); a = FpM_gauss(a,b,p); if (a) a = FpM_to_mod(a, p); break; case 2: b = RgM_to_F2m(b); a = F2m_gauss(a,b); if (a) a = F2m_to_mod(a); break; default: b = RgM_to_Flm(b, pp); a = Flm_gauss(a,b,pp); if (a) a = Flm_to_mod(a, pp); break; } break; default: return 0; } *u = a; return 1; } /* Gaussan Elimination. If a is square, return a^(-1)*b; * if a has more rows than columns and b is NULL, return c such that c a = Id. * a is a (not necessarily square) matrix * b is a matrix or column vector, NULL meaning: take the identity matrix, * effectively returning the inverse of a * If a and b are empty, the result is the empty matrix. * * li: number of rows of a and b * aco: number of columns of a * bco: number of columns of b (if matrix) */ GEN RgM_solve(GEN a, GEN b) { pari_sp av = avma, lim = stack_lim(av,1); long i, j, k, li, bco, aco; int iscol; pivot_fun pivot; GEN p, u, data; if (is_modular_solve(a,b,&u)) return gerepileupto(av, u); avma = av; if (lg(a)-1 == 2 && nbrows(a) == 2) { /* 2x2 matrix, start by inverting a */ GEN detinv = ginv(det (a)); GEN ainv = cgetg(3, t_MAT); for (j = 1; j <= 2; j++) gel (ainv, j) = cgetg (3, t_COL); gcoeff(ainv, 1, 1) = gcoeff(a, 2, 2); gcoeff(ainv, 2, 2) = gcoeff(a, 1, 1); gcoeff(ainv, 1, 2) = gneg(gcoeff (a, 1, 2)); gcoeff(ainv, 2, 1) = gneg(gcoeff (a, 2, 1)); ainv = gmul(ainv, detinv); if (b != NULL) ainv = gmul(ainv, b); return gerepileupto(av, ainv); } if (!init_gauss(a, &b, &aco, &li, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); pivot = get_pivot_fun(a, a, &data); a = RgM_shallowcopy(a); bco = lg(b)-1; if(DEBUGLEVEL>4) err_printf("Entering gauss\n"); p = NULL; /* gcc -Wall */ for (i=1; i<=aco; i++) { /* k is the line where we find the pivot */ k = pivot(a, data, i, NULL); if (k > li) return NULL; if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } p = gcoeff(a,i,i); if (i == aco) break; for (k=i+1; k<=li; k++) { GEN m = gcoeff(a,k,i); if (!gequal0(m)) { m = gdiv(m,p); for (j=i+1; j<=aco; j++) _submul(gel(a,j),k,i,m); for (j=1; j<=bco; j++) _submul(gel(b,j),k,i,m); } } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"gauss. i=%ld",i); gerepileall(av,2, &a,&b); } } if(DEBUGLEVEL>4) err_printf("Solving the triangular system\n"); u = cgetg(bco+1,t_MAT); for (j=1; j<=bco; j++) gel(u,j) = get_col(a,gel(b,j),p,aco); return gerepilecopy(av, iscol? gel(u,1): u); } /* assume dim A >= 1, A invertible + upper triangular */ static GEN RgM_inv_upper_ind(GEN A, long index) { long n = lg(A)-1, i = index, j; GEN u = zerocol(n); gel(u,i) = ginv(gcoeff(A,i,i)); for (i--; i>0; i--) { pari_sp av = avma; GEN m = gneg(gmul(gcoeff(A,i,i+1),gel(u,i+1))); /* j = i+1 */ for (j=i+2; j<=n; j++) m = gsub(m, gmul(gcoeff(A,i,j),gel(u,j))); gel(u,i) = gerepileupto(av, gdiv(m, gcoeff(A,i,i))); } return u; } GEN RgM_inv_upper(GEN A) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = RgM_inv_upper_ind(A, i); return B; } /* assume dim A >= 1, A invertible + upper triangular, 1s on diagonal */ static GEN FpM_inv_upper_1_ind(GEN A, long index, GEN p) { long n = lg(A)-1, i = index, j; GEN u = zerocol(n); gel(u,i) = gen_1; for (i--; i>0; i--) { pari_sp av = avma; GEN m = negi(mulii(gcoeff(A,i,i+1),gel(u,i+1))); /* j = i+1 */ for (j=i+2; j<=n; j++) m = subii(m, mulii(gcoeff(A,i,j),gel(u,j))); gel(u,i) = gerepileuptoint(av, modii(m,p)); } return u; } static GEN FpM_inv_upper_1(GEN A, GEN p) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = FpM_inv_upper_1_ind(A, i, p); return B; } /* assume dim A >= 1, A invertible + upper triangular, 1s on diagonal, * reduced mod p */ static GEN Flm_inv_upper_1_ind(GEN A, long index, ulong p) { long n = lg(A)-1, i = index, j; GEN u = const_vecsmall(n, 0); u[i] = 1; if (SMALL_ULONG(p)) for (i--; i>0; i--) { ulong m = ucoeff(A,i,i+1) * uel(u,i+1); /* j = i+1 */ for (j=i+2; j<=n; j++) { if (m & HIGHMASK) m %= p; m += ucoeff(A,i,j) * uel(u,j); } u[i] = Fl_neg(m % p, p); } else for (i--; i>0; i--) { ulong m = Fl_mul(ucoeff(A,i,i+1),uel(u,i+1), p); /* j = i+1 */ for (j=i+2; j<=n; j++) m = Fl_add(m, Fl_mul(ucoeff(A,i,j),uel(u,j),p), p); u[i] = Fl_neg(m, p); } return u; } static GEN F2m_inv_upper_1_ind(GEN A, long index) { pari_sp av = avma; long n = lg(A)-1, i = index, j; GEN u = const_vecsmall(n, 0); u[i] = 1; for (i--; i>0; i--) { ulong m = F2m_coeff(A,i,i+1) & uel(u,i+1); /* j = i+1 */ for (j=i+2; j<=n; j++) m ^= F2m_coeff(A,i,j) & uel(u,j); u[i] = m & 1; } return gerepileuptoleaf(av, Flv_to_F2v(u)); } static GEN Flm_inv_upper_1(GEN A, ulong p) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = Flm_inv_upper_1_ind(A, i, p); return B; } static GEN F2m_inv_upper_1(GEN A) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = F2m_inv_upper_1_ind(A, i); return B; } static GEN split_realimag_col(GEN z, long r1, long r2) { long i, ru = r1+r2; GEN x = cgetg(ru+r2+1,t_COL), y = x + r2; for (i=1; i<=r1; i++) { GEN a = gel(z,i); if (typ(a) == t_COMPLEX) a = gel(a,1); /* paranoia: a should be real */ gel(x,i) = a; } for ( ; i<=ru; i++) { GEN b, a = gel(z,i); if (typ(a) == t_COMPLEX) { b = gel(a,2); a = gel(a,1); } else b = gen_0; gel(x,i) = a; gel(y,i) = b; } return x; } GEN split_realimag(GEN x, long r1, long r2) { long i,l; GEN y; if (typ(x) == t_COL) return split_realimag_col(x,r1,r2); y = cgetg_copy(x, &l); for (i=1; i li) return NULL; d[k] = i; /* Clear k-th row but column-wise */ 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); } for (l=1; l<=bco; l++) { GEN al = gel(b,l); if (!F2v_coeff(al,k)) continue; F2v_add_inplace(al,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]); } } return u; } GEN F2m_gauss(GEN a, GEN b) { pari_sp av = avma; if (lg(a) == 1) return cgetg(1,t_MAT); return gerepileupto(av, F2m_gauss_sp(F2m_copy(a), F2m_copy(b))); } GEN F2m_F2c_gauss(GEN a, GEN b) { pari_sp av = avma; GEN z = F2m_gauss(a, mkmat(b)); if (lg(z) == 1) { avma = av; return cgetg(1,t_VECSMALL); } return gerepileuptoleaf(av, gel(z,1)); } GEN 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))); } /* destroy a, b */ static GEN Flm_gauss_sp(GEN a, GEN b, ulong *detp, ulong p) { long i, j, k, li, bco, aco = lg(a)-1, s = 1; const int OK_ulong = SMALL_ULONG(p); ulong det = 1; GEN u; if (!aco) { if (detp) *detp = 1; return cgetg(1,t_MAT); } li = nbrows(a); bco = lg(b)-1; for (i=1; i<=aco; i++) { ulong invpiv; /* Fl_get_col wants 0 <= a[i,j] < p for all i,j */ if (OK_ulong) { for (k = 1; k < i; k++) ucoeff(a,k,i) %= p; for (k = i; k <= li; k++) { ulong piv = ( ucoeff(a,k,i) %= p ); if (piv) { ucoeff(a,k,i) = Fl_inv(piv, p); if (detp) { if (det & HIGHMASK) det %= p; det *= piv; } break; } } } else { for (k = i; k <= li; k++) { ulong piv = ucoeff(a,k,i); if (piv) { ucoeff(a,k,i) = Fl_inv(piv, p); if (detp) det = Fl_mul(det, piv, p); break; } } } /* found a pivot on line k */ if (k > li) return NULL; if (k != i) { /* swap lines so that k = i */ s = -s; for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } if (i == aco) break; invpiv = ucoeff(a,i,i); /* 1/piv mod p */ for (k=i+1; k<=li; k++) { ulong m = ( ucoeff(a,k,i) %= p ); if (!m) continue; m = Fl_mul(m, invpiv, p); if (OK_ulong) { m = p - m; /* = -m */ if (m == 1) { for (j=i+1; j<=aco; j++) _Fl_add_OK(gel(a,j),k,i, p); for (j=1; j<=bco; j++) _Fl_add_OK(gel(b,j),k,i, p); } else { for (j=i+1; j<=aco; j++) _Fl_addmul_OK(gel(a,j),k,i,m, p); for (j=1; j<=bco; j++) _Fl_addmul_OK(gel(b,j),k,i,m, p); } } else { if (m == 1) { for (j=i+1; j<=aco; j++) _Fl_sub(gel(a,j),k,i, p); for (j=1; j<=bco; j++) _Fl_sub(gel(b,j),k,i, p); } else { for (j=i+1; j<=aco; j++) _Fl_submul(gel(a,j),k,i,m, p); for (j=1; j<=bco; j++) _Fl_submul(gel(b,j),k,i,m, p); } } } } if (detp) { det %= p; if (s < 0 && det) det = p - det; *detp = det; } u = cgetg(bco+1,t_MAT); if (OK_ulong) for (j=1; j<=bco; j++) gel(u,j) = Fl_get_col_OK(a,gel(b,j), aco,p); else for (j=1; j<=bco; j++) gel(u,j) = Fl_get_col(a,gel(b,j), aco,p); return u; } GEN Flm_gauss(GEN a, GEN b, ulong p) { return Flm_gauss_sp(RgM_shallowcopy(a), RgM_shallowcopy(b), NULL, p); } static GEN Flm_inv_sp(GEN a, ulong *detp, ulong p) { return Flm_gauss_sp(a, matid_Flm(lg(a)-1), detp, p); } GEN Flm_inv(GEN a, ulong p) { return Flm_inv_sp(RgM_shallowcopy(a), NULL, p); } GEN Flm_Flc_gauss(GEN a, GEN b, ulong p) { pari_sp av = avma; GEN z = Flm_gauss(a, mkmat(b), p); if (lg(z) == 1) { avma = av; return cgetg(1,t_VECSMALL); } return gerepileuptoleaf(av, gel(z,1)); } static GEN FpM_gauss_gen(GEN a, GEN b, GEN p) { void *E; 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) */ static GEN FpM_gauss_i(GEN a, GEN b, GEN p, ulong *pp) { long n = lg(a)-1; a = FpM_init(a,p,pp); switch(*pp) { case 0: if (!b) b = matid(n); return FpM_gauss_gen(a,b,p); case 2: if (b) b = ZM_to_F2m(b); else b = matid_F2m(n); return F2m_gauss_sp(a,b); default: if (b) b = ZM_to_Flm(b, *pp); else b = matid_Flm(n); return Flm_gauss_sp(a,b, NULL, *pp); } } GEN FpM_gauss(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1 || lg(b)==1) return cgetg(1, t_MAT); u = FpM_gauss_i(a, b, p, &pp); if (!u) { avma = av; return NULL; } switch(pp) { case 0: return gerepilecopy(av, u); case 2: u = F2m_to_ZM(u); break; default: u = Flm_to_ZM(u); break; } return gerepileupto(av, u); } GEN FpM_inv(GEN a, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1) return cgetg(1, t_MAT); u = FpM_gauss_i(a, NULL, p, &pp); if (!u) { avma = av; return NULL; } switch(pp) { case 0: return gerepilecopy(av, u); case 2: u = F2m_to_ZM(u); break; default: u = Flm_to_ZM(u); break; } return gerepileupto(av, u); } GEN FpM_FpC_gauss(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1) return cgetg(1, t_COL); u = FpM_gauss_i(a, mkmat(b), p, &pp); if (!u) { avma = av; return NULL; } switch(pp) { case 0: return gerepilecopy(av, gel(u,1)); case 2: u = F2c_to_ZC(gel(u,1)); break; default: u = Flc_to_ZC(gel(u,1)); break; } return gerepileupto(av, u); } static GEN FlxqM_gauss_gen(GEN a, GEN b, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_Gauss(a, b, E, S); } GEN FlxqM_gauss(GEN a, GEN b, GEN T, ulong p) { pari_sp av = avma; long n = lg(a)-1; GEN u; if (!n || lg(b)==1) { avma = av; return cgetg(1, t_MAT); } u = FlxqM_gauss_gen(a, b, T, p); if (!u) { avma = av; return NULL; } return gerepilecopy(av, u); } 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 (!u) { avma = av; return NULL; } return gerepilecopy(av, u); } GEN FlxqM_FlxqC_gauss(GEN a, GEN b, GEN T, ulong p) { pari_sp av = avma; GEN u; if (lg(a) == 1) return cgetg(1, t_COL); u = FlxqM_gauss_gen(a, mkmat(b), T, p); if (!u) { avma = av; return NULL; } return gerepilecopy(av, gel(u,1)); } static GEN FqM_gauss_gen(GEN a, GEN b, GEN T, GEN p) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_Gauss(a,b,E,S); } GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma; GEN u; long n; if (!T) return FpM_gauss(a,b,p); n = lg(a)-1; if (!n || lg(b)==1) return cgetg(1, t_MAT); u = FqM_gauss_gen(a,b,T,p); if (!u) { avma = av; return NULL; } return gerepilecopy(av, u); } GEN 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 (!u) { avma = av; return NULL; } return gerepilecopy(av, u); } GEN FqM_FqC_gauss(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma; GEN u; if (!T) return FpM_FpC_gauss(a,b,p); if (lg(a) == 1) return cgetg(1, t_COL); u = FqM_gauss_gen(a,mkmat(b),T,p); if (!u) { avma = av; return NULL; } return gerepilecopy(av, gel(u,1)); } /* Dixon p-adic lifting algorithm. * Numer. Math. 40, 137-141 (1982), DOI: 10.1007/BF01459082 */ GEN ZM_gauss(GEN a, GEN b0) { pari_sp av = avma, av2; int iscol; long n, ncol, i, m, elim; ulong p; GEN N, C, delta, xb, nb, nmin, res, b = b0; if (!init_gauss(a, &b, &n, &ncol, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); nb = gen_0; ncol = lg(b); for (i = 1; i < ncol; i++) { GEN ni = gnorml2(gel(b, i)); if (cmpii(nb, ni) < 0) nb = ni; } if (!signe(nb)) { avma = av; return gcopy(b0); } delta = gen_1; nmin = nb; for (i = 1; i <= n; i++) { GEN ni = gnorml2(gel(a, i)); if (cmpii(ni, nmin) < 0) { delta = mulii(delta, nmin); nmin = ni; } else delta = mulii(delta, ni); } if (!signe(nmin)) return NULL; elim = expi(delta)+1; av2 = avma; #ifdef LONG_IS_64BIT p = 1000000000000000000; #else p = 1000000000; #endif for(;;) { p = unextprime(p+1); C = Flm_inv(ZM_to_Flm(a, p), p); if (C) break; elim -= expu(p); if (elim < 0) return NULL; avma = av2; } /* N.B. Our delta/lambda are SQUARES of those in the paper * log(delta lambda) / log p, where lambda is 3+sqrt(5) / 2, * whose log is < 1, hence + 1 (to cater for rounding errors) */ m = (long)ceil((rtodbl(logr_abs(itor(delta,LOWDEFAULTPREC))) + 1) / log((double)p)); xb = ZlM_gauss(a, b, p, m, C); N = powuu(p, m); delta = sqrti(delta); if (iscol) res = FpC_ratlift(gel(xb,1), N, delta,delta, NULL); else res = FpM_ratlift(xb, N, delta,delta, NULL); return gerepileupto(av, res); } /* M integral, dM such that M' = dM M^-1 is integral [e.g det(M)]. Return M' */ GEN ZM_inv(GEN M, GEN dM) { pari_sp av2, av = avma, lim = stack_lim(av,1); GEN Hp,q,H; ulong p; long lM = lg(M), stable = 0; int negate = 0; forprime_t S; if (lM == 1) return cgetg(1,t_MAT); /* HACK: include dM = -1 ! */ if (dM && is_pm1(dM)) { /* modular algorithm computes M^{-1}, NOT multiplied by det(M) = -1. * We will correct (negate) at the end. */ if (signe(dM) < 0) negate = 1; dM = gen_1; } init_modular(&S); av2 = avma; H = NULL; while ((p = u_forprime_next(&S))) { ulong dMp; GEN Mp; Mp = ZM_to_Flm(M,p); if (dM == gen_1) Hp = Flm_inv_sp(Mp, NULL, p); else { if (dM) { dMp = umodiu(dM,p); if (!dMp) continue; Hp = Flm_inv_sp(Mp, NULL, p); if (!Hp) pari_err_INV("ZM_inv", Mp); } else { Hp = Flm_inv_sp(Mp, &dMp, p); if (!Hp) continue; } if (dMp != 1) Flm_Fl_mul_inplace(Hp, dMp, p); } if (!H) { H = ZM_init_CRT(Hp, p); q = utoipos(p); } else stable = ZM_incremental_CRT(&H, Hp, &q, p); if (DEBUGLEVEL>5) err_printf("inverse mod %ld (stable=%ld)\n", p,stable); if (stable) {/* DONE ? */ if (dM != gen_1) { if (RgM_isscalar(ZM_mul(M, H), dM)) break; } else { if (ZM_isidentity(ZM_mul(M, H))) break; } } if (low_stack(lim, stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_inv"); gerepileall(av2, 2, &H, &q); } } if (!p) pari_err_OVERFLOW("ZM_inv [ran out of primes]"); if (DEBUGLEVEL>5) err_printf("ZM_inv done\n"); if (negate) return gerepileupto(av, ZM_neg(H)); else return gerepilecopy(av, H); } /* same as above, M rational */ GEN QM_inv(GEN M, GEN dM) { pari_sp av = avma; GEN cM, pM = Q_primitive_part(M, &cM); if (!cM) return ZM_inv(pM,dM); return gerepileupto(av, ZM_inv(pM, gdiv(dM,cM))); } /* x a ZM. Return a multiple of the determinant of the lattice generated by * the columns of x. From Algorithm 2.2.6 in GTM138 */ GEN detint(GEN A) { if (typ(A) != t_MAT) pari_err_TYPE("detint",A); RgM_check_ZM(A, "detint"); return ZM_detmult(A); } GEN ZM_detmult(GEN A) { pari_sp av1, av = avma, lim = stack_lim(av,1); GEN B, c, v, piv; long rg, i, j, k, m, n = lg(A) - 1; if (!n) return gen_1; m = nbrows(A); if (n < m) return gen_0; c = zero_zv(m); av1 = avma; B = zeromatcopy(m,m); v = cgetg(m+1, t_COL); piv = gen_1; rg = 0; for (k=1; k<=n; k++) { GEN pivprec = piv; long t = 0; for (i=1; i<=m; i++) { pari_sp av2 = avma; GEN vi; if (c[i]) continue; vi = mulii(piv, gcoeff(A,i,k)); for (j=1; j<=m; j++) if (c[j]) vi = addii(vi, mulii(gcoeff(B,j,i),gcoeff(A,j,k))); if (!t && signe(vi)) t = i; gel(v,i) = gerepileuptoint(av2, vi); } if (!t) continue; /* at this point c[t] = 0 */ if (++rg >= m) { /* full rank; mostly done */ GEN det = gel(v,t); /* last on stack */ if (++k > n) det = absi(det); else { /* 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); for ( ; k<=n; k++) { det = gcdii(det, ZV_dotproduct(v, gel(A,k))); if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"detint end. k=%ld",k); det = gerepileuptoint(av1, det); } } } return gerepileuptoint(av, det); } piv = gel(v,t); for (i=1; i<=m; i++) { GEN mvi; if (c[i] || i == t) continue; gcoeff(B,t,i) = mvi = negi(gel(v,i)); for (j=1; j<=m; j++) if (c[j]) /* implies j != t */ { pari_sp av2 = avma; GEN z = addii(mulii(gcoeff(B,j,i), piv), mulii(gcoeff(B,j,t), mvi)); if (rg > 1) z = diviiexact(z, pivprec); gcoeff(B,j,i) = gerepileuptoint(av2, z); } } c[t] = k; if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"detint. k=%ld",k); gerepileall(av1, 2, &piv,&B); v = zerovec(m); } } avma = av; return gen_0; } /* Reduce x modulo (invertible) y */ GEN closemodinvertible(GEN x, GEN y) { return gmul(y, ground(RgM_solve(y,x))); } GEN reducemodinvertible(GEN x, GEN y) { return gsub(x, closemodinvertible(x,y)); } GEN reducemodlll(GEN x,GEN y) { return reducemodinvertible(x, ZM_lll(y, 0.75, LLL_INPLACE)); } /*******************************************************************/ /* */ /* KERNEL of an m x n matrix */ /* return n - rk(x) linearly independent vectors */ /* */ /*******************************************************************/ /* x has INTEGER coefficients. Gauss-Bareiss */ GEN keri(GEN x) { pari_sp av, av0, lim; GEN c, l, y, p, pp; long i, j, k, r, t, n, m; n = lg(x)-1; if (!n) return cgetg(1,t_MAT); av0 = avma; m = nbrows(x); pp = cgetg(n+1,t_COL); x = RgM_shallowcopy(x); c = zero_zv(m); l = cgetg(n+1, t_VECSMALL); av = avma; lim = stack_lim(av,1); for (r=0, p=gen_1, k=1; k<=n; k++) { j = 1; while ( j <= m && (c[j] || !signe(gcoeff(x,j,k))) ) j++; if (j > m) { r++; l[k] = 0; for(j=1; j nl) break; gel(d,k) = gel(ck,i); c[i] = k; l[k] = i; /* pivot d[k] in x[i,k] */ } if (k > nc) { avma = av; return cgetg(1,t_COL); } if (k == 1) { avma = av; return scalarcol_shallow(gen_1,nc); } y = cgetg(nc+1,t_COL); gel(y,1) = gcopy(gel(ck, l[1])); for (D=gel(d,1),j=2; j>1); x = zc_to_ZC(x); break; } return gerepileupto(av, x); } return deplin_aux(x); } /*******************************************************************/ /* */ /* GAUSS REDUCTION OF MATRICES (m lines x n cols) */ /* (kernel, image, complementary image, rank) */ /* */ /*******************************************************************/ /* return the transform of x under a standard Gauss pivot. * x0 is a reference point when guessing whether x[i,j] ~ 0 * (iff x[i,j] << x0[i,j]) * Set r = dim ker(x). d[k] contains the index of the first non-zero pivot * in column k */ static GEN gauss_pivot_ker(GEN x, GEN x0, GEN *dd, long *rr) { GEN c, d, p, data; pari_sp av, lim; long i, j, k, r, t, n, m; pivot_fun pivot; n=lg(x)-1; if (!n) { *dd=NULL; *rr=0; return cgetg(1,t_MAT); } m=nbrows(x); r=0; pivot = get_pivot_fun(x, x0, &data); x = RgM_shallowcopy(x); c = zero_zv(m); d = cgetg(n+1,t_VECSMALL); av=avma; lim=stack_lim(av,1); for (k=1; k<=n; k++) { j = pivot(x, data, k, c); if (j > m) { r++; d[k]=0; for(j=1; j m) { r++; d[k] = 0; } else { c[j] = k; d[k] = j; p = gdiv(gen_m1, gcoeff(x,j,k)); for (i=k+1; i<=n; i++) gcoeff(x,j,i) = gmul(p,gcoeff(x,j,i)); for (t=1; t<=m; t++) if (!c[t]) /* no pivot on that line yet */ { 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); } for (i=k; i<=n; i++) gcoeff(x,j,i) = gen_0; /* dummy */ } } *rr = r; avma = (pari_sp)d; return d; } static long ZM_count_0_cols(GEN M) { long i, l = lg(M), n = 0; for (i = 1; i < l; i++) if (ZV_equal0(gel(M,i))) n++; return n; } static void indexrank_all(long m, long n, long r, GEN d, GEN *prow, GEN *pcol); /* As RgM_pivots, integer entries. Set *rr = dim Ker M0 */ GEN ZM_pivots(GEN M0, long *rr) { GEN d, dbest = NULL; long m, n, i, imax, rmin, rbest, zc; int beenthere = 0; pari_sp av, av0 = avma; forprime_t S; rbest = n = lg(M0)-1; if (n == 0) { *rr = 0; return NULL; } zc = ZM_count_0_cols(M0); if (n == zc) { *rr = zc; return zero_zv(n); } m = nbrows(M0); rmin = (m < n-zc) ? n-m : zc; init_modular(&S); imax = (n < (1<<4))? 1: (n>>3); /* heuristic */ for(;;) { GEN row, col, M, KM, IM, RHS, X, cX; long rk; for (av = avma, i = 0;; avma = av, i++) { ulong p = u_forprime_next(&S); long rp; if (!p) pari_err_OVERFLOW("ZM_pivots [ran out of primes]"); d = Flm_gauss_pivot(ZM_to_Flm(M0, p), p, &rp); if (rp == rmin) { rbest = rp; goto END; } /* maximal rank, return */ if (rp < rbest) { /* save best r so far */ rbest = rp; if (dbest) gunclone(dbest); dbest = gclone(d); if (beenthere) break; } if (!beenthere && i >= imax) break; } beenthere = 1; /* Dubious case: there is (probably) a non trivial kernel */ indexrank_all(m,n, rbest, dbest, &row, &col); M = rowpermute(vecpermute(M0, col), row); rk = n - rbest; /* (probable) dimension of image */ IM = vecslice(M,1,rk); KM = vecslice(M,rk+1, n); M = rowslice(IM, 1,rk); /* square maximal rank */ X = ZM_gauss(M, rowslice(KM, 1,rk)); X = Q_remove_denom(X, &cX); RHS = rowslice(KM,rk+1,m); if (cX) RHS = ZM_Z_mul(RHS, cX); if (ZM_equal(ZM_mul(rowslice(IM,rk+1,m), X), RHS)) { d = vecsmall_copy(dbest); goto END; } avma = av; } END: *rr = rbest; if (dbest) gunclone(dbest); return gerepileuptoleaf(av0, d); } /* set *pr = dim Ker x */ static GEN gauss_pivot(GEN x, long *pr) { GEN data; pivot_fun pivot = get_pivot_fun(x, x, &data); return RgM_pivots(x, data, pr, pivot); } /* compute ker(x), x0 is a reference point when guessing whether x[i,j] ~ 0 * (iff x[i,j] << x0[i,j]) */ static GEN ker_aux(GEN x, GEN x0) { pari_sp av = avma; GEN d,y; long i,j,k,r,n; x = gauss_pivot_ker(x,x0,&d,&r); if (!r) { avma=av; return cgetg(1,t_MAT); } n = lg(x)-1; y=cgetg(r+1,t_MAT); for (j=k=1; j<=r; j++,k++) { GEN p = cgetg(n+1,t_COL); gel(y,j) = p; while (d[k]) k++; for (i=1; i= 1; i--) { for (; j>=1; j--) if (coeff(Y,i,j)) { d[i] = j; break; } if (!j) return NULL; } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return Flm_mul(X, Flm_inv_upper_1(Y,p), p); } static GEN F2m_invimage_i(GEN A, GEN B) { GEN d, x, X, Y; long i, j, nY, nA = lg(A)-1, nB = lg(B)-1; x = F2m_ker_sp(shallowconcat(A, B), 0); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff * Y has at least nB columns and full rank */ nY = lg(x)-1; if (nY < nB) return NULL; /* implicitly: Y = rowslice(x, nA+1, nA+nB), nB rows */ d = cgetg(nB+1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--) { for (; j>=1; j--) if (F2m_coeff(x,nA+i,j)) { d[i] = j; break; } /* Y[i,j] */ if (!j) return NULL; } x = vecpermute(x, d); X = F2m_rowslice(x, 1, nA); Y = F2m_rowslice(x, nA+1, nA+nB); return F2m_mul(X, F2m_inv_upper_1(Y)); } GEN Flm_invimage(GEN A, GEN B, ulong p) { pari_sp av = avma; GEN X = Flm_invimage_i(A,B,p); if (!X) { avma = av; return NULL; } return gerepileupto(av, X); } GEN F2m_invimage(GEN A, GEN B) { pari_sp av = avma; GEN X = F2m_invimage_i(A,B); if (!X) { avma = av; return NULL; } return gerepileupto(av, X); } static GEN FpM_invimage_i(GEN A, GEN B, GEN p) { GEN d, x, X, Y; long i, j, nY, nA = lg(A)-1, nB = lg(B)-1; if (lgefint(p) == 3) { ulong pp = p[2]; A = ZM_to_Flm(A, pp); B = ZM_to_Flm(B, pp); x = Flm_invimage_i(A, B, pp); return x? Flm_to_ZM(x): NULL; } x = FpM_ker(shallowconcat(ZM_neg(A), B), p); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff * Y has at least nB columns and full rank */ nY = lg(x)-1; if (nY < nB) return NULL; Y = rowslice(x, nA+1, nA+nB); /* nB rows */ d = cgetg(nB+1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--) { for (; j>=1; j--) if (signe(gcoeff(Y,i,j))) { d[i] = j; break; } if (!j) return NULL; } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return FpM_mul(X, FpM_inv_upper_1(Y,p), p); } GEN FpM_invimage(GEN A, GEN B, GEN p) { pari_sp av = avma; GEN X = FpM_invimage_i(A,B,p); if (!X) { avma = av; return NULL; } return gerepileupto(av, X); } /* find Z such that A Z = B. Return NULL if no solution */ GEN RgM_invimage(GEN A, GEN B) { pari_sp av = avma; GEN d, x, X, Y; long i, j, nY, nA = lg(A)-1, nB = lg(B)-1; GEN p = NULL; if (RgM_is_FpM(A, &p) && RgM_is_FpM(B, &p) && p) { ulong pp; A = RgM_Fp_init(A,p,&pp); switch(pp) { case 0: B = RgM_to_FpM(B,p); x = FpM_invimage_i(A, B, p); if (x) x = FpM_to_mod(x, p); break; case 2: B = RgM_to_F2m(B); x = F2m_invimage_i(A, B); if (x) x = F2m_to_mod(x); break; default: B = RgM_to_Flm(B,pp); x = Flm_invimage_i(A, B, pp); if (x) x = Flm_to_mod(x,pp); break; } if (!x) { avma = av; return NULL; } return gerepileupto(av, x); } x = ker(shallowconcat(RgM_neg(A), B)); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff * Y has at least nB columns and full rank */ nY = lg(x)-1; if (nY < nB) { avma = av; return NULL; } Y = rowslice(x, nA+1, nA+nB); /* nB rows */ d = cgetg(nB+1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--) { for (; j>=1; j--) if (!gequal0(gcoeff(Y,i,j))) { d[i] = j; break; } if (!j) { avma = av; return NULL; } } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return gerepileupto(av, RgM_mul(X, RgM_inv_upper(Y))); } /* r = dim Ker x, n = nbrows(x) */ static GEN get_suppl(GEN x, GEN d, long n, long r, GEN(*ei)(long,long)) { pari_sp av; GEN y, c; long j, k, rx = lg(x)-1; /* != 0 due to init_suppl() */ if (rx == n && r == 0) return gcopy(x); y = cgetg(n+1, t_MAT); av = avma; c = zero_zv(n); /* c = lines containing pivots (could get it from gauss_pivot, but cheap) * In theory r = 0 and d[j] > 0 for all j, but why take chances? */ for (k = j = 1; j<=rx; j++) if (d[j]) { c[ d[j] ] = 1; gel(y,k++) = gel(x,j); } for (j=1; j<=n; j++) if (!c[j]) gel(y,k++) = (GEN)j; /* HACK */ avma = av; rx -= r; for (j=1; j<=rx; j++) gel(y,j) = gcopy(gel(y,j)); for ( ; j<=n; j++) gel(y,j) = ei(n, y[j]); return y; } static void init_suppl(GEN x) { if (lg(x) == 1) pari_err_IMPL("suppl [empty matrix]"); /* HACK: avoid overwriting d from gauss_pivot() after avma=av */ (void)new_chunk(lgcols(x) * 2); } /* x is an n x k matrix, rank(x) = k <= n. Return an invertible n x n matrix * whose first k columns are given by x. If rank(x) < k, undefined result. */ GEN suppl(GEN x) { pari_sp av = avma; GEN d, X = x, p = NULL; long r; if (typ(x)!=t_MAT) pari_err_TYPE("suppl",x); if (RgM_is_FpM(x, &p) && p) { ulong pp; x = RgM_Fp_init(x, p, &pp); switch(pp) { case 0: x = FpM_to_mod(FpM_suppl(x,p), p); break; case 2: x = F2m_to_mod(F2m_suppl(x)); break; default:x = Flm_to_mod(Flm_suppl(x,pp), pp); break; } return gerepileupto(av, x); } avma = av; init_suppl(x); d = gauss_pivot(X,&r); avma = av; return get_suppl(X,d,nbrows(X),r,&col_ei); } GEN FpM_suppl(GEN x, GEN p) { pari_sp av = avma; GEN d; long r; init_suppl(x); d = FpM_gauss_pivot(x,p, &r); avma = av; return get_suppl(x,d,nbrows(x),r,&col_ei); } GEN Flm_suppl(GEN x, ulong p) { pari_sp av = avma; GEN d; long r; init_suppl(x); d = Flm_gauss_pivot(Flm_copy(x),p, &r); avma = av; return get_suppl(x,d,nbrows(x),r,&vecsmall_ei); } GEN F2m_suppl(GEN x) { pari_sp av = avma; GEN d; long r; init_suppl(x); d = F2m_gauss_pivot(F2m_copy(x), &r); avma = av; return get_suppl(x,d,mael(x,1,1),r,&F2v_ei); } GEN FqM_suppl(GEN x, GEN T, GEN p) { pari_sp av = avma; GEN d; long r; if (!T) return FpM_suppl(x,p); init_suppl(x); d = FqM_gauss_pivot(x,T,p,&r); avma = av; return get_suppl(x,d,nbrows(x),r,&col_ei); } GEN image2(GEN x) { pari_sp av = avma; long k, n, i; GEN A, B; if (typ(x)!=t_MAT) pari_err_TYPE("image2",x); if (lg(x) == 1) return cgetg(1,t_MAT); A = ker(x); k = lg(A)-1; if (!k) { avma = av; return gcopy(x); } A = suppl(A); n = lg(A)-1; B = cgetg(n-k+1, t_MAT); for (i = k+1; i <= n; i++) gel(B,i-k) = RgM_RgC_mul(x, gel(A,i)); return gerepileupto(av, B); } GEN matimage0(GEN x,long flag) { switch(flag) { case 0: return image(x); case 1: return image2(x); default: pari_err_FLAG("matimage"); } return NULL; /* not reached */ } long rank(GEN x) { pari_sp av = avma; long r; GEN ff = NULL, p = NULL; if (typ(x)!=t_MAT) pari_err_TYPE("rank",x); if (RgM_is_FpM(x, &p) && p) { ulong pp; x = RgM_Fp_init(x,p,&pp); switch(pp) { case 0: r = FpM_rank(x,p); break; case 2: r = F2m_rank(x); break; default:r = Flm_rank(x,pp); break; } avma = av; return r; } if (RgM_is_FFM(x, &ff)) return FFM_rank(x, ff); (void)gauss_pivot(x, &r); avma = av; return lg(x)-1 - r; } /* d a t_VECSMALL of integers in 1..n. Return the vector of the d[i] * followed by the missing indices */ static GEN perm_complete(GEN d, long n) { GEN y = cgetg(n+1, t_VECSMALL); long i, j = 1, k = n, l = lg(d); pari_sp av = avma; char *T = stack_calloc(n+1); for (i = 1; i < l; i++) T[d[i]] = 1; for (i = 1; i <= n; i++) if (T[i]) y[j++] = i; else y[k--] = i; avma = av; return y; } /* n = dim x, r = dim Ker(x), d from gauss_pivot */ static GEN indexrank0(long n, long r, GEN d) { GEN p1, p2, res = cgetg(3,t_VEC); long i, j; r = n - r; /* now r = dim Im(x) */ p1 = cgetg(r+1,t_VECSMALL); gel(res,1) = p1; p2 = cgetg(r+1,t_VECSMALL); gel(res,2) = p2; if (d) { for (i=0,j=1; j<=n; j++) if (d[j]) { i++; p1[i] = d[j]; p2[i] = j; } vecsmall_sort(p1); } return res; } /* n = dim x, r = dim Ker(x), d from gauss_pivot */ static GEN indeximage0(long n, long r, GEN d) { long i, j; GEN v; r = n - r; /* now r = dim Im(x) */ v = cgetg(r+1,t_VECSMALL); if (d) for (i=j=1; j<=n; j++) if (d[j]) v[i++] = j; return v; } /* x an m x n t_MAT, n > 0, r = dim Ker(x), d from gauss_pivot */ static void indexrank_all(long m, long n, long r, GEN d, GEN *prow, GEN *pcol) { GEN IR = indexrank0(n, r, d); *prow = perm_complete(gel(IR,1), m); *pcol = perm_complete(gel(IR,2), n); } static void init_indexrank(GEN x) { (void)new_chunk(3 + 2*lg(x)); /* HACK */ } GEN indexrank(GEN x) { pari_sp av = avma; long r; GEN d, p = NULL; if (typ(x)!=t_MAT) pari_err_TYPE("indexrank",x); init_indexrank(x); if (RgM_is_FpM(x, &p) && p) { ulong pp; x = RgM_Fp_init(x,p,&pp); switch(pp) { case 0: d = FpM_gauss_pivot(x,p,&r); break; case 2: d = F2m_gauss_pivot(x,&r); break; default:d = Flm_gauss_pivot(x,pp,&r); break; } } else d = gauss_pivot(x,&r); avma = av; return indexrank0(lg(x)-1, r, d); } GEN FpM_indexrank(GEN x, GEN p) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = FpM_gauss_pivot(x,p,&r); avma = av; return indexrank0(lg(x)-1, r, d); } GEN Flm_indexrank(GEN x, ulong p) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = Flm_gauss_pivot(Flm_copy(x),p,&r); avma = av; return indexrank0(lg(x)-1, r, d); } GEN F2m_indexrank(GEN x) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = F2m_gauss_pivot(F2m_copy(x),&r); avma = av; return indexrank0(lg(x)-1, r, d); } GEN ZM_indeximage(GEN x) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = ZM_pivots(x,&r); avma = av; return indeximage0(lg(x)-1, r, d); } long ZM_rank(GEN x) { pari_sp av = avma; long r; (void)ZM_pivots(x,&r); avma = av; return lg(x)-1-r; } /*******************************************************************/ /* */ /* Structured Elimination */ /* */ /*******************************************************************/ static void rem_col(GEN c, long i, GEN iscol, GEN Wrow, long *rcol, long *rrow) { long lc = lg(c), k; iscol[i] = 0; (*rcol)--; for (k = 1; k < lc; ++k) { Wrow[c[k]]--; if (Wrow[c[k]]==0) (*rrow)--; } } static void rem_singleton(GEN M, GEN iscol, GEN Wrow, long *rcol, long *rrow) { long i, j; long nbcol = lg(iscol)-1, last; do { last = 0; for (i = 1; i <= nbcol; ++i) if (iscol[i]) { GEN c = gmael(M, i, 1); long lc = lg(c); for (j = 1; j < lc; ++j) if (Wrow[c[j]] == 1) { rem_col(c, i, iscol, Wrow, rcol, rrow); last=1; break; } } } while (last); } static GEN fill_wcol(GEN M, GEN iscol, GEN Wrow, long *w, GEN wcol) { long nbcol = lg(iscol)-1; long i, j, m, last; GEN per; for (m = 2, last=0; !last ; m++) { for (i = 1; i <= nbcol; ++i) { wcol[i] = 0; if (iscol[i]) { GEN c = gmael(M, i, 1); long lc = lg(c); for (j = 1; j < lc; ++j) if (Wrow[c[j]] == m) { wcol[i]++; last = 1; } } } } per = vecsmall_indexsort(wcol); *w = wcol[per[nbcol]]; return per; } /* M is a RgMs with nbrow rows, A a list of row indices. Eliminate rows of M with a single entry that do not belong to A, and the corresponding columns. Also eliminate columns until #colums=#rows. Return pcol and prow: pcol is a map from the new columns indices to the old one. prow is a map from the old rows indices to the new one (0 if removed). */ void RgMs_structelim(GEN M, long nbrow, GEN A, GEN *p_col, GEN *p_row) { long i,j,k; long nbcol = lg(M)-1, lA = lg(A); GEN prow = cgetg(nbrow+1, t_VECSMALL); GEN pcol = zero_zv(nbcol); pari_sp av = avma; long rcol = nbcol, rrow = 0, imin = nbcol - usqrt(nbcol); GEN iscol = const_vecsmall(nbcol, 1); GEN Wrow = zero_zv(nbrow); GEN wcol = cgetg(nbcol+1, t_VECSMALL); pari_sp av2=avma; for (i = 1; i <= nbcol; ++i) { GEN F = gmael(M, i, 1); long l = lg(F)-1; for (j = 1; j <= l; ++j) Wrow[F[j]]++; } for (j = 1; j < lA; ++j) { if (Wrow[A[j]] == 0) { *p_col=NULL; return; } Wrow[A[j]] = -1; } for (i = 1; i <= nbrow; ++i) if (Wrow[i]) rrow++; rem_singleton(M, iscol, Wrow, &rcol, &rrow); if (rcolrrow;) { long w; GEN per = fill_wcol(M, iscol, Wrow, &w, wcol); for (i = nbcol; i>=imin && wcol[per[i]]>=w && rcol>rrow; i--) rem_col(gmael(M, per[i], 1), per[i], iscol, Wrow, &rcol, &rrow); rem_singleton(M, iscol, Wrow, &rcol, &rrow); avma = av2; } for (j = 1, i = 1; i <= nbcol; ++i) if (iscol[i]) pcol[j++] = i; setlg(pcol,j); for (k = 1, i = 1; i <= nbrow; ++i) prow[i] = Wrow[i] ? k++: 0; avma = av; *p_col = pcol; *p_row = prow; } /*******************************************************************/ /* */ /* EIGENVECTORS */ /* (independent eigenvectors, sorted by increasing eigenvalue) */ /* */ /*******************************************************************/ GEN mateigen(GEN x, long flag, long prec) { GEN y, R, T; long k, l, ex, n = lg(x); pari_sp av = avma; if (typ(x)!=t_MAT) pari_err_TYPE("eigen",x); if (n != 1 && n != lgcols(x)) pari_err_DIM("eigen"); if (flag < 0 || flag > 1) pari_err_FLAG("mateigen"); if (n == 1) { if (flag) retmkvec2(cgetg(1,t_VEC), cgetg(1,t_MAT)); return cgetg(1,t_VEC); } if (n == 2) { if (flag) retmkvec2(mkveccopy(gcoeff(x,1,1)), matid(1)); return matid(1); } ex = 16 - prec2nbits(prec); T = charpoly(x,0); if (RgX_is_QX(T)) { T = Q_primpart(T); (void)ZX_gcd_all(T, ZX_deriv(T), &T); R = nfrootsQ(T); if (lg(R)-1 < degpol(T)) { /* add missing complex roots */ GEN r = cleanroots(RgX_div(T, roots_to_pol(R, 0)), prec); settyp(r, t_VEC); R = shallowconcat(R, r); } } else { GEN r1, v = vectrunc_init(lg(T)); long e; R = cleanroots(T,prec); r1 = NULL; for (k = 1; k < lg(R); k++) { GEN r2 = gel(R,k), r = grndtoi(r2, &e); if (e < ex) r2 = r; if (r1) { r = gsub(r1,r2); if (gequal0(r) || gexpo(r) < ex) continue; } vectrunc_append(v, r2); r1 = r2; } R = v; } /* R = distinct complex roots of charpoly(x) */ l = lg(R); y = cgetg(l, t_VEC); for (k = 1; k < l; k++) { GEN F = ker_aux(RgM_Rg_sub_shallow(x, gel(R,k)), x); long d = lg(F)-1; if (!d) pari_err_PREC("mateigen"); gel(y,k) = F; if (flag) gel(R,k) = const_vec(d, gel(R,k)); } y = shallowconcat1(y); if (lg(y) > n) pari_err_PREC("mateigen"); /* lg(y) < n if x is not diagonalizable */ if (flag) y = mkvec2(shallowconcat1(R), y); return gerepilecopy(av,y); } GEN eigen(GEN x, long prec) { return mateigen(x, 0, prec); } /*******************************************************************/ /* */ /* DETERMINANT */ /* */ /*******************************************************************/ GEN det0(GEN a,long flag) { switch(flag) { case 0: return det(a); case 1: return det2(a); default: pari_err_FLAG("matdet"); } return NULL; /* not reached */ } /* M a 2x2 matrix, returns det(M) */ static GEN RgM_det2(GEN M) { pari_sp av = avma; GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); return gerepileupto(av, gsub(gmul(a,d), gmul(b,c))); } /* M a 2x2 ZM, returns det(M) */ static GEN ZM_det2(GEN M) { pari_sp av = avma; GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); return gerepileuptoint(av, subii(mulii(a,d), mulii(b, c))); } /* M a 3x3 ZM, return det(M) */ static GEN ZM_det3(GEN M) { pari_sp av = avma; 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 { p1 = mulii(mulii(a,e), i); p5 = mulii(mulii(b,d), i); } 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 { p3 = mulii(mulii(c,d), h); p4 = mulii(mulii(a,f), h); } 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); long i,j,k, s = 1, nbco = lg(a)-1; GEN p, x = gen_1; a = RgM_shallowcopy(a); for (i=1; i nbco) return gerepilecopy(av, gcoeff(a,i,i)); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); s = -s; } p = gcoeff(a,i,i); x = gmul(x,p); for (k=i+1; k<=nbco; k++) { GEN m = gcoeff(a,i,k); if (gequal0(m)) continue; m = gdiv(m,p); 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(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&x); p = gcoeff(a,i,i); m = gcoeff(a,i,k); m = gdiv(m, p); } } } } if (s < 0) x = gneg_i(x); return gerepileupto(av, gmul(x, gcoeff(a,nbco,nbco))); } GEN det2(GEN a) { GEN data; pivot_fun pivot; long n = lg(a)-1; if (typ(a)!=t_MAT) pari_err_TYPE("det2",a); if (!n) return gen_1; if (n != nbrows(a)) pari_err_DIM("det2"); if (n == 1) return gcopy(gcoeff(a,1,1)); if (n == 2) return RgM_det2(a); pivot = get_pivot_fun(a, a, &data); return det_simple_gauss(a, data, pivot); } static GEN mydiv(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == ty && tx == t_POL && varn(x) == varn(y)) return RgX_div(x,y); return gdiv(x,y); } /* Assumes a a square t_MAT of dimension n > 0. Returns det(a) using * Gauss-Bareiss. */ static GEN det_bareiss(GEN a) { pari_sp av = avma, lim = stack_lim(av,2); long nbco = lg(a)-1,i,j,k,s = 1; GEN p, pprec; a = RgM_shallowcopy(a); for (pprec=gen_1,i=1; inbco) return gerepilecopy(av, p); swap(gel(a,k), gel(a,i)); s = -s; p = gcoeff(a,i,i); } ci = gel(a,i); for (k=i+1; k<=nbco; k++) { ck = gel(a,k); m = gel(ck,i); if (gequal0(m)) { if (gequal1(p)) { if (diveuc) gel(a,k) = mydiv(gel(a,k), pprec); } else for (j=i+1; j<=nbco; j++) { GEN p1 = gmul(p, gel(ck,j)); if (diveuc) p1 = mydiv(p1,pprec); gel(ck,j) = p1; } } else { for (j=i+1; j<=nbco; j++) { pari_sp av2 = avma; 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(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&pprec); ci = gel(a,i); ck = gel(a,k); m = gel(ck,i); p = gcoeff(a,i,i); } } } } } p = gcoeff(a,nbco,nbco); p = (s < 0)? gneg(p): gcopy(p); return gerepileupto(av, p); } /* count non-zero entries in col j, at most 'max' of them. * Return their indices */ static GEN col_count_non_zero(GEN a, long j, long max) { GEN v = cgetg(max+1, t_VECSMALL); GEN c = gel(a,j); long i, l = lg(a), k = 1; for (i = 1; i < l; i++) if (!gequal0(gel(c,i))) { if (k > max) return NULL; /* fail */ v[k++] = i; } setlg(v, k); return v; } /* count non-zero entries in row i, at most 'max' of them. * Return their indices */ static GEN row_count_non_zero(GEN a, long i, long max) { GEN v = cgetg(max+1, t_VECSMALL); long j, l = lg(a), k = 1; for (j = 1; j < l; j++) if (!gequal0(gcoeff(a,i,j))) { if (k > max) return NULL; /* fail */ v[k++] = j; } setlg(v, k); return v; } static GEN det_develop(GEN a, long max, double bound); /* (-1)^(i+j) a[i,j] * det RgM_minor(a,i,j) */ static GEN coeff_det(GEN a, long i, long j, long max, double bound) { GEN c = gcoeff(a, i, j); c = gmul(c, det_develop(RgM_minor(a, i,j), max, bound)); if (odd(i+j)) c = gneg(c); return c; } /* a square t_MAT, 'bound' a rough upper bound for the number of * multiplications we are willing to pay while developing rows/columns before * switching to Gaussian elimination */ static GEN det_develop(GEN M, long max, double bound) { pari_sp av = avma; long i,j, n = lg(M)-1, lbest = max+2, best_col = 0, best_row = 0; GEN best = NULL; if (bound < 1.) return det_bareiss(M); /* too costly now */ switch(n) { case 0: return gen_1; case 1: return gcopy(gcoeff(M,1,1)); case 2: return RgM_det2(M); } if (max > ((n+2)>>1)) max = (n+2)>>1; for (j = 1; j <= n; j++) { pari_sp av2 = avma; GEN v = col_count_non_zero(M, j, max); long lv; if (!v || (lv = lg(v)) >= lbest) { avma = av2; continue; } if (lv == 1) { avma = av; return gen_0; } if (lv == 2) { avma = av; return gerepileupto(av, coeff_det(M,v[1],j,max,bound)); } best = v; lbest = lv; best_col = j; } for (i = 1; i <= n; i++) { pari_sp av2 = avma; GEN v = row_count_non_zero(M, i, max); long lv; if (!v || (lv = lg(v)) >= lbest) { avma = av2; continue; } if (lv == 1) { avma = av; return gen_0; } if (lv == 2) { avma = av; return gerepileupto(av, coeff_det(M,i,v[1],max,bound)); } best = v; lbest = lv; best_row = i; } if (best_row) { double d = lbest-1; GEN s = NULL; long k; bound /= d*d*d; for (k = 1; k < lbest; k++) { GEN c = coeff_det(M, best_row, best[k], max, bound); s = s? gadd(s, c): c; } return gerepileupto(av, s); } if (best_col) { double d = lbest-1; GEN s = NULL; long k; bound /= d*d*d; for (k = 1; k < lbest; k++) { GEN c = coeff_det(M, best[k], best_col, max, bound); s = s? gadd(s, c): c; } return gerepileupto(av, s); } return det_bareiss(M); } /* area of parallelogram bounded by (v1,v2) */ static GEN parallelogramarea(GEN v1, GEN v2) { return gsub(gmul(gnorml2(v1), gnorml2(v2)), gsqr(RgV_dotproduct(v1, v2))); } /* Square of Hadamard bound for det(a), a square matrix. * Slightly improvement: instead of using the column norms, use the area of * the parallelogram formed by pairs of consecutive vectors */ GEN RgM_Hadamard(GEN a) { pari_sp av = avma; long n = lg(a)-1, i; GEN B; if (n == 0) return gen_1; if (n == 1) return gsqr(gcoeff(a,1,1)); a = RgM_gtofp(a, LOWDEFAULTPREC); B = gen_1; for (i = 1; i <= n/2; i++) B = gmul(B, parallelogramarea(gel(a,2*i-1), gel(a,2*i))); if (odd(n)) B = gmul(B, gnorml2(gel(a, n))); return gerepileuptoint(av, ceil_safe(B)); } /* assume dim(a) = n > 0 */ static GEN ZM_det_i(GEN M, long n) { const long DIXON_THRESHOLD = 40; pari_sp av = avma, av2; long i; ulong p, compp, Dp = 1; forprime_t S; GEN D, h, q, v, comp; if (n == 1) return icopy(gcoeff(M,1,1)); if (n == 2) return ZM_det2(M); if (n == 3) return ZM_det3(M); h = RgM_Hadamard(M); if (!signe(h)) { avma = av; return gen_0; } h = sqrti(h); q = gen_1; init_modular(&S); p = 0; /* -Wall */ while( cmpii(q, h) <= 0 && (p = u_forprime_next(&S)) ) { av2 = avma; Dp = Flm_det(ZM_to_Flm(M, p), p); avma = av2; if (Dp) break; q = muliu(q, p); } if (!p) pari_err_OVERFLOW("ZM_det [ran out of primes]"); if (!Dp) { avma = av; return gen_0; } if (n <= DIXON_THRESHOLD) D = q; else { av2 = avma; v = cgetg(n+1, t_COL); gel(v, 1) = gen_1; /* ensure content(v) = 1 */ for (i = 2; i <= n; i++) gel(v, i) = stoi(random_Fl(15) - 7); D = Q_denom(ZM_gauss(M, v)); if (expi(D) < expi(h) >> 1) { /* First try unlucky, try once more */ for (i = 2; i <= n; i++) gel(v, i) = stoi(random_Fl(15) - 7); D = lcmii(D, Q_denom(ZM_gauss(M, v))); } D = gerepileuptoint(av2, D); if (q != gen_1) D = lcmii(D, q); } /* determinant is M multiple of D */ h = shifti(divii(h, D), 1); compp = Fl_div(Dp, umodiu(D,p), p); comp = Z_init_CRT(compp, p); q = utoipos(p); while (cmpii(q, h) <= 0) { p = u_forprime_next(&S); if (!p) pari_err_OVERFLOW("ZM_det [ran out of primes]"); Dp = umodiu(D, p); if (!Dp) continue; av2 = avma; compp = Fl_div(Flm_det(ZM_to_Flm(M, p), p), Dp, p); avma = av2; (void) Z_incremental_CRT(&comp, compp, &q, p); } return gerepileuptoint(av, mulii(comp, D)); } static long det_init_max(long n) { if (n > 100) return 0; if (n > 50) return 1; if (n > 30) return 4; return 7; } GEN det(GEN a) { long n = lg(a)-1; double B; GEN data, ff = NULL, p = NULL; pivot_fun pivot; if (typ(a)!=t_MAT) pari_err_TYPE("det",a); if (!n) return gen_1; if (n != nbrows(a)) pari_err_DIM("det"); if (n == 1) return gcopy(gcoeff(a,1,1)); if (n == 2) return RgM_det2(a); if (RgM_is_FpM(a, &p)) { pari_sp av = avma; ulong pp, d; if (!p) return ZM_det_i(a, n); /* ZM */ /* FpM */ a = RgM_Fp_init(a,p,&pp); switch(pp) { case 0: return gerepileupto(av, Fp_to_mod(FpM_det(a,p),p)); break; case 2: d = F2m_det(a); break; default:d = Flm_det(a,pp); break; } avma = av; return mkintmodu(d, pp); } if (RgM_is_FFM(a, &ff)) return FFM_det(a, ff); pivot = get_pivot_fun(a, a, &data); if (pivot != gauss_get_pivot_NZ) return det_simple_gauss(a, data, pivot); B = (double)n; return det_develop(a, det_init_max(n), B*B*B); } GEN ZM_det(GEN a) { long n = lg(a)-1; if (!n) return gen_1; return ZM_det_i(a, n); } /* return a solution of congruence system sum M_{ i,j } X_j = Y_i mod D_i * If ptu1 != NULL, put in *ptu1 a Z-basis of the homogeneous system */ static GEN gaussmoduloall(GEN M, GEN D, GEN Y, GEN *ptu1) { pari_sp av = avma; long n, m, j, l, lM; GEN delta, H, U, u1, u2, x; if (typ(M)!=t_MAT) pari_err_TYPE("gaussmodulo",M); lM = lg(M); if (lM == 1) { switch(typ(Y)) { case t_INT: break; case t_COL: if (lg(Y) != 1) pari_err_DIM("gaussmodulo"); break; default: pari_err_TYPE("gaussmodulo",Y); } switch(typ(D)) { case t_INT: break; case t_COL: if (lg(D) != 1) pari_err_DIM("gaussmodulo"); break; default: pari_err_TYPE("gaussmodulo",D); } if (ptu1) *ptu1 = cgetg(1, t_MAT); return gen_0; } n = nbrows(M); switch(typ(D)) { case t_COL: if (lg(D)-1!=n) pari_err_DIM("gaussmodulo"); delta = diagonal_shallow(D); break; case t_INT: delta = scalarmat_shallow(D,n); break; default: pari_err_TYPE("gaussmodulo",D); return NULL; /* not reached */ } switch(typ(Y)) { case t_INT: Y = const_col(n, Y); break; case t_COL: if (lg(Y)-1!=n) pari_err_DIM("gaussmodulo"); break; default: pari_err_TYPE("gaussmodulo",Y); return NULL; /* not reached */ } H = ZM_hnfall(shallowconcat(M,delta), &U, 1); Y = hnf_solve(H,Y); if (!Y) return gen_0; l = lg(H); /* may be smaller than lM if some moduli are 0 */ n = l-1; m = lg(U)-1 - n; u1 = cgetg(m+1,t_MAT); u2 = cgetg(n+1,t_MAT); for (j=1; j<=m; j++) { GEN c = gel(U,j); setlg(c,lM); gel(u1,j) = c; } U += m; for (j=1; j<=n; j++) { GEN c = gel(U,j); setlg(c,lM); gel(u2,j) = c; } /* (u1 u2) * (M D) (* * ) = (0 H) */ u1 = ZM_lll(u1, 0.75, LLL_INPLACE); Y = ZM_ZC_mul(u2,Y); x = ZC_reducemodmatrix(Y, u1); if (!ptu1) x = gerepileupto(av, x); else { gerepileall(av, 2, &x, &u1); *ptu1 = u1; } return x; } GEN matsolvemod0(GEN M, GEN D, GEN Y, long flag) { pari_sp av; GEN p1,y; if (!flag) return gaussmoduloall(M,D,Y,NULL); av=avma; y = cgetg(3,t_VEC); p1 = gaussmoduloall(M,D,Y, (GEN*)y+2); if (p1==gen_0) { avma=av; return gen_0; } gel(y,1) = p1; return y; } GEN gaussmodulo2(GEN M, GEN D, GEN Y) { return matsolvemod0(M,D,Y,1); } GEN gaussmodulo(GEN M, GEN D, GEN Y) { return matsolvemod0(M,D,Y,0); } pari-2.7.5/src/basemath/ifactor1.c0000644000175000017500000040422712526672541015360 0ustar billbill/* 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" /***********************************************************************/ /** **/ /** PRIMES IN SUCCESSION **/ /** (abstracted by GN 1998Aug21 mainly for use in ellfacteur() below) **/ /** **/ /***********************************************************************/ /* map from prime residue classes mod 210 to their numbers in {0...47}. * Subscripts into this array take the form ((k-1)%210)/2, ranging from * 0 to 104. Unused entries are */ #define NPRC 128 /* non-prime residue class */ static unsigned char prc210_no[] = { 0, NPRC, NPRC, NPRC, NPRC, 1, 2, NPRC, 3, 4, NPRC, /* 21 */ 5, NPRC, NPRC, 6, 7, NPRC, NPRC, 8, NPRC, 9, /* 41 */ 10, NPRC, 11, NPRC, NPRC, 12, NPRC, NPRC, 13, 14, NPRC, /* 63 */ NPRC, 15, NPRC, 16, 17, NPRC, NPRC, 18, NPRC, 19, /* 83 */ NPRC, NPRC, 20, NPRC, NPRC, NPRC, 21, NPRC, 22, 23, NPRC, /* 105 */ 24, 25, NPRC, 26, NPRC, NPRC, NPRC, 27, NPRC, NPRC, /* 125 */ 28, NPRC, 29, NPRC, NPRC, 30, 31, NPRC, 32, NPRC, NPRC, /* 147 */ 33, 34, NPRC, NPRC, 35, NPRC, NPRC, 36, NPRC, 37, /* 167 */ 38, NPRC, 39, NPRC, NPRC, 40, 41, NPRC, NPRC, 42, NPRC, /* 189 */ 43, 44, NPRC, 45, 46, NPRC, NPRC, NPRC, NPRC, 47, /* 209 */ }; #if 0 /* map from prime residue classes mod 210 (by number) to their smallest * positive representatives */ static unsigned char prc210_rp[] = { /* 19 + 15 + 14 = [0..47] */ 1, 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, 121, 127, 131, 137, 139, 143, 149, 151, 157, 163, 167, 169, 173, 179, 181, 187, 191, 193, 197, 199, 209, }; #endif /* first differences of the preceding */ static unsigned char prc210_d1[] = { 10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2, 10, 2, }; /* return 0 for overflow */ ulong unextprime(ulong n) { long rc, rc0, rcd, rcn; switch(n) { case 0: case 1: case 2: return 2; case 3: return 3; case 4: case 5: return 5; case 6: case 7: return 7; } #ifdef LONG_IS_64BIT if (n > (ulong)-59) return 0; #else if (n > (ulong)-5) return 0; #endif /* here n > 7 */ n |= 1; /* make it odd */ rc = rc0 = n % 210; /* find next prime residue class mod 210 */ for(;;) { rcn = (long)(prc210_no[rc>>1]); if (rcn != NPRC) break; rc += 2; /* cannot wrap since 209 is coprime and rc odd */ } if (rc > rc0) n += rc - rc0; /* now find an actual (pseudo)prime */ for(;;) { if (uisprime(n)) break; rcd = prc210_d1[rcn]; if (++rcn > 47) rcn = 0; n += rcd; } return n; } GEN nextprime(GEN n) { long rc, rc0, rcd, rcn; pari_sp av = avma; if (typ(n) != t_INT) { n = gceil(n); if (typ(n) != t_INT) pari_err_TYPE("nextprime",n); } if (signe(n) <= 0) { avma = av; return gen_2; } if (lgefint(n) == 3) { ulong k = unextprime(n[2]); avma = av; if (k) return utoipos(k); #ifdef LONG_IS_64BIT return uutoi(1,13); #else return uutoi(1,15); #endif } /* here n > 7 */ if (!mod2(n)) n = addsi(1,n); rc = rc0 = smodis(n, 210); /* find next prime residue class mod 210 */ for(;;) { rcn = (long)(prc210_no[rc>>1]); if (rcn != NPRC) break; rc += 2; /* cannot wrap since 209 is coprime and rc odd */ } if (rc > rc0) n = addsi(rc - rc0, n); /* now find an actual (pseudo)prime */ for(;;) { if (BPSW_psp(n)) break; rcd = prc210_d1[rcn]; if (++rcn > 47) rcn = 0; n = addsi(rcd, n); } if (avma == av) return icopy(n); return gerepileuptoint(av, n); } ulong uprecprime(ulong n) { long rc, rc0, rcd, rcn; { /* check if n <= 10 */ if (n <= 1) return 0; if (n == 2) return 2; if (n <= 4) return 3; if (n <= 6) return 5; if (n <= 10) return 7; } /* here n >= 11 */ if (!(n % 2)) n--; rc = rc0 = n % 210; /* find previous prime residue class mod 210 */ for(;;) { rcn = (long)(prc210_no[rc>>1]); if (rcn != NPRC) break; rc -= 2; /* cannot wrap since 1 is coprime and rc odd */ } if (rc < rc0) n += rc - rc0; /* now find an actual (pseudo)prime */ for(;;) { if (uisprime(n)) break; if (--rcn < 0) rcn = 47; rcd = prc210_d1[rcn]; n -= rcd; } return n; } GEN precprime(GEN n) { long rc, rc0, rcd, rcn; pari_sp av = avma; if (typ(n) != t_INT) { n = gfloor(n); if (typ(n) != t_INT) pari_err_TYPE("nextprime",n); } if (signe(n) <= 0) { avma = av; return gen_0; } if (lgefint(n) <= 3) { ulong k = (ulong)n[2]; avma = av; return utoi(uprecprime(k)); } if (!mod2(n)) n = addsi(-1,n); rc = rc0 = smodis(n, 210); /* find previous prime residue class mod 210 */ for(;;) { rcn = (long)(prc210_no[rc>>1]); if (rcn != NPRC) break; rc -= 2; /* cannot wrap since 1 is coprime and rc odd */ } if (rc < rc0) n = addsi(rc - rc0, n); /* now find an actual (pseudo)prime */ for(;;) { if (BPSW_psp(n)) break; if (--rcn < 0) rcn = 47; rcd = prc210_d1[rcn]; n = addsi(-rcd, n); } if (avma == av) return icopy(n); return gerepileuptoint(av, n); } /* Find next single-word prime strictly larger than p. * If **d is non-NULL (somewhere in a diffptr), this is p + *(*d)++; * otherwise imitate nextprime(). * *rcn = NPRC or the correct residue class for the current p; we'll use this * to track the current prime residue class mod 210 once we're out of range of * the diffptr table, and we'll update it before that if it isn't NPRC. * * *q is incremented whenever q!=NULL and we wrap from 209 mod 210 to * 1 mod 210 * k = second argument for MR_Jaeschke(). --GN1998Aug22 */ ulong snextpr(ulong p, byteptr *d, long *rcn, long *q, long k) { ulong n; if (**d) { byteptr dd = *d; long d1 = 0; NEXT_PRIME_VIADIFF(d1,dd); /* d1 = nextprime(p+1) - p */ if (*rcn != NPRC) { long rcn0 = *rcn; while (d1 > 0) { d1 -= prc210_d1[*rcn]; if (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } } if (d1 < 0) { char *s=stack_sprintf("snextpr: %lu!=prc210_rp[%ld] mod 210\n",p,rcn0); pari_err_BUG(s); } } NEXT_PRIME_VIADIFF(p,*d); return p; } /* we are beyond the diffptr table */ if (*rcn == NPRC) { /* initialize */ *rcn = prc210_no[(p % 210) >> 1]; if (*rcn == NPRC) { char *s = stack_sprintf("snextpr: %lu should have been prime\n", p); pari_err_BUG(s); } } /* look for the next one */ n = p + prc210_d1[*rcn]; if (++*rcn > 47) *rcn = 0; while (!Fl_MR_Jaeschke(n, k)) { n += prc210_d1[*rcn]; if (n <= 11) pari_err_OVERFLOW("snextpr"); if (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } } return n; } /********************************************************************/ /** **/ /** INTEGER FACTORIZATION **/ /** **/ /********************************************************************/ int factor_add_primes = 0, factor_proven = 0; /***********************************************************************/ /** **/ /** FACTORIZATION (ECM) -- GN Jul-Aug 1998 **/ /** Integer factorization using the elliptic curves method (ECM). **/ /** ellfacteur() returns a non trivial factor of N, assuming N>0, **/ /** is composite, and has no prime divisor below 2^14 or so. **/ /** Thanks to Paul Zimmermann for much helpful advice and to **/ /** Guillaume Hanrot and Igor Schein for intensive testing **/ /** **/ /***********************************************************************/ #define nbcmax 64 /* max number of simultaneous curves */ #define bstpmax 1024 /* max number of baby step table entries */ /* addition/doubling/multiplication of a point on an 'elliptic curve mod N' * may result in one of three things: * - a new bona fide point * - a point at infinity (denominator divisible by N) * - a point at infinity mod some p | N but finite mod q | N betraying itself * by a denominator which has nontrivial gcd with N. * * In the second case, addition/doubling aborts, copying one of the summands * to the destination array of points unless they coincide. * Multiplication will stop at some unpredictable intermediate stage: The * destination will contain _some_ multiple of the input point, but not * necessarily the desired one, which doesn't matter. As long as we're * multiplying (B1 phase) we simply carry on with the next multiplier. * During the B2 phase, the only additions are the giant steps, and the * worst that can happen here is that we lose one residue class mod 210 * of prime multipliers on 4 of the curves, so again, we ignore the problem * and just carry on.) * * Idea: select nbc curves mod N and one point P on each of them. For each * such P, compute [M]P = Q where M is the product of all powers <= B2 of * primes <= nextprime(B1). Then check whether [p]Q for p < nextprime(B2) * betrays a factor. This second stage looks separately at the primes in * each residue class mod 210, four curves at a time, and steps additively * to ever larger multipliers, by comparing X coordinates of points which we * would need to add in order to reach another prime multiplier in the same * residue class. 'Comparing' means that we accumulate a product of * differences of X coordinates, and from time to time take a gcd of this * product with N. Montgomery's multi-inverse trick is used heavily. */ /* *** auxiliary functions for ellfacteur: *** */ /* (Rx,Ry) <- (Px,Py)+(Qx,Qy) over Z/NZ, z=1/(Px-Qx). If Ry = NULL, don't set */ static void FpE_add_i(GEN N, GEN z, GEN Px, GEN Py, GEN Qx, GEN Qy, GEN *Rx, GEN *Ry) { GEN slope = modii(mulii(subii(Py, Qy), z), N); GEN t = subii(sqri(slope), addii(Qx, Px)); affii(modii(t, N), *Rx); if (Ry) { t = subii(mulii(slope, subii(Px, *Rx)), Py); affii(modii(t, N), *Ry); } } /* X -> Z; cannot add on one of the curves: make sure Z contains * something useful before letting caller proceed */ static void ZV_aff(long n, GEN *X, GEN *Z) { if (X != Z) { long k; for (k = n; k--; ) affii(X[k],Z[k]); } } /* Parallel addition on nbc curves, assigning the result to locations at and * following *X3, *Y3. (If Y-coords of result not desired, set Y=NULL.) * Safe even if (X3,Y3) = (X2,Y2), _not_ if (X1,Y1). It is also safe to * overwrite Y2 with X3. If nbc1 < nbc, the first summand is * assumed to hold only nbc1 distinct points, repeated as often as we need * them (to add one point on each of a few curves to several other points on * the same curves): only used with nbc1 = nbc or nbc1 = 4 | nbc. * * Return 0 [SUCCESS], 1 [N | den], 2 [gcd(den, N) is a factor of N, preserved * in gl. * Stack space is bounded by a constant multiple of lgefint(N)*nbc: * - Phase 2 creates 12 items on the stack per iteration, of which 4 are twice * as long and 1 is thrice as long as N, i.e. 18 units per iteration. * - Phase 1 creates 4 units. * Total can be as large as 4*nbcmax + 18*8 units; ecm_elladd2() is * just as bad, and elldouble() comes to 3*nbcmax + 29*8 units. */ static int ecm_elladd0(GEN N, GEN *gl, long nbc, long nbc1, GEN *X1, GEN *Y1, GEN *X2, GEN *Y2, GEN *X3, GEN *Y3) { const ulong mask = (nbc1 == 4)? 3: ~0UL; /*nbc1 = 4 or nbc*/ GEN W[2*nbcmax], *A = W+nbc; /* W[0],A[0] unused */ long i; pari_sp av = avma; W[1] = subii(X1[0], X2[0]); for (i=1; i copy Y2->Y3 */ ZV_aff(2*nbc, X5,X6); /* also copy Y5->Y6 */ avma = av; return 1; } while (j--) /* nbc times */ { pari_sp av2 = avma; GEN Px = X4[j], Py = Y4[j], Qx = X5[j], Qy = Y5[j]; GEN z = mulii(*gl,W[--i]); /*1/(Px-Qx)*/ FpE_add_i(N,z, Px,Py, Qx,Qy, X6+j,Y6+j); avma = av2; *gl = modii(mulii(*gl, A[i]), N); } while (i--) /* nbc times */ { pari_sp av2 = avma; GEN Px = X1[i], Py = Y1[i], Qx = X2[i], Qy = Y2[i]; GEN z = i? mulii(*gl, W[i]): *gl; /*1/(Px-Qx)*/ FpE_add_i(N,z, Px,Py, Qx,Qy, X3+i,Y3+i); if (!i) break; avma = av2; *gl = modii(mulii(*gl, A[i]), N); } avma = av; return 0; } /* Parallel doubling on nbc curves, assigning the result to locations at * and following *X2. Safe to be called with X2 equal to X1. Return * value as for ecm_elladd. If we find a point at infinity mod N, * and if X1 != X2, we copy the points at X1 to X2. */ static int elldouble(GEN N, GEN *gl, long nbc, GEN *X1, GEN *X2) { GEN *Y1 = X1+nbc, *Y2 = X2+nbc; GEN W[nbcmax+1]; /* W[0] unused */ long i; pari_sp av = avma; /*W[0] = gen_1;*/ W[1] = Y1[0]; for (i=1; iY2 */ avma = av; return 1; } while (i--) /* nbc times */ { pari_sp av2; GEN v, w, L, z = i? mulii(*gl,W[i]): *gl; if (i) *gl = modii(mulii(*gl, Y1[i]), N); av2 = avma; L = modii(mulii(addsi(1, mului(3, Fp_sqr(X1[i],N))), z), N); if (signe(L)) /* half of zero is still zero */ L = shifti(mod2(L)? addii(L, N): L, -1); v = modii(subii(sqri(L), shifti(X1[i],1)), N); w = modii(subii(mulii(L, subii(X1[i], v)), Y1[i]), N); affii(v, X2[i]); affii(w, Y2[i]); avma = av2; } avma = av; return 0; } /* Parallel multiplication by an odd prime k on nbc curves, storing the * result to locations at and following *X2. Safe to be called with X2 = X1. * Return values as ecm_elladd. Uses (a simplified variant of) Montgomery's * PRAC algorithm; see ftp://ftp.cwi.nl/pub/pmontgom/Lucas.ps.gz . * With thanks to Paul Zimmermann for the reference. --GN1998Aug13 */ static int get_rule(ulong d, ulong e) { if (d <= e + (e>>2)) /* floor(1.25*e) */ { if ((d+e)%3 == 0) return 0; /* rule 1 */ if ((d-e)%6 == 0) return 1; /* rule 2 */ } /* d <= 4*e but no ofl */ if ((d+3)>>2 <= e) return 2; /* rule 3, common case */ if ((d&1)==(e&1)) return 1; /* rule 4 = rule 2 */ if (!(d&1)) return 3; /* rule 5 */ if (d%3 == 0) return 4; /* rule 6 */ if ((d+e)%3 == 0) return 5; /* rule 7 */ if ((d-e)%3 == 0) return 6; /* rule 8 */ /* when we get here, e is even, otherwise one of rules 4,5 would apply */ return 7; /* rule 9 */ } /* k>2 assumed prime, XAUX = scratchpad */ static int ellmult(GEN N, GEN *gl, long nbc, ulong k, GEN *X1, GEN *X2, GEN *XAUX) { ulong r, d, e, e1; int res; GEN *A = X2, *B = XAUX, *T = XAUX + 2*nbc; ZV_aff(2*nbc,X1,XAUX); /* first doubling picks up X1; after this we'll be working in XAUX and * X2 only, mostly via A and B and T */ if ((res = elldouble(N, gl, nbc, X1, X2)) != 0) return res; /* split the work at the golden ratio */ r = (ulong)(k*0.61803398875 + .5); d = k - r; e = r - d; /* d+e == r, so no danger of ofl below */ while (d != e) { /* apply one of the nine transformations from PM's Table 4. */ switch(get_rule(d,e)) { case 0: /* rule 1 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, T)) ) return res; if ( (res = ecm_elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; e1 = d - e; d = (d + e1)/3; e = (e - e1)/3; break; case 1: /* rules 2 and 4 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; if ( (res = elldouble(N, gl, nbc, A, A)) ) return res; d = (d-e)>>1; break; case 3: /* rule 5 */ if ( (res = elldouble(N, gl, nbc, A, A)) ) return res; d >>= 1; break; case 4: /* rule 6 */ if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, T, A, A)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; d = d/3 - e; break; case 2: /* rule 3 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; d -= e; break; case 5: /* rule 7 */ if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; d = (d - 2*e)/3; break; case 6: /* rule 8 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, T, A, A)) ) return res; d = (d - e)/3; break; case 7: /* rule 9 */ if ( (res = elldouble(N, gl, nbc, B, B)) ) return res; e >>= 1; break; } /* swap d <-> e and A <-> B if necessary */ if (d < e) { lswap(d,e); pswap(A,B); } } return ecm_elladd(N, gl, nbc, XAUX, X2, X2); } /* Auxiliary routines need < (3*nbc+240)*tf words on the PARI stack, in * addition to the spc*(tf+1) words occupied by our main table. * If stack space is already tight, use the heap & newblock(). */ static GEN* alloc_scratch(long nbc, long spc, long tf) { 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) { if (DEBUGLEVEL>4) err_printf("ECM: stack tight, using heap space\n"); X = (GEN*)newblock(len); } else X = (GEN*)new_chunk(len); /* hack for X[i] = cgeti(tf). X = current point in B1 phase */ w = (GEN)(X + spc + 385); for (i = spc-1; i >= 0; i--) { X[i] = w; *w = tw; w += tf; } return X; } /* PRAC implementation notes - main changes against the paper version: * (1) The general function [m+n]P = f([m]P,[n]P,[m-n]P) collapses (for m!=n) * to an ecm_elladd() which does not depend on the third argument; thus * references to the third variable (C in the paper) can be eliminated. * (2) Since our multipliers are prime, the outer loop of the paper * version executes only once, and thus is invisible above. * (3) The first step in the inner loop of the paper version will always be * rule 3, but the addition requested by this rule amounts to a doubling, and * will always be followed by a swap, so we have unrolled this first iteration. * (4) Simplifications in rules 6 and 7 are possible given the above, and we * save one addition in each of the two cases. NB none of the other * ecm_elladd()s in the loop can ever degenerate into an elldouble. * (5) I tried to optimize for rule 3, which is used more frequently than all * others together, but it didn't improve things, so I removed the nested * tight loop again. --GN */ /* The main loop body of ellfacteur() runs _slower_ under PRAC than under a * straightforward left-shift binary multiplication when N has <30 digits and * B1 is small; PRAC wins when N and B1 get larger. Weird. --GN */ /* memory layout in ellfacteur(): a large array of GEN pointers, and one * huge chunk of memory containing all the actual GEN (t_INT) objects. * nbc is constant throughout the invocation: * - The B1 stage of each iteration through the main loop needs little * space: enough for the X and Y coordinates of the current points, * and twice as much again as scratchpad for ellmult(). * - The B2 stage, starting from some current set of points Q, needs, in * succession: * + space for [2]Q, [4]Q, ..., [10]Q, and [p]Q for building the helix; * + space for 48*nbc X and Y coordinates to hold the helix. This could * re-use [2]Q,...,[8]Q, but only with difficulty, since we don't * know in advance which residue class mod 210 our p is going to be in. * It can and should re-use [p]Q, though; * + space for (temporarily [30]Q and then) [210]Q, [420]Q, and several * further doublings until the giant step multiplier is reached. This * can re-use the remaining cells from above. The computation of [210]Q * will have been the last call to ellmult() within this iteration of the * main loop, so the scratchpad is now also free to be re-used. We also * compute [630]Q by a parallel addition; we'll need it later to get the * baby-step table bootstrapped a little faster. * + Finally, for no more than 4 curves at a time, room for up to 1024 X * coordinates only: the Y coordinates needed whilst setting up this baby * step table are temporarily stored in the upper half, and overwritten * during the last series of additions. * * Graphically: after end of B1 stage (X,Y are the coords of Q): * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * | X Y | scratch | [2]Q| [4]Q| [6]Q| [8]Q|[10]Q| ... | ... * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * *X *XAUX *XT *XD *XB * * [30]Q is computed from [10]Q. [210]Q can go into XY, etc: * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * |[210]|[420]|[630]|[840]|[1680,3360,6720,...,2048*210] |bstp table... * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * *X *XAUX *XT *XD [*XG, somewhere here] *XB .... *XH * * So we need (13 + 48) * 2 * nbc slots here + 4096 slots for the baby step * table (not all of which will be used when we start with a small B1, but * better to allocate and initialize ahead of time all the slots that might * be needed later). * * Note on memory locality: During the B2 phase, accesses to the helix * (once it is set up) will be clustered by curves (4 out of nbc at a time). * Accesses to the baby steps table will wander from one end of the array to * the other and back, one such cycle per giant step, and during a full cycle * we would expect on the order of 2E4 accesses when using the largest giant * step size. Thus we shouldn't be doing too bad with respect to thrashing * a 512KBy L2 cache. However, we don't want the baby step table to grow * larger than this, even if it would reduce the number of EC operations by a * few more per cent for very large B2, lest cache thrashing slow down * everything disproportionally. --GN */ /* parameters for MR_Jaeschke() via snextpr(), for use by ellfacteur() */ static const long MR_Jaeschke_k1 = 16;/* B1 phase, foolproof below 10^12 */ static const long MR_Jaeschke_k2 = 1; /* B2 phase, not foolproof, 2xfaster */ /* MR_Jaeschke_k2 will let thousands of composites slip through, which doesn't * harm ECM, but ellmult() during the B1 phase should only be fed primes * which really are prime */ /* ellfacteur() has been re-tuned to be useful as a first stage before * MPQS, especially for large arguments, when 'insist' is false, and now * also for the case when 'insist' is true, vaguely following suggestions * by Paul Zimmermann (http://www.loria.fr/~zimmerma/records/ecmnet.html). * --GN 1998Jul,Aug */ GEN ellfacteur(GEN N, int insist) { const ulong TB1[] = { 142,172,208,252,305,370,450,545,661,801,972,1180,1430, 1735,2100,2550,3090,3745,4540,5505,6675,8090,9810,11900, 14420,17490,21200,25700,31160,37780UL,45810UL,55550UL,67350UL, 81660UL,99010UL,120050UL,145550UL,176475UL,213970UL,259430UL, 314550UL,381380UL,462415UL,560660UL,679780UL,824220UL,999340UL, 1211670UL,1469110UL,1781250UL,2159700UL,2618600UL,3175000UL, 3849600UL,4667500UL,5659200UL,6861600UL,8319500UL,10087100UL, 12230300UL,14828900UL,17979600UL,21799700UL,26431500UL, 32047300UL,38856400UL, /* 110 times that still fits into 32bits */ #ifdef LONG_IS_64BIT 47112200UL,57122100UL,69258800UL,83974200UL,101816200UL, 123449000UL,149678200UL,181480300UL,220039400UL,266791100UL, 323476100UL,392204900UL,475536500UL,576573500UL,699077800UL, 847610500UL,1027701900UL,1246057200UL,1510806400UL,1831806700UL, 2221009800UL,2692906700UL,3265067200UL,3958794400UL,4799917500UL, /* Someone can extend this table when the hardware gets faster */ #endif }; const ulong TB1_for_stage[] = { /* Start below the optimal B1 for finding factors which would just have been * missed by pollardbrent(), and escalate, changing curves to give good * coverage of the small factor ranges. Entries grow faster than what would * be optimal but a table instead of a 2D array keeps the code simple */ 500,520,560,620,700,800,900,1000,1150,1300,1450,1600,1800,2000, 2200,2450,2700,2950,3250,3600,4000,4400,4850,5300,5800,6400, 7100,7850,8700,9600,10600,11700,12900,14200,15700,17300, 19000,21000,23200,25500,28000,31000,34500UL,38500UL,43000UL, 48000UL,53800UL,60400UL,67750UL,76000UL,85300UL,95700UL, 107400UL,120500UL,135400UL,152000UL,170800UL,191800UL,215400UL, 241800UL,271400UL,304500UL,341500UL,383100UL,429700UL,481900UL, 540400UL,606000UL,679500UL,761800UL,854100UL,957500UL,1073500UL, }; long nbc,nbc2,dsn,dsnmax,rep,spc,gse,gss,rcn,rcn0,bstp,bstp0; long a, i, j, k, size = expi(N) + 1, tf = lgefint(N); ulong B1,B2,B2_p,B2_rt,m,p,p0,dp; GEN *X,*XAUX,*XT,*XD,*XG,*YG,*XH,*XB,*XB2,*Xh,*Yh,*Xb; GEN res = cgeti(tf), gl; pari_sp av1, avtmp, av = avma; pari_timer T; int rflag; /* Determine where to start, how long to persist, and how many curves to * use in parallel */ if (insist) { #ifdef LONG_IS_64BIT const long DSNMAX = 90; #else const long DSNMAX = 65; #endif dsnmax = (size >> 2) - 10; if (dsnmax < 0) dsnmax = 0; else if (dsnmax > DSNMAX) dsnmax = DSNMAX; dsn = (size >> 3) - 5; if (dsn < 0) dsn = 0; else if (dsn > 47) dsn = 47; /* pick up the torch where non-insistent stage would have given up */ nbc = dsn + (dsn >> 2) + 9; /* 8 or more curves in parallel */ nbc &= ~3; /* 4 | nbc */ if (nbc > nbcmax) nbc = nbcmax; a = 1 + (nbcmax<<7)*(size&0xffff); /* seed for choice of curves */ rep = 0; /* gcc -Wall */ } else { dsn = (size - 140) >> 3; if (dsn > 12) dsn = 12; dsnmax = 72; if (dsn < 0) /* < 140 bits: decline the task */ { #ifdef __EMX__ /* unless DOS/EMX: MPQS's disk access is abysmally slow */ dsn = 0; rep = 20; nbc = 8; #else if (DEBUGLEVEL >= 4) err_printf("ECM: number too small to justify this stage\n"); avma = av; return NULL; #endif } else { rep = (size <= 248 ? (size <= 176 ? (size - 124) >> 4 : (size - 148) >> 3) : (size - 224) >> 1); nbc = ((size >> 3) << 2) - 80; if (nbc < 8) nbc = 8; else if (nbc > nbcmax) nbc = nbcmax; #ifdef __EMX__ rep += 20; #endif } /* Use disjoint sets of curves for non-insist and insist phases; moreover, * repeated calls acting on factors of the same original number should try * to use fresh curves. The following achieves this */ a = 1 + (nbcmax<<3)*(size & 0xf); } if (dsn > dsnmax) dsn = dsnmax; if (DEBUGLEVEL >= 4) { timer_start(&T); err_printf("ECM: working on %ld curves at a time; initializing", nbc); if (!insist) { if (rep == 1) err_printf(" for one round"); else err_printf(" for up to %ld rounds", rep); } err_printf("...\n"); } nbc2 = nbc << 1; spc = (13 + 48) * nbc2 + bstpmax * 4; X = alloc_scratch(nbc, spc, tf); XAUX = X + nbc2; /* scratchpad for ellmult() */ XT = XAUX + nbc2; /* ditto, will later hold [3*210]Q */ XD = XT + nbc2; /* room for various multiples */ XB = XD + 10*nbc2; /* start of baby steps table */ XB2 = XB + 2 * bstpmax; /* middle of baby steps table */ XH = XB2 + 2 * bstpmax; /* end of bstps table, start of helix */ Xh = XH + 48*nbc2; /* little helix, X coords */ Yh = XH + 192; /* ditto, Y coords */ /* XG will be set inside the main loop, since it depends on B2 */ /* Xh range of 384 pointers not set; these will later duplicate the pointers * in the XH range, 4 curves at a time. Some of the cells reserved here for * the XB range will never be used, instead, we'll warp the pointers to * connect to (read-only) GENs in the X/XD range */ for(;;) { byteptr d0, d = diffptr; rcn = NPRC; /* multipliers begin at the beginning */ /* pick curves & bounds */ for (i = nbc2; i--; ) affui(a++, X[i]); B1 = insist ? TB1[dsn] : TB1_for_stage[dsn]; B2 = 110*B1; B2_rt = (ulong)(sqrt((double)B2)); /* pick giant step exponent and size. * With 32 baby steps, a giant step corresponds to 32*420 = 13440, * appropriate for the smallest B2s. With 1024, a giant step will be 430080; * appropriate for B1 >~ 42000, where 512 baby steps would imply roughly * the same number of E.C. additions. */ gse = B1 < 656 ? (B1 < 200? 5: 6) : (B1 < 10500 ? (B1 < 2625? 7: 8) : (B1 < 42000? 9: 10)); gss = 1UL << gse; XG = XT + gse*nbc2; /* will later hold [2^(gse+1)*210]Q */ YG = XG + nbc; if (DEBUGLEVEL >= 4) { err_printf("ECM: time = %6ld ms\nECM: dsn = %2ld,\tB1 = %4lu,", timer_delay(&T), dsn, B1); err_printf("\tB2 = %6lu,\tgss = %4ld*420\n", B2, gss); } p = 0; NEXT_PRIME_VIADIFF(p,d); /* ---B1 PHASE--- */ /* treat p=2 separately */ B2_p = B2 >> 1; for (m=1; m<=B2_p; m<<=1) { if ((rflag = elldouble(N, &gl, nbc, X, X)) > 1) goto fin; else if (rflag) break; } /* p=3,...,nextprime(B1) */ while (p < B1 && p <= B2_rt) { pari_sp av = avma; p = snextpr(p, &d, &rcn, NULL, MR_Jaeschke_k1); B2_p = B2/p; /* beware integer overflow on 32-bit CPUs */ for (m=1; m<=B2_p; m*=p) { if ((rflag = ellmult(N, &gl, nbc, p, X, X, XAUX)) > 1) goto fin; else if (rflag) break; avma = av; } avma = av; } /* primes p larger than sqrt(B2) appear only to the 1st power */ while (p < B1) { pari_sp av = avma; p = snextpr(p, &d, &rcn, NULL, MR_Jaeschke_k1); if (ellmult(N, &gl, nbc, p, X, X, XAUX) > 1) goto fin; avma = av; } if (DEBUGLEVEL >= 4) { err_printf("ECM: time = %6ld ms, B1 phase done, ", timer_delay(&T)); err_printf("p = %lu, setting up for B2\n", p); } /* ---B2 PHASE--- */ /* compute [2]Q,...,[10]Q, needed to build the helix */ if (elldouble(N, &gl, nbc, X, XD) > 1) goto fin; /* [2]Q */ if (elldouble(N, &gl, nbc, XD, XD + nbc2) > 1) goto fin; /* [4]Q */ if (ecm_elladd(N, &gl, nbc, XD, XD + nbc2, XD + (nbc<<2)) > 1) goto fin; /* [6]Q */ if (ecm_elladd2(N, &gl, nbc, XD, XD + (nbc<<2), XT + (nbc<<3), XD + nbc2, XD + (nbc<<2), XD + (nbc<<3)) > 1) goto fin; /* [8]Q and [10]Q */ if (DEBUGLEVEL >= 7) err_printf("\t(got [2]Q...[10]Q)\n"); /* get next prime (still using the foolproof test) */ p = snextpr(p, &d, &rcn, NULL, MR_Jaeschke_k1); /* make sure we have the residue class number (mod 210) */ if (rcn == NPRC) { rcn = prc210_no[(p % 210) >> 1]; if (rcn == NPRC) { err_printf("ECM: %lu should have been prime but isn\'t\n", p); pari_err_BUG("ellfacteur"); } } /* compute [p]Q and put it into its place in the helix */ if (ellmult(N, &gl, nbc, p, X, XH + rcn*nbc2, XAUX) > 1) goto fin; if (DEBUGLEVEL >= 7) err_printf("\t(got [p]Q, p = %lu = prc210_rp[%ld] mod 210)\n", p, rcn); /* save current p, d, and rcn; we'll need them more than once below */ p0 = p; d0 = d; rcn0 = rcn; /* remember where the helix wraps */ bstp0 = 0; /* p is at baby-step offset 0 from itself */ /* fill up the helix, stepping forward through the prime residue classes * mod 210 until we're back at the r'class of p0. Keep updating p so * that we can print meaningful diagnostics if a factor shows up; don't * bother checking which of these p's are in fact prime */ for (i = 47; i; i--) /* 47 iterations */ { p += (dp = (ulong)prc210_d1[rcn]); if (rcn == 47) { /* wrap mod 210 */ if (ecm_elladd(N, &gl, nbc, XT+dp*nbc, XH+rcn*nbc2, XH) > 1) goto fin; rcn = 0; continue; } if (ecm_elladd(N, &gl, nbc, XT+dp*nbc, XH+rcn*nbc2, XH+rcn*nbc2+nbc2) > 1) goto fin; rcn++; } if (DEBUGLEVEL >= 7) err_printf("\t(got initial helix)\n"); /* compute [210]Q etc, needed for the baby step table */ if (ellmult(N, &gl, nbc, 3, XD + (nbc<<3), X, XAUX) > 1) goto fin; if (ellmult(N, &gl, nbc, 7, X, X, XAUX) > 1) goto fin; /* [210]Q */ /* this was the last call to ellmult() in the main loop body; may now * overwrite XAUX and slots XD and following */ if (elldouble(N, &gl, nbc, X, XAUX) > 1) goto fin; /* [420]Q */ if (ecm_elladd(N, &gl, nbc, X, XAUX, XT) > 1) goto fin;/* [630]Q */ if (ecm_elladd(N, &gl, nbc, X, XT, XD) > 1) goto fin; /* [840]Q */ for (i=1; i <= gse; i++) if (elldouble(N, &gl, nbc, XT + i*nbc2, XD + i*nbc2) > 1) goto fin; /* (the last iteration has initialized XG to [210*2^(gse+1)]Q) */ if (DEBUGLEVEL >= 4) err_printf("ECM: time = %6ld ms, entering B2 phase, p = %lu\n", timer_delay(&T), p); /* inner loop over small sets of 4 curves at a time */ for (i = nbc - 4; i >= 0; i -= 4) { if (DEBUGLEVEL >= 6) err_printf("ECM: finishing curves %ld...%ld\n", i, i+3); /* Copy relevant pointers from XH to Xh. Memory layout in XH: * nbc X coordinates, nbc Y coordinates for residue class * 1 mod 210, then the same for r.c. 11 mod 210, etc. Memory layout for * Xh is: four X coords for 1 mod 210, four for 11 mod 210, ..., four * for 209 mod 210, then the corresponding Y coordinates in the same * order. This allows a giant step on Xh using just three calls to * ecm_elladd0() each acting on 64 points in parallel */ for (j = 48; j--; ) { k = nbc2*j + i; m = j << 2; /* X coordinates */ Xh[m] = XH[k]; Xh[m+1] = XH[k+1]; Xh[m+2] = XH[k+2]; Xh[m+3] = XH[k+3]; k += nbc; /* Y coordinates */ Yh[m] = XH[k]; Yh[m+1] = XH[k+1]; Yh[m+2] = XH[k+2]; Yh[m+3] = XH[k+3]; } /* Build baby step table of X coords of multiples of [210]Q. XB[4*j] * will point at X coords on four curves from [(j+1)*210]Q. Until * we're done, we need some Y coords as well, which we keep in the * second half of the table, overwriting them at the end when gse=10. * Multiples which we already have (by 1,2,3,4,8,16,...,2^gse) are * entered simply by copying the pointers, ignoring the few slots in w * that were initially reserved for them. Here are the initial entries */ for (Xb=XB,k=2,j=i; k--; Xb=XB2,j+=nbc) /* do first X, then Y coords */ { Xb[0] = X[j]; Xb[1] = X[j+1]; /* [210]Q */ Xb[2] = X[j+2]; Xb[3] = X[j+3]; Xb[4] = XAUX[j]; Xb[5] = XAUX[j+1]; /* [420]Q */ Xb[6] = XAUX[j+2]; Xb[7] = XAUX[j+3]; Xb[8] = XT[j]; Xb[9] = XT[j+1]; /* [630]Q */ Xb[10] = XT[j+2]; Xb[11] = XT[j+3]; Xb += 4; /* points at [420]Q */ /* ... entries at powers of 2 times 210 .... */ for (m = 2; m < (ulong)gse+k; m++) /* omit Y coords of [2^gse*210]Q */ { long m2 = m*nbc2 + j; Xb += (2UL<= 7) err_printf("\t(extracted precomputed helix / baby step entries)\n"); /* ... glue in between, up to 16*210 ... */ if (ecm_elladd0(N, &gl, 12, 4, /* 12 pts + (4 pts replicated thrice) */ XB + 12, XB2 + 12, XB, XB2, XB + 16, XB2 + 16) > 1) goto fin; /*4+{1,2,3} = {5,6,7}*/ if (ecm_elladd0(N, &gl, 28, 4, /* 28 pts + (4 pts replicated 7fold) */ XB + 28, XB2 + 28, XB, XB2, XB + 32, XB2 + 32) > 1) goto fin; /*8+{1,...,7} = {9,...,15}*/ /* ... and the remainder of the lot */ for (m = 5; m <= (ulong)gse; m++) { /* fill in from 2^(m-1)+1 to 2^m-1 in chunks of 64 and 60 points */ ulong m2 = 2UL << m; /* will point at 2^(m-1)+1 */ for (j = 0; (ulong)j < m2-64; j+=64) /* executed 0 times when m = 5 */ { if (ecm_elladd0(N, &gl, 64, 4, XB + m2-4, XB2 + m2-4, XB + j, XB2 + j, XB + m2+j, (m<(ulong)gse? XB2+m2+j: NULL)) > 1) goto fin; } /* j = m2-64 here, 60 points left */ if (ecm_elladd0(N, &gl, 60, 4, XB + m2-4, XB2 + m2-4, XB + j, XB2 + j, XB + m2+j, (m<(ulong)gse? XB2+m2+j: NULL)) > 1) goto fin; /* when m=gse, drop Y coords of result, and when both equal 1024, * overwrite Y coords of second argument with X coords of result */ } if (DEBUGLEVEL >= 7) err_printf("\t(baby step table complete)\n"); /* initialize a few other things */ bstp = bstp0; p = p0; d = d0; rcn = rcn0; gl = gen_1; av1 = avma; /* scratchspace for prod (x_i-x_j) */ avtmp = (pari_sp)new_chunk(8 * lgefint(N)); /* The correct entry in XB to use depends on bstp and on where we are * on the helix. As we skip from prime to prime, bstp is incremented * by snextpr each time we wrap around through residue class number 0 * (1 mod 210), but the baby step should not be taken until rcn>=rcn0, * i.e. until we pass again the residue class of p0. * * The correct signed multiplier is thus k = bstp - (rcn < rcn0), * and the offset from XB is four times (|k| - 1). When k=0, we ignore * the current prime: if it had led to a factorization, this * would have been noted during the last giant step, or -- when we * first get here -- whilst initializing the helix. When k > gss, * we must do a giant step and bump bstp back by -2*gss. * * The gcd of the product of X coord differences against N is taken just * before we do a giant step. */ while (p < B2) {/* loop over probable primes p0 < p <= nextprime(B2), inserting giant * steps as necessary */ /* get next probable prime */ p = snextpr(p, &d, &rcn, &bstp, MR_Jaeschke_k2); /* work out the corresponding baby-step multiplier */ k = bstp - (rcn < rcn0 ? 1 : 0); /* check whether it's giant-step time */ if (k > gss) { /* take gcd */ gl = gcdii(gl, N); if (!is_pm1(gl) && !equalii(gl, N)) goto fin; gl = gen_1; avma = av1; while (k > gss) { /* giant step */ if (DEBUGLEVEL >= 7) err_printf("\t(giant step at p = %lu)\n", p); if (ecm_elladd0(N, &gl, 64, 4, XG + i, YG + i, Xh, Yh, Xh, Yh) > 1) goto fin; if (ecm_elladd0(N, &gl, 64, 4, XG + i, YG + i, Xh + 64, Yh + 64, Xh + 64, Yh + 64) > 1) goto fin; if (ecm_elladd0(N, &gl, 64, 4, XG + i, YG + i, Xh + 128, Yh + 128, Xh + 128, Yh + 128) > 1) goto fin; bstp -= (gss << 1); k = bstp - (rcn < rcn0? 1: 0); /* recompute multiplier */ } } if (!k) continue; /* point of interest is already in Xh */ if (k < 0) k = -k; m = ((ulong)k - 1) << 2; /* accumulate product of differences of X coordinates */ j = rcn<<2; avma = avtmp; /* go to garbage zone */ gl = modii(mulii(gl, subii(XB[m], Xh[j])), N); gl = modii(mulii(gl, subii(XB[m+1], Xh[j+1])), N); gl = modii(mulii(gl, subii(XB[m+2], Xh[j+2])), N); gl = mulii(gl, subii(XB[m+3], Xh[j+3])); avma = av1; gl = modii(gl, N); } /* loop over p */ avma = av1; } /* for i (loop over sets of 4 curves) */ /* continuation part of main loop */ if (dsn < dsnmax) { dsn += insist ? 1 : 2; if (dsn > dsnmax) dsn = dsnmax; } if (!insist && !--rep) { if (DEBUGLEVEL >= 4) { err_printf("ECM: time = %6ld ms,\tellfacteur giving up.\n", timer_delay(&T)); err_flush(); } res = NULL; goto ret; } } fin: affii(gl, res); if (DEBUGLEVEL >= 4) { err_printf("ECM: time = %6ld ms,\tp <= %6lu,\n\tfound factor = %Ps\n", timer_delay(&T), p, res); err_flush(); } ret: if (!isonstack((GEN)X)) killblock((GEN)X); avma = av; return res; } /***********************************************************************/ /** **/ /** FACTORIZATION (Pollard-Brent rho) --GN1998Jun18-26 **/ /** pollardbrent() returns a nontrivial factor of n, assuming n is **/ /** composite and has no small prime divisor, or NULL if going on **/ /** would take more time than we want to spend. Sometimes it finds **/ /** more than one factor, and returns a structure suitable for **/ /** interpretation by ifac_crack. (Cf Algo 8.5.2 in ACiCNT) **/ /** **/ /***********************************************************************/ #define VALUE(x) gel(x,0) #define EXPON(x) gel(x,1) #define CLASS(x) gel(x,2) INLINE void INIT(GEN x, GEN v, GEN e, GEN c) { VALUE(x) = v; EXPON(x) = e; CLASS(x) = c; } static void ifac_delete(GEN x) { INIT(x,NULL,NULL,NULL); } static void rho_dbg(pari_timer *T, long c, long msg_mask) { if (c & msg_mask) return; err_printf("Rho: time = %6ld ms,\t%3ld round%s\n", timer_delay(T), c, (c==1?"":"s")); err_flush(); } /* Tuning parameter: for input up to 64 bits long, we must not spend more * than a very short time, for fear of slowing things down on average. * With the current tuning formula, increase our efforts somewhat at 49 bit * input (an extra round for each bit at first), and go up more and more * rapidly after we pass 80 bits.-- Changed this to adjust for the presence of * squfof, which will finish input up to 59 bits quickly. */ /* Return NULL when we run out of time, or a single t_INT containing a * nontrivial factor of n, or a vector of t_INTs, each triple of successive * entries containing a factor, an exponent (equal to one), and a factor * class (NULL for unknown or zero for known composite), matching the * internal representation used by the ifac_*() routines below. Repeated * factors may arise; the caller will sort the factors anyway. */ GEN pollardbrent(GEN n) { const long tune_pb_min = 14; /* even 15 seems too much. */ long tf = lgefint(n), size = 0, delta, retries = 0, msg_mask; long c0, c, k, k1, l; pari_sp GGG, avP, avx, av = avma; GEN x, x1, y, P, g, g1, res; pari_timer T; if (DEBUGLEVEL >= 4) timer_start(&T); if (tf >= 4) size = expi(n) + 1; else if (tf == 3) /* try to keep purify happy... */ size = 1 + expu((ulong)n[2]); if (size <= 28) c0 = 32;/* amounts very nearly to 'insist'. Now that we have squfof(), we * don't insist any more when input is 2^29 ... 2^32 */ else if (size <= 42) c0 = tune_pb_min; else if (size <= 59) /* match squfof() cutoff point */ c0 = tune_pb_min + ((size - 42)<<1); else if (size <= 72) c0 = tune_pb_min + size - 24; else if (size <= 301) /* nonlinear increase in effort, kicking in around 80 bits */ /* 301 gives 48121 + tune_pb_min */ c0 = tune_pb_min + size - 60 + ((size-73)>>1)*((size-70)>>3)*((size-56)>>4); else c0 = 49152; /* ECM is faster when it'd take longer */ c = c0 << 5; /* 2^5 iterations per round */ msg_mask = (size >= 448? 0x1fff: (size >= 192? (256L<<((size-128)>>6))-1: 0xff)); PB_RETRY: /* trick to make a 'random' choice determined by n. Don't use x^2+0 or * x^2-2, ever. Don't use x^2-3 or x^2-7 with a starting value of 2. * x^2+4, x^2+9 are affine conjugate to x^2+1, so don't use them either. * * (the point being that when we get called again on a composite cofactor * of something we've already seen, we had better avoid the same delta) */ switch ((size + retries) & 7) { case 0: delta= 1; break; case 1: delta= -1; break; case 2: delta= 3; break; case 3: delta= 5; break; case 4: delta= -5; break; case 5: delta= 7; break; case 6: delta= 11; break; /* case 7: */ default: delta=-11; break; } if (DEBUGLEVEL >= 4) { if (!retries) err_printf("Rho: searching small factor of %ld-bit integer\n", size); else err_printf("Rho: restarting for remaining rounds...\n"); err_printf("Rho: using X^2%+1ld for up to %ld rounds of 32 iterations\n", delta, c >> 5); err_flush(); } x = gen_2; P = gen_1; g1 = NULL; k = 1; l = 1; (void)new_chunk(10 + 6 * tf); /* enough for cgetg(10) + 3 modii */ y = cgeti(tf); affsi(2, y); x1= cgeti(tf); affsi(2, x1); avx = avma; avP = (pari_sp)new_chunk(2 * tf); /* enough for x = addsi(tf+1) */ GGG = (pari_sp)new_chunk(4 * tf); /* enough for P = modii(2tf+1, tf) */ for (;;) /* terminated under the control of c */ { /* use the polynomial x^2 + delta */ #define one_iter() STMT_START {\ avma = GGG; x = remii(sqri(x), n); /* to garbage zone */\ avma = avx; x = addsi(delta,x); /* erase garbage */\ avma = GGG; P = mulii(P, subii(x1, x));\ avma = avP; P = modii(P,n); } STMT_END one_iter(); if ((--c & 0x1f)==0) { /* one round complete */ g = gcdii(n, P); if (!is_pm1(g)) goto fin; if (c <= 0) { /* getting bored */ if (DEBUGLEVEL >= 4) { err_printf("Rho: time = %6ld ms,\tPollard-Brent giving up.\n", timer_delay(&T)); err_flush(); } avma = av; return NULL; } P = gen_1; /* not necessary, but saves 1 mulii/round */ if (DEBUGLEVEL >= 4) rho_dbg(&T, c0-(c>>5), msg_mask); affii(x,y); } if (--k) continue; /* normal end of loop body */ if (c & 0x1f) /* otherwise, we already checked */ { g = gcdii(n, P); if (!is_pm1(g)) goto fin; P = gen_1; } /* Fast forward phase, doing l inner iterations without computing gcds. * Check first whether it would take us beyond the alloted time. * Fast forward rounds count only half (although they're taking * more like 2/3 the time of normal rounds). This to counteract the * nuisance that all c0 between 4096 and 6144 would act exactly as * 4096; with the halving trick only the range 4096..5120 collapses * (similarly for all other powers of two) */ if ((c -= (l>>1)) <= 0) { /* got bored */ if (DEBUGLEVEL >= 4) { err_printf("Rho: time = %6ld ms,\tPollard-Brent giving up.\n", timer_delay(&T)); err_flush(); } avma = av; return NULL; } c &= ~0x1f; /* keep it on multiples of 32 */ /* Fast forward loop */ affii(x, x1); k = l; l <<= 1; /* don't show this for the first several (short) fast forward phases. */ if (DEBUGLEVEL >= 4 && (l>>7) > msg_mask) { err_printf("Rho: fast forward phase (%ld rounds of 64)...\n", l>>7); err_flush(); } for (k1=k; k1; k1--) one_iter(); if (DEBUGLEVEL >= 4 && (l>>7) > msg_mask) { err_printf("Rho: time = %6ld ms,\t%3ld rounds, back to normal mode\n", timer_delay(&T), c0-(c>>5)); err_flush(); } affii(x,y); } /* forever */ fin: /* An accumulated gcd was > 1 */ /* if it isn't n, and looks prime, return it */ if (!equalii(g,n)) { if (MR_Jaeschke(g,17)) { if (DEBUGLEVEL >= 4) { rho_dbg(&T, c0-(c>>5), 0); err_printf("\tfound factor = %Ps\n",g); err_flush(); } avma = av; return icopy(g); } avma = avx; g1 = icopy(g); /* known composite, keep it safe */ avx = avma; } else g1 = n; /* and work modulo g1 for backtracking */ /* Here g1 is known composite */ if (DEBUGLEVEL >= 4 && size > 192) { err_printf("Rho: hang on a second, we got something here...\n"); err_flush(); } for(;;) /* backtrack until period recovered. Must terminate */ { avma = GGG; y = remii(sqri(y), g1); avma = avx; y = addsi(delta,y); g = gcdii(subii(x1, y), g1); if (!is_pm1(g)) break; if (DEBUGLEVEL >= 4 && (--c & 0x1f) == 0) rho_dbg(&T, c0-(c>>5), msg_mask); } avma = av; /* safe */ if (g1 == n || equalii(g,g1)) { if (g1 == n && equalii(g,g1)) { /* out of luck */ if (DEBUGLEVEL >= 4) { rho_dbg(&T, c0-(c>>5), 0); err_printf("\tPollard-Brent failed.\n"); err_flush(); } if (++retries >= 4) return NULL; goto PB_RETRY; } /* half lucky: we've split n, but g1 equals either g or n */ if (DEBUGLEVEL >= 4) { rho_dbg(&T, c0-(c>>5), 0); err_printf("\tfound %sfactor = %Ps\n", (g1!=n ? "composite " : ""), g); err_flush(); } res = cgetg(7, t_VEC); /* g^1: known composite when g1!=n */ INIT(res+1, icopy(g), gen_1, (g1!=n? gen_0: NULL)); /* cofactor^1: status unknown */ INIT(res+4, diviiexact(n,g), gen_1, NULL); return res; } /* g < g1 < n : our lucky day -- we've split g1, too */ res = cgetg(10, t_VEC); /* unknown status for all three factors */ INIT(res+1, icopy(g), gen_1, NULL); INIT(res+4, diviiexact(g1,g), gen_1, NULL); INIT(res+7, diviiexact(n,g1), gen_1, NULL); if (DEBUGLEVEL >= 4) { rho_dbg(&T, c0-(c>>5), 0); err_printf("\tfound factors = %Ps, %Ps,\n\tand %Ps\n", res[1], res[4], res[7]); err_flush(); } return res; } /***********************************************************************/ /** **/ /** FACTORIZATION (Shanks' SQUFOF) --GN2000Sep30-Oct01 **/ /** squfof() returns a nontrivial factor of n, assuming n is odd, **/ /** composite, not a pure square, and has no small prime divisor, **/ /** or NULL if it fails to find one. It works on two discriminants **/ /** simultaneously (n and 5n for n=1(4), 3n and 4n for n=3(4)). **/ /** Present implementation is limited to input <2^59, and works most **/ /** of the time in signed arithmetic on integers <2^31 in absolute **/ /** size. (Cf. Algo 8.7.2 in ACiCNT) **/ /** **/ /***********************************************************************/ /* The following is invoked to walk back along the ambiguous cycle* until we * hit an ambiguous form and thus the desired factor, which it returns. If it * fails for any reason, it returns 0. It doesn't interfere with timing and * diagnostics, which it leaves to squfof(). * * Before we invoke this, we've found a form (A, B, -C) with A = a^2, where a * isn't blacklisted and where gcd(a, B) = 1. According to ACiCANT, we should * now proceed reducing the form (a, -B, -aC), but it is easy to show that the * first reduction step always sends this to (-aC, B, a), and the next one, * with q computed as usual from B and a (occupying the c position), gives a * reduced form, whose third member is easiest to recover by going back to D. * From this point onwards, we're once again working with single-word numbers. * No need to track signs, just work with the abs values of the coefficients. */ static long squfof_ambig(long a, long B, long dd, GEN D) { long b, c, q, qc, qcb, a0, b0, b1, c0; long cnt = 0; /* count reduction steps on the cycle */ q = (dd + (B>>1)) / a; b = ((q*a) << 1) - B; { pari_sp av = avma; c = itos(divis(shifti(subii(D, sqrs(b)), -2), a)); avma = av; } #ifdef DEBUG_SQUFOF err_printf("SQUFOF: ambigous cycle of discriminant %Ps\n", D); err_printf("SQUFOF: Form on ambigous cycle (%ld, %ld, %ld)\n", a, b, c); #endif a0 = a; b0 = b1 = b; /* end of loop detection and safeguard */ for (;;) /* reduced cycles are finite */ { /* reduction step */ c0 = c; if (c0 > dd) q = 1; else q = (dd + (b>>1)) / c0; if (q == 1) { qcb = c0 - b; b = c0 + qcb; c = a - qcb; } else { qc = q*c0; qcb = qc - b; b = qc + qcb; c = a - q*qcb; } a = c0; cnt++; if (b == b1) break; /* safeguard against infinite loop: recognize when we've walked the entire * cycle in vain. (I don't think this can actually happen -- exercise.) */ if (b == b0 && a == a0) return 0; b1 = b; } q = a&1 ? a : a>>1; if (DEBUGLEVEL >= 4) { if (q > 1) err_printf("SQUFOF: found factor %ld from ambiguous form\n" "\tafter %ld steps on the ambiguous cycle\n", q / ugcd(q,15), cnt); else err_printf("SQUFOF: ...found nothing on the ambiguous cycle\n" "\tafter %ld steps there\n", cnt); if (DEBUGLEVEL >= 6) err_printf("SQUFOF: squfof_ambig returned %ld\n", q); } return q; } #define SQUFOF_BLACKLIST_SZ 64 /* assume 2,3,5 do not divide n */ GEN squfof(GEN n) { ulong d1, d2; long tf = lgefint(n), nm4, cnt = 0; long a1, b1, c1, dd1, L1, a2, b2, c2, dd2, L2, a, q, c, qc, qcb; GEN D1, D2; pari_sp av = avma; long blacklist1[SQUFOF_BLACKLIST_SZ], blacklist2[SQUFOF_BLACKLIST_SZ]; long blp1 = 0, blp2 = 0; int act1 = 1, act2 = 1; #ifdef LONG_IS_64BIT if (tf > 3 || (tf == 3 && (ulong)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 return NULL; /* n too large */ /* now we have 5 < n < 2^59 */ nm4 = mod4(n); if (nm4 == 1) { /* n = 1 (mod4): run one iteration on D1 = n, another on D2 = 5n */ D1 = n; D2 = mului(5,n); d2 = itou(sqrti(D2)); dd2 = (long)((d2>>1) + (d2&1)); b2 = (long)((d2-1) | 1); /* b1, b2 will always stay odd */ } else { /* n = 3 (mod4): run one iteration on D1 = 3n, another on D2 = 4n */ D1 = mului(3,n); D2 = shifti(n,2); dd2 = itou(sqrti(n)); d2 = dd2 << 1; b2 = (long)(d2 & (~1UL)); /* largest even below d2, will stay even */ } d1 = itou(sqrti(D1)); b1 = (long)((d1-1) | 1); /* largest odd number not exceeding d1 */ c1 = itos(shifti(subii(D1, sqru((ulong)b1)), -2)); if (!c1) pari_err_BUG("squfof [caller of] (n or 3n is a square)"); c2 = itos(shifti(subii(D2, sqru((ulong)b2)), -2)); if (!c2) pari_err_BUG("squfof [caller of] (5n is a square)"); L1 = (long)usqrt(d1); L2 = (long)usqrt(d2); /* dd1 used to compute floor((d1+b1)/2) as dd1+floor(b1/2), without * overflowing the 31bit signed integer size limit. Same for dd2. */ dd1 = (long) ((d1>>1) + (d1&1)); a1 = a2 = 1; /* The two (identity) forms (a1,b1,-c1) and (a2,b2,-c2) are now set up. * * a1 and c1 represent the absolute values of the a,c coefficients; we keep * track of the sign separately, via the iteration counter cnt: when cnt is * even, c is understood to be negative, else c is positive and a < 0. * * L1, L2 are the limits for blacklisting small leading coefficients * on the principal cycle, to guarantee that when we find a square form, * its square root will belong to an ambiguous cycle (i.e. won't be an * earlier form on the principal cycle). * * When n = 3(mod 4), D2 = 12(mod 16), and b^2 is always 0 or 4 mod 16. * It follows that 4*a*c must be 4 or 8 mod 16, respectively, so at most * one of a,c can be divisible by 2 at most to the first power. This fact * is used a couple of times below. * * The flags act1, act2 remain true while the respective cycle is still * active; we drop them to false when we return to the identity form with- * out having found a square form (or when the blacklist overflows, which * shouldn't happen). */ if (DEBUGLEVEL >= 4) err_printf("SQUFOF: entering main loop with forms\n" "\t(1, %ld, %ld) and (1, %ld, %ld)\n\tof discriminants\n" "\t%Ps and %Ps, respectively\n", b1, -c1, b2, -c2, D1, D2); /* MAIN LOOP: walk around the principal cycle looking for a square form. * Blacklist small leading coefficients. * * The reduction operator can be computed entirely in 32-bit arithmetic: * Let q = floor(floor((d1+b1)/2)/c1) (when c1>dd1, q=1, which happens * often enough to special-case it). Then the new b1 = (q*c1-b1) + q*c1, * which does not overflow, and the new c1 = a1 - q*(q*c1-b1), which is * bounded by d1 in abs size since both the old and the new a1 are positive * and bounded by d1. */ while (act1 || act2) { if (act1) { /* send first form through reduction operator if active */ c = c1; q = (c > dd1)? 1: (dd1 + (b1>>1)) / c; if (q == 1) { qcb = c - b1; b1 = c + qcb; c1 = a1 - qcb; } else { qc = q*c; qcb = qc - b1; b1 = qc + qcb; c1 = a1 - q*qcb; } a1 = c; if (a1 <= L1) { /* blacklist this */ if (blp1 >= SQUFOF_BLACKLIST_SZ) /* overflows: shouldn't happen */ act1 = 0; /* silently */ else { if (DEBUGLEVEL >= 6) err_printf("SQUFOF: blacklisting a = %ld on first cycle\n", a1); blacklist1[blp1++] = a1; } } } if (act2) { /* send second form through reduction operator if active */ c = c2; q = (c > dd2)? 1: (dd2 + (b2>>1)) / c; if (q == 1) { qcb = c - b2; b2 = c + qcb; c2 = a2 - qcb; } else { qc = q*c; qcb = qc - b2; b2 = qc + qcb; c2 = a2 - q*qcb; } a2 = c; if (a2 <= L2) { /* blacklist this */ if (blp2 >= SQUFOF_BLACKLIST_SZ) /* overflows: shouldn't happen */ act2 = 0; /* silently */ else { if (DEBUGLEVEL >= 6) err_printf("SQUFOF: blacklisting a = %ld on second cycle\n", a2); blacklist2[blp2++] = a2; } } } /* bump counter, loop if this is an odd iteration (i.e. if the real * leading coefficients are negative) */ if (++cnt & 1) continue; /* second half of main loop entered only when the leading coefficients * are positive (i.e., during even-numbered iterations) */ /* examine first form if active */ if (act1 && a1 == 1) /* back to identity */ { /* drop this discriminant */ act1 = 0; if (DEBUGLEVEL >= 4) err_printf("SQUFOF: first cycle exhausted after %ld iterations,\n" "\tdropping it\n", cnt); } if (act1) { if (uissquareall((ulong)a1, (ulong*)&a)) { /* square form */ if (DEBUGLEVEL >= 4) err_printf("SQUFOF: square form (%ld^2, %ld, %ld) on first cycle\n" "\tafter %ld iterations\n", a, b1, -c1, cnt); if (a <= L1) { /* blacklisted? */ long j; for (j = 0; j < blp1; j++) if (a == blacklist1[j]) { a = 0; break; } } if (a > 0) { /* not blacklisted */ q = ugcd(a, b1); /* imprimitive form? */ if (q > 1) { /* q^2 divides D1 hence n [ assuming n % 3 != 0 ] */ avma = av; if (DEBUGLEVEL >= 4) err_printf("SQUFOF: found factor %ld^2\n", q); return mkvec3(utoipos(q), gen_2, NULL);/* exponent 2, unknown status */ } /* chase the inverse root form back along the ambiguous cycle */ q = squfof_ambig(a, b1, dd1, D1); if (nm4 == 3 && q % 3 == 0) q /= 3; if (q > 1) { avma = av; return utoipos(q); } /* SUCCESS! */ } else if (DEBUGLEVEL >= 4) /* blacklisted */ err_printf("SQUFOF: ...but the root form seems to be on the " "principal cycle\n"); } } /* examine second form if active */ if (act2 && a2 == 1) /* back to identity form */ { /* drop this discriminant */ act2 = 0; if (DEBUGLEVEL >= 4) err_printf("SQUFOF: second cycle exhausted after %ld iterations,\n" "\tdropping it\n", cnt); } if (act2) { if (uissquareall((ulong)a2, (ulong*)&a)) { /* square form */ if (DEBUGLEVEL >= 4) err_printf("SQUFOF: square form (%ld^2, %ld, %ld) on second cycle\n" "\tafter %ld iterations\n", a, b2, -c2, cnt); if (a <= L2) { /* blacklisted? */ long j; for (j = 0; j < blp2; j++) if (a == blacklist2[j]) { a = 0; break; } } if (a > 0) { /* not blacklisted */ q = ugcd(a, b2); /* imprimitive form? */ /* NB if b2 is even, a is odd, so the gcd is always odd */ if (q > 1) { /* q^2 divides D2 hence n [ assuming n % 5 != 0 ] */ avma = av; if (DEBUGLEVEL >= 4) err_printf("SQUFOF: found factor %ld^2\n", q); return mkvec3(utoipos(q), gen_2, NULL);/* exponent 2, unknown status */ } /* chase the inverse root form along the ambiguous cycle */ q = squfof_ambig(a, b2, dd2, D2); if (nm4 == 1 && q % 5 == 0) q /= 5; if (q > 1) { avma = av; return utoipos(q); } /* SUCCESS! */ } else if (DEBUGLEVEL >= 4) /* blacklisted */ err_printf("SQUFOF: ...but the root form seems to be on the " "principal cycle\n"); } } } /* end main loop */ /* both discriminants turned out to be useless. */ if (DEBUGLEVEL>=4) err_printf("SQUFOF: giving up\n"); avma = av; return NULL; } /***********************************************************************/ /* */ /* DETECTING ODD POWERS --GN1998Jun28 */ /* Factoring engines like MPQS which ultimately rely on computing */ /* gcd(N, x^2-y^2) to find a nontrivial factor of N can't split */ /* N = p^k for an odd prime p, since (Z/p^k)^* is then cyclic. Here */ /* is an analogue of Z_issquareall() for 3rd, 5th and 7th powers. */ /* The general case is handled by is_kth_power */ /* */ /***********************************************************************/ /* Multistage sieve. First stages work mod 211, 209, 61, 203 in this order * (first reduce mod the product of these and then take the remainder apart). * Second stages use 117, 31, 43, 71. Moduli which are no longer interesting * are skipped. Everything is encoded in a table of 106 24-bit masks. We only * need the first half of the residues. Three bits per modulus indicate which * residues are 7th (bit 2), 5th (bit 1) or 3rd (bit 0) powers; the eight * moduli above are assigned right-to-left. The table was generated using: */ #if 0 L = [71, 43, 31, [O(3^2),O(13)], [O(7),O(29)], 61, [O(11),O(19)], 211]; ispow(x, N, k)= { if (type(N) == "t_INT", return (ispower(Mod(x,N), k))); for (i = 1, #N, if (!ispower(x + N[i], k), return (0))); 1 } check(r) = { print1(" 0"); for (i=1,#L, N = 0; if (ispow(r, L[i], 3), N += 1); if (ispow(r, L[i], 5), N += 2); if (ispow(r, L[i], 7), N += 4); print1(N); ); print("ul, /* ", r, " */") } for (r = 0, 105, check(r)) #endif static ulong powersmod[106] = { 077777777ul, /* 0 */ 077777777ul, /* 1 */ 013562440ul, /* 2 */ 012402540ul, /* 3 */ 013562440ul, /* 4 */ 052662441ul, /* 5 */ 016603440ul, /* 6 */ 016463450ul, /* 7 */ 013573551ul, /* 8 */ 012462540ul, /* 9 */ 012462464ul, /* 10 */ 013462771ul, /* 11 */ 012406473ul, /* 12 */ 012463641ul, /* 13 */ 052463646ul, /* 14 */ 012503446ul, /* 15 */ 013562440ul, /* 16 */ 052466440ul, /* 17 */ 012472451ul, /* 18 */ 012462454ul, /* 19 */ 032463550ul, /* 20 */ 013403664ul, /* 21 */ 013463460ul, /* 22 */ 032562565ul, /* 23 */ 012402540ul, /* 24 */ 052662441ul, /* 25 */ 032672452ul, /* 26 */ 013573551ul, /* 27 */ 012467541ul, /* 28 */ 012567640ul, /* 29 */ 032706450ul, /* 30 */ 012762452ul, /* 31 */ 033762662ul, /* 32 */ 012502562ul, /* 33 */ 032463562ul, /* 34 */ 013563440ul, /* 35 */ 016663440ul, /* 36 */ 036662550ul, /* 37 */ 012462552ul, /* 38 */ 033502450ul, /* 39 */ 012462643ul, /* 40 */ 033467540ul, /* 41 */ 017403441ul, /* 42 */ 017463462ul, /* 43 */ 017472460ul, /* 44 */ 033462470ul, /* 45 */ 052566450ul, /* 46 */ 013562640ul, /* 47 */ 032403640ul, /* 48 */ 016463450ul, /* 49 */ 016463752ul, /* 50 */ 033402440ul, /* 51 */ 012462540ul, /* 52 */ 012472540ul, /* 53 */ 053562462ul, /* 54 */ 012463465ul, /* 55 */ 012663470ul, /* 56 */ 052607450ul, /* 57 */ 012566553ul, /* 58 */ 013466440ul, /* 59 */ 012502741ul, /* 60 */ 012762744ul, /* 61 */ 012763740ul, /* 62 */ 012763443ul, /* 63 */ 013573551ul, /* 64 */ 013462471ul, /* 65 */ 052502460ul, /* 66 */ 012662463ul, /* 67 */ 012662451ul, /* 68 */ 012403550ul, /* 69 */ 073567540ul, /* 70 */ 072463445ul, /* 71 */ 072462740ul, /* 72 */ 012472442ul, /* 73 */ 012462644ul, /* 74 */ 013406650ul, /* 75 */ 052463471ul, /* 76 */ 012563474ul, /* 77 */ 013503460ul, /* 78 */ 016462441ul, /* 79 */ 016462440ul, /* 80 */ 012462540ul, /* 81 */ 013462641ul, /* 82 */ 012463454ul, /* 83 */ 013403550ul, /* 84 */ 057563540ul, /* 85 */ 017466441ul, /* 86 */ 017606471ul, /* 87 */ 053666573ul, /* 88 */ 012562561ul, /* 89 */ 013473641ul, /* 90 */ 032573440ul, /* 91 */ 016763440ul, /* 92 */ 016702640ul, /* 93 */ 033762552ul, /* 94 */ 012562550ul, /* 95 */ 052402451ul, /* 96 */ 033563441ul, /* 97 */ 012663561ul, /* 98 */ 012677560ul, /* 99 */ 012462464ul, /* 100 */ 032562642ul, /* 101 */ 013402551ul, /* 102 */ 032462450ul, /* 103 */ 012467445ul, /* 104 */ 032403440ul, /* 105 */ }; static int check_res(ulong x, ulong N, int shift, ulong *mask) { long r = x%N; if ((ulong)r> (N>>1)) r = N - r; *mask &= (powersmod[r] >> shift); return *mask; } /* is x mod 211*209*61*203*117*31*43*71 a 3rd, 5th or 7th power ? */ int uis_357_powermod(ulong x, ulong *mask) { if ( !check_res(x, 211UL, 0, mask)) return 0; if (*mask & 3 && !check_res(x, 209UL, 3, mask)) return 0; if (*mask & 3 && !check_res(x, 61UL, 6, mask)) return 0; if (*mask & 5 && !check_res(x, 203UL, 9, mask)) return 0; if (*mask & 1 && !check_res(x, 117UL,12, mask)) return 0; if (*mask & 3 && !check_res(x, 31UL,15, mask)) return 0; if (*mask & 5 && !check_res(x, 43UL,18, mask)) return 0; if (*mask & 6 && !check_res(x, 71UL,21, mask)) return 0; return 1; } /* asume x > 0 and pt != NULL */ int uis_357_power(ulong x, ulong *pt, ulong *mask) { double logx; if (!odd(x)) { long v = vals(x); if (v % 7) *mask &= ~4; if (v % 5) *mask &= ~2; if (v % 3) *mask &= ~1; if (!*mask) return 0; } if (!uis_357_powermod(x, mask)) return 0; logx = log((double)x); while (*mask) { long e, b; ulong y, ye; if (*mask & 1) { b = 1; e = 3; } else if (*mask & 2) { b = 2; e = 5; } else { b = 4; e = 7; } y = (ulong)(exp(logx / e) + 0.5); ye = upowuu(y,e); if (ye == x) { *pt = y; return e; } #ifdef LONG_IS_64BIT if (ye > x) y--; else y++; ye = upowuu(y,e); if (ye == x) { *pt = y; return e; } #endif *mask &= ~b; /* turn the bit off */ } return 0; } #ifndef LONG_IS_64BIT /* as above, split in two functions */ /* is x mod 211*209*61*203 a 3rd, 5th or 7th power ? */ static int uis_357_powermod_32bit_1(ulong x, ulong *mask) { if ( !check_res(x, 211UL, 0, mask)) return 0; if (*mask & 3 && !check_res(x, 209UL, 3, mask)) return 0; if (*mask & 3 && !check_res(x, 61UL, 6, mask)) return 0; if (*mask & 5 && !check_res(x, 203UL, 9, mask)) return 0; return 1; } /* is x mod 117*31*43*71 a 3rd, 5th or 7th power ? */ static int uis_357_powermod_32bit_2(ulong x, ulong *mask) { if (*mask & 1 && !check_res(x, 117UL,12, mask)) return 0; if (*mask & 3 && !check_res(x, 31UL,15, mask)) return 0; if (*mask & 5 && !check_res(x, 43UL,18, mask)) return 0; if (*mask & 6 && !check_res(x, 71UL,21, mask)) return 0; return 1; } #endif /* Returns 3, 5, or 7 if x is a cube (but not a 5th or 7th power), a 5th * power (but not a 7th), or a 7th power, and in this case creates the * base on the stack and assigns its address to *pt. Otherwise returns 0. * x must be of type t_INT and positive; this is not checked. The *mask * argument tells us which things to check -- bit 0: 3rd, bit 1: 5th, * bit 2: 7th pwr; set a bit to have the corresponding power examined -- * and is updated appropriately for a possible follow-up call */ int is_357_power(GEN x, GEN *pt, ulong *mask) { long lx = lgefint(x); ulong r; pari_sp av; GEN y; if (!*mask) return 0; /* useful when running in a loop */ if (DEBUGLEVEL>4) err_printf("OddPwrs: examining %ld-bit integer\n", expi(x)); if (lgefint(x) == 3) { ulong t; long e = uis_357_power(x[2], &t, mask); if (e) { if (pt) *pt = utoi(t); return e; } return 0; } #ifdef LONG_IS_64BIT r = (lx == 3)? (ulong)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); if (!uis_357_powermod_32bit_1(r, mask)) return 0; r = (lx == 3)? (ulong)x[2]: umodiu(x, 117*31*43*71); if (!uis_357_powermod_32bit_2(r, mask)) return 0; #endif av = avma; while (*mask) { long e, b; /* priority to higher powers: if we have a 21st, it is easier to rediscover * that its 7th root is a cube than that its cube root is a 7th power */ if (*mask & 4) { b = 4; e = 7; } else if (*mask & 2) { b = 2; e = 5; } else { b = 1; e = 3; } y = mpround( sqrtnr(itor(x, nbits2prec(64 + bit_accuracy(lx) / e)), e) ); if (equalii(powiu(y,e), x)) { if (!pt) { avma = av; return e; } avma = (pari_sp)y; *pt = gerepileuptoint(av, y); return e; } if (DEBUGLEVEL>4) err_printf("\tBut it nevertheless wasn't a %ld%s power.\n", e,eng_ord(e)); *mask &= ~b; /* turn the bit off */ avma = av; } return 0; } /* Is x a n-th power ? * if d = NULL, n not necessarily prime, otherwise, n prime and d the * corresponding diffptr to go on looping over primes. * If pt != NULL, it receives the n-th root */ ulong is_kth_power(GEN x, ulong n, GEN *pt) { forprime_t T; long j; ulong q, residue; GEN y; pari_sp av = avma; (void)u_forprime_arith_init(&T, odd(n)? 2*n+1: n+1, ULONG_MAX, 1,n); /* we'll start at q, smallest prime >= n */ /* Modular checks, use small primes q congruent 1 mod n */ /* A non n-th power nevertheless passes the test with proba n^(-#checks), * We'd like this < 1e-6 but let j = floor(log(1e-6) / log(n)) which * ensures much less. */ if (n < 16) j = 5; else if (n < 32) j = 4; else if (n < 101) j = 3; else if (n < 1001) j = 2; else if (n < 17886697) /* smallest such that smallest suitable q is > 2^32 */ j = 1; else j = 0; for (; j > 0; j--) { if (!(q = u_forprime_next(&T))) break; /* q a prime = 1 mod n */ residue = umodiu(x, q); if (residue == 0) { if (Z_lval(x,q) % n) { avma = av; return 0; } continue; } /* n-th power mod q ? */ if (Fl_powu(residue, (q-1)/n, q) != 1) { avma = av; return 0; } } avma = av; if (DEBUGLEVEL>4) err_printf("\nOddPwrs: [%lu] passed modular checks\n",n); /* go to the horse's mouth... */ y = roundr( sqrtnr(itor(x, nbits2prec((expi(x)+16*n)/n)), n) ); if (!equalii(powiu(y, n), x)) { if (DEBUGLEVEL>4) err_printf("\tBut it wasn't a pure power.\n"); avma = av; return 0; } if (!pt) avma = av; else { avma = (pari_sp)y; *pt = gerepileuptoint(av, y); } return 1; } /* is x a p^i-th power, p >= 11 prime ? Similar to is_357_power(), but instead * of the mask, we keep the current test exponent around. Cut off when * log_2 x^(1/k) < cutoffbits since we would have found it by trial division. * Everything needed here (primitive roots etc.) is computed from scratch on * the fly; compared to the size of numbers under consideration, these * word-sized computations take negligible time. * Any cutoffbits > 0 is safe, but direct root extraction attempts are faster * when trial division has been used to discover very small bases. We become * competitive at cutoffbits ~ 10 */ int is_pth_power(GEN x, GEN *pt, forprime_t *T, ulong cutoffbits) { long cnt=0, size = expi(x) /* not +1 */; ulong p; pari_sp av = avma; while ((p = u_forprime_next(T)) && size/p >= cutoffbits) { long v = 1; if (DEBUGLEVEL>5 && cnt++==2000) { cnt=0; err_printf("%lu%% ", 100*p*cutoffbits/size); } while (is_kth_power(x, p, pt)) { v *= p; x = *pt; size = expi(x); } if (v > 1) { if (DEBUGLEVEL>5) err_printf("\nOddPwrs: is a %ld power\n",v); return v; } } if (DEBUGLEVEL>5) err_printf("\nOddPwrs: not a power\n",p); avma = av; return 0; /* give up */ } /***********************************************************************/ /** **/ /** FACTORIZATION (master iteration) **/ /** Driver for the various methods of finding large factors **/ /** (after trial division has cast out the very small ones). **/ /** GN1998Jun24--30 **/ /** **/ /***********************************************************************/ /* Direct use: * ifac_start_hint(n,moebius,hint) registers with the iterative factorizer * - an integer n (without prime factors < tridiv_bound(n)) * - registers whether or not we should terminate early if we find a square * factor, * - a hint about which method(s) to use. * This must always be called first. If input is not composite, oo loop. * The routine decomposes n nontrivially into a product of two factors except * in squarefreeness ('Moebius') mode. * * ifac_start(n,moebius) same using default hint. * * ifac_primary_factor() returns a prime divisor (not necessarily the * smallest) and the corresponding exponent. * * Encapsulated user interface: Many arithmetic functions have a 'contributor' * ifac_xxx, to be called on any large composite cofactor left over after trial * division by small primes: xxx is one of moebius, issquarefree, totient, etc. * * We never test whether the input number is prime or composite, since * presumably it will have come out of the small factors finder stage * (which doesn't really exist yet but which will test the left-over * cofactor for primality once it does). */ /* The data structure in which we preserve whatever we know about our number N * is kept on the PARI stack, and updated as needed. * This makes the machinery re-entrant, and avoids memory leaks when a lengthy * factorization is interrupted. We try to keep the whole affair connected, * and the parent object is always older than its children. This may in * rare cases lead to some extra copying around, and knowing what is garbage * at any given time is not trivial. See below for examples how to do it right. * (Connectedness is destroyed if callers of ifac_main() create stuff on the * stack in between calls. This is harmless as long as ifac_realloc() is used * to re-create a connected object at the head of the stack just before * collecting garbage.) * A t_INT may well have > 10^6 distinct prime factors larger than 2^16. Since * we need not find factors in order of increasing size, we must be prepared to * drag a very large amount of data around. We start with a small structure * and extend it when necessary. */ /* The idea of the algorithm is: * Let N0 be whatever is currently left of N after dividing off all the * prime powers we have already returned to the caller. Then we maintain * N0 as a product * (1) N0 = \prod_i P_i^{e_i} * \prod_j Q_j^{f_j} * \prod_k C_k^{g_k} * where the P_i and Q_j are distinct primes, each C_k is known composite, * none of the P_i divides any C_k, and we also know the total ordering * of all the P_i, Q_j and C_k; in particular, we will never try to divide * a C_k by a larger Q_j. Some of the C_k may have common factors. * * Caveat implementor: Taking gcds among C_k's is very likely to cost at * least as much time as dividing off any primes as we find them, and book- * keeping would be tough (since D=gcd(C_1,C_2) can still have common factors * with both C_1/D and C_2/D, and so on...). * * At startup, we just initialize the structure to * (2) N = C_1^1 (composite). * * Whenever ifac_primary_factor() or one of the arithmetic user interface * routines needs a primary factor, and the smallest thing in our list is P_1, * we return that and its exponent, and remove it from our list. (When nothing * is left, we return a sentinel value -- gen_1. And in Moebius mode, when we * see something with exponent > 1, whether prime or composite, we return gen_0 * or 0, depending on the function). In all other cases, ifac_main() iterates * the following steps until we have a P_1 in the smallest position. * * When the smallest item is C_1, as it is initially: * (3.1) Crack C_1 into a nontrivial product U_1 * U_2 by whatever method * comes to mind for this size. (U for 'unknown'.) Cracking will detect * perfect powers, so we may instead see a power of some U_1 here, or even * something of the form U_1^k*U_2^k; of course the exponent already attached * to C_1 is taken into account in the following. * (3.2) If we have U_1*U_2, sort the two factors (distinct: squares are caught * in stage 3.1). N.B. U_1 and U_2 are smaller than anything else in our list. * (3.3) Check U_1 and U_2 for primality, and flag them accordingly. * (3.4) Iterate. * * When the smallest item is Q_1: * This is the unpleasant case. We go through the entire list and try to * divide Q_1 off each of the current C_k's, which usually fails, but may * succeed several times. When a division was successful, the corresponding * C_k is removed from our list, and the cofactor becomes a U_l for the moment * unless it is 1 (which happens when C_k was a power of Q_1). When we're * through we upgrade Q_1 to P_1 status, then do a primality check on each U_l * and sort it back into the list either as a Q_j or as a C_k. If during the * insertion sort we discover that some U_l equals some P_i or Q_j or C_k we * already have, we just add U_l's exponent to that of its twin. (The sorting * therefore happens before the primality test). Since this may produce one or * more elements smaller than the P_1 we just confirmed, we may have to repeat * the iteration. * A trick avoids some Q_1 instances: just after the sweep classifying * all current unknowns as either composites or primes, we do another downward * sweep beginning with the largest current factor and stopping just above the * largest current composite. Every Q_j we pass is turned into a P_i. * (Different primes are automatically coprime among each other, and primes do * not divide smaller composites.) * NB: We have no use for comparing the square of a prime to N0. Normally * we will get called after casting out only the smallest primes, and * since we cannot guarantee that we see the large prime factors in as- * cending order, we cannot stop when we find one larger than sqrt(N0). */ /* Data structure: We keep everything in a single t_VEC of t_INTs. The * first 2 components are read-only: * 1) the first records whether we're doing full (NULL) or Moebius (gen_1) * factorization; in the latter case subroutines return a sentinel value as * soon as they spot an exponent > 1. * 2) the second records the hint from factorint()'s optional flag, for use by * ifac_crack(). * * The remaining components (initially 15) are used in groups of three: * [ factor (t_INT), exponent (t_INT), factor class ], where factor class is * NULL : unknown * gen_0: known composite C_k * gen_1: known prime Q_j awaiting trial division * gen_2: finished prime P_i. * When during the division stage we re-sort a C_k-turned-U_l to a lower * position, we rotate any intervening material upward towards its old * slot. When a C_k was divided down to 1, its slot is left empty at * first; similarly when the re-sorting detects a repeated factor. * After the sorting phase, we de-fragment the list and squeeze all the * occupied slots together to the high end, so that ifac_crack() has room * for new factors. When this doesn't suffice, we abandon the current vector * and allocate a somewhat larger one, defragmenting again while copying. * * For internal use: note that all exponents will fit into C longs, given * PARI's lgefint field size. When we work with them, we sometimes read * out the GEN pointer, and sometimes do an itos, whatever is more con- * venient for the task at hand. */ /*** Overview ***/ /* The '*where' argument in the following points into *partial at the first of * the three fields of the first occupied slot. It's there because the caller * would already know where 'here' is, so we don't want to search for it again. * We do not preserve this from one user-interface call to the next. */ /* In the most common cases, control flows from the user interface to * ifac_main() and then to a succession of ifac_crack()s and ifac_divide()s, * with (typically) none of the latter finding anything. */ static long ifac_insert_multiplet(GEN *, GEN *, GEN, long); #define LAST(x) x+lg(x)-3 #define FIRST(x) x+3 #define MOEBIUS(x) gel(x,1) #define HINT(x) gel(x,2) /* y <- x */ INLINE void SHALLOWCOPY(GEN x, GEN y) { VALUE(y) = VALUE(x); EXPON(y) = EXPON(x); CLASS(y) = CLASS(x); } /* y <- x */ INLINE void COPY(GEN x, GEN y) { icopyifstack(VALUE(x), VALUE(y)); icopyifstack(EXPON(x), EXPON(y)); CLASS(y) = CLASS(x); } /* Diagnostics */ static void ifac_factor_dbg(GEN x) { GEN c = CLASS(x), v = VALUE(x); if (c == gen_2) err_printf("IFAC: factor %Ps\n\tis prime (finished)\n", v); else if (c == gen_1) err_printf("IFAC: factor %Ps\n\tis prime\n", v); else if (c == gen_0) err_printf("IFAC: factor %Ps\n\tis composite\n", v); } static void ifac_check(GEN partial, GEN where) { if (!where || where < FIRST(partial) || where > LAST(partial)) pari_err_BUG("ifac_check ['where' out of bounds]"); } static void ifac_print(GEN part, GEN where) { long l = lg(part); GEN p; err_printf("ifac partial factorization structure: %ld slots, ", (l-3)/3); if (MOEBIUS(part)) err_printf("Moebius mode, "); err_printf("hint = %ld\n", itos(HINT(part))); ifac_check(part, where); for (p = part+3; p < part + l; p += 3) { GEN v = VALUE(p), e = EXPON(p), c = CLASS(p); const char *s = ""; if (!v) { err_printf("[empty slot]\n"); continue; } if (c == NULL) s = "unknown"; else if (c == gen_0) s = "composite"; else if (c == gen_1) s = "unfinished prime"; else if (c == gen_2) s = "prime"; else pari_err_BUG("unknown factor class"); err_printf("[%Ps, %Ps, %s]\n", v, e, s); } err_printf("Done.\n"); } static const long decomp_default_hint = 0; /* assume n a non-zero t_INT */ /* return initial data structure, see ifac_crack() for the hint argument */ static GEN ifac_start_hint(GEN n, int moebius, long hint) { const long ifac_initial_length = 3 + 7*3; /* codeword, moebius, hint, 7 slots -- a 512-bit product of distinct 8-bit * primes needs at most 7 slots at a time) */ GEN here, part = cgetg(ifac_initial_length, t_VEC); MOEBIUS(part) = moebius? gen_1 : NULL; HINT(part) = stoi(hint); if (isonstack(n)) n = absi(n); /* make copy, because we'll later want to replace it in place. * If it's not on stack, then we assume it is a clone made for us by * ifactor, and we assume the sign has already been set positive */ /* fill first slot at the top end */ here = part + ifac_initial_length - 3; /* LAST(part) */ INIT(here, n,gen_1,gen_0); /* n^1: composite */ while ((here -= 3) > part) ifac_delete(here); return part; } GEN ifac_start(GEN n, int moebius) { return ifac_start_hint(n,moebius,decomp_default_hint); } /* Return next nonempty slot after 'here', NULL if none exist */ static GEN ifac_find(GEN partial) { GEN scan, end = partial + lg(partial); #ifdef IFAC_DEBUG ifac_check(partial, partial); #endif for (scan = partial+3; scan < end; scan += 3) if (VALUE(scan)) return scan; return NULL; } /* Defragment: squeeze out unoccupied slots above *where. Unoccupied slots * arise when a composite factor dissolves completely whilst dividing off a * prime, or when ifac_resort() spots a coincidence and merges two factors. * Update *where */ static void ifac_defrag(GEN *partial, GEN *where) { GEN scan_new = LAST(*partial), scan_old; for (scan_old = scan_new; scan_old >= *where; scan_old -= 3) { if (!VALUE(scan_old)) continue; /* empty slot */ if (scan_old < scan_new) SHALLOWCOPY(scan_old, scan_new); scan_new -= 3; /* point at next slot to be written */ } scan_new += 3; /* back up to last slot written */ *where = scan_new; while ((scan_new -= 3) > *partial) ifac_delete(scan_new); /* erase junk */ } /* Move to a larger main vector, updating *where if it points into it, and * *partial in any case. Can be used as a specialized gcopy before * a gerepileupto() (pass 0 as the new length). Normally, one would pass * new_lg=1 to let this function guess the new size. To be used sparingly. * Complex version of ifac_defrag(), combined with reallocation. If new_lg * is 0, use the old length, so this acts just like gcopy except that the * 'where' pointer is carried along; if it is 1, we make an educated guess. * Exception: If new_lg is 0, the vector is full to the brim, and the first * entry is composite, we make it longer to avoid being called again a * microsecond later. It is safe to call this with *where = NULL: * if it doesn't point anywhere within the old structure, it is left alone */ static void ifac_realloc(GEN *partial, GEN *where, long new_lg) { long old_lg = lg(*partial); GEN newpart, scan_new, scan_old; if (new_lg == 1) new_lg = 2*old_lg - 6; /* from 7 slots to 13 to 25... */ else if (new_lg <= old_lg) /* includes case new_lg == 0 */ { GEN first = *partial + 3; new_lg = old_lg; /* structure full and first entry composite or unknown */ if (VALUE(first) && (CLASS(first) == gen_0 || CLASS(first)==NULL)) new_lg += 6; /* give it a little more breathing space */ } newpart = cgetg(new_lg, t_VEC); if (DEBUGMEM >= 3) err_printf("IFAC: new partial factorization structure (%ld slots)\n", (new_lg - 3)/3); MOEBIUS(newpart) = MOEBIUS(*partial); icopyifstack(HINT(*partial), HINT(newpart)); /* Downward sweep through the old *partial. Pick up 'where' and carry it * over if we pass it. (Only useful if it pointed at a non-empty slot.) * Factors are COPY'd so that we again have a nice object (parent older * than children, connected), except the one factor that may still be living * in a clone where n originally was; exponents are similarly copied if they * aren't global constants; class-of-factor fields are global constants so we * need only copy them as pointers. Caller may then do a gerepileupto() */ scan_new = newpart + new_lg - 3; /* LAST(newpart) */ scan_old = *partial + old_lg - 3; /* LAST(*partial) */ for (; scan_old > *partial + 2; scan_old -= 3) { if (*where == scan_old) *where = scan_new; if (!VALUE(scan_old)) continue; /* skip empty slots */ COPY(scan_old, scan_new); scan_new -= 3; } scan_new += 3; /* back up to last slot written */ while ((scan_new -= 3) > newpart) ifac_delete(scan_new); *partial = newpart; } /* Re-sort one (typically unknown) entry from washere to a new position, * rotating intervening entries upward to fill the vacant space. If the new * position is the same as the old one, or the new value of the entry coincides * with a value already occupying a lower slot, then we just add exponents (and * use the 'more known' class, and return 1 immediately when in Moebius mode). * Slots between *where and washere must be in sorted order, so a sweep using * this to re-sort several unknowns must proceed upward, see ifac_resort(). * Bubble-sort-of-thing sort. Won't be exercised frequently, so this is ok */ static void ifac_sort_one(GEN *where, GEN washere) { GEN old, scan = washere - 3; GEN value, exponent, class0, class1; long cmp_res; if (scan < *where) return; /* nothing to do, washere==*where */ value = VALUE(washere); exponent = EXPON(washere); class0 = CLASS(washere); cmp_res = -1; /* sentinel */ while (scan >= *where) /* at least once */ { if (VALUE(scan)) { /* current slot nonempty, check against where */ cmp_res = cmpii(value, VALUE(scan)); if (cmp_res >= 0) break; /* have found where to stop */ } /* copy current slot upward by one position and move pointers down */ SHALLOWCOPY(scan, scan+3); scan -= 3; } scan += 3; /* At this point there are the following possibilities: * 1) cmp_res == -1. Either value is less than that at *where, or *where was * pointing at vacant slots and any factors we saw en route were larger than * value. At any rate, scan == *where now, and scan is pointing at an empty * slot, into which we'll stash our entry. * 2) cmp_res == 0. The entry at scan-3 is the one, we compare class0 * fields and add exponents, and put it all into the vacated scan slot, * NULLing the one at scan-3 (and possibly updating *where). * 3) cmp_res == 1. The slot at scan is the one to store our entry into. */ if (cmp_res) { if (cmp_res < 0 && scan != *where) pari_err_BUG("ifact_sort_one [misaligned partial]"); INIT(scan, value, exponent, class0); return; } /* case cmp_res == 0: repeated factor detected */ if (DEBUGLEVEL >= 4) err_printf("IFAC: repeated factor %Ps\n\tin ifac_sort_one\n", value); old = scan - 3; /* if old class0 was composite and new is prime, or vice versa, complain * (and if one class0 was unknown and the other wasn't, use the known one) */ class1 = CLASS(old); if (class0) /* should never be used */ { if (class1) { if (class0 == gen_0 && class1 != gen_0) pari_err_BUG("ifac_sort_one (composite = prime)"); else if (class0 != gen_0 && class1 == gen_0) pari_err_BUG("ifac_sort_one (prime = composite)"); else if (class0 == gen_2) CLASS(scan) = class0; } else CLASS(scan) = class0; } /* else stay with the existing known class0 */ CLASS(scan) = class1; /* in any case, add exponents */ if (EXPON(old) == gen_1 && exponent == gen_1) EXPON(scan) = gen_2; else EXPON(scan) = addii(EXPON(old), exponent); /* move the value over and null out the vacated slot below */ old = scan - 3; *scan = *old; ifac_delete(old); /* finally, see whether *where should be pulled in */ if (old == *where) *where += 3; } /* Sort all current unknowns downward to where they belong. Sweeps in the * upward direction. Not needed after ifac_crack(), only when ifac_divide() * returned true. Update *where. */ static void ifac_resort(GEN *partial, GEN *where) { GEN scan, end; ifac_defrag(partial, where); end = LAST(*partial); for (scan = *where; scan <= end; scan += 3) if (VALUE(scan) && !CLASS(scan)) ifac_sort_one(where, scan); /*unknown*/ ifac_defrag(partial, where); /* remove newly created gaps */ } /* Let x be a t_INT known not to have small divisors (< 2^14). Return 0 if x * is a proven composite. Return 1 if we believe it to be prime (fully proven * prime if factor_proven is set). */ int ifac_isprime(GEN x) { if (!BPSW_psp_nosmalldiv(x)) return 0; /* composite */ if (factor_proven && ! BPSW_isprime(x)) { pari_warn(warner, "IFAC: pseudo-prime %Ps\n\tis not prime. PLEASE REPORT!\n", x); return 0; } return 1; } static int ifac_checkprime(GEN x) { int res = ifac_isprime(VALUE(x)); CLASS(x) = res? gen_1: gen_0; if (DEBUGLEVEL>2) ifac_factor_dbg(x); return res; } /* Determine primality or compositeness of all current unknowns, and set * class Q primes to finished (class P) if everything larger is already * known to be prime. When after_crack >= 0, only look at the * first after_crack things in the list (do nothing when it's 0) */ static void ifac_whoiswho(GEN *partial, GEN *where, long after_crack) { GEN scan, scan_end = LAST(*partial); #ifdef IFAC_DEBUG ifac_check(*partial, *where); #endif if (after_crack == 0) return; if (after_crack > 0) /* check at most after_crack entries */ scan = *where + 3*(after_crack - 1); /* assert(scan <= scan_end) */ else for (scan = scan_end; scan >= *where; scan -= 3) { if (CLASS(scan)) { /* known class of factor */ if (CLASS(scan) == gen_0) break; if (CLASS(scan) == gen_1) { if (DEBUGLEVEL>=3) { err_printf("IFAC: factor %Ps\n\tis prime (no larger composite)\n", VALUE(*where)); err_printf("IFAC: prime %Ps\n\tappears with exponent = %ld\n", VALUE(*where), itos(EXPON(*where))); } CLASS(scan) = gen_2; } continue; } if (!ifac_checkprime(scan)) break; /* must disable Q-to-P */ CLASS(scan) = gen_2; /* P_i, finished prime */ if (DEBUGLEVEL>2) ifac_factor_dbg(scan); } /* go on, Q-to-P trick now disabled */ for (; scan >= *where; scan -= 3) { if (CLASS(scan)) continue; (void)ifac_checkprime(scan); /* Qj | Ck */ } } /* Divide all current composites by first (prime, class Q) entry, updating its * exponent, and turning it into a finished prime (class P). Return 1 if any * such divisions succeeded (in Moebius mode, the update may then not have * been completed), or 0 if none of them succeeded. Doesn't modify *where. * Here we normally do not check that the first entry is a not-finished * prime. Stack management: we may allocate a new exponent */ static long ifac_divide(GEN *partial, GEN *where, long moebius_mode) { GEN scan, scan_end = LAST(*partial); long res = 0, exponent, newexp, otherexp; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (CLASS(*where) != gen_1) pari_err_BUG("ifac_divide [division by composite or finished prime]"); if (!VALUE(*where)) pari_err_BUG("ifac_divide [division by nothing]"); #endif newexp = exponent = itos(EXPON(*where)); if (exponent > 1 && moebius_mode) return 1; /* should've been caught by caller */ for (scan = *where+3; scan <= scan_end; scan += 3) { if (CLASS(scan) != gen_0) continue; /* the other thing ain't composite */ otherexp = 0; /* divide in place to keep stack clutter minimal */ while (dvdiiz(VALUE(scan), VALUE(*where), VALUE(scan))) { if (moebius_mode) return 1; /* immediately */ if (!otherexp) otherexp = itos(EXPON(scan)); newexp += otherexp; } if (newexp > exponent) /* did anything happen? */ { EXPON(*where) = (newexp == 2 ? gen_2 : utoipos(newexp)); exponent = newexp; if (is_pm1((GEN)*scan)) /* factor dissolved completely */ { ifac_delete(scan); if (DEBUGLEVEL >= 4) err_printf("IFAC: a factor was a power of another prime factor\n"); } else { CLASS(scan) = NULL; /* at any rate it's Unknown now */ if (DEBUGLEVEL >= 4) err_printf("IFAC: a factor was divisible by another prime factor,\n" "\tleaving a cofactor = %Ps\n", VALUE(scan)); } res = 1; if (DEBUGLEVEL >= 5) err_printf("IFAC: prime %Ps\n\tappears at least to the power %ld\n", VALUE(*where), newexp); } } /* for */ CLASS(*where) = gen_2; /* make it a finished prime */ if (DEBUGLEVEL >= 3) err_printf("IFAC: prime %Ps\n\tappears with exponent = %ld\n", VALUE(*where), newexp); return res; } /* found out our integer was factor^exp. Update */ static void update_pow(GEN where, GEN factor, long exp, pari_sp *av) { GEN ex = EXPON(where); if (DEBUGLEVEL>3) err_printf("IFAC: found %Ps =\n\t%Ps ^%ld\n", *where, factor, exp); affii(factor, VALUE(where)); avma = *av; if (ex == gen_1) { EXPON(where) = exp == 2? gen_2: utoipos(exp); *av = avma; } else if (ex == gen_2) { EXPON(where) = utoipos(exp<<1); *av = avma; } else affsi(exp * itos(ex), EXPON(where)); } /* hint == 0 : Use a default strategy * hint & 1 : Avoid mpqs(), use ellfacteur() after pollardbrent() * hint & 2 : Avoid first-stage ellfacteur() in favour of mpqs() * (may still fall back to ellfacteur() if mpqs() is not installed or gives up) * hint & 4 : Avoid even the pollardbrent() and squfof() stages. Put under * the same governing bit, for no good reason other than avoiding a * proliferation of bits. * hint & 8 : Avoid final ellfacteur(); this may declare a composite to be * prime. */ #define get_hint(partial) (itos(HINT(*partial)) & 15) /* Split the first (composite) entry. There _must_ already be room for another * factor below *where, and *where is updated. Two cases: * - entry = factor^k is a pure power: factor^k is inserted, leaving *where * unchanged; * - entry = factor * cofactor (not necessarily coprime): both factors are * inserted in the correct order, updating *where * The inserted factors class is set to unknown, they inherit the exponent * (or a multiple thereof) of their ancestor. * * Returns number of factors written into the structure, normally 2 (1 if pure * power, maybe > 2 if a factoring engine returned a vector of factors instead * of a single factor). Can reallocate the data structure in the * vector-of-factors case, not in the most common single-factor case. * Stack housekeeping: this routine may create one or more objects (a new * factor, or possibly several, and perhaps one or more new exponents > 2) */ static long ifac_crack(GEN *partial, GEN *where, long moebius_mode) { long cmp_res, hint = get_hint(partial); GEN factor, exponent; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (*where < *partial + 6) pari_err_BUG("ifac_crack ['*where' out of bounds]"); if (!(VALUE(*where)) || typ(VALUE(*where)) != t_INT) pari_err_BUG("ifac_crack [incorrect VALUE(*where)]"); if (CLASS(*where) != gen_0) pari_err_BUG("ifac_crack [operand not known composite]"); #endif if (DEBUGLEVEL>2) { err_printf("IFAC: cracking composite\n\t%Ps\n", **where); if (DEBUGLEVEL>3) err_printf("IFAC: checking for pure square\n"); } /* MPQS cannot factor prime powers. Look for pure powers even if MPQS is * blocked by hint: fast and useful in bounded factorization */ { forprime_t T; ulong exp = 1, mask = 7; long good = 0; pari_sp av = avma; (void)u_forprime_init(&T, 11, ULONG_MAX); /* crack squares */ while (Z_issquareall(VALUE(*where), &factor)) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, 2, &av); if (moebius_mode) return 0; /* no need to carry on */ } while ( (exp = is_357_power(VALUE(*where), &factor, &mask)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp, &av); if (moebius_mode) return 0; /* no need to carry on */ } /* cutoff at 14 bits as trial division must have found everything below */ while ( (exp = is_pth_power(VALUE(*where), &factor, &T, 15)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp, &av); if (moebius_mode) return 0; /* no need to carry on */ } if (good && hint != 15 && ifac_checkprime(*where)) { /* our composite was a prime power */ if (DEBUGLEVEL>3) err_printf("IFAC: factor %Ps\n\tis prime\n", VALUE(*where)); return 0; /* bypass subsequent ifac_whoiswho() call */ } } /* pure power stage */ factor = NULL; if (!(hint & 4)) { /* pollardbrent() Rho usually gets a first chance */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Pollard-Brent rho method\n"); factor = pollardbrent(VALUE(*where)); if (!factor) { /* Shanks' squfof() */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Shanks' SQUFOF, will fail silently if input\n" " is too large for it.\n"); factor = squfof(VALUE(*where)); } } if (!factor && !(hint & 2)) { /* First ECM stage */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Lenstra-Montgomery ECM\n"); factor = ellfacteur(VALUE(*where), 0); /* do not insist */ } if (!factor && !(hint & 1)) { /* MPQS stage */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying MPQS\n"); factor = mpqs(VALUE(*where)); } if (!factor) { if (!(hint & 8)) { /* still no luck? Final ECM stage, guaranteed to succeed */ if (DEBUGLEVEL >= 4) err_printf("IFAC: forcing ECM, may take some time\n"); factor = ellfacteur(VALUE(*where), 1); } else { /* limited factorization */ if (DEBUGLEVEL >= 2) { if (hint != 15) pari_warn(warner, "IFAC: unfactored composite declared prime"); else pari_warn(warner, "IFAC: untested integer declared prime"); /* don't print it out at level 3 or above, where it would appear * several times before and after this message already */ if (DEBUGLEVEL == 2) err_printf("\t%Ps\n", VALUE(*where)); } CLASS(*where) = gen_1; /* might as well trial-divide by it... */ return 1; } } if (typ(factor) == t_VEC) /* delegate this case */ return ifac_insert_multiplet(partial, where, factor, moebius_mode); /* typ(factor) == t_INT */ /* got single integer back: work out the cofactor (in place) */ if (!dvdiiz(VALUE(*where), factor, VALUE(*where))) { err_printf("IFAC: factoring %Ps\n", VALUE(*where)); err_printf("\tyielded 'factor' %Ps\n\twhich isn't!\n", factor); pari_err_BUG("factoring"); } /* factoring engines report the factor found; tell about the cofactor */ if (DEBUGLEVEL >= 4) err_printf("IFAC: cofactor = %Ps\n", VALUE(*where)); /* The two factors are 'factor' and VALUE(*where), find out which is larger */ cmp_res = cmpii(factor, VALUE(*where)); CLASS(*where) = NULL; /* mark factor /cofactor 'unknown' */ exponent = EXPON(*where); *where -= 3; CLASS(*where) = NULL; /* mark factor /cofactor 'unknown' */ EXPON(*where) = isonstack(exponent)? icopy(exponent): exponent; if (cmp_res < 0) VALUE(*where) = factor; /* common case */ else if (cmp_res > 0) { /* factor > cofactor, rearrange */ GEN old = *where + 3; VALUE(*where) = VALUE(old); /* move cofactor pointer to lowest slot */ VALUE(old) = factor; /* save factor */ } else pari_err_BUG("ifac_crack [Z_issquareall miss]"); return 2; } /* Gets called to complete ifac_crack's job when a factoring engine splits * the current factor into a product of three or more new factors. Makes room * for them if necessary, sorts them, gives them the right exponents and class. * Also returns the number of factors actually written, which may be less than * the number of components in facvec if there are duplicates.--- Vectors of * factors (cf pollardbrent()) actually contain 'slots' of three GENs per * factor with the three fields interpreted as in our partial factorization * data structure. Thus 'engines' can tell us what they already happen to * know about factors being prime or composite and/or appearing to a power * larger than the first. * Don't collect garbage. No diagnostics: the factoring engine should have * printed what it found. facvec contains slots of three components per factor; * repeated factors are allowed (and their classes shouldn't contradict each * other whereas their exponents will be added up) */ static long ifac_insert_multiplet(GEN *partial, GEN *where, GEN facvec, long moebius_mode) { long j,k=1, lfv=lg(facvec)-1, nf=lfv/3, room=(long)(*where-*partial); /* one of the factors will go into the *where slot, so room is now 3 times * the number of slots we can use */ long needroom = lfv - room; GEN e, newexp, cur, sorted, auxvec = cgetg(nf+1, t_VEC), factor; long exponent = itos(EXPON(*where)); /* the old exponent */ if (DEBUGLEVEL >= 5) /* squfof may return a single squared factor as a set */ err_printf("IFAC: incorporating set of %ld factor(s)\n", nf); if (needroom > 0) /* one extra slot for paranoia, errm, future use */ ifac_realloc(partial, where, lg(*partial) + needroom + 3); /* create sort permutation from the values of the factors */ for (j=nf; j; j--) auxvec[j] = facvec[3*j-2]; /* just the pointers */ sorted = indexsort(auxvec); /* and readjust the result for the triple spacing */ for (j=nf; j; j--) sorted[j] = 3*sorted[j]-2; /* store factors, beginning at *where, and catching any duplicates */ cur = facvec + sorted[nf]; VALUE(*where) = VALUE(cur); newexp = EXPON(cur); if (newexp != gen_1) /* new exponent > 1 */ { if (exponent == 1) e = isonstack(newexp)? icopy(newexp): newexp; else e = mului(exponent, newexp); EXPON(*where) = e; } /* if new exponent is 1, the old exponent already in place will do */ CLASS(*where) = CLASS(cur); if (DEBUGLEVEL >= 6) err_printf("\tstored (largest) factor no. %ld...\n", nf); for (j=nf-1; j; j--) { cur = facvec + sorted[j]; factor = VALUE(cur); if (equalii(factor, VALUE(*where))) { if (DEBUGLEVEL >= 6) err_printf("\tfactor no. %ld is a duplicate%s\n", j, (j>1? "...": "")); /* update exponent, ignore class which would already have been set, * then forget current factor */ newexp = EXPON(cur); if (newexp != gen_1) /* new exp > 1 */ e = addis(EXPON(*where), exponent * itos(newexp)); else if (EXPON(*where) == gen_1 && exponent == 1) e = gen_2; else e = addis(EXPON(*where), exponent); EXPON(*where) = e; if (moebius_mode) return 0; /* stop now, but with exponent updated */ continue; } *where -= 3; CLASS(*where) = CLASS(cur); /* class as given */ newexp = EXPON(cur); if (newexp != gen_1) /* new exp > 1 */ { if (exponent == 1 && newexp == gen_2) e = gen_2; else /* exponent*newexp > 2 */ e = mului(exponent, newexp); } else e = (exponent == 1 ? gen_1 : (exponent == 2 ? gen_2 : utoipos(exponent))); /* inherit parent's exponent */ EXPON(*where) = e; /* keep components younger than *partial */ VALUE(*where) = isonstack(factor) ? icopy(factor) : factor; k++; if (DEBUGLEVEL >= 6) err_printf("\tfactor no. %ld was unique%s\n", j, j>1? " (so far)...": ""); } /* make the 'sorted' object safe for garbage collection (it should be in the * garbage zone from everybody's perspective, but it's easy to do it) */ *sorted = evaltyp(t_INT) | evallg(nf+1); return k; } /* main loop: iterate until smallest entry is a finished prime; returns * a 'where' pointer, or NULL if nothing left, or gen_0 in Moebius mode if * we aren't squarefree */ static GEN ifac_main(GEN *partial) { const long moebius_mode = !!MOEBIUS(*partial); GEN here = ifac_find(*partial); long nf; if (!here) return NULL; /* nothing left */ /* loop until first entry is a finished prime. May involve reallocations, * thus updates of *partial */ while (CLASS(here) != gen_2) { if (CLASS(here) == gen_0) /* composite: crack it */ { /* make sure there's room for another factor */ if (here < *partial + 6) { ifac_defrag(partial, &here); if (here < *partial + 6) ifac_realloc(partial, &here, 1); /* no luck */ } nf = ifac_crack(partial, &here, moebius_mode); if (moebius_mode && EXPON(here) != gen_1) /* that was a power */ { if (DEBUGLEVEL >= 3) err_printf("IFAC: main loop: repeated new factor\n\t%Ps\n", *here); return gen_0; } /* deal with the new unknowns. No sort: ifac_crack did it */ ifac_whoiswho(partial, &here, nf); continue; } if (CLASS(here) == gen_1) /* prime but not yet finished: finish it */ { if (ifac_divide(partial, &here, moebius_mode)) { if (moebius_mode) { if (DEBUGLEVEL >= 3) err_printf("IFAC: main loop: another factor was divisible by\n" "\t%Ps\n", *here); return gen_0; } ifac_resort(partial, &here); /* sort new cofactors down */ ifac_whoiswho(partial, &here, -1); } continue; } pari_err_BUG("ifac_main [non-existent factor class]"); } /* while */ if (moebius_mode && EXPON(here) != gen_1) { if (DEBUGLEVEL >= 3) err_printf("IFAC: after main loop: repeated old factor\n\t%Ps\n", *here); return gen_0; } if (DEBUGLEVEL >= 4) { nf = (*partial + lg(*partial) - here - 3)/3; if (nf) err_printf("IFAC: main loop: %ld factor%s left\n", nf, (nf>1)? "s": ""); else err_printf("IFAC: main loop: this was the last factor\n"); } if (factor_add_primes && !(get_hint(partial) & 8)) { GEN p = VALUE(here); if (lgefint(p)>3 || (ulong)p[2] > 0x1000000UL) (void)addprimes(p); } return here; } /* Encapsulated routines */ /* prime/exponent pairs need to appear contiguously on the stack, but we also * need our data structure somewhere, and we don't know in advance how many * primes will turn up. The following discipline achieves this: When * ifac_decomp() is called, n should point at an object older than the oldest * small prime/exponent pair (ifactor() guarantees this). * We allocate sufficient space to accommodate several pairs -- eleven pairs * ought to fit in a space not much larger than n itself -- before calling * ifac_start(). If we manage to complete the factorization before we run out * of space, we free the data structure and cull the excess reserved space * before returning. When we do run out, we have to leapfrog to generate more * (guesstimating the requirements from what is left in the partial * factorization structure); room for fresh pairs is allocated at the head of * the stack, followed by an ifac_realloc() to reconnect the data structure and * move it out of the way, followed by a few pointer tweaks to connect the new * pairs space to the old one. This whole affair translates into a surprisingly * compact routine. */ /* find primary factors of n */ static long ifac_decomp(GEN n, long hint) { pari_sp av = avma, lim = stack_lim(av, 1); long nb = 0; GEN part, here, workspc, pairs = (GEN)av; /* workspc will be doled out in pairs of smaller t_INTs. For n = prod p^{e_p} * (p not necessarily prime), need room to store all p and e_p [ cgeti(3) ], * bounded by * sum_{p | n} ( log_{2^BIL} (p) + 6 ) <= log_{2^BIL} n + 6 log_2 n */ workspc = new_chunk((expi(n) + 1) * 7); part = ifac_start_hint(n, 0, hint); for (;;) { here = ifac_main(&part); if (!here) break; if (low_stack(lim, stack_lim(av,1))) { long offset; if(DEBUGMEM>1) { pari_warn(warnmem,"[2] ifac_decomp"); ifac_print(part, here); } ifac_realloc(&part, &here, 0); offset = here - part; part = gerepileupto((pari_sp)workspc, part); here = part + offset; } nb++; pairs = icopy_avma(VALUE(here), (pari_sp)pairs); pairs = icopy_avma(EXPON(here), (pari_sp)pairs); ifac_delete(here); } avma = (pari_sp)pairs; if (DEBUGLEVEL >= 3) err_printf("IFAC: found %ld large prime (power) factor%s.\n", nb, (nb>1? "s": "")); return nb; } /***********************************************************************/ /** ARITHMETIC FUNCTIONS WITH EARLY-ABORT **/ /** needing direct access to the factoring machinery to avoid work: **/ /** e.g. if we find a square factor, moebius returns 0, core doesn't **/ /** need to factor it, etc. **/ /***********************************************************************/ /* memory management */ static void ifac_GC(pari_sp av, GEN *part) { GEN here = NULL; if(DEBUGMEM>1) pari_warn(warnmem,"ifac_xxx"); ifac_realloc(part, &here, 0); *part = gerepileupto(av, *part); } static long ifac_moebius(GEN n) { long mu = 1; pari_sp av = avma, lim = stack_lim(av,1); GEN part = ifac_start(n, 1); for(;;) { long v; 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); } } int ifac_read(GEN part, GEN *p, long *e) { GEN here = ifac_find(part); if (!here) return 0; *p = VALUE(here); *e = EXPON(here)[2]; return 1; } void ifac_skip(GEN part) { GEN here = ifac_find(part); if (here) ifac_delete(here); } static int ifac_ispowerful(GEN n) { pari_sp av = avma, lim = stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { long e; GEN p; if (!ifac_read(part,&p,&e)) return 1; /* power: skip */ 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); } } static GEN ifac_core(GEN n) { GEN m = gen_1, c = cgeti(lgefint(n)); pari_sp av = avma, lim = stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { long e; GEN p; if (!ifac_read(part,&p,&e)) return m; /* square: skip */ 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); } } } /* Where to stop trial dividing in factorization. Guaranteed >= 2^14 */ ulong tridiv_bound(GEN n) { ulong l = (ulong)expi(n) + 1; if (l <= 32) return 1UL<<14; if (l <= 512) return (l-16) << 10; return 1UL<<19; /* Rho is generally faster above this */ } /* return a value <= (48 << 10) = 49152 < primelinit */ static ulong utridiv_bound(ulong n) { #ifdef LONG_IS_64BIT if (n & HIGHMASK) return ((ulong)expu(n) + 1 - 16) << 10; #else (void)n; #endif return 1UL<<14; } static void ifac_factoru(GEN n, GEN P, GEN E, long *pi) { GEN part = ifac_start(n, 0); for(;;) { long v; GEN p; if (!ifac_next(&part,&p,&v)) return; P[*pi] = itou(p); E[*pi] = v; (*pi)++; } } static long ifac_moebiusu(GEN n) { GEN part = ifac_start(n, 1); long s = 1; for(;;) { long v; GEN p; if (!ifac_next(&part,&p,&v)) return v? 0: s; s = -s; } } INLINE ulong u_forprime_next_fast(forprime_t *T) { if (*(T->d)) { NEXT_PRIME_VIADIFF(T->p, T->d); return T->p > T->b ? 0: T->p; } return u_forprime_next(T); } /* Factor n and output [p,e] where * p, e are vecsmall with n = prod{p[i]^e[i]} */ GEN factoru(ulong n) { GEN f, E, E2, P, P2; pari_sp av; ulong p; long v, i, oldi; 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; /* 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); 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)) ) { 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++; } else { GEN perm; ifac_factoru(utoipos(n), P, E, &i); setlg(P, i); perm = vecsmall_indexsort(P); P = vecpermute(P, perm); E = vecpermute(E, perm); } END: avma = av; P2 = cgetg(i, t_VECSMALL); gel(f,1) = P2; E2 = cgetg(i, t_VECSMALL); gel(f,2) = E2; while (--i >= 1) { P2[i] = P[i]; E2[i] = E[i]; } return f; } long moebiusu(ulong n) { pari_sp av; ulong p; long s, v, test_prime; forprime_t S; switch(n) { case 0: (void)check_arith_non0(gen_0,"moebius");/*error*/ case 1: return 1; case 2: return -1; } v = vals(n); if (v == 0) s = 1; else { if (v > 1) return 0; n >>= 1; s = -1; } av = avma; u_forprime_init(&S, 3, utridiv_bound(n)); test_prime = 0; while ((p = u_forprime_next_fast(&S))) { int stop; /* tiny integers without small factors are often primes */ if (p == 673) { test_prime = 0; if (uisprime_661(n)) { avma = av; return -s; } } v = u_lvalrem_stop(&n, p, &stop); if (v) { if (v > 1) { avma = av; return 0; } test_prime = 1; s = -s; } if (stop) { avma = av; return n == 1? s: -s; } } avma = av; if (test_prime && uisprime_661(n)) return -s; else { long t = ifac_moebiusu(utoipos(n)); avma = av; if (t == 0) return 0; return (s == t)? 1: -1; } } long moebius(GEN n) { pari_sp av = avma; GEN F; ulong p; long i, l, s, v; forprime_t S; if ((F = check_arith_non0(n,"moebius"))) { GEN E; F = clean_Z_factor(F); E = gel(F,2); l = lg(E); for(i = 1; i < l; i++) if (!equali1(gel(E,i))) { avma = av; return 0; } avma = av; return odd(l)? 1: -1; } if (lgefint(n) == 3) return moebiusu(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); u_forprime_init(&S, 3, tridiv_bound(n)); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v > 1) { avma = av; return 0; } s = -s; if (stop) { avma = av; return is_pm1(n)? s: -s; } } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { if (v > 1) { avma = av; return 0; } s = -s; if (is_pm1(n)) { avma = av; return s; } } } if (ifac_isprime(n)) { avma = av; return -s; } /* large composite without small factors */ v = ifac_moebius(n); avma = av; return (s<0 ? -v : v); /* correct also if v==0 */ } long ispowerful(GEN n) { pari_sp av = avma; GEN F; ulong p, bound; long i, l, v; forprime_t S; if ((F = check_arith_all(n, "ispowerful"))) { GEN p, P = gel(F,1), E = gel(F,2); if (lg(P) == 1) return 1; /* 1 */ p = gel(P,1); if (!signe(p)) return 1; /* 0 */ i = is_pm1(p)? 2: 1; /* skip -1 */ l = lg(E); for (; i < l; i++) if (equali1(gel(E,i))) return 0; return 1; } if (!signe(n)) return 1; if (mod4(n) == 2) return 0; n = shifti(n, -vali(n)); if (is_pm1(n)) return 1; setabssign(n); bound = tridiv_bound(n); u_forprime_init(&S, 3, bound); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v == 1) { avma = av; return 0; } if (stop) { avma = av; return is_pm1(n); } } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { if (v == 1) { avma = av; return 0; } if (is_pm1(n)) { avma = av; return 1; } } } /* no need to factor: must be p^2 or not powerful */ if(cmpii(powuu(bound+1, 3), n) > 0) { long res = Z_issquare(n); avma = av; return res; } if (ifac_isprime(n)) { avma=av; return 0; } /* large composite without small factors */ v = ifac_ispowerful(n); avma = av; return v; } ulong coreu(ulong n) { if (n == 0) return 0; else { pari_sp av = avma; GEN f = factoru(n), P = gel(f,1), E = gel(f,2); long i, l = lg(P), m = 1; avma = av; for (i = 1; i < l; i++) { ulong p = P[i], e = E[i]; if (e & 1) m *= p; } return m; } } GEN core(GEN n) { pari_sp av = avma; GEN m, F; ulong p; long i, l, v; forprime_t S; if ((F = check_arith_all(n, "core"))) { GEN p, x, P = gel(F,1), E = gel(F,2); long j = 1; if (lg(P) == 1) return gen_1; p = gel(P,1); if (!signe(p)) return gen_0; l = lg(P); x = cgetg(l, t_VEC); for (i = 1; i < l; i++) if (mpodd(gel(E,i))) gel(x,j++) = gel(P,i); setlg(x, j); return ZV_prod(x); } switch(lgefint(n)) { case 2: return gen_0; case 3: p = coreu(n[2]); return signe(n) > 0? utoipos(p): utoineg(p); } m = signe(n) < 0? gen_m1: gen_1; n = absi(n); u_forprime_init(&S, 2, tridiv_bound(n)); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v & 1) m = muliu(m, p); if (stop) { if (!is_pm1(n)) m = mulii(m, n); return gerepileuptoint(av, m); } } } l = lg(primetab); for (i = 1; i < l; i++) { GEN q = gel(primetab,i); v = Z_pvalrem(n, q, &n); if (v) { if (v & 1) m = mulii(m, q); if (is_pm1(n)) return gerepileuptoint(av, m); } } if (ifac_isprime(n)) { m = mulii(m, n); return gerepileuptoint(av, m); } /* large composite without small factors */ return gerepileuptoint(av, mulii(m, ifac_core(n))); } long Z_issmooth(GEN m, ulong lim) { pari_sp av=avma; ulong p = 2; forprime_t S; u_forprime_init(&S, 2, lim); while ((p = u_forprime_next_fast(&S))) { int stop; (void)Z_lvalrem_stop(&m, p, &stop); if (stop) { avma = av; return cmpiu(m,lim)<=0; } } avma = av; return 0; } GEN Z_issmooth_fact(GEN m, ulong lim) { pari_sp av=avma; GEN F, P, E; ulong p; long i = 1, l = expi(m)+1; forprime_t S; P = cgetg(l, t_VECSMALL); E = cgetg(l, t_VECSMALL); F = mkmat2(P,E); u_forprime_init(&S, 2, lim); while ((p = u_forprime_next_fast(&S))) { long v; int stop; if ((v = Z_lvalrem_stop(&m, p, &stop))) { P[i] = p; E[i] = v; i++; if (stop) { if (cmpiu(m,lim) > 0) break; P[i] = m[2]; E[i] = 1; i++; setlg(P, i); setlg(E, i); avma = (pari_sp)F; return F; } } } avma = av; return NULL; } /***********************************************************************/ /** **/ /** COMPUTING THE MATRIX OF PRIME DIVISORS AND EXPONENTS **/ /** **/ /***********************************************************************/ static GEN aux_end(GEN M, GEN n, long nb) { GEN P,E, z = (GEN)avma; long i; if (n) gunclone(n); P = cgetg(nb+1,t_COL); E = cgetg(nb+1,t_COL); for (i=nb; i; i--) { /* allow a stackdummy in the middle */ while (typ(z) != t_INT) z += lg(z); gel(E,i) = z; z += lg(z); gel(P,i) = z; z += lg(z); } gel(M,1) = P; gel(M,2) = E; return sort_factor(M, (void*)&absi_cmp, cmp_nodata); } static void STORE(long *nb, GEN x, long e) { (*nb)++; (void)x; (void)utoipos(e); } static void STOREu(long *nb, ulong x, long e) { STORE(nb, utoipos(x), e); } static void STOREi(long *nb, GEN x, long e) { STORE(nb, icopy(x), e); } /* no prime less than p divides n */ static int special_primes(GEN n, ulong p, long *nb, GEN T) { long i, l = lg(T); if (l > 1) { /* pp = square of biggest p tried so far */ long pp[] = { evaltyp(t_INT)|_evallg(4), 0,0,0 }; pari_sp av = avma; affii(sqru(p), pp); avma = av; for (i = 1; i < l; i++) if (dvdiiz(n,gel(T,i), n)) { long k = 1; while (dvdiiz(n,gel(T,i), n)) k++; STOREi(nb, gel(T,i), k); if (absi_cmp(pp, n) > 0) return 1; } } return 0; } /* factor(sn*|n|), where sn = -1,1 or 0. * all != 0 : only look for prime divisors < all */ static GEN ifactor_sign(GEN n, ulong all, long hint, long sn) { GEN M, N; pari_sp av; long nb = 0, i; ulong lim; forprime_t T; if (!sn) retmkmat2(mkcol(gen_0), mkcol(gen_1)); if (lgefint(n) == 3) { /* small integer */ GEN f, Pf, Ef, P, E, F = cgetg(3, t_MAT); long l; 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]); avma = av; Pf = gel(f,1); Ef = gel(f,2); l = lg(Pf); if (sn < 0) { /* add sign */ long L = l+1; gel(F,1) = P = cgetg(L, t_COL); gel(F,2) = E = cgetg(L, t_COL); gel(P,1) = gen_m1; P++; gel(E,1) = gen_1; E++; } else { gel(F,1) = P = cgetg(l, t_COL); gel(F,2) = E = cgetg(l, t_COL); } for (i = 1; i < l; i++) { gel(P,i) = utoipos(Pf[i]); gel(E,i) = utoipos(Ef[i]); } return F; } M = cgetg(3,t_MAT); if (sn < 0) STORE(&nb, utoineg(1), 1); if (is_pm1(n)) return aux_end(M,NULL,nb); n = N = gclone(n); setabssign(n); /* trial division bound */ lim = all; if (!lim) lim = tridiv_bound(n); if (lim > 2) { ulong maxp, p; pari_sp av2; i = vali(n); if (i) { STOREu(&nb, 2, i); av = avma; affii(shifti(n,-i), n); avma = av; } if (is_pm1(n)) return aux_end(M,n,nb); /* trial division */ maxp = maxprime(); av = avma; u_forprime_init(&T, 3, minss(lim, maxp)); av2 = avma; /* first pass: known to fit in private prime table */ while ((p = u_forprime_next_fast(&T))) { pari_sp av3 = avma; int stop; long k = Z_lvalrem_stop(&n, p, &stop); if (k) { affii(n, N); n = N; avma = av3; STOREu(&nb, p, k); } if (stop) { if (!is_pm1(n)) STOREi(&nb, n, 1); stackdummy(av, av2); return aux_end(M,n,nb); } } stackdummy(av, av2); if (lim > maxp) { /* second pass, usually empty: outside private prime table */ av = avma; u_forprime_init(&T, maxp+1, lim); av2 = avma; while ((p = u_forprime_next(&T))) { pari_sp av3 = avma; int stop; long k = Z_lvalrem_stop(&n, p, &stop); if (k) { affii(n, N); n = N; avma = av3; STOREu(&nb, p, k); } if (stop) { if (!is_pm1(n)) STOREi(&nb, n, 1); stackdummy(av, av2); return aux_end(M,n,nb); } } stackdummy(av, av2); } } /* trial divide by the special primes */ if (special_primes(n, lim, &nb, primetab)) { if (!is_pm1(n)) STOREi(&nb, n, 1); return aux_end(M,n,nb); } if (all) { /* smallfact: look for easy pure powers then stop. Cf Z_isanypower */ GEN x; long k; av = avma; k = isanypower_nosmalldiv(n, &x); if (k > 1) affii(x, n); avma = av; STOREi(&nb, n, k); if (DEBUGLEVEL >= 2) { pari_warn(warner, "IFAC: untested %ld-bit integer declared prime", expi(n)); if (expi(n) <= 256) err_printf("\t%Ps\n", n); } return aux_end(M,n,nb); } if (ifac_isprime(n)) { STOREi(&nb, n, 1); return aux_end(M,n,nb); } nb += ifac_decomp(n, hint); return aux_end(M,n, nb); } static GEN ifactor(GEN n, ulong all, long hint) { return ifactor_sign(n, all, hint, signe(n)); } int ifac_next(GEN *part, GEN *p, long *e) { GEN here = ifac_main(part); if (here == gen_0) { *p = NULL; *e = 1; return 0; } if (!here) { *p = NULL; *e = 0; return 0; } *p = VALUE(here); *e = EXPON(here)[2]; ifac_delete(here); return 1; } /* see before ifac_crack for current semantics of 'hint' (factorint's 'flag') */ GEN factorint(GEN n, long flag) { GEN F; if ((F = check_arith_all(n,"factorint"))) return gcopy(F); return ifactor(n,0,flag); } GEN Z_factor_limit(GEN n, ulong all) { if (!all) all = GP_DATA->primelimit + 1; return ifactor(n,all,decomp_default_hint); } GEN absi_factor_limit(GEN n, ulong all) { if (!all) all = GP_DATA->primelimit + 1; return ifactor_sign(n,all,decomp_default_hint, signe(n)?1 : 0); } GEN Z_factor(GEN n) { return ifactor(n,0,decomp_default_hint); } GEN absi_factor(GEN n) { return ifactor_sign(n, 0, decomp_default_hint, signe(n)? 1: 0); } /* Factor until the unfactored part is smaller than limit. Return the * factored part. Hence factorback(output) may be smaller than n */ GEN Z_factor_until(GEN n, GEN limit) { pari_sp av2, av = avma; ulong B = tridiv_bound(n); GEN q, part, F = ifactor(n, B, decomp_default_hint); GEN P = gel(F,1), E = gel(F,2), P2, E2, F2; long l = lg(P), l2; av2 = avma; q = gel(P,l-1); if (cmpiu(q, B) <= 0 || cmpii(q, sqru(B)) < 0 || ifac_isprime(q)) { avma = av2; return F; } /* q = composite unfactored part, remove from P/E */ setlg(E,l-1); setlg(P,l-1); if (cmpii(q, limit) > 0) { /* factor further */ l2 = expi(q)+1; P2 = vectrunc_init(l2); E2 = vectrunc_init(l2); F2 = mkmat2(P2,E2); part = ifac_start(q, 0); for(;;) { long e; GEN p; if (!ifac_next(&part,&p,&e)) break; vectrunc_append(P2, p); vectrunc_append(E2, utoipos(e)); q = diviiexact(q, powiu(p, e)); if (cmpii(q, limit) <= 0) break; } F2 = sort_factor(F2, (void*)&absi_cmp, cmp_nodata); F = merge_factor(F, F2, (void*)&absi_cmp, cmp_nodata); } return gerepilecopy(av, F); } pari-2.7.5/src/basemath/bit.c0000644000175000017500000002730212405547147014420 0ustar billbill/* 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" /*********************************************************************/ /** **/ /** BINARY DECOMPOSITION **/ /** **/ /*********************************************************************/ INLINE GEN inegate(GEN z) { return subsi(-1,z); } GEN binaire(GEN x) { ulong m,u; long i,lx,ex,ly,tx=typ(x); GEN y,p1,p2; 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>=1); } break; } case t_REAL: ex=expo(x); if (!signe(x)) return const_vec(maxss(-ex,0), gen_0); lx=lg(x); y=cgetg(3,t_VEC); if (ex > bit_prec(x)) pari_err_PREC("binary"); p1 = cgetg(maxss(ex,0)+2,t_VEC); p2 = cgetg(bit_prec(x)-ex,t_VEC); gel(y,1) = p1; gel(y,2) = p2; ly = -ex; ex++; m = HIGHBIT; if (ex<=0) { gel(p1,1) = gen_0; for (i=1; i <= -ex; i++) gel(p2,i) = gen_0; i=2; } else { ly=1; for (i=2; i>=1) && ly<=ex); } ly=1; if (m) i--; else m=HIGHBIT; } for (; i>=1); m=HIGHBIT; } break; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i xl) /* Need to grow */ { GEN out, outp, xp = int_MSW(x); out = cgetipos(len_out); outp = int_MSW(out); if (!lowbits) *outp = ~uzero; else *outp = (1L << lowbits) - 1; for (i = 3; i < len_out - xl + 2; i++) { outp = int_precW(outp); *outp = ~uzero; } for ( ; i < len_out; i++) { outp = int_precW(outp); *outp = ~*xp; xp = int_precW(xp); } return out; } x = icopy(x); for (i = 2; i < xl; i++) x[i] = ~x[i]; return ibittrunc(int_normalize(x,0), bits); } /* bitwise 'and' of two positive integers (any integers, but we ignore sign). * Inputs are not necessary normalized. */ GEN ibitand(GEN x, GEN y) { long lx, ly, lout; long *xp, *yp, *outp; GEN out; long i; if (!signe(x) || !signe(y)) return gen_0; lx=lgefint(x); ly=lgefint(y); lout = minss(lx,ly); /* > 2 */ xp = int_LSW(x); yp = int_LSW(y); out = cgetipos(lout); outp = int_LSW(out); for (i=2; i 2 */ out = cgetipos(lx); outp = int_LSW(out); for (i=2;i 2 */ out = cgetipos(lx); outp = int_LSW(out); for (i=2;i y) == ~(~x | y) == x & ~y */ GEN ibitnegimply(GEN x, GEN y) { long lx, ly, lin; long *xp, *yp, *outp; GEN out; long i; if (!signe(x)) return gen_0; if (!signe(y)) return absi(x); lx = lgefint(x); xp = int_LSW(x); ly = lgefint(y); yp = int_LSW(y); lin = minss(lx,ly); out = cgetipos(lx); outp = int_LSW(out); for (i=2; i= 0) << 1) | (signe(y) >= 0)); } static void checkint2(const char *f,GEN x, GEN y) { if (typ(x)!=t_INT || typ(y)!=t_INT) pari_err_TYPE2(f,x,y); } GEN gbitor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise or",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitor(x,y); case 2: /*1,-1*/ z = ibitnegimply(inegate(y),x); break; case 1: /*-1,1*/ z = ibitnegimply(inegate(x),y); break; default: /*-1,-1*/ z = ibitand(inegate(x),inegate(y)); break; } return gerepileuptoint(ltop, inegate(z)); } GEN gbitand(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise and",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitand(x,y); case 2: /*1,-1*/ z = ibitnegimply(x,inegate(y)); break; case 1: /*-1,1*/ z = ibitnegimply(y,inegate(x)); break; default: /*-1,-1*/ z = inegate(ibitor(inegate(x),inegate(y))); break; } return gerepileuptoint(ltop, z); } GEN gbitxor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise xor",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitxor(x,y); case 2: /*1,-1*/ z = inegate(ibitxor(x,inegate(y))); break; case 1: /*-1,1*/ z = inegate(ibitxor(inegate(x),y)); break; default: /*-1,-1*/ z = ibitxor(inegate(x),inegate(y)); break; } return gerepileuptoint(ltop,z); } /* x & ~y */ GEN gbitnegimply(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise negated imply",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitnegimply(x,y); case 2: /*1,-1*/ z = ibitand(x,inegate(y)); break; case 1: /*-1,1*/ z = inegate(ibitor(y,inegate(x))); break; default: /*-1,-1*/ z = ibitnegimply(inegate(y),inegate(x)); break; } return gerepileuptoint(ltop,z); } INLINE long hamming_word(ulong w) { #if 0 return __builtin_popcountl(w); #endif static long byte_weight[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; long sum = 0; while (w) { sum += byte_weight[w & 255]; w >>= 8; } return sum; } /* number of non-zero entries among x[a], ..., x[b] */ static long hamming_slice(GEN x, long a, long b) { long i, nb = 0; for (i = a; i <= b; i++) if (!gequal0(gel(x,i))) nb++; return nb; } static long hamming_mat(GEN x) { long i, lx = lg(x), nb = 0; for (i = 1; i < lx; i++) nb += hammingweight(gel(x,i)); return nb; } static long hamming_vecsmall(GEN x) { long i, lx = lg(x), nb = 0; for (i = 1; i < lx; i++) if (x[i]) nb++; return nb; } static long hamming_int(GEN n) { long lx = lgefint(n), i, sum; if (lx == 2) return 0; sum = hamming_word(n[2]); for (i = 3; i < lx; i++) sum += hamming_word(n[i]); return sum; } long hammingweight(GEN n) { switch(typ(n)) { case t_INT: return hamming_int(n); case t_VEC: case t_COL: return hamming_slice(n, 1, lg(n)-1); case t_POL: return hamming_slice(n, 2, lg(n)-1); case t_VECSMALL: return hamming_vecsmall(n); case t_MAT: return hamming_mat(n); } pari_err_TYPE("hammingweight", n); return 0;/*notreached*/ } pari-2.7.5/src/basemath/subcyclo.c0000644000175000017500000006645512405547147015501 0ustar billbill/* 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" /*************************************************************************/ /** **/ /** Routines for handling subgroups of (Z/nZ)^* **/ /** without requiring discrete logarithms. **/ /** **/ /*************************************************************************/ /* Subgroups are [gen,ord,bits] where * gen is a vecsmall of generators * ord is theirs relative orders * bits is a bit vector of the elements, of length(n). */ /*The algorithm is similar to testpermutation*/ static void znstar_partial_coset_func(long n, GEN H, void (*func)(void *data,long c) , void *data, long d, long c) { GEN gen, ord, cache; long i, j, card; if (!d) { (*func)(data,c); return; } cache = const_vecsmall(d,c); (*func)(data,c); /* AFTER cache: may contain gerepileupto statement */ gen = gel(H,1); ord = gel(H,2); card = ord[1]; for (i = 2; i <= d; i++) card *= ord[i]; for(i=1; i0;i--) { long p = P[i], e = E[i], q = n; if (DEBUGLEVEL>=4) err_printf("SubCyclo: testing %ld^%ld\n",p,e); for ( ; e>=1; e--) { long z = 1; q /= p; for (j = 1; j < p; j++) { z += q; if (!F2v_coeff(gel(H,3),z) && ugcd(z,n)==1) break; } if ( j < p ) { if (DEBUGLEVEL>=4) err_printf("SubCyclo: %ld not found\n",z); break; } cnd /= p; if (DEBUGLEVEL>=4) err_printf("SubCyclo: new conductor:%ld\n",cnd); } } if (DEBUGLEVEL>=6) err_printf("SubCyclo: conductor:%ld\n",cnd); avma=ltop; return cnd; } /* Compute the orbits of a subgroups of Z/nZ given by a generator * or a set of generators given as a vector. */ GEN znstar_cosets(long n, long phi_n, GEN H) { long k; long c = 0; long card = znstar_order(H); long index = phi_n/card; GEN cosets = cgetg(index+1,t_VECSMALL); pari_sp ltop = avma; GEN bits = zero_F2v(n); for (k = 1; k <= index; k++) { for (c++ ; F2v_coeff(bits,c) || ugcd(c,n)!=1; c++); cosets[k]=c; znstar_coset_bits_inplace(n, H, bits, c); } avma=ltop; return cosets; } /*************************************************************************/ /** **/ /** znstar/HNF interface **/ /** **/ /*************************************************************************/ static GEN vecmod_to_vecsmall(GEN z) { long i, l = lg(z); GEN x = cgetg(l, t_VECSMALL); for (i=1; i= 6) timer_start(&ti); for (i=1; i<=d; i++, base = Fl_mul(base,z,n)) { pari_sp av = avma; long ex = base; GEN s = gen_0; for (k=0; k= 6) timer_printf(&ti, "polsubcyclo_cyclic"); return V; } struct _subcyclo_orbits_s { GEN powz; GEN *s; ulong count; pari_sp ltop; }; static void _subcyclo_orbits(struct _subcyclo_orbits_s *data, long k) { GEN powz = data->powz; GEN *s = data->s; if (!data->count) data->ltop = avma; *s = gadd(*s, polsubcyclo_powz(powz,k)); data->count++; if ((data->count & 0xffUL) == 0) *s = gerepileupto(data->ltop, *s); } /* Newton sums mod le. if le==NULL, works with complex instead */ static GEN polsubcyclo_orbits(long n, GEN H, GEN O, GEN powz, GEN le) { long i, d = lg(O); GEN V = cgetg(d,t_VEC); struct _subcyclo_orbits_s data; long lle = le?lg(le)*2+1: 2*lg(gmael(powz,1,2))+3;/*dvmdii uses lx+ly space*/ data.powz = powz; for(i=1; i= 4) err_printf("Subcyclo: prime l=%ld\n",l); gl = utoipos(l); av = avma; if (!borne) { /* Use vecmax(Vec((x+o)^d)) = max{binomial(d,i)*o^i ;1<=i<=d} */ i = d-(1+d)/(1+o); borne = mulii(binomial(utoipos(d),i),powuu(o,i)); } if (DEBUGLEVEL >= 4) err_printf("Subcyclo: bound=2^%ld\n",expi(borne)); val = logint(shifti(borne,2), gl, NULL); avma = av; if (DEBUGLEVEL >= 4) err_printf("Subcyclo: val=%ld\n",val); le = powiu(gl,val); z = utoipos( Fl_powu(pgener_Fl(l), e, l) ); z = Zp_sqrtnlift(gen_1,utoipos(n),z,gl,val); *ptr_val = val; *ptr_l = l; return gmodulo(z,le); } /*Fill in the powz table: * powz[1]: baby-step * powz[2]: giant-step * powz[3] exists only if the field is real (value is ignored). */ static GEN polsubcyclo_complex_roots(long n, long real, long prec) { long i, m = (long)(1+sqrt((double) n)); GEN bab, gig, powz = cgetg(real?4:3, t_VEC); bab = cgetg(m+1,t_VEC); gel(bab,1) = gen_1; gel(bab,2) = expIr(divru(Pi2n(1, prec), n)); /* = e_n(1) */ for (i=3; i<=m; i++) gel(bab,i) = gmul(gel(bab,2),gel(bab,i-1)); gig = cgetg(m+1,t_VEC); gel(gig,1) = gen_1; gel(gig,2) = gmul(gel(bab,2),gel(bab,m));; for (i=3; i<=m; i++) gel(gig,i) = gmul(gel(gig,2),gel(gig,i-1)); gel(powz,1) = bab; gel(powz,2) = gig; if (real) gel(powz,3) = gen_0; return powz; } static GEN muliimod_sz(GEN x, GEN y, GEN l, long siz) { pari_sp av = avma; GEN p1; (void)new_chunk(siz); /* HACK */ p1 = mulii(x,y); avma = av; return modii(p1,l); } static GEN polsubcyclo_roots(long n, GEN zl) { GEN le = gel(zl,1), z = gel(zl,2); long i, lle = lg(le)*3; /*Assume dvmdii use lx+ly space*/ long m = (long)(1+sqrt((double) n)); GEN bab, gig, powz = cgetg(3,t_VEC); pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); bab = cgetg(m+1,t_VEC); gel(bab,1) = gen_1; gel(bab,2) = icopy(z); for (i=3; i<=m; i++) gel(bab,i) = muliimod_sz(z,gel(bab,i-1),le,lle); gig = cgetg(m+1,t_VEC); gel(gig,1) = gen_1; gel(gig,2) = muliimod_sz(z,gel(bab,m),le,lle);; for (i=3; i<=m; i++) gel(gig,i) = muliimod_sz(gel(gig,2),gel(gig,i-1),le,lle); if (DEBUGLEVEL >= 6) timer_printf(&ti, "polsubcyclo_roots"); gel(powz,1) = bab; gel(powz,2) = gig; return powz; } GEN galoiscyclo(long n, long v) { ulong av = avma; GEN grp, G, z, le, L, elts; long val, l, i, j, k; GEN zn = znstar(stoi(n)); long card = itos(gel(zn,1)); GEN gen = vec_to_vecsmall(lift(gel(zn,3))); GEN ord = gtovecsmall(gel(zn,2)); z = polsubcyclo_start(n,card/2,2,NULL,&val,&l); le = gel(z,1); z = gel(z,2); L = cgetg(1+card,t_VEC); gel(L,1) = z; for (j = 1, i = 1; j < lg(gen); j++) { long c = i * (ord[j]-1); for (k = 1; k <= c; k++) gel(L,++i) = Fp_powu(gel(L,k), gen[j], le); } G = abelian_group(ord); elts = group_elts(G, card); /*not stack clean*/ grp = cgetg(9, t_VEC); gel(grp,1) = polcyclo(n,v); gel(grp,2) = mkvec3(stoi(l), stoi(val), icopy(le)); gel(grp,3) = gcopy(L); gel(grp,4) = vandermondeinversemod(L, gel(grp,1), gen_1, le); gel(grp,5) = gen_1; gel(grp,6) = gcopy(elts); gel(grp,7) = gcopy(gel(G,1)); gel(grp,8) = gcopy(gel(G,2)); return gerepileupto(av, grp); } /* Convert a bnrinit(Q,n) to a znstar(n) * complex is set to 0 if the bnr is real and to 1 if it is complex. * Not stack clean */ GEN bnr_to_znstar(GEN bnr, long *complex) { GEN gen, cond, v, bid; long l2, i; checkbnr(bnr); bid = bnr_get_bid(bnr); gen = bnr_get_gen(bnr); if (nf_get_degree(bnr_get_nf(bnr)) != 1) pari_err_DOMAIN("bnr_to_znstar", "bnr", "!=", strtoGENstr("Q"), bnr); /* cond is the finite part of the conductor, * complex is the infinite part*/ cond = gcoeff(bid_get_ideal(bid), 1, 1); *complex = signe(gel(bid_get_arch(bid), 1)); l2 = lg(gen); v = cgetg(l2, t_VEC); for (i = 1; i < l2; ++i) { GEN x = gel(gen,i); switch(typ(x)) { case t_MAT: x = gcoeff(x,1,1); break; case t_COL: x = gel(x,1); break; } gel(v,i) = gmodulo(absi(x), cond); } return mkvec3(bnr_get_no(bnr), bnr_get_cyc(bnr), v); } GEN galoissubcyclo(GEN N, GEN sg, long flag, long v) { pari_sp ltop= avma, av; GEN H, V, B, zl, L, T, le, powz, O, Z = NULL; long i, card, phi_n, val,l, n, cnd, complex=1; pari_timer ti; if (flag<0 || flag>2) pari_err_FLAG("galoissubcyclo"); if (v < 0) v = 0; if (!sg) sg = gen_1; switch(typ(N)) { case t_INT: n = itos(N); if (n < 1) pari_err_DOMAIN("galoissubcyclo", "degree", "<=", gen_0, stoi(n)); break; case t_VEC: if (lg(N)==7) N = bnr_to_znstar(N,&complex); if (lg(N)==4) { /* znstar */ GEN gen = gel(N,3); Z = N; if (typ(gen)!=t_VEC) pari_err_TYPE("galoissubcyclo",gen); if (lg(gen) == 1) n = 1; else { GEN z = gel(gen,1); n = itos(gel(z,1)); } break; } default: /*fall through*/ pari_err_TYPE("galoissubcyclo",N); return NULL;/*Not reached*/ } if (n==1) { avma = ltop; return deg1pol_shallow(gen_1,gen_m1,v); } switch(typ(sg)) { case t_INTMOD: case t_INT: V = mkvecsmall( lift_check_modulus(sg,n) ); break; case t_VECSMALL: V = gcopy(sg); for (i=1; i= 6) { err_printf("Subcyclo: elements:"); for (i=1;i conj(z) = z^-1 = z^(n-1) is in H */ complex = !F2v_coeff(gel(H,3),n-1); if (DEBUGLEVEL >= 6) err_printf("Subcyclo: complex=%ld\n",complex); if (DEBUGLEVEL >= 1) timer_start(&ti); cnd = znstar_conductor(n,H); if (DEBUGLEVEL >= 1) timer_printf(&ti, "znstar_conductor"); if (flag == 1) { avma=ltop; return stoi(cnd); } if (cnd == 1) { avma= ltop; return gscycloconductor(deg1pol_shallow(gen_1,gen_m1,v),1,flag); } if (n != cnd) { H = znstar_reduce_modulus(H, cnd); n = cnd; } card = znstar_order(H); phi_n = eulerphiu(n); if (card == phi_n) { avma = ltop; return gscycloconductor(polcyclo(n,v),n,flag); } O = znstar_cosets(n, phi_n, H); if (DEBUGLEVEL >= 1) timer_printf(&ti, "znstar_cosets"); if (DEBUGLEVEL >= 6) err_printf("Subcyclo: orbits=%Ps\n",O); if (DEBUGLEVEL >= 4) err_printf("Subcyclo: %ld orbits with %ld elements each\n",phi_n/card,card); av = avma; powz = polsubcyclo_complex_roots(n,!complex,LOWDEFAULTPREC); L = polsubcyclo_orbits(n,H,O,powz,NULL); B = polsubcyclo_complex_bound(av,L,LOWDEFAULTPREC); zl = polsubcyclo_start(n,phi_n/card,card,B,&val,&l); powz = polsubcyclo_roots(n,zl); le = gel(zl,1); L = polsubcyclo_orbits(n,H,O,powz,le); if (DEBUGLEVEL >= 6) timer_start(&ti); T = FpV_roots_to_pol(L,le,v); if (DEBUGLEVEL >= 6) timer_printf(&ti, "roots_to_pol"); T = FpX_center(T,le,shifti(le,-1)); return gerepileupto(ltop, gscycloconductor(T,n,flag)); } /* Z = znstar(n) cyclic. n = 1,2,4,p^a or 2p^a, * and d | phi(n) = 1,1,2,(p-1)p^(a-1) */ static GEN polsubcyclo_g(long n, long d, GEN Z, long v) { pari_sp ltop = avma; long o, p, r, g, gd, l , val; GEN zl, L, T, le, B, powz; pari_timer ti; if (d==1) return deg1pol_shallow(gen_1,gen_m1,v); /* get rid of n=1,2 */ if ((n & 3) == 2) n >>= 1; /* n = 4 or p^a, p odd */ o = itos(gel(Z,1)); g = itos(gmael3(Z,3,1,2)); p = n / ugcd(n,o); /* p^a / gcd(p^a,phi(p^a)) = p*/ r = ugcd(d,n); /* = p^(v_p(d)) < n */ n = r*p; /* n is now the conductor */ o = n-r; /* = phi(n) */ if (o == d) return polcyclo(n,v); o /= d; gd = Fl_powu(g%n, d, n); /*FIXME: If degree is small, the computation of B is a waste of time*/ powz = polsubcyclo_complex_roots(n,(o&1)==0,LOWDEFAULTPREC); L = polsubcyclo_cyclic(n,d,o,g,gd,powz,NULL); B = polsubcyclo_complex_bound(ltop,L,LOWDEFAULTPREC); zl = polsubcyclo_start(n,d,o,B,&val,&l); le = gel(zl,1); powz = polsubcyclo_roots(n,zl); L = polsubcyclo_cyclic(n,d,o,g,gd,powz,le); if (DEBUGLEVEL >= 6) timer_start(&ti); T = FpV_roots_to_pol(L,le,v); if (DEBUGLEVEL >= 6) timer_printf(&ti, "roots_to_pol"); return gerepileupto(ltop, FpX_center(T,le,shifti(le,-1))); } GEN polsubcyclo(long n, long d, long v) { pari_sp ltop = avma; GEN L, Z; if (v<0) v = 0; if (d<=0) pari_err_DOMAIN("polsubcyclo","d","<=",gen_0,stoi(d)); if (n<=0) pari_err_DOMAIN("polsubcyclo","n","<=",gen_0,stoi(n)); Z = znstar(stoi(n)); if (!dvdis(gel(Z,1), d)) { avma = ltop; return cgetg(1, t_VEC); } if (lg(gel(Z,2)) == 2) { /* faster but Z must be cyclic */ avma = ltop; return polsubcyclo_g(n, d, Z, v); } L = subgrouplist(gel(Z,2), mkvec(stoi(d))); if (lg(L) == 2) return gerepileupto(ltop, galoissubcyclo(Z, gel(L,1), 0, v)); else { GEN V = cgetg(lg(L),t_VEC); long i; for (i=1; i< lg(V); i++) gel(V,i) = galoissubcyclo(Z, gel(L,i), 0, v); return gerepileupto(ltop, V); } } struct aurifeuille_t { GEN z, le; ulong l; long e; }; /* Let z a primitive n-th root of 1, n > 1, A an integer such that * Aurifeuillian factorization of Phi_n(A) exists ( z.A is a square in Q(z) ). * Let G(p) the Gauss sum mod p prime: * sum_x (x|p) z^(xn/p) for p odd, i - 1 for p = 2 [ i := z^(n/4) ] * We have N(-1) = Nz = 1 (n != 1,2), and * G^2 = (-1|p) p for p odd, G^2 = -2i for p = 2 * In particular, for odd A, (-1|A) A = g^2 is a square. If A = prod p^{e_p}, * sigma_j(g) = \prod_p (sigma_j G(p)))^e_p = \prod_p (j|p)^e_p g = (j|A) g * n odd : z^2 is a primitive root, A = g^2 * Phi_n(A) = N(A - z^2) = N(g - z) N(g + z) * * n = 2 (4) : -z^2 is a primitive root, -A = g^2 * Phi_n(A) = N(A - (-z^2)) = N(g^2 - z^2) [ N(-1) = 1 ] * = N(g - z) N(g + z) * * n = 4 (8) : i z^2 primitive root, -Ai = g^2 * Phi_n(A) = N(A - i z^2) = N(-Ai - z^2) = N(g - z) N(g + z) * sigma_j(g) / g = (j|A) if j = 1 (4) * (-j|A)i if j = 3 (4) * */ /* factor Phi_n(A), Astar: A* = squarefree kernel of A, P = odd prime divisors * of n */ static GEN factor_Aurifeuille_aux(GEN A, long Astar, long n, GEN P, struct aurifeuille_t *S) { pari_sp av; GEN f, a, b, s, powers, z = S->z, le = S->le; long j, k, maxjump, lastj, e = S->e; ulong l = S->l; char *invertible; if ((n & 7) == 4) { /* A^* even */ GEN i = Fp_powu(z, n>>2, le), z2 = Fp_sqr(z, le); invertible = stack_malloc(n); /* even indices unused */ for (j = 1; j < n; j+=2) invertible[j] = 1; for (k = 1; k < lg(P); k++) { long p = P[k]; for (j = p; j < n; j += 2*p) invertible[j] = 0; } lastj = 1; maxjump = 2; for (j= 3; j < n; j+=2) if (invertible[j]) { long jump = j - lastj; if (jump > maxjump) maxjump = jump; lastj = j; } powers = cgetg(maxjump+1, t_VEC); /* powers[k] = z^k, odd indices unused */ gel(powers,2) = z2; for (k = 4; k <= maxjump; k+=2) gel(powers,k) = odd(k>>1)? Fp_mul(gel(powers, k-2), z2, le) : Fp_sqr(gel(powers, k>>1), le); if (Astar == 2) { /* important special case (includes A=2), split for efficiency */ if (!equalis(A, 2)) { GEN f = sqrti(shifti(A,-1)), mf = Fp_neg(f,le), fi = Fp_mul(f,i,le); a = Fp_add(mf, fi, le); b = Fp_sub(mf, fi, le); } else { a = addsi(-1,i); b = subsi(-1,i); } av = avma; s = z; f = subii(a, s); lastj = 1; for (j = 3, k = 0; j < n; j+=2) if (invertible[j]) { s = Fp_mul(gel(powers, j-lastj), s, le); /* z^j */ lastj = j; f = Fp_mul(f, subii((j & 3) == 1? a: b, s), le); if (++k == 0x1ff) { gerepileall(av, 2, &s, &f); k = 0; } } } else { GEN ma, mb, B = Fp_mul(A, i, le), gl = utoipos(l); long t; Astar >>= 1; t = Astar & 3; if (Astar < 0) t = 4-t; /* t = 1 or 3 */ if (t == 1) B = Fp_neg(B, le); a = Zp_sqrtlift(B, Fp_sqrt(B, gl), gl, e); b = Fp_mul(a, i, le); ma = Fp_neg(a, le); mb = Fp_neg(b, le); av = avma; s = z; f = subii(a, s); lastj = 1; for (j = 3, k = 0; j>= 1; } /* A^* = 1 (mod 4) */ g = Fl_sqrt(umodiu(A,l), l); a = Zp_sqrtlift(A, utoipos(g), utoipos(l), e); b = negi(a); invertible = stack_malloc(n); for (j = 1; j < n; j++) invertible[j] = 1; for (k = 1; k < lg(P); k++) { long p = P[k]; for (j = p; j < n; j += p) invertible[j] = 0; } lastj = 2; maxjump = 1; for (j= 3; j < n; j++) if (invertible[j]) { long jump = j - lastj; if (jump > maxjump) maxjump = jump; lastj = j; } powers = cgetg(maxjump+1, t_VEC); /* powers[k] = z^k */ gel(powers,1) = z; for (k = 2; k <= maxjump; k++) gel(powers,k) = odd(k)? Fp_mul(gel(powers, k-1), z, le) : Fp_sqr(gel(powers, k>>1), le); av = avma; s = z; f = subii(a, s); lastj = 1; for(j = 2, k = 0; j < n; j++) if (invertible[j]) { s = Fp_mul(gel(powers, j-lastj), s, le); lastj = j; f = Fp_mul(f, subii(kross(j,Astar)==1? a: b, s), le); if (++k == 0x1ff) { gerepileall(av, 2, &s, &f); k = 0; } } } return f; } /* fd = factoru(odd part of d = d or d/4). Return eulerphi(d) */ static ulong phi(long d, GEN fd) { GEN P = gel(fd,1), E = gel(fd,2); long i, l = lg(P); ulong phi = 1; for (i = 1; i < l; i++) { ulong p = P[i], e = E[i]; phi *= upowuu(p, e-1)*(p-1); } if (!odd(d)) phi <<= 1; return phi; } static void Aurifeuille_init(GEN a, long d, GEN fd, struct aurifeuille_t *S) { GEN sqrta = sqrtr_abs(itor(a, LOWDEFAULTPREC)); GEN bound = ceil_safe(powru(addrs(sqrta,1), phi(d, fd))); GEN zl = polsubcyclo_start(d, 0, 0, bound, &(S->e), (long*)&(S->l)); S->le = gel(zl,1); S->z = gel(zl,2); } GEN factor_Aurifeuille_prime(GEN p, long d) { pari_sp av = avma; struct aurifeuille_t S; GEN fd; long pp; if ((d & 3) == 2) { d >>= 1; p = negi(p); } fd = factoru(odd(d)? d: d>>2); pp = itos(p); Aurifeuille_init(p, d, fd, &S); return gerepileuptoint(av, factor_Aurifeuille_aux(p, pp, d, gel(fd,1), &S)); } /* an algebraic factor of Phi_d(a), a != 0 */ GEN factor_Aurifeuille(GEN a, long d) { pari_sp av = avma; GEN fd, P, A; long i, lP, va = vali(a), sa, astar, D; struct aurifeuille_t S; if (d <= 0) pari_err_DOMAIN("factor_Aurifeuille", "degre", "<=",gen_0,stoi(d)); if ((d & 3) == 2) { d >>= 1; a = negi(a); } if ((va & 1) == (d & 1)) { avma = av; return gen_1; } sa = signe(a); if (odd(d)) { long a4; if (d == 1) { if (!Z_issquareall(a, &A)) return gen_1; return gerepileuptoint(av, addis(A,1)); } A = va? shifti(a, -va): a; a4 = mod4(A); if (sa < 0) a4 = 4 - a4; if (a4 != 1) { avma = av; return gen_1; } } else if ((d & 7) == 4) A = shifti(a, -va); else { avma = av; return gen_1; } /* v_2(d) = 0 or 2. Kill 2 from factorization (minor efficiency gain) */ fd = factoru(odd(d)? d: d>>2); P = gel(fd,1); lP = lg(P); astar = sa; if (odd(va)) astar <<= 1; for (i = 1; i < lP; i++) if (odd( (Z_lvalrem(A, P[i], &A)) ) ) astar *= P[i]; if (sa < 0) { /* negate in place if possible */ if (A == a) A = icopy(A); setabssign(A); } if (!Z_issquare(A)) { avma = av; return gen_1; } D = odd(d)? 1: 4; for (i = 1; i < lP; i++) D *= P[i]; if (D != d) { a = powiu(a, d/D); d = D; } Aurifeuille_init(a, d, fd, &S); return gerepileuptoint(av, factor_Aurifeuille_aux(a, astar, d, P, &S)); } pari-2.7.5/src/basemath/F2x.c0000644000175000017500000011134712405547147014304 0ustar billbill/* Copyright (C) 2007 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 polynomials over F_2 */ /***********************************************************************/ /** **/ /** F2x **/ /** **/ /***********************************************************************/ /* F2x objects are defined as follows: An F2x is a t_VECSMALL: x[0] = codeword x[1] = evalvarn(variable number) (signe is not stored). x[2] = a_0...a_31 x[3] = a_32..a_63, etc. on 32bit x[2] = a_0...a_63 x[3] = a_64..a_127, etc. on 64bit where the a_i are bits. signe(x) is not valid. Use lgpol(x)!=0 instead. Note: pol0_F2x=pol0_Flx and pol1_F2x=pol1_Flx */ INLINE long F2x_degree_lg(GEN x, long l) { return (l==2)?-1:bit_accuracy(l)-bfffo(x[l-1])-1; } long F2x_degree(GEN x) { return F2x_degree_lg(x, lg(x)); } GEN F2x_to_ZX(GEN x) { long l=3+F2x_degree(x); GEN z=cgetg(l,t_POL); long i,j,k; for(i=2,k=2;i=3)|x[1]; return z; } GEN F2xC_to_ZXC(GEN v) { long j, N = lg(v); GEN y = cgetg(N, t_COL); for (j=1; j>j)&1UL; return z; } GEN Z_to_F2x(GEN x, long v) { long sv = evalvarn(v); return mpodd(x) ? pol1_F2x(sv): pol0_F2x(sv); } GEN ZX_to_F2x(GEN x) { long l=nbits2lg(lgpol(x)); GEN z=cgetg(l,t_VECSMALL); long i,j,k; z[1]=((ulong)x[1])&VARNBITS; for(i=2, k=1,j=BITS_IN_LONG;ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz, t_VECSMALL) + 2; for (i=0; inx)? ny+2: nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) *--zd = *--xd; x = zd + a; while (zd > x) *--zd = 0; } else { xd = new_chunk(d); yd = y+d; x = F2x_addspec(x,yd,nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) *--zd = *--yd; *--zd = vs; *--zd = evaltyp(t_VECSMALL) | evallg(lz); return zd; } /* shift polynomial + gerepile */ /* Do not set evalvarn. Cf Flx_shiftip */ static GEN F2x_shiftip(pari_sp av, GEN x, long v) { long i, lx = lg(x), ly; GEN y; if (!v || lx==2) return gerepileuptoleaf(av, x); ly = lx + v; (void)new_chunk(ly); /* check that result fits */ x += lx; y = (GEN)av; for (i = 2; i>BITS_IN_HALFULONG; ulong x2=x&LOWMASK; ulong y1=(y&HIGHMASK)>>BITS_IN_HALFULONG; ulong y2=y&LOWMASK; ulong r1,r2,rr; GEN z; ulong i; rr=r1=r2=0UL; if (x2) for(i=0;i>BITS_IN_HALFULONG; z=cgetg((r1?4:3),t_VECSMALL); z[2]=r2; if (r1) z[3]=r1; return z; } /* fast product (Karatsuba) of polynomials a,b. These are not real GENs, a+2, * b+2 were sent instead. na, nb = number of terms of a, b. * Only c, c0, c1, c2 are genuine GEN. */ static GEN F2x_mulspec(GEN a, GEN b, long na, long nb) { GEN a0,c,c0; long n0, n0a, i, v = 0; pari_sp av; while (na && !a[0]) { a++; na-=1; v++; } while (nb && !b[0]) { b++; nb-=1; v++; } if (na < nb) swapspec(a,b, na,nb); if (!nb) return pol0_F2x(0); av = avma; if (na <=1) return F2x_shiftip(av,F2x_mul1(*a,*b),v); i=(na>>1); n0=na-i; na=i; a0=a+n0; n0a=n0; while (n0a && !a[n0a-1]) n0a--; if (nb > n0) { GEN b0,c1,c2; long n0b; nb -= n0; b0 = b+n0; n0b = n0; while (n0b && !b[n0b-1]) n0b--; c = F2x_mulspec(a,b,n0a,n0b); c0 = F2x_mulspec(a0,b0,na,nb); c2 = F2x_addspec(a0,a,na,n0a); c1 = F2x_addspec(b0,b,nb,n0b); c1 = F2x_mul(c1,c2); c2 = F2x_add(c0,c); c2 = F2x_add(c1,c2); c0 = F2x_addshift(c0,c2,n0); } else { c = F2x_mulspec(a,b,n0a,nb); c0 = F2x_mulspec(a0,b,na,nb); } c0 = F2x_addshift(c0,c,n0); return F2x_shiftip(av,c0, v); } GEN F2x_mul(GEN x, GEN y) { GEN z = F2x_mulspec(x+2,y+2, lgpol(x),lgpol(y)); z[1] = x[1]; return z; } GEN F2x_sqr(GEN x) { const ulong sq[]={0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85}; long i,ii,j,jj; long lx=lg(x), lz=2+((lx-2)<<1); GEN z; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (j=2,jj=2;j>BITS_IN_HALFULONG; ulong x2=(ulong)x[j]&LOWMASK; z[jj]=0; if (x2) for(i=0,ii=0;i>i)&15UL]<>i)&15UL]<>1); GEN z; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (j=2,jj=2;jj>i)&15UL, rh = (x2>>(i+4))&15UL; z[jj]|=sq[rl|(rh<<1)]<>i)&15UL, rh = (x2>>(i+4))&15UL; z[jj]|=(sq[rl|(rh<<1)]<>dc; } if (r) x[i+dl] ^= r; } else for(i=2; i=2; i--) { x[i] = (((ulong)y[i+dl])>>db)|r; r = ((ulong)y[i+dl])<>dc; } x[i+dl] = r; } else for(i=2; i=dy) { F2x_addshiftip(x,y,dx-dy); while (lx>2 && x[lx-1]==0) lx--; dx = F2x_degree_lg(x,lx); } return F2x_renormalize(x, lx); } GEN F2x_divrem(GEN x, GEN y, GEN *pr) { long dx, dy, dz, lx = lg(x), vs = x[1]; GEN z; dy = F2x_degree(y); if (dy<0) pari_err_INV("F2x_divrem",y); if (pr == ONLY_REM) return F2x_rem(x, y); if (!dy) { z = vecsmall_copy(x); if (pr && pr != ONLY_DIVIDES) *pr = pol0_F2x(vs); return z; } dx = F2x_degree_lg(x,lx); dz = dx-dy; if (dz < 0) { if (pr == ONLY_DIVIDES) return dx < 0? vecsmall_copy(x): NULL; z = pol0_F2x(vs); if (pr) *pr = vecsmall_copy(x); return z; } z = zero_zv(lg(x)-lg(y)+2); z[1] = vs; x = vecsmall_copy(x); while (dx>=dy) { F2x_set(z,dx-dy); F2x_addshiftip(x,y,dx-dy); while (lx>2 && x[lx-1]==0) lx--; dx = F2x_degree_lg(x,lx); } z = F2x_renormalize(z, lg(z)); if (!pr) { cgiv(x); return z; } x = F2x_renormalize(x, lx); if (pr == ONLY_DIVIDES) { if (lg(x) == 2) { cgiv(x); return z; } avma = (pari_sp)(z + lg(z)); return NULL; } *pr = x; return z; } long F2x_valrem(GEN x, GEN *Z) { long v, v2, i, l=lg(x); GEN y; if (l==2) { *Z = leafcopy(x); return LONG_MAX; } for (i=2; i> v2; else { const ulong sh = BITS_IN_LONG - v2; ulong r = x[2+v]; for (i=3; i> v2); r = x[i+v]; } y[l-1] = r >> v2; (void)F2x_renormalize(y,l); } *Z = y; return (v << TWOPOTBITS_IN_LONG) + v2; } GEN F2x_deflate(GEN x, long d) { GEN y; long i,id, dy, dx = F2x_degree(x); if (d <= 1) return Flx_copy(x); if (dx < 0) return leafcopy(x); dy = dx/d; /* dy+1 coefficients + 1 extra word for variable */ y = zero_zv(nbits2lg(dy+1)-1); y[1] = x[1]; for (i=id=0; i<=dy; i++,id+=d) if (F2x_coeff(x,id)) F2x_set(y, i); return y; } /* write p(X) = e(X^2) + Xo(X^2), shallow function */ void F2x_even_odd(GEN p, GEN *pe, GEN *po) { long n = F2x_degree(p), n0, n1, i; GEN p0, p1; if (n <= 0) { *pe = leafcopy(p); *po = pol0_F2x(p[1]); return; } n0 = (n>>1)+1; n1 = n+1 - n0; /* n1 <= n0 <= n1+1 */ p0 = zero_zv(nbits2lg(n0+1)-1); p0[1] = p[1]; p1 = zero_zv(nbits2lg(n1+1)-1); p1[1] = p[1]; for (i=0; i>1)&mask; return F2x_renormalize(x,l); } GEN F2x_gcd(GEN a, GEN b) { pari_sp av = avma, lim = stack_lim(av,2); 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 (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); return a; } GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv) { pari_sp av=avma, lim = stack_lim(av,2); GEN u,v,d,d1,v1; long vx = a[1]; d = a; d1 = b; v = pol0_F2x(vx); v1 = pol1_F2x(vx); while (lgpol(d1)) { GEN r, q = F2x_divrem(d,d1, &r); 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 (DEBUGMEM>1) pari_warn(warnmem,"F2x_extgcd (d = %ld)",F2x_degree(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } 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); return d; } static GEN F2x_halfgcd_i(GEN a, GEN b) { pari_sp av=avma, lim = stack_lim(av,2); GEN u,u1,v,v1; long vx = a[1]; long n = (F2x_degree(a)+1)>>1; u1 = v = pol0_F2x(vx); u = v1 = pol1_F2x(vx); while (F2x_degree(b)>=n) { GEN r, q = F2x_divrem(a,b, &r); 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 (DEBUGMEM>1) pari_warn(warnmem,"F2x_halfgcd (d = %ld)",F2x_degree(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } return gerepilecopy(av, mkmat2(mkcol2(u,u1), mkcol2(v,v1))); } GEN F2x_halfgcd(GEN x, GEN y) { pari_sp av; GEN M,q,r; if (F2x_degree(y)= F2x_degree(T); return gen_powers(x, l, use_sqr, (void*)T, &_F2xq_sqr, &_F2xq_mul, &_F2xq_one); } GEN F2xq_matrix_pow(GEN y, long n, long m, GEN P) { return F2xV_to_F2m(F2xq_powers(y,m-1,P),n); } static struct bb_algebra F2xq_algebra = { _F2xq_red,_F2xq_add,_F2xq_mul,_F2xq_sqr,_F2xq_one,_F2xq_zero}; GEN F2x_F2xqV_eval(GEN Q, GEN x, GEN T) { long d = F2x_degree(Q); return gen_bkeval_powers(Q,d,x,(void*)T,&F2xq_algebra,_F2xq_cmul); } GEN F2x_F2xq_eval(GEN Q, GEN x, GEN T) { long d = F2x_degree(Q); int use_sqr = (F2x_degree(x)<<1) >= F2x_degree(T); return gen_bkeval(Q, d, x, use_sqr, (void*)T, &F2xq_algebra, _F2xq_cmul); } static GEN F2xq_autpow_sqr(void * T, GEN x) { return F2x_F2xq_eval(x, x, (GEN) T); } static GEN F2xq_autpow_mul(void * T, GEN x, GEN y) { return F2x_F2xq_eval(x, y, (GEN) T); } GEN F2xq_autpow(GEN x, long n, GEN T) { return gen_powu(x,n,(void*)T,F2xq_autpow_sqr,F2xq_autpow_mul); } ulong F2xq_trace(GEN x, GEN T) { pari_sp av = avma; ulong t; long n = F2x_degree(T)-1; GEN z = F2x_mul(x, F2x_deriv(T)); z = F2x_rem(z, T); t = F2x_degree(z)>n, d = dT-(h<1) err_printf("Found %lu\n", g[2]); } return gerepileuptoint(av, l); } } avma = av; return NULL; } 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); while (1) { GEN M; *g = F2xq_mul(*g, b, T); (*e)++; M = F2x_halfgcd(*g,T); if (F2x_is_smooth(gcoeff(M,1,1), r)) { GEN z = F2x_add(F2x_mul(gcoeff(M,1,1),*g), F2x_mul(gcoeff(M,1,2),T)); if (F2x_is_smooth(z, r)) { GEN F = F2x_factorel(z); GEN G = F2x_factorel(gcoeff(M,1,1)); GEN rel = mkmat2(vecsmall_concat(gel(F, 1),gel(G, 1)), vecsmall_concat(gel(F, 2),zv_neg(gel(G, 2)))); gerepileall(av, 2, g, &rel); return rel; } } if (low_stack(lim, stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xq_log_find_rel"); *g = gerepileuptoleaf(av, *g); } } } static GEN F2xq_log_Coppersmith_rec(GEN W, long r2, GEN a, long r, long n, GEN T, GEN m) { GEN b = polx_F2x(T[1]); ulong AV = 0; GEN g = a, bad = pol0_F2x(T[1]); pari_timer ti; while(1) { long i, l; GEN V, F, E, Ao; timer_start(&ti); V = F2xq_log_find_rel(b, r2, T, &g, &AV); if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r2); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i>n, d = dT-(h<nbrel) break; if (i==j) continue; z = rel_Coppersmith(v, u, h, R, r, n, d); nbtest++; if (!z) continue; gel(M,rel++) = gerepilecopy(av, z); av = avma; if (DEBUGLEVEL && (rel&511UL)==0) err_printf("%ld%%[%ld] ",rel*100/nbrel,i); if (rel>nbrel) break; } } if (rel>nbrel) break; } if (DEBUGLEVEL) err_printf(": %ld tests\n", nbtest); return M; } static GEN smallirred_F2x(ulong n, long sv) { GEN a = zero_zv(nbits2lg(n+1)-1); a[1] = sv; F2x_set(a,n); a[2]++; while (!F2x_is_irred(a)) a[2]+=2; return a; } static GEN check_kernel(long N, GEN M, GEN T, GEN m) { pari_sp av = avma; GEN K = FpMs_leftkernel_elt(M, N, m); long i, f=0; long l = lg(K), lm = lgefint(m); GEN g = polx_F2x(T[1]); GEN idx = diviiexact(subis(int2n(F2x_degree(T)),1),m); pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); K = FpC_Fp_mul(K, Fp_inv(gel(K,g[2]), m), m); for(i=1; i100); GEN T = smallirred_F2x(n,T0[1]); long d = 2, r2 = 3*r/2, d2 = 2; long N = (1UL<<(r+1))-1UL; long nbi = itos(ffsumnbirred(gen_2, r)), nbrel=nbi*5/4; if (DEBUGLEVEL) { err_printf("F2xq_log: Parameters r=%ld r2=%ld\n", r,r2); err_printf("F2xq_log: Size FB=%ld rel. needed=%ld\n", nbi, nbrel); timer_start(&ti); } S = Flx_to_F2x(Flx_ffisom(F2x_to_Flx(T0),F2x_to_Flx(T),2)); a = F2x_F2xq_eval(a0, S, T); b = F2x_F2xq_eval(b0, S, T); if (DEBUGLEVEL) timer_printf(&ti,"model change"); M = F2xq_log_Coppersmith(nbrel,r,d,T); if(DEBUGLEVEL) timer_printf(&ti,"relations"); W = check_kernel(N, M, T, m); timer_start(&ti); Ao = F2xq_log_Coppersmith_rec(W, r2, a, r, d2, T, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth element"); Bo = F2xq_log_Coppersmith_rec(W, r2, b, r, d2, T, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth generator"); e = Fp_div(Ao, Bo, m); if (!F2x_equal(F2xq_pow(b0,e,T0),a0)) pari_err_BUG("F2xq_log"); return gerepileupto(av, e); } static GEN F2xq_easylog(void* E, GEN a, GEN g, GEN ord) { if (F2x_equal1(a)) return gen_0; if (F2x_equal(a,g)) return gen_1; if (typ(ord)!=t_INT) return NULL; if (expi(ord)<28) return NULL; return F2xq_log_index(a,g,ord,(GEN)E); } GEN F2xq_log(GEN a, GEN g, GEN ord, GEN T) { GEN z, v = dlog_get_ordfa(ord); ord = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(28))); z = gen_PH_log(a,g,ord,(void*)T,&F2xq_star); return z? z: cgetg(1,t_VEC); } GEN F2xq_Artin_Schreier(GEN a, GEN T) { pari_sp ltop=avma; long j,N = F2x_degree(T); GEN Q, XP; pari_timer ti; timer_start(&ti); XP = F2xq_sqr(polx_F2x(T[1]),T); Q = F2xq_matrix_pow(XP,N,N,T); for (j=1; j<=N; j++) F2m_flip(Q,j,j); if(DEBUGLEVEL>=9) timer_printf(&ti,"Berlekamp matrix"); F2v_add_inplace(gel(Q,1),a); Q = F2m_ker_sp(Q,0); if(DEBUGLEVEL>=9) timer_printf(&ti,"kernel"); if (lg(Q)!=2) return NULL; Q = gel(Q,1); Q[1] = T[1]; return gerepileuptoleaf(ltop, Q); } GEN F2xq_sqrt_fast(GEN c, GEN sqx, GEN T) { GEN c0, c1; F2x_even_odd(c, &c0, &c1); return F2x_add(c0, F2xq_mul(c1, sqx, T)); } static int F2x_is_x(GEN a) { return lg(a)==3 && a[2]==2; } GEN F2xq_sqrt(GEN a, GEN T) { pari_sp av = avma; long n = F2x_degree(T); GEN sqx; if (n==1) return leafcopy(a); if (n==2) return F2xq_sqr(a,T); sqx = F2xq_autpow(mkF2(4, T[1]), n-1, T); return gerepileuptoleaf(av, F2x_is_x(a)? sqx: F2xq_sqrt_fast(a,sqx,T)); } GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta) { if (!lgpol(a)) { if (signe(n) < 0) pari_err_INV("F2xq_sqrtn",a); if (zeta) *zeta=pol1_F2x(T[1]); return pol0_F2x(T[1]); } return gen_Shanks_sqrtn(a,n,addis(powuu(2,F2x_degree(T)),-1),zeta,(void*)T,&F2xq_star); } GEN gener_F2xq(GEN T, GEN *po) { long i, j, vT = T[1], f = F2x_degree(T); pari_sp av0 = avma, av; GEN g, L2, o, q; if (f == 1) { if (po) *po = mkvec2(gen_1, trivial_fact()); return pol1_F2x(vT); } q = subis(powuu(2,f), 1); o = factor_pn_1(gen_2,f); L2 = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(L2); i++) { if (equaliu(gel(L2,i),2)) continue; gel(L2,j++) = diviiexact(q, gel(L2,i)); } setlg(L2, j); for (av = avma;; avma = av) { g = random_F2x(f, vT); if (F2x_degree(g) < 1) continue; for (i = 1; i < j; i++) { GEN a = F2xq_pow(g, gel(L2,i), T); if (F2x_equal1(a)) break; } if (i == j) break; } if (!po) g = gerepilecopy(av0, g); else { *po = mkvec2(subis(int2n(f), 1), o); gerepileall(av0, 2, &g, po); } return g; } GEN ZXX_to_F2xX(GEN B, long v) { long lb=lg(B); long i; GEN b=cgetg(lb,t_POL); b[1]=evalsigne(1)|(((ulong)B[1])&VARNBITS); for (i=2; i>j)&1UL; return z; } GEN F2m_to_Flm(GEN z) { long i, l = lg(z); GEN x = cgetg(l,t_MAT); for (i=1; in = n; S->t = addsi(-1,n); S->r1 = vali(S->t); S->t1 = shifti(S->t, -S->r1); S->sqrt1 = cgeti(lg(n)); S->sqrt1[1] = evalsigne(0)|evallgefint(2); S->sqrt2 = cgeti(lg(n)); S->sqrt2[1] = evalsigne(0)|evallgefint(2); } static void Fl_init_MR_Jaeschke(Fl_MR_Jaeschke_t *S, ulong n) { S->n = n; S->t = n-1; S->r1 = vals(S->t); S->t1 = S->t >> S->r1; S->sqrt1 = 0; S->sqrt2 = 0; } /* c = sqrt(-1) seen in bad_for_base. End-matching: compare or remember * If ends do mismatch, then we have factored n, and this information * should somehow be made available to the factoring machinery. But so * exceedingly rare... besides we use BSPW now. */ static int MR_Jaeschke_ok(MR_Jaeschke_t *S, GEN c) { if (signe(S->sqrt1)) { /* saw one earlier: compare */ if (!equalii(c, S->sqrt1) && !equalii(c, S->sqrt2)) { /* too many sqrt(-1)s mod n */ if (DEBUGLEVEL) { GEN z = gcdii(addii(c, S->sqrt1), S->n); pari_warn(warner,"found factor\n\t%Ps\ncurrently lost to the factoring machinery", z); } return 1; } } else { /* remember */ affii(c, S->sqrt1); affii(subii(S->n, c), S->sqrt2); } return 0; } static int Fl_MR_Jaeschke_ok(Fl_MR_Jaeschke_t *S, ulong c) { if (S->sqrt1) { /* saw one earlier: compare */ if (c != S->sqrt1 && c != S->sqrt2) return 1; } else { /* remember */ S->sqrt1 = c; S->sqrt2 = S->n - c; } return 0; } /* is n strong pseudo-prime for base a ? 'End matching' (check for square * roots of -1) added by GN */ static int bad_for_base(MR_Jaeschke_t *S, GEN a) { long r, lim, av = avma; 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(DEBUGMEM>1) pari_warn(warnmem,"Rabin-Miller"); c = gerepileuptoint(av, c); } } return 1; } static int Fl_bad_for_base(Fl_MR_Jaeschke_t *S, ulong a) { long r; ulong c2, c = Fl_powu(a, S->t1, S->n); if (c == 1 || c == S->t) return 0; /* go fishing for -1, not for 1 (saves one squaring) */ for (r = S->r1 - 1; r; r--) /* r1 - 1 squarings */ { c2 = c; c = Fl_sqr(c, S->n); if (c == S->t) return Fl_MR_Jaeschke_ok(S, c2); } return 1; } /* Miller-Rabin test for k random bases */ long millerrabin(GEN n, long k) { pari_sp av2, av = avma; ulong r; long i; MR_Jaeschke_t S; 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 (!mod2(n)) return 0; init_MR_Jaeschke(&S, n); av2 = avma; for (i=1; i<=k; i++) { do r = umodui(pari_rand(), n); while (!r); if (DEBUGLEVEL > 4) err_printf("Miller-Rabin: testing base %ld\n", r); if (bad_for_base(&S, utoipos(r))) { avma = av; return 0; } avma = av2; } avma = av; return 1; } GEN gispseudoprime(GEN x, long flag) { return flag? map_proto_lGL(millerrabin, x, flag): map_proto_lG(BPSW_psp,x); } long ispseudoprime(GEN x, long flag) { return flag? millerrabin(x, flag): BPSW_psp(x); } /* As above for k bases taken in pr (i.e not random). We must have |n|>2 and * 1<=k<=11 (not checked) or k in {16,17} to select some special sets of bases. * * From Jaeschke, 'On strong pseudoprimes to several bases', Math.Comp. 61 * (1993), 915--926 (see also http://www.utm.edu/research/primes/prove2.html), * we have: * * k == 4 (bases 2,3,5,7) detects all composites * n < 118 670 087 467 == 172243 * 688969 with the single exception of * n == 3 215 031 751 == 151 * 751 * 28351, * * k == 5 (bases 2,3,5,7,11) detects all composites * n < 2 152 302 898 747 == 6763 * 10627 * 29947, * * k == 6 (bases 2,3,...,13) detects all composites * n < 3 474 749 660 383 == 1303 * 16927 * 157543, * * k == 7 (bases 2,3,...,17) detects all composites * n < 341 550 071 728 321 == 10670053 * 32010157, * Even this limiting value is caught by an end mismatch between bases 5 and 17 * * Moreover, the four bases chosen at * * k == 16 (2,13,23,1662803) detects all composites up * to at least 10^12, and the combination at * * k == 17 (31,73) detects most odd composites without prime factors > 100 * in the range n < 2^36 (with less than 250 exceptions, indeed with fewer * than 1400 exceptions up to 2^42). --GN */ int Fl_MR_Jaeschke(ulong n, long k) { const ulong pr[] = { 0, 2,3,5,7,11,13,17,19,23,29, 31,73, 2,13,23,1662803UL, }; const ulong *p; ulong r; long i; Fl_MR_Jaeschke_t S; if (!(n & 1)) return 0; if (k == 16) { /* use smaller (faster) bases if possible */ p = (n < 3215031751UL)? pr: pr+13; k = 4; } else if (k == 17) { p = (n < 1373653UL)? pr: pr+11; k = 2; } else p = pr; /* 2,3,5,... */ Fl_init_MR_Jaeschke(&S, n); for (i=1; i<=k; i++) { r = p[i] % n; if (!r) break; if (Fl_bad_for_base(&S, r)) return 0; } return 1; } int MR_Jaeschke(GEN n, long k) { pari_sp av2, av = avma; const ulong pr[] = { 0, 2,3,5,7,11,13,17,19,23,29, 31,73, 2,13,23,1662803UL, }; const ulong *p; long i; MR_Jaeschke_t S; if (lgefint(n) == 3) return Fl_MR_Jaeschke((ulong)n[2], k); if (!mod2(n)) return 0; if (k == 16) { p = pr+13; k = 4; } /* 2,13,23,1662803 */ else if (k == 17) { p = pr+11; k = 2; } /* 31,73 */ else p = pr; /* 2,3,5,... */ init_MR_Jaeschke(&S, n); av2 = avma; for (i=1; i<=k; i++) { if (bad_for_base(&S, utoipos(p[i]))) { avma = av; return 0; } avma = av2; } avma = av; return 1; } /*********************************************************************/ /** **/ /** PSEUDO PRIMALITY (LUCAS) **/ /** **/ /*********************************************************************/ /* compute n-th term of Lucas sequence modulo N. * v_{k+2} = P v_{k+1} - v_k, v_0 = 2, v_1 = P. * Assume n > 0 */ static GEN LucasMod(GEN n, ulong P, GEN N) { pari_sp av = avma, lim = stack_lim(av, 1); GEN nd = int_MSW(n); long i, m = *nd, j = 1+bfffo((ulong)m); GEN v = utoipos(P), v1 = utoipos(P*P - 2); m <<= j; j = BITS_IN_LONG - j; for (i=lgefint(n)-2;;) /* cf. leftright_pow */ { for (; j; m<<=1,j--) { /* v = v_k, v1 = v_{k+1} */ if (m < 0) { /* set v = v_{2k+1}, v1 = v_{2k+2} */ v = subis(mulii(v,v1), (long)P); v1= subis(sqri(v1), 2); } else {/* set v = v_{2k}, v1 = v_{2k+1} */ v1= subis(mulii(v,v1), (long)P); v = subis(sqri(v), 2); } v = modii(v, N); v1= modii(v1,N); if (low_stack(lim,stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"LucasMod"); gerepileall(av, 2, &v,&v1); } } if (--i == 0) return v; j = BITS_IN_LONG; nd=int_precW(nd); m = *nd; } } /* compute n-th term of Lucas sequence modulo N. * v_{k+2} = P v_{k+1} - v_k, v_0 = 2, v_1 = P. * Assume n > 0 */ static ulong u_LucasMod(ulong n, ulong P, ulong N) { long j = 1 + bfffo(n); ulong v = P, v1 = P*P - 2, mP = N - P, m2 = N - 2, m = n << j; j = BITS_IN_LONG - j; for (; j; m<<=1,j--) { /* v = v_k, v1 = v_{k+1} */ if (((long)m) < 0) { /* set v = v_{2k+1}, v1 = v_{2k+2} */ v = Fl_add(Fl_mul(v,v1,N), mP, N); v1= Fl_add(Fl_mul(v1,v1,N),m2, N); } else {/* set v = v_{2k}, v1 = v_{2k+1} */ v1= Fl_add(Fl_mul(v,v1,N),mP, N); v = Fl_add(Fl_mul(v,v,N), m2, N); } } return v; } int uislucaspsp(ulong n) { long i, v; ulong b, z, m2, m = n + 1; for (b=3, i=0;; b+=2, i++) { ulong c = b*b - 4; /* = 1 mod 4 */ if (krouu(n % c, c) < 0) break; if (i == 64 && uissquareall(n, &c)) return 0; /* oo loop if N = m^2 */ } if (!m) return 0; /* neither 2^32-1 nor 2^64-1 are Lucas-pp */ v = vals(m); m >>= v; z = u_LucasMod(m, b, n); if (z == 2) return 1; m2 = n - 2; if (z == m2) return 1; for (i=1; i 3 */ static int IsLucasPsP(GEN N) { pari_sp av = avma, lim = stack_lim(av, 1); GEN N_2, m, z; long i, v; ulong b; for (b=3, i=0;; b+=2, i++) { ulong c = b*b - 4; /* = 1 mod 4 */ if (i == 64 && Z_issquare(N)) return 0; /* avoid oo loop if N = m^2 */ if (krouu(umodiu(N,c), c) < 0) break; } m = addis(N,1); v = vali(m); m = shifti(m,-v); z = LucasMod(m, b, N); if (equaliu(z, 2)) return 1; N_2 = subis(N,2); if (equalii(z, N_2)) return 1; for (i=1; i1) pari_warn(warnmem,"IsLucasPsP"); z = gerepileupto(av, z); } } return 0; } /* assume u odd, u > 1 */ static int iu_coprime(GEN N, ulong u) { const ulong n = umodiu(N, u); return (n == 1 || gcduodd(n, u) == 1); } /* assume u odd, u > 1 */ static int uu_coprime(ulong n, ulong u) { return gcduodd(n, u) == 1; } /* composite strong 2-pseudoprime < 1016801 whose prime divisors are > 101 */ static int is_2_prp_101(ulong n) { switch(n) { case 42799: case 49141: case 88357: case 90751: case 104653: case 130561: case 196093: case 220729: case 253241: case 256999: case 271951: case 280601: case 357761: case 390937: case 458989: case 486737: case 489997: case 514447: case 580337: case 741751: case 838861: case 873181: case 877099: case 916327: case 976873: case 983401: return 1; } return 0; } static int u_2_prp(ulong n) { Fl_MR_Jaeschke_t S; Fl_init_MR_Jaeschke(&S, n); return Fl_bad_for_base(&S, 2) == 0; } static int uBPSW_psp(ulong n) { return (u_2_prp(n) && uislucaspsp(n)); } int uisprime(ulong n) { if (n < 103) switch(n) { case 2: case 3: case 5: case 7: case 11: case 13: case 17: case 19: case 23: case 29: case 31: case 37: case 41: case 43: case 47: case 53: case 59: case 61: case 67: case 71: case 73: case 79: case 83: case 89: case 97: case 101: return 1; default: return 0; } if (!odd(n)) return 0; #ifdef LONG_IS_64BIT /* 16294579238595022365 = 3*5*7*11*13*17*19*23*29*31*37*41*43*47*53 * 7145393598349078859 = 59*61*67*71*73*79*83*89*97*101 */ if (!uu_coprime(n, 16294579238595022365UL) || !uu_coprime(n, 7145393598349078859UL)) return 0; #else /* 4127218095 = 3*5*7*11*13*17*19*23*37 * 3948078067 = 29*31*41*43*47*53 * 4269855901 = 59*83*89*97*101 * 1673450759 = 61*67*71*73*79 */ if (!uu_coprime(n, 4127218095UL) || !uu_coprime(n, 3948078067UL) || !uu_coprime(n, 1673450759UL) || !uu_coprime(n, 4269855901UL)) return 0; #endif if (n < 10427) return 1; if (n < 1016801) return !is_2_prp_101(n) && u_2_prp(n); return uBPSW_psp(n); } /* assume no prime divisor <= 101 */ int uisprime_101(ulong n) { if (n < 10427) return 1; if (n < 1016801) return !is_2_prp_101(n) && u_2_prp(n); return uBPSW_psp(n); } /* assume no prime divisor <= 661 */ int uisprime_661(ulong n) { return uBPSW_psp(n); } long BPSW_psp(GEN N) { pari_sp av; MR_Jaeschke_t S; int k; 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 (!mod2(N)) return 0; #ifdef LONG_IS_64BIT /* 16294579238595022365 = 3*5*7*11*13*17*19*23*29*31*37*41*43*47*53 * 7145393598349078859 = 59*61*67*71*73*79*83*89*97*101 */ if (!iu_coprime(N, 16294579238595022365UL) || !iu_coprime(N, 7145393598349078859UL)) return 0; #else /* 4127218095 = 3*5*7*11*13*17*19*23*37 * 3948078067 = 29*31*41*43*47*53 * 4269855901 = 59*83*89*97*101 * 1673450759 = 61*67*71*73*79 */ if (!iu_coprime(N, 4127218095UL) || !iu_coprime(N, 3948078067UL) || !iu_coprime(N, 1673450759UL) || !iu_coprime(N, 4269855901UL)) return 0; #endif /* no prime divisor < 103 */ av = avma; init_MR_Jaeschke(&S, N); k = (!bad_for_base(&S, gen_2) && IsLucasPsP(N)); avma = av; return k; } /* can we write n = x^k ? Assume N has no prime divisor <= 2^14. * Not memory clean */ long isanypower_nosmalldiv(GEN N, GEN *px) { GEN x = N, y; ulong mask = 7; long ex, k = 1; forprime_t T; while (Z_issquareall(x, &y)) { k <<= 1; x = y; } while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } (void)u_forprime_init(&T, 11, ULONG_MAX); /* stop when x^(1/k) < 2^14 */ while ( (ex = is_pth_power(x, &y, &T, 15)) ) { k *= ex; x = y; } *px = x; return k; } /* no prime divisor <= 2^14 (> 661) */ long BPSW_psp_nosmalldiv(GEN N) { pari_sp av; MR_Jaeschke_t S; long l = lgefint(N); int k; if (l == 3) return uisprime_661((ulong)N[2]); av = avma; /* N large: test for pure power, rarely succeeds, but requires < 1% of * compositeness test times */ if (bit_accuracy(l) > 512 && isanypower_nosmalldiv(N, &N) != 1) { avma = av; return 0; } init_MR_Jaeschke(&S, N); k = (!bad_for_base(&S, gen_2) && IsLucasPsP(N)); avma = av; return k; } /***********************************************************************/ /** **/ /** Pocklington-Lehmer **/ /** P-1 primality test **/ /** **/ /***********************************************************************/ /* Assume x BPSW pseudoprime. Check whether it's small enough to be certified * prime (< 2^64). Reference for strong 2-pseudoprimes: * http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html */ static int BPSW_isprime_small(GEN x) { long l = lgefint(x); #ifdef LONG_IS_64BIT return (l == 3); #else return (l <= 4); #endif } /* Brillhart, Lehmer, Selfridge test (Crandall & Pomerance, Th 4.1.5) * N^(1/3) <= f fully factored, f | N-1. If pl831(p) is true for * any prime divisor p of f, then any divisor of N is 1 mod f. * In that case return 1 iff N is prime */ static int BLS_test(GEN N, GEN f) { GEN c1, c2, r, q; q = dvmdii(N, f, &r); if (!is_pm1(r)) return 0; c2 = dvmdii(q, f, &c1); /* N = 1 + f c1 + f^2 c2, 0 <= c_i < f; check whether it is of the form * (1 + f a)(1 + fb) */ return ! Z_issquare(subii(sqri(c1), shifti(c2,2))); } /*assume N>1, p^e || N-1. Find a witness a(p) such that * a^(N-1) = 1 (mod N) * a^(N-1)/p - 1 invertible mod N. * Proves that any divisor of N is 1 mod p^e */ static ulong pl831(GEN N, GEN p) { pari_sp ltop = avma, av; ulong a; GEN Nmunp = diviiexact(addis(N,-1), p); av = avma; for(a = 2;; a++, avma = av) { GEN b = Fp_pow(utoipos(a), Nmunp, N); GEN c = Fp_pow(b,p,N), g = gcdii(addis(b,-1), N); if (!is_pm1(c)) return 0; if (is_pm1(g)) { avma=ltop; return a; } if (!equalii(g,N)) return 0; } } /* Assume x BPSW pseudoprime. Return gen_0 if not prime, and a primality * certificate otherwise */ static GEN isprimePL(GEN N); static GEN 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; } /* initialize Selfridge / Pocklington-Lehmer test, return 0 * if proven composite */ static int selfridge_init(GEN N, GEN *pF, GEN *pf) { GEN cbrtN = sqrtnint(N, 3); GEN N_1 = addis(N,-1); GEN F = Z_factor_until(N_1, sqri(cbrtN)); GEN f = factorback(F); /* factored part of N-1, f^3 > N */ *pF = gel(F,1); *pf = f; /* smooth or N^(1/2)-smooth (Pocklington) or N^(1/3)-smooth (BLS) */ return equalii(f, N_1) || cmpii(sqri(f), N) > 0 || BLS_test(N,f); } /* Assume N is a strong BPSW pseudoprime, Pocklington-Lehmer primality proof. * * return gen_0 (non-prime), gen_1 (small prime), matrix (large prime) * * The matrix has 3 columns, [a,b,c] with * a[i] prime factor of N-1, * b[i] witness for a[i] as in pl831 * c[i] isprimePL(a[i]) */ static GEN isprimePL(GEN N) { pari_sp ltop = avma; long i, l; int eps; GEN C, P, W, R, F, f; if (typ(N) != t_INT) pari_err_TYPE("isprimePL",N); eps = cmpis(N,2); if (eps <= 0) return eps? gen_0: gen_1; /* N > 2 */ if (!selfridge_init(N, &F, &f)) { avma = ltop; return gen_0; } if (DEBUGLEVEL>3) { err_printf("Pocklington-Lehmer: proving primality of N = %Ps\n", 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); for(i=1; i3) err_printf("Pocklington-Lehmer: recursively proving primality of p = %Ps\n", p); if (!BPSW_isprime(p)) return 0; } return 1; } /* assume N a BPSW pseudoprime, in particular, it is odd > 2 */ long BPSW_isprime(GEN N) { pari_sp av = avma; long l, res; ulong B; GEN fa, P, E, p, U, F, N_1; 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; } 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); } /* 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); avma = av; return res; } GEN gisprime(GEN x, long flag) { switch (flag) { case 0: return map_proto_lG(isprime,x); case 1: return map_proto_G(isprimePL,x); case 2: return map_proto_lG(isprimeAPRCL,x); } pari_err_FLAG("gisprime"); return NULL; } long isprime(GEN x) { return BPSW_psp(x) && BPSW_isprime(x); } /***********************************************************************/ /** **/ /** PRIME NUMBERS **/ /** **/ /***********************************************************************/ static struct { ulong p; long n; } prime_table[] = { { 0, 0}, { 7919, 1000}, { 17389, 2000}, { 27449, 3000}, { 37813, 4000}, { 48611, 5000}, { 59359, 6000}, { 70657, 7000}, { 81799, 8000}, { 93179, 9000}, { 104729, 10000}, { 224737, 20000}, { 350377, 30000}, { 479909, 40000}, { 611953, 50000}, { 746773, 60000}, { 882377, 70000}, { 1020379, 80000}, { 1159523, 90000}, { 1299709, 100000}, { 2750159, 200000}, { 7368787, 500000}, { 15485863, 1000000}, { 32452843, 2000000}, { 86028121, 5000000}, { 179424673, 10000000}, { 373587883, 20000000}, { 982451653, 50000000}, { 2038074743, 100000000}, { 4000000483UL,189961831}, { 4222234741UL,200000000}, #if BITS_IN_LONG == 64 { 11037271757, 500000000}, { 22801763489, 1000000000}, { 47055833459, 2000000000}, {122430513841, 5000000000}, {200000000507, 8007105083}, #endif }; static const int prime_table_len = sizeof(prime_table)/sizeof(prime_table[0]); /* find prime closest to n in prime_table. */ static long prime_table_closest_p(ulong n) { long i; for (i = 1; i < prime_table_len; i++) { ulong p = prime_table[i].p; if (p > n) { ulong u = n - prime_table[i-1].p; if (p - n > u) i--; break; } } if (i == prime_table_len) i = prime_table_len - 1; return i; } /* return the n-th successor of prime p > 2 */ static GEN prime_successor(ulong p, ulong n) { forprime_t S; ulong i; forprime_init(&S, utoipos(p+1), NULL); for (i = 1; i < n; i++) (void)forprime_next(&S); return forprime_next(&S); } /* find the N-th prime */ static GEN prime_table_find_n(ulong N) { byteptr d; ulong n, p, maxp = maxprime(); long i; for (i = 1; i < prime_table_len; i++) { n = prime_table[i].n; if (n > N) { ulong u = N - prime_table[i-1].n; if (n - N > u) i--; break; } } if (i == prime_table_len) i = prime_table_len - 1; p = prime_table[i].p; n = prime_table[i].n; if (n > N && p > maxp) { i--; p = prime_table[i].p; n = prime_table[i].n; } /* if beyond prime table, then n <= N */ d = diffptr + n; if (n > N) { n -= N; do { n--; PREC_PRIME_VIADIFF(p,d); } while (n) ; } else if (n < N) { n = N-n; if (p > maxp) return prime_successor(p, n); do { if (!*d) return prime_successor(p, n); n--; NEXT_PRIME_VIADIFF(p,d); } while (n) ; } return utoipos(p); } ulong uprime(long N) { pari_sp av = avma; GEN p; if (N <= 0) pari_err_DOMAIN("prime", "n", "<=",gen_0, stoi(N)); p = prime_table_find_n(N); if (lgefint(p) != 3) pari_err_OVERFLOW("uprime"); avma = av; return p[2]; } GEN prime(long N) { pari_sp av = avma; GEN p; if (N <= 0) pari_err_DOMAIN("prime", "n", "<=",gen_0, stoi(N)); new_chunk(4); /*HACK*/ p = prime_table_find_n(N); avma = av; return icopy(p); } /* random b-bit prime */ GEN randomprime(GEN N) { pari_sp av = avma, av2; GEN a, b, d; if (!N) for(;;) { ulong p = random_bits(31); if (uisprime(p)) return utoipos(p); } switch(typ(N)) { case t_INT: a = gen_2; 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); break; case t_VEC: if (lg(N) != 3) pari_err_TYPE("randomprime",N); a = gel(N,1); b = gel(N,2); if (gcmp(b, a) < 0) pari_err_DOMAIN("randomprime","b-a", "<", gen_0, mkvec2(a,b)); if (typ(a) != t_INT) { a = gceil(a); if (typ(a) != t_INT) pari_err_TYPE("randomprime",a); } if (typ(b) != t_INT) { b = gfloor(b); if (typ(b) != t_INT) pari_err_TYPE("randomprime",b); } if (cmpis(a, 2) < 0) { a = gen_2; d = subiu(b,1); } else d = addiu(subii(b,a), 1); if (signe(d) <= 0) pari_err_DOMAIN("randomprime","floor(b) - max(ceil(a),2)", "<", gen_0, mkvec2(a,b)); break; default: pari_err_TYPE("randomprime", N); return NULL; /*notreached*/ } av2 = avma; for (;;) { GEN p = addii(a, randomi(d)); if (BPSW_psp(p)) return gerepileuptoint(av, p); avma = av2; } } /* set *pp = nextprime(a) = p * *pd so that NEXT_PRIME_VIADIFF(d, p) = nextprime(p+1) * *pn so that p = the n-th prime * error if nextprime(a) is out of primetable bounds */ void prime_table_next_p(ulong a, byteptr *pd, ulong *pp, ulong *pn) { byteptr d; ulong p, n, maxp = maxprime(); long i = prime_table_closest_p(a); p = prime_table[i].p; if (p > a && p > maxp) { i--; p = prime_table[i].p; } /* if beyond prime table, then p <= a */ n = prime_table[i].n; d = diffptr + n; if (p < a) { if (a > maxp) pari_err_MAXPRIME(a); do { n++; NEXT_PRIME_VIADIFF(p,d); } while (p < a); } else if (p != a) { do { n--; PREC_PRIME_VIADIFF(p,d); } while (p > a) ; if (p < a) { NEXT_PRIME_VIADIFF(p,d); n++; } } *pn = n; *pp = p; *pd = d; } ulong uprimepi(ulong a) { ulong p, n, maxp = maxprime(); if (a <= maxp) { byteptr d; prime_table_next_p(a, &d, &p, &n); return p == a? n: n-1; } else { long i = prime_table_closest_p(a); forprime_t S; p = prime_table[i].p; if (p > a) { i--; p = prime_table[i].p; } /* p = largest prime in table <= a */ n = prime_table[i].n; (void)u_forprime_init(&S, p+1, a); for (; p; n++) p = u_forprime_next(&S); return n-1; } } GEN primepi(GEN x) { pari_sp av = avma; GEN pp, nn, N = typ(x) == t_INT? x: gfloor(x); forprime_t S; ulong n, p; long i, l; if (typ(N) != t_INT) pari_err_TYPE("primepi",N); if (signe(N) <= 0) return gen_0; avma = av; l = lgefint(N); if (l == 3) return utoi(uprimepi(N[2])); i = prime_table_len-1; p = prime_table[i].p; n = prime_table[i].n; (void)forprime_init(&S, utoipos(p+1), N); nn = setloop(utoipos(n)); pp = gen_0; for (; pp; incloop(nn)) pp = forprime_next(&S); return gerepileuptoint(av, subiu(nn,1)); } /* pi(x) < x/log x * (1 + 1/log x + 2.51/log^2 x)), x>=355991 [ Dusart ] * pi(x) < x/(log x - 1.1), x >= 60184 [ Dusart ] * ? \p9 * ? M = 0; for(x = 4, 60184, M = max(M, log(x) - x/primepi(x))); M * %1 = 1.11196252 */ double primepi_upper_bound(double x) { if (x >= 355991) { double L = 1/log(x); return x * L * (1 + L + 2.51*L*L); } if (x >= 60184) return x / (log(x) - 1.1); if (x < 5) return 2; /* don't bother */ return x / (log(x) - 1.111963); } /* pi(x) > x/log x (1 + 1/log x), x >= 599 [ Dusart ] * pi(x) > x / (log x + 2), x >= 55 [ Rosser ] */ double primepi_lower_bound(double x) { if (x >= 599) { double L = 1/log(x); return x * L * (1 + L); } if (x < 55) return 0; /* don't bother */ return x / (log(x) + 2.); } GEN gprimepi_upper_bound(GEN x) { pari_sp av = avma; double L; if (typ(x) != t_INT) x = gfloor(x); if (expi(x) <= 1022) { avma = av; return dbltor(primepi_upper_bound(gtodouble(x))); } x = itor(x, LOWDEFAULTPREC); L = 1 / rtodbl(logr_abs(x)); x = mulrr(x, dbltor(L * (1 + L + 2.51*L*L))); return gerepileuptoleaf(av, x); } GEN gprimepi_lower_bound(GEN x) { pari_sp av = avma; double L; if (typ(x) != t_INT) x = gfloor(x); if (cmpiu(x, 55) <= 0) return gen_0; if (expi(x) <= 1022) { avma = av; return dbltor(primepi_lower_bound(gtodouble(x))); } x = itor(x, LOWDEFAULTPREC); L = 1 / rtodbl(logr_abs(x)); x = mulrr(x, dbltor(L * (1 + L))); return gerepileuptoleaf(av, x); } GEN primes(long n) { forprime_t S; long i; GEN y; if (n <= 0) return cgetg(1, t_VEC); y = cgetg(n+1, t_VEC); (void)new_chunk(3*n); /*HACK*/ u_forprime_init(&S, 2, ULONG_MAX); avma = (pari_sp)y; for (i = 1; i <= n; i++) gel(y, i) = utoipos( u_forprime_next(&S) ); return y; } GEN primes_zv(long n) { forprime_t S; long i; GEN y; if (n <= 0) return cgetg(1, t_VECSMALL); y = cgetg(n+1,t_VECSMALL); u_forprime_init(&S, 2, ULONG_MAX); for (i = 1; i <= n; i++) y[i] = u_forprime_next(&S); avma = (pari_sp)y; return y; } GEN primes0(GEN N) { switch(typ(N)) { case t_INT: return primes(itos(N)); case t_VEC: if (lg(N) == 3) return primes_interval(gel(N,1),gel(N,2)); } pari_err_TYPE("primes", N); return NULL; } GEN primes_interval(GEN a, GEN b) { pari_sp av = avma; forprime_t S; long i, n; GEN y, d, p; 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) { avma = av; y = primes_interval_zv(itou(a), itou(b)); n = lg(y); settyp(y, t_VEC); for (i = 1; i < n; i++) gel(y,i) = utoipos(y[i]); return y; } /* at most d+1 primes in [a,b]. If d large, try better bound to lower * memory use */ if (cmpiu(d,100000) > 0) { GEN D = gsub(gprimepi_upper_bound(b), gprimepi_lower_bound(a)); D = ceil_safe(D); if (cmpii(D, d) < 0) d = D; } n = itos(d)+1; forprime_init(&S, a, b); y = cgetg(n+1, t_VEC); i = 1; while ((p = forprime_next(&S))) gel(y, i++) = icopy(p); setlg(y, i); return gerepileupto(av, y); } /* a <= b, at most d primes in [a,b]. Return them */ static GEN primes_interval_i(ulong a, ulong b, ulong d) { ulong p, i = 1, n = d + 1; forprime_t S; GEN y = cgetg(n+1, t_VECSMALL); pari_sp av = avma; u_forprime_init(&S, a, b); while ((p = u_forprime_next(&S))) y[i++] = p; avma = av; setlg(y, i); stackdummy((pari_sp)(y + i), (pari_sp)(y + n+1)); return y; } GEN primes_interval_zv(ulong a, ulong b) { ulong d; if (!a) return primes_upto_zv(b); if (b < a) return cgetg(1, t_VECSMALL); d = b - 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 primes_upto_zv(ulong b) { ulong d; if (b < 2) return cgetg(1, t_VECSMALL); d = (b > 100000UL)? primepi_upper_bound(b): b; return primes_interval_i(2, b, d); } /***********************************************************************/ /** **/ /** PRIVATE PRIME TABLE **/ /** **/ /***********************************************************************/ /* delete dummy NULL entries */ static void cleanprimetab(GEN T) { long i,j, l = lg(T); for (i = j = 1; i < l; i++) if (T[i]) T[j++] = T[i]; setlg(T,j); } /* remove p from T */ static void rmprime(GEN T, GEN p) { long i; if (typ(p) != t_INT) pari_err_TYPE("removeprimes",p); i = ZV_search(T, p); if (!i) pari_err_DOMAIN("removeprime","prime","not in", strtoGENstr("primetable"), p); gunclone(gel(T,i)); gel(T,i) = NULL; cleanprimetab(T); } /*stolen from ZV_union_shallow() : clone entries from y */ static GEN addp_union(GEN x, GEN y) { long i, j, k, lx = lg(x), ly = lg(y); GEN z = cgetg(lx + ly - 1, t_VEC); i = j = k = 1; while (i 0) gel(z,k++) = gclone(gel(y,j++)); else { gel(z,k++) = gel(x,i++); j++; } } while (i1; k++,l-=2) { av = avma; a = diviuuexact(muluui(l, l-1, a), 4*k, n-k); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } static void polchebyshev1_eval_aux(long n, GEN x, GEN *pt1, GEN *pt2) { GEN t1, t2, b; if (n == 1) { *pt1 = gen_1; *pt2 = x; return; } if (n == 0) { *pt1 = x; *pt2 = gen_1; return; } polchebyshev1_eval_aux((n+1) >> 1, x, &t1, &t2); b = gsub(gmul(gmul2n(t1,1), t2), x); if (odd(n)) { *pt1 = gadd(gmul2n(gsqr(t1), 1), gen_m1); *pt2 = b; } else { *pt1 = b; *pt2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); } } static GEN polchebyshev1_eval(long n, GEN x) { GEN t1, t2; long i, v; pari_sp av; if (n < 0) n = -n; if (n==0) return gen_1; if (n==1) return gcopy(x); av = avma; v = u_lvalrem(n, 2, (ulong*)&n); polchebyshev1_eval_aux((n+1)>>1, x, &t1, &t2); if (n != 1) t2 = gsub(gmul(gmul2n(t1,1), t2), x); for (i = 1; i <= v; i++) t2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); return gerepileupto(av, t2); } /* Chebychev polynomial of the second kind U(n,x): the coefficient in front of * x^(n-2*m) is (-1)^m * 2^(n-2m)*(n-m)!/m!/(n-2m)! for m=0,1,...,n/2 */ GEN polchebyshev2(long n, long v) { pari_sp av; GEN q, a, r; long m; int neg = 0; if (v<0) v = 0; /* polchebyshev(-n,2) = -polchebyshev(n-2,2) */ if (n < 0) { if (n == -1) return zeropol(v); neg = 1; n = -n-2; } if (n==0) return neg ? scalar_ZX_shallow(gen_m1, v): pol_1(v); q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n); if (neg) togglesign(a); gel(r--,0) = a; gel(r--,0) = gen_0; for (m=1; 2*m<= n; m++) { av = avma; a = diviuuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m, n-m+1); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } static void polchebyshev2_eval_aux(long n, GEN x, GEN *pu1, GEN *pu2) { GEN u1, u2, u, mu1; if (n == 1) { *pu1 = gen_1; *pu2 = gmul2n(x,1); return; } if (n == 0) { *pu1 = gen_0; *pu2 = gen_1; return; } polchebyshev2_eval_aux(n >> 1, x, &u1, &u2); mu1 = gneg(u1); u = gmul(gadd(u2,u1), gadd(u2,mu1)); if (odd(n)) { *pu1 = u; *pu2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); } else { *pu2 = u; *pu1 = gmul(gmul2n(u1,1), gadd(u2, gmul(x,mu1))); } } static GEN polchebyshev2_eval(long n, GEN x) { GEN u1, u2, mu1; long neg = 0; pari_sp av; if (n < 0) { if (n == -1) return gen_0; neg = 1; n = -n-2; } if (n==0) return neg ? gen_m1: gen_1; av = avma; polchebyshev2_eval_aux(n>>1, x, &u1, &u2); mu1 = gneg(u1); if (odd(n)) u2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); else u2 = gmul(gadd(u2,u1), gadd(u2,mu1)); if (neg) u2 = gneg(u2); return gerepileupto(av, u2); } GEN polchebyshev(long n, long kind, long v) { switch (kind) { case 1: return polchebyshev1(n, v); case 2: return polchebyshev2(n, v); default: pari_err_FLAG("polchebyshev"); } return NULL; /* not reached */ } GEN polchebyshev_eval(long n, long kind, GEN x) { if (!x) return polchebyshev(n, kind, 0); if (gequalX(x)) return polchebyshev(n, kind, varn(x)); switch (kind) { case 1: return polchebyshev1_eval(n, x); case 2: return polchebyshev2_eval(n, x); default: pari_err_FLAG("polchebyshev"); } return NULL; /* not reached */ } /* Hermite polynomial H(n,x): H(n+1) = 2x H(n) - 2n H(n-1) * The coefficient in front of x^(n-2*m) is * (-1)^m * n! * 2^(n-2m)/m!/(n-2m)! for m=0,1,...,n/2.. */ GEN polhermite(long n, long v) { long m; pari_sp av; GEN q,a,r; if (v<0) v = 0; if (n < 0) pari_err_DOMAIN("polhermite", "degree", "<", gen_0, stoi(n)); if (n==0) return pol_1(v); q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n); gel(r--,0) = a; gel(r--,0) = gen_0; for (m=1; 2*m<= n; m++) { av = avma; a = diviuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m); togglesign(a); gel(r--,0) = a = gerepileuptoint(av, a); gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } GEN polhermite_eval(long n, GEN x) { long i; pari_sp av, av2; GEN x2, u, v; if (!x) return polhermite(n, 0); if (gequalX(x)) return polhermite(n, varn(x)); if (n==0) return gen_1; if (n==1) return gmul2n(x,1); av = avma; x2 = gmul2n(x,1); v = gen_1; u = x2; av2= avma; for (i=1; i1; k++,l-=2) { /* l = n-2*k+2 */ av = avma; a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return gerepileupto(av, gmul2n(q,-n)); } GEN pollegendre_eval(long n, GEN x) { long i; pari_sp av; GEN u, v; if (!x) return pollegendre(n, 0); if (gequalX(x)) return pollegendre(n, varn(x)); /* pollegendre(-n) = pollegendre(n-1) */ if (n < 0) n = -n-1; if (n==0) return gen_1; if (n==1) return gcopy(x); av = avma; v = gen_1; u = x; for (i=1; i 1) { qpow = new_chunk(I+1); gel(qpow,2)=q; } for (j=3; j<=I; j++) gel(qpow,j) = gmul(q, gel(qpow,j-1)); } for (i=1; i<=n; i++) { I = (i+1)/2; gcoeff(m,i,1)= gen_1; if (q) { for (j=2; j<=I; j++) gcoeff(m,i,j) = gadd(gmul(gel(qpow,j),gcoeff(m,i-1,j)), gcoeff(m,i-1,j-1)); } else { for (j=2; j<=I; j++) gcoeff(m,i,j) = addii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1)); } for ( ; j<=i; j++) gcoeff(m,i,j) = gcoeff(m,i,i+1-j); for ( ; j<=n; j++) gcoeff(m,i,j) = gen_0; } return gerepilecopy(av, m); } /******************************************************************/ /** **/ /** PRECISION CHANGES **/ /** **/ /******************************************************************/ GEN gprec(GEN x, long l) { long lx, i; GEN y; if (l <= 0) pari_err_DOMAIN("gprec", "precision", "<=", gen_0, stoi(l)); switch(typ(x)) { case t_REAL: return rtor(x, ndec2prec(l)); case t_COMPLEX: y = cgetg(3, t_COMPLEX); gel(y,1) = gprec(gel(x,1),l); gel(y,2) = gprec(gel(x,2),l); break; case t_PADIC: if (!signe(gel(x,4))) return zeropadic(gel(x,2), l+precp(x)); y=cgetg(5,t_PADIC); y[1]=x[1]; setprecp(y,l); gel(y,2) = icopy(gel(x,2)); gel(y,3) = powiu(gel(x,2),l); gel(y,4) = modii(gel(x,4), gel(y,3)); break; case t_SER: if (lg(x) == 2) return zeroser(varn(x), l); y=cgetg(l+2,t_SER); y[1]=x[1]; l++; i=l; lx = lg(x); if (l>=lx) for ( ; i>=lx; i--) gel(y,i) = gen_0; for ( ; i>=2; i--) gel(y,i) = gcopy(gel(x,i)); break; case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i pr)? rtor(x,pr): x; case t_COMPLEX: y = cgetg(3, t_COMPLEX); gel(y,1) = gprec_wtrunc(gel(x,1),pr); gel(y,2) = gprec_wtrunc(gel(x,2),pr); break; case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i n) return gen_0; k = minuu(k,n-k); if (!k) return gen_1; if (k == 1) return utoipos(n); z = diviiexact(mulu_interval(n-k+1, n), mulu_interval(2UL, k)); return gerepileuptoint(ltop,z); } GEN binomial(GEN n, long k) { long i, prec; pari_sp av; GEN y; if (k <= 1) { if (is_noncalc_t(typ(n))) pari_err_TYPE("binomial",n); if (k < 0) return gen_0; if (k == 0) return gen_1; return gcopy(n); } av = avma; if (typ(n) == t_INT) { if (signe(n) > 0) { GEN z = subis(n,k); if (cmpis(z,k) < 0) { k = itos(z); avma = av; if (k <= 1) { if (k < 0) return gen_0; if (k == 0) return gen_1; return icopy(n); } } } /* k > 1 */ if (lgefint(n) == 3 && signe(n) > 0) { y = binomialuu(itou(n),(ulong)k); return gerepileupto(av, y); } else { y = cgetg(k+1,t_VEC); for (i=1; i<=k; i++) gel(y,i) = subis(n,i-1); y = divide_conquer_prod(y,mulii); } y = diviiexact(y, mpfact(k)); return gerepileuptoint(av, y); } prec = precision(n); if (prec && k > 200 + 0.8*prec2nbits(prec)) { GEN A = mpfactr(k, prec), B = ggamma(gsubgs(n,k-1), prec); return gerepileupto(av, gdiv(ggamma(gaddgs(n,1), prec), gmul(A,B))); } y = cgetg(k+1,t_VEC); for (i=1; i<=k; i++) gel(y,i) = gsubgs(n,i-1); y = divide_conquer_prod(y,gmul); y = gdiv(y, mpfact(k)); return gerepileupto(av, y); } /* Assume n >= 0, return bin, bin[k+1] = binomial(n, k) */ GEN vecbinome(long n) { long d, k; GEN C; if (!n) return mkvec(gen_1); C = cgetg(n+2, t_VEC) + 1; /* C[k] = binomial(n, k) */ gel(C,0) = gen_1; gel(C,1) = utoipos(n); d = (n + 1) >> 1; for (k=2; k <= d; k++) { pari_sp av = avma; gel(C,k) = gerepileuptoint(av, diviuexact(mului(n-k+1, gel(C,k-1)), k)); } for ( ; k <= n; k++) gel(C,k) = gel(C,n-k); return C - 1; } /********************************************************************/ /** STIRLING NUMBERS **/ /********************************************************************/ /* Stirling number of the 2nd kind. The number of ways of partitioning a set of n elements into m non-empty subsets. */ GEN stirling2(ulong n, ulong m) { pari_sp av = avma, lim = stack_lim(av, 2); GEN s, bmk; ulong k; if (n==0) return (m == 0)? gen_1: gen_0; if (m > n || m == 0) return gen_0; if (m==n) return gen_1; /* k = 0 */ bmk = gen_1; s = powuu(m, n); for (k = 1; k <= ((m-1)>>1); ++k) { /* bmk = binomial(m, k) */ GEN c, kn, mkn; bmk = diviuexact(mului(m-k+1, bmk), k); kn = powuu(k, n); mkn = powuu(m-k, n); 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(DEBUGMEM>1) pari_warn(warnmem,"stirling2"); gerepileall(av, 2, &s, &bmk); } } /* k = m/2 */ if (!odd(m)) { GEN c; bmk = diviuexact(mului(k+1, bmk), k); c = mulii(bmk, powuu(k,n)); s = odd(k)? subii(s, c): addii(s, c); } return gerepileuptoint(av, diviiexact(s, mpfact(m))); } /* Stirling number of the first kind. Up to the sign, the number of permutations of n symbols which have exactly m cycles. */ GEN stirling1(ulong n, ulong m) { pari_sp ltop=avma; ulong k; GEN s, t; if (n < m) return gen_0; else if (n==m) return gen_1; /* t = binomial(n-1+k, m-1) * binomial(2n-m, n-m-k) */ /* k = n-m > 0 */ t = binomialuu(2*n-m-1, m-1); s = mulii(t, stirling2(2*(n-m), n-m)); if (odd(n-m)) togglesign(s); for (k = n-m-1; k > 0; --k) { GEN c; t = diviuuexact(muluui(n-m+k+1, n+k+1, t), n+k, n-m-k); c = mulii(t, stirling2(n-m+k, k)); s = odd(k)? subii(s, c): addii(s, c); if ((k & 0x1f) == 0) { t = gerepileuptoint(ltop, t); s = gerepileuptoint(avma, s); } } return gerepileuptoint(ltop, s); } GEN stirling(long n, long m, long flag) { if (n < 0) pari_err_DOMAIN("stirling", "n", "<", gen_0, stoi(n)); if (m < 0) pari_err_DOMAIN("stirling", "m", "<", gen_0, stoi(m)); switch (flag) { case 1: return stirling1((ulong)n,(ulong)m); case 2: return stirling2((ulong)n,(ulong)m); default: pari_err_FLAG("stirling"); } return NULL; /*NOT REACHED*/ } /***********************************************************************/ /** PERMUTATIONS **/ /***********************************************************************/ GEN numtoperm(long n, GEN x) { pari_sp av, lim; 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); 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))) x = gerepileuptoint(av, x); } avma = av; for (i=1; i<=(ulong)n; i++) gel(v,i) = utoipos(v[i]); return v; } GEN permtonum(GEN p) { long n = lg(p)-1, i, r; pari_sp av = avma, av2, lim; GEN v, x; if (!is_vec_t(typ(p))) pari_err_TYPE("permtonum",p); v = cgetg(n+1,t_VECSMALL); for (i=1; i<=n; i++) { GEN pi = gel(p, i); if (typ(pi) != t_INT) pari_err_TYPE("permtonum",pi); v[i] = itos(pi); } x = gen_0; av2 = avma; lim = stack_lim(av2,2); 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))) x = gerepileuptoint(av2, x); } return gerepileuptoint(av, x); } /*******************************************************************/ /** **/ /** RECIPROCAL POLYNOMIAL **/ /** **/ /*******************************************************************/ /* return coefficients s.t x = x_0 X^n + ... + x_n */ GEN polrecip(GEN x) { if (typ(x) != t_POL) pari_err_TYPE("polrecip",x); return RgX_recip(x); } /********************************************************************/ /** **/ /** POLYNOMIAL INTERPOLATION **/ /** **/ /********************************************************************/ /* allow X = NULL for [1,...,n] */ GEN RgV_polint(GEN X, GEN Y, long v) { pari_sp av0 = avma, av, lim; GEN Q, P = NULL; long i, l = lg(Y); if (!X) { X = cgetg(l, t_VEC); for (i=1; i1) pari_warn(warnmem,"FpV_polint"); P = gerepileupto(av, P); } } if (!P) { avma = av; return zeropol(v); } return gerepileupto(av0, P); } /* X,Y are "spec" GEN vectors with n > 1 components ( at X[0], ... X[n-1] ) */ GEN polint_i(GEN X, GEN Y, GEN x, long n, GEN *ptdy) { long i, m, ns = 0; pari_sp av = avma; GEN y, c, d, dy = NULL; /* gcc -Wall */ if (!X) { X = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) gel(X,i) = utoipos(i); X++; } switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: { GEN D = NULL; for (i=0; ib? 1: (a= lx) pari_err_TYPE("lexicographic vecsort, index too large", stoi(c)); s = lexcmp(gel(x,c), gel(y,c)); if (s) return s; } return 0; } /* return permutation sorting v[1..n], removing duplicates. Assume n > 0 */ static GEN gen_sortspec_uniq(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN)) { pari_sp av; long NX, nx, ny, m, ix, iy, i; GEN x, y, w, W; int s; switch(n) { case 1: return mkvecsmall(1); case 2: s = cmp(E,gel(v,1),gel(v,2)); if (s < 0) return mkvecsmall2(1,2); else if (s > 0) return mkvecsmall2(2,1); return mkvecsmall(1); case 3: s = cmp(E,gel(v,1),gel(v,2)); if (s < 0) { s = cmp(E,gel(v,2),gel(v,3)); if (s < 0) return mkvecsmall3(1,2,3); else if (s == 0) return mkvecsmall2(1,2); s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall3(1,3,2); else if (s > 0) return mkvecsmall3(3,1,2); return mkvecsmall2(1,2); } else if (s > 0) { s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall3(2,1,3); else if (s == 0) return mkvecsmall2(2,1); s = cmp(E,gel(v,2),gel(v,3)); if (s < 0) return mkvecsmall3(2,3,1); else if (s > 0) return mkvecsmall3(3,2,1); return mkvecsmall2(2,1); } else { s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall2(1,3); else if (s == 0) return mkvecsmall(1); return mkvecsmall2(3,1); } } NX = nx = n>>1; ny = n-nx; av = avma; x = gen_sortspec_uniq(v, nx,E,cmp); nx = lg(x)-1; y = gen_sortspec_uniq(v+NX,ny,E,cmp); ny = lg(y)-1; w = cgetg(n+1, t_VECSMALL); m = ix = iy = 1; while (ix<=nx && iy<=ny) { s = cmp(E, gel(v,x[ix]), gel(v,y[iy]+NX)); if (s < 0) w[m++] = x[ix++]; else if (s > 0) w[m++] = y[iy++]+NX; else { w[m++] = x[ix++]; iy++; } } while (ix<=nx) w[m++] = x[ix++]; while (iy<=ny) w[m++] = y[iy++]+NX; avma = av; W = cgetg(m, t_VECSMALL); for (i = 1; i < m; i++) W[i] = w[i]; return W; } /* return permutation sorting v[1..n]. Assume n > 0 */ static GEN gen_sortspec(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN)) { long nx, ny, m, ix, iy; GEN x, y, w; switch(n) { case 1: (void)cmp(E,gel(v,1),gel(v,1)); /* check for type error */ return mkvecsmall(1); case 2: return cmp(E,gel(v,1),gel(v,2)) <= 0? mkvecsmall2(1,2) : mkvecsmall2(2,1); case 3: if (cmp(E,gel(v,1),gel(v,2)) <= 0) { if (cmp(E,gel(v,2),gel(v,3)) <= 0) return mkvecsmall3(1,2,3); return (cmp(E,gel(v,1),gel(v,3)) <= 0)? mkvecsmall3(1,3,2) : mkvecsmall3(3,1,2); } else { if (cmp(E,gel(v,1),gel(v,3)) <= 0) return mkvecsmall3(2,1,3); return (cmp(E,gel(v,2),gel(v,3)) <= 0)? mkvecsmall3(2,3,1) : mkvecsmall3(3,2,1); } } nx = n>>1; ny = n-nx; w = cgetg(n+1,t_VECSMALL); x = gen_sortspec(v, nx,E,cmp); y = gen_sortspec(v+nx,ny,E,cmp); m = ix = iy = 1; while (ix<=nx && iy<=ny) if (cmp(E, gel(v,x[ix]), gel(v,y[iy]+nx))<=0) w[m++] = x[ix++]; else w[m++] = y[iy++]+nx; while (ix<=nx) w[m++] = x[ix++]; while (iy<=ny) w[m++] = y[iy++]+nx; avma = (pari_sp)w; return w; } static void init_sort(GEN *x, long *tx, long *lx) { *tx = typ(*x); if (*tx == t_LIST) { *x = list_data(*x); *lx = *x? lg(*x): 1; } else { if (!is_matvec_t(*tx) && *tx != t_VECSMALL) pari_err_TYPE("gen_sort",*x); *lx = lg(*x); } } /* (x o y)[1..lx-1], destroy y */ INLINE GEN sort_extract(GEN x, GEN y, long tx, long lx) { long i; switch(tx) { case t_VECSMALL: for (i=1; i (cmp_REV|cmp_LEX|cmp_IND|cmp_UNIQ)) pari_err_FLAG("vecsort"); if (flag & cmp_UNIQ) x = flag & cmp_IND? gen_indexsort_uniq(x, E, CMP): gen_sort_uniq(x, E, CMP); else x = flag & cmp_IND? gen_indexsort(x, E, CMP): gen_sort(x, E, CMP); if (flag & cmp_REV) { /* reverse order */ long j, lx; GEN y; if (typ(x)==t_LIST) { y = list_data(x); if (!y) return x; } else y = x; lx = lg(y); for (j=1; j<=(lx-1)>>1; j++) swap(gel(y,j), gel(y,lx-j)); } return x; } GEN indexsort(GEN x) { return gen_indexsort(x, (void*)&gcmp, cmp_nodata); } GEN indexlexsort(GEN x) { return gen_indexsort(x, (void*)&lexcmp, cmp_nodata); } GEN indexvecsort(GEN x, GEN k) { if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k); return gen_indexsort(x, (void*)k, &veccmp); } GEN sort(GEN x) { return gen_sort(x, (void*)gcmp, cmp_nodata); } GEN lexsort(GEN x) { return gen_sort(x, (void*)lexcmp, cmp_nodata); } GEN vecsort(GEN x, GEN k) { if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k); return gen_sort(x, (void*)k, &veccmp); } long vecsearch(GEN v, GEN x, GEN k) { pari_sp av = avma; void *E; int (*CMP)(void*,GEN,GEN) = sort_function(&E, x, k); long r; if (!is_matvec_t(typ(v))) pari_err_TYPE("vecsearch", v); r = gen_search(v, x, 0, E, CMP); avma = av; return r; } GEN ZV_indexsort(GEN L) { return gen_indexsort(L, (void*)&cmpii, &cmp_nodata); } GEN ZV_sort(GEN L) { return gen_sort(L, (void*)&cmpii, &cmp_nodata); } GEN ZV_sort_uniq(GEN L) { return gen_sort_uniq(L, (void*)&cmpii, &cmp_nodata); } /********************************************************************/ /** SEARCH IN SORTED VECTOR **/ /********************************************************************/ /* index of x in table T, 0 otherwise */ long tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN)) { long l = 1, u = lg(T)-1, i, s; while (u>=l) { i = (l+u)>>1; s = cmp(x, gel(T,i)); if (!s) return i; if (s<0) u=i-1; else l=i+1; } return 0; } /* looks if x belongs to the set T and returns the index if yes, 0 if no */ long gen_search(GEN T, GEN x, long flag, void *data, int (*cmp)(void*,GEN,GEN)) { long lx = lg(T), i, l, u, s; if (lx==1) return flag? 1: 0; l = 1; u = lx-1; do { i = (l+u)>>1; s = cmp(data, x, gel(T,i)); if (!s) return flag? 0: i; if (s<0) u=i-1; else l=i+1; } while (u>=l); if (!flag) return 0; return (s<0)? i: i+1; } long ZV_search(GEN x, GEN y) { return tablesearch(x, y, cmpii); } long zv_search(GEN x, long y) { return tablesearch(x, (GEN)y, cmp_small); } /********************************************************************/ /** COMPARISON FUNCTIONS **/ /********************************************************************/ int cmp_nodata(void *data, GEN x, GEN y) { int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data; return cmp(x,y); } /* assume x and y come from the same idealprimedec call (uniformizer unique) */ int cmp_prime_over_p(GEN x, GEN y) { long k = pr_get_f(x) - pr_get_f(y); /* diff. between residue degree */ return k? ((k > 0)? 1: -1) : ZV_cmp(pr_get_gen(x), pr_get_gen(y)); } int cmp_prime_ideal(GEN x, GEN y) { int k = cmpii(pr_get_p(x), pr_get_p(y)); return k? k: cmp_prime_over_p(x,y); } /* assume x and y are t_POL in the same variable whose coeffs can be * compared (used to sort polynomial factorizations) */ int gen_cmp_RgX(void *data, GEN x, GEN y) { int (*coeff_cmp)(GEN,GEN)=(int(*)(GEN,GEN))data; long i, lx = lg(x), ly = lg(y); int fl; if (lx > ly) return 1; if (lx < ly) return -1; for (i=lx-1; i>1; i--) if ((fl = coeff_cmp(gel(x,i), gel(y,i)))) return fl; return 0; } static int cmp_RgX_Rg(GEN x, GEN y) { long lx = lg(x); if (lx > 3) return 1; if (lx < 3) return -1; return gcmp(gel(x,2), y); } int cmp_RgX(GEN x, GEN y) { if (typ(x) == t_POLMOD) x = gel(x,2); if (typ(y) == t_POLMOD) y = gel(y,2); if (typ(x) == t_POL) { if (typ(y) != t_POL) return cmp_RgX_Rg(x, y); } else { if (typ(y) != t_POL) return gcmp(x,y); return - cmp_RgX_Rg(y,x); } return gen_cmp_RgX((void*)&gcmp,x,y); } /********************************************************************/ /** MERGE & SORT FACTORIZATIONS **/ /********************************************************************/ /* merge fx, fy two factorizations, whose 1st column is sorted in strictly * increasing order wrt cmp. Keep 0 exponents. */ GEN merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN)) { GEN x = gel(fx,1), e = gel(fx,2), M, E; GEN y = gel(fy,1), f = gel(fy,2); long ix, iy, m, lx = lg(x), ly = lg(y), l = lx+ly-1; M = cgetg(l, t_COL); E = cgetg(l, t_COL); m = ix = iy = 1; while (ix 0) z[k++] = y[j++]; else { z[k++] = x[i++]; j++; } } while (i 0) z[k++] = y[j++]; else { z[k++] = x[i++]; j++; } } while (i 0) iy++; else { gel(z, iz++) = gel(x,ix); ix++; iy++; } } setlg(z,iz); return gerepilecopy(av,z); } GEN gen_setminus(GEN A, GEN B, int (*cmp)(GEN,GEN)) { pari_sp ltop = avma; long i = 1, j = 1, k = 1, lx = lg(A), ly = lg(B); GEN diff = cgetg(lx,t_VEC); while (i < lx && j < ly) switch ( cmp(gel(A,i),gel(B,j)) ) { case -1: gel(diff,k++) = gel(A,i++); break; case 1: j++; break; case 0: i++; break; } while (i < lx) gel(diff,k++) = gel(A,i++); setlg(diff,k); return gerepilecopy(ltop,diff); } GEN setminus(GEN x, GEN y) { if (typ(x) != t_VEC) pari_err_TYPE("setminus",x); if (typ(y) != t_VEC) pari_err_TYPE("setminus",y); return gen_setminus(x,y,cmp_universal); } GEN 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) pari_err_TYPE("setbinop [function needs exactly 2 arguments]",f); lx = lg(x); if (typ(x) != t_VEC) pari_err_TYPE("setbinop", x); if (y == NULL) { /* assume x = y and f symmetric */ z = cgetg((((lx-1)*lx) >> 1) + 1, t_VEC); for (i = 1; i < lx; i++) for (j = i; j < lx; j++) gel(z, k++) = closure_callgen2(f, gel(x,i),gel(x,j)); } else { ly = lg(y); if (typ(y) != t_VEC) pari_err_TYPE("setbinop", y); z = cgetg((lx-1)*(ly-1) + 1, t_VEC); for (i = 1; i < lx; i++) for (j = 1; j < ly; j++) gel(z, k++) = closure_callgen2(f, gel(x,i),gel(y,j)); } return gerepileupto(av, gtoset(z)); } pari-2.7.5/src/basemath/buch2.c0000644000175000017500000034106212610175757014651 0ustar billbill/* 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" /*******************************************************************/ /* */ /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */ /* GENERAL NUMBER FIELDS */ /* */ /*******************************************************************/ /* get_random_ideal */ static const long RANDOM_BITS = 4; /* Buchall */ static const double BNF_C1 = 0.0, BNF_C2 = 0.0; static const long RELSUP = 5; static const long FAIL_DIVISOR = 32; static const long MINFAIL = 10; /* small_norm */ static const long BNF_RELPID = 4; static const long BMULT = 8; static const long maxtry_ELEMENT = 1000*1000; static const long maxtry_DEP = 20; static const long maxtry_FACT = 500; /* rnd_rel */ static const long RND_REL_RELPID = 1; static const long PREVENT_LLL_IN_RND_REL = 1; /* random relations */ static const long MINSFB = 3; static const long SFB_MAX = 3; static const long DEPSIZESFBMULT = 16; static const long DEPSFBDIV = 10; /* add_rel_i */ static const ulong mod_p = 27449UL; /* be_honest */ static const long maxtry_HONEST = 50; typedef struct FACT { long pr, ex; } FACT; typedef struct subFB_t { GEN subFB; struct subFB_t *old; } subFB_t; /* a factor base contains only non-inert primes * KC = # of P in factor base (p <= n, NP <= n2) * KC2= # of P assumed to generate class group (NP <= n2) * * KCZ = # of rational primes under ideals counted by KC * KCZ2= same for KC2 */ typedef struct FB_t { GEN FB; /* FB[i] = i-th rational prime used in factor base */ GEN LP; /* vector of all prime ideals in FB */ GEN *LV; /* LV[p] = vector of P|p, NP <= n2 * isclone() is set for LV[p] iff all P|p are in FB * LV[i], i not prime or i > n2, is undefined! */ GEN iLP; /* iLP[p] = i such that LV[p] = [LP[i],...] */ GEN id2; /* id2[i] = powers of ideal i */ GEN L_jid; /* indexes of "useful" prime ideals for rnd_rel */ long KC, KCZ, KCZ2; 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 */ } FB_t; enum { sfb_CHANGE = 1, sfb_INCREASE = 2 }; typedef struct REL_t { GEN R; /* relation vector as t_VECSMALL; clone */ long nz; /* index of first non-zero elt in R (hash) */ GEN m; /* pseudo-minimum yielding the relation; clone */ long relorig; /* relation this one is an image of */ long relaut; /* automorphim used to compute this relation from the original */ GEN junk[3]; /*make sure sizeof(struct) is a power of two.*/ } REL_t; typedef struct RELCACHE_t { REL_t *chk; /* last checkpoint */ REL_t *base; /* first rel found */ REL_t *last; /* last rel found so far */ REL_t *end; /* target for last relation. base <= last <= end */ size_t len; /* number of rels pre-allocated in base */ long relsup; /* how many linearly dependent relations to we allow */ GEN basis; /* mod p basis (generating family actually) */ ulong missing; /* missing vectors in generating family above */ } RELCACHE_t; typedef struct FP_t { double **q; GEN x; double *y; double *z; double *v; } FP_t; typedef struct RNDREL_t { GEN Nideal; long jid; GEN ex; GEN m1; } RNDREL_t; static void wr_rel(GEN col) { long i, l = lg(col); err_printf("\nrel = "); for (i=1; i 1) { err_printf("\n++++ cglob = %ld", cache->last - cache->base); wr_rel(cache->last->R); } else err_printf("%ld ", cache->last - cache->base); } static void dbg_cancelrel(long jid, long jdir, GEN col) { err_printf("relation cancelled: "); if (DEBUGLEVEL>3) err_printf("(jid=%ld,jdir=%ld)",jid,jdir); wr_rel(col); err_flush(); } static void delete_cache(RELCACHE_t *M) { REL_t *rel; for (rel = M->base+1; rel <= M->last; rel++) { gunclone(rel->R); if (!rel->m) continue; gunclone(rel->m); } pari_free((void*)M->base); M->base = NULL; } static void unclone_subFB(FB_t *F) { subFB_t *sub, *subold; GEN id2 = F->id2; long i; for (sub = F->allsubFB; sub; sub = subold) { GEN subFB = sub->subFB; for (i = 1; i < lg(subFB); i++) { long id = subFB[i]; if (gel(id2, id) == gen_0) continue; gunclone(gel(id2, id)); gel(id2, id) = gen_0; } subold = sub->old; pari_free(sub); } } static void delete_FB(FB_t *F) { unclone_subFB(F); gunclone(F->minidx); gunclone(F->idealperm); } static void reallocate(RELCACHE_t *M, long len) { REL_t *old = M->base; M->len = len; M->base = (REL_t*)pari_realloc((void*)old, (len+1) * sizeof(REL_t)); if (old) { size_t last = M->last - old, chk = M->chk - old, end = M->end - old; M->last = M->base + last; M->chk = M->base + chk; M->end = M->base + end; } } #define pr_get_smallp(pr) gel(pr,1)[2] /* don't take P|p all other Q|p are already there */ static int bad_subFB(FB_t *F, long t) { GEN LP, P = gel(F->LP,t); long p = pr_get_smallp(P); LP = F->LV[p]; return (isclone(LP) && t == F->iLP[p] + lg(LP)-1); } static void assign_subFB(FB_t *F, GEN yes, long iyes) { subFB_t *sub; long i, lv; /* single malloc for struct + GEN */ lv = sizeof(subFB_t) + iyes*sizeof(long); sub = (subFB_t *)pari_malloc(lv); sub->subFB = (GEN)&sub[1]; sub->old = F->allsubFB; F->allsubFB = sub; for (i = 0; i < iyes; i++) sub->subFB[i] = yes[i]; F->subFB = sub->subFB; F->newpow = 1; F->newarc = 1; } /* * Determine the permutation of the ideals made by each field automorphism. */ static void FB_aut_perm(FB_t *F, GEN nf, GEN auts, GEN cyclic) { pari_sp av0 = avma; long i, KC = F->KC, nauts = lg(auts); GEN minidx = zero_Flv(KC), perm = zero_Flm_copy(KC, nauts-1); 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); long k0 = thiscyc[1]; GEN aut = gel(auts, k0), permk0 = gel(perm, k0), ppermk; i = 1; while (i <= KC) { pari_sp av2 = avma; GEN seen = zero_Flv(KC), P = gel(F->LP, i); long imin = i, p, f, l; p = pr_get_p(P)[2]; f = pr_get_f(P); do { if (++i > KC) break; P = gel(F->LP, i); } while (p == pr_get_p(P)[2] && f == pr_get_f(P)); for (j = imin; j < i; j++) { GEN img = ZM_ZC_mul(aut, pr_get_gen(gel(F->LP, j))); for (l = imin; l < i; l++) if (!seen[l] && nfval(nf, img, gel(F->LP, l))) { seen[l] = 1; permk0[j] = l; break; } } avma = av2; } for (ppermk = permk0, i = 2; i < lg(thiscyc); i++) { GEN permk = gel(perm, thiscyc[i]); for (j = 1; j <= KC; j++) permk[j] = permk0[ppermk[j]]; ppermk = permk; } } 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; } } F->minidx = gclone(minidx); F->idealperm = gclone(perm); avma = av0; } /* set subFB. * Fill F->perm (if != NULL): primes ideals sorted by increasing norm (except * the ones in subFB come first [dense rows for hnfspec]) */ static int subFBgen(FB_t *F, GEN nf, GEN auts, GEN cyclic, double PROD, long minsFB) { GEN y, perm, yes, no; long i, j, k, iyes, ino, lv = F->KC + 1; double prod; pari_sp av; F->LP = cgetg(lv, t_VEC); F->L_jid = F->perm = cgetg(lv, t_VECSMALL); av = avma; y = cgetg(lv,t_COL); /* Norm P */ for (k=0, i=1; i <= F->KCZ; i++) { GEN LP = F->LV[F->FB[i]]; long l = lg(LP); for (j = 1; j < l; j++) { GEN P = gel(LP,j); k++; gel(y,k) = pr_norm(P); gel(F->LP,k) = P; } } /* perm sorts LP by increasing norm */ perm = indexsort(y); no = cgetg(lv, t_VECSMALL); ino = 1; yes = cgetg(lv, t_VECSMALL); iyes = 1; prod = 1.0; for (i = 1; i < lv; i++) { long t = perm[i]; if (bad_subFB(F, t)) { no[ino++] = t; continue; } yes[iyes++] = t; prod *= (double)itos(gel(y,t)); if (iyes > minsFB && prod > PROD) break; } setlg(yes, iyes); for (j=1; jperm[j] = yes[j]; for (i=1; iperm[j] = no[i]; for ( ; jperm[j] = perm[j]; F->allsubFB = NULL; FB_aut_perm(F, nf, auts, cyclic); if (iyes) assign_subFB(F, yes, iyes); avma = av; return 1; } static int subFB_change(FB_t *F) { long i, iyes, minsFB, lv = F->KC + 1, l = lg(F->subFB)-1; pari_sp av = avma; GEN yes, L_jid = F->L_jid, present = zero_zv(lv-1); switch (F->sfb_chg) { case sfb_INCREASE: minsFB = l + 1; break; default: minsFB = l; break; } yes = cgetg(minsFB+1, t_VECSMALL); iyes = 1; if (L_jid) { for (i = 1; i < lg(L_jid); i++) { long l = L_jid[i]; yes[iyes++] = l; present[l] = 1; if (iyes > minsFB) break; } } else i = 1; if (iyes <= minsFB) { for ( ; i < lv; i++) { long l = F->perm[i]; if (present[l]) continue; yes[iyes++] = l; if (iyes > minsFB) break; } if (i == lv) return 0; } if (zv_equal(F->subFB, yes)) { if (DEBUGLEVEL) err_printf("\n*** NOT Changing sub factor base\n"); } else { if (DEBUGLEVEL) err_printf("\n*** Changing sub factor base\n"); assign_subFB(F, yes, iyes); } F->sfb_chg = 0; avma = av; return 1; } static GEN init_famat(GEN x) { return mkvec2(x, cgetg(1,t_MAT)); } static GEN red(GEN nf, GEN I, GEN G0, GEN *pm) { GEN m, y, norm, norm2; norm = typ(I) == t_MAT ? ZM_det_triangular(I) : idealnorm(nf, I); y = idealred0(nf, init_famat(I), G0); m = gel(y,2); y = gel(y,1); *pm = lg(m)==1? gen_1: Q_primpart(gmael(m, 1, 1)); norm2 = typ(y) == t_MAT ? ZM_det_triangular(y) : idealnorm(nf, y); if (gcmp(norm, norm2) < 0 || is_pm1(gcoeff(y,1,1))) { *pm = gen_1; y = I; } return idealtwoelt(nf,y); } /* make sure enough room to store n more relations */ static void pre_allocate(RELCACHE_t *cache, size_t n) { size_t len = (cache->last - cache->base) + n; if (len >= cache->len) reallocate(cache, len << 1); } void init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD) { const double c1 = PI*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->maxprimes = 16000; /* sufficient for LIMC=176081*/ S->primes = (GRHprime_t*)pari_malloc(S->maxprimes*sizeof(*S->primes)); S->nprimes = 0; S->limp = 0; u_forprime_init(&S->P, 2, ULONG_MAX); } void free_GRHcheck(GRHcheck_t *S) { if (S->clone) { long i = S->nprimes; GRHprime_t *pr; for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--) gunclone(pr->dec); } pari_free(S->primes); } int GRHok(GRHcheck_t *S, double L, double SA, double SB) { return (S->cD + (S->cN + 2*SB) / L - 2*SA < -1e-8); } /* Return factorization pattern of p: [f,n], where n[i] primes of * residue degree f[i] */ static GEN get_fs(GEN nf, GEN P, GEN index, ulong p) { long j, k, f, n, l; GEN fs, ns; if (umodiu(index, p)) { /* easy case: p does not divide index */ GEN F = Flx_degfact(ZX_to_Flx(P,p), p); fs = gel(F,1); l = lg(fs); ns = gel(F,2); /*to be overwritten*/ } else { GEN F = idealprimedec(nf, utoipos(p)); l = lg(F); fs = cgetg(l, t_VECSMALL); for (j = 1; j < l; j++) fs[j] = pr_get_f(gel(F,j)); ns = cgetg(l, t_VECSMALL); } f = fs[1]; n = 1; for (j = 2, k = 1; j < l; j++) if (fs[j] == f) n++; else { ns[k] = n; fs[k] = f; k++; f = fs[j]; n = 1; } ns[k] = n; fs[k] = f; k++; setlg(fs, k); setlg(ns, k); return mkvec2(fs,ns); } /* cache data for all rational primes up to the LIM */ static void cache_prime_dec(GRHcheck_t *S, ulong LIM, GEN nf) { pari_sp av = avma; GRHprime_t *pr; GEN index, P; double nb; if (S->limp >= LIM) return; S->clone = 1; nb = primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */ GRH_ensure(S, nb+1); /* room for one extra prime */ P = nf_get_pol(nf); index = nf_get_index(nf); for (pr = S->primes + S->nprimes;;) { ulong p = u_forprime_next(&(S->P)); pr->p = p; pr->logp = log((double)p); pr->dec = gclone(get_fs(nf, P, index, p)); S->nprimes++; pr++; /* store up to nextprime(LIM) included */ if (p >= LIM) { S->limp = p; break; } } avma = av; } static GEN compute_invres(GRHcheck_t *S) { 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); for (; i > 0; pr++, i--) { GEN dec, a = NULL, b = NULL, fs, ns; long j, k, limp = llimc/pr->logp; ulong p = pr->p; dec = pr->dec; fs = gel(dec, 1); ns = gel(dec, 2); k = lg(fs); for (j = 1; j < k; j++) { long f, nb; GEN nor; f = fs[j]; if (f > limp) continue; nb = ns[j]; nor = powuu(p, f); if (a) { a = mulii(a, powiu(nor, nb)); b = mulii(b, powiu(subii(nor, gen_1), nb)); } else { a = powuu(p, f*nb-1); b = diviuexact(powiu(subii(nor, gen_1), nb), p-1); } } if (a) invres = divri(mulir(b, invres), a); else invres = divru(mulur(p, invres), p-1); } return gerepileuptoleaf(av, invres); } static long nthideal(GRHcheck_t *S, GEN nf, long n) { pari_sp av = avma; GEN P = nf_get_pol(nf); ulong p = 0, *vecN = (ulong*)const_vecsmall(n, LONG_MAX); long i, res, N = poldegree(P, -1); for (i = 0; ; i++) { GRHprime_t *pr; GEN fs; cache_prime_dec(S, p+1, nf); pr = S->primes + i; fs = gel(pr->dec, 1); p = pr->p; if (fs[1] != N) { GEN ns = gel(pr->dec, 2); long k, l, j = lg(fs); while (--j > 0) { ulong NP = upowuu(p, fs[j]); long nf; if (!NP) continue; for (k = 1; k <= n; k++) if (vecN[k] > NP) break; if (k > n) continue; /* vecN[k] <= NP */ nf = ns[j]; /*#{primes of norme NP} = nf, insert them here*/ for (l = k+nf; l <= n; l++) vecN[l] = vecN[l-nf]; for (l = 0; l < nf && k+l <= n; l++) vecN[k+l] = NP; while (l <= k) vecN[l++] = NP; } } if (p > vecN[n]) break; } res = vecN[n]; avma = av; return res; } /* Compute FB, LV, iLP + KC*. Reset perm * C2: bound for norm of tested prime ideals (includes be_honest()) * C1: bound for p, such that P|p (NP <= C2) used to build relations * Return prod_{p<=C2} (1-1/p) / prod_{Norm(P)<=C2} (1-1/Norm(P)), * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D) */ static void FBgen(FB_t *F, GEN nf, long N, ulong C1, ulong C2, GRHcheck_t *S) { GRHprime_t *pr; long i, ip; GEN prim; const double L = log((double)C2 + 0.5); cache_prime_dec(S, C2, nf); pr = S->primes; F->sfb_chg = 0; F->FB = cgetg(C2+1, t_VECSMALL); F->iLP = cgetg(C2+1, t_VECSMALL); F->LV = (GEN*)const_vec(C2, NULL); prim = icopy(gen_1); i = ip = 0; F->KC = F->KCZ = 0; for (;; pr++) /* p <= C2 */ { ulong p = pr->p; pari_sp av = avma; long k, l, m; GEN LP, nb, f; if (!F->KC && p > C1) { F->KCZ = i; F->KC = ip; } if (p > C2) break; if (DEBUGLEVEL>1) { err_printf(" %ld",p); err_flush(); } f = gel(pr->dec, 1); nb = gel(pr->dec, 2); if (f[1] == N) continue; /* p inert */ /* 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++) { GEN t = gel(LP,m); gel(t,5) = zk_scalar_or_multable(nf, gel(t,5)); } if (m == lg(LP)) setisclone(LP); /* flag it: all prime divisors in FB */ else { setlg(LP,k+1); LP = gerepilecopy(av,LP); } 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; } } /* Note F->KC > 0 otherwise GRHchk is false */ setlg(F->FB, F->KCZ+1); F->KCZ2 = i; if (DEBUGLEVEL>1) { err_printf("\n"); if (DEBUGLEVEL>6) { err_printf("########## FACTORBASE ##########\n\n"); err_printf("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld\n", ip, F->KC, F->KCZ, F->KCZ2); for (i=1; i<=F->KCZ; i++) err_printf("++ LV[%ld] = %Ps",i,F->LV[F->FB[i]]); } } F->perm = NULL; F->L_jid = NULL; } static int GRHchk(GEN nf, GRHcheck_t *S, ulong LIMC) { double logC = log((ulong)LIMC), SA = 0, SB = 0; GRHprime_t *pr = S->primes; cache_prime_dec(S, LIMC, nf); for (pr = S->primes;; pr++) { ulong p = pr->p; GEN dec, fs, ns; double logCslogp; long j; if (p > LIMC) break; dec = pr->dec; fs = gel(dec, 1); ns = gel(dec,2); logCslogp = logC/pr->logp; for (j = 1; j < lg(fs); j++) { long f = fs[j], M, nb; double logNP, q, A, B; if (f > logCslogp) break; logNP = f * pr->logp; q = 1/sqrt(upowuu(p, f)); A = logNP * q; B = logNP * A; M = (long)(logCslogp/f); if (M > 1) { double inv1_q = 1 / (1-q); A *= (1 - pow(q, M)) * inv1_q; B *= (1 - pow(q, M)*(M+1 - M*q)) * inv1_q * inv1_q; } nb = ns[j]; SA += nb * A; SB += nb * B; } if (p == LIMC) break; } return GRHok(S, logC, SA, SB); } /* SMOOTH IDEALS */ static void store(long i, long e, FACT *fact) { ++fact[0].pr; fact[fact[0].pr].pr = i; /* index */ fact[fact[0].pr].ex = e; /* exponent */ } /* divide out x by all P|p, where x as in can_factor(). k = v_p(Nx) */ static int divide_p_elt(GEN LP, long ip, long k, GEN nf, GEN m, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } static int divide_p_id(GEN LP, long ip, long k, GEN nf, GEN I, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } static int divide_p_quo(GEN LP, long ip, long k, GEN nf, GEN I, GEN m, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } /* |*N| != 0 is the norm of a primitive ideal, in particular not divisible by * any inert prime. Is |*N| a smooth rational integer wrt F ? (put the * exponents in *ex) */ static int 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 */ 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; if (i == KCZ) return 0; } (*ex)[0] = i; return (cmpiu(*N,limp) <= 0); } static int 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); } /* Let x = m if I == NULL, * I if m == NULL, * m/I otherwise. * Can we factor the integral primitive ideal x ? |N| = Norm x > 0 */ static long can_factor(FB_t *F, GEN nf, GEN I, GEN m, GEN N, FACT *fact) { GEN ex; long i, res = 0; fact[0].pr = 0; if (is_pm1(N)) return 1; if (!smooth_norm(F, &N, &ex)) goto END; for (i=1; i<=ex[0]; i++) if (ex[i] && !divide_p(F, F->FB[i], ex[i], nf, I, m, fact)) goto END; res = is_pm1(N) || divide_p(F, itou(N), 1, nf, I, m, fact); END: if (!res && DEBUGLEVEL > 1) { err_printf("."); err_flush(); } return res; } /* can we factor m/I ? [m in I from idealpseudomin_nonscalar], NI = norm I */ static long factorgen(FB_t *F, GEN nf, GEN I, GEN NI, GEN m, FACT *fact) { long e, r1 = nf_get_r1(nf); GEN M = nf_get_M(nf); GEN N = divri(embed_norm(RgM_RgC_mul(M,m), r1), NI); /* ~ N(m/I) */ N = grndtoi(N, &e); if (e > -1) { if (DEBUGLEVEL > 1) { err_printf("+"); err_flush(); } return 0; } return can_factor(F, nf, I, m, N, fact); } /* FUNDAMENTAL UNITS */ /* a, m real. Return (Re(x) + a) + I * (Im(x) % m) */ static GEN addRe_modIm(GEN x, GEN a, GEN m) { GEN re, im, z; if (typ(x) == t_COMPLEX) { im = modr_safe(gel(x,2), m); if (!im) return NULL; re = gadd(gel(x,1), a); z = gequal0(im)? re: mkcomplex(re, im); } else z = gadd(x, a); return z; } /* clean archimedean components */ static GEN cleanarch(GEN x, long N, long prec) { long i, R1, RU, tx = typ(x); GEN s, y, pi2; if (tx == t_MAT) { y = cgetg(lg(x), tx); for (i=1; i < lg(x); i++) { gel(y,i) = cleanarch(gel(x,i), N, prec); if (!gel(y,i)) return NULL; } return y; } if (!is_vec_t(tx)) pari_err_TYPE("cleanarch",x); RU = lg(x)-1; R1 = (RU<<1)-N; s = gdivgs(RgV_sum(real_i(x)), -N); /* -log |norm(x)| / N */ y = cgetg(RU+1,tx); pi2 = Pi2n(1, prec); for (i=1; i<=R1; i++) { gel(y,i) = addRe_modIm(gel(x,i), s, pi2); if (!gel(y,i)) return NULL; } if (i <= RU) { GEN pi4 = Pi2n(2, prec), s2 = gmul2n(s, 1); for ( ; i<=RU; i++) { gel(y,i) = addRe_modIm(gel(x,i), s2, pi4); if (!gel(y,i)) return NULL; } } return y; } static GEN not_given(long reason) { if (DEBUGLEVEL) switch(reason) { case fupb_LARGE: pari_warn(warner,"fundamental units too large, not given"); break; case fupb_PRECI: pari_warn(warner,"insufficient precision for fundamental units, not given"); break; } return cgetg(1,t_MAT); } /* check whether exp(x) will 1) get too big (real(x) large), 2) require * large accuracy for argument reduction (imag(x) large) */ static int exp_OK(GEN x, long *pte) { long i,I,j,J, e = - (long)HIGHEXPOBIT; RgM_dimensions(x, &I,&J); for (j=1; j<=J; j++) for (i=1; i<=I; i++) { GEN c = gcoeff(x,i,j), re; if (typ(c)!=t_COMPLEX) re = c; else { GEN im = gel(c,2); e = maxss(e, expo(im) + 5 - bit_prec(im)); re = gel(c,1); } if (expo(re) > 20) { *pte = LONG_MAX; return 0; } } *pte = -e; return (e < 0); } static GEN getfu(GEN nf, GEN *ptA, long *pte, long prec) { GEN p1, p2, u, y, matep, A, vec, T = nf_get_pol(nf), M = nf_get_M(nf); long e, i, j, R1, RU, N = degpol(T); if (DEBUGLEVEL) err_printf("\n#### Computing fundamental units\n"); R1 = nf_get_r1(nf); RU = (N+R1)>>1; if (RU==1) { *pte=LONG_MAX; return cgetg(1,t_VEC); } *pte = 0; A = *ptA; matep = cgetg(RU,t_MAT); for (j=1; j= 0) return not_given(fupb_PRECI); for (j=1; j 0 */ y = coltoliftalg(nf, y); vec = cgetg(RU+1,t_COL); p1 = PiI2n(0,prec); for (i=1; i<=R1; i++) gel(vec,i) = p1; p2 = PiI2n(1,prec); for ( ; i<=RU; i++) gel(vec,i) = p2; for (j=1; j pmax) pmax = p; } L = const_vec(pmax, NULL); if (list_pr) { for (i=1; iKCZ = i; F->KC = ip; F->FB = FB; setlg(FB, i+1); F->LV = (GEN*)LV; F->iLP= iLP; return L; } /* add v^e to factorization */ static void add_to_fact(long v, long e, FACT *fact) { long i, l = fact[0].pr; for (i=1; i<=l && fact[i].pr < v; i++)/*empty*/; if (i <= l && fact[i].pr == v) fact[i].ex += e; else store(v, e, fact); } /* L (small) list of primes above the same p including pr. Return pr index */ static int pr_index(GEN L, GEN pr) { long j, l = lg(L); GEN al = pr_get_gen(pr); for (j=1; jiLP[p] + pr_index(F->LV[p], pr); } /* return famat y (principal ideal) such that y / x is smooth [wrt Vbase] */ static GEN SPLIT(FB_t *F, GEN nf, GEN x, GEN Vbase, FACT *fact) { GEN vecG, z, ex, y, x0, Nx = ZM_det_triangular(x); long nbtest_lim, nbtest, i, j, ru, lgsub; pari_sp av; if (nf_get_degree(nf) != lg(x)-1) pari_err_TYPE("idealtyp [dimension != degree]", x); /* try without reduction if x is small */ if (gexpo(gcoeff(x,1,1)) < 100 && can_factor(F, nf, x, NULL, Nx, fact)) return NULL; av = avma; y = idealpseudomin_nonscalar(x, nf_get_roundG(nf)); if (factorgen(F, nf, x, Nx, y, fact)) return y; avma = av; /* reduce in various directions */ ru = lg(nf_get_roots(nf)); vecG = cgetg(ru, t_VEC); for (j=1; j2) err_printf("# ideals tried = %ld\n",nbtest); for (i=1; i nbtest_lim) { nbtest = 0; if (++lgsub < 7) { nbtest_lim <<= 1; ex = cgetg(lgsub, t_VECSMALL); } else nbtest_lim = LONG_MAX; /* don't increase further */ if (DEBUGLEVEL>2) err_printf("SPLIT: increasing factor base [%ld]\n",lgsub); } } } /* return principal y such that y / x is smooth. Store factorization of latter*/ static GEN split_ideal(GEN nf, FB_t *F, GEN x, GEN Vbase, GEN L, FACT *fact) { GEN y = SPLIT(F, nf, x, Vbase, fact); long p,j, i, l = lg(F->FB); p = j = 0; /* -Wall */ for (i=1; i<=fact[0].pr; i++) { /* decode index C = ip+j --> (p,j) */ long q,k,t, C = fact[i].pr; for (t=1; tFB[t]; k = C - F->iLP[q]; if (k <= 0) break; p = q; j = k; } fact[i].pr = gel(L, p)[j]; } return y; } /* return sorted vectbase [sorted in bnf since version 2.2.4] */ static GEN get_Vbase(GEN bnf) { GEN vectbase = gel(bnf,5), perm = gel(bnf,6), Vbase; long i, l, tx = typ(perm); if (tx == t_INT) return vectbase; /* old format */ l = lg(vectbase); Vbase = cgetg(l,t_VEC); for (i=1; i1) err_printf("**** Testing Different = %Ps\n",D); L = bnfisprincipal0(bnf, D, nf_FORCE); if (DEBUGLEVEL>1) err_printf(" is %Ps\n", L); } /* sort factorbase for tablesearch */ fb = gen_sort(gel(bnf,5), (void*)&cmp_prime_ideal, cmp_nodata); pmax = itou( pr_get_p(gel(fb, lg(fb)-1)) ); /* largest p in factorbase */ Vbase = get_Vbase(bnf); (void)recover_partFB(&F, Vbase, nf_get_degree(nf)); fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT)); forprime_init(&S, gen_2, BOUND); av = avma; while (( p = forprime_next(&S) )) { GEN vP; long i, l; if (DEBUGLEVEL == 1 && ++count > 1000) { err_printf("passing p = %Ps / %Ps\n", p, BOUND); count = 0; } avma = av; vP = idealprimedec(bnf, p); l = lg(vP); 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; i1) 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) err_printf(" is %Ps\n", isprincipal(bnf,P)); else /* faster: don't compute result */ (void)SPLIT(&F, nf, idealhnf_two(nf,P), Vbase, fact); } } avma = av0; } /**** logarithmic embeddings ****/ static GEN famat_to_arch(GEN nf, GEN fa, long prec); static GEN triv_arch(GEN nf) { return zerovec(lg(nf_get_roots(nf))-1); } /* Get archimedean components: [e_i Log( sigma_i(X) )], where X = primpart(x), * and e_i = 1 (resp 2.) for i <= R1 (resp. > R1) */ static GEN get_arch(GEN nf, GEN x, long prec) { long i, l, R1; GEN v; if (typ(x) == t_MAT) return famat_to_arch(nf,x,prec); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return triv_arch(nf); x = RgM_RgC_mul(nf_get_M(nf), Q_primpart(x)); l = lg(x); for (i=1; i < l; i++) if (gequal0(gabs(gel(x,i),prec))) return NULL; v = cgetg(l,t_VEC); R1 = nf_get_r1(nf); for (i=1; i<=R1; i++) gel(v,i) = glog(gel(x,i),prec); for ( ; i < l; i++) gel(v,i) = gmul2n(glog(gel(x,i),prec),1); return v; } static GEN famat_to_arch(GEN nf, GEN fa, long prec) { GEN g,e, y = NULL; long i,l; if (typ(fa) != t_MAT) pari_err_TYPE("famat_to_arch",fa); if (lg(fa) == 1) return triv_arch(nf); g = gel(fa,1); e = gel(fa,2); l = lg(e); for (i=1; i= l */ a = cgetg(l, t_VEC); for (i=1; i e) e = f; } return e; } /* col = archimedian components of x, Nx = kNx^e its norm (e > 0, usually = 1), * dx a bound for its denominator. Return x or NULL (fail) */ GEN isprincipalarch(GEN bnf, GEN col, GEN kNx, GEN e, GEN dx, long *pe) { GEN nf, x, y, logfu, s, M; long N, R1, RU, i, prec = gprecision(col); bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); M = nf_get_M(nf); if (!prec) prec = prec_arch(bnf); logfu = bnf_get_logfu(bnf); N = nf_get_degree(nf); R1 = nf_get_r1(nf); RU = (N + R1)>>1; col = cleanarch(col,N,prec); settyp(col, t_COL); if (!col) pari_err_PREC( "isprincipalarch"); if (RU > 1) { /* reduce mod units */ GEN u, z = init_red_mod_units(bnf,prec); u = red_mod_units(col,z); if (!u && z) return NULL; if (u) col = RgC_add(col, RgM_RgC_mul(logfu, u)); } s = divru(mulir(e, glog(kNx,prec)), N); for (i=1; i<=R1; i++) gel(col,i) = gexp(gadd(s, gel(col,i)),prec); for ( ; i<=RU; i++) gel(col,i) = gexp(gadd(s, gmul2n(gel(col,i),-1)),prec); /* d.alpha such that x = alpha \prod gj^ej */ x = RgM_solve_realimag(M,col); if (!x) return NULL; x = RgC_Rg_mul(x, dx); y = grndtoi(x, pe); if (*pe > -5) { *pe = needed_bitprec(x); return NULL; } return RgC_Rg_div(y, dx); } /* y = C \prod g[i]^e[i] ? */ static int fact_ok(GEN nf, GEN y, GEN C, GEN g, GEN e) { pari_sp av = avma; long i, c = lg(e); GEN z = C? C: gen_1; for (i=1; i=0 for all i. C may be NULL (omitted) * e destroyed ! */ static GEN expand(GEN nf, GEN C, GEN P, GEN e) { long i, l = lg(e), done = 1; GEN id = C; for (i=1; i 0)? 0: n>>1, n); return v; } if (!isint1(Q_denom(x))) { avma = av; return cgetg(1,t_COL); } } R1 = nf_get_r1(nf); v = cgetg(RU+1,t_COL); for (i=1; i<=R1; i++) gel(v,i) = gen_1; for ( ; i<=RU; i++) gel(v,i) = gen_2; logunit = shallowconcat(logunit, v); /* ex = fundamental units exponents */ rlog = real_i(logunit); prec = nf_get_prec(nf); for (i=1;; i++) { GEN rx = get_arch_real(nf,x,&emb, MEDDEFAULTPREC); if (rx) { GEN logN = RgV_sum(rx); /* log(Nx), should be ~ 0 */ if (gexpo(logN) > -20) { /* precision problem ? */ if (typ(logN) != t_REAL) { avma = av; return cgetg(1,t_COL); } /*no*/ if (i == 1) { GEN N = nfnorm(nf, x); if (!is_pm1(N)) { avma = av; return cgetg(1, t_COL); } } } else { ex = RgM_solve(rlog, rx); if (ex) { ex = grndtoi(ex, &e); if (!signe(gel(ex,RU)) && e < -4) break; } } } if (i == 1) prec = nbits2prec(gexpo(x) + 128); else { if (i > 4) pari_err_PREC("bnfisunit"); prec = precdbl(prec); } if (DEBUGLEVEL) pari_warn(warnprec,"bnfisunit",prec); nf = nfnewprec_shallow(nf, prec); } setlg(ex, RU); /* ZC */ p1 = imag_i( row_i(logunit,1, 1,RU-1) ); p1 = RgV_dotproduct(p1, ex); if (!R1) p1 = gmul2n(p1, -1); p1 = gsub(garg(gel(emb,1),prec), p1); /* p1 = arg(the missing root of 1) */ pi2_sur_w = divru(mppi(prec), n>>1); /* 2pi / n */ e = umodiu(roundr(divrr(p1, pi2_sur_w)), n); if (n > 2) { GEN z = algtobasis(nf, bnf_get_tuU(bnf)); /* primitive root of 1 */ GEN ro = RgV_dotproduct(row(nf_get_M(nf), 1), z); GEN p2 = roundr(divrr(garg(ro, prec), pi2_sur_w)); e *= Fl_inv(umodiu(p2,n), n); e %= n; } gel(ex,RU) = mkintmodu(e, n); setlg(ex, RU+1); return gerepilecopy(av, ex); } GEN nfsign_from_logarch(GEN LA, GEN invpi, GEN archp) { long l = lg(archp), i; GEN y = cgetg(l, t_VECSMALL); pari_sp av = avma; for (i=1; im; long i; if (!z) return zerocol(RU); arch = typ(z) == t_COL? RgM_RgC_mul(M, z): RgC_Rg_mul(gel(M,1), z); C = cgetg(RU+1, t_COL); arch = glog(arch, prec); for (i=1; i<=R1; i++) gel(C,i) = gel(arch,i); for ( ; i<=RU; i++) gel(C,i) = gmul2n(gel(arch,i), 1); return C; } static GEN perm_log_embed(GEN C, GEN perm) { long i, n; GEN Cnew = cgetg_copy(C, &n); for (i = 1; i < n; i++) { long v = perm[i]; if (v > 0) gel(Cnew, i) = gel(C, v); else gel(Cnew, i) = gconj(gel(C, -v)); } return Cnew; } static GEN set_fact(FB_t *F, FACT *fact, GEN ex, long *pnz) { long i, n = fact[0].pr; long nz; GEN c = zero_Flv(F->KC); if (!n) /* trivial factorization */ *pnz = F->KC; else { nz = fact[1].pr; if (fact[n].pr < nz) /* Possible with jid in rnd_rel */ nz = fact[n].pr; for (i=1; i<=n; i++) c[fact[i].pr] = fact[i].ex; if (ex) { for (i=1; isubFB[i]; c[v] += ex[i]; if (v < nz) nz = v; } } *pnz = nz; } return c; } /* Is cols already in the cache ? bs = index of first non zero coeff in cols * General check for colinearity useless since exceedingly rare */ static int already_known(RELCACHE_t *cache, long bs, GEN cols) { REL_t *r; long l = lg(cols); for (r = cache->last; r > cache->base; r--) if (bs == r->nz) { GEN coll = r->R; long b = bs; while (b < l && cols[b] == coll[b]) b++; if (b == l) return 1; } return 0; } /* Add relation R to cache, nz = index of first non zero coeff in R. * If relation is a linear combination of the previous ones, return 0. * Otherwise, update basis and return > 0. Compute mod p (much faster) * so some kernel vector might not be genuine. */ static int add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t **relp, long in_rnd_rel) { long i, k, n = lg(R)-1; if (already_known(cache, nz, R)) return -1; if (cache->last >= cache->base + cache->len) return 0; if (DEBUGLEVEL>6) { err_printf("adding vector = %Ps\n",R); err_printf("generators =\n%Ps\n", cache->basis); } if (cache->missing) { GEN a = leafcopy(R), basis = cache->basis; k = lg(a); do --k; while (!a[k]); while (k) { GEN c = gel(basis, k); if (c[k]) { long ak = a[k]; for (i=1; i < k; i++) if (c[i]) a[i] = (a[i] + ak*(mod_p-c[i])) % mod_p; a[k] = 0; do --k; while (!a[k]); /* k cannot go below 0: codeword is a sentinel */ } else { ulong invak = Fl_inv((ulong)a[k], mod_p); /* Cleanup a */ for (i = k; i-- > 1; ) { long j, ai = a[i]; c = gel(basis, i); if (!ai || !c[i]) continue; ai = mod_p-ai; for (j = 1; j < i; j++) if (c[j]) a[j] = (a[j] + ai*c[j]) % mod_p; a[i] = 0; } /* Insert a/a[k] as k-th column */ c = gel(basis, k); for (i = 1; imissing--; break; } } } else k = (cache->last - cache->base) + 1; if (k || cache->relsup > 0 || (m && in_rnd_rel)) { REL_t *rel; rel = ++cache->last; if (!k && cache->relsup) { cache->relsup--; k = (rel - cache->base) + cache->missing; } rel->R = gclone(R); rel->m = m ? gclone(m) : NULL; rel->nz = nz; if (aut) { rel->relorig = (rel - cache->base) - orig; rel->relaut = aut; } else rel->relaut = 0; if (relp) *relp = rel; if (DEBUGLEVEL) dbg_newrel(cache); } return k; } static int add_rel(RELCACHE_t *cache, FB_t *F, GEN R, long nz, GEN m, long in_rnd_rel) { REL_t *rel; long k, l, reln; const long nauts = lg(F->idealperm), KC = F->KC; k = add_rel_i(cache, R, nz, m, 0, 0, &rel, in_rnd_rel); if (k > 0 && m) { GEN Rl = cgetg(KC+1, t_VECSMALL); reln = rel - cache->base; for (l = 1; l < nauts; l++) { GEN perml = gel(F->idealperm, l); long i, nzl = perml[nz]; for (i = 1; i <= KC; i++) Rl[i] = 0; for (i = nz; i <= KC; i++) if (R[i]) { long v = perml[i]; if (v < nzl) nzl = v; Rl[v] = R[i]; } (void)add_rel_i(cache, Rl, nzl, NULL, reln, l, NULL, in_rnd_rel); } } return k; } /* Compute powers of prime ideal (P^0,...,P^a) (a > 1) */ static void powPgen(GEN nf, GEN vp, GEN *ppowP, long a) { GEN id2, J; long j; id2 = cgetg(a+1,t_VEC); J = mkvec2(pr_get_p(vp), zk_scalar_or_multable(nf,pr_get_gen(vp))); gel(id2,1) = J; vp = idealhnf_two(nf,vp); for (j=2; j<=a; j++) { if (DEBUGLEVEL>1) err_printf(" %ld", j); J = idealtwoelt(nf, idealmul_HNF(nf, vp, J)); gel(J, 2) = zk_scalar_or_multable(nf, gel(J,2)); gel(id2,j) = J; } setlg(id2, j); *ppowP = id2; if (DEBUGLEVEL>1) err_printf("\n"); } /* Compute powers of prime ideals (P^0,...,P^a) in subFB (a > 1) */ static void powFBgen(RELCACHE_t *cache, FB_t *F, GEN nf, GEN auts) { const long a = 1L<subFB, idealperm = F->idealperm; long i, k, l, id, n = lg(F->subFB), naut = lg(auts); if (DEBUGLEVEL) err_printf("Computing powers for subFB: %Ps\n",subFB); if (cache) pre_allocate(cache, n*naut); for (i=1; iid2, id) == gen_0) { GEN id2 = NULL; for (k = 1; k < naut; k++) { long sigmaid = coeff(idealperm, id, k); GEN sigmaid2 = gel(F->id2, sigmaid); if (sigmaid2 != gen_0) { GEN aut = gel(auts, k), invaut = gel(auts, F->invs[k]); long lid2; id2 = cgetg_copy(sigmaid2, &lid2); if (DEBUGLEVEL>1) err_printf("%ld: automorphism(%ld)\n", id,sigmaid); for (l = 1; l < lid2; l++) { GEN id2l = gel(sigmaid2, l); gel(id2, l) = mkvec2(gel(id2l, 1), ZM_mul(ZM_mul(invaut, gel(id2l, 2)), aut)); } break; } } if (!id2) { if (DEBUGLEVEL>1) err_printf("%ld: 1", id); powPgen(nf, gel(F->LP, id), &id2, a); } gel(F->id2, id) = gclone(id2); avma = av; } } F->sfb_chg = 0; F->newpow = 0; } INLINE void step(GEN x, double *y, GEN inc, long k) { if (!y[k]) x[k]++; /* leading coeff > 0 */ else { long i = inc[k]; x[k] += i; inc[k] = (i > 0)? -1-i: 1-i; } } INLINE long Fincke_Pohst_ideal(RELCACHE_t *cache, FB_t *F, GEN nf, GEN M, GEN G, GEN ideal0, FACT *fact, long nbrelpid, FP_t *fp, RNDREL_t *rr, long prec, long *nbsmallnorm, long *nbfact) { pari_sp av; const long N = nf_get_degree(nf), R1 = nf_get_r1(nf); GEN r, u, gx, inc=const_vecsmall(N, 1), ideal; GEN Nideal = nbrelpid ? NULL : idealnorm(nf, ideal0); 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); 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)"); skipfirst = ZV_isscalar(gel(ideal,1))? 1: 0; /* 1 probable */ for (k=1; k<=N; k++) { fp->v[k] = gtodouble(gcoeff(r,k,k)); for (j=1; jq[j][k] = gtodouble(gcoeff(r,j,k)); if (DEBUGLEVEL>3) err_printf("fp->v[%ld]=%.4g ",k,fp->v[k]); } BOUND = mindd(BMULT*fp->v[1], 2*(fp->v[2]+fp->v[1]*fp->q[1][2]*fp->q[1][2])); /* BOUND at most BMULT fp->x smallest known vector */ if (DEBUGLEVEL>1) { if (DEBUGLEVEL>3) err_printf("\n"); err_printf("BOUND = %.4g\n",BOUND); err_flush(); } BOUND *= 1 + 1e-6; k = N; fp->y[N] = fp->z[N] = 0; fp->x[N] = 0; for (av = avma;; avma = av, step(fp->x,fp->y,inc,k)) { GEN R; long nz; do { /* look for primitive element of small norm, cf minim00 */ int fl = 0; double p; if (k > 1) { long l = k-1; fp->z[l] = 0; for (j=k; j<=N; j++) fp->z[l] += fp->q[l][j]*fp->x[j]; p = (double)fp->x[k] + fp->z[k]; fp->y[l] = fp->y[k] + p*p*fp->v[k]; if (l <= skipfirst && !fp->y[1]) fl = 1; fp->x[l] = (long)floor(-fp->z[l] + 0.5); k = l; } for(;; step(fp->x,fp->y,inc,k)) { if (++try_elt > maxtry_ELEMENT) return 0; if (!fl) { p = (double)fp->x[k] + fp->z[k]; if (fp->y[k] + p*p*fp->v[k] <= BOUND) break; step(fp->x,fp->y,inc,k); p = (double)fp->x[k] + fp->z[k]; if (fp->y[k] + p*p*fp->v[k] <= BOUND) break; } fl = 0; inc[k] = 1; if (++k > N) return 0; } } while (k > 1); /* element complete */ if (zv_content(fp->x) !=1) continue; /* not primitive */ gx = ZM_zc_mul(ideal,fp->x); if (ZV_isscalar(gx)) continue; if (++try_factor > maxtry_FACT) return 0; if (!nbrelpid) { if (!factorgen(F,nf,ideal0,Nideal,gx,fact)) continue; return 1; } else if (rr) { if (!factorgen(F,nf,ideal0,rr->Nideal,gx,fact)) continue; add_to_fact(rr->jid, 1, fact); gx = nfmul(nf, rr->m1, gx); } else { GEN Nx, xembed = RgM_RgC_mul(M, gx); long e; if (nbsmallnorm) (*nbsmallnorm)++; Nx = grndtoi(embed_norm(xembed, R1), &e); if (e >= 0) { if (DEBUGLEVEL > 1) { err_printf("+"); err_flush(); } continue; } if (!can_factor(F, nf, NULL, gx, Nx, fact)) continue; } /* smooth element */ R = set_fact(F, fact, rr ? rr->ex : NULL, &nz); /* make sure we get maximal rank first, then allow all relations */ if (add_rel(cache, F, R, nz, gx, rr ? 1 : 0) <= 0) { /* probably Q-dependent from previous ones: forget it */ if (DEBUGLEVEL>1) err_printf("*"); if (++dependent > maxtry_DEP) break; continue; } dependent = 0; if (DEBUGLEVEL && nbfact) (*nbfact)++; if (cache->last >= cache->end) return 1; /* we have enough */ if (++nbrelideal == nbrelpid) break; } return 0; } static void small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long nbrelpid, double LOGD, double LIMC2, FACT *fact, GEN p0) { pari_timer T; const long N = nf_get_degree(nf), 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); REL_t *last = cache->last; if (DEBUGLEVEL) { timer_start(&T); err_printf("\n#### Look for %ld relations in %ld ideals (small_norm)\n", cache->end - last, lg(L_jid)-1); } 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); for (av = avma; --noideal; avma = av) { GEN ideal=gel(F->LP,L_jid[noideal]); if (DEBUGLEVEL>1) err_printf("\n*** Ideal no %ld: %Ps\n", L_jid[noideal], vecslice(ideal,1,4)); else if (DEBUGLEVEL) err_printf("(%ld) ", L_jid[noideal]); if (p0) ideal = idealmul(nf, p0, ideal); else ideal = idealhnf_two(nf, ideal); if (Fincke_Pohst_ideal(cache, F, nf, M, G, ideal, fact, nbrelpid, &fp, NULL, prec, &nbsmallnorm, &nbfact)) break; if (DEBUGLEVEL>1) timer_printf(&T, "for this ideal"); } if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&T, "small norm relations"); if (nbsmallnorm && DEBUGLEVEL > 1) err_printf(" nb. fact./nb. small norm = %ld/%ld = %.3f\n", nbfact,nbsmallnorm,((double)nbfact)/nbsmallnorm); } } /* I integral ideal in HNF form */ static GEN remove_content(GEN I) { long N = lg(I)-1; if (!is_pm1(gcoeff(I,N,N))) I = Q_primpart(I); return I; } static GEN get_random_ideal(FB_t *F, GEN nf, GEN ex) { long l = lg(ex); for (;;) { GEN ideal = NULL; long i; for (i=1; isubFB[i]; ex[i] = random_bits(RANDOM_BITS); if (ex[i]) { GEN a = gmael(F->id2,id,ex[i]); ideal = ideal? idealmul_HNF(nf,ideal, a): idealhnf_two(nf,a); } } if (ideal) { /* ex != 0 */ ideal = remove_content(ideal); if (!is_pm1(gcoeff(ideal,1,1))) return ideal; /* ideal != Z_K */ } } } static void rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact) { pari_timer T; const GEN L_jid = F->L_jid, M = nf_get_M(nf), G = F->G0; GEN baseideal; 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); long jlist; pari_sp av; /* will compute P[ L_jid[i] ] * (random product from subFB) */ if (DEBUGLEVEL) { timer_start(&T); err_printf("\n#### Look for %ld relations in %ld ideals (rnd_rel)\n", cache->end - cache->last, lg(L_jid)-1); } rr.ex = cgetg(lgsub, t_VECSMALL); 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); for (av = avma, jlist = 1; jlist < l_jid; jlist++, avma = av) { long j; GEN ideal; pari_sp av1; REL_t *last = cache->last; rr.jid = L_jid[jlist]; ideal = gel(F->LP,rr.jid); 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); ideal = idealmul_HNF(nf, baseideal, ideal); rr.Nideal = ZM_det_triangular(ideal); if (Fincke_Pohst_ideal(cache, F, nf, M, G, ideal, fact, RND_REL_RELPID, &fp, &rr, prec, NULL, NULL)) break; if (PREVENT_LLL_IN_RND_REL || cache->last != last) continue; for (av1 = avma, j = 1; j <= nbG; j++, avma = av1) { /* reduce along various directions */ GEN m = idealpseudomin_nonscalar(ideal, gel(F->vecG,j)); GEN R; long nz; if (!factorgen(F,nf,ideal,rr.Nideal,m,fact)) continue; /* can factor ideal, record relation */ add_to_fact(rr.jid, 1, fact); R = set_fact(F, fact, rr.ex, &nz); switch (add_rel(cache, F, R, nz, nfmul(nf, m, rr.m1), 1)) { case -1: /* forget it */ if (DEBUGLEVEL>1) dbg_cancelrel(rr.jid,j,R); continue; } if (DEBUGLEVEL) timer_printf(&T, "for this relation"); /* Need more, try next prime ideal */ if (cache->last < cache->end) break; /* We have found enough. Return */ avma = av; return; } } if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&T, "for remaining ideals"); } } /* remark: F->KCZ changes if be_honest() fails */ static int be_honest(FB_t *F, GEN nf, GEN auts, FACT *fact) { GEN P, done_by_autom; long ex, i, j, J, iz, nbtest; long lgsub = lg(F->subFB), KCZ0 = F->KCZ; long N = nf_get_degree(nf), prec = nf_get_prec(nf); GEN M = nf_get_M(nf), G = nf_get_G(nf); FP_t fp; pari_sp av; if (DEBUGLEVEL) { err_printf("Be honest for %ld primes from %ld to %ld\n", F->KCZ2 - F->KCZ, F->FB[ F->KCZ+1 ], F->FB[ F->KCZ2 ]); } minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v); av = avma; for (iz=F->KCZ+1; iz<=F->KCZ2; iz++, avma = av) { long p = F->FB[iz]; P = F->LV[p]; J = lg(P); /* all P|p in FB + last is unramified --> check all but last */ if (isclone(P) && pr_get_e(gel(P,J-1)) == 1) J--; if (DEBUGLEVEL>1) err_printf("%ld ", p); done_by_autom = zero_zv(J); for (j=1; j maxtry_HONEST) { if (DEBUGLEVEL) pari_warn(warner,"be_honest() failure on prime %Ps\n", P[j]); return 0; } ideal = ideal0; if (F->newpow) powFBgen(NULL, F, nf, auts); for (i=1; isubFB[i]; ex = random_bits(RANDOM_BITS); if (ex) ideal = idealmul_HNF(nf,ideal, gmael(F->id2,id,ex)); } ideal = remove_content(ideal); } avma = av2; } F->KCZ++; /* SUCCESS, "enlarge" factorbase */ } F->KCZ = KCZ0; avma = av; return 1; } /* A t_MAT of complex floats, in fact reals. Extract a submatrix B * whose columns are definitely non-0, i.e. gexpo(A[j]) >= -2 * * If possible precision problem (t_REAL 0 with large exponent), set * *precpb to 1 */ static GEN clean_cols(GEN A, int *precpb) { long l = lg(A), h, i, j, k; GEN B; *precpb = 0; if (l == 1) return A; h = lgcols(A);; B = cgetg(l, t_MAT); for (i = k = 1; i < l; i++) { GEN Ai = gel(A,i); int non0 = 0; for (j = 1; j < h; j++) { GEN c = gel(Ai,j); if (gexpo(c) >= -2) { if (gequal0(c)) *precpb = 1; else non0 = 1; } } if (non0) gel(B, k++) = Ai; } setlg(B, k); return B; } static long compute_multiple_of_R_pivot(GEN X, GEN x0/*unused*/, long ix, GEN c) { GEN x = gel(X,ix); long i, k = 0, ex = - (long)HIGHEXPOBIT, lx = lg(x); (void)x0; for (i=1; i ex) { ex = e; k = i; } } return (k && ex > -32)? k: lx; } /* A = complex logarithmic embeddings of units (u_j) found so far, * RU = R1+R2 = unit rank, N = field degree * need = unit rank defect * L = NULL (prec problem) or B^(-1) * A with approximate rational entries * (as t_REAL), B a submatrix of A, with (probably) maximal rank RU */ static GEN compute_multiple_of_R(GEN A, long RU, long N, long *pneed, GEN *ptL) { GEN T, d, mdet, Im_mdet, kR, xreal, L; long i, j, r, R1 = 2*RU - N; int precpb; pari_sp av = avma; if (RU == 1) { *ptL = zeromat(0, lg(A)-1); return gen_1; } if (DEBUGLEVEL) err_printf("\n#### Computing regulator multiple\n"); xreal = real_i(A); /* = (log |sigma_i(u_j)|) */ mdet = clean_cols(xreal, &precpb); /* will cause precision to increase on later failure, but we may succeed! */ *ptL = precpb? NULL: gen_1; T = cgetg(RU+1,t_COL); for (i=1; i<=R1; i++) gel(T,i) = gen_1; for ( ; i<=RU; i++) gel(T,i) = gen_2; mdet = shallowconcat(T, mdet); /* det(Span(mdet)) = N * R */ /* could be using indexrank(), but need custom "get_pivot" function */ d = RgM_pivots(mdet, NULL, &r, &compute_multiple_of_R_pivot); /* # of independent columns == unit rank ? */ if (lg(mdet)-1 - r != RU) { if (DEBUGLEVEL) err_printf("Unit group rank = %ld < %ld\n",lg(mdet)-1 - r, RU); *pneed = RU - (lg(mdet)-1-r); avma = av; return NULL; } Im_mdet = cgetg(RU+1, t_MAT); /* extract independent columns */ /* N.B: d[1] = 1, corresponding to T above */ gel(Im_mdet, 1) = T; for (i = j = 2; i <= RU; j++) if (d[j]) gel(Im_mdet, i++) = gel(mdet,j); /* integral multiple of R: the cols we picked form a Q-basis, they have an * index in the full lattice. First column is T */ kR = divru(det2(Im_mdet), N); /* R > 0.2 uniformly */ if (!signe(kR) || expo(kR) < -3) { avma=av; *pneed = 0; return NULL; } setabssign(kR); L = RgM_inv(Im_mdet); if (!L) { *ptL = NULL; return kR; } L = rowslice(L, 2, RU); /* remove first line */ L = RgM_mul(L, xreal); /* approximate rational entries */ gerepileall(av,2, &L, &kR); *ptL = L; return kR; } static GEN bestappr_noer(GEN x, GEN k) { GEN y; pari_CATCH(e_PREC) { y = NULL; } pari_TRY { y = bestappr(x,k); } pari_ENDCATCH; return y; } /* Input: * lambda = approximate rational entries: coords of units found so far on a * sublattice of maximal rank (sublambda) * *ptkR = regulator of sublambda = multiple of regulator of lambda * Compute R = true regulator of lambda. * * If c := Rz ~ 1, by Dirichlet's formula, then lambda is the full group of * units AND the full set of relations for the class group has been computed. * * In fact z is a very rough approximation and we only expect 0.75 < Rz < 1.3 * * Output: *ptkR = R, *ptU = basis of fundamental units (in terms lambda) */ static int compute_R(GEN lambda, GEN z, GEN *ptL, GEN *ptkR, pari_timer *T) { pari_sp av = avma; long r, ec; GEN L, H, D, den, R, c; if (DEBUGLEVEL) { err_printf("\n#### Computing check\n"); err_flush(); } D = gmul2n(mpmul(*ptkR,z), 1); /* bound for denom(lambda) */ if (expo(D) < 0 && rtodbl(D) < 0.95) return fupb_PRECI; lambda = bestappr_noer(lambda,D); if (!lambda) { if (DEBUGLEVEL) err_printf("truncation error in bestappr\n"); return fupb_PRECI; } den = Q_denom(lambda); if (mpcmp(den,D) > 0) { if (DEBUGLEVEL) err_printf("D = %Ps\nden = %Ps\n",D, lgefint(den) <= DEFAULTPREC? den: itor(den,LOWDEFAULTPREC)); return fupb_PRECI; } L = Q_muli_to_int(lambda, den); H = ZM_hnf(L); r = lg(H)-1; if (r && r != nbrows(H)) R = gen_0; /* wrong rank */ else R = gmul(*ptkR, gdiv(ZM_det_triangular(H), powiu(den, r))); /* R = tentative regulator; regulator > 0.2 uniformly */ if (gexpo(R) < -3) { if (DEBUGLEVEL) { err_printf("\n#### Tentative regulator: %.28Pg\n", R); timer_printf(T, "computing check"); } avma = av; return fupb_PRECI; } c = gmul(R,z); /* should be n (= 1 if we are done) */ if (DEBUGLEVEL) { err_printf("\n#### Tentative regulator: %.28Pg\n", R); err_printf("\n ***** check = %.28Pg\n",c); timer_printf(T, "computing check"); } ec = gexpo(c); /* safe check for c < 0.75 : avoid underflow in gtodouble() */ if (ec < -1 || (ec == -1 && gtodouble(c) < 0.75)) { avma = av; return fupb_PRECI; } /* safe check for c > 1.3 : avoid overflow */ if (ec > 0 || (ec == 0 && gtodouble(c) > 1.3)) { avma = av; return fupb_RELAT; } *ptkR = R; *ptL = L; return fupb_NONE; } /* norm of an extended ideal I, whose 1st component is in integral HNF */ static GEN idnorm(GEN I) { return ZM_det_triangular(gel(I,1)); } /* find the smallest (wrt norm) among I, I^-1 and red(I^-1) */ static GEN inverse_if_smaller(GEN nf, GEN I) { GEN d, dmin, I1; dmin = idnorm(I); I1 = idealinv(nf,I); gel(I1,1) = Q_remove_denom(gel(I1,1), NULL); d = idnorm(I1); if (cmpii(d,dmin) < 0) {I=I1; dmin=d;} /* try reducing (often _increases_ the norm) */ I1 = idealred(nf,I1); d = idnorm(I1); if (cmpii(d,dmin) < 0) I=I1; return I; } /* in place */ static void neg_row(GEN U, long i) { GEN c = U + lg(U)-1; for (; c>U; c--) gcoeff(c,i,0) = negi(gcoeff(c,i,0)); } static void setlg_col(GEN U, long l) { GEN c = U + lg(U)-1; for (; c>U; c--) setlg(*c, l); } /* compute class group (clg1) + data for isprincipal (clg2) */ static void class_group_gen(GEN nf,GEN W,GEN C,GEN Vbase,long prec, GEN nf0, GEN *ptclg1,GEN *ptclg2) { pari_timer T; GEN z,G,Ga,ga,GD,cyc,X,Y,D,U,V,Ur,Ui,Uir,I,J,arch; long i,j,lo,lo0; if (DEBUGLEVEL) timer_start(&T); D = ZM_snfall(W,&U,&V); /* UWV = D, D diagonal, G = g Ui (G=new gens, g=old) */ Ui = RgM_inv(U); lo0 = lo = lg(D); /* we could set lo = lg(cyc) and truncate all matrices below * setlg_col(D && U && Y, lo) + setlg(D && V && X && Ui, lo) * but it's not worth the complication: * 1) gain is negligible (avoid computing z^0 if lo < lo0) * 2) when computing ga, the products XU and VY use the original matrices */ Ur = ZM_hnfdivrem(U, D, &Y); Uir = ZM_hnfdivrem(Ui,W, &X); /* [x] = logarithmic embedding of x (arch. component) * NB: z = idealred(I) --> I = y z[1], with [y] = - z[2] * P invertible diagonal matrix (\pm 1) which is only implicitly defined * G = g Uir P + [Ga], Uir = Ui + WX * g = G P Ur + [ga], Ur = U + DY */ G = cgetg(lo,t_VEC); Ga= cgetg(lo,t_VEC); z = init_famat(NULL); if (!nf0) nf0 = nf; for (j=1; j pmax) pmax = p; } L = const_vec(pmax, NULL); for (i=1; i0; j--) { pari_sp av0 = avma, av; GEN c = getrand(), y; av = avma; y = get_y(bnf, 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)); if (E > prec) prec = E; } else { if (DEBUGLEVEL>1) err_printf("%ld ",j); gel(ma,j) = gerepileupto(av0,y); } } if (prec) { long k, l = lg(retry); GEN y, nf = bnf_get_nf(bnf); if (DEBUGLEVEL) pari_warn(warnprec,"makematal",prec); nf = nfnewprec_shallow(nf,prec); bnf = Buchall(nf, nf_FORCE, prec); if (DEBUGLEVEL) err_printf("makematal, adding missing entries:"); for (k=1; k1) err_printf("%ld ",j); gel(ma,j) = gerepileupto(av,y); } } if (DEBUGLEVEL>1) err_printf("\n"); return ma; } #define MATAL 1 #define CYCGEN 2 GEN check_and_build_cycgen(GEN bnf) { return obj_checkbuild(bnf, CYCGEN, &makecycgen); } GEN check_and_build_matal(GEN bnf) { return obj_checkbuild(bnf, MATAL, &makematal); } static GEN get_regulator(GEN mun) { pari_sp av = avma; GEN R; if (lg(mun) == 1) return gen_1; R = det( rowslice(real_i(mun), 1, lgcols(mun)-2) ); setabssign(R); return gerepileuptoleaf(av, R); } /* return corrected archimedian components for elts of x (vector) * (= log(sigma_i(x)) - log(|Nx|) / [K:Q]) */ static GEN get_archclean(GEN nf, GEN x, long prec, int units) { long k,N, la = lg(x); GEN M = cgetg(la,t_MAT); if (la == 1) return M; N = nf_get_degree(nf); for (k=1; k 1) { long e = gexpo(bnf_get_logfu(bnf)) + 1 - TWOPOTBITS_IN_LONG; if (e >= 0) prec += nbits2extraprec(e); } if (DEBUGLEVEL && prec1!=prec) pari_warn(warnprec,"bnfnewprec",prec); matal = check_and_build_matal(bnf); for(;;) { pari_sp av = avma; nf = nfnewprec_shallow(nf0,prec); mun = get_archclean(nf,funits,prec,1); if (mun) { gac = get_archclean(nf,matal,prec,0); if (gac) break; } avma = av; prec = precdbl(prec); if (DEBUGLEVEL) pari_warn(warnprec,"bnfnewprec(extra)",prec); } y = leafcopy(bnf); gel(y,3) = mun; gel(y,4) = gac; gel(y,7) = nf; my_class_group_gen(y,prec,nf0, &clgp,&clgp2); res = leafcopy(gel(bnf,8)); gel(res,1) = clgp; gel(res,2) = get_regulator(mun); gel(y,8) = res; gel(y,9) = clgp2; return y; } GEN bnfnewprec(GEN bnf, long prec) { pari_sp av = avma; return gerepilecopy(av, bnfnewprec_shallow(checkbnf(bnf), prec)); } GEN bnrnewprec_shallow(GEN bnr, long prec) { GEN y = cgetg(7,t_VEC); long i; gel(y,1) = bnfnewprec_shallow(bnr_get_bnf(bnr), prec); for (i=2; i<7; i++) gel(y,i) = gel(bnr,i); return y; } GEN bnrnewprec(GEN bnr, long prec) { GEN y = cgetg(7,t_VEC); long i; checkbnr(bnr); gel(y,1) = bnfnewprec(bnr_get_bnf(bnr), prec); for (i=2; i<7; i++) gel(y,i) = gcopy(gel(bnr,i)); return y; } static void nfbasic_from_sbnf(GEN sbnf, nfbasic_t *T) { T->x0 = T->x = gel(sbnf,1); T->dK = gel(sbnf,3); T->bas = gel(sbnf,4); T->index= get_nfindex(T->bas); T->r1 = itos(gel(sbnf,2)); T->dx = NULL; T->dKP = NULL; T->basden = NULL; } static GEN get_clfu(GEN clgp, GEN reg, GEN zu, GEN fu) { return mkvec5(clgp, reg, gen_1/*DUMMY*/, zu, fu); } static GEN buchall_end(GEN nf,GEN res, GEN clg2, GEN W, GEN B, GEN A, GEN C,GEN Vbase) { GEN z = cgetg(11,t_VEC); gel(z,1) = W; gel(z,2) = B; gel(z,3) = A; gel(z,4) = C; gel(z,5) = Vbase; gel(z,6) = gen_0; gel(z,7) = nf; gel(z,8) = res; gel(z,9) = clg2; gel(z,10) = zerovec(2); return z; } static GEN bnftosbnf(GEN bnf) { GEN nf = bnf_get_nf(bnf), T = nf_get_pol(nf); GEN y = cgetg(13,t_VEC); gel(y,1) = T; gel(y,2) = gmael(nf,2,1); gel(y,3) = nf_get_disc(nf); gel(y,4) = nf_get_zk(nf); gel(y,5) = nf_get_roots(nf); gel(y,6) = gen_0; /* FIXME: unused */ gel(y,7) = gel(bnf,1); gel(y,8) = gel(bnf,2); gel(y,9) = codeprimes(gel(bnf,5), degpol(T)); gel(y,10) = mkvec2(utoipos(bnf_get_tuN(bnf)), nf_to_scalar_or_basis(nf, bnf_get_tuU(bnf))); gel(y,11) = matalgtobasis(bnf, bnf_get_fu_nocheck(bnf)); (void)check_and_build_matal(bnf); gel(y,12) = gel(bnf,10); return y; } GEN bnfcompress(GEN bnf) { pari_sp av = avma; bnf = checkbnf(bnf); return gerepilecopy(av, bnftosbnf( checkbnf(bnf) )); } static GEN sbnf2bnf(GEN sbnf, long prec) { long j, k, l, n; pari_sp av = avma; GEN ro, nf, A, fu, FU, L; GEN pfc, C, clgp, clgp2, res, y, W, zu, matal, Vbase; nfbasic_t T; if (typ(sbnf) != t_VEC || lg(sbnf) != 13) pari_err_TYPE("bnfmake",sbnf); if (prec < DEFAULTPREC) prec = DEFAULTPREC; nfbasic_from_sbnf(sbnf, &T); ro = gel(sbnf,5); fu = gel(sbnf,11); if (prec > gprecision(ro)) ro = get_roots(T.x,T.r1,prec); nf = nfbasic_to_nf(&T, ro, prec); A = get_archclean(nf, fu, prec, 1); if (!A) pari_err_PREC( "bnfmake"); prec = gprecision(ro); matal = check_and_build_matal(sbnf); C = get_archclean(nf,matal,prec,0); if (!C) pari_err_PREC( "bnfmake"); pfc = gel(sbnf,9); l = lg(pfc); Vbase = cgetg(l,t_COL); L = decode_pr_lists(nf, pfc); n = nf_get_degree(nf); for (j=1; j 5) pari_err_TYPE("bnfinit",data); switch(lx) { case 4: relpid = itos(gel(data,3)); case 3: c2 = gtodouble(gel(data,2)); case 2: c1 = gtodouble(gel(data,1)); } } switch(flag) { case 2: case 0: fl = 0; break; case 1: fl = nf_FORCE; break; default: pari_err_FLAG("bnfinit"); return NULL; /* not reached */ } return Buchall_param(P, c1, c2, relpid, fl, prec); } GEN Buchall(GEN P, long flag, long prec) { return Buchall_param(P, BNF_C1, BNF_C2, BNF_RELPID, flag, prec); } static GEN Buchall_deg1(GEN nf) { GEN v = cgetg(1,t_VEC), m = cgetg(1,t_MAT); GEN W, A, B, C, Vbase, res; GEN fu = v, R = gen_1, zu = mkvec2(gen_2, gen_m1); GEN clg1 = mkvec3(gen_1,v,v), clg2 = mkvec3(m,v,v); W = A = B = C = m; Vbase = cgetg(1,t_COL); res = get_clfu(clg1, R, zu, fu); return buchall_end(nf,res,clg2,W,B,A,C,Vbase); } /* return (small set of) indices of columns generating the same lattice as x. * Assume HNF(x) is inexpensive (few rows, many columns). * Dichotomy approach since interesting columns may be at the very end */ GEN extract_full_lattice(GEN x) { long dj, j, k, l = lg(x); GEN h, h2, H, v; if (l < 200) return NULL; /* not worth it */ v = vecsmalltrunc_init(l); H = ZM_hnf(x); h = cgetg(1, t_MAT); dj = 1; for (j = 1; j < l; ) { pari_sp av = avma; long lv = lg(v); for (k = 0; k < dj; k++) v[lv+k] = j+k; setlg(v, lv + dj); h2 = ZM_hnf(vecpermute(x, v)); if (ZM_equal(h, h2)) { /* these dj columns can be eliminated */ avma = av; setlg(v, lv); j += dj; if (j >= l) break; dj <<= 1; if (j + dj >= l) { dj = (l - j) >> 1; if (!dj) dj = 1; } } else if (dj > 1) { /* at least one interesting column, try with first half of this set */ avma = av; setlg(v, lv); dj >>= 1; /* > 0 */ } else { /* this column should be kept */ if (ZM_equal(h2, H)) break; h = h2; j++; } } return v; } static void init_rel(RELCACHE_t *cache, FB_t *F, long add_need) { const long n = F->KC + add_need; /* expected # of needed relations */ long i, j, k, p; GEN c, P; GEN R; if (DEBUGLEVEL) err_printf("KCZ = %ld, KC = %ld, n = %ld\n", F->KCZ,F->KC,n); reallocate(cache, 10*n + 50); /* make room for lots of relations */ cache->chk = cache->base; cache->end = cache->base + n; cache->relsup = add_need; cache->last = cache->base; cache->missing = lg(cache->basis) - 1; for (i = 1; i <= F->KCZ; i++) { /* trivial relations (p) = prod P^e */ p = F->FB[i]; P = F->LV[p]; if (!isclone(P)) continue; /* all prime divisors in FB */ c = zero_Flv(F->KC); k = F->iLP[p]; R = c; c += k; for (j = lg(P)-1; j; j--) c[j] = pr_get_e(gel(P,j)); add_rel(cache, F, R, k+1, /*m*/NULL, 0); } } static void shift_embed(GEN G, GEN Gtw, long a, long r1) { long j, k, l = lg(G); if (a <= r1) for (j=1; jG0 = G0 = ground(G); F->vecG = mkvec( G0 ); return; } for (e = 32;;) { G = gmul2n(G, e); G0 = ground(G); if (ZM_rank(G0) == r) break; /* maximal rank ? */ } Gtw0 = ground(gmul2n(G, 10)); vecG = cgetg(1 + n*(n+1)/2,t_VEC); for (ind=j=1; j<=n; j++) for (i=1; i<=j; i++) gel(vecG,ind++) = shift_G(G0,Gtw0,i,j,r1); F->G0 = G0; F->vecG = vecG; } static GEN automorphism_perms(GEN M, GEN auts, GEN cyclic, long N) { pari_sp av; const long r1plusr2 = lgcols(M), r1 = 2*r1plusr2-N-2, r2 = r1plusr2-r1-1; long nauts = lg(auts), ncyc = lg(cyclic), i, j, l, m; GEN Mt, perms = cgetg(nauts, t_VEC); for (l = 1; l < nauts; l++) gel(perms, l) = cgetg(r1plusr2, t_VECSMALL); av = avma; Mt = shallowtrans(gprec_w(M, 3)); /* need little accuracy */ Mt = shallowconcat(Mt, gconj(vecslice(Mt, r1+1, r1+r2))); for (l = 1; l < ncyc; l++) { GEN thiscyc = gel(cyclic, l); long k = thiscyc[1]; GEN Nt = RgM_mul(shallowtrans(gel(auts, k)), Mt); GEN perm = gel(perms, k), permprec; pari_sp av2 = avma; for (i = 1; i < r1plusr2; i++, avma = av2) { GEN vec = gel(Nt, i), minnorm; minnorm = gnorml2(gsub(vec, gel(Mt, 1))); perm[i] = 1; for (j = 2; j <= N; j++) { GEN thisnorm = gnorml2(gsub(vec, gel(Mt, j))); if (gcmp(thisnorm, minnorm) < 0) { minnorm = thisnorm; perm[i] = j >= r1plusr2 ? r2-j : j; } } } for (permprec = perm, m = 2; m < lg(thiscyc); m++) { GEN thisperm = gel(perms, thiscyc[m]); for (i = 1; i < r1plusr2; i++) { long pp = labs(permprec[i]); thisperm[i] = permprec[i] < 0 ? -perm[pp] : perm[pp]; } permprec = thisperm; } } avma = av; return perms; } /* Determine the field automorphisms and its matrix in the integral basis. */ static GEN automorphism_matrices(GEN nf, GEN *invp, GEN *cycp) { pari_sp av = avma; GEN auts = galoisconj(nf, NULL), mats, cyclic, cyclicidx; GEN invs; long nauts = lg(auts)-1, i, j, k, l; cyclic = cgetg(nauts+1, t_VEC); cyclicidx = zero_Flv(nauts); invs = zero_Flv(nauts-1); for (l = 1; l <= nauts; l++) { GEN aut = gel(auts, l); if (degpol(aut) == 1 && isint1(leading_term(aut)) && isintzero(constant_term(aut))) { swap(gel(auts, l), gel(auts, nauts)); break; } } for (l = 1; l <= nauts; l++) gel(auts, l) = algtobasis(nf, gel(auts, l)); /* Compute maximal cyclic subgroups */ for (l = nauts; --l > 0; ) if (!cyclicidx[l]) { GEN elt = gel(auts, l), aut = elt, cyc = cgetg(nauts+1, t_VECSMALL); cyclicidx[l] = l; cyc[1] = l; j = 1; do { elt = galoisapply(nf, elt, aut); for (k = 1; k <= nauts; k++) if (gequal(elt, gel(auts, k))) break; cyclicidx[k] = l; cyc[++j] = k; } while (k != nauts); setlg(cyc, j); gel(cyclic, l) = cyc; /* Store the inverses */ for (i = 1; i <= j/2; i++) { invs[cyc[i]] = cyc[j-i]; invs[cyc[j-i]] = cyc[i]; } } for (i = j = 1; i < nauts; i++) if (cyclicidx[i] == i) cyclic[j++] = cyclic[i]; setlg(cyclic, j); mats = cgetg(nauts, t_VEC); while (--j > 0) { GEN cyc = gel(cyclic, j); long id = cyc[1]; GEN M, Mi, aut = gel(auts, id); gel(mats, id) = Mi = M = nfgaloismatrix(nf, aut); for (i = 2; i < lg(cyc); i++) { Mi = ZM_mul(Mi, M); gel(mats, cyc[i]) = Mi; } } gerepileall(av, 3, &mats, &invs, &cyclic); *invp = invs; *cycp = cyclic; return mats; } static GEN trim_list(FB_t *F) { pari_sp av = avma; GEN L_jid = F->L_jid, present = zero_Flv(F->KC); long i, j, imax = minss(lg(L_jid), F->KC + 1); GEN minidx = F->minidx, idx = cgetg(imax, t_VECSMALL); for (i = j = 1; i < imax; i++) { long id = minidx[L_jid[i]]; if (!present[id]) { idx[j++] = L_jid[i]; present[id] = 1; } } setlg(idx, j); return gerepileuptoleaf(av, idx); } static void try_elt(RELCACHE_t *cache, FB_t *F, GEN nf, GEN x, FACT *fact) { pari_sp av = avma; GEN R, Nx; long nz, tx = typ(x); if (tx == t_INT || tx == t_FRAC) return; if (tx != t_COL) x = algtobasis(nf, x); if (RgV_isscalar(x)) return; x = Q_primpart(x); Nx = nfnorm(nf, x); if (!can_factor(F, nf, NULL, x, Nx, fact)) return; /* smooth element */ R = set_fact(F, fact, NULL, &nz); /* make sure we get maximal rank first, then allow all relations */ (void) add_rel(cache, F, R, nz, x, 0); avma = av; } GEN Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long prec) { pari_timer T; pari_sp av0 = avma, av, av2; long PRECREG, N, R1, R2, RU, low, high, LIMC0, LIMC, LIMC2, LIMCMAX, zc, i; long MAXDEPSIZESFB, MAXDEPSFB; long nreldep, sfb_trials, need, old_need, precdouble = 0, precadd = 0; long done_small, small_fail, fail_limit, squash_index; double lim, drc, LOGD, LOGD2; GEN computed = NULL, zu, nf, 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; const char *precpb = NULL; int FIRST = 1, class1 = 0; RELCACHE_t cache; FB_t F; GRHcheck_t GRHcheck; FACT *fact; if (DEBUGLEVEL) timer_start(&T); P = get_nfpol(P, &nf); if (nf) PRECREG = nf_get_prec(nf); else { PRECREG = maxss(prec, MEDDEFAULTPREC); nf = nfinit(P, PRECREG); if (lg(nf)==3) { /* P non-monic and nfinit CHANGEd it ? */ pari_warn(warner,"non-monic polynomial. Change of variables discarded"); nf = gel(nf,1); P = nf_get_pol(nf); } } N = degpol(P); if (N <= 1) return gerepilecopy(av0, Buchall_deg1(nf)); zu = rootsof1(nf); gel(zu,2) = nf_to_scalar_or_alg(nf, gel(zu,2)); if (DEBUGLEVEL) timer_printf(&T, "nfinit & rootsof1"); auts = automorphism_matrices(nf, &F.invs, &cyclic); if (DEBUGLEVEL) timer_printf(&T, "automorphisms"); F.embperm = automorphism_perms(nf_get_M(nf), auts, cyclic, N); if (DEBUGLEVEL) timer_printf(&T, "complex embedding permutations"); nf_get_sign(nf, &R1, &R2); RU = R1+R2; compute_vecG(nf, &F, minss(RU, 9)); if (DEBUGLEVEL) timer_printf(&T, "weighted G matrices"); 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); if (lim < 3.) lim = 3.; if (cbach > 12.) { if (cbach2 < cbach) cbach2 = cbach; cbach = 12.; } if (cbach < 0.) pari_err_DOMAIN("Buchall","Bach constant","<",gen_0,dbltor(cbach)); cache.base = NULL; F.subFB = NULL; F.LP = NULL; 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; high *= 2; } while (high - low > 1) { long test = (low+high)/2; if (GRHchk(nf, &GRHcheck, test)) high = test; else low = test; } if (high == LIMC0+1 && GRHchk(nf, &GRHcheck, LIMC0)) LIMC2 = LIMC0; else LIMC2 = high; if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX; if (DEBUGLEVEL) err_printf("LIMC2 = %ld\n", LIMC2); 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 = maxss(LIMC, nthideal(&GRHcheck, nf, N)); if (DEBUGLEVEL) timer_printf(&T, "computing Bach constant"); START: if (DEBUGLEVEL) timer_start(&T); if (!FIRST) LIMC = check_LIMC(LIMC,LIMCMAX); if (DEBUGLEVEL && LIMC > LIMC0) err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2); if (cache.base) { REL_t *rel; for (i = 1, rel = cache.base + 1; rel < cache.last; rel++) if (rel->m) i++; computed = cgetg(i, t_VEC); for (i = 1, rel = cache.base + 1; rel < cache.last; rel++) if (rel->m) gel(computed, i++) = rel->m; computed = gclone(computed); delete_cache(&cache); } FIRST = 0; avma = av; if (F.LP) delete_FB(&F); if (LIMC2 < LIMC) LIMC2 = LIMC; if (DEBUGLEVEL) { err_printf("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); } FBgen(&F, nf, N, LIMC, LIMC2, &GRHcheck); if (!F.KC) goto START; av = avma; subFBgen(&F,nf,auts,cyclic,mindd(lim,LIMC2) + 0.5,MINSFB); if (DEBUGLEVEL) { if (lg(F.subFB) > 1) timer_printf(&T, "factorbase (#subFB = %ld) and ideal permutations", lg(F.subFB)-1); 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); small_multiplier = zero_Flv(F.KC); F.id2 = zerovec(F.KC); MAXDEPSIZESFB = (lg(F.subFB) - 1) * DEPSIZESFBMULT; MAXDEPSFB = MAXDEPSIZESFB / DEPSFBDIV; done_small = 0; small_fail = 0; squash_index = 0; fail_limit = F.KC + 1; R = NULL; A = NULL; av2 = avma; init_rel(&cache, &F, RELSUP + RU-1); /* trivial relations */ old_need = need = cache.end - cache.last; W = NULL; zc = 0; sfb_trials = nreldep = 0; if (computed) { for (i = 1; i < lg(computed); i++) try_elt(&cache, &F, nf, gel(computed, i), fact); if (isclone(computed)) gunclone(computed); if (DEBUGLEVEL && i > 1) { err_printf("\n"); timer_printf(&T, "including already computed relations"); } need = 0; } do { do { pari_sp av4 = avma; if (need > 0) { long oneed = cache.end - cache.last; /* Test below can be true if small_norm did not find enough linearly * dependent relations */ if (need < oneed) need = oneed; pre_allocate(&cache, need+lg(auts)-1+(R ? lg(W)-1 : 0)); cache.end = cache.last + need; F.L_jid = trim_list(&F); } if (need > 0 && nbrelpid > 0 && (done_small <= F.KC+1 || A) && small_fail <= fail_limit && cache.last < cache.base + 2*F.KC+2*RU+RELSUP /* heuristic */) { pari_sp av3 = avma; GEN p0 = NULL; long j, k; REL_t *last = cache.last; if (R && lg(W) > 1 && (done_small % 2)) { /* We have full rank for class group and unit, however those * lattices are too small. The following tries to improve the * prime group lattice: it specifically looks for relations * involving the primes generating the class group. */ long l = lg(W) - 1; /* We need lg(W)-1 relations to squash the class group. */ F.L_jid = vecslice(F.perm, 1, l); cache.end = cache.last + l; /* Lie to the add_rel subsystem: pretend we miss relations involving * the primes generating the class group (and only those). */ cache.missing = l; for ( ; l > 0; l--) mael(cache.basis, F.perm[l], F.perm[l]) = 0; } j = done_small % (F.KC+1); if (j) { long mj = small_multiplier[j]; p0 = gel(F.LP, j); if (!A) { /* Prevent considering both P_iP_j and P_jP_i in small_norm */ /* Since not all elements end up in F.L_jid (because they can * be eliminated by hnfspec/add or by trim_list, keep track * of which ideals are being considered at each run. */ for (i = k = 1; i < lg(F.L_jid); i++) if (F.L_jid[i] > mj) { small_multiplier[F.L_jid[i]] = j; F.L_jid[k++] = F.L_jid[i]; } setlg(F.L_jid, k); } } if (lg(F.L_jid) > 1) small_norm(&cache, &F, nf, nbrelpid, LOGD, LIMC2, fact, p0); avma = av3; if (!A && cache.last != last) small_fail = 0; else small_fail++; if (R && lg(W) > 1 && (done_small % 2)) { long l = lg(W) - 1; for ( ; l > 0; l--) mael(cache.basis, F.perm[l], F.perm[l]) = 1; cache.missing = 0; } F.L_jid = F.perm; need = 0; cache.end = cache.last; done_small++; if (!need) F.sfb_chg = 0; } if (need > 0) { /* Random relations */ if (lg(F.subFB) == 1) goto START; nreldep++; if (nreldep > MAXDEPSIZESFB) { if (++sfb_trials > SFB_MAX && LIMC < LIMCMAX/6) goto START; F.sfb_chg = sfb_INCREASE; nreldep = 0; } else if (!(nreldep % MAXDEPSFB)) F.sfb_chg = sfb_CHANGE; if (F.newpow) { F.sfb_chg = 0; if (DEBUGLEVEL) err_printf("\n"); } if (F.sfb_chg && !subFB_change(&F)) goto START; if (F.newpow) { powFBgen(&cache, &F, nf, auts); MAXDEPSIZESFB = (lg(F.subFB) - 1) * DEPSIZESFBMULT; MAXDEPSFB = MAXDEPSIZESFB / DEPSFBDIV; if (DEBUGLEVEL) timer_printf(&T, "powFBgen"); } if (!F.sfb_chg) rnd_rel(&cache, &F, nf, fact); F.L_jid = F.perm; } if (DEBUGLEVEL) timer_start(&T); if (precpb) { GEN nf0 = nf; if (precadd) { PRECREG += precadd; precadd = 0; } else PRECREG = precdbl(PRECREG); if (DEBUGLEVEL) { char str[64]; sprintf(str,"Buchall_param (%s)",precpb); pari_warn(warnprec,str,PRECREG); } nf = gclone( nfnewprec_shallow(nf, PRECREG) ); 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 */ } avma = av4; if (cache.chk != cache.last) { /* Reduce relation matrices */ long l = cache.last - cache.chk + 1, j; GEN M = nf_get_M(nf), mat = cgetg(l, t_MAT), emb = cgetg(l, t_MAT); int first = (W == NULL); /* never reduced before */ REL_t *rel; for (j=1,rel = cache.chk + 1; j < l; rel++,j++) { gel(mat,j) = rel->R; if (!rel->relaut) gel(emb,j) = get_log_embed(rel, M, RU, R1, PRECREG); else gel(emb,j) = perm_log_embed(gel(emb, j-rel->relorig), gel(F.embperm, rel->relaut)); } if (DEBUGLEVEL) timer_printf(&T, "floating point embeddings"); if (first) { C = emb; W = hnfspec_i(mat, F.perm, &dep, &B, &C, F.subFB ? lg(F.subFB)-1:0); } else W = hnfadd_i(W, F.perm, &dep, &B, &C, mat, emb); gerepileall(av2, 4, &W,&C,&B,&dep); cache.chk = cache.last; if (DEBUGLEVEL) { if (first) timer_printf(&T, "hnfspec [%ld x %ld]", lg(F.perm)-1, l-1); else timer_printf(&T, "hnfadd (%ld + %ld)", l-1, lg(dep)-1); } } else if (!W) { need = old_need; F.L_jid = vecslice(F.perm, 1, need); continue; } need = F.KC - (lg(W)-1) - (lg(B)-1); /* FIXME: replace by err(e_BUG,"") */ if (!need && cache.missing) { /* The test above will never be true except if 27449|class number, * but the code implicitely assumes that if we have maximal rank * for the ideal lattice, then cache.missing == 0. */ for (i = 1; cache.missing; i++) if (!mael(cache.basis, i, i)) { long j; mael(cache.basis, i, i) = 1; cache.missing--; for (j = i+1; j <= F.KC; j++) mael(cache.basis, j, i) = 0; } } zc = (lg(C)-1) - (lg(B)-1) - (lg(W)-1); if (zc < RU-1) { /* need more columns for units */ need += RU-1 - zc; if (need > F.KC) need = F.KC; } if (need) { /* dependent rows */ F.L_jid = vecslice(F.perm, 1, need); vecsmall_sort(F.L_jid); if (need != old_need) nreldep = 0; old_need = need; } else { /* If the relation lattice is too small, check will be > 1 and we * will do a new run of small_norm/rnd_rel asking for 1 relation. * However they tend to give a relation involving the first element * of L_jid. We thus permute which element is the first of L_jid in * order to increase the probability of finding a good relation, i.e. * one that increases the relation lattice. */ if (lg(W) > 2 && squash_index % (lg(W) - 1)) { long j, l = lg(W) - 1; F.L_jid = leafcopy(F.perm); for (j = 1; j <= l; j++) F.L_jid[j] = F.perm[1 + (j + squash_index - 1) % l]; } else F.L_jid = F.perm; squash_index++; } } while (need); if (!A) { small_fail = 0; fail_limit = maxss(F.KC / FAIL_DIVISOR, MINFAIL); old_need = 0; } A = vecslice(C, 1, zc); /* cols corresponding to units */ R = compute_multiple_of_R(A, RU, N, &need, &lambda); if (need < old_need) small_fail = 0; old_need = need; if (!lambda) { precpb = "bestappr"; continue; } if (!R) { /* not full rank for units */ if (DEBUGLEVEL) err_printf("regulator is zero.\n"); if (!need) precpb = "regulator"; continue; } h = ZM_det_triangular(W); if (DEBUGLEVEL) err_printf("\n#### Tentative class number: %Ps\n", h); switch (compute_R(lambda, mulir(h,invhr), &L, &R, &T)) { case fupb_RELAT: need = 1; /* not enough relations */ continue; case fupb_PRECI: /* prec problem unless we cheat on Bach constant */ if ((precdouble&7) == 7 && LIMC<=LIMCMAX/6) goto START; precpb = "compute_R"; continue; } /* DONE */ if (F.KCZ2 > F.KCZ) { if (F.sfb_chg && !subFB_change(&F)) goto START; if (!be_honest(&F, nf, auts, fact)) goto START; if (DEBUGLEVEL) timer_printf(&T, "to be honest"); } F.KCZ2 = 0; /* be honest only once */ /* fundamental units */ { pari_sp av3 = avma; GEN AU, U, H, v = extract_full_lattice(L); /* L may be very large */ long e; if (v) { A = vecpermute(A, v); L = vecpermute(L, v); } /* 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)); AU = RgM_mul(A, U); A = cleanarch(AU, N, PRECREG); if (DEBUGLEVEL) timer_printf(&T, "cleanarch"); if (!A) { precadd = nbits2extraprec( gexpo(AU) + 64 ) - gprecision(AU); if (precadd <= 0) precadd = 1; precpb = "cleanarch"; continue; } fu = getfu(nf, &A, &e, PRECREG); if (DEBUGLEVEL) timer_printf(&T, "getfu"); if ((flun & nf_FORCE) && typ(fu) == t_MAT) { /* units not found but we want them */ if (e > 0) pari_err_OVERFLOW("bnfinit [fundamental units too large]"); if (e < 0) precadd = nbits2extraprec( (-e - (BITS_IN_LONG - 1)) + 64); avma = av3; precpb = "getfu"; continue; } } /* class group generators */ i = lg(C)-zc; C += zc; C[0] = evaltyp(t_MAT)|evallg(i); C0 = C; C = cleanarch(C, N, PRECREG); if (!C) { precadd = nbits2extraprec( gexpo(C0) + 64 ) - gprecision(C0); if (precadd <= 0) precadd = 1; precpb = "cleanarch"; } } while (need || precpb); delete_cache(&cache); delete_FB(&F); free_GRHcheck(&GRHcheck); Vbase = vecpermute(F.LP, F.perm); class_group_gen(nf,W,C,Vbase,PRECREG,NULL, &clg1, &clg2); res = get_clfu(clg1, R, zu, fu); res = buchall_end(nf,res,clg2,W,B,A,C,Vbase); res = gerepilecopy(av0, res); if (precdouble) gunclone(nf); return res; } pari-2.7.5/src/basemath/lll.c0000644000175000017500000006107612405547147014433 0ustar billbill/* Copyright (C) 2008 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" /* default quality ratio for LLL */ static const double LLLDFT = 0.99; /* assume flag & (LLL_KER|LLL_IM|LLL_ALL). LLL_INPLACE implies LLL_IM */ static GEN lll_trivial(GEN x, long flag) { GEN y; if (lg(x) == 1) { /* dim x = 0 */ if (! (flag & LLL_ALL)) return cgetg(1,t_MAT); y=cgetg(3,t_VEC); gel(y,1) = cgetg(1,t_MAT); gel(y,2) = cgetg(1,t_MAT); return y; } /* dim x = 1 */ if (gequal0(gel(x,1))) { if (flag & LLL_KER) return matid(1); if (flag & (LLL_IM|LLL_INPLACE)) return cgetg(1,t_MAT); y = cgetg(3,t_VEC); gel(y,1) = matid(1); gel(y,2) = cgetg(1,t_MAT); return y; } if (flag & LLL_INPLACE) return gcopy(x); if (flag & LLL_KER) return cgetg(1,t_MAT); if (flag & LLL_IM) return matid(1); y=cgetg(3,t_VEC); gel(y,1) = cgetg(1,t_MAT); gel(y,2) = (flag & LLL_GRAM)? gcopy(x): matid(1); return y; } /* vecslice(h,#h-k,#h) in place. Works for t_MAT, t_VEC/t_COL */ static GEN lll_get_im(GEN h, long k) { ulong mask = h[0] & ~LGBITS; long l = lg(h) - k; h += k; h[0] = mask | evallg(l); return h; } /* k = dim Kernel */ static GEN lll_finish(GEN h, long k, long flag) { GEN g; if (flag & LLL_KER) { setlg(h,k+1); return h; } if (flag & LLL_IM) return lll_get_im(h, k); g = vecslice(h,1,k); return mkvec2(g, lll_get_im(h, k)); } /********************************************************************/ /** **/ /** FPLLL (adapted from D. Stehle's code) **/ /** **/ /********************************************************************/ /* Babai() and fplll() are a conversion to libpari API and data types of the file proved.c in fplll-1.3 by Damien Stehle'. Copyright 2005, 2006 Damien Stehle'. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program implements ideas from the paper "Floating-point LLL Revisited", by Phong Nguyen and Damien Stehle', in the Proceedings of Eurocrypt'2005, Springer-Verlag; and was partly inspired by Shoup's NTL library: http://www.shoup.net/ntl/ */ /***********************************************/ /* Babai's Nearest Plane algorithm (iterative) */ /***********************************************/ /* Size-reduces b_kappa using mu_{i,j} and r_{i,j} for j<=i 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; for (;;) { int go_on = 0; GEN max3mu; long i, j; if (low_stack(lim, stack_lim(av,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa); gerepileall(av,U?5:4,&B,&G,&maxmu,&max2mu,&U); } /* Step2: compute the GSO for stage kappa */ max3mu = max2mu; max2mu = maxmu; maxmu = real_0(prec); for (j=aa; j k) { tmp = mulrr(gmael(mu,j,k), gmael(r,kappa,k)); rtmp = subir(gmael(G,kappa,j), tmp); for (k++; k5) err_printf("prec too low\n"); return kappa; } /* Step3--5: compute the X_j's */ for (j=kappa-1; j>zeros; j--) { tmp = gmael(mu,kappa,j); if (absr_cmp(tmp, eta) <= 0) continue; /* (essentially) size-reduced */ if (low_stack(lim, stack_lim(av,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); } go_on = 1; /* we consider separately the case |X| = 1 */ if (absr_cmp(tmp, halfplus1) <= 0) { if (signe(tmp) > 0) { /* in this case, X = 1 */ pari_sp btop = avma; for (k=zeros+1; k= 2 */ ztmp = roundr_safe(tmp); if (lgefint(ztmp) == 3) { pari_sp btop = avma; ulong xx = ztmp[2]; /* X fits in an ulong */ if (signe(ztmp) > 0) /* = xx */ { for (k=zeros+1; kkappa; i--) for (j=1;j<=d;j++) gmael(mu,i,j) = gmael(mu,i-1,j); for (j=1;j<=d;j++) gmael(mu,kappa,j) = gel(mutmp,j); avma = av; } /* ****************** */ /* The LLL Algorithm */ /* ****************** */ /* LLL-reduces the integer matrix(ces) (G,B,U)? "in place" */ static GEN fplll(GEN *ptrB, GEN *ptrU, GEN *ptrr, double DELTA, double ETA, long flag, long prec) { const long gram = flag & LLL_GRAM; /*Gram matrix*/ const long keepfirst = flag & LLL_KEEP_FIRST; /*never swap with first vector*/ pari_sp av, av2; long kappa, kappa2, d, n, i, j, zeros, kappamax, maxG, bab; GEN G, mu, r, s, tmp, SPtmp, alpha; GEN delta = dbltor(DELTA), eta = dbltor(ETA), halfplus1 = dbltor(1.5); const long triangular = 0; pari_timer T; GEN B = *ptrB, U; d = lg(B)-1; if (gram) { G = B; n = d; B = cgetg(1, t_VECSMALL); /* dummy */ } else { G = zeromatcopy(d,d); n = nbrows(B); } U = *ptrU; /* NULL if inplace */ if(DEBUGLEVEL>=4) { timer_start(&T); err_printf("Entering L^2: LLL-parameters (%P.3f,%.3Pf), working precision %d words\n",delta,eta, prec); } mu = cgetg(d+1, t_MAT); r = cgetg(d+1, t_MAT); s = cgetg(d+1, t_VEC); for (j = 1; j <= d; j++) { GEN M = cgetg(d+1, t_COL), R = cgetg(d+1, t_COL); gel(mu,j)= M; gel(r,j) = R; gel(s,j) = cgetr(prec); for (i = 1; i <= d; i++) { gel(R,i) = cgetr(prec); gel(M,i) = cgetr(prec); } } SPtmp = zerovec(d+1); alpha = cgetg(d+1, t_VECSMALL); av = avma; /* Step2: Initializing the main loop */ kappamax = 1; i = 1; maxG = d; /* later updated to kappamax if (!gram) */ do { if (!gram) gmael(G,i,i) = ZV_dotsquare(gel(B,i)); affir(gmael(G,i,i), gmael(r,i,i)); } while (signe(gmael(G,i,i)) == 0 && (++i <=d)); zeros = i-1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i; if (zeros < d) affir(gmael(G,zeros+1,zeros+1), gmael(r,zeros+1,zeros+1)); for (i=zeros+1; i<=d; i++) alpha[i]=1; while (++kappa <= d) { if (kappa>kappamax) { if (DEBUGLEVEL>=4) err_printf("K%ld ",kappa); kappamax = kappa; if (!gram) { for (i=zeros+1; i<=kappa; i++) gmael(G,kappa,i) = ZV_dotproduct(gel(B,kappa), gel(B,i)); maxG = kappamax; } } /* Step3: Call to the Babai algorithm, mu,r,s updated in place */ bab = Babai(av, kappa, &G,&B,&U, mu,r,s, alpha[kappa], zeros, maxG, gram? 0 : ((triangular && kappamax <= n) ? kappamax: n), eta, halfplus1, prec); if (bab) {*ptrB=(gram?G:B); *ptrU=U; return NULL; } av2 = avma; if ((keepfirst && kappa == 2) || cmprr(mulrr(gmael(r,kappa-1,kappa-1), delta), gel(s,kappa-1)) <= 0) { /* Step4: Success of Lovasz's condition */ alpha[kappa] = kappa; tmp = mulrr(gmael(mu,kappa,kappa-1), gmael(r,kappa,kappa-1)); affrr(subrr(gel(s,kappa-1), tmp), gmael(r,kappa,kappa)); avma = av2; } 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); } kappa2 = kappa; do { kappa--; if (kappakappa; i--) alpha[i] = alpha[i-1]; for (i=kappa2+1; i<=kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; /* Step6: Update the mu's and r's */ rotate(mu,kappa2,kappa,d); rotate(r,kappa2,kappa,d); affrr(gel(s,kappa), gmael(r,kappa,kappa)); /* Step7: Update B, G, U */ if (!gram) rotate(B,kappa2,kappa,n); if (U) rotate(U,kappa2,kappa,d); for (i=1; i<=kappa2; i++) gel(SPtmp,i) = gmael(G,kappa2,i); for (i=kappa2+1; i<=maxG; i++) gel(SPtmp,i) = gmael(G,i,kappa2); for (i=kappa2; i>kappa; i--) { for (j=1; j=4) timer_printf(&T,"LLL"); if (ptrr) *ptrr = RgM_diagonal_shallow(r); if (!U) { if (zeros) { if (gram) { G = lll_get_im(G, zeros); d -= zeros; for (i = 1; i <= d; i++) gel(G,i) = lll_get_im(gel(G,i), zeros); } else B = lll_get_im(B, zeros); } } else if (flag & (LLL_IM|LLL_KER|LLL_ALL)) U = lll_finish(U, zeros, flag); if (gram) { if (U) return U; for (i = 1; i <= d; i++) for (j = i+1; j <= d; j++) gmael(G,i,j) = gmael(G,j,i); return G; } return U? U: B; } /* Assume x a ZM, if ptB != NULL, set it to Gram-Schmidt (squared) norms */ GEN ZM_lll_norms(GEN x, double DELTA, long flag, GEN *B) { pari_sp ltop = avma; 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)) { GEN m = fplll(&x, &U, B, DELTA, ETA, flag, p); if (m) return m; gerepileall(ltop, U? 2: 1, &x, &U); } return NULL; /* NOT REACHED */ } /********************************************************************/ /** **/ /** LLL OVER K[X] **/ /** **/ /********************************************************************/ static int pslg(GEN x) { long tx; if (gequal0(x)) return 2; tx = typ(x); return is_scalar_t(tx)? 3: lg(x); } static int REDgen(long k, long l, GEN h, GEN L, GEN B) { GEN q, u = gcoeff(L,k,l); long i; if (pslg(u) < pslg(B)) return 0; q = gneg(gdeuc(u,B)); gel(h,k) = gadd(gel(h,k), gmul(q,gel(h,l))); for (i=1; i 2) k--; } else { for (l=k-2; l>=1; l--) 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(DEBUGMEM>1) pari_warn(warnmem,"lllgramallgen"); gerepileall(av,3,&B,&L,&h); } } k=1; while (k 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)); } return R; } 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) { 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; } /* a1 x + a3 */ static GEN ellLHS0(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)); } static GEN ellLHS0_i(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 */ static GEN ellLHS(GEN e, GEN z) { GEN y = gel(z,2); return gmul(y, gadd(y, ellLHS0(e,gel(z,1)))); } /* 2y + a1 x + a3 */ static GEN d_ellLHS(GEN e, GEN z) { return gadd(ellLHS0(e, gel(z,1)), gmul2n(gel(z,2),1)); } /* return basic elliptic struct y[1..13], y[14] (domain type) and y[15] * (domain-specific data) are left uninitialized, from x[1], ..., x[5]. * Also allocate room for n dynamic members (actually stored in the last * component y[16])*/ static GEN initsmall(GEN x, long n) { GEN a1,a2,a3,a4,a6, b2,b4,b6,b8, c4,c6, D, j; GEN y = obj_init(15, n); switch(lg(x)) { case 1: case 2: case 4: case 5: pari_err_TYPE("ellxxx [not an elliptic curve (ell5)]",x); return NULL; break; /* not reached */ case 3: a1 = a2 = a3 = gen_0; a4 = gel(x,1); a6 = gel(x,2); b2 = gen_0; b4 = gmul2n(a4,1); b6 = gmul2n(a6,2); b8 = gneg(gsqr(a4)); c4 = gmulgs(a4,-48); c6 = gmulgs(a6,-864); D = gadd(gmul(gmulgs(a4,-64), gsqr(a4)), gmulsg(-432,gsqr(a6))); break; default: /* l > 5 */ { GEN a11, a13, a33, b22; a1 = gel(x,1); a2 = gel(x,2); a3 = gel(x,3); a4 = gel(x,4); a6 = gel(x,5); a11= gsqr(a1); b2 = gadd(a11, gmul2n(a2,2)); a13= gmul(a1, a3); b4 = gadd(a13, gmul2n(a4,1)); a33= gsqr(a3); b6 = gadd(a33, gmul2n(a6,2)); b8 = gsub(gadd(gmul(a11,a6), gmul(b6, a2)), gmul(a4, gadd(a4,a13))); b22= gsqr(b2); c4 = gadd(b22, gmulsg(-24,b4)); c6 = gadd(gmul(b2,gsub(gmulsg(36,b4),b22)), gmulsg(-216,b6)); D = gsub(gmul(b4, gadd(gmulsg(9,gmul(b2,b6)),gmulsg(-8,gsqr(b4)))), gadd(gmul(b22,b8),gmulsg(27,gsqr(b6)))); break; } } gel(y,1) = a1; gel(y,2) = a2; gel(y,3) = a3; gel(y,4) = a4; gel(y,5) = a6; gel(y,6) = b2; /* a1^2 + 4a2 */ gel(y,7) = b4; /* a1 a3 + 2a4 */ gel(y,8) = b6; /* a3^2 + 4 a6 */ gel(y,9) = b8; /* a1^2 a6 + 4a6 a2 + a2 a3^2 - a4(a4 + a1 a3) */ gel(y,10)= c4; /* b2^2 - 24 b4 */ gel(y,11)= c6; /* 36 b2 b4 - b2^3 - 216 b6 */ gel(y,12)= D; if (gequal0(D)) { gel(y, 13) = gen_0; return NULL; } if (typ(D) == t_POL && typ(c4) == t_POL && varn(D) == varn(c4)) { /* c4^3 / D, simplifying incrementally */ GEN g = RgX_gcd(D, c4); if (degpol(g) == 0) j = gred_rfrac_simple(gmul(gsqr(c4),c4), D); else { GEN d, c = RgX_div(c4, g); D = RgX_div(D, g); g = RgX_gcd(D,c4); if (degpol(g) == 0) j = gred_rfrac_simple(gmul(gsqr(c4),c), D); else { D = RgX_div(D, g); d = RgX_div(c4, g); g = RgX_gcd(D,c4); if (degpol(g)) { D = RgX_div(D, g); c4 = RgX_div(c4, g); } j = gred_rfrac_simple(gmul(gmul(c4, d),c), D); } } } else j = gdiv(gmul(gsqr(c4),c4), D); gel(y,13) = j; gel(y,16) = zerovec(n); return y; } void ellprint(GEN e) { pari_sp av = avma; long vx, vy; GEN z; 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))); (void)delete_var(); (void)delete_var(); avma = av; } /* compute a,b such that E1: y^2 = x(x-a)(x-b) ~ 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; 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) ) */ return mkvec2(a, b); } GEN ellR_ab(GEN E, long prec) { return obj_checkbuild_prec(E, R_AB, &doellR_ab, prec); } /* return x mod p */ static GEN padic_mod(GEN x) { return modii(gel(x,4), gel(x,2)); } /* a1, b1 are t_PADICs, a1/b1 = 1 (mod p) if p odd, (mod 2^4) otherwise. * Return u^2 = 1 / 4M2(a1,b1), where M2(A,B) = B AGM(sqrt(A/B),1)^2; M2(A,B) * is the common limit of (A_n, B_n), A_0 = A, B _0 = B; * A_{n+1} = (A_n + B_n + 2 B_{n+1}) / 4 * B_{n+1} = B_n sqrt(A_n / B_n) = the square root of A_n B_n congruent to B_n * Update (x,y) using p-adic Landen transform; if *pty = NULL, don't update y */ static GEN do_padic_agm(GEN *ptx, GEN *pty, GEN a1, GEN b1) { GEN bp = padic_mod(b1), x = *ptx; for(;;) { GEN p1, d, a = a1, b = b1; b1 = Qp_sqrt(gmul(a,b)); if (!b1) pari_err_PREC("p-adic AGM"); if (!equalii(padic_mod(b1), bp)) b1 = gneg_i(b1); a1 = gmul2n(gadd(gadd(a,b),gmul2n(b1,1)),-2); d = gsub(a1,b1); if (gequal0(d)) { *ptx = x; return ginv(gmul2n(a1,2)); } p1 = Qp_sqrt(gdiv(gadd(x,d),x)); /* = 1 (mod p) */ /* x_{n+1} = x_n ((1 + sqrt(1 + r_n/x_n)) / 2)^2 */ x = gmul(x, gsqr(gmul2n(gaddsg(1,p1),-1))); /* y_{n+1} = y_n / (1 - (r_n/4x_{n+1})^2) */ if (pty) *pty = gdiv(*pty, gsubsg(1, gsqr(gdiv(d,gmul2n(x,2))))); } } /* q a t_REAL*/ static long real_prec(GEN q) { return signe(q)? realprec(q): LONG_MAX; } /* q a t_PADIC */ static long padic_prec(GEN q) { return signe(gel(q,4))? precp(q)+valp(q): valp(q); } /* check whether moduli are consistent */ static void chk_p(GEN p, GEN p2) { if (!equalii(p, p2)) pari_err_MODULUS("ellinit", p,p2); } static long base_ring(GEN x, GEN *pp, long *prec) { long i, e = *prec, imax = minss(lg(x), 6); GEN p = NULL; long t = t_FRAC; if (*pp) switch(t = typ(*pp)) { case t_INT: if (cmpis(*pp,2) < 0) { t = t_FRAC; p = NULL; break; } p = *pp; t = t_INTMOD; break; case t_INTMOD: p = gel(*pp, 1); break; case t_REAL: e = real_prec(*pp); p = NULL; break; case t_PADIC: e = padic_prec(*pp); p = gel(*pp, 2); break; case t_FFELT: p = *pp; break; default: pari_err_TYPE("elliptic curve base_ring", *pp); return 0; } /* Possible cases: * t = t_FFELT (p t_FFELT) * t = t_INTMOD (p a prime) * t = t_PADIC (p a prime, e = padic prec) * t = t_REAL (p = NULL, e = real prec) * t = t_FRAC (p = NULL) */ for (i = 1; i < imax; i++) { GEN p2, q = gel(x,i); switch(typ(q)) { case t_PADIC: p2 = gel(q,2); switch(t) { case t_FRAC: t = t_PADIC; p = p2; break; case t_PADIC: chk_p(p,p2); break; default: pari_err_TYPE("elliptic curve base_ring", x); } e = minss(e, padic_prec(q)); break; case t_INTMOD: p2 = gel(q,1); switch(t) { case t_FRAC: t = t_INTMOD; p = p2; break; case t_FFELT: chk_p(FF_p_i(p),p2); break; case t_INTMOD:chk_p(p,p2); break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; case t_FFELT: switch(t) { case t_INTMOD: chk_p(p, FF_p_i(q)); /* fall through */ case t_FRAC: t = t_FFELT; p = q; break; case t_FFELT: if (!FF_samefield(p,q)) pari_err_MODULUS("ellinit", p,q); break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; case t_INT: case t_FRAC: break; case t_REAL: switch(t) { case t_REAL: e = minss(e, real_prec(q)); break; case t_FRAC: e = real_prec(q); t = t_REAL; break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; default: /* base ring too general */ return t_COMPLEX; } } *pp = p; *prec = e; return t; } 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); } 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); } 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); } 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); } 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); } 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; } GEN ellinit(GEN x, GEN p, long prec) { pari_sp av = avma; GEN y; switch(typ(x)) { case t_STR: x = gel(ellsearchcurve(x),2); break; case t_VEC: break; default: pari_err_TYPE("ellxxx [not an elliptic curve (ell5)]",x); } switch (base_ring(x, &p, &prec)) { case t_PADIC: y = ellinit_Qp(x, p, prec); break; case t_INTMOD: y = ellinit_Fp(x, p); break; case t_FFELT: y = ellinit_Fq(x, p); break; case t_FRAC: y = ellinit_Q(x, prec); break; case t_REAL: y = ellinit_Rg(x, 1, prec); break; default: y = ellinit_Rg(x, 0, prec); } if (!y) { avma = av; return cgetg(1,t_VEC); } return y; } /********************************************************************/ /** **/ /** COORDINATE CHANGE **/ /** Apply [u,r,s,t]. All coordch_* functions update E[1..14] only **/ /** and copy E[15] (type-specific data), E[16] (dynamic data) **/ /** verbatim **/ /** **/ /********************************************************************/ /* [1,0,0,0] */ static GEN init_ch(void) { return mkvec4(gen_1,gen_0,gen_0,gen_0); } static int is_trivial_change(GEN v) { GEN u, r, s, t; if (typ(v) == t_INT) return 1; u = gel(v,1); r = gel(v,2); s = gel(v,3); t = gel(v,4); return isint1(u) && isintzero(r) && isintzero(s) && isintzero(t); } /* compose coordinate changes, *vtotal = v is a ZV */ /* v = [u,0,0,0] o v, u t_INT */ static void composev_u(GEN *vtotal, GEN u) { GEN v = *vtotal; if (typ(v) == t_INT) *vtotal = mkvec4(u,gen_0,gen_0,gen_0); else if (!equali1(u)) { GEN U = gel(v,1); GEN uU = equali1(U)? u: mulii(u, U); gel(v,1) = uU; } } /* v = [1,r,0,0] o v, r t_INT */ static void composev_r(GEN *vtotal, GEN r) { GEN v = *vtotal; if (typ(v) == t_INT) *vtotal = mkvec4(gen_1,r,gen_0,gen_0); else if (signe(r)) { GEN U = gel(v,1), R = gel(v,2), S = gel(v,3), T = gel(v,4); GEN rU2 = equali1(U)? r: mulii(r, sqri(U)); gel(v,2) = addii(R, rU2); gel(v,4) = addii(T, mulii(rU2, S)); } } /* v = [1,0,s,0] o v, s t_INT */ static void composev_s(GEN *vtotal, GEN s) { GEN v = *vtotal; if (typ(v) == t_INT) *vtotal = mkvec4(gen_1,gen_0,s,gen_0); else if (signe(s)) { GEN U = gel(v,1), S = gel(v,3); GEN sU = equali1(U)? s: mulii(s,U); gel(v,3) = addii(S, sU); } } /* v = [1,0,0,t] o v, t t_INT */ static void composev_t(GEN *vtotal, GEN t) { GEN v = *vtotal; if (typ(v) == t_INT) *vtotal = mkvec4(gen_1,gen_0,gen_0,t); else if (signe(t)) { GEN U = gel(v,1), T = gel(v,4); GEN tU3 = equali1(U)? t: mulii(t, powiu(U,3)); gel(v,4) = addii(T, tU3); } } /* v = [1,0,s,t] o v, s,t t_INT */ static void composev_st(GEN *vtotal, GEN s, GEN t) { GEN v = *vtotal; if (typ(v) == t_INT) *vtotal = mkvec4(gen_1,gen_0,s,t); else if (!signe(t)) composev_s(vtotal, s); else if (!signe(s)) composev_t(vtotal, t); else { GEN U = gel(v,1), S = gel(v,3), T = gel(v,4); if (!equali1(U)) { GEN U3 = mulii(sqri(U), U); t = mulii(U3, t); s = mulii(U, s); } gel(v,3) = addii(S, s); gel(v,4) = addii(T, t); } } /* v = [1,r,s,t] o v, r,s,t t_INT */ static void composev_rst(GEN *vtotal, GEN r, GEN s, GEN t) { GEN v = *vtotal, U, R, S, T; if (typ(v) == t_INT) { *vtotal = mkvec4(gen_1,r,s,t); return; } if (!signe(r)) { composev_st(vtotal, s,t); return; } v = *vtotal; U = gel(v,1); R = gel(v,2); S = gel(v,3); T = gel(v,4); if (equali1(U)) t = addii(t, mulii(S, r)); else { GEN U2 = sqri(U); t = mulii(U2, addii(mulii(U, t), mulii(S, r))); r = mulii(U2, r); s = mulii(U, s); } gel(v,2) = addii(R, r); gel(v,3) = addii(S, s); gel(v,4) = addii(T, t); } /* Accumulate the effects of variable changes w o v, where * w = [u,r,s,t], *vtotal = v = [U,R,S,T]. No assumption on types */ static void gcomposev(GEN *vtotal, GEN w) { GEN v = *vtotal; GEN U2, U, R, S, T, u, r, s, t; if (typ(v) == t_INT) { *vtotal = w; return; } U = gel(v,1); R = gel(v,2); S = gel(v,3); T = gel(v,4); u = gel(w,1); r = gel(w,2); s = gel(w,3); t = gel(w,4); U2 = gsqr(U); gel(v,1) = gmul(U, u); gel(v,2) = gadd(R, gmul(U2, r)); gel(v,3) = gadd(S, gmul(U, s)); gel(v,4) = gadd(T, gmul(U2, gadd(gmul(U, t), gmul(S, r)))); } /* [u,r,s,t]^-1 = [ 1/u,-r/u^2,-s/u, (rs-t)/u^3 ] */ GEN ellchangeinvert(GEN w) { GEN u,r,s,t, u2,u3, U,R,S,T; if (typ(w) == t_INT) return w; u = gel(w,1); r = gel(w,2); s = gel(w,3); t = gel(w,4); u2 = gsqr(u); u3 = gmul(u2,u); U = ginv(u); R = gdiv(gneg(r), u2); S = gdiv(gneg(s), u); T = gdiv(gsub(gmul(r,s), t), u3); return mkvec4(U,R,S,T); } /* apply [u,0,0,0] */ static GEN coordch_u(GEN e, GEN u) { GEN y, u2, u3, u4, u6; long lx; if (gequal1(u)) return e; y = cgetg_copy(e, &lx); u2 = gsqr(u); u3 = gmul(u,u2); u4 = gsqr(u2); u6 = gsqr(u3); gel(y,1) = gdiv(ell_get_a1(e), u); gel(y,2) = gdiv(ell_get_a2(e), u2); gel(y,3) = gdiv(ell_get_a3(e), u3); gel(y,4) = gdiv(ell_get_a4(e), u4); gel(y,5) = gdiv(ell_get_a6(e), u6); if (lx == 6) return y; gel(y,6) = gdiv(ell_get_b2(e), u2); gel(y,7) = gdiv(ell_get_b4(e), u4); gel(y,8) = gdiv(ell_get_b6(e), u6); gel(y,9) = gdiv(ell_get_b8(e), gsqr(u4)); gel(y,10)= gdiv(ell_get_c4(e), u4); gel(y,11)= gdiv(ell_get_c6(e), u6); gel(y,12)= gdiv(ell_get_disc(e), gsqr(u6)); gel(y,13)= ell_get_j(e); gel(y,14)= gel(e,14); gel(y,15)= gel(e,15); gel(y,16)= gel(e,16); return y; } /* apply [1,r,0,0] */ static GEN coordch_r(GEN e, GEN r) { GEN a2, b4, b6, y, p1, r2, b2r, rx3; if (gequal0(r)) return e; y = leafcopy(e); a2 = ell_get_a2(e); rx3 = gmulsg(3,r); /* A2 = a2 + 3r */ gel(y,2) = gadd(a2,rx3); /* A3 = a1 r + a3 */ gel(y,3) = ellLHS0(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); if (lg(y) == 6) return y; b4 = ell_get_b4(e); b6 = ell_get_b6(e); /* B2 = 12r + b2 */ gel(y,6) = gadd(ell_get_b2(e),gmul2n(rx3,2)); b2r = gmul(r, ell_get_b2(e)); r2 = gsqr(r); /* B4 = 6r^2 + b2 r + b4 */ gel(y,7) = gadd(b4,gadd(b2r, gmulsg(6,r2))); /* B6 = 4r^3 + 2b2 r^2 + 2b4 r + b6 */ gel(y,8) = gadd(b6,gmul(r,gadd(gmul2n(b4,1), gadd(b2r,gmul2n(r2,2))))); /* B8 = 3r^4 + b2 r^3 + 3b4 r^2 + 3b6 r + b8 */ p1 = gadd(gmulsg(3,b4),gadd(b2r, gmulsg(3,r2))); gel(y,9) = gadd(ell_get_b8(e), gmul(r,gadd(gmulsg(3,b6), gmul(r,p1)))); return y; } /* apply [1,0,s,0] */ static GEN coordch_s(GEN e, GEN s) { GEN a1, y; if (gequal0(s)) return e; a1 = ell_get_a1(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = gadd(a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = gsub(ell_get_a2(e),gmul(s,gadd(a1,s))); /* A4 = a4 - s a3 */ gel(y,4) = gsub(ell_get_a4(e),gmul(s,ell_get_a3(e))); return y; } /* apply [1,0,0,t] */ static GEN coordch_t(GEN e, GEN t) { GEN a1, a3, y; if (gequal0(t)) return e; a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A3 = 2t + a3 */ gel(y,3) = gadd(a3, gmul2n(t,1)); /* A4 = a4 - a1 t */ gel(y,4) = gsub(ell_get_a4(e), gmul(t,a1)); /* A6 = a6 - t(t + a3) */ gel(y,5) = gsub(ell_get_a6(e), gmul(t,gadd(t, a3))); return y; } /* apply [1,0,s,t] */ static GEN coordch_st(GEN e, GEN s, GEN t) { GEN y, a1, a3; if (gequal0(s)) return coordch_t(e, t); if (gequal0(t)) return coordch_s(e, s); a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = gadd(a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = gsub(ell_get_a2(e),gmul(s,gadd(a1,s))); /* A3 = 2t + a3 */ gel(y,3) = gadd(a3,gmul2n(t,1)); /* A4 = a4 - (a1 t + s (2t + a3)) */ gel(y,4) = gsub(ell_get_a4(e),gadd(gmul(t,a1),gmul(s,gel(y,3)))); /* A6 = a6 - t(t + a3) */ gel(y,5) = gsub(ell_get_a6(e), gmul(t,gadd(t, a3))); return y; } /* apply [1,r,s,t] */ static GEN coordch_rst(GEN e, GEN r, GEN s, GEN t) { e = coordch_r(e, r); return coordch_st(e, s, t); } /* apply w = [u,r,s,t] */ static GEN coordch(GEN e, GEN w) { if (typ(w) == t_INT) return e; e = coordch_rst(e, gel(w,2), gel(w,3), gel(w,4)); return coordch_u(e, gel(w,1)); } /* the ch_* routines update E[14] (type), E[15] (type specific data), E[16] * (dynamic data) */ static GEN ch_Qp(GEN E, GEN e, GEN w) { GEN S, p = ellQp_get_zero(E), u2 = NULL, u = gel(w,1), r = gel(w,2); long prec = valp(p); if (base_ring(E, &p, &prec) != t_PADIC) return ellinit(E, p, prec); if ((S = obj_check(e, Qp_ROOT))) { if (!u2) u2 = gsqr(u); obj_insert_shallow(E, Qp_ROOT, gdiv(gsub(S, r), u2)); } if ((S = obj_check(e, Qp_TATE))) { GEN U2 = gel(S,1), U = gel(S,2), Q = gel(S,3), AB = gel(S,4); if (!u2) u2 = gsqr(u); U2 = gmul(U2, u2); U = gmul(U, u); AB = gdiv(AB, u2); obj_insert_shallow(E, Qp_TATE, mkvec4(U2,U,Q,AB)); } return E; } /* common to Q and Rg */ static GEN ch_R(GEN E, GEN e, GEN w) { GEN S, u = gel(w,1), r = gel(w,2); if ((S = obj_check(e, R_PERIODS))) obj_insert(E, R_PERIODS, gmul(S, u)); if ((S = obj_check(e, R_ETA))) obj_insert(E, R_ETA, gmul(S, u)); if ((S = obj_check(e, R_ROOTS))) { GEN ro = cgetg(4, t_VEC), u2 = gsqr(u); long i; for (i = 1; i <= 3; i++) gel(ro,i) = gdiv(gsub(gel(S,i), r), u2); obj_insert(E, R_ROOTS, ro); } return E; } static GEN ch_Rg(GEN E, GEN e, GEN w) { GEN p = NULL; long prec = ellR_get_prec(E); if (base_ring(E, &p, &prec) != t_REAL) return ellinit(E, p, prec); ch_R(E, e, w); return E; } static GEN ch_Q(GEN E, GEN e, GEN w) { long prec = ellR_get_prec(E); GEN S, v = NULL, p = NULL; if (base_ring(E, &p, &prec) != t_FRAC) return ellinit(E, p, prec); ch_R(E, e, w); if ((S = obj_check(e, Q_GROUPGEN))) S = obj_insert_shallow(E, Q_GROUPGEN, ellchangepoint(S, w)); if ((S = obj_check(e, Q_MINIMALMODEL))) { if (lg(S) == 2) { /* model was minimal */ if (!is_trivial_change(w)) /* no longer minimal */ S = mkvec3(gel(S,1), ellchangeinvert(w), e); (void)obj_insert_shallow(E, Q_MINIMALMODEL, S); } else { v = gel(S,2); if (gequal(v, w) || (is_trivial_change(v) && is_trivial_change(w))) S = mkvec(gel(S,1)); /* now minimal */ else { w = ellchangeinvert(w); gcomposev(&w, v); v = w; S = leafcopy(S); /* don't modify S in place: would corrupt e */ gel(S,2) = v; } (void)obj_insert_shallow(E, Q_MINIMALMODEL, S); } } if ((S = obj_check(e, Q_GLOBALRED))) S = obj_insert_shallow(E, Q_GLOBALRED, S); if ((S = obj_check(e, Q_ROOTNO))) S = obj_insert_shallow(E, Q_ROOTNO, S); return E; } static void ch_FF(GEN E, GEN e, GEN w) { GEN S; if ((S = obj_check(e, FF_CARD))) S = obj_insert_shallow(E, FF_CARD, S); if ((S = obj_check(e, FF_GROUP))) S = obj_insert_shallow(E, FF_GROUP, S); if ((S = obj_check(e, FF_GROUPGEN))) S = obj_insert_shallow(E, FF_GROUPGEN, ellchangepoint(S, w)); if ((S = obj_check(e, FF_O))) S = obj_insert_shallow(E, FF_O, S); } /* FF_CARD, FF_GROUP, FF_O are invariant */ static GEN ch_Fp(GEN E, GEN e, GEN w) { long prec = 0; GEN p = ellff_get_field(E); if (base_ring(E, &p, &prec) != t_INTMOD) return ellinit(E, p, prec); gel(E,15) = mkvec2(p, ell_to_a4a6_bc(E, p)); ch_FF(E, e, w); return E; } static GEN ch_Fq(GEN E, GEN e, GEN w) { long prec = 0; GEN p = ellff_get_field(E); if (base_ring(E, &p, &prec) != t_FFELT) return ellinit(E, p, prec); gel(E,15) = FF_elldata(E, p); ch_FF(E, e, w); return E; } static void ell_reset(GEN E) { gel(E,16) = zerovec(lg(gel(E,16))-1); } GEN ellchangecurve(GEN e, GEN w) { pari_sp av = avma; GEN E; checkell5(e); if (equali1(w)) return gcopy(e); checkcoordch(w); E = coordch(leafcopy(e), w); if (lg(E) != 6) { ell_reset(E); switch(ell_get_type(E)) { case t_ELL_Qp: E = ch_Qp(E,e,w); break; case t_ELL_Fp: E = ch_Fp(E,e,w); break; case t_ELL_Fq: E = ch_Fq(E,e,w); break; case t_ELL_Q: E = ch_Q(E,e,w); break; case t_ELL_Rg: E = ch_Rg(E,e,w); break; } } return gerepilecopy(av, E); } static void E_compose_u(GEN *vtotal, GEN *e, GEN u) {*e=coordch_u(*e,u); composev_u(vtotal,u);} static void E_compose_r(GEN *vtotal, GEN *e, GEN r) {*e=coordch_r(*e,r); composev_r(vtotal,r);} #if 0 static void E_compose_s(GEN *vtotal, GEN *e, GEN s) {*e=coordch_s(*e,s); composev_s(vtotal,s);} #endif static void E_compose_t(GEN *vtotal, GEN *e, GEN t) {*e=coordch_t(*e,t); composev_t(vtotal,t);} 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 ellchangepoint0(GEN P, GEN v2, GEN v3, GEN r, GEN s, GEN t) { GEN a, x, y; if (ell_is_inf(P)) return P; x = gel(P,1); y = gel(P,2); a = gsub(x,r); retmkvec2(gmul(v2, a), gmul(v3, gsub(y, gadd(gmul(s,a),t)))); } GEN ellchangepoint(GEN x, GEN ch) { GEN y, v, v2, v3, r, s, t, u; long tx, i, lx = lg(x); pari_sp av = avma; if (typ(x) != t_VEC) pari_err_TYPE("ellchangepoint",x); if (equali1(ch)) return gcopy(x); checkcoordch(ch); if (lx == 1) return cgetg(1, t_VEC); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = ginv(u); v2 = gsqr(v); v3 = gmul(v,v2); tx = typ(gel(x,1)); if (is_matvec_t(tx)) { y = cgetg(lx,tx); for (i=1; i e) e = f; } return e; } /* Exactness of lhs and rhs in the following depends in non-obvious ways * on the coeffs of the curve as well as on the components of the point z. * Thus if e is exact, with a1==0, and z has exact y coordinate only, the * lhs will be exact but the rhs won't. */ int oncurve(GEN e, GEN z) { GEN LHS, RHS, x; long pl, pr, ex, expx; pari_sp av; checkellpt(z); if (ell_is_inf(z)) return 1; /* oo */ av = avma; LHS = ellLHS(e,z); RHS = ellRHS(e,gel(z,1)); x = gsub(LHS,RHS); if (gequal0(x)) { avma = av; return 1; } pl = precision(LHS); pr = precision(RHS); if (!pl && !pr) { avma = av; return 0; } /* both of LHS, RHS are exact */ /* at least one of LHS,RHS is inexact */ ex = pr? gexpo(RHS): gexpo(LHS); /* don't take exponent of exact 0 */ if (!pr || (pl && pl < pr)) pr = pl; /* min among nonzero elts of {pl,pr} */ expx = gexpo(x); pr = (expx < ex - prec2nbits(pr) + 15 || expx < ellexpo(e) - prec2nbits(pr) + 5); avma = av; return pr; } GEN ellisoncurve(GEN e, GEN x) { long i, tx = typ(x), lx; checkell5(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)); if (is_vec_t(tx)) { GEN z = cgetg(lx,tx); for (i=1; i= gexpo(y1)); else eq = gequal(y1,y2); if (!eq) { avma = av; return ellinf(); } } p2 = d_ellLHS(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)))); } else { p1 = gsub(y2,y1); p2 = gsub(x2,x1); } 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))); tetpil = avma; p1 = cgetg(3,t_VEC); gel(p1,1) = gcopy(x); gel(p1,2) = gneg(y); return gerepile(av,tetpil,p1); } static GEN ellneg_i(GEN e, GEN z) { GEN t; if (ell_is_inf(z)) return z; 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)))); return t; } GEN ellneg(GEN e, GEN z) { pari_sp av; GEN t, y; checkell5(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)))); gel(t,2) = gerepileupto(av, y); return t; } GEN ellsub(GEN e, GEN z1, GEN z2) { pari_sp av = avma; checkell5(e); checkellpt(z2); return gerepileupto(av, elladd(e, z1, ellneg_i(e,z2))); } /* E an ell, x a scalar */ 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; /* solve y*(y+b) = a */ if (gequal0(D)) { if (ell_get_type(E) == t_ELL_Fq && equaliu(ellff_get_p(E),2)) retmkvec( FF_sqrt(a) ); b = gneg_i(b); y = cgetg(2,t_VEC); gel(y,1) = gmul2n(b,-1); return gerepileupto(av,y); } /* D != 0 */ switch(ell_get_type(E)) { case t_ELL_Fp: /* imply p!=2 */ p = ellff_get_p(E); D = gel(D,2); if (kronecker(D, p) < 0) { avma = av; return cgetg(1,t_VEC); } d = Fp_sqrt(D, p); break; case t_ELL_Fq: if (equaliu(ellff_get_p(E),2)) { GEN F = FFX_roots(mkpoln(3, gen_1, b, a), D); if (lg(F) == 1) { avma = av; return cgetg(1,t_VEC); } return gerepileupto(av, F); } if (!FF_issquareall(D,&d)) { avma = av; return cgetg(1,t_VEC); } break; case t_ELL_Q: if (typ(x) == t_COMPLEX) { d = gsqrt(D, prec); break; } if (!issquareall(D,&d)) { avma = av; return cgetg(1,t_VEC); } break; case t_ELL_Qp: p = ellQp_get_p(E); D = cvtop(D, p, ellQp_get_prec(E)); if (!issquare(D)) { avma = av; return cgetg(1,t_VEC); } d = Qp_sqrt(D); break; default: d = gsqrt(D,prec); } a = gsub(d,b); y = cgetg(3,t_VEC); gel(y,1) = gmul2n(a, -1); gel(y,2) = gsub(gel(y,1),d); return gerepileupto(av,y); } GEN ellordinate(GEN e, GEN x, long prec) { checkell(e); if (is_matvec_t(typ(x))) { long i, lx; GEN v = cgetg_copy(x, &lx); for (i=1; i>1)-4)>>2; z1 = ellwpseries(e, 0, ln); z2 = gsubst(z1, 0, monomial(n, 1, 0)); p0 = gen_0; p1 = gen_1; q0 = gen_1; q1 = gen_0; do { GEN p2,q2, ss = gen_0; do { ep = (-valp(z2)) >> 1; ss = gadd(ss, gmul(gel(z2,2), monomial(gen_1, ep, 0))); z2 = gsub(z2, gmul(gel(z2,2), gpowgs(z1, ep))); } while (valp(z2) <= 0); p2 = gadd(p0, gmul(ss,p1)); p0 = p1; p1 = p2; q2 = gadd(q0, gmul(ss,q1)); q0 = q1; q1 = q2; if (!signe(z2)) break; z2 = ginv(z2); } while (degpol(p1) < vn); if (degpol(p1) > vn || signe(z2)) pari_err_TYPE("ellmul [not a complex multiplication]", n); q1p = RgX_deriv(q1); b2ov12 = gdivgs(ell_get_b2(e), 12); /* x - b2/12 */ grdx = gadd(gel(z,1), b2ov12); q1 = poleval(q1, grdx); if (gequal0(q1)) return ellinf(); p1p = RgX_deriv(p1); p1 = poleval(p1, grdx); p1p = poleval(p1p, grdx); q1p = poleval(q1p, grdx); 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)); return mkvec2(x, gmul2n(y,-1)); } static GEN _sqr(void *e, GEN x) { return elladd((GEN)e, x, x); } static GEN _mul(void *e, GEN x, GEN y) { return elladd((GEN)e, x, y); } static GEN ellffmul(GEN E, GEN P, GEN n) { GEN fg = ellff_get_field(E); if (typ(fg)==t_FFELT) return FF_ellmul(E, P, n); else { pari_sp av = avma; GEN p = fg, e = ellff_get_a4a6(E), Q; GEN Pp = FpE_changepointinv(RgE_to_FpE(P, p), gel(e,3), p); GEN Qp = FpE_mul(Pp, n, gel(e,1), p); Q = FpE_to_mod(FpE_changepoint(Qp, gel(e,3), p), p); return gerepileupto(av, Q); } } /* [n] z, n integral */ static GEN 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); s = signe(n); if (!s) return ellinf(); if (s < 0) z = ellneg_i(e,z); if (is_pm1(n)) return z; return gen_pow(z, n, (void*)e, &_sqr, &_mul); } /* x a t_REAL, try to round it to an integer */ enum { OK, LOW_PREC, NO }; static long myroundr(GEN *px) { GEN x = *px; long e; if (bit_prec(x) - expo(x) < 5) return LOW_PREC; *px = grndtoi(x, &e); if (e >= -5) return NO; return OK; } /* E has CM by Q, t_COMPLEX or t_QUAD. Return q such that E has CM by Q/q * or gen_1 (couldn't find q > 1) * or NULL (doesn't have CM by Q) */ static GEN CM_factor(GEN E, GEN Q) { GEN w, tau, D, v, x, y, F, dF, q, r, fk, fkb, fkc; long prec; if (ell_get_type(E) != t_ELL_Q) return gen_1; switch(typ(Q)) { case t_COMPLEX: D = utoineg(4); v = gel(Q,2); break; case t_QUAD: D = quad_disc(Q); v = gel(Q,3); break; default: return NULL; /*-Wall*/ } /* disc Q = v^2 D, D < 0 fundamental */ w = ellR_omega(E, DEFAULTPREC + nbits2nlong(expi(D))); tau = gdiv(gel(w,2), gel(w,1)); prec = precision(tau); /* disc tau = -4 k^2 (Im tau)^2 for some integral k * Assuming that E has CM by Q, then disc Q / disc tau = f^2 is a square. * Compute f*k */ x = gel(tau,1); y = gel(tau,2); /* tau = x + Iy */ fk = gmul(gdiv(v, gmul2n(y, 1)), sqrtr_abs(itor(D, prec))); switch(myroundr(&fk)) { case NO: return NULL; case LOW_PREC: return gen_1; } fk = absi(fk); fkb = gmul(fk, gmul2n(x,1)); switch(myroundr(&fkb)) { case NO: return NULL; case LOW_PREC: return gen_1; } fkc = gmul(fk, cxnorm(tau)); switch(myroundr(&fkc)) { case NO: return NULL; case LOW_PREC: return gen_1; } /* tau is a root of fk (X^2 - b X + c) \in Z[X], */ F = Q_primpart(mkvec3(fk, fkb, fkc)); dF = qfb_disc(F); /* = disc tau, E has CM by orders of disc dF q^2, all q */ q = dvmdii(dF, D, &r); if (r != gen_0 || !Z_issquareall(q, &q)) return NULL; /* disc(Q) = disc(tau) (v / q)^2 */ v = dvmdii(absi(v), q, &r); if (r != gen_0) return NULL; return is_pm1(v)? gen_1: v; /* E has CM by Q/q: [Q] = [q] o [Q/q] */ } /* [a + w] z, a integral, w pure imaginary */ 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); q = CM_factor(e, w); if (!q) pari_err_TYPE("ellmul [not a complex multiplication]",w); if (q != gen_1) w = gdiv(w, q); /* compute [a + q w] z, z has CM by w */ if (typ(w) == t_QUAD && is_pm1(gel(gel(w,1), 3))) { /* replace w by w - u, u in Z, so that N(w-u) is minimal * N(w - u) = N w - Tr w u + u^2, minimal for u = Tr w / 2 */ GEN u = gtrace(w); if (typ(u) != t_INT) pari_err_TYPE("ellmul_CM",w); u = shifti(u, -1); if (signe(u)) { w = gsub(w, u); a = addii(a, mulii(q,u)); } /* [a + w]z = [(a + qu)] z + [q] [(w - u)] z */ } A = ellmul_Z(e,z,a); B = ellmul_CM(e,z,w); if (q != gen_1) B = ellmul_Z(e, B, q); return elladd(e, A, B); } GEN ellmul(GEN e, GEN z, GEN n) { pari_sp av = avma; checkell5(e); checkellpt(z); if (ell_is_inf(z)) return ellinf(); switch(typ(n)) { case t_INT: return gerepilecopy(av, ellmul_Z(e,z,n)); case t_QUAD: { GEN pol = gel(n,1), a = gel(n,2), b = gel(n,3); if (signe(gel(pol,2)) < 0) pari_err_TYPE("ellmul_CM",n); /* disc > 0 ? */ return gerepileupto(av, ellmul_CM_aux(e,z,a,mkquad(pol, gen_0,b))); } case t_COMPLEX: { GEN a = gel(n,1), b = gel(n,2); return gerepileupto(av, ellmul_CM_aux(e,z,a,mkcomplex(gen_0,b))); } } pari_err_TYPE("ellmul (non integral, non CM exponent)",n); return NULL; /* not reached */ } /********************************************************************/ /** **/ /** Periods **/ /** **/ /********************************************************************/ /* References: The complex AGM, periods of elliptic curves over C and complex elliptic logarithms John E. Cremona, Thotsaphon Thongjunthug, arXiv:1011.0914 */ static GEN ellomega_agm(GEN a, GEN b, GEN c, long prec) { GEN pi = mppi(prec), mIpi = mkcomplex(gen_0, negr(pi)); GEN Mac = agm(a,c,prec), Mbc = agm(b,c,prec); retmkvec2(gdiv(pi, Mac), gdiv(mIpi, Mbc)); } static GEN 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); return gerepileupto(av, ellomega_agm(a,b,c,prec)); } /* return [w1,w2] for E / R; w1 > 0 is real. * If e.disc > 0, w2 = -I r; else w2 = w1/2 - I r, for some real r > 0. * => tau = w1/w2 is in upper half plane */ static GEN doellR_omega(GEN E, long prec) { pari_sp av = avma; GEN roots, e1, e3, 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*/ a = gel(z,1); /* >= 0 */ b = gel(z,2); c = gabs(z, prec); z = ellomega_agm(a,b,c,prec); return gerepilecopy(av, mkvec2(gel(z,1),gmul2n(gadd(gel(z,1),gel(z,2)),-1))); } static GEN doellR_eta(GEN E, long prec) { GEN w = ellR_omega(E, prec); return elleta(w, prec); } GEN ellR_omega(GEN E, long prec) { return obj_checkbuild_prec(E, R_PERIODS, &doellR_omega, prec); } GEN ellR_eta(GEN E, long prec) { return obj_checkbuild_prec(E, R_ETA, &doellR_eta, prec); } GEN ellR_roots(GEN E, long prec) { return obj_checkbuild_prec(E, R_ROOTS, &doellR_roots, prec); } /********************************************************************/ /** **/ /** ELLIPTIC FUNCTIONS **/ /** **/ /********************************************************************/ /* P = [x,0] is 2-torsion on y^2 = g(x). Return w1/2, (w1+w2)/2, or w2/2 * depending on whether x is closest to e1,e2, or e3, the 3 complex root of g */ static GEN zell_closest_0(GEN om, GEN x, GEN ro) { GEN e1 = gel(ro,1), e2 = gel(ro,2), e3 = gel(ro,3); GEN d1 = gnorm(gsub(x,e1)); GEN d2 = gnorm(gsub(x,e2)); GEN d3 = gnorm(gsub(x,e3)); GEN z = gel(om,2); if (gcmp(d1, d2) <= 0) { if (gcmp(d1, d3) <= 0) z = gel(om,1); } else { if (gcmp(d2, d3)<=0) z = gadd(gel(om,1),gel(om,2)); } return gmul2n(z, -1); } 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); if (gequal0(y0)) return zell_closest_0(ellomega_cx(E,prec),x0,roots); 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 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); /* |a+b| < |a-b| */ if (gcmp(gmul(ar,br), gneg(gmul(ai,bi))) < 0) b = gneg(b); return zellagmcx(a,b,r,t,prec); } } /* Assume E/R, disc E < 0, and P \in E(R) ==> z \in R */ static GEN zellrealneg(GEN E, GEN P, long prec) { GEN x0 = gel(P,1), y0 = d_ellLHS(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 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)); GEN r2 = ginv(gsqrt(gaddsg(1,gdiv(gmul(ai,zi),gmul(ar,zr))),prec)); return zellagmcx(ar,gabs(a,prec),r2,gmul(t,r2),prec); } } /* Assume E/R, disc E > 0, and P \in E(R) */ 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); 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)); return zellagmcx(a,b,r,t,prec); } else { GEN om = ellR_omega(E,prec); GEN r = gdiv(a,gsqrt(gsub(e1,x0),prec)); GEN t = gdiv(gmul(r,y0),gmul2n(gsub(x0,e3),1)); return gsub(zellagmcx(a,b,r,t,prec),gmul2n(gel(om,2),-1)); } } /* Let T = 4x^3 + b2 x^2 + 2b4 x + b6, where T has a unique p-adic root 'a'. * Return a lift of a to padic accuracy prec. We have * 216 T = 864 X^3 - 18 c4X - c6, where X = x + b2/12 */ static GEN doellQp_root(GEN E, long prec) { GEN c4=ell_get_c4(E), c6=ell_get_c6(E), j=ell_get_j(E), p=ellQp_get_p(E); GEN c4p, c6p, T, a, pe; long alpha; int pis2 = equaliu(p, 2); if (Q_pval(j, p) >= 0) pari_err_DOMAIN(".root", "v_p(j)", ">=", gen_0, j); /* v(j) < 0 => v(c4^3) = v(c6^2) = 2 alpha */ alpha = Q_pvalrem(ell_get_c4(E), p, &c4) >> 1; if (alpha) (void)Q_pvalrem(ell_get_c6(E), p, &c6); /* Renormalized so that v(c4) = v(c6) = 0; multiply by p^alpha at the end */ if (prec < 4 && pis2) prec = 4; pe = powiu(p, prec); c4 = Rg_to_Fp(c4, pe); c4p = remii(c4,p); c6 = Rg_to_Fp(c6, pe); c6p = remii(c6,p); if (pis2) { /* Use 432T(X/4) = 27X^3 - 9c4 X - 2c6 to have integral root; a=0 mod 2 */ T = mkpoln(4, utoipos(27), gen_0, Fp_muls(c4, -9, pe), Fp_muls(c6, -2, pe)); a = ZpX_liftroot(T, gen_0, p, prec); alpha -= 2; } else if (equaliu(p, 3)) { /* Use 216T(X/3) = 32X^3 - 6c4 X - c6 to have integral root; a=-c6 mod 3 */ a = Fp_neg(c6p, p); T = mkpoln(4, utoipos(32), gen_0, Fp_muls(c4, -6, pe), Fp_neg(c6, pe)); a = ZX_Zp_root(T, a, p, prec); switch(lg(a)-1) { case 1: /* single root */ a = gel(a,1); break; case 3: /* three roots, e.g. "15a1", choose the right one */ { GEN a1 = gel(a,1), a2 = gel(a,2), a3 = gel(a,3); long v1 = Z_lval(subii(a2, a3), 3); long v2 = Z_lval(subii(a1, a3), 3); long v3 = Z_lval(subii(a1, a2), 3); if (v1 == v2) a = a3; else if (v1 == v3) a = a2; else a = a1; } break; } alpha--; } else { /* p != 2,3: T = 4(x-a)(x-b)^2 = 4x^3 - 3a^2 x - a^3 when b = -a/2 * (so that the trace coefficient vanishes) => a = c6/6c4 (mod p)*/ a = Fp_div(c6p, Fp_mulu(c4p, 6, p), p); T = mkpoln(4, utoipos(864), gen_0, Fp_muls(c4, -18, pe), Fp_neg(c6, pe)); a = ZpX_liftroot(T, a, p, prec); } a = cvtop(a, p, prec); if (alpha) setvalp(a, valp(a)+alpha); return gsub(a, gdivgs(ell_get_b2(E), 12)); } GEN ellQp_root(GEN E, long prec) { return obj_checkbuild_padicprec(E, Qp_ROOT, &doellQp_root, prec); } /* compute a,b such that E1: y^2 = x(x-a)(x-b) ~ E */ static void doellQp_ab(GEN E, GEN *pta, GEN *ptb, long prec) { GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), e1 = ellQp_root(E, prec); GEN w, t = gadd(gdivgs(b2,4), gmulsg(3,e1)); w = Qp_sqrt(gmul2n(gadd(b4,gmul(e1,gadd(b2,gmulsg(6,e1)))),1)); if (valp(gadd(t,w)) <= valp(w)) w = gneg_i(w); /* <=> v(d) > v(w) */ /* w^2 = 2b4 + 2b2 e1 + 12 e1^2 = 4(e1-e2)(e1-e3) */ *pta = gmul2n(gsub(w,t),-2); *ptb = gmul2n(w,-1); } static GEN doellQp_Tate_uniformization(GEN E, long prec0) { GEN p = ellQp_get_p(E), j = ell_get_j(E); GEN u, u2, q, x1, a, b, d, s, t; long v, prec = prec0+2; if (Q_pval(j, p) >= 0) pari_err_DOMAIN(".tate", "v_p(j)", ">=", gen_0, j); START: doellQp_ab(E, &a, &b, prec); d = gsub(a,b); v = prec0 - precp(d); if (v > 0) { prec += v; goto START; } x1 = gmul2n(d,-2); u2 = do_padic_agm(&x1,NULL,a,b); t = gaddsg(1, ginv(gmul2n(gmul(u2,x1),1))); s = Qp_sqrt(gsubgs(gsqr(t), 1)); q = gadd(t,s); if (gequal0(q)) q = gsub(t,s); v = prec0 - precp(q); if (v > 0) { prec += v; goto START; } if (valp(q) < 0) q = ginv(q); if (issquare(u2)) 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); } return mkvec4(u2, u, q, mkvec2(a, b)); } GEN ellQp_Tate_uniformization(GEN E, long prec) {return obj_checkbuild_padicprec(E,Qp_TATE,&doellQp_Tate_uniformization,prec);} GEN ellQp_u(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,2); } GEN ellQp_u2(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,1); } GEN ellQp_q(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,3); } GEN ellQp_ab(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,4); } static GEN zellQp(GEN E, GEN z, long prec) { pari_sp av = avma; GEN b2, a, b, ab, c0, r0, r1, ar1, e1, x, y, delta, x0,x1, y0,y1, t; if (ell_is_inf(z)) return gen_1; b2 = ell_get_b2(E); e1 = ellQp_root(E, prec); ab = ellQp_ab(E, prec); a = gel(ab,1); b = gel(ab,2); r1 = gsub(a,b); x = gel(z,1); y = gel(z,2); r0 = gadd(e1,gmul2n(b2,-2)); 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)))); 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))))); if (gequal0(x1)) pari_err_PREC("ellpointtoz"); (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)); return gerepileupto(av, t); } 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 = = w2 <1,tau> */ GEN W1,W2,Tau; /* new basis for L = = 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, lim = stack_lim(av, 1); 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 (low_stack(lim, stack_lim(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; case t_QUAD: z = isexactzero(gel(z,2))? gel(z,1): quadtofp(z, T->prec); break; default: pari_err_TYPE("reduction mod 2-dim lattice (reduce_z)", z); } T->z = z; Z = gdiv(z, T->W2); T->x = ground(gdiv(imag_i(Z), imag_i(T->Tau))); if (signe(T->x)) Z = gsub(Z, gmul(T->x,T->Tau)); T->y = ground(real_i(Z)); if (signe(T->y)) Z = gsub(Z, T->y); if (typ(Z) != t_COMPLEX) T->some_z_is_real = T->abs_u_is_1 = 1; else if (typ(z) != t_COMPLEX) T->some_z_is_real = 1; else if (isexactzero(gel(z,1)) || isexactzero(gel(Z,1))) T->some_z_is_pure_imag = 1; p = precision(Z); if (gequal0(Z) || (p && gexpo(Z) < 5 - prec2nbits(p))) Z = NULL; /*z in L*/ if (p && p < T->prec) T->prec = p; T->Z = Z; } /* return x.eta1 + y.eta2 */ static GEN eta_correction(ellred_t *T, GEN eta) { GEN y1 = NULL, y2 = NULL; if (signe(T->x)) y1 = gmul(T->x, gel(eta,1)); if (signe(T->y)) y2 = gmul(T->y, gel(eta,2)); if (!y1) return y2? y2: gen_0; return y2? gadd(y1, y2): y1; } /* e is either * - [w1,w2] * - [[w1,w2],[eta1,eta2]] * - an ellinit structure */ static void compute_periods(ellred_t *T, GEN z, long prec) { GEN w, e; T->q_is_real = 0; T->some_q_is_real = 0; switch(T->type) { case t_PER_ELL: { long pr, p = prec; if (z && (pr = precision(z))) p = pr; e = T->in; w = ellR_omega(e, p); T->some_q_is_real = T->q_is_real = 1; break; } case t_PER_W: w = T->in; break; default: /*t_PER_WETA*/ w = gel(T->in,1); break; } T->w1 = gel(w,1); T->w2 = gel(w,2); red_modSL2(T, prec); if (z) reduce_z(z, T); } static int check_periods(GEN e, ellred_t *T) { GEN w1; if (typ(e) != t_VEC) return 0; T->in = e; switch(lg(e)) { case 17: T->type = t_PER_ELL; break; case 3: w1 = gel(e,1); if (typ(w1) != t_VEC) T->type = t_PER_W; else { if (lg(w1) != 3) return 0; T->type = t_PER_WETA; } break; default: return 0; } return 1; } static int get_periods(GEN e, GEN z, ellred_t *T, long prec) { if (!check_periods(e, T)) return 0; compute_periods(T, z, prec); return 1; } /* 2iPi/x, more efficient when x pure imaginary */ static GEN PiI2div(GEN x, long prec) { return gdiv(Pi2n(1, prec), mulcxmI(x)); } /* exp(I x y), more efficient for x in R, y pure imaginary */ GEN expIxy(GEN x, GEN y, long prec) { return gexp(gmul(x, mulcxI(y)), prec); } static GEN check_real(GEN q) { return (typ(q) == t_COMPLEX && gequal0(gel(q,2)))? gel(q,1): q; } /* Return E_k(tau). Slow if tau is not in standard fundamental domain */ static GEN trueE(GEN tau, long k, long prec) { pari_sp lim, av; GEN p1, q, y, qn; long n = 1; if (k == 2) return trueE2(tau, 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; 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(DEBUGMEM>1) pari_warn(warnmem,"elleisnum"); gerepileall(av, 2, &y,&qn); } } return gadd(gen_1, gmul(y, gdiv(gen_2, szeta(1-k, prec)))); } /* (2iPi/W2)^k E_k(W1/W2) */ static GEN _elleisnum(ellred_t *T, long k) { GEN y = trueE(T->Tau, k, T->prec); y = gmul(y, gpowgs(mulcxI(gdiv(Pi2n(1,T->prec), T->W2)),k)); return check_real(y); } /* Return (2iPi)^k E_k(L) = (2iPi/w2)^k E_k(tau), with L = , k > 0 even * E_k(tau) = 1 + 2/zeta(1-k) * sum(n>=1, n^(k-1) q^n/(1-q^n)) * If flag is != 0 and k=4 or 6, compute g2 = E4/12 or g3 = -E6/216 resp. */ GEN elleisnum(GEN om, long k, long flag, long prec) { pari_sp av = avma; GEN y; ellred_t T; if (k<=0) pari_err_DOMAIN("elleisnum", "k", "<=", gen_0, stoi(k)); if (k&1) pari_err_DOMAIN("elleisnum", "k % 2", "!=", gen_0, stoi(k)); if (!get_periods(om, NULL, &T, prec)) pari_err_TYPE("elleisnum",om); y = _elleisnum(&T, k); if (k==2 && signe(T.c)) { GEN a = gmul(Pi2n(1,T.prec), mului(12, T.c)); y = gsub(y, mulcxI(gdiv(a, gmul(T.w2, T.W2)))); } else if (k==4 && flag) y = gdivgs(y, 12); else if (k==6 && flag) y = gdivgs(y,-216); return gerepileupto(av,y); } /* return quasi-periods associated to [T->W1,T->W2] */ static GEN _elleta(ellred_t *T) { GEN y1, y2, e2 = gdivgs(_elleisnum(T,2), 12); y2 = gmul(T->W2, e2); y1 = gadd(PiI2div(T->W2, T->prec), gmul(T->W1,e2)); retmkvec2(gneg(y1), gneg(y2)); } /* compute eta1, eta2 */ GEN elleta(GEN om, long prec) { pari_sp av = avma; GEN y1, y2, E2, pi; ellred_t T; if (!check_periods(om, &T)) pari_err_TYPE("elleta",om); if (T.type == t_PER_ELL) return ellR_eta(om, prec); compute_periods(&T, NULL, prec); prec = T.prec; pi = mppi(prec); E2 = trueE2(T.Tau, prec); /* E_2(Tau) */ if (signe(T.c)) { GEN u = gdiv(T.w2, T.W2); /* E2 := u^2 E2 + 6iuc/pi = E_2(tau) */ E2 = gadd(gmul(gsqr(u), E2), mulcxI(gdiv(gmul(mului(6,T.c), u), pi))); } y2 = gdiv(gmul(E2, sqrr(pi)), gmulsg(3, T.w2)); if (T.swap) { y1 = y2; y2 = gadd(gmul(T.tau,y1), PiI2div(T.w2, prec)); } else y1 = gsub(gmul(T.tau,y2), PiI2div(T.w2, prec)); switch(typ(T.w1)) { case t_INT: case t_FRAC: case t_REAL: y1 = real_i(y1); } return gerepilecopy(av, mkvec2(y1,y2)); } GEN ellperiods(GEN w, long flag, long prec) { pari_sp av = avma; ellred_t T; if (!get_periods(w, NULL, &T, prec)) pari_err_TYPE("ellperiods",w); switch(flag) { case 0: return gerepilecopy(av, mkvec2(T.W1, T.W2)); case 1: return gerepilecopy(av, mkvec2(mkvec2(T.W1, T.W2), _elleta(&T))); default: pari_err_FLAG("ellperiods"); return NULL;/*not reached*/ } } /* 2Pi Im(z)/log(2) */ static double get_toadd(GEN z) { return (2*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' */ static GEN ellwpnum_all(GEN e, GEN z, long flall, long prec) { long toadd; pari_sp av = avma, lim, av1; GEN pi2, q, u, y, yp, u1, u2, qn; ellred_t T; int simple_case; if (!get_periods(e, z, &T, prec)) pari_err_TYPE("ellwp",e); if (!T.Z) return NULL; prec = T.prec; /* Now L,Z normalized to <1,tau>. Z in fund. domain of <1, tau> */ pi2 = Pi2n(1, prec); q = expIxy(pi2, T.Tau, prec); u = expIxy(pi2, T.Z, prec); u1 = gsubsg(1,u); u2 = gsqr(u1); /* (1-u)^2 = -4u sin^2(Pi Z) */ if (gequal0(u2)) return NULL; /* possible if loss of accuracy */ y = gdiv(u,u2); /* -1/4(sin^2(Pi Z)) */ if (T.abs_u_is_1) y = real_i(y); simple_case = T.abs_u_is_1 && T.q_is_real; y = gadd(mkfrac(gen_1, utoipos(12)), y); 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; 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 */ GEN yadd, ypadd = NULL; GEN qnu = gmul(qn,u); /* q^n u */ GEN a = gsubsg(1,qnu);/* 1 - q^n u */ GEN a2 = gsqr(a); /* (1 - q^n u)^2 */ if (yp) ypadd = gdiv(gaddsg(1,qnu),gmul(a,a2)); if (simple_case) { /* conj(u) = 1/u: formula simplifies */ yadd = gdiv(u, a2); yadd = gmul2n(real_i(yadd), 1); if (yp) ypadd = gmul2n(real_i(ypadd), 1); } else { GEN b = gsub(qn,u);/* q^n - u */ GEN b2 = gsqr(b); /* (q^n - u)^2 */ yadd = gmul(u, gadd(ginv(a2),ginv(b2))); if (yp) ypadd = gadd(ypadd, gdiv(gadd(qn,u),gmul(b,b2))); } yadd = gsub(yadd, gmul2n(ginv(gsqr(gsubsg(1,qn))), 1)); y = gadd(y, gmul(qn,yadd)); if (yp) yp = gadd(yp, gmul(qn,ypadd)); qn = gmul(q,qn); if (gexpo(qn) <= - prec2nbits(prec) - 5 - toadd) break; if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ellwp"); gerepileall(av1, flall? 3: 2, &y, &qn, &yp); } } u1 = gdiv(pi2, mulcxmI(T.W2)); u2 = gsqr(u1); y = gmul(u2,y); /* y *= (2i pi / w2)^2 */ if (T.some_q_is_real && (T.some_z_is_real || T.some_z_is_pure_imag)) y = real_i(y); if (yp) { yp = gmul(u, gmul(gmul(u1,u2),yp));/* yp *= u (2i pi / w2)^3 */ if (T.some_q_is_real && T.some_z_is_real) yp = real_i(yp); y = mkvec2(y, gmul2n(yp,-1)); } return gerepilecopy(av, y); } static GEN ellwpseries_aux(GEN c4, GEN c6, long v, long PRECDL) { long i, k, l; pari_sp av; GEN t, res = cgetg(PRECDL+2,t_SER), *P = (GEN*)(res + 2); res[1] = evalsigne(1) | _evalvalp(-2) | evalvarn(v); if (!PRECDL) { setsigne(res,0); return res; } for (i=1; i 1) pari_err_FLAG("ellsigma"); if (!z) z = pol_x(0); y = toser_i(z); if (y) { long vy = varn(y), v = valp(y); GEN P, Q, c4,c6; if (!get_c4c6(w,&c4,&c6,prec0)) pari_err_TYPE("ellsigma",w); if (v <= 0) pari_err_IMPL("ellsigma(t_SER) away from 0"); if (flag) pari_err_TYPE("log(ellsigma)",y); if (gequal0(y)) { avma = av; return zeroser(vy, -v); } P = ellwpseries_aux(c4,c6, vy, lg(y)-2); P = integser(gneg(P)); /* \zeta' = - \wp*/ /* (log \sigma)' = \zeta; remove log-singularity first */ P = integser(gsub(P, monomial(gen_1,-1,vy))); P = gexp(P, prec0); setvalp(P, valp(P)+1); Q = gsubst(P, varn(P), y); return gerepileupto(av, Q); } if (!get_periods(w, z, &T, prec0)) pari_err_TYPE("ellsigma",w); if (!T.Z) { if (!flag) return gen_0; pari_err_DOMAIN("log(ellsigma)", "argument","=",gen_0,z); } prec = T.prec; pi2 = Pi2n(1,prec); pi = mppi(prec); toadd = (long)ceil(fabs( get_toadd(T.Z) )); uhalf = expIxy(pi, T.Z, prec); /* exp(i Pi Z) */ u = gsqr(uhalf); q8 = expIxy(gmul2n(pi2,-3), T.Tau, prec); q = gpowgs(q8,8); u = gneg_i(u); uinv = ginv(u); y = gen_0; av1 = avma; lim = stack_lim(av1,1); qn = q; qn2 = gen_1; urn = uhalf; urninv = ginv(uhalf); for(n=0;;n++) { y = gadd(y,gmul(qn2,gsub(urn,urninv))); qn2 = gmul(qn,qn2); if (gexpo(qn2) + n*toadd <= - prec2nbits(prec) - 5) break; qn = gmul(q,qn); urn = gmul(urn,u); urninv = gmul(urninv,uinv); if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ellsigma"); gerepileall(av1,5, &y,&qn,&qn2,&urn,&urninv); } } y = gmul(gmul(y,q8), gdiv(mulcxmI(T.W2), gmul(pi2,gpowgs(trueeta(T.Tau,prec),3)))); et = _elleta(&T); etnew = eta_correction(&T, et); zinit = gmul(T.Z,T.W2); etnew = gmul(etnew, gadd(zinit, gmul2n(gadd(gmul(T.x,T.W1), gmul(T.y,T.W2)),-1))); if (mpodd(T.x) || mpodd(T.y)) etnew = gadd(etnew, mulcxI(pi)); y1 = gadd(etnew, gmul2n(gmul(gmul(T.Z,zinit),gel(et,2)),-1)); if (flag) { y = gadd(y1, glog(y,prec)); if (T.some_q_is_real && T.some_z_is_real) { /* y = log(some real number): im(y) is 0 or Pi */ if (gexpo(imag_i(y)) < 1) y = real_i(y); } } else { y = gmul(y, gexp(y1,prec)); if (T.some_q_is_real) { if (T.some_z_is_real) y = real_i(y); else if (T.some_z_is_pure_imag) gel(y,1) = gen_0; } } return gerepilecopy(av, y); } GEN pointell(GEN e, GEN z, long prec) { pari_sp av = avma; GEN v; checkell(e); 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)); return gerepilecopy(av, v); } /********************************************************************/ /** **/ /** Tate's algorithm e (cf Anvers IV) **/ /** Kodaira types, global minimal model **/ /** **/ /********************************************************************/ /* Given an integral elliptic curve in ellinit form, and a prime p, returns the type of the fiber at p of the Neron model, as well as the change of variables in the form [f, kod, v, c]. * The integer f is the conductor's exponent. * The integer kod is the Kodaira type using the following notation: II , III , IV --> 2, 3, 4 I0 --> 1 Inu --> 4+nu for nu > 0 A '*' negates the code (e.g I* --> -2) * v is a quadruple [u, r, s, t] yielding a minimal model * c is the Tamagawa number. Uses Tate's algorithm (Anvers IV). Given the remarks at the bottom of page 46, the "long" algorithm is used for p = 2,3 only. */ static GEN localred_result(long f, long kod, long c, GEN v) { GEN z = cgetg(5, t_VEC); gel(z,1) = stoi(f); gel(z,2) = stoi(kod); gel(z,3) = gcopy(v); gel(z,4) = stoi(c); return z; } static GEN localredbug(GEN p, const char *s) { if (BPSW_psp(p)) pari_err_BUG(s); pari_err_PRIME("localred",p); return NULL; /* not reached */ } /* v_p( denom(j(E)) ) >= 0 */ static long j_pval(GEN E, GEN p) { return Z_pval(Q_denom(ell_get_j(E)), p); } #if 0 /* Here p > 3. e assumed integral, return v_p(N). Simplified version of * localred_p */ static long localred_p_get_f(GEN e, GEN p) { long nuj, nuD; GEN D = ell_get_disc(e); nuj = j_pval(e, p); nuD = Z_pval(D, p); if (nuj == 0) return (nuD % 12)? 2 : 0; return (nuD - nuj) % 12 ? 2: 1; } #endif /* Here p > 3. e assumed integral, minim = 1 if we only want a minimal model */ static GEN localred_p(GEN e, GEN p) { long k, f, kod, c, nuj, nuD; GEN p2, v, tri, c4, c6, D = ell_get_disc(e); c4 = ell_get_c4(e); c6 = ell_get_c6(e); nuj = j_pval(e, p); nuD = Z_pval(D, p); k = (nuD - nuj) / 12; if (k <= 0) v = init_ch(); else { /* model not minimal */ GEN pk = powiu(p,k), p2k = sqri(pk), p4k = sqri(p2k), p6k = mulii(p4k,p2k); GEN r, s, t; s = negi(ell_get_a1(e)); if (mpodd(s)) s = addii(s, pk); s = shifti(s, -1); r = subii(ell_get_a2(e), mulii(s, addii(ell_get_a1(e), s))); switch(umodiu(r, 3)) { default: break; /* 0 */ case 2: r = addii(r, p2k); break; case 1: r = subii(r, p2k); break; } r = negi( diviuexact(r, 3) ); t = negi(ellLHS0_i(e,r)); if (mpodd(t)) t = addii(t, mulii(pk, p2k)); t = shifti(t, -1); v = mkvec4(pk,r,s,t); nuD -= 12 * k; c4 = diviiexact(c4, p4k); c6 = diviiexact(c6, p6k); D = diviiexact(D, sqri(p6k)); } if (nuj > 0) switch(nuD - nuj) { case 0: f = 1; kod = 4+nuj; /* Inu */ switch(kronecker(negi(c6),p)) { case 1: c = nuD; break; case -1: c = odd(nuD)? 1: 2; break; default: return localredbug(p,"localred (p | c6)"); } break; case 6: { GEN d = Fp_red(diviiexact(D, powiu(p, 6+nuj)), p); if (nuj & 1) d = Fp_mul(d, diviiexact(c6, powiu(p,3)), p); f = 2; kod = -4-nuj; c = 3 + kronecker(d, p); /* Inu* */ break; } default: return localredbug(p,"localred (nu_D - nu_j != 0,6)"); } else switch(nuD) { case 0: f = 0; kod = 1; c = 1; break; /* I0, regular */ case 2: f = 2; kod = 2; c = 1; break; /* II */ case 3: f = 2; kod = 3; c = 2; break; /* III */ case 4: f = 2; kod = 4; /* IV */ c = 2 + krosi(-6,p) * kronecker(diviiexact(c6,sqri(p)), p); break; case 6: f = 2; kod = -1; /* I0* */ p2 = sqri(p); /* x^3 - 3c4/p^2 x - 2c6/p^3 */ tri = mkpoln(4, gen_1, gen_0, negi(mului(3, diviiexact(c4, p2))), negi(shifti(diviiexact(c6, mulii(p2,p)), 1))); c = 1 + FpX_nbroots(tri, p); break; case 8: f = 2; kod = -4; /* IV* */ c = 2 + krosi(-6,p) * kronecker(diviiexact(c6, sqri(sqri(p))), p); break; case 9: f = 2; kod = -3; c = 2; break; /* III* */ case 10: f = 2; kod = -2; c = 1; break; /* II* */ default: return localredbug(p,"localred"); } return localred_result(f, kod, c, v); } /* return a_{ k,l } in Tate's notation, pl = p^l */ static ulong aux(GEN ak, ulong q, ulong pl) { return umodiu(ak, q) / pl; } static ulong aux2(GEN ak, ulong p, GEN pl) { pari_sp av = avma; ulong res = umodiu(diviiexact(ak, pl), p); avma = av; return res; } /* number of distinct roots of X^3 + aX^2 + bX + c modulo p = 2 or 3 * assume a,b,c in {0, 1} [ p = 2 ] or {0, 1, 2} [ p = 3 ] * if there's a multiple root, put it in *mult */ static long numroots3(long a, long b, long c, long p, long *mult) { if (p == 2) { if ((c + a * b) & 1) return 3; *mult = b; return (a + b) & 1 ? 2 : 1; } /* p = 3 */ if (!a) { *mult = -c; return b ? 3 : 1; } *mult = a * b; if (b == 2) return (a + c) == 3 ? 2 : 3; else return c ? 3 : 2; } /* same for aX^2 +bX + c */ static long numroots2(long a, long b, long c, long p, long *mult) { if (p == 2) { *mult = c; return b & 1 ? 2 : 1; } /* p = 3 */ *mult = a * b; return (b * b - a * c) % 3 ? 2 : 1; } /* p = 2 or 3 */ static GEN localred_23(GEN e, long p) { long c, nu, nuD, r, s, t; long theroot, p2, p3, p4, p5, p6, a21, a42, a63, a32, a64; GEN v; nuD = Z_lval(ell_get_disc(e), (ulong)p); v = init_ch(); if (p == 2) { p2 = 4; p3 = 8; p4 = 16; p5 = 32; p6 = 64;} else { p2 = 9; p3 = 27; p4 = 81; p5 =243; p6 =729; } for (;;) { if (!nuD) return localred_result(0, 1, 1, v); /* I0 */ if (umodiu(ell_get_b2(e), p)) /* p \nmid b2 */ { if (umodiu(negi(ell_get_c6(e)), p == 2 ? 8 : 3) == 1) c = nuD; else c = 2 - (nuD & 1); return localred_result(1, 4 + nuD, c, v); } /* Inu */ if (p == 2) { r = umodiu(ell_get_a4(e), 2); s = umodiu(ell_get_a2(e), 2); t = umodiu(ell_get_a6(e), 2); if (r) { t = (s + t) & 1; s = (s + 1) & 1; } } else /* p == 3 */ { r = - umodiu(ell_get_b6(e), 3); s = umodiu(ell_get_a1(e), 3); t = umodiu(ell_get_a3(e), 3); if (s) { t = (t + r*s) % 3; if (t < 0) t += 3; } } /* p | (a1, a2, a3, a4, a6) */ if (r || s || t) E_compose_rst(&v, &e, stoi(r), stoi(s), stoi(t)); if (umodiu(ell_get_a6(e), p2)) return localred_result(nuD, 2, 1, v); /* II */ if (umodiu(ell_get_b8(e), p3)) return localred_result(nuD - 1, 3, 2, v); /* III */ if (umodiu(ell_get_b6(e), p3)) { if (umodiu(ell_get_b6(e), (p==2)? 32: 27) == (ulong)p2) c = 3; else c = 1; return localred_result(nuD - 2, 4, c, v); } /* IV */ if (umodiu(ell_get_a6(e), p3)) E_compose_t(&v, &e, p == 2? gen_2: modis(ell_get_a3(e), 9)); /* p | a1, a2; p^2 | a3, a4; p^3 | a6 */ a21 = aux(ell_get_a2(e), p2, p); a42 = aux(ell_get_a4(e), p3, p2); a63 = aux(ell_get_a6(e), p4, p3); switch (numroots3(a21, a42, a63, p, &theroot)) { case 3: c = a63 ? 1: 2; if (p == 2) c += ((a21 + a42 + a63) & 1); else { if (((1 + a21 + a42 + a63) % 3) == 0) c++; if (((1 - a21 + a42 - a63) % 3) == 0) c++; } return localred_result(nuD - 4, -1, c, v); case 2: /* I0* */ { /* compute nu */ GEN pk, pk1, p2k; long al, be, ga; if (theroot) E_compose_r(&v, &e, stoi(theroot * p)); /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */ nu = 1; pk = utoipos(p2); p2k = utoipos(p4); for(;;) { be = aux2(ell_get_a3(e), p, pk); ga = -aux2(ell_get_a6(e), p, p2k); al = 1; if (numroots2(al, be, ga, p, &theroot) == 2) break; if (theroot) E_compose_t(&v, &e, mulsi(theroot,pk)); pk1 = pk; pk = mului(p, pk); p2k = mului(p, p2k); nu++; al = a21; be = aux2(ell_get_a4(e), p, pk); ga = aux2(ell_get_a6(e), p, p2k); if (numroots2(al, be, ga, p, &theroot) == 2) break; if (theroot) E_compose_r(&v, &e, mulsi(theroot, pk1)); p2k = mului(p, p2k); nu++; } if (p == 2) c = 4 - 2 * (ga & 1); else c = 3 + kross(be * be - al * ga, 3); return localred_result(nuD - 4 - nu, -4 - nu, c, v); } case 1: /* Inu* */ if (theroot) E_compose_r(&v, &e, stoi(theroot*p)); /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */ a32 = aux(ell_get_a3(e), p3, p2); a64 = aux(ell_get_a6(e), p5, p4); if (numroots2(1, a32, -a64, p, &theroot) == 2) { if (p == 2) c = 3 - 2 * a64; else c = 2 + kross(a32 * a32 + a64, 3); return localred_result(nuD - 6, -4, c, v); } /* IV* */ if (theroot) E_compose_t(&v, &e, stoi(theroot*p2)); /* p | a1; p^2 | a2; p^3 | a3, a4; p^5 | a6 */ if (umodiu(ell_get_a4(e), p4)) return localred_result(nuD - 7, -3, 2, v); /* III* */ if (umodiu(ell_get_a6(e), p6)) return localred_result(nuD - 8, -2, 1, v); /* II* */ E_compose_u(&v, &e, utoipos(p)); /* not minimal */ nuD -= 12; } } } static GEN localred(GEN e, GEN p) { if (cmpiu(p, 3) > 0) /* p != 2,3 */ return localred_p(e,p); else { long l = itos(p); if (l < 2) pari_err_PRIME("localred",p); return localred_23(e, l); } } GEN elllocalred(GEN e, GEN p) { 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)); } /* 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 */ static GEN ellintegralmodel(GEN e, GEN *pv) { 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 c = gel(e,i); gel(a,i) = c; switch(typ(c)) { 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); } } /* 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; } } t = mulii(t, powiu(p, n)); } u = ginv(t); if (pv) *pv = mkvec4(u,gen_0,gen_0,gen_0); return coordch_u(e, u); } /* FIXME: export ? */ static ulong Mod32(GEN x) { long s = signe(x); ulong m; if (!s) return 0; m = mod32(x); if (!m) return m; if (s < 0) m = 32 - m; return m; } #define Mod16(x) Mod32(x)&15 #define Mod2(x) Mod32(x)&1 /* structure to hold incremental computation of standard minimal model/Q */ typedef struct { long a1; /*{0,1}*/ long a2; /*{-1,0,1}*/ long a3; /*{0,1}*/ long b2; /* centermod(-c6, 12), in [-5,6] */ GEN u, u2, u3, u4, u6; GEN a4, a6, b4, b6, b8, c4, c6, D; } ellmin_t; /* u from [u,r,s,t] */ static void min_set_u(ellmin_t *M, GEN u) { M->u = u; if (is_pm1(u)) M->u2 = M->u3 = M->u4 = M->u6 = gen_1; else { M->u2 = sqri(u); M->u3 = mulii(M->u2, u); M->u4 = sqri(M->u2); M->u6 = sqri(M->u3); } } /* E = original curve */ static void min_set_c(ellmin_t *M, GEN E) { GEN c4 = ell_get_c4(E), c6 = ell_get_c6(E); if (!is_pm1(M->u4)) { c4 = diviiexact(c4, M->u4); c6 = diviiexact(c6, M->u6); } M->c4 = c4; M->c6 = c6; } static void min_set_D(ellmin_t *M, GEN E) { GEN D = ell_get_disc(E); if (!is_pm1(M->u6)) D = diviiexact(D, sqri(M->u6)); M->D = D; } static void min_set_b(ellmin_t *M) { long b2 = Fl_center(12 - umodiu(M->c6,12), 12, 6); long b22 = b2*b2; /* in [0,36] */ M->b2 = b2; M->b4 = diviuexact(subui(b22, M->c4), 24); M->b6 = diviuexact(subii(mulsi(b2, subiu(mului(36,M->b4),b22)), M->c6), 216); } static void min_set_a(ellmin_t *M) { long a1, a2, a3, a13, b2 = M->b2; GEN b4 = M->b4, b6 = M->b6; if (odd(b2)) { a1 = 1; a2 = (b2 - 1) >> 2; } else { a1 = 0; a2 = b2 >> 2; } M->a1 = a1; M->a2 = a2; M->a3 = a3 = Mod2(b6)? 1: 0; a13 = a1 & a3; /* a1 * a3 */ M->a4 = shifti(subiu(b4, a13), -1); M->a6 = shifti(subiu(b6, a3), -2); } static GEN min_to_ell(ellmin_t *M, GEN E) { GEN b8, y = obj_init(15, 8); long a11, a13; gel(y,1) = M->a1? gen_1: gen_0; gel(y,2) = stoi(M->a2); gel(y,3) = M->a3? gen_1: gen_0; gel(y,4) = M->a4; gel(y,5) = M->a6; gel(y,6) = stoi(M->b2); gel(y,7) = M->b4; gel(y,8) = M->b6; a11 = M->a1; a13 = M->a1 & M->a3; b8 = subii(addii(mului(a11,M->a6), mulis(M->b6, M->a2)), mulii(M->a4, addiu(M->a4,a13))); gel(y,9) = b8; /* a1^2 a6 + 4a6 a2 + a2 a3^2 - a4(a4 + a1 a3) */ gel(y,10)= M->c4; gel(y,11)= M->c6; gel(y,12)= M->D; gel(y,13)= gel(E,13); gel(y,14)= gel(E,14); gel(y,15)= gel(E,15); return y; } static GEN 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); return mkvec4(M->u,r,s,t); } static long F2_card(ulong a1, ulong a2, ulong a3, ulong a4, ulong a6) { long N = 1; /* oo */ if (!a3) N ++; /* x = 0, y=0 or 1 */ else if (!a6) N += 2; /* x = 0, y arbitrary */ if ((a3 ^ a1) == 0) N++; /* x = 1, y = 0 or 1 */ else if (a2 ^ a4 ^ a6) N += 2; /* x = 1, y arbitrary */ return N; } static long F3_card(ulong b2, ulong b4, ulong b6) { ulong Po = 1+2*b4, Pe = b2+b6; /* kro(x,3)+1 = (x+1)%3, N = 4 + sum(kro) = 1+ sum(1+kro) */ return 1+(b6+1)%3+(Po+Pe+1)%3+(2*Po+Pe+1)%3; } static long cardmod2(GEN e) { /* solve y(1 + a1x + a3) = x (1 + a2 + a4) + a6 */ ulong a1 = Rg_to_F2(ell_get_a1(e)); ulong a2 = Rg_to_F2(ell_get_a2(e)); ulong a3 = Rg_to_F2(ell_get_a3(e)); ulong a4 = Rg_to_F2(ell_get_a4(e)); ulong a6 = Rg_to_F2(ell_get_a6(e)); return F2_card(a1,a2,a3,a4,a6); } static long cardmod3(GEN e) { ulong b2 = Rg_to_Fl(ell_get_b2(e), 3); ulong b4 = Rg_to_Fl(ell_get_b4(e), 3); ulong b6 = Rg_to_Fl(ell_get_b6(e), 3); return F3_card(b2,b4,b6); } /* return v_p(u), where [u,r,s,t] is the variable change to minimal model */ static long get_vu_p_small(GEN E, ulong p, long *pv6, long *pvD) { GEN c6 = ell_get_c6(E), D = ell_get_disc(E); long d, v6, vD = Z_lval(D,p); if (!signe(c6)) { d = vD / 12; if (d) { if (p == 2) { GEN c4 = ell_get_c4(E); long a = Mod16( shifti(c4, -4*d) ); if (a) d--; } if (d) vD -= 12*d; /* non minimal model */ } v6 = 12; /* +oo */ } else { v6 = Z_lval(c6,p); d = minss(2*v6, vD) / 12; if (d) { if (p == 2) { GEN c4 = ell_get_c4(E); long a = Mod16( shifti(c4, -4*d) ); long b = Mod32( shifti(c6, -6*d) ); if ((b & 3) != 3 && (a || (b && b!=8))) d--; } else if (p == 3) { if (v6 == 6*d+2) d--; } if (d) { v6 -= 6*d; vD -= 12*d; } /* non minimal model */ } } *pv6 = v6; *pvD = vD; return d; } static ulong ZtoF2(GEN x) { return (ulong)mpodd(x); } /* complete local reduction at 2, u = 2^d */ static void min_set_2(ellmin_t *M, GEN E, long d) { min_set_u(M, int2n(d)); min_set_c(M, E); min_set_b(M); min_set_a(M); } /* local reduction at 3, u = 3^d, don't compute the a_i */ static void min_set_3(ellmin_t *M, GEN E, long d) { min_set_u(M, powuu(3, d)); min_set_c(M, E); min_set_b(M); } static long is_minimal_ap_small(GEN E, ulong p, int *good_red) { long vc6, vD, d = get_vu_p_small(E, p, &vc6, &vD); if (vD) /* bad reduction */ { GEN c6; long s; *good_red = 0; if (vc6) return 0; c6 = ell_get_c6(E); if (d) c6 = diviiexact(c6, powuu(p, 6*d)); s = kroiu(c6,p); if ((p & 3) == 3) s = -s; return s; } *good_red = 1; if (p == 2) { ellmin_t M; if (!d) return 3 - cardmod2(E); min_set_2(&M, E, d); return 3 - F2_card(M.a1, M.a2 & 1, M.a3, ZtoF2(M.a4), ZtoF2(M.a6)); } else if (p == 3) { ellmin_t M; if (!d) return 4 - cardmod3(E); min_set_3(&M, E, d); return 4 - F3_card(M.b2, umodiu(M.b4,3), umodiu(M.b6,3)); } else { ellmin_t M; GEN a4, a6, pp = utoipos(p); min_set_u(&M, powuu(p,d)); min_set_c(&M, E); c4c6_to_a4a6(M.c4, M.c6, pp, &a4,&a6); return itos( subui(p+1, Fp_ellcard(a4, a6, pp)) ); } } static GEN is_minimal_ap(GEN E, GEN p, int *good_red) { GEN a4,a6, c4, c6, D; long vc6, vD, d; if (lgefint(p) == 3) return stoi( is_minimal_ap_small(E, p[2], good_red) ); c6 = ell_get_c6(E); D = ell_get_disc(E); vc6 = Z_pval(c6,p); vD = Z_pval(D,p); d = minss(2*vc6, vD) / 12; if (d) { vc6 -= 6*d; vD -= 12*d; } /* non minimal model */ if (vD) /* bad reduction */ { long s; *good_red = 0; if (vc6) return gen_0; if (d) c6 = diviiexact(c6, powiu(p, 6*d)); s = kronecker(c6,p); if (mod4(p) == 3) s = -s; return s < 0? gen_m1: gen_1; } *good_red = 1; c4 = ell_get_c4(E); if (d) { GEN u2 = powiu(p, 2*d), u4 = sqri(u2), u6 = mulii(u2,u4); c4 = diviiexact(c4, u4); c6 = diviiexact(c6, u6); } c4c6_to_a4a6(c4, c6, p, &a4,&a6); return subii(addiu(p,1), Fp_ellcard(a4, a6, p)); } /* E/Q, integral model, Laska-Kraus-Connell algorithm */ static GEN get_u(GEN E, GEN *pc4c6P, GEN P) { pari_sp av; GEN c4, c6, g, u, D, c4c6P; long l, k; D = ell_get_disc(E); c4 = ell_get_c4(E); c6 = ell_get_c6(E); if (!P) P = gel(Z_factor(gcdii(c4,c6)),1); /* primes dividing gcd(c4,c6) */ l = lg(P); c4c6P = vectrunc_init(l); settyp(c4c6P,t_COL); av = avma; g = gcdii(sqri(c6), D); u = gen_1; for (k = 1; k < l; k++) { GEN p = gel(P, k); long vg = Z_pval(g, p), d = vg / 12, r = vg % 12; if (!d) { vectrunc_append(c4c6P, p); continue; } switch(itou_or_0(p)) { case 2: { long a, b; a = Mod16( shifti(c4, -4*d) ); b = Mod32( shifti(c6, -6*d) ); if ((b & 3) != 3 && (a || (b && b!=8))) { d--; r += 12; } break; } case 3: if (Z_lval(c6,3) == 6*d+2) { d--; r += 12; } break; } if (r) vectrunc_append(c4c6P, p); if (d) u = mulii(u, powiu(p, d)); } *pc4c6P = c4c6P; return gerepileuptoint(av, u); } /* update Q_MINIMALMODEL entry in E, but don't update type-specific data on * ellminimalmodel(E) */ static GEN ellminimalmodel_i(GEN E, GEN *ptv) { GEN S, y, e, v, v0, u; GEN c4c6P; ellmin_t M; if ((S = obj_check(E, Q_MINIMALMODEL))) { if (lg(S) != 2) { E = gel(S,3); v = gel(S,2); } else v = init_ch(); if (ptv) *ptv = v; return gcopy(E); } e = ellintegralmodel(E, &v0); u = get_u(e, &c4c6P, NULL); min_set_u(&M, u); min_set_c(&M, e); min_set_D(&M, e); min_set_b(&M); min_set_a(&M); y = min_to_ell(&M, e); v = min_get_v(&M, e); if (v0) { gcomposev(&v0, v); v = v0; } if (is_trivial_change(v)) { v = init_ch(); S = mkvec(c4c6P); } else S = mkvec3(c4c6P, v, y); obj_insert(E, Q_MINIMALMODEL, S); *ptv = v; return y; } GEN ellminimalmodel(GEN E, GEN *ptv) { pari_sp av = avma; GEN S, y, v; checkell_Q(E); y = ellminimalmodel_i(E, &v); if (!is_trivial_change(v)) ch_Q(y, E, v); S = obj_check(E, Q_MINIMALMODEL); obj_insert_shallow(y, Q_MINIMALMODEL, mkvec(gel(S,1))); if (!ptv) y = gerepilecopy(av, y); else { *ptv = v; gerepileall(av, 2, &y, ptv); } return y; } /* Reduction of a rational curve E to its standard minimal model, don't * update type-dependant components. * Set v = [u, r, s, t] = change of variable E -> minimal model, with u > 0 * Set gr = [N, [u,r,s,t], c, fa, L], where * N = arithmetic conductor of E * c = product of the local Tamagawa numbers cp * fa = factorization of N * L = list of localred(E,p) for p | N. * Return standard minimal model (a1,a3 = 0 or 1, a2 = -1, 0 or 1) */ static GEN ellglobalred_all(GEN e, GEN *pgr, GEN *pv) { long k, l, iN; GEN S, E, c, L, P, NP, NE, D; E = ellminimalmodel_i(e, pv); S = obj_check(e, Q_MINIMALMODEL); P = gel(S,1); l = lg(P); /* prime divisors of (c4,c6) */ D = ell_get_disc(E); for (k = 1; k < l; k++) (void)Z_pvalrem(D, gel(P,k), &D); if (!is_pm1(D)) P = ZV_sort( shallowconcat(P, gel(absi_factor(D),1)) ); l = lg(P); c = gen_1; iN = 1; NP = cgetg(l, t_COL); NE = cgetg(l, t_COL); L = cgetg(l, t_VEC); for (k = 1; k < l; k++) { GEN p = gel(P,k), q = localred(E, p), ex = gel(q,1); if (signe(ex)) { gel(NP, iN) = p; gel(NE, iN) = ex; gel(L, iN) = q; iN++; gel(q,3) = gen_0; /*delete variable change*/ c = mulii(c, gel(q,4)); } } setlg(L, iN); setlg(NP, iN); setlg(NE, iN); *pgr = mkvec4(factorback2(NP,NE), c, mkmat2(NP,NE), L); return E; } static GEN doellglobalred(GEN E) { GEN v, gr; E = ellglobalred_all(E, &gr, &v); return gr; } static GEN ellglobalred_i(GEN E) { return obj_checkbuild(E, Q_GLOBALRED, &doellglobalred); } GEN ellglobalred(GEN E) { pari_sp av = avma; GEN S, gr, v; checkell_Q(E); gr = ellglobalred_i(E); S = obj_check(E, Q_MINIMALMODEL); v = (lg(S) == 2)? init_ch(): gel(S,2); return gerepilecopy(av, mkvec5(gel(gr,1), v, gel(gr,2),gel(gr,3),gel(gr,4))); } static GEN doellrootno(GEN e); /* Return E = ellminimalmodel(e), but only update E[1..14]. * insert MINIMALMODEL, GLOBALRED, ROOTNO in both e (regular insertion) * and E (shallow insert) */ GEN ellanal_globalred(GEN e, GEN *ch) { GEN E, S, v = NULL; checkell_Q(e); if (!(S = obj_check(e, Q_MINIMALMODEL))) { E = ellminimalmodel_i(e, &v); S = obj_check(e, Q_MINIMALMODEL); obj_insert_shallow(E, Q_MINIMALMODEL, mkvec(gel(S,1))); } else if (lg(S) == 2) /* trivial change */ E = e; else { v = gel(S,2); E = gcopy(gel(S,3)); obj_insert_shallow(E, Q_MINIMALMODEL, mkvec(gel(S,1))); } if (ch) *ch = v; S = ellglobalred_i(e); if (E != e) obj_insert_shallow(E, Q_GLOBALRED, S); S = obj_check(e, Q_ROOTNO); if (!S) { S = doellrootno(E); obj_insert(e, Q_ROOTNO, S); /* insert in e */ } if (E != e) obj_insert_shallow(E, Q_ROOTNO, S); /* ... and in E */ return E; } /********************************************************************/ /** **/ /** ROOT NUMBER (after Halberstadt at p = 2,3) **/ /** **/ /********************************************************************/ /* x a t_INT */ static long val_aux(GEN x, long p, long pk, long *u) { long v; GEN z; if (!signe(x)) { *u = 0; return 12; } v = Z_lvalrem(x,p,&z); *u = umodiu(z,pk); return v; } static void val_init(GEN e, long p, long pk, long *v4, long *u, long *v6, long *v, long *vD, long *d1) { GEN c4 = ell_get_c4(e), c6 = ell_get_c6(e), D = ell_get_disc(e); pari_sp av = avma; *v4 = val_aux(c4, p,pk, u); *v6 = val_aux(c6, p,pk, v); *vD = val_aux(D , p,pk, d1); avma = av; } static long kod_23(GEN e, long p) { GEN S, nv; if ((S = obj_check(e, Q_GLOBALRED))) { GEN NP = gmael(S,3,1), L = gel(S,4); nv = equaliu(gel(NP,1), p)? gel(L,1): gel(L,2); /* localred(p) */ } else nv = localred_23(e, p); return itos(gel(nv,2)); } /* v(c4), v(c6), v(D) for minimal model, +oo is coded by 12 */ static long neron_2(long v4, long v6, long vD, long kod) { if (kod > 4) return 1; switch(kod) { case 1: return (v6>0) ? 2 : 1; case 2: if (vD==4) return 1; else { if (vD==7) return 3; else return v4==4 ? 2 : 4; } case 3: switch(vD) { case 6: return 3; case 8: return 4; case 9: return 5; default: return v4==5 ? 2 : 1; } case 4: return v4>4 ? 2 : 1; case -1: switch(vD) { case 9: return 2; case 10: return 4; default: return v4>4 ? 3 : 1; } case -2: switch(vD) { case 12: return 2; case 14: return 3; default: return 1; } case -3: switch(vD) { case 12: return 2; case 14: return 3; case 15: return 4; default: return 1; } case -4: return v6==7 ? 2 : 1; case -5: return (v6==7 || v4==6) ? 2 : 1; case -6: switch(vD) { case 12: return 2; case 13: return 3; default: return v4==6 ? 2 : 1; } case -7: return (vD==12 || v4==6) ? 2 : 1; default: return v4==6 ? 2 : 1; } } /* p = 3; v(c4), v(c6), v(D) for minimal model, +oo is coded by 12 */ static long neron_3(long v4, long v6, long vD, long kod) { if (labs(kod) > 4) return 1; switch(kod) { case -1: case 1: return v4&1 ? 2 : 1; case -3: case 3: return (2*v6>vD+3) ? 2 : 1; case -4: case 2: switch (vD%6) { case 4: return 3; case 5: return 4; default: return v6%3==1 ? 2 : 1; } default: /* kod = -2 et 4 */ switch (vD%6) { case 0: return 2; case 1: return 3; default: return 1; } } } static long ellrootno_2(GEN e) { long n2, kod, u, v, x1, y1, D1, vD, v4, v6; long d = get_vu_p_small(e, 2, &v6, &vD); if (!vD) return 1; 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); kod = kod_23(e,2); n2 = neron_2(v4,v6,vD, kod); if (kod>=5) { long a2, a3; a2 = ZtoF2(ell_get_a2(e)); a3 = ZtoF2(ell_get_a3(e)); return odd(a2 + a3) ? 1 : -1; } if (kod<-9) return (n2==2) ? -kross(-1,v) : -1; x1 = u+v+v; switch(kod) { case 1: return 1; case 2: switch(n2) { case 1: switch(v4) { case 4: return kross(-1,u); case 5: return 1; default: return -1; } case 2: return (v6==7) ? 1 : -1; case 3: return (v%8==5 || (u*v)%8==5) ? 1 : -1; case 4: if (v4>5) return kross(-1,v); return (v4==5) ? -kross(-1,u) : -1; } case 3: switch(n2) { case 1: return -kross(2,u*v); case 2: return -kross(2,v); case 3: y1 = (u - (v << (v6-5))) & 15; return (y1==7 || y1==11) ? 1 : -1; case 4: return (v%8==3 || (2*u+v)%8==7) ? 1 : -1; case 5: return v6==8 ? kross(2,x1) : kross(-2,u); } case -1: switch(n2) { case 1: return -kross(2,x1); case 2: return (v%8==7) || (x1%32==11) ? 1 : -1; case 3: return v4==6 ? 1 : -1; case 4: if (v4>6) return kross(-1,v); return v4==6 ? -kross(-1,u*v) : -1; } case -2: return n2==1 ? kross(-2,v) : kross(-1,v); case -3: switch(n2) { case 1: y1=(u-2*v)%64; if (y1<0) y1+=64; return (y1==3) || (y1==19) ? 1 : -1; case 2: return kross(2*kross(-1,u),v); case 3: return -kross(-1,u)*kross(-2*kross(-1,u),u*v); case 4: return v6==11 ? kross(-2,x1) : -kross(-2,u); } case -5: if (n2==1) return x1%32==23 ? 1 : -1; else return -kross(2,2*u+v); case -6: switch(n2) { case 1: return 1; case 2: return v6==10 ? 1 : -1; case 3: return (u%16==11) || ((u+4*v)%16==3) ? 1 : -1; } case -7: if (n2==1) return 1; else { y1 = (u + (v << (v6-8))) & 15; if (v6==10) return (y1==9 || y1==13) ? 1 : -1; else return (y1==9 || y1==5) ? 1 : -1; } case -8: return n2==2 ? kross(-1,v*D1) : -1; case -9: return n2==2 ? -kross(-1,D1) : -1; default: return -1; } } static long ellrootno_3(GEN e) { long n2, kod, u, v, D1, r6, K4, K6, vD, v4, v6; long d = get_vu_p_small(e, 3, &v6, &vD); if (!vD) return 1; if (d) { /* not minimal */ 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); kod = kod_23(e,3); K6 = kross(v,3); if (kod>4) return K6; n2 = neron_3(v4,v6,vD,kod); r6 = v%9; K4 = kross(u,3); switch(kod) { case 1: case 3: case -3: return 1; case 2: switch(n2) { case 1: return (r6==4 || r6>6) ? 1 : -1; case 2: return -K4*K6; case 3: return 1; case 4: return -K6; } case 4: switch(n2) { case 1: return K6*kross(D1,3); case 2: return -K4; case 3: return -K6; } case -2: return n2==2 ? 1 : K6; case -4: switch(n2) { case 1: if (v4==4) return (r6==4 || r6==8) ? 1 : -1; else return (r6==1 || r6==2) ? 1 : -1; case 2: return -K6; case 3: return (r6==2 || r6==7) ? 1 : -1; case 4: return K6; } default: return -1; } } /* p > 3. Don't assume that e is minimal or even integral at p */ static long ellrootno_p(GEN e, GEN p) { long nuj, nuD, nu; GEN D = ell_get_disc(e); long ep, z; nuD = Q_pval(D, p); if (!nuD) return 1; nuj = j_pval(e, p); nu = (nuD - nuj) % 12; if (nu == 0) { GEN c6; long d, vg; if (!nuj) return 1; /* good reduction */ /* p || N */ c6 = ell_get_c6(e); /* != 0 */ vg = minss(2*Q_pval(c6, p), nuD); d = vg / 12; if (d) { GEN q = powiu(p,6*d); c6 = (typ(c6) == t_INT)? diviiexact(c6, q): gdiv(c6, q); } if (typ(c6) != t_INT) c6 = Rg_to_Fp(c6,p); /* c6 in minimal model */ return -kronecker(negi(c6), p); } if (nuj) return krosi(-1,p); ep = 12 / ugcd(12, nu); if (ep==4) z = 2; else z = (ep&1) ? 3 : 1; return krosi(-z, p); } static GEN doellrootno(GEN e) { GEN S, V, v, P; long i, l, s = -1; if ((S = obj_check(e, Q_GLOBALRED))) { GEN S2 = obj_check(e, Q_MINIMALMODEL); if (lg(S2) != 2) e = gel(S2,3); } else { GEN E = ellglobalred_all(e, &S, &v); obj_insert(e, Q_GLOBALRED, S); e = E; } P = gmael(S,3,1); l = lg(P); V = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { GEN p = gel(P,i); long t; switch(itou_or_0(p)) { case 2: t = ellrootno_2(e); break; case 3: t = ellrootno_3(e); break; default:t = ellrootno_p(e, p); } V[i] = t; s *= t; } return mkvec2(stoi(s), V); } long ellrootno_global(GEN e) { pari_sp av = avma; GEN S = obj_checkbuild(e, Q_ROOTNO, &doellrootno); avma = av; return itos(gel(S,1)); } /* local epsilon factor at p (over Q), including p=0 for the infinite place. * Global if p==1 or NULL. */ long ellrootno(GEN e, GEN p) { pari_sp av = avma; GEN S; long s; checkell_Q(e); if (!p || isint1(p)) return ellrootno_global(e); if (typ(p) != t_INT) pari_err_TYPE("ellrootno", p); if (signe(p) < 0) pari_err_PRIME("ellrootno",p); if (!signe(p)) return -1; /* local factor at infinity */ if ( (S = obj_check(e, Q_ROOTNO)) ) { GEN T = obj_check(e, Q_GLOBALRED), NP = gmael(T,3,1); long i, l = lg(NP); for (i = 1; i < l; i++) { GEN q = gel(NP,i); if (equalii(p, q)) { GEN V = gel(S,2); return V[i]; } } return 1; } switch(itou_or_0(p)) { case 2: e = ellintegralmodel(e, NULL); s = ellrootno_2(e); break; case 3: e = ellintegralmodel(e, NULL); s = ellrootno_3(e); break; default: s = ellrootno_p(e,p); break; } avma = av; return s; } /********************************************************************/ /** **/ /** TRACE OF FROBENIUS **/ /** **/ /********************************************************************/ /* assume e has good reduction mod p */ static long ellap_small_goodred(int CM, GEN E, ulong p) { 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); } static void checkell_int(GEN e) { checkell_Q(e); if (typ(ell_get_a1(e)) != t_INT || typ(ell_get_a2(e)) != t_INT || typ(ell_get_a3(e)) != t_INT || typ(ell_get_a4(e)) != t_INT || typ(ell_get_a6(e)) != t_INT) pari_err_TYPE("anellsmall [not an integral model]",e); } static int ell_get_CM(GEN e) { GEN j = ell_get_j(e); int CM = 0; if (typ(j) == t_INT) switch(itos_or_0(j)) { case 0: if (!signe(j)) CM = -3; break; case 1728: CM = -4; break; case -3375: CM = -7; break; case 8000: CM = -8; break; case 54000: CM = -12; break; case -32768: CM = -11; break; case 287496: CM = -16; break; case -884736: CM = -19; break; case -12288000: CM = -27; break; case 16581375: CM = -28; break; case -884736000: CM = -43; break; #ifdef LONG_IS_64BIT case -147197952000: CM = -67; break; case -262537412640768000: CM = -163; break; #endif } return CM; } GEN anellsmall(GEN e, long n0) { pari_sp av; ulong p, m, SQRTn, n = (ulong)n0; GEN an, D; int CM; checkell_int(e); if (n0 <= 0) return cgetg(1,t_VEC); if (n >= LGBITS) pari_err_IMPL( stack_sprintf("ellan for n >= %lu", LGBITS) ); SQRTn = (ulong)sqrt(n); D = ell_get_disc(e); CM = ell_get_CM(e); an = cgetg(n+1,t_VECSMALL); an[1] = 1; av = avma; for (p=2; p <= n; p++) an[p] = LONG_MAX; /* not computed yet */ for (p=2; p<=n; p++) { long ap; if (an[p] != LONG_MAX) continue; /* p not prime */ if (!umodiu(D,p)) /* p | D, bad reduction or non-minimal model */ { int good_red; ap = is_minimal_ap_small(e, p, &good_red); if (good_red) goto GOOD_RED; switch (ap) /* (-c6/p) */ { case -1: { /* non-split */ ulong N = n/p; for (m=1; m<=N; m++) if (an[m] != LONG_MAX) an[m*p] = -an[m]; break; } case 0: /* additive */ for (m=p; m<=n; m+=p) an[m] = 0; break; case 1: { /* split */ ulong N = n/p; for (m=1; m<=N; m++) if (an[m] != LONG_MAX) an[m*p] = an[m]; break; } } } else /* good reduction */ { ap = ellap_small_goodred(CM, e, p); GOOD_RED: if (p <= SQRTn) { ulong pk, oldpk = 1; for (pk=p; pk <= n; oldpk=pk, pk *= p) { if (pk == p) an[pk] = ap; else an[pk] = ap * an[oldpk] - p * an[oldpk/p]; for (m = n/pk; m > 1; m--) if (an[m] != LONG_MAX && m%p) an[m*pk] = an[m] * an[pk]; } } else { an[p] = ap; for (m = n/p; m > 1; m--) if (an[m] != LONG_MAX) an[m*p] = ap * an[m]; } } } avma = av; return an; } GEN anell(GEN e, long n0) { GEN v = anellsmall(e, n0); long i; for (i = 1; i <= n0; i++) gel(v,i) = stoi(v[i]); settyp(v, t_VEC); return v; } static GEN apk_good(GEN ap, GEN p, long e) { GEN u, v, w; long j; if (e == 1) return ap; u = ap; w = subii(sqri(ap), p); for (j=3; j<=e; j++) { v = u; u = w; w = subii(mulii(ap,u), mulii(p,v)); } return w; } GEN akell(GEN e, GEN n) { long i, j, s; pari_sp av = avma; GEN fa, P, E, D, u, y; checkell_int(e); if (typ(n) != t_INT) pari_err_TYPE("akell",n); if (signe(n)<= 0) return gen_0; if (gequal1(n)) return gen_1; D = ell_get_disc(e); u = coprime_part(n, D); y = gen_1; s = 1; if (!equalii(u, n)) { /* bad reduction at primes dividing n/u */ fa = Z_factor(diviiexact(n, u)); P = gel(fa,1); E = gel(fa,2); for (i=1; i 0) { GEN a0 = a; x = gsub(x, b); a = gneg(b); b = gsub(a0, b); } a = gsqrt(gneg(a), prec); b = gsqrt(gneg(b), prec); /* compute height on isogenous curve E1 ~ E0 */ for(n=0; ; n++) { GEN p1, p2, ab, a0 = a; a = gmul2n(gadd(a0,b), -1); r = gsub(a, a0); if (gequal0(r) || gexpo(r) < ex) break; ab = gmul(a0, b); b = gsqrt(ab, prec); p1 = gmul2n(gsub(x, ab), -1); p2 = gsqr(a); x = gadd(p1, gsqrt(gadd(gsqr(p1), gmul(x, p2)), prec)); V = shallowconcat(V, gadd(x, p2)); } if (n) { x = gel(V,n); while (--n > 0) x = gdiv(gsqr(x), gel(V,n)); } else { x = gadd(x, gsqr(a)); } /* height on E1 is log(x)/2. Go back to E0 */ return flag? gsqr( gdiv(gsqr(x), x_a) ) : gdiv(x, sqrtr( mpabs(x_a) )); } /* is P \in E(R)^0, the neutral component ? */ static int ellR_on_neutral(GEN E, GEN P, long prec) { GEN x = gel(P,1), e1 = ellR_root(E, prec); return gcmp(x, e1) >= 0; } /* exp( 4h_oo(z) ) */ 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) { pari_sp av = avma; GEN h; checkell_Q(E); 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| */ h = gmul(eh, gabs(d_ellLHS(E, z), prec)); } else h = exphellagm(E, z, 1, prec); return gerepileuptoleaf(av, gmul2n(mplog(h), -2)); } GEN ellheight0(GEN e, GEN a, long flag, long prec) { long i, tx = typ(a), 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)); if ((S = obj_check(e, Q_MINIMALMODEL))) { /* switch to minimal model if needed */ if (lg(S) != 2) { v = gel(S,2); e = gel(S,3); a = ellchangepoint(a, v); } } else { e = ellminimalmodel_i(e, &v); a = ellchangepoint(a, v); } if (is_matvec_t(tx)) { z = cgetg(lx,tx); for (i=1; i N) n = N; u = n * ((N<<1) - n); v = N << 3; } else { n2 = Z_pval(psi2, p); n = Z_pval(psi3, p); if (n >= 3*n2) { u = n2; v = 3; } else { u = n; v = 8; } } /* z -= u log(p) / v */ z = gsub(z, divru(mulur(u, logr_abs(itor(p,prec))), v)); } return gerepileupto(av, gmul2n(z, 1)); } GEN ghell(GEN e, GEN a, long prec) { return ellheight0(e,a,2,prec); } GEN mathell(GEN e, GEN x, long prec) { GEN y, h, pdiag; long lx = lg(x),i,j,tx=typ(x); pari_sp av = avma; if (!is_vec_t(tx)) pari_err_TYPE("ellheightmatrix",x); y = cgetg(lx,t_MAT); pdiag = new_chunk(lx); for (i=1; i = 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) { GEN G = ellgroup(E, NULL), d1 = gel(G,1); return mkvec2(d1, Z_factor(d1)); } GEN ellff_get_o(GEN E) { return obj_checkbuild(E, FF_O, &doellff_get_o); } GEN elllog(GEN E, GEN a, GEN g, GEN o) { pari_sp av = avma; GEN fg, r; checkell_Fq(E); checkellpt(a); checkellpt(g); fg = ellff_get_field(E); if (!o) o = ellff_get_o(E); if (typ(fg)==t_FFELT) r = FF_elllog(E, a, g, o); else { GEN p = fg, e = ellff_get_a4a6(E); GEN Pp = FpE_changepointinv(RgE_to_FpE(a,p), gel(e,3), p); GEN Qp = FpE_changepointinv(RgE_to_FpE(g,p), gel(e,3), p); r = FpE_log(Pp, Qp, o, gel(e,1), p); } 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; it) 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< 3 */ ell_to_a4a6(E, p, &a4,&a6); G = Fp_ellgroup(a4,a6,N,p, &m); END: return mkvec2(G, m); } static GEN doellgroup(GEN E) { GEN fg = ellff_get_field(E); return typ(fg) == t_FFELT ? FF_ellgroup(E): ellgroup_m(E, fg); } GEN ellff_get_group(GEN E) { return obj_checkbuild(E, FF_GROUP, &doellgroup); } /* E / Fp */ static GEN doellgens(GEN E) { GEN fg = ellff_get_field(E); if (typ(fg)==t_FFELT) return FF_ellgens(E); else { GEN e, Gm, F, p = fg; e = ellff_get_a4a6(E); Gm = ellff_get_group(E); F = Fp_ellgens(gel(e,1),gel(e,2),gel(e,3), gel(Gm,1),gel(Gm,2), p); return FpVV_to_mod(F,p); } } GEN ellff_get_gens(GEN E) { return obj_checkbuild(E, FF_GROUPGEN, &doellgens); } GEN ellgroup(GEN E, GEN p) { pari_sp av = avma; GEN G; p = checkellp(E,p, "ellgroup"); if (ell_over_Fq(E)) G = ellff_get_group(E); else G = ellgroup_m(E,p); /* t_ELL_Q */ return gerepilecopy(av, gel(G,1)); } GEN ellgroup0(GEN E, GEN p, long flag) { pari_sp av = avma; GEN V; if (flag==0) return ellgroup(E, p); if (flag!=1) pari_err_FLAG("ellgroup"); p = checkellp(E, p, "ellgroup"); if (!ell_over_Fq(E)) { /* t_ELL_Q */ GEN Gm = ellgroup_m(E, p), G = gel(Gm,1), m = gel(Gm,2); GEN F = FpVV_to_mod(ellgen(E,G,m,p), p); return gerepilecopy(av, mkvec3(ZV_prod(G),G,F)); } V = mkvec3(ellff_get_card(E), gel(ellff_get_group(E), 1), ellff_get_gens(E)); return gerepilecopy(av, V); } GEN ellgenerators(GEN E) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return obj_checkbuild(E, Q_GROUPGEN, &elldatagenerators); case t_ELL_Fp: case t_ELL_Fq: return gcopy(ellff_get_gens(E)); default: pari_err_TYPE("ellgenerators",E); return NULL;/*not reached*/ } } /* char != 2,3, j != 0, 1728 */ static GEN ellfromj_simple(GEN j) { pari_sp av = avma; GEN k = gsubsg(1728,j), kj = gmul(k, j), k2j = gmul(kj, k); GEN E = zerovec(5); gel(E,4) = gmulsg(3,kj); gel(E,5) = gmulsg(2,k2j); return gerepileupto(av, E); } GEN ellfromj(GEN j) { GEN T = NULL, p = typ(j)==t_FFELT? FF_p_i(j): NULL; /* trick: use j^0 to get 1 in the proper base field */ if ((p || (Rg_is_FpXQ(j,&T,&p) && p)) && lgefint(p) == 3) switch(p[2]) { case 2: if (gequal0(j)) retmkvec5(gen_0,gen_0, gpowgs(j,0), gen_0,gen_0); else retmkvec5(gpowgs(j,0),gen_0,gen_0, gen_0,ginv(j)); case 3: if (gequal0(j)) retmkvec5(gen_0,gen_0,gen_0, gpowgs(j,0), gen_0); else { GEN E = zerovec(5); pari_sp av = avma; gel(E,5) = gerepileupto(av, gneg(gsqr(j))); gel(E,2) = gcopy(j); return E; } } if (gequal0(j)) retmkvec5(gen_0,gen_0,gen_0,gen_0, gpowgs(j,0)); if (gequalgs(j,1728)) retmkvec5(gen_0,gen_0,gen_0, gpowgs(j,0), gen_0); return ellfromj_simple(j); } /* 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) { GEN b2,b4,b6,b8, res; if (n==0) return pol_0(v); if (n<=2) return N? scalarpol_shallow(mkintmod(gen_1,N),v): pol_1(v); b2 = ell_get_b2(e); b4 = ell_get_b4(e); b6 = ell_get_b6(e); b8 = ell_get_b8(e); if (n==3) res = mkpoln(5, N? modsi(3,N): utoi(3),b2,gmulsg(3,b4),gmulsg(3,b6),b8); else { 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); } setvarn(res, v); return res; } /* T = (2y + a1x + a3)^2 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) { GEN ret; long m = n/2; if (gel(t,n)) return gel(t,n); if (n<=4) ret = elldivpol4(e, N, n, v); else if (odd(n)) { GEN t1 = RgX_mul(elldivpol0(e,t,N,T,m+2,v), gpowgs(elldivpol0(e,t,N,T,m,v),3)); GEN t2 = RgX_mul(elldivpol0(e,t,N,T,m-1,v), gpowgs(elldivpol0(e,t,N,T,m+1,v),3)); if (odd(m))/*f_{4l+3} = f_{2l+3}f_{2l+1}^3 - T f_{2l}f_{2l+2}^3, m=2l+1*/ ret = RgX_sub(t1, RgX_mul(T,t2)); else /*f_{4l+1} = T f_{2l+2}f_{2l}^3 - f_{2l-1}f_{2l+1}^3, m=2l*/ ret = RgX_sub(RgX_mul(T,t1), t2); } else { /* f_2m = f_m(f_{m+2}f_{m-1}^2 - f_{m-2}f_{m+1}^2) */ GEN t1 = RgX_mul(elldivpol0(e,t,N,T,m+2,v), RgX_sqr(elldivpol0(e,t,N,T,m-1,v))); GEN t2 = RgX_mul(elldivpol0(e,t,N,T,m-2,v), RgX_sqr(elldivpol0(e,t,N,T,m+1,v))); ret = RgX_mul(elldivpol0(e,t,N,T,m,v), RgX_sub(t1,t2)); } gel(t,n) = ret; return ret; } GEN elldivpol(GEN e, long n, long v) { pari_sp av = avma; GEN ret, 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); N = characteristic(D); if (!signe(N)) N = NULL; if (n<0) n = -n; if (n==1 || n==3) ret = elldivpol4(e, N, n, v); else { GEN d2 = RHSpol(e, N); /* (2y + a1x + 3)^2 mod E */ setvarn(d2,v); if (n <= 4) ret = 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); } return gerepilecopy(av, ret); } pari-2.7.5/src/basemath/base4.c0000644000175000017500000023661612405547147014652 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* BASIC NF OPERATIONS */ /* (continued) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* IDEAL OPERATIONS */ /* */ /*******************************************************************/ /* A valid ideal is either principal (valid nf_element), or prime, or a matrix * on the integer basis in HNF. * A prime ideal is of the form [p,a,e,f,b], where the ideal is p.Z_K+a.Z_K, * p is a rational prime, a belongs to Z_K, e=e(P/p), f=f(P/p), and b * is Lenstra's constant, such that p.P^(-1)= p Z_K + b Z_K. * * An extended ideal is a couple [I,F] where I is a valid ideal and F is * either an algebraic number, or a factorization matrix associated to an * algebraic number. All routines work with either extended ideals or ideals * (an omitted F is assumed to be [;] <-> 1). * All ideals are output in HNF form. */ /* types and conversions */ long idealtyp(GEN *ideal, GEN *arch) { GEN x = *ideal; long t,lx,tx = typ(x); if (tx==t_VEC && lg(x)==3) { *arch = gel(x,2); x = gel(x,1); tx = typ(x); } else *arch = NULL; switch(tx) { case t_MAT: lx = lg(x); if (lx == 1) { t = id_PRINCIPAL; x = gen_0; break; } if (lx != lgcols(x)) pari_err_TYPE("idealtyp [non-square t_MAT]",x); t = id_MAT; break; case t_VEC: if (lg(x)!=6) pari_err_TYPE("idealtyp",x); t = id_PRIME; break; case t_POL: case t_POLMOD: case t_COL: case t_INT: case t_FRAC: t = id_PRINCIPAL; break; default: pari_err_TYPE("idealtyp",x); return 0; /*not reached*/ } *ideal = x; return t; } /* nf a true nf; v = [a,x,...], a in Z. Return (a,x) */ GEN idealhnf_two(GEN nf, GEN v) { GEN p = gel(v,1), pi = gel(v,2), m = zk_scalar_or_multable(nf, pi); if (typ(m) == t_INT) return scalarmat(gcdii(m,p), nf_get_degree(nf)); return ZM_hnfmodid(m, p); } static GEN ZM_Q_mul(GEN x, GEN y) { return typ(y) == t_INT? ZM_Z_mul(x,y): RgM_Rg_mul(x,y); } GEN idealhnf_principal(GEN nf, GEN x) { GEN cx; x = nf_to_scalar_or_basis(nf, x); switch(typ(x)) { case t_COL: break; 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)); default: pari_err_TYPE("idealhnf",x); } x = Q_primitive_part(x, &cx); RgV_check_ZV(x, "idealhnf"); x = zk_multable(nf, x); x = ZM_hnfmod(x, ZM_detmult(x)); return cx? ZM_Q_mul(x,cx): x; } /* x integral ideal in t_MAT form, nx columns */ static GEN vec_mulid(GEN nf, GEN x, long nx, long N) { GEN m = cgetg(nx*N + 1, t_MAT); long i, j, k; for (i=k=1; i<=nx; i++) for (j=1; j<=N; j++) gel(m, k++) = zk_ei_mul(nf, gel(x,i),j); return m; } GEN idealhnf_shallow(GEN nf, GEN x) { long tx = typ(x), lx = lg(x), N; /* cannot use idealtyp because here we allow non-square matrices */ if (tx == t_VEC && lx == 3) { x = gel(x,1); tx = typ(x); lx = lg(x); } if (tx == t_VEC && lx == 6) return idealhnf_two(nf,x); /* PRIME */ switch(tx) { case t_MAT: { GEN cx; long nx = lx-1; N = nf_get_degree(nf); if (nx == 0) return cgetg(1, t_MAT); if (nbrows(x) != N) pari_err_TYPE("idealhnf [wrong dimension]",x); if (nx == 1) return idealhnf_principal(nf, gel(x,1)); if (nx == N && RgM_is_ZM(x) && ZM_ishnf(x)) return x; x = Q_primitive_part(x, &cx); if (nx < N) x = vec_mulid(nf, x, nx, N); x = ZM_hnfmod(x, ZM_detmult(x)); return cx? ZM_Q_mul(x,cx): x; } case t_QFI: case t_QFR: { pari_sp av = avma; GEN u, D = nf_get_disc(nf), T = nf_get_pol(nf), f = nf_get_index(nf); GEN A = gel(x,1), B = gel(x,2); N = nf_get_degree(nf); if (N != 2) pari_err_TYPE("idealhnf [Qfb for non-quadratic fields]", x); if (!equalii(qfb_disc(x), D)) pari_err_DOMAIN("idealhnf [Qfb]", "disc(q)", "!=", D, x); /* x -> A Z + (-B + sqrt(D)) / 2 Z K = Q[t]/T(t), t^2 + ut + v = 0, u^2 - 4v = Df^2 => t = (-u + sqrt(D) f)/2 => sqrt(D)/2 = (t + u/2)/f */ u = gel(T,3); B = deg1pol_shallow(ginv(f), gsub(gdiv(u, shifti(f,1)), gdiv(B,gen_2)), varn(T)); return gerepileupto(av, idealhnf_two(nf, mkvec2(A,B))); } default: return idealhnf_principal(nf, x); /* PRINCIPAL */ } } GEN idealhnf(GEN nf, GEN x) { pari_sp av = avma; GEN y = idealhnf_shallow(checknf(nf), x); return (avma == av)? gcopy(y): gerepileupto(av, y); } /* GP functions */ GEN idealtwoelt0(GEN nf, GEN x, GEN a) { if (!a) return idealtwoelt(nf,x); return idealtwoelt2(nf,x,a); } GEN idealpow0(GEN nf, GEN x, GEN n, long flag) { if (flag) return idealpowred(nf,x,n); return idealpow(nf,x,n); } GEN idealmul0(GEN nf, GEN x, GEN y, long flag) { if (flag) return idealmulred(nf,x,y); return idealmul(nf,x,y); } GEN idealdiv0(GEN nf, GEN x, GEN y, long flag) { switch(flag) { case 0: return idealdiv(nf,x,y); case 1: return idealdivexact(nf,x,y); default: pari_err_FLAG("idealdiv"); } return NULL; /* not reached */ } GEN idealaddtoone0(GEN nf, GEN arg1, GEN arg2) { if (!arg2) return idealaddmultoone(nf,arg1); return idealaddtoone(nf,arg1,arg2); } /* b not a scalar */ static GEN hnf_Z_ZC(GEN nf, GEN a, GEN b) { return hnfmodid(zk_multable(nf,b), a); } /* b not a scalar */ static GEN hnf_Z_QC(GEN nf, GEN a, GEN b) { GEN db; b = Q_remove_denom(b, &db); if (db) a = mulii(a, db); b = hnf_Z_ZC(nf,a,b); return db? RgM_Rg_div(b, db): b; } /* b not a scalar (not point in trying to optimize for this case) */ static GEN hnf_Q_QC(GEN nf, GEN a, GEN b) { GEN da, db; if (typ(a) == t_INT) return hnf_Z_QC(nf, a, b); da = gel(a,2); a = gel(a,1); b = Q_remove_denom(b, &db); /* write da = d*A, db = d*B, gcd(A,B) = 1 * gcd(a/(d A), b/(d B)) = gcd(a B, A b) / A B d = gcd(a B, b) / A B d */ if (db) { GEN d = gcdii(da,db); if (!is_pm1(d)) db = diviiexact(db,d); /* B */ if (!is_pm1(db)) { a = mulii(a, db); /* a B */ da = mulii(da, db); /* A B d = lcm(denom(a),denom(b)) */ } } return RgM_Rg_div(hnf_Z_ZC(nf,a,b), da); } static GEN hnf_QC_QC(GEN nf, GEN a, GEN b) { GEN da, db, d, x; a = Q_remove_denom(a, &da); b = Q_remove_denom(b, &db); if (da) b = ZC_Z_mul(b, da); if (db) a = ZC_Z_mul(a, db); d = mul_denom(da, db); x = shallowconcat(zk_multable(nf,a), zk_multable(nf,b)); x = ZM_hnfmod(x, ZM_detmult(x)); return d? RgM_Rg_div(x, d): x; } static GEN hnf_Q_Q(GEN nf, GEN a, GEN b) {return scalarmat(Q_gcd(a,b), nf_get_degree(nf));} GEN idealhnf0(GEN nf, GEN a, GEN b) { long ta, tb; pari_sp av; GEN x; if (!b) return idealhnf(nf,a); /* HNF of aZ_K+bZ_K */ av = avma; nf = checknf(nf); a = nf_to_scalar_or_basis(nf,a); ta = typ(a); b = nf_to_scalar_or_basis(nf,b); tb = typ(b); if (ta == t_COL) x = (tb==t_COL)? hnf_QC_QC(nf, a,b): hnf_Q_QC(nf, b,a); else x = (tb==t_COL)? hnf_Q_QC(nf, a,b): hnf_Q_Q(nf, a,b); return gerepileupto(av, x); } /*******************************************************************/ /* */ /* TWO-ELEMENT FORM */ /* */ /*******************************************************************/ static GEN idealapprfact_i(GEN nf, GEN x, int nored); static int ok_elt(GEN x, GEN xZ, GEN y) { pari_sp av = avma; int r = ZM_equal(x, ZM_hnfmodid(y, xZ)); avma = av; return r; } static GEN addmul_col(GEN a, long s, GEN b) { long i,l; if (!s) return a? leafcopy(a): a; if (!a) return gmulsg(s,b); l = lg(a); for (i=1; i 1 && elt_egal(gel(G,k), gel(G,k-1))) { gel(E,k-1) = addii(gel(E,k), gel(E,k-1)); k--; } } /* kill 0 exponents */ l = k; for (k=i=1; i 1 && G[k] == G[k-1]) { E[k-1] += E[k]; k--; } } /* kill 0 exponents */ l = k; for (k=i=1; i x * (b/p)^v_pr(x) / z^k u, where z = b^e/p^(e-1) * b/p = pr^(-1) times something prime to p; both numerator and denominator * are integral and coprime to pr. Globally, we multiply by (b/p)^v_pr(A) = 1. * * EX = multiple of exponent of (O_K / pr^k)^* used to reduce the product in * case the e[i] are large */ GEN 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); GEN newg = cgetg(l+1, t_VEC); /* room for z */ prkZ = gcoeff(prk, 1,1); for (i=1; i < l; i++) { GEN dx, x = nf_to_scalar_or_basis(nf, gel(g,i)); long vdx = 0; x = Q_remove_denom(x, &dx); if (dx) { vdx = Z_pvalrem(dx, p, &u); if (!is_pm1(u)) { /* could avoid the inversion, but prkZ is small--> cheap */ u = Fp_inv(u, prkZ); x = typ(x) == t_INT? mulii(x,u): ZC_Z_mul(x, u); } if (vdx) vden = addii(vden, mului(vdx, gel(e,i))); } if (typ(x) == t_INT) { if (!vdx) vden = subii(vden, mului(Z_pvalrem(x, p, &x), gel(e,i))); } else { (void)ZC_nfvalrem(nf, x, pr, &x); x = ZC_hnfrem(x, prk); } gel(newg,i) = x; if (low_stack(lim, stack_lim(av, 2))) { GEN dummy = cgetg(1,t_VEC); long j; if(DEBUGMEM>1) pari_warn(warnmem,"famat_makecoprime"); for (j = i+1; j <= l; j++) gel(newg,j) = dummy; gerepileall(av,2, &newg, &vden); } } if (vden == gen_0) setlg(newg, l); else { GEN t = special_anti_uniformizer(nf, pr); if (typ(t) == t_INT) setlg(newg, l); /* = 1 */ else { if (typ(t) == t_MAT) t = gel(t,1); /* multiplication table */ gel(newg,i) = FpC_red(t, prkZ); e = shallowconcat(e, negi(vden)); } } return famat_to_nf_modideal_coprime(nf, newg, e, prk, EX); } /* prod g[i]^e[i] mod bid, assume (g[i], id) = 1 */ GEN famat_to_nf_moddivisor(GEN nf, GEN g, GEN e, GEN bid) { GEN t,sarch,module,cyc,fa2; long lc; if (lg(g) == 1) return scalarcol_shallow(gen_1, nf_get_degree(nf)); /* 1 */ module = bid_get_mod(bid); cyc = bid_get_cyc(bid); lc = lg(cyc); fa2 = gel(bid,4); sarch = gel(fa2,lg(fa2)-1); t = NULL; if (lc != 1) { GEN EX = gel(cyc,1); /* group exponent */ GEN id = gel(module,1); t = famat_to_nf_modideal_coprime(nf, g, e, id, EX); } if (!t) t = gen_1; return set_sign_mod_divisor(nf, mkmat2(g,e), t, module, sarch); } GEN vecmul(GEN x, GEN y) { long i,lx, tx = typ(x); GEN z; if (is_scalar_t(tx)) return gmul(x,y); z = cgetg_copy(x, &lx); for (i=1; i 1) swap(gel(x,1), gel(x,i)); /* help HNF */ gel(x,1) = scalarcol_shallow(gel(x,1), lx-1); break; } x = ZM_hnfmod(x, ZM_detmult(x)); return cx? ZM_Q_mul(x,cx): x; } /* tx <= ty */ static GEN idealmul_aux(GEN nf, GEN x, GEN y, long tx, long ty) { GEN z, cx, cy; switch(tx) { case id_PRINCIPAL: switch(ty) { case id_PRINCIPAL: return idealhnf_principal(nf, nfmul(nf,x,y)); case id_PRIME: { GEN p = gel(y,1), pi = gel(y,2), cx; if (pr_is_inert(y)) return RgM_Rg_mul(idealhnf_principal(nf,x),p); x = nf_to_scalar_or_basis(nf, x); switch(typ(x)) { case t_INT: 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)); } /* t_COL */ x = Q_primitive_part(x, &cx); x = zk_multable(nf, x); z = shallowconcat(ZM_Z_mul(x,p), ZM_ZC_mul(x,pi)); z = ZM_hnfmod(z, ZM_detmult(z)); return cx? ZM_Q_mul(z, cx): z; } default: /* id_MAT */ return idealmulelt(nf, x,y); } case id_PRIME: if (ty==id_PRIME) { y = idealhnf_two(nf,y); cy = NULL; } else y = Q_primitive_part(y, &cy); y = idealmul_HNF_two(nf,y,x); return cy? RgM_Rg_mul(y,cy): y; default: /* id_MAT */ x = Q_primitive_part(x, &cx); y = Q_primitive_part(y, &cy); cx = mul_content(cx,cy); y = idealmul_HNF(nf,x,y); return cx? ZM_Q_mul(y,cx): y; } } /* output the ideal product ix.iy */ GEN idealmul(GEN nf, GEN x, GEN y) { pari_sp av; GEN res, ax, ay, z; long tx = idealtyp(&x,&ax); long ty = idealtyp(&y,&ay), f; if (tx>ty) { swap(ax,ay); swap(x,y); lswap(tx,ty); } f = (ax||ay); res = f? cgetg(3,t_VEC): NULL; /*product is an extended ideal*/ av = avma; z = gerepileupto(av, idealmul_aux(checknf(nf), x,y, tx,ty)); if (!f) return z; if (ax && ay) ax = ext_mul(nf, ax, ay); else ax = gcopy(ax? ax: ay); gel(res,1) = z; gel(res,2) = ax; return res; } GEN idealsqr(GEN nf, GEN x) { pari_sp av; GEN res, ax, z; long tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; /*product is an extended ideal*/ av = avma; z = gerepileupto(av, idealmul_aux(checknf(nf), x,x, tx,tx)); if (!ax) return z; gel(res,1) = z; gel(res,2) = ext_sqr(nf, ax); return res; } /* norm of an ideal */ GEN idealnorm(GEN nf, GEN x) { pari_sp av; GEN y, T; long tx; switch(idealtyp(&x,&y)) { case id_PRIME: return pr_norm(x); case id_MAT: return RgM_det_triangular(x); } /* id_PRINCIPAL */ nf = checknf(nf); T = nf_get_pol(nf); av = avma; x = nf_to_scalar_or_alg(nf, x); x = (typ(x) == t_POL)? RgXQ_norm(x, T): gpowgs(x, degpol(T)); tx = typ(x); if (tx == t_INT) return gerepileuptoint(av, absi(x)); if (tx != t_FRAC) pari_err_TYPE("idealnorm",x); return gerepileupto(av, Q_abs(x)); } /* inverse */ /* rewritten from original code by P.M & M.H. * * I^(-1) = { x \in K, Tr(x D^(-1) I) \in Z }, D different of K/Q * * nf[5][6] = pp( D^(-1) ) = pp( HNF( T^(-1) ) ), T = (Tr(wi wj)) * nf[5][7] = same in 2-elt form. * Assume I integral. Return the integral ideal (I\cap Z) I^(-1) */ static GEN idealinv_HNF_aux(GEN nf, GEN I) { GEN J, dual, IZ = gcoeff(I,1,1); /* I \cap Z */ if (isint1(IZ)) return matid(lg(I)-1); J = idealmul_HNF(nf,I, gmael(nf,5,7)); /* I in HNF, hence easily inverted; multiply by IZ to get integer coeffs * missing content cancels while solving the linear equation */ dual = shallowtrans( hnf_divscale(J, gmael(nf,5,6), IZ) ); return ZM_hnfmodid(dual, IZ); } /* I HNF with rational coefficients (denominator d). */ static GEN idealinv_HNF(GEN nf, GEN I) { GEN J, IQ = gcoeff(I,1,1); /* I \cap Q; d IQ = dI \cap Z */ /* J = (dI)^(-1) * (d IQ) */ J = idealinv_HNF_aux(nf, Q_remove_denom(I, NULL)); if (typ(IQ) != t_INT || !is_pm1(IQ)) J = RgM_Rg_div(J, IQ); return J; } /* return p * P^(-1) [integral] */ GEN pidealprimeinv(GEN nf, GEN x) { if (pr_is_inert(x)) return matid(lg(gel(x,2)) - 1); return idealhnf_two(nf, mkvec2(gel(x,1), gel(x,5))); } GEN idealinv(GEN nf, GEN x) { GEN res,ax; pari_sp av; long tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; nf = checknf(nf); av = avma; switch (tx) { case id_MAT: if (lg(x)-1 != nf_get_degree(nf)) pari_err_DIM("idealinv"); x = idealinv_HNF(nf,x); break; case id_PRINCIPAL: tx = typ(x); if (is_const_t(tx)) x = ginv(x); else { GEN T; switch(tx) { case t_COL: x = coltoliftalg(nf,x); break; case t_POLMOD: x = gel(x,2); break; } if (typ(x) != t_POL) { x = ginv(x); break; } T = nf_get_pol(nf); if (varn(x) != varn(T)) pari_err_VAR("idealinv", x, T); x = QXQ_inv(x, T); } x = idealhnf_principal(nf,x); break; case id_PRIME: x = RgM_Rg_div(pidealprimeinv(nf,x), gel(x,1)); } x = gerepileupto(av,x); if (!ax) return x; gel(res,1) = x; gel(res,2) = ext_inv(nf, ax); return res; } /* write x = A/B, A,B coprime integral ideals */ GEN idealnumden(GEN nf, GEN x) { pari_sp av = avma; GEN ax, c, d, A, B, J; long tx = idealtyp(&x,&ax); nf = checknf(nf); switch (tx) { case id_PRIME: retmkvec2(idealhnf(nf, x), gen_1); case id_PRINCIPAL: x = nf_to_scalar_or_basis(nf, x); switch(typ(x)) { case t_INT: return gerepilecopy(av, mkvec2(absi(x),gen_1)); case t_FRAC: return gerepilecopy(av, mkvec2(absi(gel(x,1)), gel(x,2))); } /* t_COL */ x = Q_remove_denom(x, &d); if (!d) return gerepilecopy(av, mkvec2(idealhnf(nf, x), gen_1)); x = idealhnf(nf, x); break; case id_MAT: { long n = lg(x)-1; if (n == 0) return mkvec2(gen_0, gen_1); if (n != nf_get_degree(nf)) pari_err_DIM("idealnumden"); x = Q_remove_denom(x, &d); if (!d) return gerepilecopy(av, mkvec2(x, gen_1)); break; } } J = hnfmodid(x, d); /* = d/B */ c = gcoeff(J,1,1); /* (d/B) \cap Z, divides d */ B = idealinv_HNF_aux(nf, J); /* (d/B \cap Z) B/d */ c = diviiexact(d, c); if (!is_pm1(c)) B = ZM_Z_mul(B, c); /* = B ! */ A = idealmul(nf, x, B); /* d * (original x) * B = d A */ if (!is_pm1(d)) A = ZM_Z_divexact(A, d); /* = A ! */ if (is_pm1(gcoeff(B,1,1))) B = gen_1; return gerepilecopy(av, mkvec2(A, B)); } /* Return x, integral in 2-elt form, such that pr^n = x/d. Assume n != 0 */ static GEN idealpowprime(GEN nf, GEN pr, GEN n, GEN *d) { long s = signe(n); GEN q, gen; if (is_pm1(n)) /* n = 1 special cased for efficiency */ { q = pr_get_p(pr); if (s < 0) { gen = pr_get_tau(pr); if (typ(gen) == t_MAT) gen = gel(gen,1); *d = q; } else { gen = pr_get_gen(pr); *d = NULL; } } else { ulong r; GEN p = pr_get_p(pr); GEN m = diviu_rem(n, pr_get_e(pr), &r); if (r) m = addis(m,1); /* m = ceil(|n|/e) */ q = powii(p,m); if (s < 0) { gen = pr_get_tau(pr); if (typ(gen) == t_MAT) gen = gel(gen,1); n = negi(n); gen = ZC_Z_divexact(nfpow(nf, gen, n), powii(p, subii(n,m))); *d = q; } else { gen = nfpow(nf, pr_get_gen(pr), n); *d = NULL; } } return mkvec2(q, gen); } /* x * pr^n. Assume x in HNF (possibly non-integral) */ GEN idealmulpowprime(GEN nf, GEN x, GEN pr, GEN n) { GEN cx,y,dx; if (!signe(n)) return x; nf = checknf(nf); /* inert, special cased for efficiency */ if (pr_is_inert(pr)) return RgM_Rg_mul(x, powii(pr_get_p(pr), n)); y = idealpowprime(nf, pr, n, &dx); x = Q_primitive_part(x, &cx); if (cx && dx) { cx = gdiv(cx, dx); if (typ(cx) != t_FRAC) dx = NULL; else { dx = gel(cx,2); cx = gel(cx,1); } if (is_pm1(cx)) cx = NULL; } x = idealmul_HNF_two(nf,x,y); if (cx) x = RgM_Rg_mul(x,cx); if (dx) x = RgM_Rg_div(x,dx); return x; } GEN idealdivpowprime(GEN nf, GEN x, GEN pr, GEN n) { return idealmulpowprime(nf,x,pr, negi(n)); } static GEN idealpow_aux(GEN nf, GEN x, long tx, GEN n) { GEN T = nf_get_pol(nf), m, cx, n1, a, alpha; long N = degpol(T), s = signe(n); if (!s) return matid(N); switch(tx) { case id_PRINCIPAL: x = nf_to_scalar_or_alg(nf, x); x = (typ(x) == t_POL)? RgXQ_pow(x,n,T): powgi(x,n); return idealhnf_principal(nf,x); case id_PRIME: { GEN d; if (pr_is_inert(x)) return scalarmat(powii(gel(x,1), n), N); x = idealpowprime(nf, x, n, &d); x = idealhnf_two(nf,x); return d? RgM_Rg_div(x, d): x; } default: if (is_pm1(n)) return (s < 0)? idealinv(nf, x): gcopy(x); n1 = (s < 0)? negi(n): n; x = Q_primitive_part(x, &cx); a = mat_ideal_two_elt(nf,x); alpha = gel(a,2); a = gel(a,1); alpha = nfpow(nf,alpha,n1); m = zk_scalar_or_multable(nf, alpha); if (typ(m) == t_INT) { x = gcdii(m, powii(a,n1)); if (s<0) x = ginv(x); if (cx) x = gmul(x, powgi(cx,n)); x = scalarmat(x, N); } else { x = ZM_hnfmodid(m, powii(a,n1)); if (cx) cx = powgi(cx,n); if (s<0) { GEN xZ = gcoeff(x,1,1); cx = cx ? gdiv(cx, xZ): ginv(xZ); x = idealinv_HNF_aux(nf,x); } if (cx) x = RgM_Rg_mul(x, cx); } return x; } } /* raise the ideal x to the power n (in Z) */ GEN idealpow(GEN nf, GEN x, GEN n) { pari_sp av; long tx; GEN res, ax; if (typ(n) != t_INT) pari_err_TYPE("idealpow",n); tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; av = avma; x = gerepileupto(av, idealpow_aux(checknf(nf), x, tx, n)); if (!ax) return x; ax = ext_pow(nf, ax, n); gel(res,1) = x; gel(res,2) = ax; return res; } /* Return ideal^e in number field nf. e is a C integer. */ GEN idealpows(GEN nf, GEN ideal, long e) { long court[] = {evaltyp(t_INT) | _evallg(3),0,0}; affsi(e,court); return idealpow(nf,ideal,court); } static GEN _idealmulred(GEN nf, GEN x, GEN y) { return idealred(nf,idealmul(nf,x,y)); } static GEN _idealsqrred(GEN nf, GEN x) { return idealred(nf,idealsqr(nf,x)); } static GEN _mul(void *data, GEN x, GEN y) { return _idealmulred((GEN)data,x,y); } static GEN _sqr(void *data, GEN x) { return _idealsqrred((GEN)data, x); } /* compute x^n (x ideal, n integer), reducing along the way */ GEN idealpowred(GEN nf, GEN x, GEN n) { pari_sp av = avma; long s; GEN y; if (typ(n) != t_INT) pari_err_TYPE("idealpowred",n); s = signe(n); if (s == 0) return idealpow(nf,x,n); y = gen_pow(x, n, (void*)nf, &_sqr, &_mul); if (s < 0) y = idealinv(nf,y); if (s < 0 || is_pm1(n)) y = idealred(nf,y); return gerepileupto(av,y); } GEN idealmulred(GEN nf, GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, _idealmulred(nf,x,y)); } long isideal(GEN nf,GEN x) { long N, i, j, lx, tx = typ(x); pari_sp av; GEN T; nf = checknf(nf); T = nf_get_pol(nf); lx = lg(x); if (tx==t_VEC && lx==3) { x = gel(x,1); tx = typ(x); lx = lg(x); } switch(tx) { case t_INT: case t_FRAC: return 1; case t_POL: return varn(x) == varn(T); case t_POLMOD: return RgX_equal_var(T, gel(x,1)); case t_VEC: return get_prid(x)? 1 : 0; case t_MAT: break; default: return 0; } N = degpol(T); if (lx-1 != N) return (lx == 1); if (nbrows(x) != N) return 0; av = avma; x = Q_primpart(x); if (!ZM_ishnf(x)) return 0; for (i=2; i<=N; i++) for (j=2; j<=N; j++) if (! hnf_invimage(x, zk_ei_mul(nf,gel(x,i),j))) { avma = av; return 0; } avma=av; return 1; } GEN idealdiv(GEN nf, GEN x, GEN y) { pari_sp av = avma, tetpil; GEN z = idealinv(nf,y); tetpil = avma; return gerepile(av,tetpil, idealmul(nf,x,z)); } /* This routine computes the quotient x/y of two ideals in the number field nf. * It assumes that the quotient is an integral ideal. The idea is to find an * ideal z dividing y such that gcd(Nx/Nz, Nz) = 1. Then * * x + (Nx/Nz) x * ----------- = --- * y + (Ny/Nz) y * * Proof: we can assume x and y are integral. Let p be any prime ideal * * If p | Nz, then it divides neither Nx/Nz nor Ny/Nz (since Nx/Nz is the * product of the integers N(x/y) and N(y/z)). Both the numerator and the * denominator on the left will be coprime to p. So will x/y, since x/y is * assumed integral and its norm N(x/y) is coprime to p. * * If instead p does not divide Nz, then v_p (Nx/Nz) = v_p (Nx) >= v_p(x). * Hence v_p (x + Nx/Nz) = v_p(x). Likewise for the denominators. QED. * * Peter Montgomery. July, 1994. */ GEN idealdivexact(GEN nf, GEN x0, GEN y0) { pari_sp av = avma; GEN x, y, yZ, Nx, Ny, Nz, cy; nf = checknf(nf); x = idealhnf_shallow(nf, x0); y = idealhnf_shallow(nf, y0); if (lg(y) == 1) pari_err_INV("idealdivexact", y0); if (lg(x) == 1) { avma = av; return cgetg(1, t_MAT); } /* numerator is zero */ y = Q_primitive_part(y, &cy); 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)); /* Find a norm Nz | Ny such that gcd(Nx/Nz, Nz) = 1 */ for (Nz = Ny;;) { GEN p1 = gcdii(Nz, diviiexact(Nx,Nz)); if (is_pm1(p1)) break; Nz = diviiexact(Nz,p1); } /* Replace x/y by x+(Nx/Nz) / y+(Ny/Nz) */ x = ZM_hnfmodid(x, diviiexact(Nx,Nz)); /* y reduced to unit ideal ? */ if (Nz == Ny) return gerepileupto(av, x); y = ZM_hnfmodid(y, diviiexact(Ny,Nz)); yZ = gcoeff(y,1,1); y = idealmul_HNF(nf,x, idealinv_HNF_aux(nf,y)); return gerepileupto(av, RgM_Rg_div(y, yZ)); } GEN idealintersect(GEN nf, GEN x, GEN y) { pari_sp av = avma; long lz, lx, i; GEN z, dx, dy, xZ, yZ;; nf = checknf(nf); x = idealhnf_shallow(nf,x); y = idealhnf_shallow(nf,y); if (lg(x) == 1 || lg(y) == 1) { avma = av; return cgetg(1,t_MAT); } x = Q_remove_denom(x, &dx); y = Q_remove_denom(y, &dy); if (dx) y = ZM_Z_mul(y, dx); if (dy) x = ZM_Z_mul(x, dy); xZ = gcoeff(x,1,1); yZ = gcoeff(y,1,1); dx = mul_denom(dx,dy); z = ZM_lll(shallowconcat(x,y), 0.99, LLL_KER); lz = lg(z); lx = lg(x); for (i=1; i d = den(I/x) = T / c * J = (d I / x); I[1,1] = I \cap Z --> d I[1,1] belongs to J and Z */ I = ZM_hnfmodid(J, mulii(gcoeff(I,1,1), c? diviiexact(T,c): T)); if (!aI) return gerepileupto(av, I); c = mul_content(c,c1); y = c? gmul(y, gdiv(c,T)): gdiv(y, T); aI = ext_mul(nf, aI,y); return gerepilecopy(av, mkvec2(I, aI)); END: if (c1) aI = ext_mul(nf, aI,c1); return gerepilecopy(av, mkvec2(I, aI)); } GEN idealmin(GEN nf, GEN x, GEN vdir) { pari_sp av = avma; GEN y, dx; nf = checknf(nf); switch( idealtyp(&x,&y) ) { case id_PRINCIPAL: return gcopy(x); case id_PRIME: x = idealhnf_two(nf,x); break; case id_MAT: if (lg(x) == 1) return gen_0; } x = Q_remove_denom(x, &dx); y = idealpseudomin(x, vdir? nf_get_Gtwist(nf,vdir): nf_get_roundG(nf)); if (dx) y = RgC_Rg_div(y, dx); return gerepileupto(av, y); } /*******************************************************************/ /* */ /* APPROXIMATION THEOREM */ /* */ /*******************************************************************/ /* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */ GEN coprime_part(GEN x, GEN f) { for (;;) { f = gcdii(x, f); if (is_pm1(f)) break; x = diviiexact(x, f); } return x; } /* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */ ulong ucoprime_part(ulong x, ulong f) { for (;;) { f = ugcd(x, f); if (f == 1) break; x /= f; } return x; } /* x t_INT, f ideal. Write x = x1 x2, sqf(x1) | f, (x2,f) = 1. Return x2 */ static GEN nf_coprime_part(GEN nf, GEN x, GEN listpr) { long v, j, lp = lg(listpr), N = nf_get_degree(nf); GEN x1, x2, ex; #if 0 /*1) via many gcds. Expensive ! */ GEN f = idealprodprime(nf, listpr); f = ZM_hnfmodid(f, x); /* first gcd is less expensive since x in Z */ x = scalarmat(x, N); for (;;) { if (gequal1(gcoeff(f,1,1))) break; x = idealdivexact(nf, x, f); f = ZM_hnfmodid(shallowconcat(f,x), gcoeff(x,1,1)); /* gcd(f,x) */ } x2 = x; #else /*2) from prime decomposition */ x1 = NULL; for (j=1; j 0 */ x1 = x1? idealmulpowprime(nf, x1, pr, ex) : idealpow(nf, pr, ex); } x = scalarmat(x, N); x2 = x1? idealdivexact(nf, x, x1): x; #endif return x2; } /* L0 in K^*, assume (L0,f) = 1. Return L integral, L0 = L mod f */ GEN make_integral(GEN nf, GEN L0, GEN f, GEN listpr) { GEN fZ, t, L, D2, d1, d2, d; L = Q_remove_denom(L0, &d); if (!d) return L0; /* L0 = L / d, L integral */ fZ = gcoeff(f,1,1); if (typ(L) == t_INT) return Fp_mul(L, Fp_inv(d, fZ), fZ); /* Kill denom part coprime to fZ */ d2 = coprime_part(d, fZ); t = Fp_inv(d2, fZ); if (!is_pm1(t)) L = ZC_Z_mul(L,t); if (equalii(d, d2)) return L; d1 = diviiexact(d, d2); /* L0 = (L / d1) mod f. d1 not coprime to f * write (d1) = D1 D2, D2 minimal, (D2,f) = 1. */ D2 = nf_coprime_part(nf, d1, listpr); t = idealaddtoone_i(nf, D2, f); /* in D2, 1 mod f */ L = nfmuli(nf,t,L); /* if (L0, f) = 1, then L in D1 ==> in D1 D2 = (d1) */ return Q_div_to_int(L, d1); /* exact division */ } /* assume L is a list of prime ideals. Return the product */ GEN idealprodprime(GEN nf, GEN L) { long l = lg(L), i; GEN z; if (l == 1) return matid(nf_get_degree(nf)); z = idealhnf_two(nf, gel(L,1)); for (i=2; i = 0 for all other pr. * For optimal performance, all [anti-]uniformizers should be precomputed, * but no support for this yet. * * If nored, do not reduce result. * No garbage collecting */ static GEN idealapprfact_i(GEN nf, GEN x, int nored) { GEN z, d, L, e, e2, F; long i, r; int flagden; nf = checknf(nf); L = gel(x,1); e = gel(x,2); F = init_unif_mod_fZ(L); flagden = 0; z = NULL; r = lg(e); for (i = 1; i < r; i++) { long s = signe(gel(e,i)); GEN pi, q; if (!s) continue; if (s < 0) flagden = 1; pi = unif_mod_fZ(gel(L,i), F); q = nfpow(nf, pi, gel(e,i)); z = z? nfmul(nf, z, q): q; } if (!z) return scalarcol_shallow(gen_1, nf_get_degree(nf)); if (nored) { if (flagden) pari_err_IMPL("nored + denominator in idealapprfact"); return z; } e2 = cgetg(r, t_VEC); for (i=1; i=v_p(x) for all prime ideals p in the ideal factorization * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138. * Certainly not the most efficient, but sure. */ GEN idealchinese(GEN nf, GEN x, GEN w) { pari_sp av = avma; long ty = typ(w), i, N, r; GEN y, L, e, F, s, den; nf = checknf(nf); N = nf_get_degree(nf); if (typ(x) != t_MAT || lg(x) != 3) pari_err_TYPE("idealchinese [not a factorization]",x); L = gel(x,1); r = lg(L); e = gel(x,2); if (!is_vec_t(ty) || lg(w) != r) pari_err_TYPE("idealchinese",w); if (r == 1) return scalarcol_shallow(gen_1,N); w = Q_remove_denom(matalgtobasis(nf,w), &den); if (den) { GEN p = gen_indexsort(L, (void*)&cmp_prime_ideal, cmp_nodata); GEN fa = idealfactor(nf, den); /* sorted */ L = vecpermute(L, p); e = vecpermute(e, p); w = vecpermute(w, p); settyp(w, t_VEC); /* make sure typ = t_VEC */ merge_fact(&L, &e, gel(fa,1), gel(fa,2)); i = lg(L); w = shallowconcat(w, zerovec(i - r)); r = i; } else e = leafcopy(e); /* do not destroy x[2] */ for (i=1; iidef; 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; kN) 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) { pari_sp av = avma; GEN z, p, pr = modpr, T; nf = checknf(nf); modpr = nf_to_Fq_init(nf,&pr,&T,&p); x = nf_to_Fq(nf,x,modpr); y = nf_to_Fq(nf,y,modpr); z = Fq_mul(x,y,T,p); return gerepileupto(av, algtobasis(nf, Fq_to_nf(z,modpr))); } GEN nfdivmodpr(GEN nf, GEN x, GEN y, GEN modpr) { pari_sp av = avma; nf = checknf(nf); return gerepileupto(av, nfreducemodpr(nf, nfdiv(nf,x,y), modpr)); } GEN nfpowmodpr(GEN nf, GEN x, GEN k, GEN modpr) { pari_sp av=avma; GEN z, T, p, pr = modpr; nf = checknf(nf); modpr = nf_to_Fq_init(nf,&pr,&T,&p); z = nf_to_Fq(nf,x,modpr); z = Fq_pow(z,k,T,p); return gerepileupto(av, algtobasis(nf, Fq_to_nf(z,modpr))); } GEN nfkermodpr(GEN nf, GEN x, GEN modpr) { pari_sp av = avma; GEN T, p, pr = modpr; nf = checknf(nf); modpr = nf_to_Fq_init(nf, &pr,&T,&p); if (typ(x)!=t_MAT) pari_err_TYPE("nfkermodpr",x); x = nfM_to_FqM(x, nf, modpr); return gerepilecopy(av, FqM_to_nfM(FqM_ker(x,T,p), modpr)); } GEN nfsolvemodpr(GEN nf, GEN a, GEN b, GEN pr) { const char *f = "nfsolvemodpr"; pari_sp av = avma; GEN T, p, modpr; nf = checknf(nf); modpr = nf_to_Fq_init(nf, &pr,&T,&p); if (typ(a)!=t_MAT) pari_err_TYPE(f,a); a = nfM_to_FqM(a, nf, modpr); switch(typ(b)) { case t_MAT: b = nfM_to_FqM(b, nf, modpr); b = FqM_gauss(a,b,T,p); if (!b) pari_err_INV(f,a); a = FqM_to_nfM(b, modpr); break; case t_COL: b = nfV_to_FqV(b, nf, modpr); b = FqM_FqC_gauss(a,b,T,p); if (!b) pari_err_INV(f,a); a = FqV_to_nfV(b, modpr); break; default: pari_err_TYPE(f,b); } 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; j1) 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)); } pari-2.7.5/src/basemath/perm.c0000644000175000017500000006325012405547147014607 0ustar billbill/* Copyright (C) 2000-2003 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" /*************************************************************************/ /** **/ /** Routines for handling VEC/COL **/ /** **/ /*************************************************************************/ int vec_isconst(GEN v) { long i, l = lg(v); GEN w; if (l==1) return 1; w = gel(v,1); for(i=2;i>1, ny=n-nx; long m, ix, iy; GEN x, y; if (n<=2) { if (n==1) w[0]=v[0]; else if (n==2) { long v0=v[0], v1=v[1]; if (v0<=v1) { w[0]=v0; w[1]=v1; } else { w[0]=v1; w[1]=v0; } } return; } x=new_chunk(nx); y=new_chunk(ny); vecsmall_sortspec(v,nx,x); vecsmall_sortspec(v+nx,ny,y); for (m=0, ix=0, iy=0; ix>1; ny = n-nx; w = cgetg(n+1,t_VECSMALL); x = vecsmall_indexsortspec(v,nx); y = vecsmall_indexsortspec(v+nx,ny); for (m=1, ix=1, iy=1; ix<=nx && iy<=ny; ) if (v[x[ix]] <= v[y[iy]+nx]) w[m++] = x[ix++]; else w[m++] = y[iy++]+nx; for(;ix<=nx;) w[m++] = x[ix++]; for(;iy<=ny;) w[m++] = y[iy++]+nx; avma = (pari_sp)w; return w; } /*indirect sort.*/ GEN vecsmall_indexsort(GEN V) { long l=lg(V)-1; if (l==0) return cgetg(1, t_VECSMALL); return vecsmall_indexsortspec(V,l); } /* assume V sorted */ GEN vecsmall_uniq_sorted(GEN V) { GEN W; long i,j, l = lg(V); if (l == 1) return vecsmall_copy(V); W = cgetg(l,t_VECSMALL); W[1] = V[1]; for(i=j=2; iperm[i] * cyc (VEC of VECSMALL): a product of disjoint cycles. */ /* Multiply (compose) two permutations, putting the result in the second one. */ static void perm_mul_inplace2(GEN s, GEN t) { long i, l = lg(s); for (i = 1; i < l; i++) t[i] = s[t[i]]; } /* Orbits of the subgroup generated by v on {1,..,n} */ static GEN vecperm_orbits_i(GEN v, long n) { long mj = 1, k, l, m; GEN cy, cycle = cgetg(n+1, t_VEC), bit = zero_F2v(n); for (k = 1, l = 1; k <= n;) { for ( ; F2v_coeff(bit,mj); mj++) /*empty*/; cy = cgetg(n+1, t_VECSMALL); m = 1; k++; cy[m++] = mj; F2v_set(bit, mj++); for(;;) { long o, mold = m; for (o = 1; o < lg(v); o++) { GEN vo = gel(v,o); long p; for (p = 1; p < m; p++) /* m increases! */ { long j = vo[ cy[p] ]; if (!F2v_coeff(bit,j)) cy[m++] = j; F2v_set(bit,j); } } if (m == mold) break; k += m - mold; } setlg(cy, m); gel(cycle,l++) = cy; } setlg(cycle, l); return cycle; } /* memory clean version */ GEN vecperm_orbits(GEN v, long n) { pari_sp av = avma; return gerepilecopy(av, vecperm_orbits_i(v, n)); } /* Compute the cyclic decomposition of a permutation */ GEN perm_cycles(GEN v) { pari_sp av = avma; return gerepilecopy(av, vecperm_orbits_i(mkvec(v), lg(v)-1)); } /* Output the order of p */ long perm_order(GEN v) { pari_sp ltop = avma; GEN c = vecperm_orbits_i(mkvec(v), lg(v)-1); long i, d; for(i=1, d=1; i= n) l -= n; } } } return c; } /* Compute the power of a permutation given by product of cycles * Ouput a perm, not a cyc */ GEN cyc_pow_perm(GEN cyc, long exp) { long e, j, k, l, n; GEN p; for (n = 0, j = 1; j < lg(cyc); j++) n += lg(gel(cyc,j))-1; p = cgetg(n + 1, t_VECSMALL); for (j = 1; j < lg(cyc); j++) { GEN v = gel(cyc,j); n = lg(v) - 1; e = smodss(exp, n); for (k = 1, l = e; k <= n; k++) { p[v[k]] = v[l+1]; if (++l == n) l = 0; } } return p; } /* Compute the power of a permutation. * TODO: make it more clever for small exp */ GEN perm_pow(GEN perm, long exp) { return cyc_pow_perm(perm_cycles(perm), exp); } GEN perm_to_GAP(GEN p) { pari_sp ltop=avma; GEN gap; GEN x; long i; long nb, c=0; char *s; long sz; long lp=lg(p)-1; if (typ(p) != t_VECSMALL) pari_err_TYPE("perm_to_GAP",p); x = perm_cycles(p); sz = (long) ((bfffo(lp)+1) * LOG10_2 + 1); /*Dry run*/ for (i = 1, nb = 1; i < lg(x); ++i) { GEN z = gel(x,i); long lz = lg(z)-1; nb += 1+lz*(sz+2); } nb++; /*Real run*/ gap = cgetg(nchar2nlong(nb) + 1, t_STR); s = GSTR(gap); for (i = 1; i < lg(x); ++i) { long j; GEN z = gel(x,i); if (lg(z) > 2) { s[c++] = '('; for (j = 1; j < lg(z); ++j) { if (j > 1) { s[c++] = ','; s[c++] = ' '; } sprintf(s+c,"%ld",z[j]); while(s[c++]) /* empty */; c--; } s[c++] = ')'; } } if (!c) { s[c++]='('; s[c++]=')'; } s[c] = '\0'; return gerepileupto(ltop,gap); } int perm_commute(GEN s, GEN t) { long i, l = lg(t); for (i = 1; i < l; i++) if (t[ s[i] ] != s[ t[i] ]) return 0; return 1; } /*************************************************************************/ /** **/ /** Routines for handling groups **/ /** **/ /*************************************************************************/ /* A Group is a t_VEC [gen,orders] * gen (vecvecsmall): list of generators given by permutations * orders (vecsmall): relatives orders of generators. */ INLINE GEN grp_get_gen(GEN G) { return gel(G,1); } INLINE GEN grp_get_ord(GEN G) { return gel(G,2); } /* A Quotient Group is a t_VEC [gen,coset] * gen (vecvecsmall): coset generators * coset (vecsmall): gen[coset[p[1]]] generate the p-coset. */ INLINE GEN quo_get_gen(GEN C) { return gel(C,1); } INLINE GEN quo_get_coset(GEN C) { return gel(C,2); } static GEN trivialsubgroups(void) { GEN L = cgetg(2, t_VEC); gel(L,1) = trivialgroup(); return L; } /* Compute the order of p modulo the group given by a set */ long perm_relorder(GEN p, GEN set) { pari_sp ltop = avma; long n = 1; long q = p[1]; while (!F2v_coeff(set,q)) { q = p[q]; n++; } avma = ltop; return n; } GEN perm_generate(GEN S, GEN H, long o) { long i, n = lg(H)-1; GEN L = cgetg(n*o + 1, t_VEC); for(i=1; i<=n; i++) gel(L,i) = vecsmall_copy(gel(H,i)); for( ; i <= n*o; i++) gel(L,i) = perm_mul(gel(L,i-n), S); return L; } /*Return the order (cardinal) of a group */ long group_order(GEN G) { return zv_prod(grp_get_ord(G)); } /* G being a subgroup of S_n, output n */ long group_domain(GEN G) { GEN gen = grp_get_gen(G); if (lg(gen) < 2) pari_err_DOMAIN("group_domain", "#G", "=", gen_1,G); return lg(gel(gen,1)) - 1; } /*Left coset of g mod G: gG*/ GEN group_leftcoset(GEN G, GEN g) { GEN gen = grp_get_gen(G), ord = grp_get_ord(G); GEN res = cgetg(group_order(G)+1, t_VEC); long i, j, k; gel(res,1) = vecsmall_copy(g); k = 1; for (i = 1; i < lg(gen); i++) { long c = k * (ord[i] - 1); for (j = 1; j <= c; j++) gel(res,++k) = perm_mul(gel(res,j), gel(gen,i)); } return res; } /*Right coset of g mod G: Gg*/ GEN group_rightcoset(GEN G, GEN g) { GEN gen = grp_get_gen(G), ord = grp_get_ord(G); GEN res = cgetg(group_order(G)+1, t_VEC); long i, j, k; gel(res,1) = vecsmall_copy(g); k = 1; for (i = 1; i < lg(gen); i++) { long c = k * (ord[i] - 1); for (j = 1; j <= c; j++) gel(res,++k) = perm_mul(gel(gen,i), gel(res,j)); } return res; } /*Elements of a group from the generators, cf group_leftcoset*/ GEN group_elts(GEN G, long n) { GEN gen = grp_get_gen(G), ord = grp_get_ord(G); GEN res = cgetg(group_order(G)+1, t_VEC); long i, j, k; gel(res,1) = identity_perm(n); k = 1; for (i = 1; i < lg(gen); i++) { long c = k * (ord[i] - 1); /* j = 1, use res[1] = identity */ gel(res,++k) = vecsmall_copy(gel(gen,i)); for (j = 2; j <= c; j++) gel(res,++k) = perm_mul(gel(res,j), gel(gen,i)); } return res; } GEN groupelts_set(GEN elts, long n) { GEN res = zero_F2v(n); long i, l = lg(elts); for(i=1; i G/H */ /*The ouput is [gen,hash]*/ /* gen (vecvecsmall): coset generators * coset (vecsmall): vecsmall of coset number) */ GEN group_quotient(GEN G, GEN H) { pari_sp ltop = avma; GEN p2, p3; long i, j, a = 1; long n = group_domain(G), o = group_order(H); GEN elt = group_elts(G,n), el; long le = lg(elt)-1; GEN used = zero_F2v(le+1); long l = le/o; p2 = cgetg(l+1, t_VEC); p3 = zero_zv(n); el = zero_zv(n); for (i = 1; i<=le; i++) el[mael(elt,i,1)]=i; for (i = 1; i <= l; ++i) { GEN V; while(F2v_coeff(used,a)) a++; V = group_leftcoset(H,gel(elt,a)); gel(p2,i) = gel(V,1); for(j=1;j G/H * * Lift a subgroup S of G/H to a subgroup of G containing H */ GEN quotient_subgroup_lift(GEN C, GEN H, GEN S) { GEN genH = grp_get_gen(H); GEN genS = grp_get_gen(S); GEN genC = quo_get_gen(C); long l1 = lg(genH)-1; long l2 = lg(genS)-1, j; GEN p1 = cgetg(3, t_VEC), L = cgetg(l1+l2+1, t_VEC); for (j = 1; j <= l1; ++j) gel(L,j) = gel(genH,j); for (j = 1; j <= l2; ++j) gel(L,l1+j) = gel(genC, mael(genS,j,1)); gel(p1,1) = L; gel(p1,2) = vecsmall_concat(grp_get_ord(H), grp_get_ord(S)); return p1; } /* Let G a group and C a quotient map G --> G/H * Assume H is normal, return the group G/H */ GEN quotient_group(GEN C, GEN G) { pari_sp ltop = avma; GEN Qgen, Qord, Qelt, Qset, Q; GEN Cgen = quo_get_gen(C); GEN Ggen = grp_get_gen(G); long i,j, n = lg(Cgen)-1, l = lg(Ggen); Qord = cgetg(l, t_VECSMALL); Qgen = cgetg(l, t_VEC); Qelt = mkvec(identity_perm(n)); Qset = groupelts_set(Qelt, n); for (i = 1, j = 1; i < l; ++i) { GEN g = quotient_perm(C, gel(Ggen,i)); long o = perm_relorder(g, Qset); gel(Qgen,j) = g; Qord[j] = o; if (o != 1) { Qelt = perm_generate(g, Qelt, o); Qset = groupelts_set(Qelt, n); j++; } } setlg(Qgen,j); setlg(Qord,j); Q = mkvec2(Qgen, Qord); return gerepilecopy(ltop,Q); } /* Return 1 if g normalizes N, 0 otherwise */ long group_perm_normalize(GEN N, GEN g) { pari_sp ltop = avma; long r = gequal(vecvecsmall_sort(group_leftcoset(N, g)), vecvecsmall_sort(group_rightcoset(N, g))); avma = ltop; return r; } /* L is a list of subgroups, C is a coset and r a relative order.*/ static GEN liftlistsubgroups(GEN L, GEN C, long r) { pari_sp ltop = avma; long c = lg(C)-1, l = lg(L)-1, n = lg(gel(C,1))-1, i, k; GEN R; if (!l) return cgetg(1,t_VEC); R = cgetg(l*c+1, t_VEC); for (i = 1, k = 1; i <= l; ++i) { GEN S = gel(L,i), Selt = group_set(S,n); GEN gen = grp_get_gen(S); GEN ord = grp_get_ord(S); long j; for (j = 1; j <= c; ++j) { 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), vecsmall_append(ord, r)); } } setlg(R, k); return gerepilecopy(ltop, R); } /* H is a normal subgroup, C is the quotient map G -->G/H, * S is a subgroup of G/H, and G is embedded in Sym(l) * Return all the subgroups K of G such that * S= K mod H and K inter H={1} */ static GEN liftsubgroup(GEN C, GEN H, GEN S) { pari_sp ltop = avma; GEN V = trivialsubgroups(); GEN Sgen = grp_get_gen(S); GEN Sord = grp_get_ord(S); GEN Cgen = quo_get_gen(C); long n = lg(Sgen), i; for (i = 1; i < n; ++i) { /*loop over generators of S*/ GEN W = group_leftcoset(H, gel(Cgen, mael(Sgen, i, 1))); V = liftlistsubgroups(V, W, Sord[i]); } return gerepilecopy(ltop,V); } /* 1:A4 2:S4 0: other */ long group_isA4S4(GEN G) { GEN elt = grp_get_gen(G); GEN ord = grp_get_ord(G); long n = lg(ord); if (n != 4 && n != 5) return 0; if (ord[1]!=2 || ord[2]!=2 || ord[3]!=3) return 0; if (perm_commute(gel(elt,1),gel(elt,3))) return 0; if (n==4) return 1; if (ord[4]!=2) return 0; if (perm_commute(gel(elt,3),gel(elt,4))) return 0; return 2; } /* compute all the subgroups of a group G */ GEN group_subgroups(GEN G) { pari_sp ltop = avma; GEN p1, H, C, Q, M, sg1, sg2, sg3; GEN gen = grp_get_gen(G); GEN ord = grp_get_ord(G); long lM, i, j, n = lg(gen); if (n == 1) return trivialsubgroups(); if (group_isA4S4(G)) { GEN s = gel(gen,1); /*s = (1,2)(3,4) */ GEN t = gel(gen,2); /*t = (1,3)(2,4) */ GEN st = perm_mul(s, t); /*st = (1,4)(2,3) */ H = dicyclicgroup(s, t, 2, 2); /* sg3 is the list of subgroups intersecting only partially with H*/ sg3 = cgetg((n==4)?4: 10, t_VEC); gel(sg3,1) = cyclicgroup(s, 2); gel(sg3,2) = cyclicgroup(t, 2); gel(sg3,3) = cyclicgroup(st, 2); if (n==5) { GEN u = gel(gen,3); GEN v = gel(gen,4), w, u2; if (zv_equal(perm_conj(u,s), t)) /*u=(2,3,4)*/ u2 = perm_mul(u,u); else { u2 = u; u = perm_mul(u,u); } if (perm_order(v)==2) { if (!perm_commute(s,v)) /*v=(1,2)*/ { v = perm_conj(u,v); if (!perm_commute(s,v)) v = perm_conj(u,v); } w = perm_mul(v,t); /*w=(1,4,2,3)*/ } else { w = v; if (!zv_equal(perm_mul(w,w), s)) /*w=(1,4,2,3)*/ { w = perm_conj(u,w); if (!zv_equal(perm_mul(w,w), s)) w = perm_conj(u,w); } v = perm_mul(w,t); /*v=(1,2)*/ } gel(sg3,4) = dicyclicgroup(s,v,2,2); gel(sg3,5) = dicyclicgroup(t,perm_conj(u,v),2,2); gel(sg3,6) = dicyclicgroup(st,perm_conj(u2,v),2,2); gel(sg3,7) = dicyclicgroup(s,w,2,2); gel(sg3,8) = dicyclicgroup(t,perm_conj(u,w),2,2); gel(sg3,9) = dicyclicgroup(st,perm_conj(u2,w),2,2); } } else { long osig = mael(factoru(ord[1]), 1, 1); GEN sig = perm_pow(gel(gen,1), ord[1]/osig); H = cyclicgroup(sig,osig); sg3 = NULL; } C = group_quotient(G,H); Q = quotient_group(C,G); M = group_subgroups(Q); lM = lg(M); /* sg1 is the list of subgroups containing H*/ sg1 = cgetg(lM, t_VEC); for (i = 1; i < lM; ++i) gel(sg1,i) = quotient_subgroup_lift(C,H,gel(M,i)); /*sg2 is a list of lists of subgroups not intersecting with H*/ sg2 = cgetg(lM, t_VEC); /* Loop over all subgroups of G/H */ for (j = 1; j < lM; ++j) gel(sg2,j) = liftsubgroup(C, H, gel(M,j)); p1 = concat(sg1, shallowconcat1(sg2)); if (sg3) { p1 = concat(p1, sg3); if (n==5) /*ensure that the D4 subgroups of S4 are in supersolvable format*/ for(j = 3; j <= 5; j++) { GEN c = gmael(p1,j,1); if (!perm_commute(gel(c,1),gel(c,3))) { if (perm_commute(gel(c,2),gel(c,3))) { swap(gel(c,1), gel(c,2)); } else perm_mul_inplace2(gel(c,2), gel(c,1)); } } } return gerepileupto(ltop,p1); } /*return 1 if G is abelian, else 0*/ long group_isabelian(GEN G) { GEN g = grp_get_gen(G); long i, j, n = lg(g); for(i=2; i 1 && group_domain(G) != group_domain(H)) pari_err_DOMAIN("group_subgroup_isnormal","domain(H)","!=", strtoGENstr("domain(G)"), H); for(i=1; i 1) gel(s,k++) = comma; gel(s,k++) = perm_to_GAP(gel(g,i)); } gel(s,k++) = strtoGENstr(")"); return gerepilecopy(av, shallowconcat1(s)); } GEN group_export_MAGMA(GEN G) { pari_sp av = avma; GEN s, comma, g = grp_get_gen(G); long i, k, l = lg(g); if (l == 1) return strtoGENstr("PermutationGroup<1|>"); s = cgetg(2*l, t_VEC); comma = strtoGENstr(", "); gel(s,1) = gsprintf("PermutationGroup<%ld|",group_domain(G)); for (i=1, k=2; i < l; ++i) { if (i > 1) gel(s,k++) = comma; gel(s,k++) = GENtoGENstr( vecsmall_to_vec(gel(g,i)) ); } gel(s,k++) = strtoGENstr(">"); return gerepilecopy(av, shallowconcat1(s)); } GEN group_export(GEN G, long format) { switch(format) { case 0: return group_export_GAP(G); case 1: return group_export_MAGMA(G); } pari_err_FLAG("galoisexport"); return NULL; /*-Wall*/ } pari-2.7.5/src/basemath/FF.c0000644000175000017500000010610612405547147014135 0ustar billbill/* Copyright (C) 2000-2003 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" /*************************************************************************/ /** **/ /** Routines for handling FFELT **/ /** **/ /*************************************************************************/ INLINE void _getFF(GEN x, GEN *T, GEN *p, ulong *pp) { *T=gel(x,3); *p=gel(x,4); *pp=(*p)[2]; } INLINE GEN _initFF(GEN x, GEN *T, GEN *p, ulong *pp) { _getFF(x,T,p,pp); return cgetg(5,t_FFELT); } INLINE void _checkFF(GEN x, GEN y, const char *s) { if (!FF_samefield(x,y)) pari_err_OP(s,x,y); } INLINE GEN _mkFF(GEN x, GEN z, GEN r) { z[1]=x[1]; gel(z,2)=r; gel(z,3)=gcopy(gel(x,3)); gel(z,4)=icopy(gel(x,4)); return z; } INLINE GEN _mkFF_i(GEN x, GEN z, GEN r) { z[1]=x[1]; gel(z,2)=r; gel(z,3)=gel(x,3); gel(z,4)=gel(x,4); return z; } INLINE GEN mkFF_i(GEN x, GEN r) { GEN z = cgetg(5,t_FFELT); return _mkFF_i(x,z,r); } /* Return true if x and y are defined in the same field */ int FF_samefield(GEN x, GEN y) { return x[1] == y[1] && equalii(gel(x,4),gel(y,4)) && gidentical(gel(x,3),gel(y,3)); } int FF_equal(GEN x, GEN y) { return FF_samefield(x,y) && gidentical(gel(x,2),gel(y,2)); } int FF_equal0(GEN x) { return lgpol(gel(x,2))==0; } int FF_equal1(GEN x) { GEN A = gel(x,2); switch(x[1]) { case t_FF_FpXQ: return degpol(A)==0 && gequal1(gel(A,2)); default: return degpol(A)==0 && A[2]==1; } } static int Fp_cmp_1(GEN x, GEN p) { pari_sp av = avma; int b = equalii(x, addis(p,-1)); avma = av; return b; } int FF_equalm1(GEN x) { ulong pp; GEN T, p, y = gel(x,2); _getFF(x,&T,&p,&pp); switch(x[1]) { 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); } } GEN FF_zero(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=zeropol(varn(T)); break; case t_FF_F2xq: r=zero_F2x(T[1]); break; default: r=zero_Flx(T[1]); } return _mkFF(x,z,r); } GEN FF_1(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=pol_1(varn(T)); break; case t_FF_F2xq: r=pol1_F2x(T[1]); break; default: r=pol1_Flx(T[1]); } return _mkFF(x,z,r); } GEN FF_q(GEN x) { ulong pp; GEN T, p; _getFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: return powiu(p, degpol(T)); break; case t_FF_F2xq: return int2n(F2x_degree(T)); break; default: return powuu(pp,degpol(T)); } } GEN FF_p(GEN x) { return icopy(gel(x,4)); } GEN FF_p_i(GEN x) { return gel(x,4); } GEN FF_mod(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_copy(gel(x,3)); case t_FF_F2xq: return F2x_to_ZX(gel(x,3)); default: return Flx_to_ZX(gel(x,3)); } } long FF_f(GEN x) { switch(x[1]) { case t_FF_F2xq: return F2x_degree(gel(x,3)); default: return degpol(gel(x,3)); } } GEN FF_to_F2xq(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_F2x(gel(x,2)); case t_FF_F2xq: return zv_copy(gel(x,2)); default: return Flx_to_F2x(gel(x,2)); } } GEN FF_to_F2xq_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_F2x(gel(x,2)); case t_FF_F2xq: return gel(x,2); default: return Flx_to_F2x(gel(x,2)); } } GEN FF_to_Flxq(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_Flx(gel(x,2),itou(gel(x,4))); case t_FF_F2xq: return F2x_to_Flx(gel(x,2)); default: return zv_copy(gel(x,2)); } } GEN FF_to_Flxq_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_Flx(gel(x,2),itou(gel(x,4))); case t_FF_F2xq: return F2x_to_Flx(gel(x,2)); default: return gel(x,2); } } GEN FF_to_FpXQ(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_copy(gel(x,2)); case t_FF_F2xq: return F2x_to_ZX(gel(x,2)); default: return Flx_to_ZX(gel(x,2)); } } GEN FF_to_FpXQ_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return gel(x,2); case t_FF_F2xq: return F2x_to_ZX(gel(x,2)); default: return Flx_to_ZX(gel(x,2)); } } GEN FF_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); _checkFF(x,y,"+"); switch(x[1]) { case t_FF_FpXQ: r=FpX_add(gel(x,2),gel(y,2),p); break; case t_FF_F2xq: r=F2x_add(gel(x,2),gel(y,2)); break; default: r=Flx_add(gel(x,2),gel(y,2),pp); } return _mkFF(x,z,r); } GEN FF_sub(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); _checkFF(x,y,"+"); switch(x[1]) { case t_FF_FpXQ: r=FpX_sub(gel(x,2),gel(y,2),p); break; case t_FF_F2xq: r=F2x_add(gel(x,2),gel(y,2)); break; default: r=Flx_sub(gel(x,2),gel(y,2),pp); } return _mkFF(x,z,r); } GEN FF_Z_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpX_Fp_add(gel(x,2),modii(y,p),p)); break; } case t_FF_F2xq: r=mpodd(y)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2)); break; default: r=Flx_Fl_add(gel(x,2),umodiu(y,pp),pp); } return _mkFF(x,z,r); } GEN FF_Q_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpX_Fp_add(gel(x,2),Rg_to_Fp(y,p),p)); break; } case t_FF_F2xq: r=Rg_to_Fl(y,pp)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2)); break; default: r=Flx_Fl_add(gel(x,2),Rg_to_Fl(y,pp),pp); } return _mkFF(x,z,r); } GEN FF_neg(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; case t_FF_F2xq: r=vecsmall_copy(gel(x,2)); break; default: r=Flx_neg(gel(x,2),pp); } return _mkFF(x,z,r); } GEN FF_neg_i(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; case t_FF_F2xq: r=gel(x,2); break; default: r=Flx_neg(gel(x,2),pp); } return _mkFF_i(x,z,r); } GEN FF_mul(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); _checkFF(x,y,"*"); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpXQ_mul(gel(x,2),gel(y,2),T,p)); break; } case t_FF_F2xq: r=F2xq_mul(gel(x,2),gel(y,2),T); break; default: r=Flxq_mul(gel(x,2),gel(y,2),T,pp); } return _mkFF(x,z,r); } GEN FF_Z_mul(GEN x, GEN y) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: /* modii(y,p) left on stack for efficiency */ r = FpX_Fp_mul(A, modii(y,p),p); break; case t_FF_F2xq: r = mpodd(y)? vecsmall_copy(A): zero_Flx(A[1]); break; default: r = Flx_Fl_mul(A, umodiu(y,pp), pp); } return _mkFF(x,z,r); } GEN FF_Z_Z_muldiv(GEN x, GEN a, GEN b) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: /* Fp_div(a,b,p) left on stack for efficiency */ r = FpX_Fp_mul(A, Fp_div(a,b,p), p); break; case t_FF_F2xq: if (!mpodd(b)) pari_err_INV("FF_Z_Z_muldiv", b); r = mpodd(a)? vecsmall_copy(A): zero_Flx(A[1]); break; default: r = Flx_Fl_mul(A, Fl_div(umodiu(a,pp),umodiu(b,pp),pp),pp); } return _mkFF(x,z,r); } GEN FF_sqr(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpXQ_sqr(gel(x,2),T,p)); break; } case t_FF_F2xq: r=F2xq_sqr(gel(x,2),T); break; default: r=Flxq_sqr(gel(x,2),T,pp); } return _mkFF(x,z,r); } GEN FF_mul2n(GEN x, long n) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { GEN p1; /* left on stack for efficiency */ if (n>0) p1=remii(int2n(n),p); else p1=Fp_inv(remii(int2n(-n),p),p); r = FpX_Fp_mul(A, p1, p); } break; case t_FF_F2xq: if (n<0) pari_err_INV("FF_mul2n", gen_2); r = n==0? vecsmall_copy(A): zero_Flx(A[1]); break; default: { ulong l1; if (n>0) l1 = umodiu(int2n(n),pp); else l1 = Fl_inv(umodiu(int2n(-n),pp),pp); r = Flx_Fl_mul(A,l1,pp); } } return _mkFF(x,z,r); } GEN FF_inv(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); pari_sp av=avma; switch(x[1]) { case t_FF_FpXQ: r=gerepileupto(av,FpXQ_inv(gel(x,2),T,p)); break; case t_FF_F2xq: r=F2xq_inv(gel(x,2),T); break; default: r=Flxq_inv(gel(x,2),T,pp); } return _mkFF(x,z,r); } GEN FF_div(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); pari_sp av=avma; _checkFF(x,y,"/"); switch(x[1]) { case t_FF_FpXQ: r=gerepileupto(av,FpXQ_div(gel(x,2),gel(y,2),T,p)); break; case t_FF_F2xq: r=gerepileupto(av,F2xq_div(gel(x,2),gel(y,2),T)); break; default: r=gerepileupto(av,Flxq_div(gel(x,2),gel(y,2),T,pp)); } return _mkFF(x,z,r); } GEN Z_FF_div(GEN n, GEN x) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); pari_sp av=avma; switch(x[1]) { case t_FF_FpXQ: r = gerepileupto(av,FpX_Fp_mul(FpXQ_inv(A,T,p),modii(n,p),p)); break; case t_FF_F2xq: r = F2xq_inv(A,T); /*Check for division by 0*/ if(!mpodd(n)) { avma = av; r = zero_Flx(A[1]); } break; default: r = gerepileupto(av, Flx_Fl_mul(Flxq_inv(A,T,pp),umodiu(n,pp),pp)); } return _mkFF(x,z,r); } GEN FF_sqrtn(GEN x, GEN n, GEN *zetan) { ulong pp; GEN r, T, p, y=_initFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: r=FpXQ_sqrtn(gel(x,2),n,T,p,zetan); break; case t_FF_F2xq: r=F2xq_sqrtn(gel(x,2),n,T,zetan); break; default: r=Flxq_sqrtn(gel(x,2),n,T,pp,zetan); } if (!r) pari_err_SQRTN("FF_sqrtn",x); (void)_mkFF(x, y, r); if (zetan) { GEN z = cgetg(lg(y),t_FFELT); *zetan=_mkFF(x, z, *zetan); } return y; } GEN FF_sqrt(GEN x) { ulong pp; GEN r, T, p, y=_initFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: r = FpXQ_sqrt(gel(x,2),T,p); break; case t_FF_F2xq: r = F2xq_sqrt(gel(x,2),T); break; default: r = Flxq_sqrt(gel(x,2),T,pp); } if (!r) pari_err_SQRTN("FF_sqrt",x); return _mkFF(x, y, r); } long FF_issquare(GEN x) { GEN T, p; ulong pp; _getFF(x, &T, &p, &pp); switch(x[1]) { case t_FF_FpXQ: return FpXQ_issquare(gel(x,2), T, p); case t_FF_F2xq: return 1; default: /* case t_FF_Flxq: */ return Flxq_issquare(gel(x,2), T, pp); } } long FF_issquareall(GEN x, GEN *pt) { if (!pt) return FF_issquare(x); return FF_ispower(x, gen_2, pt); } long FF_ispower(GEN x, GEN K, GEN *pt) { ulong pp; GEN r, T, p; pari_sp av = avma; if (FF_equal0(x)) { if (pt) *pt = gcopy(x); return 1; } _getFF(x, &T, &p, &pp); if (pt) *pt = cgetg(5,t_FFELT); switch(x[1]) { case t_FF_FpXQ: r = FpXQ_sqrtn(gel(x,2),K,T,p,NULL); break; case t_FF_F2xq: r = F2xq_sqrtn(gel(x,2),K,T,NULL); break; default: /* case t_FF_Flxq: */ r = Flxq_sqrtn(gel(x,2),K,T,pp,NULL); break; } if (!r) { avma = av; return 0; } if (pt) { (void)_mkFF(x,*pt,r); } return 1; } GEN FF_pow(GEN x, GEN n) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r = FpXQ_pow(gel(x,2), n, T, p); break; case t_FF_F2xq: r = F2xq_pow(gel(x,2), n, T); break; default: r = Flxq_pow(gel(x,2), n, T, pp); } return _mkFF(x,z,r); } GEN FF_norm(GEN x) { ulong pp; GEN T,p; _getFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: return FpXQ_norm(gel(x,2),T,p); case t_FF_F2xq: return lgpol(gel(x,2))?gen_1:gen_0; default: return utoi(Flxq_norm(gel(x,2),T,pp)); } } GEN FF_trace(GEN x) { ulong pp; GEN T,p; _getFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: return FpXQ_trace(gel(x,2),T,p); case t_FF_F2xq: return F2xq_trace(gel(x,2),T)?gen_1:gen_0; default: return utoi(Flxq_trace(gel(x,2),T,pp)); } } GEN FF_conjvec(GEN x) { ulong pp; GEN r,T,p,v; long i,l; pari_sp av; _getFF(x,&T,&p,&pp); av = avma; switch(x[1]) { case t_FF_FpXQ: v = FpXQ_conjvec(gel(x,2), T, p); break; case t_FF_F2xq: v = F2xq_conjvec(gel(x,2), T); break; default: v = Flxq_conjvec(gel(x,2), T, pp); } l = lg(v); r = cgetg(l, t_COL); for(i=1; i0; i--) if (!Rg_is_FF(gel(x,i), ff)) return 0; return (*ff != NULL); } int RgM_is_FFM(GEN x, GEN *ff) { long j, lx = lg(x); for (j=lx-1; j>0; j--) if (!RgC_is_FFC(gel(x,j), ff)) return 0; return (*ff != NULL); } static GEN FFC_to_raw(GEN x) { long i, lx; GEN y = cgetg_copy(x,&lx); for(i=1; i 0) prec += nbits2extraprec( i ); return gerepileupto(av, gadd(y, quadtofp(x, prec))); } static GEN mulrfrac(GEN x, GEN y) { pari_sp av = avma; GEN z, a = gel(y,1), b = gel(y,2); if (is_pm1(a)) /* frequent special case */ { z = divri(x, b); if (signe(a) < 0) togglesign(z); return z; } return gerepileuptoleaf(av, divri(mulri(x,gel(y,1)), gel(y,2))); } static GEN mulqf(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gmul(y, quadtofp(x, prec))); } static GEN divqf(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gdiv(quadtofp(x,prec), y)); } static GEN divfq(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gdiv(x, quadtofp(y,prec))); } /* y PADIC, x + y by converting x to padic */ static GEN addTp(GEN x, GEN y) { pari_sp av = avma; GEN z; if (!valp(y)) z = cvtop2(x,y); else { long l = signe(gel(y,4))? valp(y) + precp(y): valp(y); z = cvtop(x, gel(y,2), l); } return gerepileupto(av, addsub_pp(z, y, addii)); } /* y PADIC, x * y by converting x to padic */ static GEN mulTp(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, mulpp(cvtop2(x,y), y)); } /* y PADIC, non zero x / y by converting x to padic */ static GEN divTp(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, divpp(cvtop2(x,y), y)); } /* x PADIC, x / y by converting y to padic. Assume x != 0; otherwise y * converted to O(p^e) and division by 0 */ static GEN divpT(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, divpp(x, cvtop2(y,x))); } /* z := Mod(x,X) + Mod(y,X) [ t_INTMOD preallocated ], x,y,X INT, 0 <= x,y < X * clean memory from z on */ static GEN add_intmod_same(GEN z, GEN X, GEN x, GEN y) { if (lgefint(X) == 3) { ulong u = Fl_add(itou(x),itou(y), X[2]); avma = (pari_sp)z; gel(z,2) = utoi(u); } else { GEN u = addii(x,y); if (cmpii(u, X) >= 0) u = subii(u, X); gel(z,2) = gerepileuptoint((pari_sp)z, u); } gel(z,1) = icopy(X); return z; } static GEN sub_intmod_same(GEN z, GEN X, GEN x, GEN y) { if (lgefint(X) == 3) { ulong u = Fl_sub(itou(x),itou(y), X[2]); avma = (pari_sp)z; gel(z,2) = utoi(u); } else { GEN u = subii(x,y); if (signe(u) < 0) u = addii(u, X); gel(z,2) = gerepileuptoint((pari_sp)z, u); } gel(z,1) = icopy(X); return z; } /* cf add_intmod_same */ static GEN mul_intmod_same(GEN z, GEN X, GEN x, GEN y) { if (lgefint(X) == 3) { ulong u = Fl_mul(itou(x),itou(y), X[2]); avma = (pari_sp)z; gel(z,2) = utoi(u); } else gel(z,2) = gerepileuptoint((pari_sp)z, remii(mulii(x,y), X) ); gel(z,1) = icopy(X); return z; } /* cf add_intmod_same */ 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); avma = (pari_sp)z; gel(z,2) = utoi(u); } else gel(z,2) = gerepileuptoint((pari_sp)z, remii(mulii(x, Fp_inv(y,X)), X) ); gel(z,1) = icopy(X); return z; } /*******************************************************************/ /* */ /* REDUCTION to IRREDUCIBLE TERMS (t_FRAC/t_RFRAC) */ /* */ /* (static routines are not memory clean, but OK for gerepileupto) */ /*******************************************************************/ /* Compute the denominator of (1/y) * (n/d) = n/yd, y a "scalar". * Sanity check : avoid (1/2) / (Mod(1,2)*x + 1) "=" 1 / (0 * x + 1) */ static GEN rfrac_denom_mul_scal(GEN d, GEN y) { GEN D = RgX_Rg_mul(d, y); if (lg(D) != lg(d)) { /* try to generate a meaningful diagnostic */ D = gdiv(leading_term(d), y); /* should fail */ pari_err_INV("gred_rfrac", y); /* better than nothing */ } return D; } /* d a t_POL, n a coprime t_POL of same var or "scalar". Not memory clean */ GEN gred_rfrac_simple(GEN n, GEN d) { GEN c, cn, cd, z; long dd = degpol(d); if (dd <= 0) { if (dd < 0) pari_err_INV("gred_rfrac_simple", d); n = gdiv(n, gel(d,2)); if (typ(n) != t_POL || varn(n) != varn(d)) n = scalarpol(n, varn(d)); return n; } cd = content(d); cn = (typ(n) == t_POL && varn(n) == varn(d))? content(n): n; if (!gequal1(cd)) { d = RgX_Rg_div(d,cd); if (!gequal1(cn)) { if (gequal0(cn)) { if (isexactzero(cn)) return scalarpol(cn, varn(d)); n = (cn != n)? RgX_Rg_div(n,cd): gdiv(n, cd); c = gen_1; } else { n = (cn != n)? RgX_Rg_div(n,cn): gen_1; c = gdiv(cn,cd); } } else c = ginv(cd); } else { if (!gequal1(cn)) { if (gequal0(cn)) { if (isexactzero(cn)) return scalarpol(cn, varn(d)); c = gen_1; } else { n = (cn != n)? RgX_Rg_div(n,cn): gen_1; c = cn; } } else { GEN y = cgetg(3,t_RFRAC); gel(y,1) = gcopy(n); gel(y,2) = RgX_copy(d); return y; } } if (typ(c) == t_POL) { z = c; do { z = content(z); } while (typ(z) == t_POL); cd = denom(z); cn = gmul(c, cd); } else { cn = numer(c); cd = denom(c); } z = cgetg(3,t_RFRAC); gel(z,1) = gmul(n, cn); gel(z,2) = rfrac_denom_mul_scal(d, cd); return z; } /* in rare cases x may be a t_POL, after 0/x for instance -> pol_0() */ static GEN fix_rfrac(GEN x, long d) { GEN z, N, D; if (!d || typ(x) == t_POL) return x; z = cgetg(3, t_RFRAC); N = gel(x,1); D = gel(x,2); if (d > 0) { gel(z, 1) = (typ(N)==t_POL && varn(N)==varn(D))? RgX_shift(N,d) : monomialcopy(N,d,varn(D)); gel(z, 2) = RgX_copy(D); } else { gel(z, 1) = gcopy(N); gel(z, 2) = RgX_shift(D, -d); } return z; } /* assume d != 0 */ static GEN gred_rfrac2_i(GEN n, GEN d) { GEN y, z; long v, vd, vn; n = simplify_shallow(n); if (isrationalzero(n)) return gcopy(n); d = simplify_shallow(d); if (typ(d) != t_POL) return gdiv(n,d); vd = varn(d); if (typ(n) != t_POL) { if (varncmp(vd, gvar(n)) >= 0) return gdiv(n,d); if (varncmp(vd, gvar2(n)) < 0) return gred_rfrac_simple(n,d); pari_err_BUG("gred_rfrac2_i [incompatible variables]"); } vn = varn(n); if (varncmp(vd, vn) < 0) return gred_rfrac_simple(n,d); if (varncmp(vd, vn) > 0) return RgX_Rg_div(n,d); /* now n and d are t_POLs in the same variable */ v = RgX_valrem(n, &n) - RgX_valrem(d, &d); if (!degpol(d)) { n = RgX_Rg_div(n,gel(d,2)); return v? RgX_mulXn(n,v): n; } /* X does not divide gcd(n,d), deg(d) > 0 */ if (!isinexact(n) && !isinexact(d)) { y = RgX_divrem(n, d, &z); if (!signe(z)) { cgiv(z); return v? RgX_mulXn(y, v): y; } z = RgX_gcd(d, z); if (degpol(z)) { n = RgX_div(n,z); d = RgX_div(d,z); } } return fix_rfrac(gred_rfrac_simple(n,d), v); } GEN gred_rfrac2(GEN x1, GEN x2) { pari_sp av = avma; return gerepileupto(av, gred_rfrac2_i(x1, x2)); } /* x1,x2 t_INT, return x1/x2 in reduced form */ GEN gred_frac2(GEN x1, GEN x2) { GEN r, y = dvmdii(x1,x2,&r); pari_sp av; if (r == gen_0) return y; /* gen_0 intended */ av = avma; r = gcdii(x2,r); if (lgefint(r) == 3) { ulong rr = r[2]; avma = av; if (rr == 1) y = mkfraccopy(x1, x2); else { y = cgetg(3,t_FRAC); gel(y,1) = diviuexact(x1, rr); gel(y,2) = diviuexact(x2, rr); } } else { /* rare: r left on stack for efficiency */ y = cgetg(3,t_FRAC); gel(y,1) = diviiexact(x1,r); gel(y,2) = diviiexact(x2,r); } normalize_frac(y); return y; } /*******************************************************************/ /* */ /* CONJUGATION */ /* */ /*******************************************************************/ /* lift( conj(Mod(x, y)) ), assuming degpol(y) = 2, degpol(x) < 2 */ static GEN quad_polmod_conj(GEN x, GEN y) { GEN z, u, v, a, b; pari_sp av; if (typ(x) != t_POL) return gcopy(x); if (varn(x) != varn(y) || degpol(x) <= 0) return RgX_copy(x); a = gel(y,4); u = gel(x,3); /*Mod(ux + v, ax^2 + bx + c)*/ b = gel(y,3); v = gel(x,2); z = cgetg(4, t_POL); z[1] = x[1]; av = avma; gel(z,2) = gerepileupto(av, gsub(v, gdiv(gmul(u,b), a))); gel(z,3) = gneg(u); return z; } static GEN quad_polmod_norm(GEN x, GEN y) { GEN z, u, v, a, b, c; pari_sp av; if (typ(x) != t_POL || varn(x) != varn(y) || degpol(x) <= 0) return gsqr(x); a = gel(y,4); u = gel(x,3); /*Mod(ux + v, ax^2 + bx + c)*/ b = gel(y,3); v = gel(x,2); c = gel(y,2); av = avma; z = gmul(u, gsub(gmul(c,u), gmul(b,v))); if (!gequal1(a)) z = gdiv(z, a); return gerepileupto(av, gadd(z, gsqr(v))); } GEN gconj(GEN x) { long lx, i; GEN y; switch(typ(x)) { case t_INT: case t_REAL: return mpcopy(x); case t_INTMOD: case t_FRAC: case t_PADIC: return gcopy(x); case t_COMPLEX: y = cgetg(3,t_COMPLEX); gel(y,1) = gcopy(gel(x,1)); gel(y,2) = gneg(gel(x,2)); break; case t_QUAD: y = cgetg(4,t_QUAD); gel(y,1) = ZX_copy(gel(x,1)); gel(y,2) = gequal0(gmael(x,1,3))? gcopy(gel(x,2)) : gadd(gel(x,2), gel(x,3)); gel(y,3) = gneg(gel(x,3)); break; case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i= r) { avma = av; return zeropadic(p, e+r); } if (c) { mod = diviiexact(mod, powiu(p,c)); r -= c; e += c; } } u = modii(u, mod); avma = av; z = cgetg(5,t_PADIC); z[1] = evalprecp(r) | evalvalp(e); gel(z,2) = icopy(p); gel(z,3) = icopy(mod); gel(z,4) = icopy(u); return z; } /* return x + y, where y t_PADIC and x is a non-zero t_INT or t_FRAC */ static GEN addQp(GEN x, GEN y) { pari_sp av = avma; long tx,d,r,e, vy = valp(y), py = precp(y); GEN z,q,p1,p2,mod,u, p = gel(y,2); tx = typ(x); e = (tx == t_INT)? Z_pvalrem(x,p,&p1) : Z_pvalrem(gel(x,1),p,&p1) - Z_pvalrem(gel(x,2),p,&p2); d = vy - e; r = d + py; if (r <= 0) { avma = av; return gcopy(y); } mod = gel(y,3); u = gel(y,4); (void)new_chunk(5 + ((lgefint(mod) + lgefint(p)*labs(d)) << 1)); if (d > 0) { q = powiu(p,d); mod = mulii(mod, q); u = mulii(u, q); if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, Fp_inv(p2,mod)); u = addii(u, p1); } else if (d < 0) { q = powiu(p,-d); if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, Fp_inv(p2,mod)); p1 = mulii(p1, q); u = addii(u, p1); r = py; e = vy; } else { long c; if (tx != t_INT && !is_pm1(p2)) p1 = mulii(p1, Fp_inv(p2,mod)); u = addii(u, p1); if (!signe(u) || (c = Z_pvalrem(u,p,&u)) >= r) { avma = av; return zeropadic(p,e+r); } if (c) { mod = diviiexact(mod, powiu(p,c)); r -= c; e += c; } } u = modii(u, mod); avma = av; z = cgetg(5,t_PADIC); z[1] = evalprecp(r) | evalvalp(e); gel(z,2) = icopy(p); gel(z,3) = icopy(mod); gel(z,4) = icopy(u); return z; } /* Mod(x,X) + Mod(y,X) */ #define addsub_polmod_same addsub_polmod_scal /* Mod(x,X) +/- Mod(y,Y) */ static GEN addsub_polmod(GEN X, GEN Y, GEN x, GEN y, GEN(*op)(GEN,GEN)) { long T[3] = { evaltyp(t_POLMOD) | _evallg(3),0,0 }; GEN z = cgetg(3,t_POLMOD); long vx = varn(X), vy = varn(Y); if (vx==vy) { pari_sp av; gel(z,1) = RgX_gcd(X,Y); av = avma; gel(z,2) = gerepileupto(av, gmod(op(x, y), gel(z,1))); return z; } if (varncmp(vx, vy) < 0) { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; } gel(z,2) = op(x, y); return z; } /* Mod(y, Y) +/- x, x scalar or polynomial in same var and reduced degree */ static GEN addsub_polmod_scal(GEN Y, GEN y, GEN x, GEN(*op)(GEN,GEN)) { GEN z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(Y); 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; if (isrationalzero(x)) return gcopy(y); ly = lg(y); l = valp(y); if (l < 3-ly) return gcopy(y); /* l + ly >= 3 */ if (l < 0) { z = cgetg(ly,t_SER); z[1] = y[1]; 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); } 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); 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 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); case t_RFRAC: vx = varn(gel(x,2)); vy = varn(gel(y,2)); if (vx != vy) { if (varncmp(vx, vy) < 0) return add_rfrac_scal(x, y); else return add_rfrac_scal(y, x); } return add_rfrac(x,y); case t_VEC: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgV_add(x,y); case t_COL: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgC_add(x,y); case t_MAT: lx = lg(x); if (lg(y) != lx) pari_err_OP("+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y); return RgM_add(x,y); default: pari_err_TYPE2("+",x,y); } /* tx != ty */ if (tx > ty) { swap(x,y); lswap(tx,ty); } if (is_const_t(ty)) switch(tx) /* tx < ty, is_const_t(tx) && is_const_t(ty) */ { case t_INT: switch(ty) { case t_REAL: return addir(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return add_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1))); case t_FRAC: z = cgetg(3,t_FRAC); gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulii(gel(y,2),x))); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: return addRc(x, y); case t_PADIC: if (!signe(x)) return gcopy(y); return addQp(x,y); case t_QUAD: return addRq(x, y); case t_FFELT: return FF_Z_add(y,x); } case t_REAL: switch(ty) { case t_FRAC: if (!signe(gel(y,1))) return rcopy(x); if (!signe(x)) { lx = expi(gel(y,1)) - expi(gel(y,2)) - expo(x); return lx <= 0? rcopy(x): fractor(y, nbits2prec(lx)); } av=avma; z=addir(gel(y,1),mulir(gel(y,2),x)); tetpil=avma; return gerepile(av,tetpil,divri(z,gel(y,2))); case t_COMPLEX: return addRc(x, y); case t_QUAD: return gequal0(y)? rcopy(x): addqf(y, x, lg(x)); default: pari_err_TYPE2("+",x,y); } case t_INTMOD: switch(ty) { case t_FRAC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); p1 = Fp_div(gel(y,1), gel(y,2), X); return add_intmod_same(z, X, p1, gel(x,2)); } case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("+",x,y); return FF_Z_add(y,gel(x,2)); case t_COMPLEX: return addRc(x, y); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return add_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_QUAD: return addRq(x, y); } case t_FRAC: switch (ty) { case t_COMPLEX: return addRc(x, y); case t_PADIC: if (!signe(gel(x,1))) return gcopy(y); return addQp(x,y); case t_QUAD: return addRq(x, y); case t_FFELT: return FF_Q_add(y, x); } case t_FFELT: pari_err_TYPE2("+",x,y); case t_COMPLEX: switch(ty) { case t_PADIC: return Zp_nosquare_m1(gel(y,2))? addRc(y, x): addTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("+",x,y); return gequal0(y)? gcopy(x): addqf(y, x, lx); } case t_PADIC: /* ty == t_QUAD */ return (kro_quad(y,gel(x,2)) == -1)? addRq(x, y): addTp(y, x); } /* tx < ty, !is_const_t(y) */ switch(ty) { case t_MAT: if (is_matvec_t(tx)) pari_err_TYPE2("+",x,y); if (isrationalzero(x)) return gcopy(y); return RgM_Rg_add(y, x); case t_COL: if (tx == t_VEC) pari_err_TYPE2("+",x,y); return RgC_Rg_add(y, x); case t_POLMOD: /* is_const_t(tx) in this case */ return addsub_polmod_scal(gel(y,1), gel(y,2), x, &gadd); } if (is_scalar_t(tx)) { if (tx == t_POLMOD) { vx = varn(gel(x,1)); vy = gvar(y); if (vx == vy) y = gmod(y, gel(x,1)); /* error if ty == t_SER */ else if (varncmp(vx,vy) > 0) return add_scal(y, x, ty); return addsub_polmod_scal(gel(x,1), gel(x,2), y, &gadd); } return add_scal(y, x, ty); } /* x and y are not scalars, ty != t_MAT */ vx = gvar(x); vy = gvar(y); if (vx != vy) { /* x or y is treated as a scalar */ if (is_vec_t(tx) || is_vec_t(ty)) pari_err_TYPE2("+",x,y); return (varncmp(vx, vy) < 0)? add_scal(x, y, tx) : add_scal(y, x, ty); } /* vx = vy */ switch(tx) { case t_POL: switch (ty) { case t_SER: if (lg(x) == 2) return gcopy(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); settyp(p1, t_VECSMALL); /* p1 left on stack */ return y; case t_RFRAC: return add_rfrac_scal(y, x); } break; case t_SER: if (ty == t_RFRAC) { GEN n, d; long vn, vd; av = avma; n = gel(y,1); vn = gval(n, vy); d = gel(y,2); vd = RgX_valrem(d, &d); l = lg(x) + valp(x) - (vn - vd); if (l < 3) { avma = av; return gcopy(x); } /* take advantage of y = t^n ! */ if (degpol(d)) y = gdiv(n, RgX_to_ser_inexact(d,l)); else { y = gdiv(n, gel(d,2)); if (gvar(y) == vy) y = RgX_to_ser(y,l); else y = scalarser(y, vy, l); } setvalp(y, valp(y) - vd); return gerepileupto(av, gadd(y, x)); } break; } pari_err_TYPE2("+",x,y); return NULL; /* not reached */ } GEN gaddsg(long x, GEN y) { long ty = typ(y); GEN z; switch(ty) { case t_INT: return addsi(x,y); case t_REAL: return addsr(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return add_intmod_same(z, gel(y,1), gel(y,2), modsi(x, gel(y,1))); case t_FRAC: z = cgetg(3,t_FRAC); gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulis(gel(y,2),x))); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,1) = gaddsg(x, gel(y,1)); gel(z,2) = gcopy(gel(y,2)); return z; default: return gadd(stoi(x), y); } } GEN gsubsg(long x, GEN y) { GEN z, a, b; pari_sp av; switch(typ(y)) { case t_INT: return subsi(x,y); case t_REAL: return subsr(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); a = gel(y,1); b = gel(y,2); return add_intmod_same(z, a, Fp_neg(b,a), modsi(x, a)); case t_FRAC: z = cgetg(3,t_FRAC); a = gel(y,1); b = gel(y,2); gel(z,1) = gerepileuptoint((pari_sp)z, subii(mulis(b,x), a)); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,1) = gsubsg(x, gel(y,1)); gel(z,2) = gneg(gel(y,2)); return z; } av = avma; return gerepileupto(av, gadd(stoi(x), gneg_i(y))); } /********************************************************************/ /** **/ /** SUBTRACTION **/ /** **/ /********************************************************************/ GEN gsub(GEN x, GEN y) { long tx = typ(x), ty = typ(y); pari_sp av; GEN z; if (tx == ty) switch(tx) /* shortcut to generic case */ { case t_INT: return subii(x,y); case t_REAL: return subrr(x,y); case t_INTMOD: { GEN p1, X = gel(x,1), Y = gel(y,1); z = cgetg(3,t_INTMOD); if (X==Y || equalii(X,Y)) return sub_intmod_same(z, X, gel(x,2), gel(y,2)); gel(z,1) = gcdii(X,Y); av = avma; p1 = subii(gel(x,2),gel(y,2)); gel(z,2) = gerepileuptoint(av, modii(p1, gel(z,1))); return z; } case t_FRAC: return addsub_frac(x,y, subii); case t_COMPLEX: z = cgetg(3,t_COMPLEX); gel(z,2) = gsub(gel(x,2),gel(y,2)); if (isintzero(gel(z,2))) { avma = (pari_sp)(z+3); return gsub(gel(x,1),gel(y,1)); } gel(z,1) = gsub(gel(x,1),gel(y,1)); return z; case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("+",x,y); return addsub_pp(x,y, subii); case t_QUAD: z = cgetg(4,t_QUAD); if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("+",x,y); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gsub(gel(x,2),gel(y,2)); gel(z,3) = gsub(gel(x,3),gel(y,3)); return z; case t_POLMOD: if (RgX_equal_var(gel(x,1), gel(y,1))) return addsub_polmod_same(gel(x,1), gel(x,2), gel(y,2), &gsub); return addsub_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2), &gsub); case t_FFELT: return FF_sub(x,y); case t_POL: { long vx = varn(x); long vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_sub(x, y); else return Rg_RgX_sub(x, y); } return RgX_sub(x, y); } case t_VEC: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgV_sub(x,y); case t_COL: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgC_sub(x,y); case t_MAT: { long lx = lg(x); if (lg(y) != lx) pari_err_OP("+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y); return RgM_sub(x,y); } case t_RFRAC: case t_SER: break; default: pari_err_TYPE2("+",x,y); } av = avma; return gerepileupto(av, gadd(x,gneg_i(y))); } /********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /********************************************************************/ static GEN mul_ser_scal(GEN y, GEN x) { long ly, i; GEN z; if (isrationalzero(x)) return zeropol(varn(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); } /* (n/d) * x, x "scalar" or polynomial in the same variable as d * [n/d a valid RFRAC] */ static GEN mul_rfrac_scal(GEN n, GEN d, GEN x) { pari_sp av = avma; GEN z; switch(typ(x)) { case t_PADIC: n = gmul(n, x); d = gcvtop(d, gel(x,2), signe(gel(x,4))? precp(x): 1); return gerepileupto(av, gdiv(n,d)); case t_INTMOD: case t_POLMOD: n = gmul(n, x); d = gmul(d, gmodulo(gen_1, gel(x,1))); return gerepileupto(av, gdiv(n,d)); } z = gred_rfrac2_i(x, d); n = simplify_shallow(n); if (typ(z) == t_RFRAC) { n = gmul(gel(z,1), n); d = gel(z,2); if (typ(n) == t_POL && varncmp(varn(n), varn(d)) < 0) z = RgX_Rg_div(n, d); else z = gred_rfrac_simple(n, d); } else z = gmul(z, n); return gerepileupto(av, z); } static GEN mul_scal(GEN y, GEN x, long ty) { switch(ty) { case t_POL: if (lg(y) == 2) return scalarpol(gmul(gen_0,x), varn(y)); return RgX_Rg_mul(y, x); case t_SER: return mul_ser_scal(y, x); case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x); case t_QFI: case t_QFR: if (typ(x) == t_INT && gequal1(x)) return gcopy(y); /* fall through */ } pari_err_TYPE2("*",x,y); return NULL; /* not reached */ } static GEN mul_gen_rfrac(GEN X, GEN Y) { GEN y1 = gel(Y,1), y2 = gel(Y,2); long vx = gvar(X), vy = varn(y2); return (varncmp(vx, vy) <= 0)? mul_scal(Y, X, typ(Y)): gred_rfrac_simple(gmul(y1,X), y2); } /* (x1/x2) * (y1/y2) */ static GEN mul_rfrac(GEN x1, GEN x2, GEN y1, GEN y2) { GEN z, X, Y; pari_sp av = avma; X = gred_rfrac2_i(x1, y2); Y = gred_rfrac2_i(y1, x2); if (typ(X) == t_RFRAC) { if (typ(Y) == t_RFRAC) { x1 = gel(X,1); x2 = gel(X,2); y1 = gel(Y,1); y2 = gel(Y,2); z = gred_rfrac_simple(gmul(x1,y1), gmul(x2,y2)); } else z = mul_gen_rfrac(Y, X); } else if (typ(Y) == t_RFRAC) z = mul_gen_rfrac(X, Y); else z = gmul(X, Y); return gerepileupto(av, z); } /* (x1/x2) /y2, x2 and y2 are t_POL in the same variable */ static GEN div_rfrac_pol(GEN x1, GEN x2, GEN y2) { pari_sp av = avma; GEN X = gred_rfrac2_i(x1, y2); if (typ(X) == t_RFRAC && varn(gel(X,2)) == varn(x2)) { x2 = RgX_mul(gel(X,2), x2); x1 = gel(X,1); } else x1 = X; return gerepileupto(av, gred_rfrac_simple(x1, x2)); } /* Mod(y, Y) * x, assuming x scalar */ static GEN mul_polmod_scal(GEN Y, GEN y, GEN x) { GEN z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(Y); gel(z,2) = gmul(x,y); return z; } /* cf mulqq */ static GEN quad_polmod_mul(GEN P, GEN x, GEN y) { GEN T = cgetg(4, t_POL), b = gel(P,3), c = gel(P,2), p1, p2, p3, p4; pari_sp tetpil, av = avma; T[1] = x[1]; p2 = gmul(gel(x,2), gel(y,2)); p3 = gmul(gel(x,3), gel(y,3)); p1 = gmul(gneg_i(c),p3); /* operands are usually small: gadd ~ gmul and Karatsuba is a waste */ if (typ(b) == t_INT) { if (signe(b)) { p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2))); if (is_pm1(b)) { if (signe(b) > 0) p3 = gneg(p3); } else p3 = gmul(negi(b), p3); } else { p3 = gmul(gel(x,2),gel(y,3)); p4 = gmul(gel(x,3),gel(y,2)); } } else { p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2))); p3 = gmul(gneg_i(b), p3); } tetpil = avma; gel(T,2) = gadd(p2, p1); gel(T,3) = gadd(p4, p3); gerepilecoeffssp(av,tetpil,T+2,2); return normalizepol_lg(T,4); } /* Mod(x,T) * Mod(y,T) */ static GEN mul_polmod_same(GEN T, GEN x, GEN y) { GEN z = cgetg(3,t_POLMOD), a; long v = varn(T), lx = lg(x), ly = lg(y); gel(z,1) = RgX_copy(T); /* x * y mod T optimised */ if (typ(x) != t_POL || varn(x) != v || lx <= 3 || typ(y) != t_POL || varn(y) != v || ly <= 3) a = gmul(x, y); else { if (lg(T) == 5 && isint1(gel(T,4))) /* quadratic fields */ a = quad_polmod_mul(T, x, y); else { pari_sp av = avma; GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(x, &p) && RgX_is_FpX(y, &p) && p) { T = RgX_to_FpX(T, p); x = RgX_to_FpX(x, p); y = RgX_to_FpX(y, p); if (lgefint(p) == 3) { ulong pp = p[2]; a = Flxq_mul(ZX_to_Flx(x, pp), ZX_to_Flx(y, pp), ZX_to_Flx(T, pp), pp); a = Flx_to_ZX(a); } else a = FpXQ_mul(x, y, T, p); a = FpX_to_mod(a, p); } else a = RgXQ_mul(x, y, gel(z,1)); a = gerepileupto(av, a); } } gel(z,2) = a; return z; } static GEN sqr_polmod(GEN T, GEN x) { GEN a, z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(T); if (typ(x) != t_POL || varn(x) != varn(T) || lg(x) <= 3) a = gsqr(x); else { pari_sp av = avma; GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(x, &p) && p) { T = RgX_to_FpX(T, p); x = RgX_to_FpX(x, p); if (lgefint(p) == 3) { ulong pp = p[2]; a = Flxq_sqr(ZX_to_Flx(x, pp), ZX_to_Flx(T, pp), pp); a = Flx_to_ZX(a); } else a = FpXQ_sqr(x, T, p); a = FpX_to_mod(a, p); } else a = RgXQ_sqr(x, gel(z,1)); a = gerepileupto(av, a); } gel(z,2) = a; return z; } /* Mod(x,X) * Mod(y,Y) */ static GEN mul_polmod(GEN X, GEN Y, GEN x, GEN y) { long T[3] = { evaltyp(t_POLMOD) | _evallg(3),0,0 }; long vx = varn(X), vy = varn(Y); GEN z = cgetg(3,t_POLMOD); if (vx==vy) { pari_sp av; gel(z,1) = RgX_gcd(X,Y); av = avma; gel(z,2) = gerepileupto(av, gmod(gmul(x, y), gel(z,1))); return z; } if (varncmp(vx, vy) < 0) { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; } gel(z,2) = gmul(x, y); return z; } #if 0 /* used by 3M only */ /* set z = x+y and return 1 if x,y have the same sign * set z = x-y and return 0 otherwise */ static int did_add(GEN x, GEN y, GEN *z) { long tx = typ(x), ty = typ(y); if (tx == ty) switch(tx) { case t_INT: *z = addii(x,y); return 1; case t_FRAC: *z = addsub_frac(x,y,addii); return 1; case t_REAL: if (signe(x) == -signe(y)) { *z = subrr(x,y); return 0; } else { *z = addrr(x,y); return 1; } } if (tx == t_REAL) switch(ty) { case t_INT: if (signe(x) == -signe(y)) { *z = subri(x,y); return 0; } else { *z = addri(x,y); return 1; } case t_FRAC: if (signe(x) == -signe(gel(y,1))) { *z = gsub(x,y); return 0; } else { *z = gadd(x,y); return 1; } } else if (ty == t_REAL) switch(tx) { case t_INT: if (signe(x) == -signe(y)) { *z = subir(x,y); return 0; } else { *z = addir(x,y); return 1; } case t_FRAC: if (signe(gel(x,1)) == -signe(y)) { *z = gsub(x,y); return 0; } else { *z = gadd(x,y); return 1; } } *z = gadd(x,y); return 1; } #endif /* x * I * y, x t_COMPLEX with non-intzero real part, y non-intzero "scalar" */ static GEN mulcIR(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); pari_sp av = avma; gel(z,1) = gerepileupto(av, gneg(gmul(y,gel(x,2)))); gel(z,2) = gmul(y, gel(x,1)); return z; } /* x,y COMPLEX */ static GEN mulcc(GEN x, GEN y) { GEN xr = gel(x,1), xi = gel(x,2); GEN yr = gel(y,1), yi = gel(y,2); GEN p1, p2, p3, p4, z; pari_sp tetpil, av; if (isintzero(xr)) { if (isintzero(yr)) { av = avma; return gerepileupto(av, gneg(gmul(xi,yi))); } return mulcIR(y, xi); } if (isintzero(yr)) return mulcIR(x, yi); z = cgetg(3,t_COMPLEX); av = avma; #if 0 /* 3M method avoiding catastrophic cancellation, BUT loses accuracy due to * e.g. xr + xi if exponents differ */ if (did_add(xr, xi, &p3)) { if (did_add(yr, yi, &p4)) { /* R = xr*yr - xi*yi * I = (xr+xi)(yr+yi) - xr*yr - xi*yi */ p1 = gmul(xr,yr); p2 = gmul(xi,yi); p2 = gneg(p2); p3 = gmul(p3, p4); p4 = gsub(p2, p1); } else { /* R = (xr + xi) * (yr - yi) + (xr * yi - xi * yr) * I = xr*yi + xi*yr */ p1 = gmul(p3,p4); p3 = gmul(xr,yi); p4 = gmul(xi,yr); p2 = gsub(p3, p4); } } else { if (did_add(yr, yi, &p4)) { /* R = (xr - xi) * (yr + yi) + (xi * yr - xr * yi) * I = xr*yi +xi*yr */ p1 = gmul(p3,p4); p3 = gmul(xr,yi); p4 = gmul(xi,yr); p2 = gsub(p4, p3); } else { /* R = xr*yr - xi*yi * I = -(xr-xi)(yr-yi) + xr*yr + xi*yi */ p3 = gneg( gmul(p3, p4) ); p1 = gmul(xr,yr); p2 = gmul(xi,yi); p4 = gadd(p1, p2); p2 = gneg(p2); } } tetpil = avma; 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(yi)==t_INT) { /* 3M formula */ p3 = addii(xr,xi); p4 = addii(yr,yi); p1 = mulii(xr,yr); p2 = mulii(xi,yi); p3 = mulii(p3,p4); p4 = addii(p2,p1); tetpil = avma; gel(z,1) = subii(p1,p2); gel(z,2) = subii(p3,p4); if (!signe(gel(z,2))) return gerepileuptoint((pari_sp)(z+3), gel(z,1)); } else { /* naive 4M formula: avoid all loss of accuracy */ p1 = gmul(xr,yr); p2 = gmul(xi,yi); p3 = gmul(xr,yi); p4 = gmul(xi,yr); tetpil = avma; gel(z,1) = gsub(p1,p2); gel(z,2) = gadd(p3,p4); if (isintzero(gel(z,2))) { cgiv(gel(z,2)); return gerepileupto((pari_sp)(z+3), gel(z,1)); } } #endif gerepilecoeffssp(av,tetpil, z+1,2); return z; } /* x,y PADIC */ static GEN mulpp(GEN x, GEN y) { long l = valp(x) + valp(y); pari_sp av; GEN z, t; if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("*",x,y); if (!signe(gel(x,4))) return zeropadic(gel(x,2), l); if (!signe(gel(y,4))) return zeropadic(gel(x,2), l); t = (precp(x) > precp(y))? y: x; z = cgetp(t); setvalp(z,l); av = avma; affii(remii(mulii(gel(x,4),gel(y,4)), gel(t,3)), gel(z,4)); avma = av; return z; } /* x,y QUAD */ static GEN mulqq(GEN x, GEN y) { GEN z = cgetg(4,t_QUAD); GEN p1, p2, p3, p4, P = gel(x,1), b = gel(P,3), c = gel(P,2); pari_sp av, tetpil; if (!ZX_equal(P, gel(y,1))) pari_err_OP("*",x,y); gel(z,1) = ZX_copy(P); av = avma; p2 = gmul(gel(x,2),gel(y,2)); p3 = gmul(gel(x,3),gel(y,3)); p1 = gmul(gneg_i(c),p3); if (signe(b)) p4 = gadd(gmul(gel(x,2),gel(y,3)), gmul(gel(x,3),gel(y,2))); else { p3 = gmul(gel(x,2),gel(y,3)); p4 = gmul(gel(x,3),gel(y,2)); } tetpil = avma; gel(z,2) = gadd(p2,p1); gel(z,3) = gadd(p4,p3); gerepilecoeffssp(av,tetpil,z+2,2); return z; } GEN mulcxI(GEN x) { GEN z; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return mkcomplex(gen_0, x); case t_COMPLEX: if (isintzero(gel(x,1))) return gneg(gel(x,2)); z = cgetg(3,t_COMPLEX); gel(z,1) = gneg(gel(x,2)); gel(z,2) = gel(x,1); return z; default: return gmul(gen_I(), x); } } GEN mulcxmI(GEN x) { GEN z; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return mkcomplex(gen_0, gneg(x)); case t_COMPLEX: if (isintzero(gel(x,1))) return gel(x,2); z = cgetg(3,t_COMPLEX); gel(z,1) = gel(x,2); gel(z,2) = gneg(gel(x,1)); return z; default: return gmul(mkcomplex(gen_0, gen_m1), x); } } /* fill in coefficients of t_SER z from coeffs of t_POL y */ static GEN fill_ser(GEN z, GEN y) { long i, lx = lg(z), ly = lg(y); if (ly >= lx) { for (i = 2; i < lx; i++) gel(z,i) = gel(y,i); } else { for (i = 2; i < ly; i++) gel(z,i) = gel(y,i); for ( ; i < lx; i++) gel(z,i) = gen_0; } return normalize(z); } GEN gmul(GEN x, GEN y) { long tx, ty, lx, ly, vx, vy, i, l; pari_sp av, tetpil; GEN z, p1, p2; if (x == y) return gsqr(x); tx = typ(x); ty = typ(y); if (tx == ty) switch(tx) { case t_INT: return mulii(x,y); case t_REAL: return mulrr(x,y); case t_INTMOD: { GEN X = gel(x,1), Y = gel(y,1); 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,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z; } case t_FRAC: { GEN x1 = gel(x,1), x2 = gel(x,2); GEN y1 = gel(y,1), y2 = gel(y,2); z=cgetg(3,t_FRAC); p1 = gcdii(x1, y2); if (!is_pm1(p1)) { x1 = diviiexact(x1,p1); y2 = diviiexact(y2,p1); } p1 = gcdii(x2, y1); if (!is_pm1(p1)) { x2 = diviiexact(x2,p1); y1 = diviiexact(y1,p1); } tetpil = avma; gel(z,2) = mulii(x2,y2); gel(z,1) = mulii(x1,y1); fix_frac_if_int_GC(z,tetpil); return z; } case t_COMPLEX: return mulcc(x, y); case t_PADIC: return mulpp(x, y); case t_QUAD: return mulqq(x, y); case t_FFELT: return FF_mul(x, y); case t_POLMOD: if (RgX_equal_var(gel(x,1), gel(y,1))) return mul_polmod_same(gel(x,1), gel(x,2), gel(y,2)); return mul_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2)); case t_POL: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_mul(x, y); else return RgX_Rg_mul(y, x); } if (RgX_is_ZX(x) && RgX_is_ZX(y)) return ZX_mul(x,y); return RgX_mul(x, y); case t_SER: { GEN p = NULL; vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return mul_ser_scal(x, y); else return mul_ser_scal(y, x); } lx = lg(x); ly = lg(y); if (lx > ly) { lx = ly; swap(x, y); } if (lx == 2) return zeroser(vx, valp(x)+valp(y)); z = cgetg(lx,t_SER); z[1] = evalvalp(valp(x)+valp(y)) | evalvarn(vx) | evalsigne(1); x = ser2pol_i(x, lx); y = ser2pol_i(y, lx); if (RgX_is_FpX(x,&p) && RgX_is_FpX(y,&p)) { if (!p) y = ZX_mul(x,y); else { x = RgX_to_FpX(x, p); y = RgX_to_FpX(y, p); y = FpX_to_mod(ZX_mul(x,y), p); } } else y = RgX_mullow(x, y, lx-2); z = fill_ser(z, y); return gerepilecopy((pari_sp)(z + lx), z); } case t_QFI: return qficomp(x,y); case t_QFR: return qfrcomp(x,y); case t_RFRAC: return mul_rfrac(gel(x,1),gel(x,2), gel(y,1),gel(y,2)); case t_MAT: return RgM_mul(x, y); case t_VECSMALL: /* multiply as permutation. cf perm_mul */ z = cgetg_copy(x, &l); if (l != lg(y)) break; for (i=1; i= l) pari_err_TYPE2("*",x,y); z[i] = x[yi]; } return z; default: pari_err_TYPE2("*",x,y); } /* tx != ty */ if (is_const_t(ty) && is_const_t(tx)) { if (tx > ty) { swap(x,y); lswap(tx,ty); } switch(tx) { case t_INT: switch(ty) { case t_REAL: return signe(x)? mulir(x,y): gen_0; case t_INTMOD: z = cgetg(3, t_INTMOD); return mul_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1))); case t_FRAC: if (!signe(x)) return gen_0; z=cgetg(3,t_FRAC); p1 = gcdii(x,gel(y,2)); if (is_pm1(p1)) { avma = (pari_sp)z; gel(z,2) = icopy(gel(y,2)); gel(z,1) = mulii(gel(y,1), x); } else { x = diviiexact(x,p1); tetpil = avma; gel(z,2) = diviiexact(gel(y,2), p1); gel(z,1) = mulii(gel(y,1), x); fix_frac_if_int_GC(z,tetpil); } return z; case t_COMPLEX: return signe(x)? mulRc(x, y): gen_0; case t_PADIC: return signe(x)? mulTp(x, y): gen_0; case t_QUAD: return mulRq(x,y); case t_FFELT: return FF_Z_mul(y,x); } case t_REAL: switch(ty) { case t_FRAC: return mulrfrac(x, y); case t_COMPLEX: return mulRc(x, y); case t_QUAD: return mulqf(y, x, lg(x)); default: pari_err_TYPE2("*",x,y); } case t_INTMOD: switch(ty) { case t_FRAC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); p1 = Fp_mul(gel(y,1), gel(x,2), X); return div_intmod_same(z, X, p1, remii(gel(y,2), X)); } case t_COMPLEX: return mulRc_direct(x,y); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return mul_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_QUAD: return mulRq(x, y); case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("*",x,y); return FF_Z_mul(y,gel(x,2)); } case t_FRAC: switch(ty) { case t_COMPLEX: return mulRc(x, y); case t_PADIC: return signe(gel(x,1))? mulTp(x, y): gen_0; case t_QUAD: return mulRq(x, y); case t_FFELT: return FF_Z_Z_muldiv(y, gel(x,1),gel(x,2)); } case t_FFELT: pari_err_TYPE2("*",x,y); case t_COMPLEX: switch(ty) { case t_PADIC: return Zp_nosquare_m1(gel(y,2))? mulRc(y, x): mulTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("*",x,y); return mulqf(y, x, lx); } case t_PADIC: /* ty == t_QUAD */ return (kro_quad(y,gel(x,2))== -1)? mulRq(x, y): mulTp(y, x); } } if (is_matvec_t(ty)) { if (!is_matvec_t(tx)) { if (is_noncalc_t(tx)) pari_err_TYPE2( "*",x,y); /* necessary if ly = 1 */ z = cgetg_copy(y, &ly); for (i=1; i ty) { swap(x,y); lswap(tx,ty); } /* tx < ty, !ismatvec(x and y) */ if (ty == t_POLMOD) /* is_const_t(tx) in this case */ return mul_polmod_scal(gel(y,1), gel(y,2), x); if (is_scalar_t(tx)) { if (tx == t_POLMOD) { vx = varn(gel(x,1)); vy = gvar(y); if (vx != vy) { if (varncmp(vx,vy) > 0) return mul_scal(y, x, ty); return mul_polmod_scal(gel(x,1), gel(x,2), y); } /* error if ty == t_SER */ av = avma; y = gmod(y, gel(x,1)); return gerepileupto(av, mul_polmod_same(gel(x,1), gel(x,2), y)); } return mul_scal(y, x, ty); } /* x and y are not scalars, nor matvec */ vx = gvar(x); vy = gvar(y); if (vx != vy) /* x or y is treated as a scalar */ return (varncmp(vx, vy) < 0)? mul_scal(x, y, tx) : mul_scal(y, x, ty); /* vx = vy */ switch(tx) { case t_POL: switch (ty) { case t_SER: { long vn; if (lg(x) == 2) return zeropol(vx); if (lg(y) == 2) return zeroser(vx, valp(y)+RgX_val(x)); av = avma; vn = RgX_valrem(x, &x); /* take advantage of x = t^n ! */ if (degpol(x)) { p1 = RgX_to_ser(x,lg(y)); if (vn) settyp(x, t_VECSMALL); /* *new* x left on stack */ p2 = gmul(p1,y); settyp(p1, t_VECSMALL); /* p1 left on stack */ } else { avma = av; p2 = mul_ser_scal(y, gel(x,2)); } setvalp(p2, valp(p2) + vn); return p2; } case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x); } break; case t_SER: switch (ty) { case t_RFRAC: av = avma; return gerepileupto(av, gdiv(gmul(gel(y,1),x), gel(y,2))); } break; } pari_err_TYPE2("*",x,y); return NULL; /* not reached */ } int 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) return 0; Q = RgX_to_FpX(*pol, *p); P = RgX_to_FpXQX(P, Q, *p); *x = ZXX_to_Kronecker(P, degpol(Q)); *pol = Q; return 1; } GEN sqr_ser_part(GEN x, long l1, long l2) { long i, j, l; pari_sp av; GEN Z, z, p1, p2; long mi; if (l2 < l1) return zeroser(varn(x), 2*valp(x)); p2 = cgetg(l2+2, t_VECSMALL)+1; /* left on stack on exit */ Z = cgetg(l2-l1+3, t_SER); Z[1] = evalvalp(2*valp(x)) | evalvarn(varn(x)); z = Z + 2-l1; x += 2; mi = 0; for (i=0; i>1) - 1; for (j=i-mi; j<=minss(l,mi); j++) if (p2[j] && p2[i-j]) p1 = gadd(p1, gmul(gel(x,j),gel(x,i-j))); p1 = gshift(p1,1); if ((i&1) == 0 && p2[i>>1]) p1 = gadd(p1, gsqr(gel(x,i>>1))); gel(z,i) = gerepileupto(av,p1); } return Z; } GEN gsqr(GEN x) { long i, lx; pari_sp av, tetpil; GEN z, p1, p2, p3, p4; switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_INTMOD: { GEN X = gel(x,1); z = cgetg(3,t_INTMOD); gel(z,2) = gerepileuptoint((pari_sp)z, remii(sqri(gel(x,2)), X)); gel(z,1) = icopy(X); return z; } case t_FRAC: return sqrfrac(x); case t_COMPLEX: if (isintzero(gel(x,1))) { av = avma; return gerepileupto(av, gneg(gsqr(gel(x,2)))); } z = cgetg(3,t_COMPLEX); av = avma; p1 = gadd(gel(x,1),gel(x,2)); p2 = gsub(gel(x,1), gel(x,2)); p3 = gmul(gel(x,1),gel(x,2)); tetpil = avma; gel(z,1) = gmul(p1,p2); gel(z,2) = gshift(p3,1); gerepilecoeffssp(av,tetpil,z+1,2); return z; case t_PADIC: z = cgetg(5,t_PADIC); i = (equaliu(gel(x,2), 2) && signe(gel(x,4)))? 1: 0; if (i && precp(x) == 1) i = 2; /* (1 + O(2))^2 = 1 + O(2^3) */ z[1] = evalprecp(precp(x)+i) | evalvalp(valp(x) << 1); gel(z,2) = icopy(gel(x,2)); gel(z,3) = shifti(gel(x,3), i); av = avma; gel(z,4) = gerepileuptoint(av, remii(sqri(gel(x,4)), gel(z,3))); return z; case t_QUAD: z = cgetg(4,t_QUAD); p1 = gel(x,1); gel(z,1) = ZX_copy(p1); av = avma; p2 = gsqr(gel(x,2)); p3 = gsqr(gel(x,3)); p4 = gmul(gneg_i(gel(p1,2)),p3); if (gequal0(gel(p1,3))) { tetpil = avma; gel(z,2) = gerepile(av,tetpil,gadd(p4,p2)); av = avma; p2 = gmul(gel(x,2),gel(x,3)); tetpil = avma; gel(z,3) = gerepile(av,tetpil,gmul2n(p2,1)); return z; } p1 = gmul2n(gmul(gel(x,2),gel(x,3)), 1); tetpil = avma; gel(z,2) = gadd(p2,p4); gel(z,3) = gadd(p1,p3); gerepilecoeffssp(av,tetpil,z+2,2); return z; case t_POLMOD: return sqr_polmod(gel(x,1), gel(x,2)); case t_FFELT: return FF_sqr(x); case t_POL: { GEN a = x, p = NULL, pol = NULL; av = avma; if (RgX_is_ZX(x)) return ZX_sqr(x); if (ff_poltype(&x,&p,&pol)) { z = ZX_sqr(x); if (p) z = FpX_to_mod(z,p); if (pol) z = Kronecker_to_mod(z,pol); z = gerepileupto(av, z); } else { avma = av; z = RgX_sqr(a); } return z; } case t_SER: lx = lg(x); if (lx < 40) return normalize( sqr_ser_part(x, 0, lx-3) ); else { pari_sp av = avma; GEN z = cgetg(lx,t_SER), p = NULL; z[1] = evalvalp(2*valp(x)) | evalvarn(varn(x)) | evalsigne(1); x = ser2pol_i(x,lx); if (RgX_is_FpX(x,&p)) { if (!p) x = ZX_sqr(x); else { x = RgX_to_FpX(x, p); x = FpX_to_mod(ZX_sqr(x), p); } } else x = RgX_sqrlow(x, lx-2); z = fill_ser(z, x); return gerepilecopy(av, z); } case t_RFRAC: z = cgetg(3,t_RFRAC); gel(z,1) = gsqr(gel(x,1)); gel(z,2) = gsqr(gel(x,2)); return z; case t_MAT: return RgM_sqr(x); case t_QFR: return qfrsqr(x); case t_QFI: return qfisqr(x); case t_VECSMALL: z = cgetg_copy(x, &lx); for (i=1; i= lx) pari_err_TYPE2("*",x,x); z[i] = x[xi]; } return z; } pari_err_TYPE2("*",x,x); return NULL; /* not reached */ } /********************************************************************/ /** **/ /** DIVISION **/ /** **/ /********************************************************************/ static GEN div_rfrac_scal(GEN x, GEN y) { pari_sp av = avma; GEN d = rfrac_denom_mul_scal(gel(x,2), y); return gerepileupto(av, gred_rfrac_simple(gel(x,1), d)); } static GEN 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)) { 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 div_rfrac(GEN x, GEN y) { return mul_rfrac(gel(x,1),gel(x,2), gel(y,2),gel(y,1)); } static GEN div_ser_scal(GEN x, GEN y) { long i, lx; GEN z = cgetg_copy(x, &lx); z[1] = x[1]; for (i=2; i 2; l--, ly--, y++) { y_lead = gel(y,2); if (!gequal0(y_lead)) break; } if (ly <= 2) pari_err_INV("div_ser", y); } if (ly < lx) lx = ly; p2 = cgetg(lx, t_VECSMALL); /* left on stack for efficiency */ for (i=3; i b) { M = gel(y,3); } else { M = gel(x,3); b = a; } z = cgetg(5, t_PADIC); z[1] = _evalprecp(b) | evalvalp(valp(x) - valp(y)); gel(z,2) = icopy(gel(x,2)); gel(z,3) = icopy(M); av = avma; gel(z,4) = gerepileuptoint(av, remii(mulii(gel(x,4), Fp_inv(gel(y,4), M)), M) ); return z; } static GEN div_polmod_same(GEN T, GEN x, GEN y) { long v = varn(T); GEN a, z = cgetg(3, t_POLMOD); gel(z,1) = RgX_copy(T); if (typ(y) != t_POL || varn(y) != v || lg(y) <= 3) a = gdiv(x, y); else if (typ(x) != t_POL || varn(x) != v || lg(x) <= 3) { pari_sp av = avma; a = gerepileupto(av, gmul(x, RgXQ_inv(y, T))); } else if (degpol(T) == 2 && isint1(gel(T,4))) /* quadratic fields */ { pari_sp av = avma; a = quad_polmod_mul(T, x, quad_polmod_conj(y, T)); a = RgX_Rg_div(a, quad_polmod_norm(y, T)); a = gerepileupto(av, a); } else { pari_sp av = avma; GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(x, &p) && RgX_is_FpX(y, &p) && p) { T = RgX_to_FpX(T, p); x = RgX_to_FpX(x, p); y = RgX_to_FpX(y, p); if (lgefint(p) == 3) { ulong pp = p[2]; x = ZX_to_Flx(x, pp); y = ZX_to_Flx(y, pp); T = ZX_to_Flx(T, pp); a = Flxq_mul(x, Flxq_inv(y,T,pp),T,pp); a = Flx_to_ZX(a); } else a = FpXQ_div(x, y, T, p); a = FpX_to_mod(a, p); } else a = RgXQ_mul(x, ginvmod(y, gel(z,1)), gel(z,1)); a = gerepileupto(av, a); } gel(z,2) = a; return z; } GEN gdiv(GEN x, GEN y) { long tx = typ(x), ty = typ(y), lx, ly, vx, vy, i; pari_sp av, tetpil; GEN z, p1, p2; if (tx == ty) switch(tx) { case t_INT: if (is_pm1(y)) return (signe(y) < 0)? negi(x): icopy(x); if (is_pm1(x)) { long s = signe(y); if (!s) pari_err_INV("gdiv",y); if (signe(x) < 0) s = -s; z = cgetg(3, t_FRAC); gel(z,1) = s<0? gen_m1: gen_1; gel(z,2) = absi(y); return z; } return gred_frac2(x,y); case t_REAL: return divrr(x,y); case t_INTMOD: { GEN X = gel(x,1), Y = gel(y,1); 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,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z; } case t_FRAC: { GEN x1 = gel(x,1), x2 = gel(x,2); GEN y1 = gel(y,1), y2 = gel(y,2); z = cgetg(3, t_FRAC); p1 = gcdii(x1, y1); if (!is_pm1(p1)) { x1 = diviiexact(x1,p1); y1 = diviiexact(y1,p1); } p1 = gcdii(x2, y2); if (!is_pm1(p1)) { x2 = diviiexact(x2,p1); y2 = diviiexact(y2,p1); } tetpil = avma; gel(z,2) = mulii(x2,y1); gel(z,1) = mulii(x1,y2); normalize_frac(z); fix_frac_if_int_GC(z,tetpil); return z; } case t_COMPLEX: if (isintzero(gel(y,1))) { y = gel(y,2); if (isintzero(gel(x,1))) return gdiv(gel(x,2), y); z = cgetg(3,t_COMPLEX); gel(z,1) = gdiv(gel(x,2), y); av = avma; gel(z,2) = gerepileupto(av, gneg(gdiv(gel(x,1), y))); return z; } av = avma; p1 = cxnorm(y); p2 = mulcc(x, gconj(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("/",x,y); return divpp(x, y); case t_QUAD: if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("/",x,y); av = avma; p1 = quadnorm(y); p2 = mulqq(x, gconj(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); case t_FFELT: return FF_div(x,y); case t_POLMOD: if (RgX_equal_var(gel(x,1), gel(y,1))) z = div_polmod_same(gel(x,1), gel(x,2), gel(y,2)); else { av = avma; z = gerepileupto(av, gmul(x, ginv(y))); } return z; case t_POL: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_div(x, y); else return div_scal_pol(x, y); } if (!signe(y)) pari_err_INV("gdiv",y); if (lg(y) == 3) return RgX_Rg_div(x,gel(y,2)); return gred_rfrac2(x,y); case t_SER: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return div_ser_scal(x, y); else return div_scal_ser(x, y); } return div_ser(x, y, vx); case t_RFRAC: vx = varn(gel(x,2)); vy = varn(gel(y,2)); if (vx != vy) { if (varncmp(vx, vy) < 0) return div_rfrac_scal(x, y); else return div_scal_rfrac(x, y); } return div_rfrac(x,y); case t_QFI: av = avma; return gerepileupto(av, qficomp(x, ginv(y))); case t_QFR: av = avma; return gerepileupto(av, qfrcomp(x, ginv(y))); case t_MAT: av = avma; p1 = RgM_inv(y); if (!p1) pari_err_INV("gdiv",y); return gerepileupto(av, RgM_mul(x, p1)); default: pari_err_TYPE2("/",x,y); } if (tx==t_INT && is_const_t(ty)) /* optimized for speed */ { long s = signe(x); if (!s) { if (gequal0(y)) pari_err_INV("gdiv",y); switch (ty) { default: return gen_0; case t_INTMOD: z = cgetg(3,t_INTMOD); gel(z,1) = icopy(gel(y,1)); gel(z,2) = gen_0; return z; case t_FFELT: return FF_zero(y); } } if (is_pm1(x)) { if (s > 0) return ginv(y); av = avma; return gerepileupto(av, ginv(gneg(y))); } switch(ty) { case t_REAL: return divir(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return div_intmod_same(z, gel(y,1), modii(x, gel(y,1)), gel(y,2)); case t_FRAC: z = cgetg(3,t_FRAC); p1 = gcdii(x,gel(y,1)); if (is_pm1(p1)) { avma = (pari_sp)z; gel(z,2) = icopy(gel(y,1)); gel(z,1) = mulii(gel(y,2), x); normalize_frac(z); fix_frac_if_int(z); } else { x = diviiexact(x,p1); tetpil = avma; gel(z,2) = diviiexact(gel(y,1), p1); gel(z,1) = mulii(gel(y,2), x); normalize_frac(z); fix_frac_if_int_GC(z,tetpil); } return z; case t_FFELT: return Z_FF_div(x,y); case t_COMPLEX: return divRc(x,y); case t_PADIC: return divTp(x, y); case t_QUAD: av = avma; p1 = quadnorm(y); p2 = mulRq(x, gconj(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); } } if (gequal0(y) && ty != t_MAT) pari_err_INV("gdiv",y); if (is_const_t(tx) && is_const_t(ty)) switch(tx) { case t_REAL: switch(ty) { case t_INT: return divri(x,y); case t_FRAC: av = avma; z = divri(mulri(x,gel(y,2)), gel(y,1)); return gerepileuptoleaf(av, z); case t_COMPLEX: return divRc(x, y); case t_QUAD: return divfq(x, y, lg(x)); default: pari_err_TYPE2("/",x,y); } case t_INTMOD: switch(ty) { case t_INT: z = cgetg(3, t_INTMOD); return div_intmod_same(z, gel(x,1), gel(x,2), modii(y, gel(x,1))); case t_FRAC: { GEN X = gel(x,1); z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2), gel(x,2)), X); return div_intmod_same(z, X, p1, modii(gel(y,1), X)); } case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("/",x,y); return Z_FF_div(gel(x,2),y); case t_COMPLEX: av = avma; return gerepileupto(av, mulRc_direct(gdiv(x,cxnorm(y)), gconj(y))); case t_QUAD: av = avma; p1 = quadnorm(y); p2 = gmul(x,gconj(y)); tetpil = avma; return gerepile(av,tetpil, gdiv(p2,p1)); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return div_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_REAL: pari_err_TYPE2("/",x,y); } case t_FRAC: switch(ty) { case t_INT: z = cgetg(3, t_FRAC); p1 = gcdii(y,gel(x,1)); if (is_pm1(p1)) { avma = (pari_sp)z; tetpil = 0; gel(z,1) = icopy(gel(x,1)); } else { y = diviiexact(y,p1); tetpil = avma; gel(z,1) = diviiexact(gel(x,1), p1); } gel(z,2) = mulii(gel(x,2),y); normalize_frac(z); if (tetpil) fix_frac_if_int_GC(z,tetpil); return z; case t_REAL: av=avma; p1=mulri(y,gel(x,2)); tetpil=avma; return gerepile(av, tetpil, divir(gel(x,1), p1)); case t_INTMOD: { GEN Y = gel(y,1); z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2),gel(x,2)), Y); return div_intmod_same(z, Y, modii(gel(x,1), Y), p1); } case t_FFELT: av=avma; return gerepileupto(av,Z_FF_div(gel(x,1),FF_Z_mul(y,gel(x,2)))); case t_COMPLEX: return divRc(x, y); case t_PADIC: if (!signe(gel(x,1))) return gen_0; return divTp(x, y); case t_QUAD: av=avma; p1=quadnorm(y); p2=gmul(x,gconj(y)); tetpil=avma; return gerepile(av,tetpil,gdiv(p2,p1)); } case t_FFELT: switch (ty) { case t_INT: return FF_Z_Z_muldiv(x,gen_1,y); case t_FRAC: return FF_Z_Z_muldiv(x,gel(y,2),gel(y,1)); case t_INTMOD: if (!equalii(gel(y,1),FF_p_i(x))) pari_err_OP("/",x,y); return FF_Z_Z_muldiv(x,gen_1,gel(y,2)); default: pari_err_TYPE2("/",x,y); } break; case t_COMPLEX: switch(ty) { case t_INT: case t_REAL: case t_FRAC: return divcR(x,y); case t_INTMOD: return mulRc_direct(ginv(y), x); case t_PADIC: return Zp_nosquare_m1(gel(y,2))? divcR(x,y): divTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("/",x,y); return divfq(x, y, lx); } case t_PADIC: switch(ty) { case t_INT: case t_FRAC: { GEN p = gel(x,2); return signe(gel(x,4))? divpT(x, y) : zeropadic(p, valp(x) - Q_pval(y,p)); } case t_INTMOD: { GEN Y = gel(y,1); z = cgetg(3, t_INTMOD); return div_intmod_same(z, Y, padic_to_Fp(x, Y), gel(y,2)); } case t_COMPLEX: case t_QUAD: av=avma; p1=gmul(x,gconj(y)); p2=gnorm(y); tetpil=avma; return gerepile(av,tetpil,gdiv(p1,p2)); case t_REAL: pari_err_TYPE2("/",x,y); } case t_QUAD: switch (ty) { case t_INT: case t_INTMOD: case t_FRAC: z = cgetg(4,t_QUAD); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gdiv(gel(x,2), y); gel(z,3) = gdiv(gel(x,3), y); return z; case t_REAL: return divqf(x, y, lg(y)); case t_PADIC: return divTp(x, y); case t_COMPLEX: ly = precision(y); if (!ly) pari_err_OP("/",x,y); return divqf(x, y, ly); } } switch(ty) { case t_REAL: case t_INTMOD: case t_PADIC: case t_POLMOD: return gmul(x, ginv(y)); /* missing gerepile, for speed */ case t_MAT: av = avma; p1 = RgM_inv(y); if (!p1) pari_err_INV("gdiv",y); return gerepileupto(av, gmul(x, p1)); case t_VEC: case t_COL: case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE: pari_err_TYPE2("/",x,y); } switch(tx) { case t_VEC: case t_COL: case t_MAT: z = cgetg_copy(x, &lx); for (i=1; i 0) return div_scal_T(x, y, ty); z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(X); gel(z,2) = gdiv(gel(x,2), y); return z; } /* y is POL, SER or RFRAC */ av = avma; switch(ty) { case t_RFRAC: y = gmod(ginv(y), X); break; default: y = ginvmod(gmod(y,X), X); } return gerepileupto(av, mul_polmod_same(X, gel(x,2), y)); } /* x and y are not both is_scalar_t. If one of them is scalar, it's not a * POLMOD (done already), hence its variable is NO_VARIABLE. If the other has * variable NO_VARIABLE, then the operation is incorrect */ vx = gvar(x); if (vx != vy) { /* includes cases where one is scalar */ if (varncmp(vx, vy) < 0) return div_T_scal(x, y, tx); else return div_scal_T(x, y, ty); } switch(tx) { case t_POL: switch(ty) { case t_SER: if (lg(y) == 2) return zeroser(vx, RgX_val(x) - valp(y)); p1 = RgX_to_ser(x,lg(y)); p2 = div_ser(p1, y, vx); settyp(p1, t_VECSMALL); /* p1 left on stack */ return p2; case t_RFRAC: { GEN y1 = gel(y,1), y2 = gel(y,2); if (typ(y1) == t_POL && varn(y1) == vx) return mul_rfrac_scal(y2, y1, x); av = avma; return gerepileupto(av, RgX_Rg_div(RgX_mul(y2, x), y1)); } } break; case t_SER: switch(ty) { case t_POL: if (lg(x) == 2) return zeroser(vx, valp(x) - RgX_val(y)); p1 = RgX_to_ser_inexact(y,lg(x)); p2 = div_ser(x, p1, vx); settyp(p1, t_VECSMALL); /* p1 left on stack */ return p2; case t_RFRAC: av = avma; return gerepileupto(av, gdiv(gmul(x,gel(y,2)), gel(y,1))); } break; case t_RFRAC: switch(ty) { case t_POL: return div_rfrac_pol(gel(x,1),gel(x,2), y); case t_SER: av = avma; z = RgX_to_ser_inexact(gel(x,2), lg(y)); return gerepileupto(av, gdiv(gel(x,1), gmul(z,y))); } break; } pari_err_TYPE2("/",x,y); return NULL; /* not reached */ } /********************************************************************/ /** **/ /** SIMPLE MULTIPLICATION **/ /** **/ /********************************************************************/ GEN gmulsg(long s, GEN y) { long ly, i; pari_sp av; GEN z; switch(typ(y)) { case t_INT: return mulsi(s,y); case t_REAL: return mulsr(s,y); case t_INTMOD: { GEN p = gel(y,1); z = cgetg(3,t_INTMOD); gel(z,2) = gerepileuptoint((pari_sp)z, modii(mulsi(s,gel(y,2)), p)); gel(z,1) = icopy(p); return z; } case t_FFELT: return FF_Z_mul(y,stoi(s)); case t_FRAC: if (!s) return gen_0; z = cgetg(3,t_FRAC); i = cgcd(s, smodis(gel(y,2), s)); if (i == 1) { gel(z,2) = icopy(gel(y,2)); gel(z,1) = mulis(gel(y,1), s); } else { gel(z,2) = divis(gel(y,2), i); gel(z,1) = mulis(gel(y,1), s/i); fix_frac_if_int(z); } return z; case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,1) = gmulsg(s,gel(y,1)); gel(z,2) = gmulsg(s,gel(y,2)); return z; case t_PADIC: if (!s) return gen_0; av = avma; return gerepileupto(av, mulpp(cvtop2(stoi(s),y), y)); case t_QUAD: z = cgetg(4, t_QUAD); gel(z,1) = ZX_copy(gel(y,1)); gel(z,2) = gmulsg(s,gel(y,2)); gel(z,3) = gmulsg(s,gel(y,3)); return z; case t_POLMOD: z = cgetg(3, t_POLMOD); gel(z,1) = RgX_copy(gel(y,1)); gel(z,2) = gmulsg(s,gel(y,2)); return z; case t_POL: if (!signe(y)) return RgX_copy(y); if (!s) return scalarpol(RgX_get_0(y), varn(y)); z = cgetg_copy(y, &ly); z[1]=y[1]; for (i=2; i=0) return shifti(x,n); if (!signe(x)) return gen_0; l = vali(x); n = -n; if (n<=l) return shifti(x,-n); z = cgetg(3,t_FRAC); gel(z,1) = shifti(x,-l); gel(z,2) = int2n(n-l); return z; case t_REAL: return shiftr(x,n); case t_INTMOD: b = gel(x,1); a = gel(x,2); z = cgetg(3,t_INTMOD); if (n <= 0) return div_intmod_same(z, b, a, modii(int2n(-n), b)); gel(z,2) = gerepileuptoint((pari_sp)z, modii(shifti(a,n), b)); gel(z,1) = icopy(b); return z; case t_FFELT: return FF_mul2n(x,n); case t_FRAC: a = gel(x,1); b = gel(x,2); l = vali(a); k = vali(b); if (n+l >= k) { if (expi(b) == k) return shifti(a,n-k); /* b power of 2 */ l = n-k; k = -k; } else { k = -(l+n); l = -l; } z = cgetg(3,t_FRAC); gel(z,1) = shifti(a,l); gel(z,2) = shifti(b,k); return z; case t_COMPLEX: z = cgetg(3,t_COMPLEX); gel(z,1) = gmul2n(gel(x,1),n); gel(z,2) = gmul2n(gel(x,2),n); return z; case t_QUAD: z = cgetg(4,t_QUAD); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gmul2n(gel(x,2),n); gel(z,3) = gmul2n(gel(x,3),n); return z; case t_POLMOD: z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(gel(x,1)); gel(z,2) = gmul2n(gel(x,2),n); return z; case t_POL: z = cgetg_copy(x, &lx); z[1] = x[1]; for (i=2; i 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) { GEN z = cgetg(3,t_POLMOD), a; gel(z,1) = RgX_copy(T); if (typ(x) != t_POL || varn(x) != varn(T) || lg(x) <= 3) a = ginv(x); else { pari_sp av = avma; if (lg(T) == 5) /* quadratic fields */ a = RgX_Rg_div(quad_polmod_conj(x,T), quad_polmod_norm(x,T)); else { GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(x, &p) && p) { T = RgX_to_FpX(T, p); x = RgX_to_FpX(x, p); if (lgefint(p) == 3) { ulong pp = p[2]; a = Flxq_inv(ZX_to_Flx(x, pp), ZX_to_Flx(T, pp), pp); a = Flx_to_ZX(a); } else a = FpXQ_inv(x, T, p); a = FpX_to_mod(a, p); a = gerepileupto(av, a); } else { avma = av; a = RgXQ_inv(x, gel(z,1)); } } } gel(z,2) = a; return z; } GEN ginv(GEN x) { long s; pari_sp av, tetpil; GEN z, y, p1, p2; switch(typ(x)) { case t_INT: if (is_pm1(x)) return icopy(x); s = signe(x); if (!s) pari_err_INV("ginv",gen_0); z = cgetg(3,t_FRAC); gel(z,1) = s<0? gen_m1: gen_1; gel(z,2) = absi(x); return z; case t_REAL: return invr(x); case t_INTMOD: z=cgetg(3,t_INTMOD); gel(z,1) = icopy(gel(x,1)); gel(z,2) = Fp_inv(gel(x,2),gel(x,1)); return z; case t_FRAC: { GEN a = gel(x,1), b = gel(x,2); s = signe(a); if (is_pm1(a)) return s > 0? icopy(b): negi(b); z = cgetg(3,t_FRAC); gel(z,1) = icopy(b); gel(z,2) = icopy(a); normalize_frac(z); return z; } case t_COMPLEX: av=avma; p1=cxnorm(x); p2=mkcomplex(gel(x,1), gneg(gel(x,2))); tetpil=avma; return gerepile(av,tetpil,divcR(p2,p1)); case t_QUAD: av=avma; p1=gnorm(x); p2=gconj(x); tetpil=avma; return gerepile(av,tetpil,gdiv(p2,p1)); case t_PADIC: z = cgetg(5,t_PADIC); if (!signe(gel(x,4))) pari_err_INV("ginv",x); z[1] = _evalprecp(precp(x)) | evalvalp(-valp(x)); gel(z,2) = icopy(gel(x,2)); gel(z,3) = icopy(gel(x,3)); gel(z,4) = Fp_inv(gel(x,4),gel(z,3)); return z; case t_POLMOD: return inv_polmod(gel(x,1), gel(x,2)); case t_FFELT: return FF_inv(x); case t_POL: return gred_rfrac_simple(gen_1,x); case t_SER: return gdiv(gen_1,x); case t_RFRAC: { GEN n = gel(x,1), d = gel(x,2); pari_sp av = avma, ltop; if (gequal0(n)) pari_err_INV("ginv",x); n = simplify_shallow(n); if (typ(n) != t_POL || varn(n) != varn(d)) { if (gequal1(n)) { avma = av; return RgX_copy(d); } ltop = avma; z = RgX_Rg_div(d,n); } else { ltop = avma; z = cgetg(3,t_RFRAC); gel(z,1) = RgX_copy(d); gel(z,2) = RgX_copy(n); } stackdummy(av, ltop); return z; } case t_QFR: av = avma; z = cgetg(5, t_QFR); gel(z,1) = gel(x,1); gel(z,2) = negi( gel(x,2) ); gel(z,3) = gel(x,3); gel(z,4) = negr( gel(x,4) ); return gerepileupto(av, redreal(z)); case t_QFI: y = gcopy(x); if (!equalii(gel(x,1),gel(x,2)) && !equalii(gel(x,1),gel(x,3))) togglesign(gel(y,2)); return y; case t_MAT: { GEN ff = NULL; if (RgM_is_FFM(x,&ff)) y = FFM_inv(x, ff); else y = RgM_inv(x); if (!y) pari_err_INV("ginv",x); return y; } case t_VECSMALL: { long i, lx = lg(x)-1; y = zero_zv(lx); for (i=1; i<=lx; i++) { long xi = x[i]; if (xi<1 || xi>lx || y[xi]) pari_err_TYPE("ginv [not a permutation]", x); y[xi] = i; } return y; } } pari_err_TYPE("inverse",x); return NULL; /* not reached */ } pari-2.7.5/src/basemath/base2.c0000644000175000017500000030574412611142412014630 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* MAXIMAL ORDERS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* allow p = -1 from factorizations, avoid oo loop on p = 1 */ static long safe_Z_pvalrem(GEN x, GEN p, GEN *z) { if (is_pm1(p)) { if (signe(p) > 0) return gvaluation(x,p); /*error*/ *z = absi(x); return 1; } return Z_pvalrem(x, p, z); } /* D an integer, P a ZV, return a factorization matrix for D over P, removing * entries with 0 exponent. */ static GEN fact_from_factors(GEN D, GEN P, long flag) { long i, l = lg(P), iq = 1; GEN Q = cgetg(l+1,t_COL); GEN E = cgetg(l+1,t_COL); for (i=1; iT0 == S->T) return ZX_disc(S->T); d = degpol(S->T0); l0 = leading_term(S->T0); L = S->unscale; if (typ(L) == t_FRAC && absi_cmp(gel(L,1), gel(L,2)) < 0) dT = ZX_disc(S->T); /* more efficient */ else { GEN a = gpowgs(gdiv(gpowgs(L, d), sqri(l0)), d-1); dT = gmul(a, ZX_disc(S->T0)); /* more efficient */ } return S->dT = dT; } static void nfmaxord_check_args(nfmaxord_t *S, GEN T, long flag) { GEN dT, L, E, P, fa = NULL; pari_timer t; long l, ty = typ(T); if (DEBUGLEVEL) timer_start(&t); if (ty == t_VEC) { if (lg(T) != 3) pari_err_TYPE("nfmaxord",T); fa = gel(T,2); T = gel(T,1); ty = typ(T); } if (ty != t_POL) pari_err_TYPE("nfmaxord",T); T = Q_primpart(T); if (degpol(T) <= 0) pari_err_CONSTPOL("nfmaxord"); RgX_check_ZX(T, "nfmaxord"); S->T0 = T; T = ZX_Q_normalize(T, &L); S->unscale = L; S->T = T; S->dT = dT = set_disc(S); if (fa) { if (!isint1(L)) fa = update_fact(dT, fa); switch(typ(fa)) { case t_VEC: case t_COL: fa = fact_from_factors(dT, fa, 0); break; case t_INT: fa = absi_factor_limit(dT, (signe(fa) <= 0)? 1: itou(fa)); break; case t_MAT: if (is_Z_factornon0(fa)) break; /*fall through*/ default: pari_err_TYPE("nfmaxord",fa); } if (!signe(dT)) pari_err_IRREDPOL("nfmaxord",mkvec2(T,fa)); } else fa = (flag & nf_PARTIALFACT)? absi_factor_limit(dT, 0): absi_factor(dT); P = gel(fa,1); l = lg(P); E = gel(fa,2); if (l > 1 && is_pm1(gel(P,1))) { l--; P = vecslice(P, 2, l); E = vecslice(E, 2, l); } S->dTP = P; S->dTE = vec_to_vecsmall(E); if (DEBUGLEVEL) timer_printf(&t, "disc. factorisation"); } static int fnz(GEN x,long j) { long i; for (i=1; i 0) d = t; } return d; } static void allbase_from_maxord(nfmaxord_t *S, GEN maxord) { pari_sp av = avma; GEN f = S->T, P = S->dTP, a = NULL, da = NULL, index, P2, E2, D; long n = degpol(f), lP = lg(P), i, j, k; int centered = 0; for (i=1; idK = diviiexact(S->dT, sqri(index)); S->index = index; D = S->dK; P2 = cgetg(lP, t_COL); E2 = cgetg(lP, t_VECSMALL); for (k = j = 1; j < lP; j++) { long v = Z_pvalrem(D, gel(P,j), &D); if (v) { gel(P2,k) = gel(P,j); E2[k] = v; k++; } } setlg(P2, k); S->dKP = P2; setlg(E2, k); S->dKE = P2; S->basis = RgM_to_RgXV(a, varn(f)); } static GEN disc_from_maxord(nfmaxord_t *S, GEN O) { long n = degpol(S->T), lP = lg(O), i, j; GEN index = gen_1; for (i=1; idT, sqri(index)); } /*******************************************************************/ /* */ /* ROUND 2 */ /* */ /*******************************************************************/ /* transpose of companion matrix of unitary polynomial x, cf matcompanion */ static GEN companion(GEN x) { long j, l = degpol(x); GEN c, y = cgetg(l+1,t_MAT); c = zerocol(l); gel(c,l) = gneg(gel(x,2)); gel(y,1) = c; for (j=2; j<=l; j++) { c = col_ei(l, j-1); gel(c,l) = gneg(gel(x,j+1)); gel(y,j) = c; } return y; } /* return (v - qw) mod m (only compute entries k0,..,n) * v and w are expected to have entries smaller than m */ static GEN mtran(GEN v, GEN w, GEN q, GEN m, GEN mo2, long k0) { long k; GEN p1; if (signe(q)) for (k=lg(v)-1; k >= k0; k--) { pari_sp av = avma; p1 = subii(gel(v,k), mulii(q,gel(w,k))); p1 = centermodii(p1, m, mo2); gel(v,k) = gerepileuptoint(av, p1); } return v; } /* entries of v and w are C small integers */ static GEN mtran_long(GEN v, GEN w, long q, long m, long k0) { long k, p1; if (q) { for (k=lg(v)-1; k>= k0; k--) { p1 = v[k] - q * w[k]; v[k] = p1 % m; } } return v; } /* coeffs of a are C-long integers */ static void rowred_long(GEN a, long rmod) { long j,k, c = lg(a), r = lgcols(a); for (j=1; j1) pari_warn(warnmem,"rowred j=%ld", j); p1 = gerepilecopy(av,a); for (j1=1; j1 1 */ static GEN maxord2(GEN cf, GEN p, long epsilon) { long sp,i,n=lg(cf)-1; pari_sp av=avma, av2,limit; GEN T,T2,Tn,m,v,delta,hard_case_exponent, *w; const GEN pp = sqri(p); const GEN ppo2 = shifti(pp,-1); const long pps = (2*expi(pp)+2 < (long)BITS_IN_LONG)? pp[2]: 0; if (cmpiu(p,n) > 0) { hard_case_exponent = NULL; sp = 0; /* gcc -Wall */ } else { long k; k = sp = itos(p); i=1; while (k < n) { k *= sp; i++; } hard_case_exponent = utoipos(i); } T=cgetg(n+1,t_MAT); for (i=1; i<=n; i++) gel(T,i) = cgetg(n+1,t_COL); T2=cgetg(2*n+1,t_MAT); for (i=1; i<=2*n; i++) gel(T2,i) = cgetg(n+1,t_COL); Tn=cgetg(n*n+1,t_MAT); for (i=1; i<=n*n; i++) gel(Tn,i) = cgetg(n+1,t_COL); v = new_chunk(n+1); w = (GEN*)new_chunk(n+1); av2 = avma; limit = stack_lim(av2,1); delta=gen_1; m=matid(n); for(;;) { long j, k, h; pari_sp av0 = avma; GEN t,b,jp,hh,index,p1, dd = sqri(delta), ppdd = mulii(dd,pp); GEN ppddo2 = shifti(ppdd,-1); if (DEBUGLEVEL > 3) err_printf("ROUND2: epsilon = %ld\tavma = %ld\n",epsilon,avma); b=matinv(m,delta); for (i=1; i<=n; i++) { for (j=1; j<=n; j++) for (k=1; k<=n; k++) { p1 = j==k? gcoeff(m,i,1): gen_0; for (h=2; h<=n; h++) { GEN p2 = mulii(gcoeff(m,i,h),gcoeff(gel(cf,h),j,k)); if (p2!=gen_0) p1 = addii(p1,p2); } gcoeff(T,j,k) = centermodii(p1, ppdd, ppddo2); } p1 = ZM_mul(m, ZM_mul(T,b)); for (j=1; j<=n; j++) for (k=1; k<=n; k++) gcoeff(p1,j,k) = centermodii(diviiexact(gcoeff(p1,j,k),dd),pp,ppo2); w[i] = p1; } if (hard_case_exponent) { for (j=1; j<=n; j++) { for (i=1; i<=n; i++) gcoeff(T,i,j) = gcoeff(w[j],1,i); /* ici la boucle en k calcule la puissance p mod p de w[j] */ for (k=1; k1) pari_warn(warnmem,"maxord2"); gerepileall(av2, 2, &m, &delta); } } m = shallowtrans(m); return gerepileupto(av, RgM_Rg_div(ZM_hnfmodid(m, delta), delta)); } static GEN allbase2(nfmaxord_t *S) { GEN cf, O, P = S->dTP, E = S->dTE, f = S->T; long i, lP = lg(P), n = degpol(f); cf = cgetg(n+1,t_VEC); gel(cf,2) = companion(f); for (i=3; i<=n; i++) gel(cf,i) = ZM_mul(gel(cf,2), gel(cf,i-1)); O = cgetg(lP, t_VEC); for (i=1; idTP; lP = lg(P); E = S->dTE; O = cgetg(1, t_VEC); for (i=1; iT, &g, p); k = FpX_normalize(k, p); B = dbasis(p, S->T, E[i], NULL, FpX_div(S->T,k,p)); O = shallowconcat(O, mkvec(B)); pari_CATCH_reset(); continue; } break; } default: pari_err(0, ERR); return NULL; } l = lg(u); gel(P,i) = gel(u,1); P = shallowconcat(P, vecslice(u, 2, l-1)); av = avma; N = S->dT; E[i] = Z_pvalrem(N, gel(P,i), &N); for (k=lP, lP=lg(P); k < lP; k++) E[k] = Z_pvalrem(N, gel(P,k), &N); } pari_RETRY { if (DEBUGLEVEL) err_printf("Treating p^k = %Ps^%ld\n",P[i],E[i]); O = shallowconcat(O, mkvec( maxord(gel(P,i),S->T,E[i]) )); } pari_ENDCATCH; } S->dTP = P; return O; } void 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) { nfmaxord_t S; nfmaxord(&S, fa? mkvec2(x,fa): x, flag); if (pbas) *pbas = RgXV_unscale(S.basis, S.unscale); if (pdK) *pdK = S.dK; } static GEN _nfdisc(GEN x, long flag, GEN fa) { pari_sp av = avma; nfmaxord_t S; GEN O = get_maxord(&S, fa? mkvec2(x,fa): x, flag); 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); } static ulong Flx_checkdeflate(GEN x) { ulong d = 0, i, lx = (ulong)lg(x); for (i=3; i2) err_printf(" ZX_dedekind: gcd has degree %ld\n", dk); if (!dk) { avma = av; return gen_1; } if (mf < 0) mf = ZpX_disc_val(f, p); if (2*dk >= mf-1) { k = FpX_normalize(k, p); res = dbasis(p, f, mf, NULL, FpX_div(f,k,p)); } else { GEN w, F1, F2; F1 = FpX_factor(k,p); F2 = FpX_factor(FpX_div(g,k,p),p); w = merge_sort_uniq(gel(F1,1),gel(F2,1),(void*)cmpii,&gen_cmp_RgX); res = maxord_i(p, f, mf, w, 0); } return gerepilecopy(av,res); } static GEN Zlx_sylvester_echelon(GEN f1, GEN f2, long early_abort, ulong p, ulong pm) { long j, n = degpol(f1); GEN h, a = cgetg(n+1,t_MAT); f1 = Flx_get_red(f1, pm); h = Flx_rem(f2,f1,pm); for (j=1;; j++) { gel(a,j) = Flx_to_Flv(h, n); if (j == n) break; h = Flx_rem(Flx_shift(h, 1), f1, pm); } return zlm_echelon(a, early_abort, p, pm); } /* Sylvester's matrix, mod p^m (assumes f1 monic). If early_abort * is set, return NULL if one pivot is 0 mod p^m */ static GEN ZpX_sylvester_echelon(GEN f1, GEN f2, long early_abort, GEN p, GEN pm) { long j, n = degpol(f1); GEN h, a = cgetg(n+1,t_MAT); h = FpXQ_red(f2,f1,pm); for (j=1;; j++) { gel(a,j) = RgX_to_RgV(h, n); if (j == n) break; h = FpX_rem(RgX_shift_shallow(h, 1), f1, pm); } return ZpM_echelon(a, early_abort, p, pm); } /* polynomial gcd mod p^m (assumes f1 monic). Return a QpX ! */ static GEN 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); 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); if (t == 1) return gerepilecopy(av, a); return gerepileupto(av, RgX_Rg_div(a, utoipos(t))); } } avma = av; return pol_0(v); } GEN ZpX_gcd(GEN f1, GEN f2, GEN p, GEN pm) { pari_sp av = avma; GEN a; long c, l, v; if (lgefint(pm) == 3) { ulong q = pm[2]; return Zlx_gcd(ZX_to_Flx(f1, q), ZX_to_Flx(f2,q), p[2], q); } a = ZpX_sylvester_echelon(f1,f2,0,p,pm); l = lg(a); v = varn(f1); for (c = 1; c < l; c++) { GEN t = gcoeff(a,c,c); if (signe(t)) { a = RgV_to_RgX(gel(a,c), v); if (equali1(t)) return gerepilecopy(av, a); return gerepileupto(av, RgX_Rg_div(a, t)); } } avma = av; return pol_0(v); } /* Return m > 0, such that p^m ~ 2^16 for initial value of m; p > 1 */ static long init_m(GEN p) { if (lgefint(p) > 3) return 1; return (long)(16 / log2(p[2])); } /* reduced resultant mod p^m (assumes x monic) */ GEN ZpX_reduced_resultant(GEN x, GEN y, GEN p, GEN pm) { pari_sp av = avma; GEN z; if (lgefint(pm) == 3) { ulong q = pm[2]; z = Zlx_sylvester_echelon(ZX_to_Flx(x,q), ZX_to_Flx(y,q),0,p[2],q); if (lg(z) > 1) { ulong c = ucoeff(z,1,1); if (c) { avma = av; return utoipos(c); } } } else { z = ZpX_sylvester_echelon(x,y,0,p,pm); if (lg(z) > 1) { GEN c = gcoeff(z,1,1); if (signe(c)) return gerepileuptoint(av, c); } } avma = av; return gen_0; } /* Assume Res(f,g) divides p^M. Return Res(f, g), using dynamic p-adic * precision (until result is non-zero or p^M). */ GEN ZpX_reduced_resultant_fast(GEN f, GEN g, GEN p, long M) { GEN R, q = NULL; long m; m = init_m(p); if (m < 1) m = 1; for(;; m <<= 1) { if (M < 2*m) break; q = q? sqri(q): powiu(p, m); /* p^m */ R = ZpX_reduced_resultant(f,g, p, q); if (signe(R)) return R; } q = powiu(p, M); R = ZpX_reduced_resultant(f,g, p, q); return signe(R)? R: q; } /* v_p(Res(x,y) mod p^m), assumes (lc(x),p) = 1 */ static long ZpX_resultant_val_i(GEN x, GEN y, GEN p, GEN pm) { pari_sp av = avma; GEN z; long i, l, v; if (lgefint(pm) == 3) { ulong q = pm[2], pp = p[2]; z = Zlx_sylvester_echelon(ZX_to_Flx(x,q), ZX_to_Flx(y,q), 1, pp, q); if (!z) { avma = av; return -1; } /* failure */ v = 0; l = lg(z); for (i = 1; i < l; i++) v += u_lval(ucoeff(z,i,i), pp); } else { z = ZpX_sylvester_echelon(x, y, 1, p, pm); if (!z) { avma = av; return -1; } /* failure */ v = 0; l = lg(z); for (i = 1; i < l; i++) v += Z_pval(gcoeff(z,i,i), p); } return v; } /* assume (lc(f),p) = 1; no assumption on g */ long ZpX_resultant_val(GEN f, GEN g, GEN p, long M) { pari_sp av = avma; GEN q = NULL; long v, m; m = init_m(p); if (m < 2) m = 2; for(;; m <<= 1) { if (m > M) m = M; q = q? sqri(q): powiu(p, m); /* p^m */ v = ZpX_resultant_val_i(f,g, p, q); if (v >= 0) break; if (m == M) return M; } avma = av; return v; } /* assume f separable and (lc(f),p) = 1 */ long ZpX_disc_val(GEN f, GEN p) { pari_sp av = avma; long v; if (degpol(f) == 1) return 0; v = ZpX_resultant_val(f, ZX_deriv(f), p, LONG_MAX); avma = av; return v; } /* *e a ZX, *d, *z in Z, *d = p^(*vd). Simplify e / d by cancelling a * common factor p^v; if z!=NULL, update it by cancelling the same power of p */ static void update_den(GEN p, GEN *e, GEN *d, long *vd, GEN *z) { GEN newe; long ve = ZX_pvalrem(*e, p, &newe); if (ve) { GEN newd; long v = minss(*vd, ve); if (v) { if (v == *vd) { /* rare, denominator cancelled */ if (ve != v) newe = ZX_Z_mul(newe, powiu(p, ve - v)); newd = gen_1; *vd = 0; if (z) *z =diviiexact(*z, powiu(p, v)); } else { /* v = ve < vd, generic case */ GEN q = powiu(p, v); newd = diviiexact(*d, q); *vd -= v; if (z) *z = diviiexact(*z, q); } *e = newe; *d = newd; } } } /* return denominator, a power of p */ static GEN QpX_denom(GEN x) { long i, l = lg(x); GEN maxd = gen_1; for (i=2; i 0) maxd = gel(d,2); } return maxd; } static GEN QpXV_denom(GEN x) { long l = lg(x), i; GEN maxd = gen_1; for (i = 1; i < l; i++) { GEN d = QpX_denom(gel(x,i)); if (cmpii(d, maxd) > 0) maxd = d; } return maxd; } static GEN QpX_remove_denom(GEN x, GEN p, GEN *pdx, long *pv) { *pdx = QpX_denom(x); if (*pdx == gen_1) { *pv = 0; *pdx = NULL; } else { x = Q_muli_to_int(x,*pdx); *pv = Z_pval(*pdx, p); } return x; } /* p^v * f o g mod (T,q). q = p^vq */ static GEN compmod(GEN p, GEN f, GEN g, GEN T, GEN q, long v) { GEN D = NULL, z, df, dg, qD; long vD = 0, vdf, vdg; f = QpX_remove_denom(f, p, &df, &vdf); if (typ(g) == t_VEC) /* [num,den,v_p(den)] */ { vdg = itos(gel(g,3)); dg = gel(g,2); g = gel(g,1); } else g = QpX_remove_denom(g, p, &dg, &vdg); if (df) { D = df; vD = vdf; } if (dg) { long degf = degpol(f); D = mul_content(D, powiu(dg, degf)); vD += degf * vdg; } qD = D ? mulii(q, D): q; if (dg) f = FpX_rescale(f, dg, qD); z = FpX_FpXQ_eval(f, g, T, qD); if (!D) { if (v) { if (v > 0) z = ZX_Z_mul(z, powiu(p, v)); else z = RgX_Rg_div(z, powiu(p, -v)); } return z; } update_den(p, &z, &D, &vD, NULL); qD = mulii(D,q); if (v) vD -= v; z = FpX_center(z, qD, shifti(qD,-1)); if (vD > 0) z = RgX_Rg_div(z, powiu(p, vD)); else if (vD < 0) z = ZX_Z_mul(z, powiu(p, -vD)); return z; } /* fast implementation of ZM_hnfmodid(M, D) / D, D = p^k */ static GEN ZpM_hnfmodid(GEN M, GEN p, GEN D) { long i, l = lg(M); M = RgM_Rg_div(ZpM_echelon(M,0,p,D), D); for (i = 1; i < l; i++) if (gequal0(gcoeff(M,i,i))) gcoeff(M,i,i) = gen_1; return M; } /* Return Z-basis for Z[a] + U(a)/p Z[a] in Z[t]/(f), mf = v_p(disc f), U * a ZX. Special cases: a = t is coded as NULL, U = 0 is coded as NULL */ static GEN dbasis(GEN p, GEN f, long mf, GEN a, GEN U) { long n = degpol(f), i, dU; GEN b, h; if (n == 1) return matid(1); if (a && gequalX(a)) a = NULL; if (DEBUGLEVEL>5) { err_printf(" entering Dedekind Basis with parameters p=%Ps\n",p); err_printf(" f = %Ps,\n a = %Ps\n",f, a? a: pol_x(varn(f))); } if (a) { GEN pd = powiu(p, mf >> 1); GEN da, pdp = mulii(pd,p), D = pdp; long vda; dU = U ? degpol(U): 0; b = cgetg(n+1, t_MAT); h = scalarpol(pd, varn(f)); a = QpX_remove_denom(a, p, &da, &vda); if (da) D = mulii(D, da); gel(b,1) = scalarcol_shallow(pd, n); for (i=2; i<=n; i++) { if (i == dU+1) h = compmod(p, U, mkvec3(a,da,stoi(vda)), f, pdp, (mf>>1) - 1); else { h = FpXQ_mul(h, a, f, D); if (da) h = ZX_Z_divexact(h, da); } gel(b,i) = RgX_to_RgV(h,n); } return ZpM_hnfmodid(b, p, pd); } else { if (!U) return matid(n); dU = degpol(U); if (dU == n) return matid(n); U = FpX_normalize(U, p); b = cgetg(n+1, t_MAT); for (i = 1; i <= dU; i++) gel(b,i) = vec_ei(n, i); h = RgX_Rg_div(U, p); for ( ; i <= n; i++) { gel(b, i) = RgX_to_RgV(h,n); if (i == n) break; h = RgX_shift_shallow(h,1); } return b; } } static GEN get_partial_order_as_pols(GEN p, GEN f) { GEN O = maxord(p, f, -1); long v = varn(f); return O == gen_1? pol_x_powers(degpol(f), v): RgM_to_RgXV(O, v); } typedef struct { /* constants */ long pisprime; /* -1: unknown, 1: prime, 0: composite */ GEN p, f; /* goal: factor f p-adically */ long df; GEN pdf; /* p^df = reduced discriminant of f */ long mf; /* */ GEN psf, pmf; /* stability precision for f, wanted precision for f */ long vpsf; /* v_p(p_f) */ /* these are updated along the way */ GEN phi; /* a p-integer, in Q[X] */ GEN phi0; /* a p-integer, in Q[X] from testb2 / testc2, to be composed with * phi when correct precision is known */ GEN chi; /* characteristic polynomial of phi (mod psc) in Z[X] */ GEN nu; /* irreducible divisor of chi mod p, in Z[X] */ GEN invnu; /* numerator ( 1/ Mod(nu, chi) mod pmr ) */ GEN Dinvnu;/* denominator ( ... ) */ long vDinvnu; /* v_p(Dinvnu) */ GEN prc, psc; /* reduced discriminant of chi, stability precision for chi */ long vpsc; /* v_p(p_c) */ GEN ns, nsf, precns; /* cached Newton sums for nsf and their precision */ } decomp_t; static long p_is_prime(decomp_t *S) { if (S->pisprime < 0) S->pisprime = BPSW_psp(S->p); return S->pisprime; } /* if flag = 0, maximal order, else factorization to precision r = flag */ static GEN Decomp(decomp_t *S, long flag) { pari_sp av = avma; GEN fred, pr, pk, ph, b1, b2, a, e, de, f1, f2, dt, th; GEN p = S->p, chip; long k, r = flag? flag: 2*S->df + 1; long vde, vdt; if (DEBUGLEVEL>2) { err_printf(" entering Decomp"); if (DEBUGLEVEL>5) err_printf(", parameters: %Ps^%ld\n f = %Ps",p, r, S->f); err_printf("\n"); } chip = FpX_red(S->chi, p); if (!FpX_valrem(chip, S->nu, p, &b1)) { if (!p_is_prime(S)) pari_err_PRIME("Decomp",p); pari_err_BUG("Decomp (not a factor)"); } b2 = FpX_div(chip, b1, p); a = FpX_mul(FpXQ_inv(b2, b1, p), b2, p); /* E = e / de, e in Z[X], de in Z, E = a(phi) mod (f, p) */ th = QpX_remove_denom(S->phi, p, &dt, &vdt); if (dt) { long dega = degpol(a); vde = dega * vdt; de = powiu(dt, dega); pr = mulii(p, de); a = FpX_rescale(a, dt, pr); } else { vde = 0; de = gen_1; pr = p; } e = FpX_FpXQ_eval(a, th, S->f, pr); update_den(p, &e, &de, &vde, NULL); pk = p; k = 1; /* E, (1 - E) tend to orthogonal idempotents in Zp[X]/(f) */ while (k < r + vde) { /* E <-- E^2(3-2E) mod p^2k, with E = e/de */ GEN D; pk = sqri(pk); k <<= 1; e = ZX_mul(ZX_sqr(e), Z_ZX_sub(mului(3,de), gmul2n(e,1))); de= mulii(de, sqri(de)); vde *= 3; D = mulii(pk, de); e = FpX_rem(e, centermod(S->f, D), D); /* e/de defined mod pk */ update_den(p, &e, &de, &vde, NULL); } pr = powiu(p, r); /* required precision of the factors */ ph = mulii(de, pr); fred = centermod(S->f, ph); e = centermod(e, ph); f1 = ZpX_gcd(fred, Z_ZX_sub(de, e), p, ph); /* p-adic gcd(f, 1-e) */ fred = centermod(fred, pr); f1 = centermod(f1, pr); f2 = FpX_div(fred,f1, pr); f2 = FpX_center(f2, pr, shifti(pr,-1)); if (DEBUGLEVEL>5) err_printf(" leaving Decomp: f1 = %Ps\nf2 = %Ps\ne = %Ps\nde= %Ps\n", f1,f2,e,de); if (flag) { gerepileall(av, 2, &f1, &f2); return famat_mul_shallow(ZX_monic_factorpadic(f1, p, flag), ZX_monic_factorpadic(f2, p, flag)); } else { GEN D, d1, d2, B1, B2, M; long n, n1, n2, i; gerepileall(av, 4, &f1, &f2, &e, &de); D = de; B1 = get_partial_order_as_pols(p,f1); n1 = lg(B1)-1; B2 = get_partial_order_as_pols(p,f2); n2 = lg(B2)-1; n = n1+n2; d1 = QpXV_denom(B1); d2 = QpXV_denom(B2); if (cmpii(d1, d2) < 0) d1 = d2; if (d1 != gen_1) { B1 = Q_muli_to_int(B1, d1); B2 = Q_muli_to_int(B2, d1); D = mulii(d1, D); } 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); 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); return ZpM_hnfmodid(M, p, D); } } /* minimum extension valuation: L/E */ static void vstar(GEN p,GEN h, long *L, long *E) { long first, j, k, v, w, m = degpol(h); first = 1; k = 1; v = 0; for (j=1; j<=m; j++) { GEN c = gel(h, m-j+2); if (signe(c)) { w = Z_pval(c,p); if (first || w*k < v*j) { v = w; k = j; } first = 0; } } /* v/k = max_j ( v_p(h_{m-j}) / j ) */ w = (long)ugcd(v,k); *L = v/w; *E = k/w; } static GEN redelt_i(GEN a, GEN N, GEN p, GEN *pda, long *pvda) { GEN z; a = Q_remove_denom(a, pda); *pvda = 0; if (*pda) { long v = Z_pvalrem(*pda, p, &z); if (v) { *pda = powiu(p, v); *pvda = v; N = mulii(*pda, N); } else *pda = NULL; if (!is_pm1(z)) a = ZX_Z_mul(a, Fp_inv(z, N)); } return centermod(a, N); } /* reduce the element a modulo N [ a power of p ], taking first care of the * denominators */ static GEN redelt(GEN a, GEN N, GEN p) { GEN da; long vda; a = redelt_i(a, N, p, &da, &vda); if (da) a = RgX_Rg_div(a, da); return a; } /* compute the Newton sums of g(x) mod p, assume deg g > 0 */ GEN polsymmodp(GEN g, GEN p) { pari_sp av; long d = degpol(g), i, k; GEN s, y, po2; y = cgetg(d + 1, t_COL); gel(y,1) = utoipos(d); if (d == 1) return y; /* k = 1, split off for efficiency */ po2 = shifti(p,-1); /* to be left on stack */ av = avma; s = gel(g,d-1+2); gel(y,2) = gerepileuptoint(av, centermodii(negi(s), p, po2)); for (k = 2; k < d; k++) { av = avma; s = mului(k, remii(gel(g,d-k+2), p)); for (i = 1; i < k; i++) s = addii(s, mulii(gel(y,k-i+1), gel(g,d-i+2))); togglesign_safe(&s); gel(y,k+1) = gerepileuptoint(av, centermodii(s, p, po2)); } return y; } /* compute the c first Newton sums modulo pp of the characteristic polynomial of a/d mod chi, d > 0 power of p (NULL = gen_1), a, chi in Zp[X], vda = v_p(da) ns = Newton sums of chi */ static GEN 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; a = centermod(a, pp); av = avma; lim = stack_lim(av, 1); dpa = pa = NULL; /* -Wall */ vdpa = 0; va = zerovec(c); for (j = 1; j <= c; j++) { /* pa/dpa = (a/d)^(j-1) mod (chi, pp), dpa = p^vdpa */ long degpa; pa = j == 1? a: FpXQ_mul(pa, a, chi, pp); degpa = degpol(pa); if (degpa < 0) { for (; j <= c; j++) gel(va,j) = gen_0; return va; } if (da) { dpa = j == 1? da: mulii(dpa, da); vdpa += vda; update_den(p, &pa, &dpa, &vdpa, &pp); } s = mulii(gel(pa,2), gel(ns,1)); /* k = 0 */ for (k=1; k<=degpa; k++) s = addii(s, mulii(gel(pa,k+2), gel(ns,k+1))); if (da) { GEN r; s = dvmdii(s, dpa, &r); if (r != gen_0) return NULL; } gel(va,j) = centermodii(s, pp, shifti(pp,-1)); if (low_stack(lim, stack_lim(av, 1))) { if(DEBUGMEM>1) pari_warn(warnmem, "newtonsums"); gerepileall(av, dpa?4:3, &pa, &va, &pp, &dpa); } } return va; } /* compute the characteristic polynomial of a/da mod chi (a in Z[X]), given * by its Newton sums to a precision of pp using Newton sums */ static GEN newtoncharpoly(GEN pp, GEN p, GEN NS) { long n = lg(NS)-1, j, k; GEN c = cgetg(n + 2, t_VEC); gel(c,1) = (n & 1 ? gen_m1: gen_1); for (k = 2; k <= n+1; k++) { pari_sp av2 = avma; GEN s = gen_0; ulong z; long v = u_pvalrem(k - 1, p, &z); for (j = 1; j < k; j++) { GEN t = mulii(gel(NS,j), gel(c,k-j)); if (!odd(j)) t = negi(t); s = addii(s, t); } if (v) { s = gdiv(s, powiu(p, v)); if (typ(s) != t_INT) return NULL; } s = mulii(s, Fp_inv(utoipos(z), pp)); gel(c,k) = gerepileuptoint(av2, centermod(s, pp)); } for (k = odd(n)? 1: 2; k <= n+1; k += 2) gel(c,k) = negi(gel(c,k)); return gtopoly(c, 0); } static void manage_cache(decomp_t *S, GEN f, GEN pp) { GEN t = S->precns; if (!t) t = mulii(S->pmf, powiu(S->p, S->df)); if (cmpii(t, pp) < 0) t = pp; if (!S->precns || !RgX_equal(f, S->nsf) || cmpii(S->precns, t) < 0) { if (DEBUGLEVEL>4) err_printf(" Precision for cached Newton sums for %Ps: %Ps -> %Ps\n", f, S->precns? S->precns: gen_0, t); S->nsf = f; S->ns = polsymmodp(f, t); S->precns = t; } } /* return NULL if a mod f is not an integer * The denominator of any integer in Zp[X]/(f) divides pdr */ static GEN mycaract(decomp_t *S, GEN f, GEN a, GEN pp, GEN pdr) { pari_sp av; GEN d, chi, prec1, prec2, prec3, ns; long vd, n = degpol(f); if (gequal0(a)) return pol_0(varn(f)); a = QpX_remove_denom(a, S->p, &d, &vd); prec1 = pp; if (lgefint(S->p) == 3) prec1 = mulii(prec1, powiu(S->p, factorial_lval(n, itou(S->p)))); if (d) { GEN p1 = powiu(d, n); prec2 = mulii(prec1, p1); prec3 = mulii(prec1, gmin(mulii(p1, d), pdr)); } else prec2 = prec3 = prec1; manage_cache(S, f, prec3); av = avma; ns = newtonsums(S->p, a, d, vd, f, n, prec2, S->ns); if (!ns) return NULL; chi = newtoncharpoly(prec1, S->p, ns); if (!chi) return NULL; setvarn(chi, varn(f)); return gerepileupto(av, centermod(chi, pp)); } static GEN get_nu(GEN chi, GEN p, long *ptl) { GEN P = gel(FpX_factor(chi, p),1); *ptl = lg(P) - 1; return gel(P,*ptl); } /* Factor characteristic polynomial chi of phi mod p. If it splits, update * S->{phi, chi, nu} and return 1. In any case, set *nu to an irreducible * factor mod p of chi */ static int split_char(decomp_t *S, GEN chi, GEN phi, GEN phi0, GEN *nu) { long l; *nu = get_nu(chi, S->p, &l); if (l == 1) return 0; /* single irreducible factor: doesn't split */ /* phi o phi0 mod (p, f) */ S->phi = compmod(S->p, phi, phi0, S->f, S->p, 0); S->chi = chi; S->nu = *nu; return 1; } /* Return the prime element in Zp[phi], a t_INT (iff *Ep = 1) or QX; * nup, chip are ZX. phi = NULL codes X * If *Ep < oE or Ep divides Ediv (!=0) return NULL (uninteresting) */ static GEN getprime(decomp_t *S, GEN phi, GEN chip, GEN nup, long *Lp, long *Ep, long oE, long Ediv) { GEN z, chin, q, qp; long r, s; if (phi && dvdii(constant_term(chip), S->psc)) { chip = mycaract(S, S->chi, phi, S->pmf, S->prc); if (dvdii(constant_term(chip), S->pmf)) chip = ZXQ_charpoly(phi, S->chi, varn(chip)); } if (degpol(nup) == 1) { GEN c = gel(nup,2); /* nup = X + c */ chin = signe(c)? RgX_translate(chip, negi(c)): chip; } else chin = ZXQ_charpoly(nup, chip, varn(chip)); vstar(S->p, chin, Lp, Ep); if (*Ep < oE || (Ediv && Ediv % *Ep == 0)) return NULL; if (*Ep == 1) return S->p; (void)cbezout(*Lp, -*Ep, &r, &s); /* = 1 */ if (r <= 0) { long t = 1 + ((-r) / *Ep); r += t * *Ep; s += t * *Lp; } /* r > 0 minimal such that r L/E - s = 1/E * pi = nu^r / p^s is an element of valuation 1/E, * so is pi + O(p) since 1/E < 1. May compute nu^r mod p^(s+1) */ q = powiu(S->p, s); qp = mulii(q, S->p); nup = FpXQ_powu(nup, r, S->chi, qp); if (!phi) return RgX_Rg_div(nup, q); /* phi = X : no composition */ z = compmod(S->p, nup, phi, S->chi, qp, -s); return signe(z)? z: NULL; } static int update_phi(decomp_t *S) { GEN PHI = NULL, prc, psc, X = pol_x(varn(S->f)); long k; for (k = 1;; k++) { prc = ZpX_reduced_resultant_fast(S->chi, ZX_deriv(S->chi), S->p, S->vpsc); if (!equalii(prc, S->psc)) break; /* increase precision */ S->vpsc = maxss(S->vpsf, S->vpsc + 1); S->psc = (S->vpsc == S->vpsf)? S->psf: mulii(S->psc, S->p); PHI = S->phi; if (S->phi0) PHI = compmod(S->p, PHI, S->phi0, S->f, S->psc, 0); PHI = gadd(PHI, ZX_Z_mul(X, mului(k, S->p))); S->chi = mycaract(S, S->f, PHI, S->psc, S->pdf); } psc = mulii(sqri(prc), S->p); if (!PHI) /* ok above for k = 1 */ { PHI = S->phi; if (S->phi0) { PHI = compmod(S->p, PHI, S->phi0, S->f, psc, 0); S->chi = mycaract(S, S->f, PHI, psc, S->pdf); } } S->phi = PHI; S->chi = FpX_red(S->chi, psc); /* may happen if p is unramified */ if (is_pm1(prc)) return 0; S->psc = psc; S->vpsc = 2*Z_pval(prc, S->p) + 1; S->prc = mulii(prc, S->p); return 1; } /* return 1 if at least 2 factors mod p ==> chi splits * Replace S->phi such that F increases (to D) */ static int testb2(decomp_t *S, long D, GEN theta) { long v = varn(S->chi), dlim = degpol(S->chi)-1; GEN T0 = S->phi, chi, phi, nu; if (DEBUGLEVEL>4) err_printf(" Increasing Fa\n"); for (;;) { phi = gadd(theta, random_FpX(dlim, v, S->p)); chi = mycaract(S, S->chi, phi, S->psf, S->prc); /* phi non-primary ? */ if (split_char(S, chi, phi, T0, &nu)) return 1; if (degpol(nu) == D) break; } /* F_phi=lcm(F_alpha, F_theta)=D and E_phi=E_alpha */ S->phi0 = T0; S->chi = chi; S->phi = phi; S->nu = nu; return 0; } /* return 1 if at least 2 factors mod p ==> chi can be split. * compute a new S->phi such that E = lcm(Ea, Et); * A a ZX, T a t_INT (iff Et = 1, probably impossible ?) or QX */ static int testc2(decomp_t *S, GEN A, long Ea, GEN T, long Et) { GEN c, chi, phi, nu, T0 = S->phi; if (DEBUGLEVEL>4) err_printf(" Increasing Ea\n"); if (Et == 1) /* same as other branch, split for efficiency */ c = A; /* Et = 1 => s = 1, r = 0, t = 0 */ else { long r, s, t; (void)cbezout(Ea, Et, &r, &s); t = 0; while (r < 0) { r = r + Et; t++; } while (s < 0) { s = s + Ea; t++; } /* A^s T^r / p^t */ c = RgXQ_mul(RgXQ_powu(A, s, S->chi), RgXQ_powu(T, r, S->chi), S->chi); c = RgX_Rg_div(c, powiu(S->p, t)); c = redelt(c, S->psc, S->p); } phi = RgX_add(c, pol_x(varn(S->chi))); chi = mycaract(S, S->chi, phi, S->psf, S->prc); if (split_char(S, chi, phi, T0, &nu)) return 1; /* E_phi = lcm(E_alpha,E_theta) */ S->phi0 = T0; S->chi = chi; S->phi = phi; S->nu = nu; return 0; } /* Return h^(-degpol(P)) P(x * h) if result is integral, NULL otherwise */ static GEN ZX_rescale_inv(GEN P, GEN h) { long i, l = lg(P); GEN Q = cgetg(l,t_POL), hi = h; gel(Q,l-1) = gel(P,l-1); for (i=l-2; i>=2; i--) { GEN r; gel(Q,i) = dvmdii(gel(P,i), hi, &r); if (signe(r)) return NULL; if (i == 2) break; hi = mulii(hi,h); } Q[1] = P[1]; return Q; } /* x p^-eq nu^-er mod p */ static GEN get_gamma(decomp_t *S, GEN x, long eq, long er) { GEN q, g = x, Dg = powiu(S->p, eq); long vDg = eq; if (er) { if (!S->invnu) { while (gdvd(S->chi, S->nu)) S->nu = RgX_Rg_add(S->nu, S->p); S->invnu = QXQ_inv(S->nu, S->chi); S->invnu = redelt_i(S->invnu, S->psc, S->p, &S->Dinvnu, &S->vDinvnu); } if (S->Dinvnu) { Dg = mulii(Dg, powiu(S->Dinvnu, er)); vDg += er * S->vDinvnu; } q = mulii(S->p, Dg); g = ZX_mul(g, FpXQ_powu(S->invnu, er, S->chi, q)); g = FpX_rem(g, S->chi, q); update_den(S->p, &g, &Dg, &vDg, NULL); g = centermod(g, mulii(S->p, Dg)); } if (!is_pm1(Dg)) g = RgX_Rg_div(g, Dg); return g; } static GEN get_g(decomp_t *S, long Ea, long L, long E, GEN beta, GEN *pchig, long *peq, long *per) { long eq, er; GEN g, chig, chib = NULL; for(;;) /* at most twice */ { if (L < 0) { chib = ZXQ_charpoly(beta, S->chi, varn(S->chi)); vstar(S->p, chib, &L, &E); } eq = L / E; er = L*Ea / E - eq*Ea; /* floor(L Ea/E) = eq Ea + er */ if (er || !chib) { /* g might not be an integer ==> chig = NULL */ g = get_gamma(S, beta, eq, er); chig = mycaract(S, S->chi, g, S->psc, S->prc); } else { /* g = beta/p^eq, special case of the above */ GEN h = powiu(S->p, eq); g = RgX_Rg_div(beta, h); chig = ZX_rescale_inv(chib, h); /* chib(x h) / h^N */ if (chig) chig = FpX_red(chig, S->pmf); } /* either success or second consecutive failure */ if (chig || chib) break; /* if g fails the v*-test, v(beta) was wrong. Retry once */ L = -1; } *pchig = chig; *peq = eq; *per = er; return g; } /* return 1 if at least 2 factors mod p ==> chi can be split */ static int loop(decomp_t *S, long Ea) { pari_sp av = avma, limit = stack_lim(av, 1); GEN beta = FpXQ_powu(S->nu, Ea, S->chi, S->p); long N = degpol(S->f), v = varn(S->f); S->invnu = NULL; for (;;) { /* beta tends to a factor of chi */ long L, i, Fg, eq, er; GEN chig = NULL, d, g, nug; if (DEBUGLEVEL>4) err_printf(" beta = %Ps\n", beta); L = ZpX_resultant_val(S->chi, beta, S->p, S->mf+1); if (L > S->mf) L = -1; /* from scratch */ g = get_g(S, Ea, L, N, beta, &chig, &eq, &er); if (DEBUGLEVEL>4) err_printf(" (eq,er) = (%ld,%ld)\n", eq,er); /* g = beta p^-eq nu^-er (a unit), chig = charpoly(g) */ if (split_char(S, chig, g,S->phi, &nug)) return 1; Fg = degpol(nug); if (Fg == 1) { /* frequent special case nug = x - d */ long Le, Ee; GEN chie, nue, e, pie; d = negi(gel(nug,2)); chie = RgX_translate(chig, d); nue = pol_x(v); e = RgX_Rg_sub(g, d); pie = getprime(S, e, chie, nue, &Le, &Ee, 0,Ea); if (pie) return testc2(S, S->nu, Ea, pie, Ee); } else { long Fa = degpol(S->nu), vdeng; GEN deng, numg, nume; if (Fa % Fg) return testb2(S, clcm(Fa,Fg), g); /* nu & nug irreducible mod p, deg nug | deg nu. To improve beta, look * for a root d of nug in Fp[phi] such that v_p(g - d) > 0 */ if (ZX_equal(nug, S->nu)) d = pol_x(v); else { if (!p_is_prime(S)) pari_err_PRIME("FpX_ffisom",S->p); d = FpX_ffisom(nug, S->nu, S->p); } /* write g = numg / deng, e = nume / deng */ numg = QpX_remove_denom(g, S->p, &deng, &vdeng); for (i = 1; i <= Fg; i++) { GEN chie, nue, e; if (i != 1) d = FpXQ_pow(d, S->p, S->nu, S->p); /* next root */ nume = ZX_sub(numg, ZX_Z_mul(d, deng)); /* test e = nume / deng */ if (ZpX_resultant_val(S->chi, nume, S->p, vdeng*N+1) <= vdeng*N) continue; e = RgX_Rg_div(nume, deng); chie = mycaract(S, S->chi, e, S->psc, S->prc); if (split_char(S, chie, e,S->phi, &nue)) return 1; if (RgX_is_monomial(nue)) { /* v_p(e) = v_p(g - d) > 0 */ long Le, Ee; GEN pie; pie = getprime(S, e, chie, nue, &Le, &Ee, 0,Ea); if (pie) return testc2(S, S->nu, Ea, pie, Ee); break; } } if (i > Fg) { if (!p_is_prime(S)) pari_err_PRIME("nilord",S->p); pari_err_BUG("nilord (no root)"); } } if (eq) d = gmul(d, powiu(S->p, eq)); if (er) d = gmul(d, gpowgs(S->nu, er)); beta = gsub(beta, d); if (low_stack(limit,stack_lim(av,1))) { if (DEBUGMEM > 1) pari_warn(warnmem, "nilord"); gerepileall(av, S->invnu? 6: 4, &beta, &(S->precns), &(S->ns), &(S->nsf), &(S->invnu), &(S->Dinvnu)); } } } static long loop_init(decomp_t *S, GEN *popa, long *poE) { long oE = *poE; GEN opa = *popa; for(;;) { long l, La, Ea; /* N.B If oE = 0, getprime cannot return NULL */ GEN pia = getprime(S, NULL, S->chi, S->nu, &La, &Ea, oE,0); if (pia) { /* success, we break out in THIS loop */ opa = (typ(pia) == t_POL)? RgX_RgXQ_eval(pia, S->phi, S->f): pia; oE = Ea; if (La == 1) break; /* no need to change phi so that nu = pia */ } /* phi += prime elt */ S->phi = typ(opa) == t_INT? RgX_Rg_add_shallow(S->phi, opa) : RgX_add(S->phi, opa); /* recompute char. poly. chi from scratch */ S->chi = mycaract(S, S->f, S->phi, S->psf, S->pdf); S->nu = get_nu(S->chi, S->p, &l); if (l > 1) return l; /* we can get a decomposition */ if (!update_phi(S)) return 1; /* unramified / irreducible */ if (pia) break; } *poE = oE; *popa = opa; return 0; } /* flag != 0 iff we're looking for the p-adic factorization, in which case it is the p-adic precision we want */ static GEN nilord(decomp_t *S, GEN dred, long flag) { GEN p = S->p; long oE, l, N = degpol(S->f), v = varn(S->f); GEN opa; /* t_INT or QX */ if (DEBUGLEVEL>2) { err_printf(" entering Nilord"); if (DEBUGLEVEL>4) { err_printf(" with parameters: %Ps^%ld\n", p, S->df); err_printf(" fx = %Ps, gx = %Ps", S->f, S->nu); } err_printf("\n"); } S->psc = mulii(sqri(dred), p); S->vpsc= 2*S->df + 1; S->prc = mulii(dred, p); S->psf = S->psc; S->vpsf = S->vpsc; S->chi = FpX_red(S->f, S->psc); S->phi = pol_x(v); S->pmf = powiu(p, S->mf+1); S->precns = NULL; oE = 0; opa = NULL; /* -Wall */ for(;;) { long Fa = degpol(S->nu); S->phi0 = NULL; /* no delayed composition */ l = loop_init(S, &opa, &oE); if (l > 1) return Decomp(S,flag); if (l == 1) break; if (DEBUGLEVEL>4) err_printf(" (Fa, oE) = (%ld,%ld)\n", Fa, oE); if (oE*Fa == N) { /* O = Zp[phi] */ if (flag) return NULL; return dbasis(p, S->f, S->mf, redelt(S->phi,sqri(p),p), NULL); } if (loop(S, oE)) return Decomp(S,flag); if (!update_phi(S)) break; /* unramified / irreducible */ } if (flag) return NULL; S->nu = get_nu(S->chi, S->p, &l); return l != 1? Decomp(S,flag): dbasis(p, S->f, S->mf, S->phi, S->chi); } GEN maxord_i(GEN p, GEN f, long mf, GEN w, long flag) { long l = lg(w)-1; GEN h = gel(w,l); /* largest factor */ GEN D = ZpX_reduced_resultant_fast(f, ZX_deriv(f), p, mf); decomp_t S; S.f = f; S.pisprime = -1; S.p = p; S.mf = mf; S.nu = h; S.df = Z_pval(D, p); S.pdf = powiu(p, S.df); if (l == 1) return nilord(&S, D, flag); if (flag && flag <= mf) flag = mf + 1; S.phi = pol_x(varn(f)); S.chi = f; return Decomp(&S, flag); } /* DT = multiple of disc(T) or NULL * Return a multiple of the denominator of an algebraic integer (in Q[X]/(T)) * when expressed in terms of the power basis */ GEN indexpartial(GEN T, GEN DT) { pari_sp av = avma; long i, nb; GEN fa, E, P, res = gen_1, dT = ZX_deriv(T); if (!DT) DT = ZX_disc(T); fa = absi_factor_limit(DT, 0); P = gel(fa,1); E = gel(fa,2); nb = lg(P)-1; for (i = 1; i <= nb; i++) { long e = itou(gel(E,i)), e2 = e >> 1; GEN p = gel(P,i), q = p; if (i == nb) q = powiu(p, (odd(e) && !BPSW_psp(p))? e2+1: e2); else if (e2 >= 2) q = ZpX_reduced_resultant_fast(T, dT, p, e2); res = mulii(res, q); } return gerepileuptoint(av,res); } /*******************************************************************/ /* */ /* 2-ELT REPRESENTATION FOR PRIME IDEALS (dividing index) */ /* */ /*******************************************************************/ /* to compute norm of elt in basis form */ typedef struct { long r1; GEN M; /* via embed_norm */ GEN D, w, T; /* via resultant if M = NULL */ } norm_S; static GEN get_norm(norm_S *S, GEN a) { if (S->M) { long e; GEN N = grndtoi( embed_norm(RgM_RgC_mul(S->M, a), S->r1), &e ); if (e > -5) pari_err_PREC( "get_norm"); return N; } if (S->w) a = RgV_RgC_mul(S->w, a); return ZX_resultant_all(S->T, a, S->D, 0); } static void init_norm(norm_S *S, GEN nf, GEN p) { GEN T = nf_get_pol(nf); long N = degpol(T); 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; } if (!S->M) { GEN D, w = Q_remove_denom(nf_get_zk(nf), &D), Dp = sqri(p); long i; if (!D) w = leafcopy(w); else { GEN w1 = D; long v = Z_pval(D, p); D = powiu(p, v); Dp = mulii(D, Dp); gel(w, 1) = remii(w1, Dp); } for (i=2; i<=N; i++) gel(w,i) = FpX_red(gel(w,i), Dp); S->D = D; S->w = w; S->T = T; } } /* f = f(pr/p), q = p^(f+1), a in pr. * Return 1 if v_pr(a) = 1, and 0 otherwise */ static int is_uniformizer(GEN a, GEN q, norm_S *S) { return (remii(get_norm(S,a), q) != gen_0); } /* Return x * y, x, y are t_MAT (Fp-basis of in O_K/p), assume (x,y)=1. * Either x or y may be NULL (= O_K), not both */ static GEN mul_intersect(GEN x, GEN y, GEN p) { if (!x) return y; if (!y) return x; return FpM_intersect(x, y, p); } /* Fp-basis of (ZK/pr): applied to the primes found in primedec_aux() */ static GEN Fp_basis(GEN nf, GEN pr) { long i, j, l; GEN x, y; /* already in basis form (from Buchman-Lenstra) ? */ if (typ(pr) == t_MAT) return pr; /* ordinary prid (from Kummer) */ x = idealhnf_two(nf, pr); l = lg(x); y = cgetg(l, t_MAT); for (i=j=1; i=2; i--) gel(B,i-1) = mul_intersect(gel(B,i), gel(LW,i), p); for (i=1; i<=l; i++) gel(LV,i) = mul_intersect(gel(A,i), gel(B,i), p); return LV; } static void errprime(GEN p) { pari_err_PRIME("idealprimedec",p); } /* P = Fp-basis (over O_K/p) for pr. * V = Z-basis for I_p/pr. ramif != 0 iff some pr|p is ramified. * Return a p-uniformizer for pr. Assume pr not inert, i.e. m > 0 */ static GEN uniformizer(GEN nf, norm_S *S, GEN P, GEN V, GEN p, int ramif) { long i, l, f, m = lg(P)-1, N = nf_get_degree(nf); GEN u, Mv, x, q; f = N - m; /* we want v_p(Norm(x)) = p^f */ q = powiu(p,f+1); u = FpM_FpC_invimage(shallowconcat(P, V), col_ei(N,1), p); setlg(u, lg(P)); u = centermod(ZM_ZC_mul(P, u), p); if (is_uniformizer(u, q, S)) return u; if (signe(gel(u,1)) <= 0) /* make sure u[1] in ]-p,p] */ gel(u,1) = addii(gel(u,1), p); /* try u + p */ else gel(u,1) = subii(gel(u,1), p); /* try u - p */ if (!ramif || is_uniformizer(u, q, S)) return u; /* P/p ramified, u in P^2, not in Q for all other Q|p */ Mv = zk_multable(nf, unnf_minus_x(u)); l = lg(P); for (i=1; i1) */ t = poltobasis(nf, FpX_div(T,u,p)); t = centermod(t, p); u = FpX_center(u, p, shifti(p,-1)); if (e == 1) { norm_S S; S.D = S.w = S.M = NULL; S.T = T; if (!is_uniformizer(u, powiu(p,f+1), &S)) gel(u,2) = addii(gel(u,2), p); } u = poltobasis(nf,u); t = zk_scalar_or_multable(nf, t); } return mk_pr(p,u,e,f,t); } /* return a Z basis of Z_K's p-radical, phi = x--> x^p-x */ static GEN pradical(GEN nf, GEN p, GEN *phi) { long i, N = nf_get_degree(nf); GEN q,m,frob,rad; /* matrix of Frob: x->x^p over Z_K/p */ frob = cgetg(N+1,t_MAT); for (i=1; i<=N; i++) gel(frob,i) = pow_ei_mod_p(nf,i,p, p); m = frob; q = p; while (cmpiu(q,N) < 0) { q = mulii(q,p); m = FpM_mul(m, frob, p); } rad = FpM_ker(m, p); /* m = Frob^k, s.t p^k >= N */ for (i=1; i<=N; i++) gcoeff(frob,i,i) = subis(gcoeff(frob,i,i), 1); *phi = frob; return rad; } /* return powers of a: a^0, ... , a^d, d = dim A */ static GEN get_powers(GEN mul, GEN p) { long i, d = lgcols(mul); GEN z, pow = cgetg(d+2,t_MAT), P = pow+1; gel(P,0) = scalarcol_shallow(gen_1, d-1); z = gel(mul,1); for (i=1; i<=d; i++) { gel(P,i) = z; /* a^i */ if (i!=d) z = FpM_FpC_mul(mul, z, p); } return pow; } /* minimal polynomial of a in A (dim A = d). * mul = multiplication table by a in A */ static GEN pol_min(GEN mul, GEN p) { pari_sp av = avma; GEN z = FpM_deplin(get_powers(mul, p), p); return gerepilecopy(av, RgV_to_RgX(z,0)); } static GEN get_pr(GEN nf, norm_S *S, GEN p, GEN P, GEN V, int ramif, long N) { GEN u, t; long e, f; if (typ(P) == t_VEC) return P; /* already done (Kummer) */ f = N - (lg(P)-1); /* P = (p,u) prime. t is an anti-uniformizer: Z_K + t/p Z_K = P^(-1), * so that v_P(t) = e(P/p)-1 */ if (f == N) { u = scalarcol_shallow(p,N); t = gen_1; e = 1; } else { u = uniformizer(nf, S, P, V, p, ramif); t = FpM_deplin(zk_multable(nf,u), p); e = ramif? 1 + ZC_nfval(nf,t,mk_pr(p,u,0,0,t)): 1; t = zk_scalar_or_multable(nf, t); } return mk_pr(p,u,e,f,t); } static GEN primedec_end(GEN nf, GEN L, GEN p) { long i, l = lg(L), N = nf_get_degree(nf); GEN Lpr = cgetg(l, t_VEC); GEN LV = get_LV(nf, L,p,N); int ramif = dvdii(nf_get_disc(nf), p); norm_S S; init_norm(&S, nf, p); for (i=1; i x^p - x in algebra Z_K/p */ Ip = pradical(nf,p,&phi); /* split etale algebra Z_K / (p,Ip) */ h = cgetg(N+1,t_VEC); if (iL > 1) { /* split off Kummer factors */ GEN mulbeta, beta = NULL; for (i=1; i M2 * Mi2 projector A --> A2 */ GEN M, Mi, M2, Mi2, phi2; long dim; H = gel(h,c); k = lg(H)-1; M = FpM_suppl(shallowconcat(H,UN), p); Mi = FpM_inv(M, p); M2 = vecslice(M, k+1,N); /* M = (H|M2) invertible */ Mi2 = rowslice(Mi,k+1,N); /* FIXME: FpM_mul(,M2) could be done with vecpermute */ phi2 = FpM_mul(Mi2, FpM_mul(phi,M2, p), p); mat1 = FpM_ker(phi2, p); dim = lg(mat1)-1; /* A2 product of 'dim' fields */ if (dim > 1) { /* phi2 v = 0 <==> a = M2 v in Ker phi */ GEN R, a, mula, mul2, v = gel(mat1,2); long n; a = FpM_FpC_mul(M2,v, p); mula = zk_scalar_or_multable(nf, a); /* not a scalar */ mula = FpM_red(mula, p); mul2 = FpM_mul(Mi2, FpM_mul(mula,M2, p), p); R = FpX_roots(pol_min(mul2,p), p); /* totally split mod p */ n = lg(R)-1; for (i=1; i<=n; i++) { GEN r = gel(R,i), I = RgM_Rg_add_shallow(mula, negi(r)); 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; } } else /* A2 field ==> H maximal, f = N-k = dim(A2) */ gel(L,iL++) = H; } setlg(L, iL); return primedec_end(nf, L, p); } GEN idealprimedec(GEN nf, GEN p) { pari_sp av = avma; 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)); } /* return [Fp[x]: Fp] */ static long ffdegree(GEN x, GEN frob, GEN p) { pari_sp av = avma; long d, f = lg(frob)-1; GEN y = x; for (d=1; d < f; d++) { y = FpM_FpC_mul(frob, y, p); if (ZV_equal(y, x)) break; } avma = av; return d; } static GEN lift_to_zk(GEN v, GEN c, long N) { GEN w = zerocol(N); long i, l = lg(c); for (i=1; ix^p over Z_K/pr = < w[c1], ..., w[cf] > over Fp */ frob = cgetg(f+1, t_MAT); for (i=1; i<=f; i++) { x = pow_ei_mod_p(nf,c[i],p, p); gel(frob,i) = FpM_FpC_mul(ffproj, x, p); } u = col_ei(f,2); k = 2; deg1 = ffdegree(u, frob, p); while (deg1 < f) { k++; u2 = col_ei(f, k); deg2 = ffdegree(u2, frob, p); deg = clcm(deg1,deg2); if (deg == deg1) continue; if (deg == deg2) { deg1 = deg2; u = u2; continue; } u = ZC_add(u, u2); while (ffdegree(u, frob, p) < deg) u = ZC_add(u, u2); deg1 = deg; } v = lift_to_zk(u,c,N); mul = cgetg(f+1,t_MAT); gel(mul,1) = v; /* assume w_1 = 1 */ for (i=2; i<=f; i++) gel(mul,i) = zk_ei_mul(nf,v,c[i]); } /* Z_K/pr = Fp(v), mul = mul by v */ mul = FpM_red(mul, p); mul = FpM_mul(ffproj, mul, p); pow = get_powers(mul, p); T = RgV_to_RgX(FpM_deplin(pow, p), nf_get_varn(nf)); nfproj = cgetg(f+1, t_MAT); for (i=1; i<=f; i++) gel(nfproj,i) = lift_to_zk(gel(pow,i), c, N); nfproj = coltoliftalg(nf, nfproj); setlg(pow, f+1); ffproj = FpM_mul(FpM_inv(pow, p), ffproj, p); 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,mpr_NFP) = nfproj; return gerepilecopy(av, res); } GEN nfmodprinit(GEN nf, GEN pr) { return modprinit(nf, pr, 0); } GEN zkmodprinit(GEN nf, GEN pr) { return modprinit(nf, pr, 1); } /* x may be a modpr */ static int ok_modpr(GEN x) { return typ(x) == t_COL && lg(x) >= SMALLMODPR && lg(x) <= LARGEMODPR; } void checkmodpr(GEN x) { if (!ok_modpr(x)) pari_err_TYPE("checkmodpr [use nfmodprinit]", x); checkprid(gel(x,mpr_PR)); } static int is_prid(GEN x) { return (typ(x) == t_VEC && lg(x) == 6 && typ(gel(x,2)) == t_COL && typ(gel(x,3)) == t_INT); } void checkprid(GEN x) { if (!is_prid(x)) pari_err_TYPE("checkprid",x); } GEN get_prid(GEN x) { long lx = lg(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); if (is_prid(x)) return x; } return NULL; } 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; } /* Return an element of O_K which is set to x Mod T */ GEN modpr_genFq(GEN modpr) { switch(lg(modpr)) { case SMALLMODPR: /* Fp */ return gen_1; case LARGEMODPR: /* painful case, p \mid index */ return gmael(modpr,mpr_NFP, 2); default: /* trivial case : p \nmid index */ { long v = varn( gel(modpr, mpr_T) ); return pol_x(v); } } } GEN nf_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p) { GEN modpr = to_ff_init(nf,pr,T,p,0); GEN tau = modpr_TAU(modpr); if (!tau) gel(modpr,mpr_TAU) = anti_uniformizer2(nf, *pr); return modpr; } GEN zk_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p) { return to_ff_init(nf,pr,T,p,1); } /* assume x in 'basis' form (t_COL) */ GEN zk_to_Fq(GEN x, GEN modpr) { GEN pr = gel(modpr,mpr_PR), 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))); } /* REDUCTION Modulo a prime ideal */ /* nf a true nf */ 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); long tx = typ(x); if (tx == t_POLMOD) { x = gel(x,2); tx = typ(x); } switch(tx) { case t_INT: return modii(x, p); case t_FRAC: return Rg_to_Fp(x, p); case t_POL: switch(lg(x)) { case 2: return gen_0; case 3: return Rg_to_Fp(gel(x,2), p); } x = Q_remove_denom(x, &den); x = poltobasis(nf, x); /* content(x) and den may not be coprime */ break; case t_COL: x = Q_remove_denom(x, &den); /* content(x) and den are coprime */ if (lg(x) == lg(nf_get_zk(nf))) break; default: pari_err_TYPE("Rg_to_ff",x); return NULL; } if (den) { long v = Z_pvalrem(den, p, &den); if (v) { if (tx == t_POL) v -= ZV_pvalrem(x, p, &x); /* now v = valuation(true denominator of x) */ if (v > 0) { GEN tau = modpr_TAU(modpr); if (!tau) pari_err_TYPE("zk_to_ff", x0); x = nfmuli(nf,x, nfpow_u(nf, tau, v)); v -= ZV_pvalrem(x, p, &x); } if (v > 0) pari_err_INV("Rg_to_ff", mkintmod(gen_0,p)); if (v) return gen_0; } if (!is_pm1(den)) x = ZC_Z_mul(x, Fp_inv(den, p)); x = FpC_red(x, p); } return zk_to_Fq(x, modpr); } GEN nfreducemodpr(GEN nf, GEN x, GEN modpr) { pari_sp av = avma; nf = checknf(nf); checkmodpr(modpr); return gerepileupto(av, algtobasis(nf, Fq_to_nf(Rg_to_ff(nf,x,modpr),modpr))); } /* lift A from residue field to nf */ GEN Fq_to_nf(GEN A, GEN modpr) { long dA; if (typ(A) == t_INT || lg(modpr) < LARGEMODPR) return A; dA = degpol(A); if (dA <= 0) return dA ? gen_0: gel(A,2); return mulmat_pol(gel(modpr,mpr_NFP), A); } GEN FqV_to_nfV(GEN A, GEN modpr) { long i,l = lg(A); GEN B = cgetg(l,typ(A)); for (i=1; imultab,x) : tablemul_ei_ej(D->multab,D->h,D->h); return FqV_red(z,D->T,D->p); } static GEN _msqr(void *data, GEN x) { GEN x2 = _sqr(data, x), z; rnfeltmod_muldata *D = (rnfeltmod_muldata *) data; z = tablemul_ei(D->multab, x2, D->h); return FqV_red(z,D->T,D->p); } /* Compute W[h]^n mod (T,p) in the extension, assume n >= 0. T a ZX */ static GEN rnfeltid_powmod(GEN multab, long h, GEN n, GEN T, GEN p) { pari_sp av = avma; GEN y; rnfeltmod_muldata D; if (!signe(n)) return gen_1; D.multab = multab; D.h = h; D.T = T; D.p = p; y = gen_pow_fold(NULL, n, (void*)&D, &_sqr, &_msqr); return gerepilecopy(av, y); } /* P != 0 has at most degpol(P) roots. Look for an element in Fq which is not * a root, cf repres() */ static GEN FqX_non_root(GEN P, GEN T, GEN p) { long dP = degpol(P), f, vT; long i, j, k, pi, pp; GEN v; if (dP == 0) return gen_1; pp = is_bigint(p) ? dP+1: itos(p); v = cgetg(dP + 2, t_VEC); gel(v,1) = gen_0; if (T) { f = degpol(T); vT = varn(T); } else { f = 1; vT = 0; } for (i=pi=1; i<=f; i++,pi*=pp) { GEN gi = i == 1? gen_1: monomial(gen_1, i-1, vT), jgi = gi; for (j=1; j only_maximal = 1 */ { if (mpr < 0) return NULL; if (! RgX_valrem(Ppr, &Ppr)) { /* non-zero constant coefficient */ Ppr = RgX_shift_shallow(RgX_recip_shallow(Ppr), m - mpr); P = RgX_recip_shallow(P); } else { GEN z = FqX_non_root(Ppr, T, p); if (!z) pari_err_IMPL( "Dedekind in the difficult case"); z = Fq_to_nf(z, modpr); if (typ(z) == t_INT) P = RgX_translate(P, z); else P = RgXQX_translate(P, z, T); P = RgX_recip_shallow(P); Ppr = nfX_to_FqX(P, nf, modpr); /* degpol(P) = degpol(Ppr) = m */ } } A = gel(FqX_factor(Ppr,T,p),1); r = lg(A); /* > 1 */ g = gel(A,1); for (i=2; i1) err_printf(" treating %Ps^%ld\n", pr, vdisc); modpr = nf_to_Fq_init(nf,&pr,&T,&p); av1 = avma; p1 = rnfdedekind_i(nf, pol, modpr, vdisc, 0); if (!p1) { avma = av; return NULL; } if (is_pm1(gel(p1,1))) return gerepilecopy(av,gel(p1,2)); sep = itos(gel(p1,3)); W = gmael(p1,2,1); I = gmael(p1,2,2); gerepileall(av1, 2, &W, &I); pip = coltoalg(nf, pr_get_gen(pr)); nfT = nf_get_pol(nf); n = degpol(pol); vpol = varn(pol); q = T? powiu(p,degpol(T)): p; q1 = q; while (cmpiu(q1,n) < 0) q1 = mulii(q1,q); rnfId = matid(n); prhinv = idealinv(nf, pr); C = cgetg(n+1, t_MAT); for (j=1; j<=n; j++) gel(C,j) = cgetg(n*n+1, t_COL); MW = cgetg(n*n+1, t_MAT); 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); for(cmpt=1; ; cmpt++) { GEN I0 = leafcopy(I), W0 = leafcopy(W); GEN Wa, Wainv, Waa, Ip, A, Ainv, MWmod, F, pseudo, G; if (DEBUGLEVEL>1) err_printf(" pass no %ld\n",cmpt); for (j=1; j<=n; j++) { GEN tau, tauinv; long v1, v2; if (ideal_is1(gel(I,j))) { gel(Tau,j) = gel(Tauinv,j) = gen_1; continue; } p1 = idealtwoelt(nf,gel(I,j)); v1 = nfval(nf,gel(p1,1),pr); v2 = nfval(nf,gel(p1,2),pr); tau = (v1 > v2)? gel(p1,2): gel(p1,1); tauinv = nfinv(nf, tau); gel(Tau,j) = tau; gel(Tauinv,j) = tauinv; gel(W,j) = nfC_nf_mul(nf, gel(W,j), tau); gel(I,j) = idealmul(nf, tauinv, gel(I,j)); } /* W = (Z_K/pr)-basis of O/pr. O = (W0,I0) ~ (W, I) */ Wa = matbasistoalg(nf,W); /* compute MW: W_i*W_j = sum MW_k,(i,j) W_k */ Waa = lift_intern(RgM_to_RgXV(Wa,vpol)); Wainv = lift_intern(ginv(Wa)); for (i=1; i<=n; i++) for (j=i; j<=n; j++) { GEN z = RgXQX_rem(gmul(gel(Waa,i),gel(Waa,j)), pol, nfT); long tz = typ(z); if (is_scalar_t(tz) || (tz == t_POL && varncmp(varn(z), vpol) > 0)) z = gmul(z, gel(Wainv,1)); else z = mulmat_pol(Wainv, z); for (k=1; k<=n; k++) { GEN c = grem(gel(z,k), nfT); gcoeff(MW, k, (i-1)*n+j) = c; gcoeff(MW, k, (j-1)*n+i) = c; } } /* compute Ip = pr-radical [ could use Ker(trace) if q large ] */ MWmod = nfM_to_FqM(MW,nf,modpr); F = cgetg(n+1, t_MAT); gel(F,1) = gel(rnfId,1); for (j=2; j<=n; j++) gel(F,j) = rnfeltid_powmod(MWmod, j, q1, T,p); Ip = FqM_ker(F,T,p); if (lg(Ip) == 1) { W = W0; I = I0; break; } /* Fill C: W_k A_j = sum_i C_(i,j),k A_i */ A = FqM_to_nfM(FqM_suppl(Ip,T,p), modpr); for (j=1; j3) 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(DEBUGMEM>1) pari_warn(warnmem,"rnfmaxord"); gerepileall(av1,2, &W,&I); } } return gerepilecopy(av, mkvec2(W, I)); } GEN Rg_nffix(const char *f, GEN T, GEN c, int lift) { switch(typ(c)) { case t_INT: case t_FRAC: return c; case t_POL: if (lg(c) >= lg(T)) c = RgX_rem(c,T); break; case t_POLMOD: if (!RgX_equal_var(gel(c,1), T)) pari_err_MODULUS(f, gel(c,1),T); c = gel(c,2); switch(typ(c)) { case t_POL: break; case t_INT: case t_FRAC: return c; default: pari_err_TYPE(f, c); } break; default: pari_err_TYPE(f,c); } /* typ(c) = t_POL */ if (varn(c) != varn(T)) pari_err_VAR(f, c,T); switch(lg(c)) { case 2: return gen_0; case 3: c = gel(c,2); if (is_rational_t(typ(c))) return c; pari_err_TYPE(f,c); } if (!RgX_is_QX(c)) pari_err_TYPE(f, c); return lift? c: mkpolmod(c, T); } /* check whether P is a polynomials with coeffs in number field Q[y]/(T) */ GEN RgX_nffix(const char *f, GEN T, GEN P, int lift) { long i, l, vT = varn(T); GEN Q = cgetg_copy(P, &l); if (typ(P) != t_POL) pari_err_TYPE(stack_strcat(f," [t_POL expected]"), P); if (varncmp(varn(P), vT) >= 0) pari_err_PRIORITY(f, P, ">=", vT); Q[1] = P[1]; for (i=2; i 1) z = rnfjoinmodules(nf, z, rnfmaxord(nf, pol, gel(P,i), e)); } if (!z) z = triv_order(n); A = gel(z,1); d = get_d(nf, pol, A); I = gel(z,2); i=1; while (i<=n && equali1(gel(I,i))) i++; if (i > n) { D = gen_1; if (pf) *pf = gen_1; } else { D = gel(I,i); for (i++; i<=n; i++) D = idealmul(nf,D,gel(I,i)); if (pf) *pf = idealinv(nf, D); D = idealpow(nf,D,gen_2); } if (pd) { GEN f = core2partial(Q_content(d), 0); *pd = gdiv(d, sqri(gel(f,2))); } *pD = idealmul(nf,D,d); *ppol = pol; return z; } GEN rnfpseudobasis(GEN nf, GEN pol) { pari_sp av = avma; GEN D, d, z = rnfallbase(nf,&pol, &D, &d, NULL); return gerepilecopy(av, mkvec4(gel(z,1), gel(z,2), D, d)); } GEN rnfdiscf(GEN nf, GEN pol) { pari_sp av = avma; GEN D, d; (void)rnfallbase(nf,&pol, &D, &d, NULL); return gerepilecopy(av, mkvec2(D,d)); } GEN gen_if_principal(GEN bnf, GEN x) { pari_sp av = avma; GEN z = bnfisprincipal0(bnf,x, nf_GEN_IF_PRINCIPAL | nf_FORCE); if (isintzero(z)) { avma = av; return NULL; } return z; } static int is_pseudo_matrix(GEN O) { return (typ(O) ==t_VEC && lg(O) >= 3 && typ(gel(O,1)) == t_MAT && typ(gel(O,2)) == t_VEC && lgcols(O) == lg(gel(O,2))); } /* given bnf and a pseudo-basis of an order in HNF [A,I], tries to simplify * the HNF as much as possible. The resulting matrix will be upper triangular * but the diagonal coefficients will not be equal to 1. The ideals are * guaranteed to be integral and primitive. */ GEN rnfsimplifybasis(GEN bnf, GEN x) { pari_sp av = avma; long i, l; GEN y, Az, Iz, nf, A, I; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if (!is_pseudo_matrix(x)) pari_err_TYPE("rnfsimplifybasis",x); A = gel(x,1); I = gel(x,2); l = lg(I); y = cgetg(3, t_VEC); Az = cgetg(l, t_MAT); gel(y,1) = Az; Iz = cgetg(l, t_VEC); gel(y,2) = Iz; for (i = 1; i < l; i++) { GEN c, d; if (ideal_is1(gel(I,i))) { gel(Iz,i) = gen_1; gel(Az,i) = gel(A,i); continue; } gel(Iz,i) = Q_primitive_part(gel(I,i), &c); gel(Az,i) = c? RgC_Rg_mul(gel(A,i),c): gel(A,i); if (c && ideal_is1(gel(Iz,i))) continue; d = gen_if_principal(bnf, gel(Iz,i)); if (d) { gel(Iz,i) = gen_1; gel(Az,i) = nfC_nf_mul(nf, gel(Az,i), d); } } return gerepilecopy(av, y); } static GEN get_order(GEN nf, GEN O, const char *s) { if (typ(O) == t_POL) return rnfpseudobasis(nf, O); if (!is_pseudo_matrix(O)) pari_err_TYPE(s, O); return O; } GEN rnfdet(GEN nf, GEN order) { pari_sp av = avma; GEN A, I, D; nf = checknf(nf); order = get_order(nf, order, "rnfdet"); A = gel(order,1); I = gel(order,2); D = idealmul(nf, det(matbasistoalg(nf, A)), prodid(nf, I)); return gerepileupto(av, D); } /* Given two fractional ideals a and b, gives x in a, y in b, z in b^-1, t in a^-1 such that xt-yz=1. In the present version, z is in Z. */ static void nfidealdet1(GEN nf, GEN a, GEN b, GEN *px, GEN *py, GEN *pz, GEN *pt) { GEN x, uv, y, da, db; a = idealinv(nf,a); a = Q_remove_denom(a, &da); b = Q_remove_denom(b, &db); x = idealcoprime(nf,a,b); uv = idealaddtoone(nf, idealmul(nf,x,a), b); y = gel(uv,2); if (da) x = RgC_Rg_mul(x,da); if (db) y = RgC_Rg_div(y,db); *px = x; *py = y; *pz = db ? negi(db): gen_m1; *pt = nfdiv(nf, gel(uv,1), x); } /* given a pseudo-basis of an order in HNF [A,I] (or [A,I,D,d]), gives an * n x n matrix (not in HNF) of a pseudo-basis and an ideal vector * [1,1,...,1,I] such that order = Z_K^(n-1) x I. * Uses the approximation theorem ==> slow. */ GEN rnfsteinitz(GEN nf, GEN order) { pari_sp av = avma; long i, n, l; GEN A, I, p1; nf = checknf(nf); order = get_order(nf, order, "rnfsteinitz"); A = RgM_to_nfM(nf, gel(order,1)); I = leafcopy(gel(order,2)); n=lg(A)-1; for (i=1; in) return 1; P = gel(I,j); for (j++; j<=n; j++) if (!ideal_is1(gel(I,j))) P = idealmul(nf,P,gel(I,j)); return gequal0( isprincipal(bnf,P) ); } long rnfisfree(GEN bnf, GEN order) { pari_sp av = avma; long n = rnfisfree_aux(bnf, order); avma = av; return n; } /**********************************************************************/ /** **/ /** COMPOSITUM OF TWO NUMBER FIELDS **/ /** **/ /**********************************************************************/ static GEN compositum_fix(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); return A; } /* modular version */ GEN polcompositum0(GEN A, GEN B, long flall) { pari_sp av = avma; int same; long v, k; GEN C, D, LPRS; if (typ(A)!=t_POL) pari_err_TYPE("polcompositum",A); if (typ(B)!=t_POL) pari_err_TYPE("polcompositum",B); if (degpol(A)<=0 || degpol(B)<=0) pari_err_CONSTPOL("polcompositum"); 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); D = NULL; /* -Wall */ k = same? -1: 1; C = ZX_ZXY_resultant_all(A, B, &k, flall? &LPRS: NULL); 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); } 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) { /* 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); for (i=1; i prec) prec = l; } return prec; } long ZM_max_lg(GEN x) { long i, prec = 2, n = lg(x); if (n != 1) { long j, m = lgcols(x); for (j=1; j prec) prec = l; } } } return prec; } GEN ZM_supnorm(GEN x) { long i, j, h, lx = lg(x); GEN s = gen_0; if (lx == 1) return gen_1; h = lgcols(x); for (j=1; j 0) s = c; } } return absi(s); } /********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /********************************************************************/ /* x non-empty ZM, y a compatible nc (dimension > 0). */ static GEN ZM_nc_mul_i(GEN x, GEN y, long c, long l) { long i, j; pari_sp av; GEN z = cgetg(l,t_COL), s; for (i=1; i 0). */ static GEN ZM_zc_mul_i(GEN x, GEN y, long c, long l) { long i, j; pari_sp av; GEN z = cgetg(l,t_COL), s; for (i=1; i 0). */ GEN ZM_zm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = ZM_zc_mul_i(x, gel(y,j), l,c); return z; } /* x ZM, y a compatible zn (dimension > 0). */ GEN ZM_nm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = ZM_nc_mul_i(x, gel(y,j), l,c); return z; } /* x[i,]*y. Assume lg(x) > 1 and 0 < i < lgcols(x) */ static GEN ZMrow_ZC_mul_i(GEN x, GEN y, long i, long lx) { pari_sp av = avma; GEN c = mulii(gcoeff(x,i,1), gel(y,1)), ZERO = gen_0; long k; for (k = 2; k < lx; k++) { GEN t = mulii(gcoeff(x,i,k), gel(y,k)); if (t != ZERO) c = addii(c, t); } return gerepileuptoint(av, c); } GEN ZMrow_ZC_mul(GEN x, GEN y, long i) { return ZMrow_ZC_mul_i(x, y, i, lg(x)); } /* return x * y, 1 < lx = lg(x), l = lgcols(x) */ static GEN ZM_ZC_mul_i(GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i 1 is lg(x) = lg(y) */ static GEN ZV_dotproduct_i(GEN x, GEN y, long lx) { pari_sp av = avma; GEN c = mulii(gel(x,1), gel(y,1)); long i; for (i = 2; i < lx; i++) { GEN t = mulii(gel(x,i), gel(y,i)); if (t != gen_0) c = addii(c, t); } return gerepileuptoint(av, c); } /* x~ * y, assuming result is symmetric */ GEN ZM_transmultosym(GEN x, GEN y) { long i, j, l, ly = lg(y); GEN M; if (ly == 1) return cgetg(1,t_MAT); /* lg(x) = ly */ l = lgcols(y); /* = lgcols(x) */ M = cgetg(ly, t_MAT); for (i=1; i 0)? ZC_copy(X): ZC_neg(X); l = lg(X); A = cgetg(l, t_COL); for (i=1; i 0) N[l] = M[l]*n; return N; } /* return a ZM */ GEN nm_Z_mul(GEN X, GEN c) { long i, j, h, l = lg(X), s = signe(c); GEN A; if (l == 1) return cgetg(1, t_MAT); h = lgcols(X); if (!s) return zeromat(h-1, l-1); if (is_pm1(c)) { if (s > 0) return Flm_to_ZM(X); X = Flm_to_ZM(X); ZM_togglesign(X); return X; } A = cgetg(l, t_MAT); 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) = muliu(c, x[i]); gel(A,j) = a; } return A; } GEN ZM_Z_mul(GEN X, GEN c) { long i, j, h, l = lg(X); GEN A; if (l == 1) return cgetg(1, t_MAT); h = lgcols(X); if (!signe(c)) return zeromat(h-1, l-1); if (is_pm1(c)) return (signe(c) > 0)? ZM_copy(X): ZM_neg(X); A = cgetg(l, t_MAT); 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) = mulii(c, gel(x,i)); gel(A,j) = a; } return A; } /* X <- X + v Y (elementary col operation) */ void ZC_lincomb1_inplace(GEN X, GEN Y, GEN v) { long i, m = lgefint(v); if (m == 2) return; /* v = 0 */ for (i = lg(X)-1; i; i--) gel(X,i) = addmulii_inplace(gel(X,i), gel(Y,i), v); } void Flc_lincomb1_inplace(GEN X, GEN Y, ulong v, ulong q) { long i; if (!v) return; /* v = 0 */ for (i = lg(X)-1; i; i--) X[i] = Fl_add(X[i], Fl_mul(Y[i], v, q), q); } /* X + v Y, wasteful if (v = 0) */ static GEN ZC_lincomb1(GEN v, GEN X, GEN Y) { long i, lx = lg(X); GEN A = cgetg(lx,t_COL); for (i=1; i 0) A = ZC_lincomb1 (u, Y, X); else A = ZC_lincomb_1(u, Y, X); } } else if (is_pm1(u)) { if (su > 0) A = ZC_lincomb1 (v, X, Y); else A = ZC_lincomb_1(v, X, Y); } else { /* not cgetg_copy: x may be a t_VEC */ long i, lx = lg(X); A = cgetg(lx,t_COL); for (i=1; i 0) gel(y,l) = ZC_copy(gel(x,l)); return y; } void ZV_neg_inplace(GEN M) { long l = lg(M); while (--l > 0) gel(M,l) = negi(gel(M,l)); } GEN ZC_neg(GEN M) { long l = lg(M); GEN N = cgetg(l, t_COL); while (--l > 0) gel(N,l) = negi(gel(M,l)); return N; } GEN zv_neg(GEN M) { long l; GEN N = cgetg_copy(M, &l); while (--l > 0) N[l] = -M[l]; return N; } GEN zv_neg_inplace(GEN M) { long l = lg(M); while (--l > 0) M[l] = -M[l]; return M; } GEN ZM_neg(GEN x) { long l; GEN y = cgetg_copy(x, &l); while (--l > 0) gel(y,l) = ZC_neg(gel(x,l)); return y; } void ZV_togglesign(GEN M) { long l = lg(M); while (--l > 0) togglesign_safe(&gel(M,l)); } void ZM_togglesign(GEN M) { long l = lg(M); while (--l > 0) ZV_togglesign(gel(M,l)); } /********************************************************************/ /** **/ /** "DIVISION" mod HNF **/ /** **/ /********************************************************************/ /* Reduce ZC x modulo ZM y in HNF, may return x itself (not a copy) */ GEN ZC_hnfremdiv(GEN x, GEN y, GEN *Q) { long i, l = lg(x); GEN q; if (Q) *Q = cgetg(l,t_COL); if (l == 1) return cgetg(1,t_COL); for (i = l-1; i>0; i--) { q = diviiround(gel(x,i), gcoeff(y,i,i)); if (signe(q)) { togglesign(q); x = ZC_lincomb(gen_1, q, x, gel(y,i)); } if (Q) gel(*Q, i) = q; } return x; } /* x = y Q + R, may return some columns of x (not copies) */ GEN ZM_hnfdivrem(GEN x, GEN y, GEN *Q) { long lx = lg(x), i; GEN R = cgetg(lx, t_MAT); if (Q) { GEN q = cgetg(lx, t_MAT); *Q = q; for (i=1; i 0) if (V[l]) return 0; return 1; } int ZV_equal0(GEN V) { long l = lg(V); while (--l > 0) if (signe(gel(V,l))) return 0; return 1; } static int ZV_equal_lg(GEN V, GEN W, long l) { while (--l > 0) if (!equalii(gel(V,l), gel(W,l))) return 0; return 1; } int ZV_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; return ZV_equal_lg(V, W, l); } int ZM_equal(GEN A, GEN B) { long i, m, l = lg(A); if (lg(B) != l) return 0; if (l == 1) return 1; m = lgcols(A); if (lgcols(B) != m) return 0; for (i = 1; i < l; i++) if (!ZV_equal_lg(gel(A,i), gel(B,i), m)) return 0; return 1; } int zv_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; while (--l > 0) if (V[l] != W[l]) return 0; return 1; } int zvV_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; while (--l > 0) if (!zv_equal(gel(V,l),gel(W,l))) return 0; return 1; } int ZM_ishnf(GEN x) { long i,j, lx = lg(x); for (i=1; i=0) return 0; } } return 1; } int ZM_isidentity(GEN x) { long i,j, lx = lg(x); if (lx == 1) return 1; if (lx != lgcols(x)) return 0; for (j=1; j> 1; x = cgetg(m + (odd(n)? 2: 1), t_VEC); for (k = 1; k <= m; k++) gel(x,k) = muluu(v[k<<1], v[(k<<1)-1]); if (odd(n)) gel(x,k) = utoipos(v[n]); return gerepileuptoint(av, divide_conquer_prod(x, mulii)); } GEN ZV_prod(GEN v) { pari_sp av = avma; long i, l = lg(v); GEN n; if (l == 1) return gen_1; if (l > 7) return gerepileuptoint(av, divide_conquer_prod(v, mulii)); n = gel(v,1); if (l == 2) return icopy(n); for (i = 2; i < l; i++) n = mulii(n, gel(v,i)); return gerepileuptoint(av, n); } /* assumes no overflow */ long zv_sum(GEN v) { long n, i, l = lg(v); if (l == 1) return 0; n = v[1]; for (i = 2; i < l; i++) n += v[i]; return n; } GEN ZV_sum(GEN v) { pari_sp av = avma; long i, l = lg(v); GEN n; if (l == 1) return gen_0; n = gel(v,1); if (l == 2) return icopy(n); for (i = 2; i < l; i++) n = addii(n, gel(v,i)); return gerepileuptoint(av, n); } /********************************************************************/ /** **/ /** GRAM SCHMIDT REDUCTION (integer matrices) **/ /** **/ /********************************************************************/ /* L[k,] += q * L[l,], l < k. Inefficient if q = 0 */ static void Zupdate_row(long k, long l, GEN q, GEN L, GEN B) { long i, qq = itos_or_0(q); if (!qq) { for(i=1;i= 1; k--) ZRED(nx,k, x,L,gel(B,k+1)); return gel(x,nx); } GEN ZC_reducemodmatrix(GEN v, GEN y) { pari_sp av = avma; return gerepilecopy(av, ZC_reducemodmatrix_i(v,y)); } /* Variant reducemodinvertible(ZM v, ZM y), when y singular. * Very inefficient if y is not LLL-reduced of maximal rank */ static GEN ZM_reducemodmatrix_i(GEN v, GEN y) { GEN B, L, V; long j, k, lv = lg(v), nx = lg(y), lx = nx+1; V = cgetg(lv, t_MAT); B = scalarcol_shallow(gen_1, lx); L = zeromatcopy(nx, nx); for (k=1; k < nx; k++) ZincrementalGS(y, L, B, k); for (j = 1; j < lg(v); j++) { GEN x = shallowconcat(y, gel(v,j)); ZincrementalGS(x, L, B, nx); /* overwrite last */ for (k = nx-1; k >= 1; k--) ZRED(nx,k, x,L,gel(B,k+1)); gel(V,j) = gel(x,nx); } return V; } GEN ZM_reducemodmatrix(GEN v, GEN y) { pari_sp av = avma; return gerepilecopy(av, ZM_reducemodmatrix_i(v,y)); } GEN ZC_reducemodlll(GEN x,GEN y) { pari_sp av = avma; GEN z = ZC_reducemodmatrix(x, ZM_lll(y, 0.75, LLL_INPLACE)); return gerepilecopy(av, z); } GEN ZM_reducemodlll(GEN x,GEN y) { pari_sp av = avma; GEN z = ZM_reducemodmatrix(x, ZM_lll(y, 0.75, LLL_INPLACE)); return gerepilecopy(av, z); } pari-2.7.5/src/basemath/FpX.c0000644000175000017500000013210212413013142014310 0ustar billbill/* Copyright (C) 2007 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 polynomials over Fp */ static GEN get_FpX_red(GEN T, GEN *B) { if (typ(T)!=t_VEC) { *B=NULL; return T; } *B = gel(T,1); return gel(T,2); } GEN get_FpX_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } long get_FpX_var(GEN T) { return typ(T)==t_VEC? varn(gel(T,2)): varn(T); } long get_FpX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } /***********************************************************************/ /** **/ /** FpX **/ /** **/ /***********************************************************************/ /* FpX are polynomials over Z/pZ represented as t_POL with * t_INT coefficients. * 1) Coefficients should belong to {0,...,p-1}, though non-reduced * coefficients should work but be slower. * * 2) p is not assumed to be prime, but it is assumed that impossible divisions * will not happen. * 3) Theses functions let some garbage on the stack, but are gerepileupto * compatible. */ static ulong to_Flx(GEN *P, GEN *Q, GEN p) { ulong pp = (ulong)p[2]; *P = ZX_to_Flx(*P, pp); *Q = ZX_to_Flx(*Q, pp); return pp; } static ulong to_Flxq(GEN *P, GEN *T, GEN p) { ulong pp = (ulong)p[2]; if (P) *P = ZX_to_Flx(*P, pp); *T = ZXT_to_FlxT(*T, pp); return pp; } GEN Z_to_FpX(GEN a, GEN p, long v) { pari_sp av = avma; GEN z = cgetg(3, t_POL); GEN x = modii(a, p); if (!signe(x)) { avma =av; return pol_0(v); } z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = x; return z; } /* z in Z[X], return lift(z * Mod(1,p)), normalized*/ GEN FpX_red(GEN z, GEN p) { long i, l = lg(z); GEN x = cgetg(l, t_POL); for (i=2; i= ny) { lz = nx+2; z = cgetg(lz,t_POL); z[1] = 0; z += 2; for (i=0; i=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); if (lead) p1 = mulii(p1,lead); gel(z,i-dy) = gerepileuptoint(av,modii(p1, p)); } if (!pr) { if (lead) gunclone(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); p1 = modii(p1,p); if (signe(p1)) { sx = 1; break; } if (!i) break; avma=av; } if (pr == ONLY_DIVIDES) { if (lead) gunclone(lead); if (sx) { avma=av0; return NULL; } avma = (pari_sp)rem; return z-2; } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; p1 = gerepileuptoint((pari_sp)rem, p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); gel(rem,i) = gerepileuptoint(av, modii(p1,p)); } rem -= 2; if (lead) gunclone(lead); if (!sx) (void)FpX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } GEN FpX_div_by_X_x(GEN a, GEN x, 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) = Fp_addmul(gel(a,i+1), x, gel(z,i+1), p); if (r) *r = Fp_addmul(gel(a,2), x, gel(z,2), p); return z; } long FpX_valrem(GEN x, GEN t, GEN p, GEN *py) { pari_sp av=avma; long k; GEN r, y; for (k=0; ; k++) { y = FpX_divrem(x, t, p, &r); if (signe(r)) break; x = y; } *py = gerepilecopy(av,x); return k; } static GEN FpX_halfgcd_basecase(GEN a, GEN b, GEN p) { pari_sp av=avma, lim = stack_lim(av,2); GEN u,u1,v,v1; long vx = varn(a); long n = lgpol(a)>>1; u1 = v = pol_0(vx); u = v1 = pol_1(vx); while (lgpol(b)>n) { GEN r, q = FpX_divrem(a,b,p, &r); 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 (DEBUGMEM>1) pari_warn(warnmem,"FpX_halfgcd (d = %ld)",degpol(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } return gerepilecopy(av, mkmat2(mkcol2(u,u1), mkcol2(v,v1))); } static GEN FpX_addmulmul(GEN u, GEN v, GEN x, GEN y, GEN p) { return FpX_add(FpX_mul(u, x, p),FpX_mul(v, y, p), p); } static GEN FpXM_FpX_mul2(GEN M, GEN x, GEN y, GEN p) { GEN res = cgetg(3, t_COL); gel(res, 1) = FpX_addmulmul(gcoeff(M,1,1), gcoeff(M,1,2), x, y, p); gel(res, 2) = FpX_addmulmul(gcoeff(M,2,1), gcoeff(M,2,2), x, y, p); return res; } /*TODO: implement Strassen 7 multiplications formula (p is large) */ static GEN FpXM_mul2(GEN M, GEN N, GEN p) { GEN res = cgetg(3, t_MAT); gel(res, 1) = FpXM_FpX_mul2(M,gcoeff(N,1,1),gcoeff(N,2,1),p); gel(res, 2) = FpXM_FpX_mul2(M,gcoeff(N,1,2),gcoeff(N,2,2),p); return res; } /* Return [0,1;1,-q]*M */ static GEN FpX_FpXM_qmul(GEN q, GEN M, GEN p) { GEN u, v, res = cgetg(3, t_MAT); u = FpX_sub(gcoeff(M,1,1), FpX_mul(gcoeff(M,2,1), q, p), p); gel(res,1) = mkcol2(gcoeff(M,2,1), u); v = FpX_sub(gcoeff(M,1,2), FpX_mul(gcoeff(M,2,2), q, p), p); gel(res,2) = mkcol2(gcoeff(M,2,2), v); return res; } static GEN matid2_FpXM(long v) { retmkmat2(mkcol2(pol_1(v),pol_0(v)), mkcol2(pol_0(v),pol_1(v))); } static GEN FpX_halfgcd_split(GEN x, GEN y, GEN p) { pari_sp av=avma; GEN R, S, V; GEN y1, r, q; long l = lgpol(x), n = l>>1, k; if (lgpol(y)<=n) return matid2_FpXM(varn(x)); R = FpX_halfgcd(RgX_shift_shallow(x,-n),RgX_shift_shallow(y,-n),p); V = FpXM_FpX_mul2(R,x,y,p); y1 = gel(V,2); if (lgpol(y1)<=n) return gerepilecopy(av, R); q = FpX_divrem(gel(V,1), y1, p, &r); k = 2*n-degpol(y1); S = FpX_halfgcd(RgX_shift_shallow(y1,-k), RgX_shift_shallow(r,-k),p); return gerepileupto(av, FpXM_mul2(S,FpX_FpXM_qmul(q,R,p),p)); } /* Return M in GL_2(Fp[X]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ static GEN FpX_halfgcd_i(GEN x, GEN y, GEN p) { if (lg(x)<=FpX_HALFGCD_LIMIT) return FpX_halfgcd_basecase(x,y,p); return FpX_halfgcd_split(x,y,p); } GEN FpX_halfgcd(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN M,q,r; if (lgefint(p)==3) { ulong pp = to_Flx(&x, &y, p); M = FlxM_to_ZXM(Flx_halfgcd(x, y, pp)); } else { if (!signe(x)) { long v = varn(x); retmkmat2(mkcol2(pol_0(v),pol_1(v)), mkcol2(pol_1(v),pol_0(v))); } if (degpol(y)1) pari_warn(warnmem,"FpX_gcd (d = %ld)",degpol(b)); gerepileall(av0,2, &a,&b); } av = avma; c = FpX_rem(a,b,p); a=b; b=c; } avma = av; return a; } GEN FpX_gcd(GEN x, GEN y, GEN p) { pari_sp av = avma; if (lgefint(p)==3) { ulong pp; (void)new_chunk((lg(x) + lg(y)) << 2); /* scratch space */ pp = to_Flx(&x, &y, p); x = Flx_gcd(x, y, pp); avma = av; return Flx_to_ZX(x); } x = FpX_red(x, p); y = FpX_red(y, p); if (!signe(x)) return gerepileupto(av, y); while (lg(y)>FpX_GCD_LIMIT) { GEN c; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FpX_rem(x, y, p); x = y; y = r; } c = FpXM_FpX_mul2(FpX_halfgcd(x,y, p), x, y, p); x = gel(c,1); y = gel(c,2); gerepileall(av,2,&x,&y); } return gerepileupto(av, FpX_gcd_basecase(x,y,p)); } /*Return 1 if gcd can be computed * else return a factor of p*/ GEN FpX_gcd_check(GEN x, GEN y, GEN p) { GEN a,b,c; pari_sp av=avma; a = FpX_red(x, p); b = FpX_red(y, p); while (signe(b)) { GEN lead = leading_term(b); GEN g = gcdii(lead,p); if (!equali1(g)) return gerepileuptoint(av,g); c = FpX_rem(a,b,p); a=b; b=c; } avma = av; return gen_1; } static GEN FpX_extgcd_basecase(GEN a, GEN b, GEN p, GEN *ptu, GEN *ptv) { pari_sp av=avma, lim = stack_lim(av,2); GEN u,v,d,d1,v1; long vx = varn(a); d = a; d1 = b; v = pol_0(vx); v1 = pol_1(vx); while (signe(d1)) { GEN r, q = FpX_divrem(d,d1,p, &r); 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 (DEBUGMEM>1) pari_warn(warnmem,"FpX_extgcd (d = %ld)",degpol(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = FpX_div(FpX_sub(d,FpX_mul(b,v,p),p),a,p); *ptv = v; return d; } static GEN FpX_extgcd_halfgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN u,v,R = matid2_FpXM(varn(x)); while (lg(y)>FpX_EXTGCD_LIMIT) { GEN M, c; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = FpX_divrem(x, y, p, &r); x = y; y = r; R = FpX_FpXM_qmul(q, R, p); } M = FpX_halfgcd(x,y, p); c = FpXM_FpX_mul2(M, x,y, p); R = FpXM_mul2(M, R, p); x = gel(c,1); y = gel(c,2); gerepileall(av,3,&x,&y,&R); } y = FpX_extgcd_basecase(x,y,p,&u,&v); if (ptu) *ptu = FpX_addmulmul(u,v,gcoeff(R,1,1),gcoeff(R,2,1),p); *ptv = FpX_addmulmul(u,v,gcoeff(R,1,2),gcoeff(R,2,2),p); return y; } /* x and y in Z[X], return lift(gcd(x mod p, y mod p)). Set u and v st * ux + vy = gcd (mod p) */ GEN FpX_extgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv) { GEN d; pari_sp ltop=avma; if (lgefint(p)==3) { ulong pp = to_Flx(&x, &y, p); d = Flx_extgcd(x,y, pp, ptu,ptv); d = Flx_to_ZX(d); if (ptu) *ptu=Flx_to_ZX(*ptu); *ptv=Flx_to_ZX(*ptv); } else { x = FpX_red(x, p); y = FpX_red(y, p); if (lg(y)>FpX_EXTGCD_LIMIT) d = FpX_extgcd_halfgcd(x, y, p, ptu, ptv); else d = FpX_extgcd_basecase(x, y, p, ptu, ptv); } gerepileall(ltop,ptu?3:2,&d,ptv,ptu); return d; } GEN FpX_rescale(GEN P, GEN h, GEN p) { long i, l = lg(P); GEN Q = cgetg(l,t_POL), hi = h; Q[l-1] = P[l-1]; for (i=l-2; i>=2; i--) { gel(Q,i) = Fp_mul(gel(P,i), hi, p); if (i == 2) break; hi = Fp_mul(hi,h, p); } Q[1] = P[1]; return Q; } GEN FpX_deriv(GEN x, GEN p) { return FpX_red(ZX_deriv(x), p); } int FpX_is_squarefree(GEN f, GEN p) { pari_sp av = avma; GEN z = FpX_gcd(f,FpX_deriv(f,p),p); avma = av; return degpol(z)==0; } GEN random_FpX(long d1, long v, GEN p) { long i, d = d1+2; GEN y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v); for (i=2; i=2; i=j-1) { for (j=i; !signe(gel(x,j)); j--) if (j==2) { if (i!=j) y = Fp_powu(y,i-j+1,p); p1=mulii(p1,y); goto fppoleval;/*sorry break(2) no implemented*/ } r = (i==j)? y: Fp_powu(y,i-j+1,p); p1 = Fp_addmul(gel(x,j), p1, r, p); if ((i & 7) == 0) { affii(p1, res); p1 = res; avma = av; } } fppoleval: modiiz(p1,p,res); avma = av; return res; } /* Tz=Tx*Ty where Tx and Ty coprime * return lift(chinese(Mod(x*Mod(1,p),Tx*Mod(1,p)),Mod(y*Mod(1,p),Ty*Mod(1,p)))) * if Tz is NULL it is computed * As we do not return it, and the caller will frequently need it, * it must compute it and pass it. */ GEN FpX_chinese_coprime(GEN x,GEN y,GEN Tx,GEN Ty,GEN Tz,GEN p) { pari_sp av = avma; GEN ax,p1; ax = FpX_mul(FpXQ_inv(Tx,Ty,p), Tx,p); p1 = FpX_mul(ax, FpX_sub(y,x,p),p); p1 = FpX_add(x,p1,p); if (!Tz) Tz=FpX_mul(Tx,Ty,p); p1 = FpX_rem(p1,Tz,p); return gerepileupto(av,p1); } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ GEN FpX_resultant(GEN a, GEN b, GEN p) { long da,db,dc; pari_sp av, lim; GEN c,lb, res = gen_1; if (!signe(a) || !signe(b)) return gen_0; da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); 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); while (db) { lb = gel(b,db+2); c = FpX_rem(a,b, p); a = b; b = c; dc = degpol(c); if (dc < 0) { avma = av; return NULL; } 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 (DEBUGMEM>1) pari_warn(warnmem,"FpX_resultant (da = %ld)",da); gerepileall(av,3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } res = Fp_mul(res, Fp_powu(gel(b,2), da, p), p); return gerepileuptoint(av, res); } GEN FpX_disc(GEN x, GEN p) { pari_sp av = avma; GEN L, D = FpX_resultant(x, FpX_deriv(x,p), p); if (!D || !signe(D)) return gen_0; L = leading_term(x); if (!equali1(L)) D = Fp_div(D,L,p); if (degpol(x) & 2) D = Fp_neg(D,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) { return divide_conquer_assoc(V, (void *)p, &_FpX_mul); } GEN FpV_roots_to_pol(GEN V, GEN p, long v) { pari_sp ltop=avma; long i; GEN g=cgetg(lg(V),t_VEC); for(i=1;i 1; i--) { gel(y,i) = Fp_mul(u, gel(y,i-1), p); u = Fp_mul(u, gel(x,i), p); /* u = 1 / (x[1] ... x[i-1]) */ } gel(y,1) = u; return y; } GEN FqV_inv(GEN x, GEN T, GEN p) { long i, lx = lg(x); GEN u, y = cgetg(lx, t_VEC); gel(y,1) = gel(x,1); for (i=2; i 1; i--) { gel(y,i) = Fq_mul(u, gel(y,i-1), T,p); u = Fq_mul(u, gel(x,i), T,p); /* u = 1 / (x[1] ... x[i-1]) */ } gel(y,1) = u; return y; } /***********************************************************************/ /** **/ /** Barrett reduction **/ /** **/ /***********************************************************************/ static GEN FpX_invBarrett_basecase(GEN T, GEN p) { long i, l=lg(T)-1, lr = l-1, k; GEN r=cgetg(lr, t_POL); r[1]=T[1]; gel(r,2) = gen_1; for (i=3; i=0; i--) if (signe(gel(x,i))) break; return i+1; } INLINE GEN FpX_recipspec(GEN x, long l, long n) { return RgX_recipspec_shallow(x, l, n); } static GEN FpX_invBarrett_Newton(GEN T, GEN p) { pari_sp av = avma; long nold, lx, lz, lq, l = degpol(T), i, lQ; GEN q, y, z, x = cgetg(l+2, t_POL) + 2; ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1) gel(q,1) = Fp_red(gel(q,1), p); if (lQ>1 && signe(gel(q,1))) { GEN u = gel(q, 1); if (!equali1(gel(x,0))) u = Fp_mul(u, Fp_sqr(gel(x,0), p), p); gel(x,1) = Fp_neg(u, p); lx = 2; } else lx = 1; nold = 1; for (; mask > 1; ) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = ZX_lgrenormalizespec(q, minss(lQ,lnew)); z = FpX_mulspec(x, q, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (signe(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = ZX_lgrenormalizespec (z+i, lz-i); z = FpX_mulspec(x, z+i, p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = ZX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Fp_neg(gel(z,i), p); } x -= 2; setlg(x, lx + 2); x[1] = T[1]; return gerepilecopy(av, x); } /* 1/polrecip(T)+O(x^(deg(T)-1)) */ GEN FpX_invBarrett(GEN T, GEN p) { pari_sp ltop = avma; long l = lg(T); GEN r; if (l<5) return pol_0(varn(T)); if (l<=FpX_INVBARRETT_LIMIT) { GEN c = gel(T,l-1), ci=gen_1; if (!equali1(c)) { ci = Fp_inv(c, p); T = FpX_Fp_mul(T, ci, p); r = FpX_invBarrett_basecase(T, p); r = FpX_Fp_mul(r, ci, p); } else r = FpX_invBarrett_basecase(T, p); } else r = FpX_invBarrett_Newton(T, p); return gerepileupto(ltop, r); } GEN FpX_get_red(GEN T, GEN p) { if (typ(T)==t_POL && lg(T)>FpX_BARRETT_LIMIT) retmkvec2(FpX_invBarrett(T,p),T); return T; } /* Compute x mod T where 2 <= degpol(T) <= l+1 <= 2*(degpol(T)-1) * and mg is the Barrett inverse of T. */ static GEN FpX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN T, GEN p, GEN *pr) { GEN q, r; long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = ZX_lgrenormalizespec(T+2,lt); lmg = ZX_lgrenormalizespec(mg+2,lm); q = FpX_recipspec(x+lt,ld,ld); /* q = rec(x) lq<=ld*/ q = FpX_mulspec(q+2,mg+2,p,lgpol(q),lmg); /* q = rec(x) * mg lq<=ld+lm*/ q = FpX_recipspec(q+2,minss(ld,lgpol(q)),ld);/* q = rec (rec(x) * mg) lq<=ld*/ if (!pr) return q; r = FpX_mulspec(q+2,T+2,p,lgpol(q),lT); /* r = q*pol lr<=ld+lt*/ r = FpX_subspec(x,r+2,p,lt,minss(lt,lgpol(r)));/* r = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN FpX_divrem_Barrett_noGC(GEN x, GEN mg, GEN T, GEN p, GEN *pr) { GEN q = NULL, r = FpX_red(x, p); long l = lgpol(r), lt = degpol(T), lm = 2*lt-1; long i; if (l <= lt) { if (pr == ONLY_REM) return r; if (pr == ONLY_DIVIDES) return signe(x)? NULL: pol_0(varn(x)); if (pr) *pr = r; return pol_0(varn(T)); } if (lt <= 1) return FpX_divrem_basecase(r,T,p,pr); if (pr != ONLY_REM && l>lm) { q = cgetg(l-lt+2, t_POL); for (i=0;ilm) { GEN zr, zq = FpX_divrem_Barrettspec(r+2+l-lm,lm,mg,T,p,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) { GEN zq = FpX_divrem_Barrettspec(r+2,l,mg,T,p,&r); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i lt) r = FpX_divrem_Barrettspec(r+2, l, mg, T, p, ONLY_REM); else r = FpX_renormalize(r, l+2); r[1] = x[1]; return FpX_renormalize(r, lg(r)); } if (pr) { r[1] = x[1]; r = FpX_renormalize(r, lg(r)); } q[1] = x[1]; q = FpX_renormalize(q, lg(q)); if (pr == ONLY_DIVIDES) return signe(r)? NULL: q; if (pr) *pr = r; return q; } GEN FpX_divrem(GEN x, GEN T, GEN p, GEN *pr) { GEN B, y = get_FpX_red(T, &B); long dy = degpol(y), dx = degpol(x), d = dx-dy; if (pr==ONLY_REM) return FpX_rem(x, y, p); if (!B && d+3 < FpX_DIVREM_BARRETT_LIMIT) return FpX_divrem_basecase(x,y,p,pr); else if (lgefint(p)==3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); GEN z = Flx_divrem(x, T, pp, pr); if (!z) return NULL; if (!pr || pr == ONLY_DIVIDES) return Flx_to_ZX_inplace(gerepileuptoleaf(av, z)); z = Flx_to_ZX(z); *pr = Flx_to_ZX(*pr); gerepileall(av, 2, &z, pr); return z; } else { pari_sp av=avma; GEN mg = B? B: FpX_invBarrett(y, p); GEN q1 = FpX_divrem_Barrett_noGC(x,mg,y,p,pr); if (!q1) {avma=av; return NULL;} if (!pr || pr==ONLY_DIVIDES) return gerepilecopy(av, q1); gerepileall(av,2,&q1,pr); return q1; } } GEN FpX_rem(GEN x, GEN T, GEN p) { GEN B, y = get_FpX_red(T, &B); long dy = degpol(y), dx = degpol(x), d = dx-dy; if (d < 0) return FpX_red(x,p); if (!B && d+3 < FpX_REM_BARRETT_LIMIT) return FpX_divrem_basecase(x,y,p,ONLY_REM); else if (lgefint(p)==3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); return Flx_to_ZX_inplace(gerepileuptoleaf(av, Flx_rem(x, T, pp))); } else { pari_sp av = avma; GEN mg = B? B: FpX_invBarrett(y, p); return gerepileupto(av, FpX_divrem_Barrett_noGC(x, mg, y, p, ONLY_REM)); } } /***********************************************************************/ /** **/ /** FpXQ **/ /** **/ /***********************************************************************/ /* FpXQ are elements of Fp[X]/(T), represented by FpX*/ GEN FpXQ_red(GEN x, GEN T, GEN p) { GEN z = FpX_red(x,p); return FpX_rem(z, T,p); } GEN FpXQ_mul(GEN x,GEN y,GEN T,GEN p) { GEN z = FpX_mul(x,y,p); return FpX_rem(z, T, p); } GEN FpXQ_sqr(GEN x, GEN T, GEN p) { GEN z = FpX_sqr(x,p); return FpX_rem(z, T, p); } /* Inverse of x in Z/pZ[X]/(pol) or NULL if inverse doesn't exist * return lift(1 / (x mod (p,pol))) */ GEN FpXQ_invsafe(GEN x, GEN y, GEN p) { GEN V, z = FpX_extgcd(get_FpX_mod(y), x, p, NULL, &V); if (degpol(z)) return NULL; z = Fp_invsafe(gel(z,2), p); if (!z) return NULL; return FpX_Fp_mul(V, z, p); } GEN FpXQ_inv(GEN x,GEN T,GEN p) { pari_sp av = avma; GEN U = FpXQ_invsafe(x, T, p); if (!U) pari_err_INV("FpXQ_inv",x); return gerepileupto(av, U); } GEN FpXQ_div(GEN x,GEN y,GEN T,GEN p) { pari_sp av = avma; return gerepileupto(av, FpXQ_mul(x,FpXQ_inv(y,T,p),T,p)); } struct _FpXQ { GEN T, p, mg, aut; }; static GEN _FpXQ_add(void *data, GEN x, GEN y) { (void) data; return ZX_add(x, y); } static GEN _FpXQ_cmul(void *data, GEN P, long a, GEN x) { (void) data; return ZX_Z_mul(x, gel(P,a+2)); } static GEN _FpXQ_sqr(void *data, GEN x) { struct _FpXQ *D = (struct _FpXQ*)data; return FpXQ_sqr(x, D->T, D->p); } static GEN _FpXQ_mul(void *data, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)data; return FpXQ_mul(x,y, D->T, D->p); } static GEN _FpXQ_zero(void *data) { struct _FpXQ *D = (struct _FpXQ*)data; return pol_0(get_FpX_var(D->T)); } static GEN _FpXQ_one(void *data) { struct _FpXQ *D = (struct _FpXQ*)data; return pol_1(get_FpX_var(D->T)); } static GEN _FpXQ_red(void *data, GEN x) { struct _FpXQ *D = (struct _FpXQ*)data; return FpX_red(x,D->p); } static struct bb_algebra FpXQ_algebra = { _FpXQ_red,_FpXQ_add,_FpXQ_mul,_FpXQ_sqr,_FpXQ_one,_FpXQ_zero }; /* x,pol in Z[X], p in Z, n in Z, compute lift(x^n mod (p, pol)) */ GEN FpXQ_pow(GEN x, GEN n, GEN T, GEN p) { struct _FpXQ D; pari_sp av; long s = signe(n); GEN y; if (!s) return pol_1(varn(x)); if (is_pm1(n)) /* +/- 1 */ return (s < 0)? FpXQ_inv(x,T,p): FpXQ_red(x,T,p); av = avma; if (!is_bigint(p)) { ulong pp = to_Flxq(&x, &T, p); y = Flxq_pow(x, n, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, y)); } if (s < 0) x = FpXQ_inv(x,T,p); D.p = p; D.T = FpX_get_red(T,p); y = gen_pow(x, n, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul); return gerepileupto(av, y); } GEN /*Assume n is very small*/ FpXQ_powu(GEN x, ulong n, GEN T, GEN p) { struct _FpXQ D; pari_sp av; GEN y; if (!n) return pol_1(varn(x)); if (n==1) return FpXQ_red(x,T,p); av = avma; if (!is_bigint(p)) { ulong pp = to_Flxq(&x, &T, p); y = Flxq_powu(x, n, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, y)); } D.T = FpX_get_red(T, p); D.p = p; y = gen_powu(x, n, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul); return gerepileupto(av, y); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN FpXQ_powers(GEN x, long l, GEN T, GEN p) { struct _FpXQ D; int use_sqr; if (l>2 && lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); GEN z = FlxV_to_ZXV(Flxq_powers(x, l, T, pp)); return gerepileupto(av, z); } use_sqr = (degpol(x)<<1)>=get_FpX_degree(T); D.T = FpX_get_red(T,p); D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul,&_FpXQ_one); } GEN FpXQ_matrix_pow(GEN y, long n, long m, GEN P, GEN l) { return RgXV_to_RgM(FpXQ_powers(y,m-1,P,l),n); } GEN FpX_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p) { struct _FpXQ D; D.T = FpX_get_red(T,p); D.p = p; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&D,&FpXQ_algebra,_FpXQ_cmul); } GEN FpX_FpXQ_eval(GEN Q, GEN x, GEN T, GEN p) { struct _FpXQ D; int use_sqr; if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); GEN z = Flx_Flxq_eval(ZX_to_Flx(Q, pp), x, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, z)); } use_sqr = (degpol(x)<<1) >= get_FpX_degree(T); D.T = FpX_get_red(T,p); D.p = p; return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&D,&FpXQ_algebra,_FpXQ_cmul); } GEN FpXQ_autpowers(GEN aut, long f, GEN T, GEN p) { pari_sp av = avma; long n = get_FpX_degree(T); long i, nautpow = brent_kung_optpow(n-1,f-2,1); long v = get_FpX_var(T); GEN autpow, V; T = FpX_get_red(T, p); autpow = FpXQ_powers(aut, nautpow,T,p); V = cgetg(f + 2, t_VEC); gel(V,1) = pol_x(v); if (f==0) return gerepileupto(av, V); gel(V,2) = gcopy(aut); for (i = 3; i <= f+1; i++) gel(V,i) = FpX_FpXQV_eval(gel(V,i-1),autpow,T,p); return gerepileupto(av, V); } static GEN FpXQ_autpow_sqr(void *E, GEN x) { struct _FpXQ *D = (struct _FpXQ*)E; return FpX_FpXQ_eval(x, x, D->T, D->p); } static GEN FpXQ_autpow_mul(void *E, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)E; return FpX_FpXQ_eval(x, y, D->T, D->p); } GEN FpXQ_autpow(GEN x, ulong n, GEN T, GEN p) { struct _FpXQ D; D.T = FpX_get_red(T, p); D.p = p; if (n==0) return pol_x(varn(x)); if (n==1) return ZX_copy(x); return gen_powu(x,n,(void*)&D,FpXQ_autpow_sqr,FpXQ_autpow_mul); } static GEN FpXQ_autsum_mul(void *E, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)E; 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); return mkvec2(phi3, a3); } static GEN FpXQ_autsum_sqr(void *E, GEN x) { return FpXQ_autsum_mul(E, x, x); } GEN FpXQ_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,FpXQ_autsum_sqr,FpXQ_autsum_mul); } static long bounded_order(GEN p, GEN b, long k) { long i; GEN a=modii(p,b); for(i=1;i 1) z = gel(FpXQ_autsum(mkvec2(autk, z), m, T, p), 2); if (!is_pm1(u)) z = FpXQ_pow(z, u, T, p); if (signe(v)) z = FpXQ_mul(z, FpXQ_pow(x, v, T, p), T, p); } return gerepileupto(av,signe(n)>0 ? z : FpXQ_inv(z,T,p)); } /* assume T irreducible mod p */ int FpXQ_issquare(GEN x, GEN T, GEN p) { pari_sp av; long res; 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; avma = av; return res; } int Fp_issquare(GEN x, GEN p) { if (equalui(2, p)) return 1; return kronecker(x, p) == 1; } /* assume T irreducible mod p */ int Fq_issquare(GEN x, GEN T, GEN p) { if (typ(x) != t_INT) return FpXQ_issquare(x, T, 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 2 */ ordp = subis(p, 1); /* even */ ord = dlog_get_ord(o); if (!ord) ord = T? subis(powiu(p, get_FpX_degree(T)), 1): ordp; if (equalii(a, ordp)) /* -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 = FpXQ_pow(g,q,T,p); } g = constant_term(g); } n_q = Fp_log(a,g,op,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 _FpXQ_pow(void *data, GEN x, GEN n) { struct _FpXQ *D = (struct _FpXQ*)data; return FpXQ_pow_Frobenius(x,n, D->aut, D->T, D->p); } static GEN _FpXQ_rand(void *data) { pari_sp av=avma; struct _FpXQ *D = (struct _FpXQ*)data; GEN z; do { avma=av; z=random_FpX(get_FpX_degree(D->T),get_FpX_var(D->T),D->p); } while (!signe(z)); return z; } static GEN _FpXQ_easylog(void *E, GEN a, GEN g, GEN ord) { struct _FpXQ *s=(struct _FpXQ*) E; if (degpol(a)) return NULL; return Fp_FpXQ_log(constant_term(a),g,ord,s->T,s->p); } 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) { 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 = (void*)e; return &FpXQ_star; } GEN FpXQ_order(GEN a, GEN ord, GEN T, GEN p) { if (lgefint(p)==3) { pari_sp av=avma; ulong pp = to_Flxq(&a, &T, p); GEN z = Flxq_order(a, ord, T, pp); return gerepileuptoint(av,z); } else { void *E; const struct bb_group *S = get_FpXQ_star(&E,T,p); return gen_order(a,ord,E,S); } } GEN FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p) { 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); } 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); } } GEN FpXQ_sqrtn(GEN a, GEN n, GEN T, GEN p, GEN *zeta) { pari_sp av = avma; GEN z; if (!signe(a)) { long v=varn(a); if (signe(n) < 0) pari_err_INV("FpXQ_sqrtn",a); if (zeta) *zeta=pol_1(v); return pol_0(v); } if (lgefint(p)==3) { ulong pp = to_Flxq(&a, &T, p); z = Flxq_sqrtn(a, n, T, pp, zeta); if (!z) return NULL; if (!zeta) return Flx_to_ZX_inplace(gerepileuptoleaf(av, z)); z = Flx_to_ZX(z); *zeta=Flx_to_ZX(*zeta); } else { void *E; const struct bb_group *S = get_FpXQ_star(&E,T,p); GEN o = addis(powiu(p,get_FpX_degree(T)),-1); z = gen_Shanks_sqrtn(a,n,o,zeta,E,S); if (!z) return NULL; if (!zeta) return gerepileupto(av, z); } gerepileall(av, 2, &z,zeta); return z; } GEN FpXQ_sqrt(GEN a, GEN T, GEN p) { return FpXQ_sqrtn(a, gen_2, T, p, NULL); } GEN FpXQ_norm(GEN x, GEN TB, GEN p) { pari_sp av = avma; GEN T = get_FpX_mod(TB); GEN y = FpX_resultant(T, x, p); GEN L = leading_term(T); if (gequal1(L) || signe(x)==0) return y; return gerepileupto(av, Fp_div(y, Fp_pows(L, degpol(x), p), p)); } GEN FpXQ_trace(GEN x, GEN TB, GEN p) { pari_sp av = avma; GEN T = get_FpX_mod(TB); GEN dT = FpX_deriv(T,p); long n = degpol(dT); GEN z = FpXQ_mul(x, dT, TB, p); if (degpol(z) 1 && !is_gener_Fp(t, p, p_1, Lp)) continue; t = FpXQ_pow(g, shifti(p_1,-1), T, p); } for (i = 1; i < l; i++) { GEN a = FpXQ_pow_Frobenius(t, gel(Lq,i), F, T, p); if (!degpol(a) && equalii(gel(a,2), p_1)) break; } if (i == l) return g; } } GEN gener_FpXQ(GEN T, GEN p, GEN *po) { long i, j, f = get_FpX_degree(T); GEN g, Lp, Lq, p_1, q_1, N, o; pari_sp av = avma; p_1 = subiu(p,1); if (f == 1) { GEN Lp, fa; o = p_1; fa = Z_factor(o); Lp = gel(fa,1); Lp = vecslice(Lp, 2, lg(Lp)-1); /* remove 2 for efficiency */ g = cgetg(3, t_POL); g[1] = evalsigne(1) | evalvarn(get_FpX_var(T)); gel(g,2) = pgener_Fp_local(p, Lp); if (po) *po = mkvec2(o, fa); return g; } if (lgefint(p) == 3) { ulong pp = to_Flxq(NULL, &T, p); g = gener_Flxq(T, pp, po); if (!po) return Flx_to_ZX_inplace(gerepileuptoleaf(av, g)); g = Flx_to_ZX(g); gel(*po,2) = Flx_to_ZX(gel(*po,2)); gerepileall(av, 2, &g, po); return g; } /* p now odd */ q_1 = subiu(powiu(p,f), 1); N = diviiexact(q_1, p_1); Lp = odd_prime_divisors(p_1); for (i=lg(Lp)-1; i; i--) gel(Lp,i) = diviiexact(p_1, gel(Lp,i)); o = factor_pn_1(p,f); Lq = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(Lq); i++) { if (remii(p_1, gel(Lq,i)) == gen_0) continue; gel(Lq,j++) = diviiexact(N, gel(Lq,i)); } setlg(Lq, j); g = gener_FpXQ_i(get_FpX_mod(T), p, p_1, Lp, Lq); if (!po) g = gerepilecopy(av, g); else { *po = mkvec2(q_1, o); gerepileall(av, 2, &g, po); } return g; } #if 0 /* generic version: slower */ GEN gener_FpXQ2(GEN T, GEN p, GEN *po) { pari_sp av = avma; void *E; long f = get_FpX_degree(T); GEN g, o = factor_pn_1(p,f); const struct bb_group *S = get_FpXQ_star(&E,T,p); g = gen_gener(o,E,S); if (!po) g = gerepilecopy(av, g); else { *po = mkvec2(powiu(p,f), o); gerepileall(av, 2, &g, po); } return g; } #endif GEN gener_FpXQ_local(GEN T, GEN p, GEN L) { GEN Lp, Lq, p_1 = subiu(p,1), q_1, N, Q; long f, i, ip, iq, l = lg(L); T = get_FpX_mod(T); f = degpol(T); q_1 = subiu(powiu(p,f), 1); N = diviiexact(q_1, p_1); Q = is_pm1(p_1)? gen_1: shifti(p_1,-1); Lp = cgetg(l, t_VEC); ip = 1; Lq = cgetg(l, t_VEC); iq = 1; for (i=1; i < l; i++) { GEN a, b, ell = gel(L,i); if (equaliu(ell,2)) continue; a = dvmdii(Q, ell, &b); if (b == gen_0) gel(Lp,ip++) = a; else gel(Lq,iq++) = diviiexact(N,ell); } setlg(Lp, ip); setlg(Lq, iq); return gener_FpXQ_i(T, p, p_1, Lp, Lq); } pari-2.7.5/src/basemath/base3.c0000644000175000017500000017341312413013142014622 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* BASIC NF OPERATIONS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* OPERATIONS OVER NUMBER FIELD ELEMENTS. */ /* represented as column vectors over the integral basis */ /* */ /*******************************************************************/ static GEN get_tab(GEN nf, long *N) { GEN tab = (typ(nf) == t_MAT)? nf: gel(nf,9); *N = nbrows(tab); return tab; } /* x != 0, y t_INT. Return x * y (not memory clean if x = 1) */ static GEN _mulii(GEN x, GEN y) { return is_pm1(x)? (signe(x) < 0)? negi(y): y : mulii(x, y); } GEN tablemul_ei_ej(GEN M, long i, long j) { long N; GEN tab = get_tab(M, &N); tab += (i-1)*N; return gel(tab,j); } /* Outputs x.ei, where ei is the i-th elt of the algebra basis. * x an RgV of correct length and arbitrary content (polynomials, scalars...). * M is the multiplication table ei ej = sum_k M_k^(i,j) ek */ GEN tablemul_ei(GEN M, GEN x, long i) { long j, k, N; GEN v, tab; if (i==1) return gcopy(x); tab = get_tab(M, &N); if (typ(x) != t_COL) { v = zerocol(N); gel(v,i) = gcopy(x); return v; } tab += (i-1)*N; v = cgetg(N+1,t_COL); /* wi . x = [ sum_j tab[k,j] x[j] ]_k */ for (k=1; k<=N; k++) { pari_sp av = avma; GEN s = gen_0; for (j=1; j<=N; j++) { GEN c = gcoeff(tab,k,j); if (!gequal0(c)) s = gadd(s, gmul(c, gel(x,j))); } gel(v,k) = gerepileupto(av,s); } return v; } /* as tablemul_ei, assume x a ZV of correct length */ GEN zk_ei_mul(GEN nf, GEN x, long i) { long j, k, N; GEN v, tab; if (i==1) return ZC_copy(x); tab = get_tab(nf, &N); tab += (i-1)*N; v = cgetg(N+1,t_COL); for (k=1; k<=N; k++) { pari_sp av = avma; GEN s = gen_0; for (j=1; j<=N; j++) { GEN c = gcoeff(tab,k,j); if (signe(c)) s = addii(s, _mulii(c, gel(x,j))); } gel(v,k) = gerepileuptoint(av, s); } return v; } /* table of multiplication by wi in R[w1,..., wN] */ GEN ei_multable(GEN TAB, long i) { long k,N; GEN m, tab = get_tab(TAB, &N); tab += (i-1)*N; m = cgetg(N+1,t_MAT); for (k=1; k<=N; k++) gel(m,k) = gel(tab,k); return m; } GEN zk_multable(GEN nf, GEN x) { long i, l = lg(x); GEN mul = cgetg(l,t_MAT); gel(mul,1) = x; /* assume w_1 = 1 */ for (i=2; i 0? leafcopy(v): RgC_neg(v); } l = lg(v); y = cgetg(l, t_COL); for (i=1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_COL) c = gmul(c, x); else c = RgC_Rg_mul(c, x); gel(y,i) = c; } } else { x = Q_remove_denom(x, &dx); x = zk_multable(nf, x); l = lg(v); y = cgetg(l, t_COL); for (i=1; i < l; i++) { GEN c = gel(v,i); if (typ(c)!=t_COL) { if (!isintzero(c)) c = RgC_Rg_mul(gel(x,1), c); } else { c = RgM_RgC_mul(x,c); if (QV_isscalar(c)) c = gel(c,1); } gel(y,i) = c; } } return dx? RgC_Rg_div(y, dx): y; } static GEN mulbytab(GEN M, GEN c) { return typ(c) == t_COL? RgM_RgC_mul(M,c): RgC_Rg_mul(gel(M,1), c); } GEN tablemulvec(GEN M, GEN x, GEN v) { long l, i; GEN y; if (typ(x) == t_COL && RgV_isscalar(x)) { x = gel(x,1); return typ(v) == t_POL? RgX_Rg_mul(v,x): RgV_Rg_mul(v,x); } x = multable(M, x); /* multiplication table by x */ y = cgetg_copy(v, &l); if (typ(v) == t_POL) { y[1] = v[1]; for (i=2; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i)); y = normalizepol(y); } else { for (i=1; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i)); } return y; } /* inverse of x in nf */ GEN nfinv(GEN nf, GEN x) { pari_sp av = avma; GEN T, z; nf = checknf(nf); T = nf_get_pol(nf); x = nf_to_scalar_or_alg(nf, x); if (typ(x) == t_POL) z = poltobasis(nf, QXQ_inv(x, T)); else { z = zerocol(degpol(T)); gel(z,1) = ginv(x); } return gerepileupto(av, z); } /* quotient of x and y in nf */ GEN nfdiv(GEN nf, GEN x, GEN y) { pari_sp av = avma; GEN T, z; nf = checknf(nf); T = nf_get_pol(nf); y = nf_to_scalar_or_alg(nf, y); if (typ(y) != t_POL) { x = nf_to_scalar_or_basis(nf, x); if (typ(x) == t_COL) z = RgC_Rg_div(x, y); else { z = zerocol(degpol(T)); gel(z,1) = gdiv(x,y); } } else { x = nf_to_scalar_or_alg(nf, x); z = QXQ_inv(y, T); z = (typ(x) == t_POL)? RgXQ_mul(z, x, T): RgX_Rg_mul(z, x); z = poltobasis(nf, z); } return gerepileupto(av, z); } /* product of INTEGERS (t_INT or ZC) x and y in nf * compute xy as ( sum_i x_i sum_j y_j m^{i,j}_k )_k */ GEN nfmuli(GEN nf, GEN x, GEN y) { long i, j, k, N; GEN s, v, TAB = get_tab(nf, &N); if (typ(x) == t_INT) { if (typ(y) == t_INT) return scalarcol(mulii(x,y), N); return ZC_Z_mul(y, x); } if (typ(y) == t_INT) return ZC_Z_mul(x, y); /* both x and y are ZV */ v = cgetg(N+1,t_COL); for (k=1; k<=N; k++) { pari_sp av = avma; GEN TABi = TAB; if (k == 1) s = mulii(gel(x,1),gel(y,1)); else s = addii(mulii(gel(x,1),gel(y,k)), mulii(gel(x,k),gel(y,1))); for (i=2; i<=N; i++) { GEN t, xi = gel(x,i); TABi += N; if (!signe(xi)) continue; t = NULL; for (j=2; j<=N; j++) { GEN p1, c = gcoeff(TABi, k, j); /* m^{i,j}_k */ if (!signe(c)) continue; p1 = _mulii(c, gel(y,j)); t = t? addii(t, p1): p1; } if (t) s = addii(s, mulii(xi, t)); } gel(v,k) = gerepileuptoint(av,s); } return v; } /* square of INTEGER (t_INT or ZC) x in nf */ GEN nfsqri(GEN nf, GEN x) { long i, j, k, N; GEN s, v, TAB = get_tab(nf, &N); if (typ(x) == t_INT) return scalarcol(sqri(x), N); v = cgetg(N+1,t_COL); for (k=1; k<=N; k++) { pari_sp av = avma; GEN TABi = TAB; if (k == 1) s = sqri(gel(x,1)); else s = shifti(mulii(gel(x,1),gel(x,k)), 1); for (i=2; i<=N; i++) { GEN p1, c, t, xi = gel(x,i); TABi += N; if (!signe(xi)) continue; c = gcoeff(TABi, k, i); t = signe(c)? _mulii(c,xi): NULL; for (j=i+1; j<=N; j++) { c = gcoeff(TABi, k, j); if (!signe(c)) continue; p1 = _mulii(c, shifti(gel(x,j),1)); t = t? addii(t, p1): p1; } if (t) s = addii(s, mulii(xi, t)); } gel(v,k) = gerepileuptoint(av,s); } return v; } /* both x and y are RgV */ GEN tablemul(GEN TAB, GEN x, GEN y) { long i, j, k, N; GEN s, v; if (typ(x) != t_COL) return gmul(x, y); if (typ(y) != t_COL) return gmul(y, x); N = lg(x)-1; v = cgetg(N+1,t_COL); for (k=1; k<=N; k++) { pari_sp av = avma; GEN TABi = TAB; if (k == 1) s = gmul(gel(x,1),gel(y,1)); else s = gadd(gmul(gel(x,1),gel(y,k)), gmul(gel(x,k),gel(y,1))); for (i=2; i<=N; i++) { GEN t, xi = gel(x,i); TABi += N; if (gequal0(xi)) continue; t = NULL; for (j=2; j<=N; j++) { GEN p1, c = gcoeff(TABi, k, j); /* m^{i,j}_k */ if (gequal0(c)) continue; p1 = gmul(c, gel(y,j)); t = t? gadd(t, p1): p1; } if (t) s = gadd(s, gmul(xi, t)); } gel(v,k) = gerepileupto(av,s); } return v; } GEN tablesqr(GEN TAB, GEN x) { long i, j, k, N; GEN s, v; if (typ(x) != t_COL) return gsqr(x); N = lg(x)-1; v = cgetg(N+1,t_COL); for (k=1; k<=N; k++) { pari_sp av = avma; GEN TABi = TAB; if (k == 1) s = gsqr(gel(x,1)); else s = gmul2n(gmul(gel(x,1),gel(x,k)), 1); for (i=2; i<=N; i++) { GEN p1, c, t, xi = gel(x,i); TABi += N; if (gequal0(xi)) continue; c = gcoeff(TABi, k, i); t = !gequal0(c)? gmul(c,xi): NULL; for (j=i+1; j<=N; j++) { c = gcoeff(TABi, k, j); if (gequal0(c)) continue; p1 = gmul(gmul2n(c,1), gel(x,j)); t = t? gadd(t, p1): p1; } if (t) s = gadd(s, gmul(xi, t)); } gel(v,k) = gerepileupto(av,s); } return v; } static GEN _mul(void *data, GEN x, GEN y) { return nfmuli((GEN)data,x,y); } static GEN _sqr(void *data, GEN x) { return nfsqri((GEN)data,x); } /* Compute z^n in nf, left-shift binary powering */ GEN nfpow(GEN nf, GEN z, GEN n) { pari_sp av = avma; long s, N; GEN x, cx, T; if (typ(n)!=t_INT) pari_err_TYPE("nfpow",n); nf = checknf(nf); T = nf_get_pol(nf); N = degpol(T); s = signe(n); if (!s) return scalarcol_shallow(gen_1,N); x = nf_to_scalar_or_basis(nf, z); if (typ(x) != t_COL) { GEN y = zerocol(N); gel(y,1) = powgi(x,n); return y; } if (s < 0) { /* simplified nfinv */ x = nf_to_scalar_or_alg(nf, z); x = poltobasis(nf, QXQ_inv(x, T)); n = absi(n); } x = primitive_part(x, &cx); x = gen_pow(x, n, (void*)nf, _sqr, _mul); if (cx) x = RgC_Rg_mul(x, powgi(cx, n)); return av==avma? gcopy(x): gerepileupto(av,x); } /* Compute z^n in nf, left-shift binary powering */ GEN nfpow_u(GEN nf, GEN z, ulong n) { pari_sp av = avma; long N; GEN x, cx, T; nf = checknf(nf); T = nf_get_pol(nf); N = degpol(T); if (!n) return scalarcol_shallow(gen_1,N); x = nf_to_scalar_or_basis(nf, z); if (typ(x) != t_COL) { GEN y = zerocol(N); gel(y,1) = gpowgs(x,n); return y; } x = primitive_part(x, &cx); x = gen_powu(x, n, (void*)nf, _sqr, _mul); if (cx) x = RgC_Rg_mul(x, powgi(cx, utoipos(n))); return av==avma? gcopy(x): gerepileupto(av,x); } typedef struct { GEN nf, p; long I; } eltmod_muldata; static GEN sqr_mod(void *data, GEN x) { eltmod_muldata *D = (eltmod_muldata*)data; return FpC_red(nfsqri(D->nf, x), D->p); } static GEN ei_msqr_mod(void *data, GEN x) { GEN x2 = sqr_mod(data, x); eltmod_muldata *D = (eltmod_muldata*)data; return FpC_red(zk_ei_mul(D->nf, x2, D->I), D->p); } /* x = I-th vector of the Z-basis of Z_K, in Z^n, compute lift(x^n mod p) */ GEN pow_ei_mod_p(GEN nf, long I, GEN n, GEN p) { pari_sp av = avma; eltmod_muldata D; long s,N; GEN y; if (typ(n) != t_INT) pari_err_TYPE("nfpow",n); nf = checknf(nf); N = nf_get_degree(nf); s = signe(n); if (s < 0) pari_err_IMPL("negative power in pow_ei_mod_p"); if (!s || I == 1) return scalarcol_shallow(gen_1,N); D.nf = nf; D.p = p; D.I = I; y = gen_pow_fold(col_ei(N, I), n, (void*)&D, &sqr_mod, &ei_msqr_mod); return gerepileupto(av,y); } /* valuation of integral x (ZV), with resp. to prime ideal pr */ long 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)); 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); for(v=0;; v++) { for (i=1; i n) return 1; /* room for only one such pr */ return ZV_equal(pr_get_gen(P), gQ) || ZC_prdvd(nf, gQ, P); } long nfval(GEN nf, GEN x, GEN pr) { pari_sp av = avma; long w, e; GEN cx, p; if (gequal0(x)) return LONG_MAX; nf = checknf(nf); checkprid(pr); p = pr_get_p(pr); e = pr_get_e(pr); x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) return e*Q_pval(x,p); x = Q_primitive_part(x, &cx); w = ZC_nfval(nf,x,pr); if (cx) w += e*Q_pval(cx,p); avma = av; return w; } /* want to write p^v = uniformizer^(e*v) * z^v, z coprime to pr */ /* z := tau^e / p^(e-1), algebraic integer coprime to pr; return z^v */ static GEN powp(GEN nf, GEN pr, long v) { GEN b, z; long e; if (!v) return gen_1; b = pr_get_tau(pr); if (typ(b) == t_INT) return gen_1; e = pr_get_e(pr); z = gel(b,1); if (e != 1) z = gdiv(nfpow_u(nf, z, e), powiu(pr_get_p(pr),e-1)); return nfpow_u(nf, z, v); } long nfvalrem(GEN nf, GEN x, GEN pr, GEN *py) { pari_sp av = avma; long w, e; GEN cx, p, t; if (!py) return nfval(nf,x,pr); if (gequal0(x)) { *py = gcopy(x); return LONG_MAX; } nf = checknf(nf); checkprid(pr); p = pr_get_p(pr); e = pr_get_e(pr); x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) { w = Q_pvalrem(x,p, py); if (!w) { *py = gerepilecopy(av, x); return 0; } *py = gerepileupto(av, gmul(powp(nf, pr, w), *py)); return e*w; } x = Q_primitive_part(x, &cx); w = ZC_nfvalrem(nf,x,pr, py); if (cx) { long v = Q_pvalrem(cx,p, &t); *py = nfmul(nf, *py, gmul(powp(nf,pr,v), t)); *py = gerepileupto(av, *py); w += e*v; } else *py = gerepilecopy(av, *py); return w; } GEN coltoalg(GEN nf, GEN x) { return mkpolmod( coltoliftalg(nf, x), nf_get_pol(nf) ); } GEN basistoalg(GEN nf, GEN x) { GEN z, T; nf = checknf(nf); switch(typ(x)) { case t_COL: { pari_sp av = avma; return gerepilecopy(av, coltoalg(nf, x)); } case t_POLMOD: T = nf_get_pol(nf); if (!RgX_equal_var(T,gel(x,1))) pari_err_MODULUS("basistoalg", T,gel(x,1)); return gcopy(x); case t_POL: T = nf_get_pol(nf); if (varn(T) != varn(x)) pari_err_VAR("basistoalg",x,T); z = cgetg(3,t_POLMOD); gel(z,1) = ZX_copy(T); gel(z,2) = RgX_rem(x, T); return z; case t_INT: case t_FRAC: T = nf_get_pol(nf); z = cgetg(3,t_POLMOD); gel(z,1) = ZX_copy(T); gel(z,2) = gcopy(x); return z; default: pari_err_TYPE("basistoalg",x); return NULL; /* not reached */ } } /* Assume nf is a genuine nf. */ GEN nf_to_scalar_or_basis(GEN nf, GEN x) { switch(typ(x)) { case t_INT: case t_FRAC: return x; case t_POLMOD: x = checknfelt_mod(nf,x,"nf_to_scalar_or_basis"); if (typ(x) != t_POL) return x; /* fall through */ case t_POL: { GEN T = nf_get_pol(nf); long l = lg(x); if (varn(x) != varn(T)) pari_err_VAR("nf_to_scalar_or_basis", x,T); if (l >= lg(T)) { x = RgX_rem(x, T); l = lg(x); } if (l == 2) return gen_0; if (l == 3) return gel(x,2); return poltobasis(nf,x); } case t_COL: if (lg(x) != lg(nf_get_zk(nf))) break; return QV_isscalar(x)? gel(x,1): x; } pari_err_TYPE("nf_to_scalar_or_basis",x); return NULL; /* not reached */ } /* Let x be a polynomial with coefficients in Q or nf. Return the same * polynomial with coefficients expressed as vectors (on the integral basis). * No consistency checks, not memory-clean. */ GEN RgX_to_nfX(GEN nf, GEN x) { long i, l; GEN y = cgetg_copy(x, &l); y[1] = x[1]; for (i=2; i= lg(T)) { x = RgX_rem(x, T); l = lg(x); } if (l == 2) return gen_0; if (l == 3) return gel(x,2); return x; } case t_COL: if (lg(x) != lg(nf_get_zk(nf))) break; return QV_isscalar(x)? gel(x,1): coltoliftalg(nf, x); } pari_err_TYPE("nf_to_scalar_or_alg",x); return NULL; /* not reached */ } /* gmul(A, RgX_to_Rg(x)), A t_MAT (or t_VEC) of compatible dimensions */ GEN mulmat_pol(GEN A, GEN x) { long i,l; GEN z; if (typ(x) != t_POL) return gmul(x,gel(A,1)); /* scalar */ l=lg(x)-1; if (l == 1) return typ(A)==t_VEC? gen_0: zerocol(nbrows(A)); x++; z = gmul(gel(x,1), gel(A,1)); for (i=2; i= degpol(P)) x = RgX_rem(x,P); return mulmat_pol(nf_get_invzk(nf), x); } GEN algtobasis(GEN nf, GEN x) { pari_sp av; nf = checknf(nf); switch(typ(x)) { case t_POLMOD: if (!RgX_equal_var(nf_get_pol(nf),gel(x,1))) pari_err_MODULUS("algtobasis", nf_get_pol(nf),gel(x,1)); x = gel(x,2); switch(typ(x)) { case t_INT: case t_FRAC: return scalarcol(x, nf_get_degree(nf)); case t_POL: av = avma; return gerepileupto(av,poltobasis(nf,x)); } break; case t_POL: av = avma; return gerepileupto(av,poltobasis(nf,x)); case t_COL: if (lg(x)-1 != nf_get_degree(nf)) pari_err_DIM("nfalgtobasis"); return gcopy(x); case t_INT: case t_FRAC: return scalarcol(x, nf_get_degree(nf)); } pari_err_TYPE("algtobasis",x); return NULL; /* not reached */ } GEN rnfbasistoalg(GEN rnf,GEN x) { const char *f = "rnfbasistoalg"; long lx, i; pari_sp av = avma; GEN z, nf, relpol, T; checkrnf(rnf); nf = rnf_get_nf(rnf); T = nf_get_pol(nf); relpol = QXQX_to_mod_shallow(rnf_get_pol(rnf), T); switch(typ(x)) { case t_COL: z = cgetg_copy(x, &lx); for (i=1; i= degpol(relpol)) x = RgX_rem(x,relpol); return gerepileupto(av, mulmat_pol(rnf_get_invzk(rnf), x)); } return gerepileupto(av, scalarcol(x, rnf_get_degree(rnf))); } /* Given a and b in nf, gives an algebraic integer y in nf such that a-b.y * is "small" */ GEN nfdiveuc(GEN nf, GEN a, GEN b) { pari_sp av = avma; a = nfdiv(nf,a,b); return gerepileupto(av, ground(a)); } /* Given a and b in nf, gives a "small" algebraic integer r in nf * of the form a-b.y */ GEN nfmod(GEN nf, GEN a, GEN b) { pari_sp av = avma; GEN p1 = gneg_i(nfmul(nf,b,ground(nfdiv(nf,a,b)))); return gerepileupto(av, nfadd(nf,a,p1)); } /* Given a and b in nf, gives a two-component vector [y,r] in nf such * that r=a-b.y is "small". */ GEN nfdivrem(GEN nf, GEN a, GEN b) { pari_sp av = avma; GEN p1,z, y = ground(nfdiv(nf,a,b)); p1 = gneg_i(nfmul(nf,b,y)); z = cgetg(3,t_VEC); gel(z,1) = gcopy(y); gel(z,2) = nfadd(nf,a,p1); return gerepileupto(av, z); } /*************************************************************************/ /** **/ /** (Z_K/I)^* **/ /** **/ /*************************************************************************/ /* return sign(sigma_k(x)), x t_COL (integral, primitive) */ static long 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))); if (realprec(z) < DEFAULTPREC) pari_err_PREC("nfsign_arch"); return signe(z); } GEN vec01_to_indices(GEN v) { long i, k, l; GEN p; switch (typ(v)) { case t_VECSMALL: return v; case t_VEC: break; default: pari_err_TYPE("vec01_to_indices",v); } l = lg(v); p = new_chunk(l) + l; for (k=1, i=l-1; i; i--) if (signe(gel(v,i))) { *--p = i; k++; } *--p = evallg(k) | evaltyp(t_VECSMALL); avma = (pari_sp)p; return p; } GEN indices_to_vec01(GEN p, long r) { long i, l = lg(p); GEN v = zerovec(r); for (i = 1; i < l; i++) gel(v, p[i]) = gen_1; return v; } /* return (column) vector of R1 signatures of x (0 or 1) */ GEN nfsign_arch(GEN nf, GEN x, GEN arch) { GEN M, V, archp = vec01_to_indices(arch); long i, s, n = lg(archp)-1; pari_sp av; if (!n) return cgetg(1,t_VECSMALL); nf = checknf(nf); if (typ(x) == t_MAT) { /* factorisation */ GEN g = gel(x,1), e = gel(x,2); V = zero_zv(n); for (i=1; i 10)? shifti(EX,-1): NULL; if (is_pm1(idZ)) lx = 1; /* id = Z_K */ for (i=1; i 0) plus = elt_mulpow_modideal(nf, plus, h, n, id); else /* sn < 0 */ minus = elt_mulpow_modideal(nf, minus, h, absi(n), id); if (low_stack(lim, stack_lim(av, 2))) { if(DEBUGMEM>1) pari_warn(warnmem,"famat_to_nf_modideal_coprime"); if (!plus) plus = gen_0; if (!minus) minus = gen_0; gerepileall(av,2, &plus, &minus); if (isintzero(plus)) plus = NULL; if (isintzero(minus)) minus = NULL; } } if (minus) plus = nfmulmodideal(nf, plus, nfinvmodideal(nf,minus,id), id); return plus? plus: scalarcol_shallow(gen_1, lg(id)-1); } /* given 2 integral ideals x, y in HNF s.t x | y | x^2, compute the quotient (1+x)/(1+y) in the form [[cyc],[gen]], if U != NULL, set *U := ux^-1 */ static GEN zidealij(GEN x, GEN y, GEN *U) { GEN G, cyc; long j, N; /* x^(-1) y = relations between the 1 + x_i (HNF) */ cyc = ZM_snf_group(hnf_solve(x, y), U, &G); N = lg(cyc); G = ZM_mul(x,G); settyp(G, t_VEC); /* new generators */ for (j=1; j3) err_printf("treating pr^%ld, pr = %Ps\n",e,pr); if (f == 1) g = pgener_Fp(p); else { GEN T, modpr = zk_to_Fq_init(nf, &pr, &T, &p); g = Fq_to_nf(gener_FpXQ(T,p,NULL), modpr); g = poltobasis(nf, g); } /* g generates (Z_K / pr)^* */ prb = idealhnf_two(nf,pr); pre = (e==1)? prb: idealpow(nf,pr,ep); if (x) { GEN mv; v = idealaddtoone_i(nf,idealdivpowprime(nf,x,pr,ep), pre); mv = zk_scalar_or_multable(nf, v); u = typ(mv) == t_INT? subui(1,mv): unnf_minus_x(v); v = mv; g0 = makeprimetoideal(x,u,mv,g); } else { u = v = NULL; /* gcc -Wall */ g0 = g; } y = mkvec5(mkvec(subiu(powiu(p,f), 1)), mkvec(g), mkvec(g0), mkvec(nfsign_arch(nf,g0,arch)), gen_1); if (e == 1) return gerepilecopy(av, mkvec(y)); list = vectrunc_init(e+1); vectrunc_append(list, y); mask = quadratic_prec_mask(e); a = 1; while (mask > 1) { GEN pra = prb, gen, z, s, U; long i, l, b = a << 1; if (mask & 1) b--; mask >>= 1; /* compute 1 + pr^a / 1 + pr^b, 2a <= b */ if(DEBUGLEVEL>3) err_printf(" treating a = %ld, b = %ld\n",a,b); prb = (b >= e)? pre: idealpows(nf,pr,b); z = zidealij(pra, prb, &U); gen = leafcopy(gel(z,2)); s = cgetg_copy(gen, &l); for (i = 1; i < l; i++) { if (x) gel(gen,i) = makeprimetoideal(x,u,v,gel(gen,i)); gel(s,i) = nfsign_arch(nf,gel(gen,i),arch); } y = mkvec5(gel(z,1), gel(z,2), gen, s, U); vectrunc_append(list, y); a = b; } return gerepilecopy(av, list); } /* increment y, which runs through [-d,d]^k. Return 0 when done. */ static int increment(GEN y, long k, long d) { long i = 0, j; do { if (++i > k) return 0; y[i]++; } while (y[i] > d); for (j = 1; j < i; j++) y[j] = -d; return 1; } GEN archstar_full_rk(GEN x, GEN bas, GEN v, GEN gen) { long i, r, lgmat, N = lg(bas)-1, nba = nbrows(v); GEN lambda = cgetg(N+1, t_VECSMALL), mat = cgetg(nba+1,t_MAT); lgmat = lg(v); setlg(mat, lgmat+1); for (i = 1; i < lgmat; i++) gel(mat,i) = gel(v,i); for ( ; i <= nba; i++) gel(mat,i) = cgetg(nba+1, t_VECSMALL); if (x) { x = ZM_lll(x, 0.75, LLL_INPLACE); bas = RgV_RgM_mul(bas, x); } for (r=1;; r++) { /* reset */ (void)vec_setconst(lambda, (GEN)0); if (!x) lambda[1] = r; while (increment(lambda, N, r)) { pari_sp av1 = avma; GEN a = RgM_zc_mul(bas, lambda), c = gel(mat,lgmat); for (i = 1; i <= nba; i++) { GEN t = x? gadd(gel(a,i), gen_1): gel(a,i); c[i] = (gsigne(t) < 0)? 1: 0; } avma = av1; if (Flm_deplin(mat, 2)) continue; /* c independent of previous sign vectors */ if (!x) a = zc_to_ZC(lambda); else { a = ZM_zc_mul(x, lambda); gel(a,1) = addis(gel(a,1), 1); } gel(gen,lgmat) = a; if (lgmat++ == nba) { mat = Flm_inv(mat,2); /* full rank */ settyp(mat, t_VEC); return mat; } setlg(mat,lgmat+1); } } } /* x non-0 integral ideal in HNF, compute elements in 1+x (in x, if x = zk) * whose sign matrix is invertible. archp in 'indices' format */ GEN nfarchstar(GEN nf, GEN x, GEN archp) { long nba = lg(archp) - 1; GEN cyc, gen, mat; if (!nba) cyc = gen = mat = cgetg(1, t_VEC); else { GEN xZ = gcoeff(x,1,1), gZ; pari_sp av = avma; if (is_pm1(xZ)) x = NULL; /* x = O_K */ gZ = x? subsi(1, xZ): gen_m1; /* gZ << 0, gZ = 1 mod x */ if (nba == 1) { gen = mkvec(gZ); mat = mkvec( mkvecsmall(1) ); } else { GEN bas = nf_get_M(nf); if (lgcols(bas) > lg(archp)) bas = rowpermute(bas, archp); gen = cgetg(nba+1,t_VEC); gel(gen,1) = gZ; mat = archstar_full_rk(x, bas, mkmat(const_vecsmall(nba,1)), gen); gerepileall(av,2,&gen,&mat); } cyc = const_vec(nba, gen_2); } return mkvec3(cyc,gen,mat); } static GEN apply_U(GEN U, GEN a) { GEN e; if (typ(a) == t_INT) e = RgC_Rg_mul(gel(U,1), subis(a, 1)); else { /* t_COL */ GEN t = gel(a,1); gel(a,1) = addsi(-1, gel(a,1)); /* a -= 1 */ e = RgM_RgC_mul(U, a); gel(a,1) = t; /* restore */ } return e; } /* a in Z_K (t_COL or t_INT), pr prime ideal, prk = pr^k, * list = zprimestar(nf, pr, k, ...) */ static GEN zlog_pk(GEN nf, GEN a, GEN y, GEN pr, GEN prk, GEN list, GEN *psigne) { long i,j, llist = lg(list)-1; for (j = 1; j <= llist; j++) { GEN L = gel(list,j), e; GEN cyc = gel(L,1), gen = gel(L,2), s = gel(L,4), U = gel(L,5); if (j == 1) e = mkcol( nf_log(nf, a, gel(gen,1), gel(cyc,1), pr) ); else e = apply_U(U, a); /* here lg(e) == lg(cyc) */ for (i = 1; i < lg(cyc); i++) { GEN t; if (typ(gel(e,i)) != t_INT) pari_err_COPRIME("zlog_pk", a, pr); t = modii(negi(gel(e,i)), gel(cyc,i)); gel(++y,0) = negi(t); if (!signe(t)) continue; if (mod2(t)) Flv_add_inplace(*psigne, gel(s,i), 2); if (j != llist) a = elt_mulpow_modideal(nf, a, gel(gen,i), t, prk); } } return y; } static void zlog_add_sign(GEN y0, GEN sgn, GEN lists) { GEN y, s; long i; if (!sgn) return; y = y0 + lg(y0); s = Flm_Flc_mul(gmael(lists, lg(lists)-1, 3), sgn, 2); for (i = lg(s)-1; i > 0; i--) gel(--y,0) = s[i]? gen_1: gen_0; } static GEN famat_zlog(GEN nf, GEN fa, GEN sgn, GEN bid) { GEN g = gel(fa,1), e = gel(fa,2); GEN vp = gmael(bid, 3,1), ep = gmael(bid, 3,2); GEN arch = bid_get_arch(bid); GEN cyc = bid_get_cyc(bid), lists = gel(bid,4), U = gel(bid,5); GEN y0, x, y, EX = gel(cyc,1); long i, l; y0 = y = cgetg(lg(U), t_COL); if (!sgn) sgn = nfsign_arch(nf, mkmat2(g,e), arch); l = lg(vp); for (i=1; i < l; i++) { GEN pr = gel(vp,i), prk, ex; if (l == 2) { prk = bid_get_ideal(bid); ex = EX; } else { /* try to improve EX: should be group exponent mod prf, not f */ GEN k = gel(ep,i); prk = idealpow(nf, pr, k); /* upper bound: gcd(EX, (Nv-1)p^(k-1)) = (Nv-1) p^min(k-1,v_p(EX)) */ ex = subis(pr_norm(pr),1); if (!is_pm1(k)) { GEN p = pr_get_p(pr), k_1 = subis(k,1); long v = Z_pval(EX, p); if (cmpui(v, k_1) > 0) v = itos(k_1); if (v) ex = mulii(ex, powiu(p, v)); } } x = famat_makecoprime(nf, g, e, pr, prk, ex); y = zlog_pk(nf, x, y, pr, prk, gel(lists,i), &sgn); } zlog_add_sign(y0, sgn, lists); return y0; } static GEN get_index(GEN lists) { long t = 0, j, k, l = lg(lists)-1; GEN L, ind = cgetg(l+1, t_VECSMALL); for (k = 1; k < l; k++) { L = gel(lists,k); ind[k] = t; for (j=1; jn = n; S->U = U; S->P = P; S->e = e; S->archp = vec01_to_indices(arch); S->lists = lists; S->ind = get_index(lists); } void init_zlog_bid(zlog_S *S, GEN bid) { GEN fa = gel(bid,3), lists = gel(bid,4), U = gel(bid,5); GEN arch = gel(bid_get_mod(bid), 2); init_zlog(S, lg(U)-1, gel(fa,1), gel(fa,2), arch, lists, U); } /* Return decomposition of a on the S->n successive generators contained in * S->lists. If index !=0, do the computation for the corresponding prime * ideal and set to 0 the other components. */ static GEN zlog_ind(GEN nf, GEN a, zlog_S *S, GEN sgn, long index) { GEN y0 = zerocol(S->n), y; pari_sp av = avma; long k, kmin, kmax; a = nf_to_scalar_or_basis(nf,a); if (index) { kmin = kmax = index; y = y0 + S->ind[index]; } else { kmin = 1; kmax = lg(S->P)-1; y = y0; } if (!sgn) sgn = nfsign_arch(nf, a, S->archp); for (k = kmin; k <= kmax; k++) { GEN list= gel(S->lists,k); GEN pr = gel(S->P,k); GEN prk = idealpow(nf, pr, gel(S->e,k)); y = zlog_pk(nf, a, y, pr, prk, list, &sgn); } zlog_add_sign(y0, sgn, S->lists); return gerepilecopy(av, y0); } /* sgn = sign(a, S->arch) or NULL if unknown */ GEN zlog(GEN nf, GEN a, GEN sgn, zlog_S *S) { return zlog_ind(nf, a, S, sgn, 0); } /* Log on bid.gen of generators of P_{1,I pr^{e-1}} / P_{1,I pr^e} (I,pr) = 1, * defined implicitly via CRT. 'index' is the index of pr in modulus * factorization */ GEN log_gen_pr(zlog_S *S, long index, GEN nf, long e) { long i, l, yind = S->ind[index]; GEN y, A, L, L2 = gel(S->lists,index); if (e == 1) { L = gel(L2,1); y = col_ei(S->n, yind+1); zlog_add_sign(y, gmael(L,4,1), S->lists); retmkmat( ZM_ZC_mul(S->U, y) ); } else { GEN prk, g, pr = gel(S->P,index); long narchp = lg(S->archp)-1; if (e == 2) L = gel(L2,2); else L = zidealij(idealpows(nf,pr,e-1), idealpows(nf,pr,e), NULL); g = gel(L,2); l = lg(g); A = cgetg(l, t_MAT); prk = idealpow(nf, pr, gel(S->e,index)); for (i = 1; i < l; i++) { GEN G = gel(g,i), sgn = zero_zv(narchp); /*positive at f_oo*/ y = zerocol(S->n); (void)zlog_pk(nf, G, y + yind, pr, prk, L2, &sgn); zlog_add_sign(y, sgn, S->lists); gel(A,i) = y; } return ZM_mul(S->U, A); } } /* Log on bid.gen of generator of P_{1,f} / P_{1,f v[index]} * v = vector of r1 real places */ GEN log_gen_arch(zlog_S *S, long index) { GEN y = zerocol(S->n); zlog_add_sign(y, vecsmall_ei(lg(S->archp)-1, index), S->lists); return ZM_ZC_mul(S->U, y); } /* add [h,cyc] or [h,cyc,gen] to bid */ static void add_grp(GEN nf, GEN u1, GEN cyc, GEN gen, GEN bid) { GEN h = ZV_prod(cyc); if (u1) { GEN G = mkvec3(h,cyc,NULL/*dummy, bid[2] needed below*/); gel(bid,2) = G; if (u1 != gen_1) { long i, c = lg(u1); GEN g = cgetg(c,t_VEC); for (i=1; i 1) { GEN pra = prb, z, U; long b = a << 1; if (mask & 1) b--; mask >>= 1; /* compute 1 + pr^a / 1 + pr^b, 2a <= b */ if(DEBUGLEVEL>3) err_printf(" treating a = %ld, b = %ld\n",a,b); prb = (b >= e)? pre: idealpows(nf,pr,b); z = zidealij(pra, prb, &U); y = mkvec3(gel(z,1), gel(z,2), U); vectrunc_append(list, y); a = b; } return gerepilecopy(av, list); } static GEN log_prk(GEN nf, GEN a, long nbgen, GEN list, GEN prk) { GEN y = zerocol(nbgen); long i,j, iy = 1, llist = lg(list)-1; for (j = 1; j <= llist; j++) { GEN L = gel(list,j); GEN cyc = gel(L,1), gen = gel(L,2), U = gel(L,3); GEN e = apply_U(U, a); /* here lg(e) == lg(cyc) */ for (i = 1; i < lg(cyc); i++) { GEN t = modii(negi(gel(e,i)), gel(cyc,i)); gel(y, iy++) = negi(t); if (!signe(t)) continue; if (j != llist) a = elt_mulpow_modideal(nf, a, gel(gen,i), t, prk); } } return y; } /* multiplicative group (1 + pr) / (1 + pr^e) */ GEN idealprincipalunits(GEN nf, GEN pr, long e) { pari_sp av = avma; long c, i, j, k, nbgen; GEN cyc, u1 = NULL, pre, gen; GEN g, EX, h, L2; long cp = 0; nf = checknf(nf); pre = idealpows(nf, pr, e); L2 = principal_units(nf, pr, e); c = lg(L2); gen = cgetg(c, t_VEC); for (j = 1; j < c; j++) gel(gen, j) = gmael(L2,j,2); gen = shallowconcat1(gen); nbgen = lg(gen)-1; h = cgetg(nbgen+1,t_MAT); for (j=1; j < lg(L2); j++) { GEN L = gel(L2,j), F = gel(L,1), G = gel(L,2); for (k=1; k3 && lg(G2)>3)? gen_1: NULL; nbgen = l1+l2-2; cyc = ZM_snf_group(diagonal_shallow(shallowconcat(cyc1,cyc2)), &U, gen? &u1: NULL); if (nbgen) { GEN U1 = gel(bid1,5), U2 = gel(bid2,5); U1 = l1 == 1? zeromat(nbgen,lg(U1)-1): ZM_mul(vecslice(U, 1, l1-1), U1); U2 = l2 == 1? zeromat(nbgen,lg(U2)-1): ZM_mul(vecslice(U, l1, nbgen), U2); U = shallowconcat(U1, U2); } else U = zeromat(0, lx-2); if (gen) { GEN mu,mv, u,v = idealaddtoone_i(nf,I2,I1); mv = zk_scalar_or_multable(nf, v); if (typ(mv) == t_INT) { mu = u = subui(1,mv); v = mv; } else { u = unnf_minus_x(v); mu = RgM_Rg_add(ZM_neg(mv), gen_1); /* mult by u = 1-v */ } gen = shallowconcat(makeprimetoidealvec(x,u,mv, abgrp_get_gen(G1)), makeprimetoidealvec(x,v,mu, abgrp_get_gen(G2))); } y = cgetg(6,t_VEC); gel(y,1) = mkvec2(x, bid_get_arch(bid1)); gel(y,3) = fa; gel(y,4) = lists; gel(y,5) = U; add_grp(nf, u1, cyc, gen, y); return gerepilecopy(av,y); } typedef struct _ideal_data { GEN nf, emb, L, pr, prL, arch, sgnU; } ideal_data; /* z <- ( z | f(v[i])_{i=1..#v} ) */ static void concat_join(GEN *pz, GEN v, GEN (*f)(ideal_data*,GEN), ideal_data *data) { long i, nz, lv = lg(v); GEN z, Z; if (lv == 1) return; z = *pz; nz = lg(z)-1; *pz = Z = cgetg(lv + nz, typ(z)); for (i = 1; i <=nz; i++) gel(Z,i) = gel(z,i); Z += nz; for (i = 1; i < lv; i++) gel(Z,i) = f(data, gel(v,i)); } static GEN join_idealinit(ideal_data *D, GEN x) { return join_bid(D->nf, x, D->prL); } static GEN join_ideal(ideal_data *D, GEN x) { return idealmulpowprime(D->nf, x, D->pr, D->L); } static GEN join_unit(ideal_data *D, GEN x) { return mkvec2(join_idealinit(D, gel(x,1)), vconcat(gel(x,2), D->emb)); } /* compute matrix of zlogs of units */ GEN zlog_units(GEN nf, GEN U, GEN sgnU, GEN bid) { long j, l = lg(U); 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); return m; } /* compute matrix of zlogs of units, assuming S.archp = [] */ GEN zlog_units_noarch(GEN nf, GEN U, GEN bid) { long j, l = lg(U); GEN m = cgetg(l, t_MAT), empty = cgetg(1, t_COL); zlog_S S; init_zlog_bid(&S, bid); for (j = 1; j < l; j++) gel(m,j) = zlog(nf, gel(U,j), empty, &S); return m; } /* calcule la matrice des zlog des unites */ static GEN zlog_unitsarch(GEN sgnU, GEN bid) { GEN lists = gel(bid,4), arch = gmael(bid,1,2); GEN listslast = gel(lists,lg(lists)-1); GEN m = rowpermute(sgnU, vec01_to_indices(arch)); return Flm_mul(gel(listslast,3), m, 2); } /* flag & nf_GEN : generators, otherwise no * flag &2 : units, otherwise no * flag &4 : ideals in HNF, otherwise bid */ static GEN 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; long i, j, l; GEN nf, z, p, fa, id, U, empty = cgetg(1,t_VEC); forprime_t S; ideal_data ID; GEN (*join_z)(ideal_data*, GEN) = do_units? &join_unit : (big_id? &join_idealinit: &join_ideal); nf = checknf(bnf); if ((long)bound <= 0) return empty; id = matid(nf_get_degree(nf)); if (big_id) id = Idealstar(nf,id, istar_flag); /* z[i] will contain all "objects" of norm i. Depending on flag, this means * 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 */ z = cgetg(bound+1,t_VEC); if (do_units) { U = init_units(bnf); gel(z,1) = mkvec( mkvec2(id, zlog_units_noarch(nf, U, id)) ); } else { U = NULL; /* -Wall */ gel(z,1) = mkvec(id); } for (i=2; i<=(long)bound; i++) gel(z,i) = empty; ID.nf = nf; p = cgetipos(3); u_forprime_init(&S, 2, bound); av = avma; lim = stack_lim(av,1); while ((p[2] = u_forprime_next(&S))) { if (DEBUGLEVEL>1) { err_printf("%ld ",p[2]); err_flush(); } fa = idealprimedec(nf, p); for (j=1; j bound) break; z2 = leafcopy(z); q = Q; ID.pr = ID.prL = pr; for (l=1; Q <= bound; l++, Q *= q) /* add pr^l */ { ulong iQ; ID.L = utoipos(l); if (big_id) { if (l > 1) ID.prL = idealpow(nf,pr,ID.L); ID.prL = Idealstar(nf,ID.prL, istar_flag); if (do_units) ID.emb = zlog_units_noarch(nf, U, ID.prL); } for (iQ = Q,i = 1; iQ <= bound; iQ += Q,i++) concat_join(&gel(z,iQ), gel(z2,i), join_z, &ID); } } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"Ideallist"); z = gerepilecopy(av, z); } } if (do_units) for (i = 1; i < lg(z); i++) { GEN s = gel(z,i); long l = lg(s); for (j = 1; j < l; j++) { GEN v = gel(s,j), bid = gel(v,1); gel(v,2) = ZM_mul(gel(bid,5), gel(v,2)); } } return gerepilecopy(av0, z); } GEN ideallist0(GEN bnf,long bound, long flag) { if (flag<0 || flag>4) pari_err_FLAG("ideallist"); return Ideallist(bnf,bound,flag); } GEN ideallist(GEN bnf,long bound) { return Ideallist(bnf,bound,4); } /* bid1 = for module m1 (without arch. part), arch = archimedean part. * Output: bid [[m1,arch],[h,[cyc],[gen]],idealfact,[liste],U] for m1.arch */ static GEN join_bid_arch(GEN nf, GEN bid1, GEN arch) { pari_sp av = avma; GEN f1, G1, fa1, U; GEN lists, cyc, y, u1 = NULL, x, sarch, gen; checkbid(bid1); f1 = gel(bid1,1); G1 = gel(bid1,2); fa1 = gel(bid1,3); x = gel(f1,1); sarch = nfarchstar(nf, x, arch); lists = leafcopy(gel(bid1,4)); gel(lists,lg(lists)-1) = sarch; gen = (lg(G1)>3)? gen_1: NULL; cyc = diagonal_shallow(shallowconcat(gel(G1,2), gel(sarch,1))); cyc = ZM_snf_group(cyc, &U, gen? &u1: NULL); if (gen) gen = shallowconcat(gel(G1,3), gel(sarch,2)); y = cgetg(6,t_VEC); gel(y,1) = mkvec2(x, arch); gel(y,3) = fa1; gel(y,4) = lists; gel(y,5) = U; add_grp(nf, u1, cyc, gen, y); return gerepilecopy(av,y); } static GEN join_arch(ideal_data *D, GEN x) { return join_bid_arch(D->nf, x, D->arch); } static GEN join_archunit(ideal_data *D, GEN x) { GEN bid = join_arch(D, gel(x,1)), U = gel(x,2); U = ZM_mul(gel(bid,5), vconcat(U, zm_to_ZM(zlog_unitsarch(D->sgnU, bid)))); return mkvec2(bid, U); } /* L from ideallist, add archimedean part */ GEN ideallistarch(GEN bnf, GEN L, GEN arch) { pari_sp av; long i, j, l = lg(L), lz; GEN v, z, V; ideal_data ID; GEN (*join_z)(ideal_data*, GEN); if (typ(L) != t_VEC) pari_err_TYPE("ideallistarch",L); if (l == 1) return cgetg(1,t_VEC); z = gel(L,1); if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z); z = gel(z,1); /* either a bid or [bid,U] */ if (lg(z) == 3) { /* the latter: do units */ if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z); ID.sgnU = nfsign_units(bnf, NULL, 1); join_z = &join_archunit; } else join_z = &join_arch; ID.nf = checknf(bnf); ID.arch = vec01_to_indices(arch); av = avma; V = cgetg(l, t_VEC); for (i = 1; i < l; i++) { z = gel(L,i); lz = lg(z); gel(V,i) = v = cgetg(lz,t_VEC); for (j=1; j 1 (an alg. integer has denominator dividing dn, when expressed on nf.zk */ } nflift_t; typedef struct { nflift_t *L; GEN nf; GEN pol, polbase; /* leading coeff is a t_INT */ GEN fact; GEN pr; GEN Br, bound, ZC, BS_2; } nfcmbf_t; /*******************************************************************/ /* RATIONAL RECONSTRUCTION (use ratlift) */ /*******************************************************************/ /* NOT stack clean. a, b stay on the stack */ static GEN lift_to_frac(GEN t, GEN mod, GEN amax, GEN bmax, GEN denom) { GEN a, b; if (signe(t) < 0) t = addii(t, mod); /* in case t is a centerlift */ if (!Fp_ratlift(t, mod, amax,bmax, &a,&b) || (denom && !dvdii(denom,b)) || !is_pm1(gcdii(a,b))) return NULL; if (is_pm1(b)) { cgiv(b); return a; } return mkfrac(a, b); } /* Compute rational lifting for all the components of M modulo mod. * Assume all Fp_ratlift preconditions are met; we allow centerlifts but in * that case are no longer stack clean. If one component fails, return NULL. * If denom != NULL, check that the denominators divide denom. * * We suppose gcd(mod, denom) = 1, then a and b are coprime; so we can use * mkfrac rather than gdiv */ GEN FpM_ratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom) { pari_sp av = avma; long i, j, h, l = lg(M); GEN a, N = cgetg_copy(M, &l); if (l == 1) return N; h = lgcols(M); for (j = 1; j < l; ++j) { gel(N,j) = cgetg(h, t_COL); for (i = 1; i < h; ++i) { a = lift_to_frac(gcoeff(M,i,j), mod, amax,bmax,denom); if (!a) { avma = av; return NULL; } gcoeff(N,i,j) = a; } } return N; } GEN FpC_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom) { pari_sp ltop = avma; long j, l; GEN a, Q = cgetg_copy(P, &l); for (j = 1; j < l; ++j) { a = lift_to_frac(gel(P,j), mod, amax,bmax,denom); if (!a) { avma = ltop; return NULL; } gel(Q,j) = a; } return Q; } GEN FpX_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom) { pari_sp ltop = avma; long j, l; GEN a, Q = cgetg_copy(P, &l); Q[1] = P[1]; for (j = 2; j < l; ++j) { a = lift_to_frac(gel(P,j), mod, amax,bmax,denom); if (!a) { avma = ltop; return NULL; } gel(Q,j) = a; } return Q; } /*******************************************************************/ /* GCD in K[X], K NUMBER FIELD */ /*******************************************************************/ /* P,Q in Z[X,Y], T in Z[Y] irreducible. compute GCD in Q[Y]/(T)[X]. * * M. Encarnacion "On a modular Algorithm for computing GCDs of polynomials * over number fields" (ISSAC'94). * * We procede as follows * 1:compute the gcd modulo primes discarding bad primes as they are detected. * 2:reconstruct the result via FpM_ratlift, stoping as soon as we get weird * denominators. * 3:if FpM_ratlift succeeds, try the full division. * Suppose accuracy is insufficient to get the result right: FpM_ratlift will * rarely succeed, and even if it does the polynomial we get has sensible * coefficients, so the full division will not be too costly. * * If not NULL, den must a a multiple of the denominator of the gcd, * for example the discriminant of T. * * NOTE: if T is not irreducible, nfgcd may loop forever, esp. if gcd | T */ GEN nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew) { pari_sp btop, st_lim, 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; if (!signe(P)) { if (Pnew) *Pnew = pol_0(vT); return gcopy(Q); } if (!signe(Q)) { if (Pnew) *Pnew = pol_1(vT); return gcopy(P); } /*Compute denominators*/ if (!den) den = ZX_disc(T); lP = leading_term(P); lQ = leading_term(Q); if ( !((typ(lP)==t_INT && is_pm1(lP)) || (typ(lQ)==t_INT && is_pm1(lQ))) ) den = mulii(den, gcdii(ZX_resultant(lP, T), ZX_resultant(lQ, T))); init_modular(&S); btop = avma; st_lim = stack_lim(btop, 1); for(;;) { ulong p = u_forprime_next(&S); if (!p) pari_err_OVERFLOW("nfgcd [ran out of primes]"); /*Discard primes dividing disc(T) or lc(PQ) */ if (!umodiu(den, p)) continue; if (DEBUGLEVEL>5) err_printf("nfgcd: p=%d\n",p); /*Discard primes when modular gcd does not exist*/ if ((R = FlxqX_safegcd(ZXX_to_FlxX(P,p,vT), ZXX_to_FlxX(Q,p,vT), ZX_to_Flx(T,p), p)) == NULL) continue; dR = degpol(R); if (dR == 0) { avma = ltop; if (Pnew) *Pnew = P; return pol_1(vP); } if (mod && dR > dM) continue; /* p divides Res(P/gcd, Q/gcd). Discard. */ 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 (DEBUGMEM>1) pari_warn(warnmem,"nfgcd"); gerepileall(btop, 2, &M, &mod); } (void)ZM_incremental_CRT(&M,R, &mod,p); /* I suspect it must be better to take amax > bmax*/ bo = sqrti(shifti(mod, -1)); if ((sol = FpM_ratlift(M, mod, bo, bo, den)) == NULL) continue; sol = RgM_to_RgXX(sol,vP,vT); dsol = Q_primpart(sol); if (!ZXQX_dvd(Q, dsol, T)) continue; if (Pnew) { *Pnew = RgXQX_pseudodivrem(P, dsol, T, &R); if (signe(R)) continue; } else { if (!ZXQX_dvd(P, dsol, T)) continue; } gerepileall(ltop, Pnew? 2: 1, &dsol, Pnew); return dsol; /* both remainders are 0 */ } } GEN nfgcd(GEN P, GEN Q, GEN T, GEN den) { return nfgcd_all(P,Q,T,den,NULL); } /*******************************************************************/ /* FACTOR OVER (Z_K/pr)[X] --> FqX_factor */ /*******************************************************************/ GEN nffactormod(GEN nf, GEN x, GEN pr) { long j, l, vx = varn(x), vn; pari_sp av = avma; GEN F, E, rep, xrd, modpr, T, p; nf = checknf(nf); vn = nf_get_varn(nf); if (typ(x)!=t_POL) pari_err_TYPE("nffactormod",x); if (varncmp(vx,vn) >= 0) pari_err_PRIORITY("nffactormod", x, ">=", vn); modpr = nf_to_Fq_init(nf, &pr, &T, &p); xrd = nfX_to_FqX(x, nf, modpr); rep = FqX_factor(xrd,T,p); settyp(rep, t_MAT); F = gel(rep,1); l = lg(F); E = gel(rep,2); settyp(E, t_COL); for (j = 1; j < l; j++) { gel(F,j) = FqX_to_nfX(gel(F,j), modpr); gel(E,j) = stoi(E[j]); } return gerepilecopy(av, rep); } /*******************************************************************/ /* MAIN ROUTINES nfroots / nffactor */ /*******************************************************************/ static GEN QXQX_normalize(GEN P, GEN T) { GEN P0 = leading_term(P); long t = typ(P0); if (t == t_POL) { if (degpol(P0)) return RgXQX_RgXQ_mul(P, QXQ_inv(P0,T), T); P0 = gel(P0,2); t = typ(P0); } /* t = t_INT/t_FRAC */ if (t == t_INT && is_pm1(P0) && signe(P0) > 0) return P; /* monic */ return RgX_Rg_div(P, P0); } /* assume leading term of P is an integer */ static GEN RgX_int_normalize(GEN P) { GEN P0 = leading_term(P); /* cater for t_POL */ if (typ(P0) == t_POL) { P0 = gel(P0,2); /* non-0 constant */ P = shallowcopy(P); gel(P,lg(P)-1) = P0; /* now leading term is a t_INT */ } if (typ(P0) != t_INT) pari_err_BUG("RgX_int_normalize"); if (is_pm1(P0)) return signe(P0) > 0? P: RgX_neg(P); return RgX_Rg_div(P, P0); } /* discard change of variable if nf is of the form [nf,c] as return by nfinit * for non-monic polynomials */ static GEN proper_nf(GEN nf) { return (lg(nf) == 3)? gel(nf,1): nf; } static GEN fix_nf(GEN *pnf, GEN *pT, GEN *pA) { GEN den = gen_1; if (!*pnf) { GEN fa, P, q, D, T = *pT; GEN nf, NF = nfinitall(T, nf_PARTIALFACT, DEFAULTPREC); *pnf = nf = proper_nf(NF); if (nf != NF) { /* t_POL defining base field changed (not monic) */ long i, l; GEN A = *pA, a = cgetg_copy(A, &l); GEN rev = gel(NF,2), pow, dpow; *pT = T = nf_get_pol(nf); /* need to update T */ pow = QXQ_powers(lift_intern(rev), degpol(T)-1, T); pow = Q_remove_denom(pow, &dpow); a[1] = A[1]; for (i=2; iprk), t = typ(elt); if (t != t_INT) { if (t == t_POL) elt = mulmat_pol(L->tozk, elt); u = ZM_ZC_mul(L->iprk,elt); for (i=1; iden); } else { u = ZC_Z_mul(gel(L->iprk,1), elt); for (i=1; iden); elt = scalarcol(elt, l-1); } u = ZC_sub(elt, ZM_ZC_mul(L->prk, u)); if (bound && gcmp(RgC_fpnorml2(u,DEFAULTPREC), bound) > 0) u = NULL; return u; } /* Warning: return L->topowden * (best lift). */ static GEN nf_bestlift_to_pol(GEN elt, GEN bound, nflift_t *L) { pari_sp av = avma; GEN u,v = nf_bestlift(elt,bound,L); if (!v) return NULL; if (ZV_isscalar(v)) { if (L->topowden) u = mulii(L->topowden, gel(v,1)); else u = icopy(gel(v,1)); u = gerepileuptoint(av, u); } else { v = gclone(v); avma = av; u = RgV_dotproduct(L->topow, v); gunclone(v); } return u; } /* 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) { long i, l = lg(pol); GEN t, x = cgetg(l,t_POL); x[1] = pol[1]; gel(x,l-1) = mul_content(gel(pol,l-1), T->L->topowden); for (i=l-2; i>1; i--) { t = nf_bestlift_to_pol(gel(pol,i), bound, T->L); if (!t) return NULL; gel(x,i) = t; } return x; } static GEN zerofact(long v) { GEN z = cgetg(3, t_MAT); gel(z,1) = mkcol(pol_0(v)); gel(z,2) = mkcol(gen_1); return z; } /* Return the factorization of A in Q[X]/(T) in rep [pre-allocated with * cgetg(3,t_MAT)], reclaiming all memory between avma and rep. * y is the vector of irreducible factors of B = Q_primpart( A/gcd(A,A') ). * Bad primes divide 'bad' */ static void fact_from_sqff(GEN rep, GEN A, GEN B, GEN y, GEN T, GEN bad) { pari_sp av = (pari_sp)rep; long n = lg(y)-1; GEN ex; if (A != B) { /* not squarefree */ if (n == 1) { /* perfect power, simple ! */ long e = degpol(A) / degpol(gel(y,1)); y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = mkcol(utoipos(e)); } else { /* compute valuations mod a prime of degree 1 (avoid coeff explosion) */ GEN quo, p, r, Bp, lb = leading_term(B), E = cgetalloc(t_VECSMALL,n+1); pari_sp av1 = avma; ulong pp; long j; forprime_t S; u_forprime_init(&S, degpol(T), ULONG_MAX); for (; ; avma = av1) { pp = u_forprime_next(&S); if (! umodiu(bad,pp) || !umodiu(lb, pp)) continue; p = utoipos(pp); r = FpX_oneroot(T, p); if (!r) continue; Bp = FpXY_evalx(B, r, p); if (FpX_is_squarefree(Bp, p)) break; } quo = FpXY_evalx(Q_primpart(A), r, p); for (j=n; j>=2; j--) { GEN junk, fact = Q_remove_denom(gel(y,j), &junk); long e = 0; fact = FpXY_evalx(fact, r, p); for(;; e++) { GEN q = FpX_divrem(quo,fact,p,ONLY_DIVIDES); if (!q) break; quo = q; } E[j] = e; } E[1] = degpol(quo) / degpol(gel(y,1)); y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = zc_to_ZC(E); pari_free((void*)E); } } else { y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = const_col(n, gen_1); } gel(rep,1) = y; settyp(y, t_COL); gel(rep,2) = ex; } /* return the factorization of x in nf */ GEN nffactor(GEN nf,GEN pol) { GEN bad, A, B, y, T, den, rep = cgetg(3, t_MAT); pari_sp av = avma; long dA; pari_timer ti; if (DEBUGLEVEL>2) { timer_start(&ti); err_printf("\nEntering nffactor:\n"); } T = get_nfpol(nf, &nf); RgX_check_ZX(T,"nffactor"); A = RgX_nffix("nffactor",T,pol,1); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return (dA == 0)? trivial_fact(): zerofact(varn(pol)); } A = Q_primpart( QXQX_normalize(A, T) ); if (dA == 1) { GEN c; A = gerepilecopy(av, A); c = gel(A,2); if (typ(c) == t_POL && degpol(c) > 0) gel(A,2) = mkpolmod(c, ZX_copy(T)); gel(rep,1) = mkcol(A); gel(rep,2) = mkcol(gen_1); return rep; } if (degpol(T) == 1) return gerepileupto(av, QX_factor(simplify_shallow(A))); den = get_nfsqff_data(&nf, &T, &A, &B, &bad); if (DEBUGLEVEL>2) timer_printf(&ti, "squarefree test"); if (degpol(B) != dA) B = Q_primpart( QXQX_normalize(B, T) ); ensure_lt_INT(B); y = nfsqff(nf,B, 0, den); if (DEBUGLEVEL>3) err_printf("number of factor(s) found: %ld\n", lg(y)-1); fact_from_sqff(rep, A, B, y, T, bad); return sort_factor_pol(rep, cmp_RgX); } /* assume x scalar or t_COL, G t_MAT */ static GEN arch_for_T2(GEN G, GEN x) { return (typ(x) == t_COL)? RgM_RgC_mul(G,x) : RgC_Rg_mul(gel(G,1),x); } static GEN arch_for_T2_prec(GEN G, GEN x, long prec) { return (typ(x) == t_COL)? RgM_RgC_mul(G, RgC_gtofp(x,prec)) : RgC_Rg_mul(gel(G,1), gtofp(x, prec)); } /* return a bound for T_2(P), P | polbase in C[X] * NB: Mignotte bound: A | S ==> * |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S) * * Apply to sigma(S) for all embeddings sigma, then take the L_2 norm over * sigma, then take the sup over i. **/ static GEN nf_Mignotte_bound(GEN nf, GEN polbase) { GEN G = nf_get_G(nf), lS = leading_term(polbase); /* t_INT */ GEN p1, C, N2, matGS, binlS, bin; long prec, i, j, d = degpol(polbase), n = nf_get_degree(nf), r1 = nf_get_r1(nf); binlS = bin = vecbinome(d-1); if (!isint1(lS)) binlS = ZC_Z_mul(bin,lS); N2 = cgetg(n+1, t_VEC); prec = gprecision(G); for (;;) { nffp_t F; matGS = cgetg(d+2, t_MAT); for (j=0; j<=d; j++) gel(matGS,j+1) = arch_for_T2(G, gel(polbase,j+2)); matGS = shallowtrans(matGS); for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */ { GEN c = sqrtr( RgC_fpnorml2(gel(matGS,j), DEFAULTPREC) ); gel(N2,j) = c; if (!signe(c)) goto PRECPB; } for ( ; j <= n; j+=2) { GEN q1 = RgC_fpnorml2(gel(matGS,j ), DEFAULTPREC); GEN q2 = RgC_fpnorml2(gel(matGS,j+1), DEFAULTPREC); GEN c = sqrtr( gmul2n(addrr(q1, q2), -1) ); gel(N2,j) = gel(N2,j+1) = c; if (!signe(c)) goto PRECPB; } if (j > n) break; /* done */ PRECPB: prec = precdbl(prec); remake_GM(nf, &F, prec); G = F.G; if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } /* Take sup over 0 <= i <= d of * sum_j | binom(d-1, i-1) ||sigma_j(S)||_2 + binom(d-1,i) lc(S) |^2 */ /* i = 0: n lc(S)^2 */ C = mului(n, sqri(lS)); /* i = d: sum_sigma ||sigma(S)||_2^2 */ p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1; for (i = 1; i < d; i++) { GEN B = gel(bin,i), L = gel(binlS,i+1); GEN s = sqrr(addri(mulir(B, gel(N2,1)), L)); /* j=1 */ for (j = 2; j <= n; j++) s = addrr(s, sqrr(addri(mulir(B, gel(N2,j)), L))); if (mpcmp(C, s) < 0) C = s; } return C; } /* return a bound for T_2(P), P | polbase * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2, * where [P]_2 is Bombieri's 2-norm * Sum over conjugates */ static GEN nf_Beauzamy_bound(GEN nf, GEN polbase) { GEN lt, C, s, G = nf_get_G(nf), POL, bin; long d = degpol(polbase), n = nf_get_degree(nf), prec = MEDDEFAULTPREC; bin = vecbinome(d); POL = polbase + 2; /* compute [POL]_2 */ for (;;) { nffp_t F; long i; s = real_0(prec); for (i=0; i<=d; i++) { GEN c = gel(POL,i); if (gequal0(c)) continue; c = gnorml2(arch_for_T2_prec(G, c, prec)); if (!signe(c)) goto PRECPB; /* s += T2(POL[i]) / binomial(d,i) */ s = addrr(s, divri(c, gel(bin,i+1))); } break; PRECPB: prec = precdbl(prec); remake_GM(nf, &F, prec); G = F.G; if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } lt = leading_term(polbase); s = mulri(s, muliu(sqri(lt), n)); C = powruhalf(stor(3,DEFAULTPREC), 3 + 2*d); /* 3^{3/2 + d} */ return divrr(mulrr(C, s), mulur(d, mppi(DEFAULTPREC))); } static GEN nf_factor_bound(GEN nf, GEN polbase) { pari_sp av = avma; GEN a = nf_Mignotte_bound(nf, polbase); GEN b = nf_Beauzamy_bound(nf, polbase); if (DEBUGLEVEL>2) { err_printf("Mignotte bound: %Ps\n",a); err_printf("Beauzamy bound: %Ps\n",b); } return gerepileupto(av, gmin(a, b)); } /* return Bs: if r a root of sigma_i(P), |r| < Bs[i] */ static GEN nf_root_bounds(GEN P, GEN T) { long lR, i, j, l, prec; GEN Ps, R, V, nf; if (RgX_is_rational(P)) return logmax_modulus_bound(P); T = get_nfpol(T, &nf); P = Q_primpart(P); prec = ZXX_max_lg(P) + 1; l = lg(P); if (nf && nf_get_prec(nf) >= prec) R = nf_get_roots(nf); else R = QX_complex_roots(T, prec); lR = lg(R); V = cgetg(lR, t_VEC); Ps = cgetg(l, t_POL); /* sigma (P) */ Ps[1] = P[1]; for (j=1; j sqrt(Btra). * d = dimension of low part (= [nf:Q]) * n0 = bound for |vS|^2 * */ static double get_Bhigh(long n0, long d) { double sqrtd = sqrt((double)d); double z = n0*sqrtd + sqrtd/2 * (d * (n0+1)); z = 1. + 0.5 * z; return z * z; } typedef struct { GEN d; GEN dPinvS; /* d P^(-1) S [ integral ] */ double **PinvSdbl; /* P^(-1) S as double */ GEN S1, P1; /* S = S0 + S1 q, idem P */ } trace_data; /* S1 * u - P1 * round(P^-1 S u). K non-zero coords in u given by ind */ static GEN get_trace(GEN ind, trace_data *T) { long i, j, l, K = lg(ind)-1; GEN z, s, v; s = gel(T->S1, ind[1]); if (K == 1) return s; /* compute s = S1 u */ for (j=2; j<=K; j++) s = ZC_add(s, gel(T->S1, ind[j])); /* compute v := - round(P^1 S u) */ l = lg(s); v = cgetg(l, t_VECSMALL); for (i=1; iPinvSdbl[ ind[j] ][i]; r = floor(t + 0.5); if (fabs(t + 0.5 - r) < 0.0001) { /* dubious, compute exactly */ z = gen_0; for (j=1; j<=K; j++) z = addii(z, ((GEN**)T->dPinvS)[ ind[j] ][i]); v[i] = - itos( diviiround(z, T->d) ); } else v[i] = - (long)r; } return ZC_add(s, ZM_zc_mul(T->P1, v)); } static trace_data * init_trace(trace_data *T, GEN S, nflift_t *L, GEN q) { long e = gexpo(S), i,j, l,h; GEN qgood, S1, invd; if (e < 0) return NULL; /* S = 0 */ qgood = int2n(e - 32); /* single precision check */ if (cmpii(qgood, q) > 0) q = qgood; S1 = gdivround(S, q); if (gequal0(S1)) return NULL; invd = invr(itor(L->den, DEFAULTPREC)); T->dPinvS = ZM_mul(L->iprk, S); l = lg(S); h = lgcols(T->dPinvS); T->PinvSdbl = (double**)cgetg(l, t_MAT); init_dalloc(); for (j = 1; j < l; j++) { double *t = dalloc(h * sizeof(double)); GEN c = gel(T->dPinvS,j); pari_sp av = avma; T->PinvSdbl[j] = t; for (i=1; i < h; i++) t[i] = rtodbl(mulri(invd, gel(c,i))); avma = av; } T->d = L->den; T->P1 = gdivround(L->prk, q); T->S1 = S1; return T; } static void update_trace(trace_data *T, long k, long i) { if (!T) return; gel(T->S1,k) = gel(T->S1,i); gel(T->dPinvS,k) = gel(T->dPinvS,i); T->PinvSdbl[k] = T->PinvSdbl[i]; } /* reduce coeffs mod (T,pk), then center mod pk */ static GEN FqX_centermod(GEN z, GEN T, GEN pk, GEN pks2) { long i, l; GEN y; if (!T) return centermod_i(z, pk, pks2); y = FpXQX_red(z, T, pk); l = lg(y); for (i = 2; i < l; i++) { GEN c = gel(y,i); if (typ(c) == t_INT) c = centermodii(c, pk, pks2); else c = FpX_center(c, pk, pks2); gel(y,i) = c; } return y; } typedef struct { GEN lt, C, Clt, C2lt, C2ltpol; } div_data; static void init_div_data(div_data *D, GEN pol, nflift_t *L) { GEN C = mul_content(L->topowden, L->dn); GEN C2lt, Clt, lc = leading_term(pol), lt = is_pm1(lc)? NULL: absi(lc); if (C) { GEN C2 = sqri(C); if (lt) { C2lt = mulii(C2, lt); Clt = mulii(C,lt); } else { C2lt = C2; Clt = C; } } else C2lt = Clt = lt; D->lt = lt; D->C = C; D->Clt = Clt; D->C2lt = C2lt; D->C2ltpol = C2lt? RgX_Rg_mul(pol, C2lt): pol; } static void update_target(div_data *D, GEN pol) { D->C2ltpol = D->Clt? RgX_Rg_mul(pol, D->Clt): pol; } /* nb = number of modular factors; return a "good" K such that naive * recombination of up to maxK modular factors is not too costly */ long cmbf_maxK(long nb) { if (nb > 10) return 3; return nb-1; } /* Naive recombination of modular factors: combine up to maxK modular * factors, degree <= klim * * target = polynomial we want to factor * famod = array of modular factors. Product should be congruent to * target/lc(target) modulo p^a * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */ /* set *done = 1 if factorisation is known to be complete */ static GEN nfcmbf(nfcmbf_t *T, long klim, long *pmaxK, int *done) { GEN nf = T->nf, famod = T->fact, bound = T->bound; GEN ltdn, nfpol = nf_get_pol(nf); long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1, dnf = degpol(nfpol); pari_sp av0 = avma; GEN Tpk = T->L->Tpk, pk = T->L->pk, pks2 = shifti(pk,-1); GEN ind = cgetg(lfamod+1, t_VECSMALL); GEN deg = cgetg(lfamod+1, t_VECSMALL); GEN degsofar = cgetg(lfamod+1, t_VECSMALL); GEN fa = cgetg(lfamod+1, t_VEC); const double Bhigh = get_Bhigh(lfamod, dnf); trace_data _T1, _T2, *T1, *T2; div_data D; pari_timer ti; timer_start(&ti); *pmaxK = cmbf_maxK(lfamod); init_div_data(&D, T->pol, T->L); ltdn = mul_content(D.lt, T->L->dn); { GEN q = ceil_safe(sqrtr(T->BS_2)); GEN t1,t2, lt2dn = mul_content(ltdn, D.lt); GEN trace1 = cgetg(lfamod+1, t_MAT); GEN trace2 = cgetg(lfamod+1, t_MAT); for (i=1; i <= lfamod; i++) { pari_sp av = avma; GEN P = gel(famod,i); long d = degpol(P); deg[i] = d; P += 2; t1 = gel(P,d-1);/* = - S_1 */ t2 = Fq_sqr(t1, Tpk, pk); if (d > 1) t2 = Fq_sub(t2, gmul2n(gel(P,d-2), 1), Tpk, pk); /* t2 = S_2 Newton sum */ if (ltdn) { t1 = Fq_Fp_mul(t1, ltdn, Tpk, pk); t2 = Fq_Fp_mul(t2, lt2dn, Tpk, pk); } gel(trace1,i) = gclone( nf_bestlift(t1, NULL, T->L) ); gel(trace2,i) = gclone( nf_bestlift(t2, NULL, T->L) ); avma = av; } T1 = init_trace(&_T1, trace1, T->L, q); T2 = init_trace(&_T2, trace2, T->L, q); for (i=1; i <= lfamod; i++) { gunclone(gel(trace1,i)); gunclone(gel(trace2,i)); } } degsofar[0] = 0; /* sentinel */ /* ind runs through strictly increasing sequences of length K, * 1 <= ind[i] <= lfamod */ nextK: if (K > *pmaxK || 2*K > lfamod) goto END; if (DEBUGLEVEL > 3) err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K)); setlg(ind, K+1); ind[1] = 1; i = 1; curdeg = deg[ind[1]]; for(;;) { /* try all combinations of K factors */ for (j = i; j < K; j++) { degsofar[j] = curdeg; ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]]; } if (curdeg <= klim) /* trial divide */ { GEN t, y, q; pari_sp av; av = avma; if (T1) { /* d-1 test */ t = get_trace(ind, T1); if (rtodbl(RgC_fpnorml2(t,DEFAULTPREC)) > Bhigh) { if (DEBUGLEVEL>6) err_printf("."); avma = av; goto NEXT; } } if (T2) { /* d-2 test */ t = get_trace(ind, T2); if (rtodbl(RgC_fpnorml2(t,DEFAULTPREC)) > Bhigh) { if (DEBUGLEVEL>3) err_printf("|"); avma = av; goto NEXT; } } avma = av; y = ltdn; /* full computation */ for (i=1; i<=K; i++) { GEN q = gel(famod, ind[i]); if (y) q = gmul(y, q); y = FqX_centermod(q, Tpk, pk, pks2); } y = nf_pol_lift(y, bound, T); if (!y) { if (DEBUGLEVEL>3) err_printf("@"); avma = av; goto NEXT; } /* y = topowden*dn*lt*\prod_{i in ind} famod[i] is apparently in O_K[X], * in fact in (Z[Y]/nf.pol)[X] due to multiplication by C = topowden*dn. * Try out this candidate factor */ q = RgXQX_divrem(D.C2ltpol, y, nfpol, ONLY_DIVIDES); if (!q) { if (DEBUGLEVEL>3) err_printf("*"); avma = av; goto NEXT; } /* Original T->pol in O_K[X] with leading coeff lt in Z, * y = C*lt \prod famod[i] is in O_K[X] with leading coeff in Z * q = C^2*lt*pol / y = C * (lt*pol) / (lt*\prod famod[i]) is a * K-rational factor, in fact in Z[Y]/nf.pol)[X] as above, with * leading term C*lt. */ update_target(&D, q); gel(fa,cnt++) = D.C2lt? RgX_int_normalize(y): y; /* make monic */ for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { gel(famod,k) = gel(famod,i); update_trace(T1, k, i); update_trace(T2, k, i); deg[k] = deg[i]; k++; } } lfamod -= K; *pmaxK = cmbf_maxK(lfamod); if (lfamod < 2*K) goto END; i = 1; curdeg = deg[ind[1]]; if (DEBUGLEVEL > 2) { err_printf("\n"); timer_printf(&ti, "to find factor %Ps",y); err_printf("remaining modular factor(s): %ld\n", lfamod); } continue; } NEXT: for (i = K+1;;) { if (--i == 0) { K++; goto nextK; } if (++ind[i] <= lfamod - K + i) { curdeg = degsofar[i-1] + deg[ind[i]]; if (curdeg <= klim) break; } } } END: *done = 1; if (degpol(D.C2ltpol) > 0) { /* leftover factor */ GEN q = D.C2ltpol; if (D.C2lt) q = RgX_int_normalize(q); if (lfamod >= 2*K) { /* restore leading coefficient [#930] */ if (D.lt) q = RgX_Rg_mul(q, D.lt); *done = 0; /* ... may still be reducible */ } setlg(famod, lfamod+1); gel(fa,cnt++) = q; } if (DEBUGLEVEL>6) err_printf("\n"); if (cnt == 2) { avma = av0; return mkvec(T->pol); } else { setlg(fa, cnt); return gerepilecopy(av0, fa); } } static GEN nf_chk_factors(nfcmbf_t *T, GEN P, GEN M_L, GEN famod, GEN pk) { GEN nf = T->nf, bound = T->bound; GEN nfT = nf_get_pol(nf); long i, r; GEN pol = P, list, piv, y; GEN Tpk = T->L->Tpk; div_data D; piv = special_pivot(M_L); if (!piv) return NULL; if (DEBUGLEVEL>3) err_printf("special_pivot output:\n%Ps\n",piv); r = lg(piv)-1; list = cgetg(r+1, t_VEC); init_div_data(&D, pol, T->L); for (i = 1;;) { pari_sp av = avma; 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; y = gerepilecopy(av, y); /* y is the candidate factor */ pol = RgXQX_divrem(D.C2ltpol, y, nfT, ONLY_DIVIDES); if (!pol) return NULL; if (D.C2lt) y = RgX_int_normalize(y); gel(list,i) = y; if (++i >= r) break; update_target(&D, pol); } gel(list,i) = RgX_int_normalize(pol); return list; } static GEN nf_to_Zq(GEN x, GEN T, GEN pk, GEN pks2, GEN proj) { GEN y; if (typ(x) != t_COL) return centermodii(x, pk, pks2); if (!T) { y = ZV_dotproduct(proj, x); return centermodii(y, pk, pks2); } y = ZM_ZC_mul(proj, x); y = RgV_to_RgX(y, varn(T)); return FpX_center(FpX_rem(y, T, pk), pk, pks2); } /* Assume P in nfX form, lc(P) != 0 mod p. Reduce P to Zp[X]/(T) mod p^a */ static GEN ZqX(GEN P, GEN pk, GEN T, GEN proj) { long i, l = lg(P); GEN z, pks2 = shifti(pk,-1); z = cgetg(l,t_POL); z[1] = P[1]; for (i=2; ipk)): P; return ZqX(R, L->pk, L->Tpk, L->ZqProj); } /* k allowing to reconstruct x, |x|^2 < C, from x mod pr^k */ /* return log [ 2sqrt(C/d) * ( (3/2)sqrt(gamma) )^(d-1) ] ^d / log N(pr) * cf. Belabas relative van Hoeij algorithm, lemma 3.12 */ static double bestlift_bound(GEN C, long d, double alpha, GEN Npr) { const double y = 1 / (alpha - 0.25); /* = 2 if alpha = 3/4 */ double t; C = gtofp(C,DEFAULTPREC); /* (1/2)log (4C/d) + (d-1)(log 3/2 sqrt(gamma)) */ t = rtodbl(mplog(gmul2n(divru(C,d), 2))) * 0.5 + (d-1) * log(1.5 * sqrt(y)); return ceil((t * d) / log(gtodouble(Npr))); } static GEN get_R(GEN M) { GEN R; long i, l, prec = nbits2prec( gexpo(M) + 64 ); for(;;) { R = gaussred_from_QR(M, prec); if (R) break; prec = precdbl(prec); } l = lg(R); for (i=1; iTp) { GEN coTp = FpX_div(FpX_red(nfT, L->p), L->Tp, L->p); /* Tp's cofactor */ GEN z, proj; z = ZpX_liftfact(nfT, mkvec2(L->Tp, coTp), NULL, L->p, L->k, L->pk); L->Tpk = gel(z,1); proj = get_proj_modT(L->topow, L->Tpk, L->pk); if (L->topowden) proj = FpM_red(ZM_Z_mul(proj, Fp_inv(L->topowden, L->pk)), L->pk); L->ZqProj = proj; } else { L->Tpk = NULL; L->ZqProj = dim1proj(L->prkHNF); } } /* Square of the radius of largest ball inscript in PRK's fundamental domain, * whose orthogonalized vector's norms are the Bi * Rmax ^2 = min 1/4T_i where T_i = sum ( s_ij^2 / B_j) */ static GEN max_radius(GEN PRK, GEN B) { GEN S, smax = gen_0; pari_sp av = avma; long i, j, d = lg(PRK)-1; S = RgM_inv( get_R(PRK) ); if (!S) pari_err_PREC("max_radius"); for (i=1; i<=d; i++) { GEN s = gen_0; for (j=1; j<=d; j++) s = mpadd(s, mpdiv( mpsqr(gcoeff(S,i,j)), gel(B,j))); if (mpcmp(s, smax) > 0) smax = s; } return gerepileupto(av, ginv(gmul2n(smax, 2))); } static void bestlift_init(long a, GEN nf, GEN pr, GEN C, nflift_t *L) { const double alpha = 0.99; /* LLL parameter */ const long d = nf_get_degree(nf); pari_sp av = avma, av2; GEN prk, PRK, B, GSmin, pk; pari_timer ti; timer_start(&ti); if (!a) a = (long)bestlift_bound(C, d, alpha, pr_norm(pr)); for (;; avma = av, a += (a==1)? 1: (a>>1)) /* roughly a *= 1.5 */ { if (DEBUGLEVEL>2) err_printf("exponent %ld\n",a); prk = idealpows(nf, pr, a); av2 = avma; pk = gcoeff(prk,1,1); PRK = ZM_lll_norms(prk, alpha, LLL_INPLACE, &B); GSmin = max_radius(PRK, B); if (gcmp(GSmin, C) >= 0) break; } gerepileall(av2, 2, &PRK, &GSmin); if (DEBUGLEVEL>2) err_printf("for this exponent, GSmin = %Ps\nTime reduction: %ld\n", GSmin, timer_delay(&ti)); L->k = a; L->den = L->pk = pk; L->prk = PRK; L->iprk = ZM_inv(PRK, pk); L->GSmin= GSmin; L->prkHNF = prk; init_proj(L, nf_get_pol(nf)); } /* Let X = Tra * M_L, Y = bestlift(X) return V s.t Y = X - PRK V * and set *eT2 = gexpo(Y) [cf nf_bestlift, but memory efficient] */ static GEN get_V(GEN Tra, GEN M_L, GEN PRK, GEN PRKinv, GEN pk, long *eT2) { long i, e = 0, l = lg(M_L); GEN V = cgetg(l, t_MAT); *eT2 = 0; for (i = 1; i < l; i++) { /* cf nf_bestlift(Tra * c) */ pari_sp av = avma, av2; GEN v, T2 = ZM_ZC_mul(Tra, gel(M_L,i)); v = gdivround(ZM_ZC_mul(PRKinv, T2), pk); /* small */ av2 = avma; T2 = ZC_sub(T2, ZM_ZC_mul(PRK, v)); e = gexpo(T2); if (e > *eT2) *eT2 = e; avma = av2; gel(V,i) = gerepileupto(av, v); /* small */ } return V; } static GEN nf_LLL_cmbf(nfcmbf_t *T, long rec) { const double BitPerFactor = 0.4; /* nb bits / modular factor */ nflift_t *L = T->L; GEN famod = T->fact, ZC = T->ZC, Br = T->Br, P = T->pol, dn = T->L->dn; long dnf = nf_get_degree(T->nf), dP = degpol(P); long i, C, tmax, n0; GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO, Btra; double Bhigh; pari_sp av, av2, lim; long ti_LLL = 0, ti_CF = 0; pari_timer ti2, TI; lP = absi(leading_term(P)); if (is_pm1(lP)) lP = NULL; n0 = lg(famod) - 1; /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image, * write S = S1 q + S0, P = P1 q + P0 * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */ Btra = mulrr(ZC, mulur(dP*dP, normlp(Br, 2, dnf))); Bhigh = get_Bhigh(n0, dnf); C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */ Bnorm = dbltor( n0 * C * C + Bhigh ); ZERO = zeromat(n0, dnf); av = avma; lim = stack_lim(av, 1); TT = cgetg(n0+1, t_VEC); Tra = cgetg(n0+1, t_MAT); for (i=1; i<=n0; i++) TT[i] = 0; CM_L = scalarmat_s(C, n0); /* tmax = current number of traces used (and computed so far) */ for(tmax = 0;; tmax++) { long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1; GEN M_L, q, CM_Lp, oldCM_L, S1, P1, VV; int first = 1; /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */ Btra = mulrr(ZC, mulur(dP*dP, normlp(Br, 2*tnew, dnf))); bmin = logint(ceil_safe(sqrtr(Btra)), gen_2, NULL); if (DEBUGLEVEL>2) err_printf("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n", r, tmax, bmin); /* compute Newton sums (possibly relifting first) */ if (gcmp(L->GSmin, Btra) < 0) { GEN polred; bestlift_init((L->k)<<1, T->nf, T->pr, Btra, L); polred = ZqX_normalize(T->polbase, lP, L); famod = ZpX_liftfact(polred, famod, L->Tpk, L->p, L->k, L->pk); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN h, lPpow = lP? powiu(lP, tnew): NULL; GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, L->Tpk, L->pk); gel(TT,i) = z; h = gel(z,tnew+1); /* make Newton sums integral */ lPpow = mul_content(lPpow, dn); if (lPpow) h = (typ(h) == t_INT)? Fp_mul(h, lPpow, L->pk): FpX_Fp_mul(h, lPpow, L->pk); gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */ } /* compute truncation parameter */ if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); } oldCM_L = CM_L; av2 = avma; b = delta = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); VV = get_V(Tra, M_L, L->prk, L->iprk, L->pk, &a); if (first) { /* initialize lattice, using few p-adic digits for traces */ bgood = (long)(a - maxss(32, (long)(BitPerFactor * r))); b = maxss(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ if (a < b) b = a; b = maxss(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } /* restart with truncated entries */ q = int2n(b); P1 = gdivround(L->prk, q); S1 = gdivround(Tra, q); T2 = ZM_sub(ZM_mul(S1, M_L), ZM_mul(P1, VV)); m = vconcat( CM_L, T2 ); if (first) { first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' PRK ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI)); if (!CM_L) { list = mkcol(RgX_int_normalize(P)); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) timer_printf(&ti2, "for this trace"); i = lg(CM_L) - 1; if (i == r && ZM_equal(CM_L, oldCM_L)) { CM_L = oldCM_L; avma = av2; continue; } CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */ if (lg(CM_Lp) != lg(CM_L)) { if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n"); CM_L = ZM_hnf(CM_L); } if (i <= r && i*rec < n0) { pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, L->pk); if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti); if (list) break; } CM_L = gerepilecopy(av2, CM_L); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf"); gerepileall(av, L->Tpk? 9: 8, &CM_L,&TT,&Tra,&famod,&L->pk,&L->GSmin,&L->prk,&L->iprk,&L->Tpk); } } if (DEBUGLEVEL>2) err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF); return list; } static GEN nf_combine_factors(nfcmbf_t *T, GEN polred, long klim) { nflift_t *L = T->L; GEN res; long maxK; int done; pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); T->fact = ZpX_liftfact(polred, T->fact, L->Tpk, L->p, L->k, L->pk); if (DEBUGLEVEL>2) timer_printf(&ti, "Hensel lift"); res = nfcmbf(T, klim, &maxK, &done); if (DEBUGLEVEL>2) timer_printf(&ti, "Naive recombination"); if (!done) { long l = lg(res)-1; GEN v; if (l > 1) { T->pol = gel(res,l); T->polbase = RgX_to_nfX(T->nf, T->pol); } v = nf_LLL_cmbf(T, maxK); /* remove last elt, possibly unfactored. Add all new ones. */ setlg(res, l); res = shallowconcat(res, v); } return res; } static GEN nf_DDF_roots(GEN pol, GEN polred, GEN nfpol, GEN init_fa, long nbf, long fl, nflift_t *L) { GEN z, Cltx_r, ltdn; long i, m; div_data D; init_div_data(&D, pol, L); ltdn = mul_content(D.lt, L->dn); if (L->Tpk) { int cof = (degpol(pol) > nbf); /* non trivial cofactor ? */ z = FqX_split_roots(init_fa, L->Tp, L->p, cof? polred: NULL); z = ZpX_liftfact(polred, z, L->Tpk, L->p, L->k, L->pk); if (cof) setlg(z, lg(z)-1); /* remove cofactor */ z = roots_from_deg1(z); } else z = rootpadicfast(polred, L->p, L->k); Cltx_r = deg1pol_shallow(D.Clt? D.Clt: gen_1, NULL, varn(pol)); for (m=1,i=1; i 0; i--) { r = gel(list,i); dr = degpol(r); if (dr <= maxf) return r; } } avma = av; return NULL; /* failure */ } /* Optimization problem: factorization of polynomials over large Fq is slow, * BUT bestlift correspondingly faster. * Return maximal residue degree to be considered when picking a prime ideal */ static long get_maxf(long nfdeg) { long maxf = 1; if (nfdeg >= 45) maxf =16; else if (nfdeg >= 30) maxf = 8; else if (nfdeg >= 15) maxf = 4; return maxf; } /* Select a prime ideal pr over which to factor polbase. * Return the number of factors (or roots, according to flag fl) mod pr, * Input: * ct: number of attempts to find best * Set: * lt: leading term of polbase (t_INT or NULL [ for 1 ]) * pr: a suitable maximal ideal * Fa: factors found mod pr * Tp: polynomial defining Fq/Fp */ static long nf_pick_prime(long ct, GEN nf, GEN polbase, long fl, GEN *lt, GEN *Fa, GEN *pr, GEN *Tp) { GEN nfpol = nf_get_pol(nf), bad = mulii(nf_get_disc(nf), nf_get_index(nf)); long maxf, nfdeg = degpol(nfpol), dpol = degpol(polbase), nbf = 0; ulong pp; forprime_t S; pari_timer ti_pr; if (DEBUGLEVEL>3) timer_start(&ti_pr); *lt = leading_term(polbase); /* t_INT */ if (gequal1(*lt)) *lt = NULL; *pr = NULL; *Fa = NULL; *Tp = NULL; maxf = get_maxf(nfdeg); (void)u_forprime_init(&S, 2, ULONG_MAX); /* select pr such that pol has the smallest number of factors, ct attempts */ while ((pp = u_forprime_next(&S))) { GEN aT, apr, ap, amodpr, red, r, fa = NULL; long anbf; ulong ltp = 0; pari_sp av2 = avma; /* first step : select prime of high inertia degree */ if (! umodiu(bad,pp)) continue; if (*lt) { ltp = umodiu(*lt, pp); if (!ltp) continue; } r = get_good_factor(nfpol, pp, maxf); if (!r) continue; ap = utoipos(pp); apr = primedec_apply_kummer(nf, Flx_to_ZX(r), 1, ap); amodpr = zk_to_Fq_init(nf,&apr,&aT,&ap); /* second step : evaluate factorisation mod apr */ red = nfX_to_FqX(polbase, nf, amodpr); if (!aT) { /* degree 1 */ red = ZX_to_Flx(red, pp); if (ltp) red = Flx_normalize(red, pp); if (!Flx_is_squarefree(red, pp)) { avma = av2; continue; } anbf = fl == FACTORS? Flx_nbfact(red, pp): Flx_nbroots(red, pp); } else { if (ltp) red = FqX_normalize(red, aT,ap); if (!FqX_is_squarefree(red,aT,ap)) { avma = av2; continue; } anbf = fl == FACTORS? FqX_split_by_degree(&fa, red, aT, ap) : FqX_split_deg1(&fa, red, aT, ap); } if (fl == ROOTS_SPLIT && anbf < dpol) return anbf; if (anbf <= 1) { if (fl == FACTORS) return anbf; /* irreducible */ if (!anbf) return 0; /* no root */ } if (!nbf || anbf < nbf || (anbf == nbf && pr_get_f(apr) > pr_get_f(*pr))) { nbf = anbf; *pr = apr; *Tp = aT; *Fa = fa; } else avma = av2; if (DEBUGLEVEL>3) err_printf("%3ld %s at prime\n %Ps\nTime: %ld\n", anbf, fl == FACTORS?"factors": "roots", apr, timer_delay(&ti_pr)); if (--ct <= 0) break; } if (!nbf) pari_err_OVERFLOW("nf_pick_prime [ran out of primes]"); return nbf; } /* assume lt(T) is a t_INT and T square free */ static GEN nfsqff_trager(GEN u, GEN T, GEN dent) { long k = 0, i, lx; GEN U, P, x0, mx0, fa, n = ZX_ZXY_rnfequation(T, u, &k); int tmonic; if (DEBUGLEVEL>4) err_printf("nfsqff_trager: choosing k = %ld\n",k); /* n guaranteed to be squarefree */ fa = ZX_DDF(Q_primpart(n)); lx = lg(fa); if (lx == 2) return mkcol(u); tmonic = is_pm1(leading_term(T)); P = cgetg(lx,t_COL); x0 = deg1pol_shallow(stoi(-k), gen_0, varn(T)); mx0 = deg1pol_shallow(stoi(k), gen_0, varn(T)); U = RgXQX_translate(u, mx0, T); if (!tmonic) U = Q_primpart(U); for (i=lx-1; i>0; i--) { GEN f = gel(fa,i), F = nfgcd(U, f, T, dent); F = RgXQX_translate(F, x0, T); /* F = gcd(f, u(t - x0)) [t + x0] = gcd(f(t + x0), u), more efficient */ if (typ(F) != t_POL || degpol(F) == 0) 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; } /* Factor polynomial a on the number field defined by polynomial T, using * Trager's trick */ GEN polfnf(GEN a, GEN T) { GEN rep = cgetg(3, t_MAT), A, B, y, dent, bad; long dA; int tmonic; if (typ(a)!=t_POL) pari_err_TYPE("polfnf",a); if (typ(T)!=t_POL) pari_err_TYPE("polfnf",T); T = Q_primpart(T); tmonic = is_pm1(leading_term(T)); RgX_check_ZX(T,"polfnf"); A = Q_primpart( QXQX_normalize(RgX_nffix("polfnf",T,a,1), T) ); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return (dA == 0)? trivial_fact(): zerofact(varn(A)); } bad = dent = ZX_disc(T); if (tmonic) dent = indexpartial(T, dent); (void)nfgcd_all(A,RgX_deriv(A), T, dent, &B); if (degpol(B) != dA) B = Q_primpart( QXQX_normalize(B, T) ); ensure_lt_INT(B); y = nfsqff_trager(B, T, dent); fact_from_sqff(rep, A, B, y, T, bad); return sort_factor_pol(rep, cmp_RgX); } static int nfsqff_use_Trager(long n, long dpol) { return dpol*3 0, deg(nfpol) > 1 fl is either FACTORS (return factors), or ROOTS / ROOTS_SPLIT (return roots): - ROOTS, return only the roots of x in nf - ROOTS_SPLIT, as ROOTS if pol splits, [] otherwise den is usually 1, otherwise nf.zk is doubtful, and den bounds the denominator of an arbitrary element of Z_nf on nf.zk */ static GEN nfsqff(GEN nf, GEN pol, long fl, GEN den) { long n, nbf, dpol = degpol(pol); GEN pr, C0, polbase, init_fa = NULL; GEN N2, res, polred, lt, nfpol = typ(nf)==t_POL?nf:nf_get_pol(nf); nfcmbf_t T; nflift_t L; pari_timer ti, ti_tot; if (DEBUGLEVEL>2) { timer_start(&ti); timer_start(&ti_tot); } n = degpol(nfpol); /* deg = 1 => irreducible */ if (dpol == 1) { if (fl == FACTORS) return mkvec(QXQX_normalize(pol, nfpol)); return mkvec(gneg(gdiv(gel(pol,2),gel(pol,3)))); } if (typ(nf)==t_POL || nfsqff_use_Trager(n,dpol)) { GEN z; if (DEBUGLEVEL>2) err_printf("Using Trager's method\n"); if (typ(nf) != t_POL) den = mulii(den, nf_get_index(nf)); z = nfsqff_trager(Q_primpart(pol), nfpol, den); if (fl != FACTORS) { long i, l = lg(z); for (i = 1; i < l; i++) { GEN LT, t = gel(z,i); if (degpol(t) > 1) break; LT = gel(t,3); if (typ(LT) == t_POL) LT = gel(LT,2); /* constant */ gel(z,i) = gdiv(gel(t,2), negi(LT)); } setlg(z, i); if (fl == ROOTS_SPLIT && i != l) return cgetg(1,t_VEC); } return z; } polbase = RgX_to_nfX(nf, pol); nbf = nf_pick_prime(5, nf, polbase, fl, <, &init_fa, &pr, &L.Tp); if (fl == ROOTS_SPLIT && nbf < dpol) return cgetg(1,t_VEC); if (nbf <= 1) { if (fl == FACTORS) return mkvec(QXQX_normalize(pol, nfpol)); /* irred. */ if (!nbf) return cgetg(1,t_VEC); /* no root */ } if (DEBUGLEVEL>2) { timer_printf(&ti, "choice of a prime ideal"); err_printf("Prime ideal chosen: %Ps\n", pr); } L.tozk = nf_get_invzk(nf); L.topow= Q_remove_denom(nf_get_zk(nf), &L.topowden); if (is_pm1(den)) den = NULL; L.dn = den; T.ZC = L2_bound(nf, den); T.Br = nf_root_bounds(pol, nf); if (lt) T.Br = gmul(T.Br, lt); /* C0 = bound for T_2(Q_i), Q | P */ if (fl != FACTORS) C0 = normlp(T.Br, 2, n); else C0 = nf_factor_bound(nf, polbase); T.bound = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */ N2 = mulur(dpol*dpol, normlp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */ T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */ if (DEBUGLEVEL>2) { timer_printf(&ti, "bound computation"); err_printf(" 1) T_2 bound for %s: %Ps\n", fl == FACTORS?"factor": "root", C0); err_printf(" 2) Conversion from T_2 --> | |^2 bound : %Ps\n", T.ZC); err_printf(" 3) Final bound: %Ps\n", T.bound); } L.p = pr_get_p(pr); if (L.Tp && degpol(L.Tp) == 1) L.Tp = NULL; bestlift_init(0, nf, pr, T.bound, &L); if (DEBUGLEVEL>2) timer_start(&ti); polred = ZqX_normalize(polbase, lt, &L); /* monic */ if (fl != FACTORS) { GEN z = nf_DDF_roots(pol, polred, nfpol, init_fa, nbf, fl, &L); if (lg(z) == 1) return cgetg(1, t_VEC); return z; } { pari_sp av = avma; if (L.Tp) res = FqX_split_all(init_fa, L.Tp, L.p); else { long d; res = cgetg(dpol + 1, t_VEC); gel(res,1) = FpX_red(polred,L.p); d = FpX_split_Berlekamp((GEN*)(res + 1), L.p); setlg(res, d + 1); } gen_sort_inplace(res, (void*)&cmp_RgX, &gen_cmp_RgX, NULL); T.fact = gerepilecopy(av, res); } if (DEBUGLEVEL>2) timer_printf(&ti, "splitting mod %Ps", pr); T.pr = pr; T.L = &L; T.polbase = polbase; T.pol = pol; T.nf = nf; res = nf_combine_factors(&T, polred, dpol-1); if (DEBUGLEVEL>2) err_printf("Total Time: %ld\n===========\n", timer_delay(&ti_tot)); return res; } /* assume pol monic in nf.zk[X] */ GEN nfroots_split(GEN nf, GEN pol) { GEN T = get_nfpol(nf,&nf), den = fix_nf(&nf, &T, &pol); pari_sp av = avma; GEN z = gerepilecopy(av, nfsqff(nf, pol, ROOTS_SPLIT, den)); return (lg(z) == 1)? NULL: mkvec2(z, nf); } /*******************************************************************/ /* */ /* Roots of unity in a number field */ /* (alternative to nfrootsof1 using factorization in K[X]) */ /* */ /*******************************************************************/ /* Code adapted from nffactor. Structure of the algorithm; only step 1 is * specific to roots of unity. * * [Step 1]: guess roots via ramification. If trivial output this. * [Step 2]: select prime [p] unramified and ideal [pr] above * [Step 3]: evaluate the maximal exponent [k] such that the fondamental domain * of a LLL-reduction of [prk] = pr^k contains a ball of radius larger * than the norm of any root of unity. * [Step 3]: select a heuristic exponent, * LLL reduce prk=pr^k and verify the exponent is sufficient, * otherwise try a larger one. * [Step 4]: factor the cyclotomic polynomial mod [pr], * Hensel lift to pr^k and find the representative in the ball * If there is it is a primitive root */ typedef struct { GEN q; GEN modpr; GEN pr; nflift_t *L; } prklift_t; /* FIXME: check that all primes dividing n are ramified ! */ /* Choose prime ideal unramified with "large" inertia degree */ static void nf_pick_prime_for_units(GEN nf, prklift_t *P) { GEN nfpol = nf_get_pol(nf), bad = mulii(nf_get_disc(nf), nf_get_index(nf)); GEN aT, amodpr, apr, ap = NULL, r = NULL; long nfdeg = degpol(nfpol), maxf = get_maxf(nfdeg); ulong pp; forprime_t S; (void)u_forprime_init(&S, 2, ULONG_MAX); while ( (pp = u_forprime_next(&S)) ) { if (! umodiu(bad,pp)) continue; r = get_good_factor(nfpol, pp, maxf); if (r) break; } if (!r) pari_err_OVERFLOW("nf_pick_prime [ran out of primes]"); ap = utoipos(pp); apr = primedec_apply_kummer(nf, Flx_to_ZX(r), 1, ap); amodpr = zk_to_Fq_init(nf,&apr,&aT,&ap); P->pr = apr; P->q = pr_norm(apr); P->modpr = amodpr; P->L->p = ap; P->L->Tp = aT; P->L->tozk = nf_get_invzk(nf); P->L->topow = Q_remove_denom(nf_get_zk(nf), &(P->L->topowden)); } /* *Heuristic* exponent k such that the fundamental domain of pr^k * should contain the ball of radius C */ static double mybestlift_bound(GEN C) { C = gtofp(C,DEFAULTPREC); #if 0 /* d = nf degree, Npr = Norm(pr) */ const double alpha = 0.99; /* LLL parameter */ const double y = 1 / (alpha - 0.25); /* = 2 if alpha = 3/4 */ double t; t = rtodbl(mplog(gmul2n(divru(C,d), 4))) * 0.5 + (d-1) * log(1.5 * sqrt(y)); return ceil((t * d) / log(gtodouble(Npr))); /* proved upper bound */ #endif return ceil(log(gtodouble(C)) / 0.2) + 3; } /* Returns the roots of the n_cyclo-th cyclotomic polynomial * if it splits, NULL otherwise */ static GEN 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); 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); else { ulong p = itou(P->L->p); nbf = Flx_nbroots(ZX_to_Flx(pol,p), p); } if (nbf != deg) return NULL; /* no roots in residue field */ z = nf_DDF_roots(pol, pol, nfpol, init_fa, nbf, ROOTS_SPLIT, P->L); if (lg(z) == 1) { avma = av; return NULL; } /* no roots */ return gel(z,1); } /* Guesses the number of roots of unity in number field [nf]. * Computes gcd of N(P)-1 for some primes. The value returned is a proven * multiple of the correct value. */ static long guess_roots(GEN nf) { long c = 0, nfdegree = nf_get_degree(nf), B = nfdegree + 20, l; ulong p = 2; GEN T = nf_get_pol(nf), D = nf_get_disc(nf), index = nf_get_index(nf); GEN nbroots = NULL; forprime_t S; pari_sp av; (void)u_forprime_init(&S, 3, ULONG_MAX); av = avma; /* result must be stationnary (counter c) for at least B loops */ for (l=1; (p = u_forprime_next(&S)); l++) { GEN old, F, pf_1, Tp; long i, nb, gcdf = 0; if (!umodiu(D,p) || !umodiu(index,p)) continue; Tp = ZX_to_Flx(T,p); /* squarefree */ F = Flx_nbfact_by_degree(Tp, &nb, p); /* the gcd of the p^f - 1 is p^(gcd of the f's) - 1 */ for (i = 1; i <= nfdegree; i++) if (F[i]) { gcdf = gcdf? cgcd(gcdf, i): i; if (gcdf == 1) break; } pf_1 = subis(powuu(p, gcdf), 1); old = nbroots; nbroots = nbroots? gcdii(pf_1, nbroots): pf_1; if (DEBUGLEVEL>5) err_printf("p=%ld; gcf(f(P/p))=%ld; nbroots | %Ps",p, gcdf, nbroots); /* if same result go on else reset the stop counter [c] */ if (old && equalii(nbroots,old)) { if (!is_bigint(nbroots) && ++c > B) break; } else c = 0; } if (!nbroots) pari_err_OVERFLOW("guess_roots [ran out of primes]"); if (DEBUGLEVEL>5) err_printf("%ld loops\n",l); avma = av; return itos(nbroots); } /* T(x) an irreducible ZX. Is it of the form Phi_n(c \pm x) ? * Return NULL if not, and a root of 1 of maximal order in Z[x]/(T) otherwise * * N.B. Set n_squarefree = 1 if n is squarefree, and 0 otherwise. * This last parameter is inconvenient, but it allows a cheap * stringent test. (n guessed from guess_roots())*/ static GEN ZXirred_is_cyclo_translate(GEN T, long n_squarefree) { long r, m, d = degpol(T); GEN T1, c = divis_rem(gel(T, d+1), d, &r); /* d-1 th coeff divisible by d ? */ /* The trace coefficient of polcyclo(n) is \pm1 if n is square free, and 0 * otherwise. */ if (!n_squarefree) { if (r) return NULL; } else { if (r < -1) { r += d; c = subiu(c, 1); } else if (r == d-1) { r = -1; c = addiu(c, 1); } if (r != 1 && r != -1) return NULL; } if (signe(c)) /* presumably Phi_guess(c \pm x) */ T = RgX_translate(T, negi(c)); if (!n_squarefree) T = RgX_deflate_max(T, &m); /* presumably Phi_core(guess)(\pm x), cyclotomic iff original T was */ T1 = ZX_graeffe(T); if (ZX_equal(T, T1)) /* T = Phi_n, n odd */ return deg1pol_shallow(gen_m1, negi(c), varn(T)); else if (ZX_equal(T1, ZX_unscale(T, gen_m1))) /* T = Phi_{2n}, nodd */ return deg1pol_shallow(gen_1, c, varn(T)); return NULL; } static GEN trivroots(void) { return mkvec2(gen_2, gen_m1); } /* Number of roots of unity in number field [nf]. */ GEN rootsof1(GEN nf) { prklift_t P; nflift_t L; GEN fa, LP, LE, C0, z, prim_root, disc; pari_timer ti; long i, l, nbguessed, nbroots, nfdegree; pari_sp av; nf = checknf(nf); if (nf_get_r1(nf)) return trivroots(); /* Step 1 : guess number of roots and discard trivial case 2 */ if (DEBUGLEVEL>2) timer_start(&ti); nbguessed = guess_roots(nf); if (DEBUGLEVEL>2) timer_printf(&ti, "guessing roots of 1 [guess = %ld]", nbguessed); if (nbguessed == 2) return trivroots(); nfdegree = nf_get_degree(nf); fa = factoru(nbguessed); LP = gel(fa,1); l = lg(LP); LE = gel(fa,2); disc = nf_get_disc(nf); for (i = 1; i < l; i++) { long p = LP[i]; /* Cheap test: can Q(zeta_{2p}) be a subset of K ? */ if (p == 2) { /* 2 | n and v_p(disc K) >= n/2 ? */ if (LE[i] == 1) continue; if (!odd(nfdegree) && vali(disc) >= nfdegree / 2) continue; } else { /* p-1 | n and v_p(disc K) >= (p-2) n/(p-1) ? */ ulong r, q = udivuu_rem(nfdegree, p-1, &r); if (r == 0 && (ulong)Z_lval(disc, p) >= q * (p-2)) continue; } nbguessed /= upowuu(p, LE[i]); LE[i] = 0; } if (DEBUGLEVEL>2) timer_printf(&ti, "after ramification conditions [guess = %ld]", nbguessed); if (nbguessed == 2) return trivroots(); av = avma; /* Step 1.5 : test if nf.pol == subst(polcyclo(nbguessed), x, \pm x+c) */ if (eulerphiu_fact(fa) == (ulong)nfdegree) { GEN elt = ZXirred_is_cyclo_translate(nf_get_pol(nf), uissquarefree_fact(fa)); if (elt) { if (DEBUGLEVEL>2) timer_printf(&ti, "checking for cyclotomic polynomial [yes]"); return gerepilecopy(av, mkvec2(utoipos(nbguessed), elt)); } avma = av; } if (DEBUGLEVEL>2) timer_printf(&ti, "checking for cyclotomic polynomial [no]"); /* Step 2 : choose a prime ideal for local lifting */ P.L = &L; nf_pick_prime_for_units(nf, &P); if (DEBUGLEVEL>2) timer_printf(&ti, "choosing prime %Ps, degree %ld", P.L->p, P.L->Tp? degpol(P.L->Tp): 1); /* Step 3 : compute a reduced pr^k allowing lifting of local solutions */ /* evaluate maximum L2 norm of a root of unity in nf */ C0 = gmulsg(nfdegree, L2_bound(nf, gen_1)); /* lift and reduce pr^k */ if (DEBUGLEVEL>2) err_printf("Lift pr^k; GSmin wanted: %Ps\n",C0); bestlift_init((long)mybestlift_bound(C0), nf, P.pr, C0, P.L); P.L->dn = NULL; if (DEBUGLEVEL>2) timer_start(&ti); /* Step 4 : actual computation of roots */ nbroots = 2; prim_root = gen_m1; for (i = 1; i < l; i++) { /* for all prime power factors of nbguessed, find a p^k-th root of unity */ long k, p = LP[i]; for (k = LE[i]; k > 0; k--) { /* find p^k-th roots */ long pk = upowuu(p,k); if (pk==2) continue; /* no need to test second roots ! */ z = nfcyclo_root(nf,pk,&P); if (DEBUGLEVEL>2) timer_printf(&ti, "for factoring Phi_%ld^%ld", p,k); if (z) { if (DEBUGLEVEL>2) err_printf(" %ld-th root of unity found.\n", pk); if (p==2) { nbroots = pk; prim_root = z; } else { nbroots *= pk; prim_root = nfmul(nf, prim_root,z); } break; } if (DEBUGLEVEL) pari_warn(warner,"rootsof1: wrong guess"); } } return gerepilecopy(av, mkvec2(utoi(nbroots), prim_root)); } static long nf_pm1(GEN y) { GEN z = gel(y,1); return (is_pm1(z) && ZV_isscalar(y))? signe(z): 0; } static GEN is_primitive_root(GEN nf, GEN fa, GEN x, long w) { GEN y, exp = utoipos(2), pp = gel(fa,1); long i,p, l = lg(pp); for (i=1; i 0) /* y = 1 */ { if (p!=2 || !gequal1(gcoeff(fa,i,2))) return NULL; x = gneg_i(x); } } return x; } GEN rootsof1_kannan(GEN nf) { pari_sp av = avma; long N, k, i, ws, prec; GEN z, y, d, list, w; nf = checknf(nf); if ( nf_get_r1(nf) ) return trivroots(); N = nf_get_degree(nf); prec = nf_get_prec(nf); for (;;) { GEN R = R_from_QR(nf_get_G(nf), prec); if (R) { y = fincke_pohst(mkvec(R), utoipos(N), N * N, 0, NULL); if (y) break; } prec = precdbl(prec); if (DEBUGLEVEL) pari_warn(warnprec,"rootsof1",prec); nf = nfnewprec_shallow(nf,prec); } if (itos(ground(gel(y,2))) != N) pari_err_BUG("rootsof1 (bug1)"); w = gel(y,1); ws = itos(w); if (ws == 2) { avma = av; return trivroots(); } d = Z_factor(w); list = gel(y,3); k = lg(list); for (i=1; ipp[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) */ static void gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN *psum, GEN n, long i, GEN a, GEN lasta) { pari_sp av = avma, lim = stack_lim(av,2); 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); j = 1; } else j = i; for(; j <= i; j++) { ulong p = bg->p[j]; GEN nexta, pn = mului(p, n); 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); } } } static void gen_BG_init(struct bg_data *bg, GEN E, GEN N, GEN bnd, GEN ap) { pari_sp av; long i = 1, l; bg->E = E; bg->N = N; bg->bnd = bnd; bg->rootbnd = itou(sqrtint(bnd)); bg->p = primes_upto_zv(bg->rootbnd); l = lg(bg->p); if (ap) { /* reuse known values */ i = lg(ap); bg->ap = vecsmall_lengthen(ap, maxss(l,i)-1); } else bg->ap = cgetg(l, t_VECSMALL); av = avma; for ( ; i < l; i++, avma = av) bg->ap[i] = itos(ellap(E, utoipos(bg->p[i]))); avma = av; bg->an = zero_zv(bg->rootbnd); bg->an[1] = 1; } static GEN gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg, GEN sum0) { long i, j, lp = lg(bg->p)-1, lim; GEN bndov2 = shifti(bg->bnd, -1); pari_sp av = avma, av2; GEN sum, p; forprime_t S; (void)forprime_init(&S, utoipos(bg->p[lp]+1), bg->bnd); av2 = avma; lim = stack_lim(av2,1); 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); } } 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); 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 */ for (j = 2; j <= jmax; j++) { long aj = bg->an[j]; GEN a, n; 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); } if (absi_cmp(p, bndov2) >= 0) break; } if (DEBUGLEVEL) err_printf("3nd stage, looping for p <= %Ps\n", bg->bnd); while ( (p = forprime_next(&S)) ) { 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); } } return gerepileupto(av, sum); } /* Computing L-series derivatives */ /* 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 { GEN baby, giant; ulong bgbnd; }; 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) { 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 */ a = cgetg(m+2, t_VEC); for (i = 1; i <= m+1; i++) gel(a, i) = gel(p1, i+1); return 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) { 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++) { for (n = 2; n <= m; n++) { 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; } swap(A, B); /* B becomes the new A, old A becomes the new scratchspace */ } /* 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; } /* x > 0 t_REAL, M >= 2 */ static long estimate_prec_Sx(GEN x, long M) { 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) { 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; } avma = av; return expo(p1); } /* x a t_REAL */ static long number_of_terms_Sx(GEN x, long epsbit) { 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; } } /* 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) { 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; } } /* x "small" t_REAL, use power series expansion. Returns a t_REAL */ static GEN compute_Gr_VSx(struct ellld *el, GEN x) { 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++) { 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)); } /* sum_{n = 1}^{oo} (-1)^(n-1) x^n / (n! n^r) */ } /* 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) { 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); } /* 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 */ 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)); } /* 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 */ static GEN init_G(struct ellld *el, long prec) { if (el->r == 0) { 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); } 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); } /* 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) { 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)); } /* 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) { 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)); } static void heegner_L1(void*E, GEN *psum, GEN n, GEN a, long jmax) { 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; } /* 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) { 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)); } static void init_el(struct ellld *el, GEN E, long *parity, long bitprec) { 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 */ } 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)); } GEN ellL1(GEN E, long r, long prec) { return ellL1_bitprec(E, r, prec2nbits(prec)); } GEN ellanalyticrank(GEN e, GEN eps, long prec) { struct ellld el; struct bg_data bg; long rk; pari_sp av = avma, av2; GEN ap = NULL; pari_timer T; if (!eps) eps = real2n(-prec2nbits(prec)/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); } av2 = avma; for(;; 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); } } /* This file 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. */ /* Return C, C[i][j] = Q[j]^i, i = 1..nb */ static GEN fillstep(GEN Q, long nb) { long i, k, l = lg(Q); GEN C = cgetg(nb+1,t_VEC); gel(C,1) = Q; for (i = 2; i<=nb; ++i) { gel(C,i) = cgetg(l, t_VEC); for (k = 1; kbgbnd = bnd; Q = cgetg(np, t_VEC); for (k = 1; kbaby = 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); } /*Returns lambda_bad list for one prime p, nv = localred(E, p) */ static GEN lambda1(GEN E, GEN nv, GEN p, long prec) { pari_sp av; GEN res, lp; long kod = itos(gel(nv, 2)); if (kod==2 || kod ==-2) return cgetg(1,t_VEC); av = avma; lp = glog(p, prec); if (kod > 4) { long n = Z_pval(ell_get_disc(E), p); long j, m = kod - 4, nl = 1 + (m >> 1L); res = cgetg(nl, t_VEC); for (j = 1; j < nl; j++) 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)); 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)); } return gerepilecopy(av, res); } static GEN lambdalist(GEN E, long prec) { pari_sp ltop = avma; GEN glob = ellglobalred(E), plist = gmael(glob,4,1), L = gel(glob,5); GEN res, v, D = ell_get_disc(E); long i, j, k, l, m, n, np = lg(plist), lr = 1; v = cgetg(np, t_VEC); for (j = 1, i = 1 ; j < np; ++j) { GEN p = gel(plist, j); if (dvdii(D, sqri(p))) { GEN la = lambda1(E, gel(L,j), p, prec); gel(v, i++) = la; lr *= lg(la); } } np = i; res = cgetg(lr+1, t_VEC); gel(res, 1) = gen_0; n = 1; m = 1; for (j = 1; j < np; ++j) { GEN w = gel(v, j); long lw = lg(w); for (k = 1; k <= n; k++) { GEN t = gel(res, k); for (l = 1, m = n; l < lw; l++, m+=n) gel(res, k + m) = mpadd(t, gel(w, l)); } n = m; } return gerepilecopy(ltop, res); } /* P a t_INT or t_FRAC, return its logarithmic height */ static GEN heightQ(GEN P, long prec) { long s; if (typ(P) == t_FRAC) { GEN a = gel(P,1), b = gel(P,2); P = absi_cmp(a,b) > 0 ? a: b; } s = signe(P); if (!s) return real_0(prec); if (s < 0) P = absi(P); return glog(P, prec); } /* t a t_INT or t_FRAC, returns max(1, log |t|), returns a t_REAL */ static GEN logplusQ(GEN t, long prec) { if (typ(t) == t_INT) { if (!signe(t)) return real_1(prec); if (signe(t) < 0) t = absi(t); } else { GEN a = gel(t,1), b = gel(t,2); if (absi_cmp(a, b) < 0) return real_1(prec); if (signe(a) < 0) t = gneg(t); } return glog(t, prec); } /* See GTM239, p532, Th 8.1.18 * Return M such that h_naive <= M */ static GEN hnaive_max(GEN ell, GEN ht) { const long prec = LOWDEFAULTPREC; /* minimal accuracy */ GEN b2 = ell_get_b2(ell), j = ell_get_j(ell); GEN logd = glog(absi(ell_get_disc(ell)), prec); GEN logj = logplusQ(j, prec); 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); } static GEN qfb_root(GEN Q, GEN vDi) { GEN a2 = shifti(gel(Q, 1),1), b = gel(Q, 2); return mkcomplex(gdiv(negi(b),a2),divri(vDi,a2)); } static GEN qimag2(GEN Q) { pari_sp av = avma; GEN z = gdiv(negi(qfb_disc(Q)), shifti(sqri(gel(Q, 1)),2)); return gerepileupto(av, z); } /***************************************************/ /*Routines for increasing the imaginary parts using*/ /*Atkin-Lehner operators */ /***************************************************/ static GEN qfb_mult(GEN Q, GEN M) { GEN A = gel(Q, 1) , B = gel(Q, 2) , C = gel(Q, 3); GEN a = gcoeff(M, 1, 1), b = gcoeff(M, 1, 2); GEN c = gcoeff(M, 2, 1), d = gcoeff(M, 2, 2); GEN W1 = addii(addii(mulii(sqri(a), A), mulii(mulii(c, a), B)), mulii(sqri(c), C)); GEN W2 = addii(addii(mulii(mulii(shifti(b,1), a), A), mulii(addii(mulii(d, a), mulii(c, b)), B)), mulii(mulii(shifti(d,1), c), C)); GEN W3 = addii(addii(mulii(sqri(b), A), mulii(mulii(d, b), B)), mulii(sqri(d), C)); GEN D = gcdii(W1, gcdii(W2, W3)); if (!equali1(D)) { W1 = diviiexact(W1,D); W2 = diviiexact(W2,D); W3 = diviiexact(W3,D); } return qfi(W1, W2, W3); } #ifdef DEBUG static void best_point_old(GEN Q, GEN NQ, GEN f, GEN *u, GEN *v) { long n, k; GEN U, c, d; GEN A = gel(f, 1); GEN B = gel(f, 2); GEN C = gel(f, 3); GEN q = qfi(mulii(NQ, C), negi(B), diviiexact(A, NQ)); redimagsl2(q, &U); *u = c = gcoeff(U, 1, 1); *v = d = gcoeff(U, 2, 1); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; for (n = 1; ; n++) { for (k = -n; k<=n; k++) { *u = addis(c, k); *v = addis(d, n); if (equali1(ggcd(mulii(*u, NQ), mulii(*v, Q)))) return; *v= subis(d, n); if (equali1(ggcd(mulii(*u, NQ), mulii(*v, Q)))) return; *u = addis(c, n); *v = addis(d, k); if (equali1(ggcd(mulii(*u, NQ), mulii(*v, Q)))) return; *u = subis(c, n); if (equali1(ggcd(mulii(*u, NQ), mulii(*v, Q)))) return; } } } /* q(x,y) = ax^2 + bxy + cy^2 */ static GEN qfb_eval(GEN q, GEN x, GEN y) { GEN a = gel(q,1), b = gel(q,2), c = gel(q,3); GEN x2 = sqri(x), y2 = sqri(y), xy = mulii(x,y); return addii(addii(mulii(a, x2), mulii(b,xy)), mulii(c, y2)); } #endif static long nexti(long i) { return i>0 ? -i : 1-i; } /* q0 + i q1 + i^2 q2 */ static GEN qfmin_eval(GEN q0, GEN q1, GEN q2, long i) { return addii(mulis(addii(mulis(q2, i), q1), i), q0); } /* assume a > 0, return gcd(a,b,c) */ static ulong gcduii(ulong a, GEN b, GEN c) { ulong d = a; d = ugcd(umodiu(b, d), d ); if (d == 1) return 1; d = ugcd(umodiu(c, d), d ); return d; } static void best_point(GEN Q, GEN NQ, GEN f, GEN *pu, GEN *pv) { GEN a = mulii(NQ, gel(f,3)), b = negi(gel(f,2)), c = diviiexact(gel(f,1), NQ); GEN D = absi( qfb_disc(f) ); GEN U, qr = redimagsl2(qfi(a,b,c), &U); GEN A = gel(qr,1), B = gel(qr,2), A2 = shifti(A,1), AA4 = sqri(A2); GEN V, best; long y; /* 4A qr(x,y) = (2A x + By)^2 + D y^2 * Write x = x0(y) + i, where x0 is an integer minimum * (the smallest in case of tie) of x-> qr(x,y), for given y. * 4A qr(x,y) = ((2A x0 + By)^2 + Dy^2) + 4A i (2A x0 + By) + 4A^2 i^2 * = q0(y) + q1(y) i + q2 i^2 * Loop through (x,y), y>0 by (roughly) increasing values of qr(x,y) */ /* We must test whether [X,Y]~ := U * [x,y]~ satisfy (X NQ, Y Q) = 1 * This is equivalent to (X,Y) = 1 (note that (X,Y) = (x,y)), and * (X, Q) = (Y, NQ) = 1. * We have U * [x0+i, y]~ = U * [x0,y]~ + i U[,1] =: V0 + i U[,1] */ /* try [1,0]~ = first minimum */ V = gel(U,1); /* U *[1,0]~ */ *pu = gel(V,1); *pv = gel(V,2); if (is_pm1(gcdii(*pu, Q)) && is_pm1(gcdii(*pv, NQ))) return; /* try [0,1]~ = second minimum */ V = gel(U,2); /* U *[0,1]~ */ *pu = gel(V,1); *pv = gel(V,2); if (is_pm1(gcdii(*pu, Q)) && is_pm1(gcdii(*pv, NQ))) return; /* (X,Y) = (1, \pm1) always works. Try to do better now */ best = subii(addii(a, c), absi(b)); *pu = gen_1; *pv = signe(b) < 0? gen_1: gen_m1; for (y = 1;; y++) { GEN Dy2, r, By, x0, q0, q1, V0; long i; if (y > 1) { if (gcduii(y, gcoeff(U,1,1), Q) != 1) continue; if (gcduii(y, gcoeff(U,2,1), NQ) != 1) continue; } Dy2 = mulii(D, sqru(y)); if (cmpii(Dy2, best) >= 0) break; /* we won't improve. STOP */ By = muliu(B,y), x0 = truedvmdii(negi(By), A2, &r); if (cmpii(r, A) >= 0) { x0 = subis(x0,1); r = subii(r, A2); } /* (2A x + By)^2 + Dy^2, minimal at x = x0. Assume A2 > 0 */ /* r = 2A x0 + By */ q0 = addii(sqri(r), Dy2); /* minimal value for this y, at x0 */ if (cmpii(q0, best) >= 0) continue; /* we won't improve for this y */ q1 = shifti(mulii(A2, r), 1); V0 = ZM_ZC_mul(U, mkcol2(x0, utoipos(y))); for (i = 0;; i = nexti(i)) { pari_sp av2 = avma; GEN x, N = qfmin_eval(q0, q1, AA4, i); if (cmpii(N , best) >= 0) break; x = addis(x0, i); if (ugcd(umodiu(x, y), y) == 1) { GEN u, v; V = ZC_add(V0, ZC_z_mul(gel(U,1), i)); /* [X, Y] */ u = gel(V,1); v = gel(V,2); if (is_pm1(gcdii(u, Q)) && is_pm1(gcdii(v, NQ))) { *pu = u; *pv = v; best = N; break; } } avma = av2; } } #ifdef DEBUG { GEN oldu, oldv, F = qfi(a,b,c); best_point_old(Q, NQ, f, &oldu, &oldv); if (!equalii(oldu, *pu) || !equalii(oldv, *pv)) { if (!equali1(gcdii(mulii(*pu, NQ), mulii(*pv, Q)))) pari_err_BUG("best_point (gcd)"); if (cmpii(qfb_eval(F, *pu,*pv), qfb_eval(F, oldu, oldv)) > 0) { pari_warn(warner, "%Ps,%Ps,%Ps, %Ps > %Ps", Q,NQ,f, mkvec2(*pu,*pv), mkvec2(oldu,oldv)); pari_err_BUG("best_point (too large)"); } } } #endif } static GEN best_lift(GEN N, GEN Q, GEN NQ, GEN f) { GEN a,b,c,d,M; best_point(Q, NQ, f, &c, &d); (void)bezout(mulii(d, Q), mulii(NQ, c), &a, &b); M = mkmat2( mkcol2(mulii(d, Q), mulii(negi(N), c)), mkcol2(b, mulii(a, Q))); return qfb_mult(f, M); } static GEN lift_points(GEN N, GEN listQ, GEN f, GEN *pt, GEN *pQ) { pari_sp av = avma; GEN yf = gen_0, tf = NULL, Qf = NULL; long k, l = lg(listQ); for (k = 1; k < l; ++k) { GEN c = gel(listQ, k), Q = gel(c,1), NQ = gel(c,2); GEN t = best_lift(N, Q, NQ, f), y = qimag2(t); if (gcmp(y, yf) > 0) { yf = y; Qf = Q; tf = t; } } gerepileall(av, 3, &tf, &Qf, &yf); *pt = tf; *pQ = Qf; return yf; } /***************************/ /* Twists */ /***************************/ 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,0); } static GEN ltwist1(GEN E, GEN d, long bitprec) { pari_sp av = avma; GEN Ed = twistcurve(E, d); GEN z = ellL1_bitprec(Ed, 0, bitprec); obj_free(Ed); return gerepileuptoleaf(av, z); } /* Return O_re*c(E)/(4*O_vol*|E_t|^2) */ static GEN 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)); } /* omega(gcd(D, N)), given faN = factor(N) */ static long omega_N_D(GEN faN, ulong D) { GEN P = gel(faN, 1); long i, l = lg(P), w = 0; for (i = 1; i < l; i++) if (dvdui(D, gel(P,i))) w++; return w; } static GEN heegner_indexmultD(GEN faN, GEN a, long D, GEN sqrtD) { pari_sp av = avma; GEN c; long w; switch(D) { case -3: w = 9; break; case -4: w = 4; break; default: w = 1; } c = shifti(stoi(w), omega_N_D(faN,-D)); /* (w(D)/2)^2 * 2^omega(gcd(D,N)) */ return gerepileupto(av, mulri(mulrr(a, sqrtD), c)); } static GEN heegner_try_point(GEN E, GEN lambdas, GEN ht, GEN z, long prec) { long l = lg(lambdas); long i, eps; GEN P = greal(pointell(E, z, prec)), x = gel(P,1); GEN rh = subrr(ht, shiftr(ellheightoo(E, P, prec),1)); for (i = 1; i < l; ++i) { GEN logd = shiftr(gsub(rh, gel(lambdas, i)), -1); GEN d, approxd = gexp(logd, prec); if (DEBUGLEVEL > 1) err_printf("Trying lambda number %ld, logd=%Ps, approxd=%Ps\n", i, logd, approxd); d = grndtoi(approxd, &eps); if (signe(d) > 0 && eps<-10) { GEN X, ylist, d2 = sqri(d), approxn = mulir(d2, x); if (DEBUGLEVEL > 1) err_printf("approxn=%Ps eps=%ld\n", approxn,eps); X = gdiv(ground(approxn), d2); ylist = ellordinate(E, X, prec); if (lg(ylist) > 1) { GEN P = mkvec2(X, gel(ylist, 1)); GEN hp = ghell(E,P,prec); if (cmprr(hp, shiftr(ht,1)) < 0 && cmprr(hp, shiftr(ht,-1)) > 0) return P; if (DEBUGLEVEL > 0) err_printf("found non-Heegner point %Ps\n", P); } } } return NULL; } static GEN heegner_find_point(GEN e, GEN om, GEN ht, GEN z1, long k, long prec) { GEN lambdas = lambdalist(e, prec); pari_sp av = avma; long m; GEN Ore = gel(om, 1), Oim = gel(om, 2); for (m = 0; m < k; m++) { GEN P, z2 = divrs(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); if (P) return P; if (signe(ell_get_disc(e)) > 0) { z2 = gadd(z2, gmul2n(Oim, -1)); P = heegner_try_point(e, lambdas, ht, z2, prec); if (P) return P; } avma = av; } pari_err_BUG("ellheegner, point not found"); return NULL; /* NOT REACHED */ } /* N > 1, fa = factor(N), return factor(4*N) */ static GEN fa_shift2(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2); if (equaliu(gcoeff(fa,1,1), 2)) { E = shallowcopy(E); gel(E,1) = addis(gel(E,1), 2); } else { P = shallowconcat(gen_2, P); E = shallowconcat(gen_2, E); } return mkmat2(P, E); } /* P = prime divisors of N(E). Return the product of primes p in P, a_p != -1 * HACK: restrict to small primes since large ones won't divide our C-long * discriminants */ static GEN get_bad(GEN E, GEN P) { long k, l = lg(P), ibad = 1; GEN B = cgetg(l, t_VECSMALL); for (k = 1; k < l; k++) { GEN p = gel(P,k); long pp = itos_or_0(p); if (!pp) break; if (! equalim1(ellap(E,p))) B[ibad++] = pp; } setlg(B, ibad); return ibad == 1? NULL: zv_prod_Z(B); } /* list of pairs [Q,N/Q], where Q | N and gcd(Q,N/Q) = 1 */ static GEN find_div(GEN N, GEN faN) { GEN listQ = divisors(faN); long j, k, l = lg(listQ); gel(listQ, 1) = mkvec2(gen_1, N); for (j = k = 2; k < l; ++k) { GEN Q = gel(listQ, k), NQ = diviiexact(N, Q); if (is_pm1(gcdii(Q,NQ))) gel(listQ, j++) = mkvec2(Q,NQ); } setlg(listQ, j); return listQ; } static long testDisc(GEN bad, long d) { return !bad || ugcd(umodiu(bad, -d), -d) == 1; } /* bad = product of bad primes. Return the NDISC largest fundamental * discriminants D < d such that (D,bad) = 1 and d is a square mod 4N */ static GEN listDisc(GEN fa4N, GEN bad, long d) { const long NDISC = 10; GEN v = cgetg(NDISC+1, t_VECSMALL); pari_sp av = avma; long j = 1; for(;;) { d -= odd(d)? 1: 3; if (testDisc(bad,d) && unegisfundamental(-d) && Zn_issquare(stoi(d), fa4N)) { v[j++] = d; if (j > NDISC) break; } avma = av; } avma = av; return v; } /* L = vector of [q1,q2] or [q1,q2,q2'] * cd = (b^2 - D)/(4N) */ static void listfill(GEN N, GEN b, GEN c, GEN d, GEN L, long *s) { long k, l = lg(L); GEN add, frm2, a = mulii(d, N), V = mkqfi(a,b,c), frm = redimag(V); for (k = 1; k < l; ++k) { /* Lk = [v,frm] or [v,frm,frm2] */ GEN Lk = gel(L,k); long i; for (i = 2; i < lg(Lk); i++) /* 1 or 2 elements */ if (gequal(frm, gel(Lk,i))) { GEN v = gel(Lk, 1); if (cmpii(a, gel(v,1)) < 0) gel(Lk,1) = V; return; } } frm2 = redimag( mkqfi(d, negi(b), mulii(c,N)) ); add = gequal(frm, frm2)? mkvec2(V,frm): mkvec3(V,frm,frm2); vectrunc_append(L, add); *s += lg(add) - 2; } /* faN4 = factor(4*N) */ static GEN listheegner(GEN N, GEN faN4, GEN listQ, GEN D) { 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); long l, k, s = 0; for (k = 0; k < kmin || s < h; k++) { GEN bk = addii(b, mulsi(2*k, N)); GEN C = diviiexact(shifti(subii(sqri(bk), D), -2), N); GEN div = divisors(C); long i, l = lg(div); for (i = 1; i < l; i++) { GEN d = gel(div, i), c = gel(div, l-i); /* cd = C */ listfill(N, bk, c, d, L, &s); } } l = lg(L); ymin = NULL; for (k = 1; k < l; k++) { GEN t, Q, Lk = gel(L,k), f = gel(Lk,1); GEN y = lift_points(N, listQ, f, &t, &Q); gel(L, k) = mkvec3(t, stoi(lg(Lk) - 2), Q); if (!ymin || gcmp(y, ymin) < 0) ymin = y; } return mkvec3(ymin, L, D); } /* Q | N, P = prime divisors of N, R[i] = local epsilon-factor at P[i]. * Return \prod_{p | Q} R[i] */ static long rootno(GEN Q, GEN P, GEN R) { long s = 1, i, l = lg(P); for (i = 1; i < l; i++) if (dvdii(Q, gel(P,i))) s *= R[i]; return s; } static void heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E, GEN indmult, long prec) { long d = 0; GEN faN4, bad, N, faN, listQ, listR; ellQ_get_Nfa(E, &N, &faN); faN4 = fa_shift2(faN); listQ = find_div(N, faN); bad = get_bad(E, gel(faN, 1)); listR = gel(obj_check(E, Q_ROOTNO), 2); for(;;) { pari_sp av = avma; GEN list, listD = listDisc(faN4, bad, d); long k, l = lg(listD); if (DEBUGLEVEL) err_printf("List of discriminants...%Ps\n", listD); list = cgetg(l, t_VEC); for (k = 1; k < l; ++k) gel(list, k) = listheegner(N, faN4, listQ, stoi(listD[k])); list = vecsort0(list, gen_1, 0); for (k = l-1; k > 0; --k) { long bprec = 8; GEN Lk = gel(list,k), D = gel(Lk,3); GEN sqrtD = sqrtr_abs(itor(D, prec)); /* sqrt(|D|) */ GEN indmultD = heegner_indexmultD(faN, indmult, itos(D), sqrtD); do { GEN mulf = ltwist1(E, D, bprec+expo(indmultD)); GEN 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 */ { long e, i, l; GEN pts, cfs, L, indi = grndtoi(sqrtr_abs(indr), &e); if (e > expi(indi)-7) { bprec++; pari_warn(warnprec, "ellL1",bprec); 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); for (i = 1; i < l; ++i) { GEN P = gel(L,i), z = gel(P,2), Q = gel(P,3); /* [1 or 2, Q] */ long c; gel(pts, i) = qfb_root(gel(P,1), sqrtD); c = rootno(Q, gel(faN,1), listR); if (!equali1(z)) c *= 2; cfs[i] = c; } *coefs = cfs; *points = pts; return; } } while(0); } d = listD[l-1]; avma = av; } } static GEN ell_apply_globalred_all(GEN e, GEN *N, GEN *cb, GEN *tam) { GEN E = ellanal_globalred(e, cb), red = obj_check(E, Q_GLOBALRED); *N = gel(red, 1); *tam = gel(red,2); if (signe(ell_get_disc(E))>0) *tam = shifti(*tam,1); return E; } GEN ellheegner(GEN E) { pari_sp av = avma; GEN z, P, ht, points, coefs, ymin, s, om, indmult; long ind, lint, k, l, wtor, etor; long bitprec = 16, prec = nbits2prec(bitprec)+1; pari_timer T; GEN N, cb, tam, torsion; E = ell_apply_globalred_all(E, &N, &cb, &tam); if (ellrootno_global(E) == 1) pari_err_DOMAIN("ellheegner", "(analytic rank)%2","=",gen_0,E); torsion = elltors(E); wtor = itos( gel(torsion,1) ); /* #E(Q)_tor */ etor = wtor > 1? itos(gmael(torsion, 2, 1)): 1; /* exponent of E(Q)_tor */ while (1) { GEN hnaive, l1; long bitneeded; l1 = ellL1_bitprec(E, 1, bitprec); if (expo(l1) < 1 - bitprec/2) pari_err_DOMAIN("ellheegner", "analytic rank",">",gen_1,E); om = ellR_omega(E,prec); ht = divrr(mulru(l1, wtor * wtor), mulri(gel(om,1), tam)); if (DEBUGLEVEL) err_printf("Expected height=%Ps\n", ht); hnaive = hnaive_max(E, ht); if (DEBUGLEVEL) err_printf("Naive height <= %Ps\n", hnaive); bitneeded = itos(gceil(divrr(hnaive, mplog2(prec)))) + 10; if (DEBUGLEVEL) err_printf("precision = %ld\n", bitneeded); if (bitprec>=bitneeded) break; bitprec = bitneeded; 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"); 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))); if (DEBUGLEVEL) err_printf("z=%Ps\n", z); 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 (cb) P = ellchangepointinv(P, cb); return gerepilecopy(av, P); } pari-2.7.5/src/basemath/RgV.c0000644000175000017500000004472612413013142014327 0ustar billbill/* 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" int RgM_is_ZM(GEN x) { long i, j, h, l = lg(x); if (l == 1) return 1; h = lgcols(x); if (h == 1) return 1; for (j = l-1; j > 0; j--) for (i = h-1; i > 0; i--) if (typ(gcoeff(x,i,j)) != t_INT) return 0; return 1; } int RgV_is_ZMV(GEN V) { long i, l = lg(V); for (i=1; i 0). */ static GEN 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; for (i=1; i 0). */ GEN RgM_zm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = RgM_zc_mul_i(x, gel(y,j), l,c); return z; } static GEN RgV_zc_mul_i(GEN x, GEN y, long l) { long i; GEN z = gen_0; pari_sp av = avma; for (i = 1; i < l; i++) z = gadd(z, gmulgs(gel(x,i), y[i])); return gerepileupto(av, z); } GEN RgV_zc_mul(GEN x, GEN y) { return RgV_zc_mul_i(x, y, lg(x)); } GEN RgV_zm_mul(GEN x, GEN y) { long j, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_VEC); for (j = 1; j < ly; j++) gel(z,j) = RgV_zc_mul_i(x, gel(y,j), l); return z; } /* scalar product x.x */ GEN RgV_dotsquare(GEN x) { long i, lx = lg(x); pari_sp av = avma, lim = stack_lim(av,3); GEN z; if (lx == 1) return gen_0; z = gsqr(gel(x,1)); for (i=2; i1) pari_warn(warnmem,"RgV_dotsquare, i = %ld",i); z = gerepileupto(av, z); } } return gerepileupto(av,z); } /* scalar product x.y, lx = lg(x) = lg(y) */ static GEN RgV_dotproduct_i(GEN x, GEN y, long lx) { pari_sp av = avma, lim = stack_lim(av,3); long i; GEN z; if (lx == 1) return gen_0; z = gmul(gel(x,1),gel(y,1)); for (i=2; i1) pari_warn(warnmem,"RgV_dotproduct, i = %ld",i); z = gerepileupto(av, z); } } return gerepileupto(av,z); } GEN RgV_dotproduct(GEN x,GEN y) { if (x == y) return RgV_dotsquare(x); return RgV_dotproduct_i(x, y, lg(x)); } /* v[1] + ... + v[lg(v)-1] */ GEN RgV_sum(GEN v) { GEN p; long i, l = lg(v); if (l == 1) return gen_0; p = gel(v,1); for (i=2; i n. */ GEN RgV_sumpart(GEN v, long n) { GEN p; long i; if (!n) return gen_0; p = gel(v,1); for (i=2; i<=n; i++) p = gadd(p, gel(v,i)); return p; } /* v[m] + ... + v[n]. Assume lg(v) > n, m > 0. */ GEN RgV_sumpart2(GEN v, long m, long n) { GEN p; long i; if (n < m) return gen_0; p = gel(v,m); for (i=m+1; i<=n; i++) p = gadd(p, gel(v,i)); return p; } /* ADDITION SCALAR + MATRIX */ /* x square matrix, y scalar; create the square matrix x + y*Id */ GEN RgM_Rg_add(GEN x, GEN y) { long l = lg(x), i, j; GEN z = cgetg(l,t_MAT); if (l==1) return z; if (l != lgcols(x)) pari_err_OP( "+", x, y); z = cgetg(l,t_MAT); for (i=1; i 1 */ static GEN RgMrow_RgC_mul_i(GEN x, GEN y, long i, long l) { pari_sp av = avma; GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */ long j; for (j=2; j 1, l = lgcols(x) */ static GEN RgM_RgC_mul_i(GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i1 ? lg(gel(x,1))-1:0; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&n,&RgM_algebra,&_RgM_cmul); } GEN RgX_RgM_eval(GEN Q, GEN x) { long n = lg(x)-1; return gen_bkeval(Q,degpol(Q),x,1,(void*)&n,&RgM_algebra,&_RgM_cmul); } GEN RgC_Rg_div(GEN x, GEN y) { long i, lx = lg(x); GEN z = cgetg(lx, t_COL); for (i=1; iisprime) { S->isprime = 1; S->q = p; } if (!equalii(p, S->q)) pari_err_MODULUS("characteristic", S->q, p); } static void char_update_int(struct charact *S, GEN n) { if (S->isprime) { if (dvdii(n, S->q)) return; pari_err_MODULUS("characteristic", S->q, n); } S->q = gcdii(S->q, n); } static void charact(struct charact *S, GEN x) { const long tx = typ(x); long i, l; switch(tx) { case t_INTMOD:char_update_int(S, gel(x,1)); break; case t_FFELT: char_update_prime(S, gel(x,4)); break; case t_COMPLEX: case t_QUAD: case t_POLMOD: case t_POL: case t_SER: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: l = lg(x); for (i=lontyp[tx]; i < l; i++) charact(S,gel(x,i)); break; case t_LIST: x = list_data(x); if (x) charact(S, x); break; } } static void charact_res(struct charact *S, GEN x) { const long tx = typ(x); long i, l; switch(tx) { case t_INTMOD:char_update_int(S, gel(x,1)); break; case t_FFELT: char_update_prime(S, gel(x,4)); break; case t_PADIC: char_update_prime(S, gel(x,2)); break; case t_COMPLEX: case t_QUAD: case t_POLMOD: case t_POL: case t_SER: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: l = lg(x); for (i=lontyp[tx]; i < l; i++) charact_res(S,gel(x,i)); break; case t_LIST: x = list_data(x); if (x) charact_res(S, x); break; } } GEN characteristic(GEN x) { struct charact S; S.q = gen_0; S.isprime = 0; charact(&S, x); return S.q; } GEN residual_characteristic(GEN x) { struct charact S; S.q = gen_0; S.isprime = 0; charact_res(&S, x); return S.q; } int Rg_is_Fp(GEN x, GEN *pp) { GEN mod; switch(typ(x)) { case t_INTMOD: mod = gel(x,1); if (!*pp) *pp = mod; else if (mod != *pp && !equalii(mod, *pp)) { if (DEBUGMEM) pari_warn(warner,"different moduli in Rg_is_Fp"); return 0; } return 1; case t_INT: return 1; default: return 0; } } int RgX_is_FpX(GEN x, GEN *pp) { long i, lx = lg(x); for (i=2; i 0 a t_INT, return lift(x * Mod(1,p)). * If x is an INTMOD, assume modulus is a multiple of p. */ GEN Rg_to_Fp(GEN x, GEN p) { if (lgefint(p) == 3) return utoi(Rg_to_Fl(x, (ulong)p[2])); switch(typ(x)) { case t_INT: return modii(x, p); case t_FRAC: { pari_sp av = avma; GEN z = modii(gel(x,1), p); if (z == gen_0) return gen_0; return gerepileuptoint(av, remii(mulii(z, Fp_inv(gel(x,2), p)), p)); } case t_PADIC: return padic_to_Fp(x, p); case t_INTMOD: { GEN q = gel(x,1), a = gel(x,2); if (equalii(q, p)) return icopy(a); if (!dvdii(q,p)) pari_err_MODULUS("Rg_to_Fp", q, p); return remii(a, p); } default: pari_err_TYPE("Rg_to_Fp",x); return NULL; /* not reached */ } } /* If x is a POLMOD, assume modulus is a multiple of T. */ GEN Rg_to_FpXQ(GEN x, GEN T, GEN p) { long ta, tx = typ(x), v = varn(T); GEN a, b; if (is_const_t(tx)) { if (tx == t_FFELT) return FF_to_FpXQ(x); return scalar_ZX(Rg_to_Fp(x, p), v); } switch(tx) { case t_POLMOD: b = gel(x,1); 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; return FpX_rem(a, T, p); case t_POL: if (varn(x) != v) break; return FpX_rem(RgX_to_FpX(x,p), T, p); case t_RFRAC: a = Rg_to_FpXQ(gel(x,1), T,p); b = Rg_to_FpXQ(gel(x,2), T,p); return FpXQ_div(a,b, T,p); } pari_err_TYPE("Rg_to_FpXQ",x); return NULL; /* not reached */ } GEN RgX_to_FpX(GEN x, GEN p) { long i, l; GEN z = cgetg_copy(x, &l); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return FpX_renormalize(z, l); } GEN RgV_to_FpV(GEN x, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return z; } GEN RgC_to_FpC(GEN x, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_COL); for (i = 1; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return z; } GEN RgM_to_FpM(GEN x, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(z,i) = RgC_to_FpC(gel(x,i), p); return z; } GEN RgC_to_Flc(GEN x, ulong p) { long l = lg(x), i; GEN a = cgetg(l, t_VECSMALL); for (i=1; i 1 */ GEN FpXV_FpC_mul(GEN V, GEN W, GEN p) { pari_sp av = avma; long i, l = lg(V); GEN z = ZX_Z_mul(gel(V,1),gel(W,1)); for(i=2; i 3) /* non-constant */ return FqX_Fq_mul_to_monic(z, Fq_inv(lc,T,p), T,p); /* constant */ lc = gel(lc,2); z = shallowcopy(z); gel(z, lg(z)-1) = lc; } /* lc a t_INT */ if (equali1(lc)) return z; return FqX_Fq_mul_to_monic(z, Fp_inv(lc,p), T,p); } GEN FqX_eval(GEN x, GEN y, GEN T, GEN p) { pari_sp av; GEN p1, r; long j, i=lg(x)-1; if (i<=2) return (i==2)? Fq_red(gel(x,2), T, p): gen_0; av=avma; p1=gel(x,i); /* specific attention to sparse polynomials (see poleval)*/ /*You've guessed it! It's a copy-paste(tm)*/ for (i--; i>=2; i=j-1) { for (j=i; !signe(gel(x,j)); j--) if (j==2) { if (i!=j) y = Fq_pow(y,utoipos(i-j+1), T, p); return gerepileupto(av, Fq_mul(p1,y, T, p)); } r = (i==j)? y: Fq_pow(y, utoipos(i-j+1), T, p); p1 = Fq_add(Fq_mul(p1,r,T,p), gel(x,j), T, p); } return gerepileupto(av, p1); } GEN FqXY_evalx(GEN Q, GEN x, GEN T, GEN p) { long i, lb = lg(Q); GEN z; if (!T) return FpXY_evalx(Q, x, p); z = cgetg(lb, t_POL); z[1] = Q[1]; for (i=2; i same number of solutions if Fp and F_{p^d} */ if (equalii(gcdii(subiu(p,1),n), gcdii(subiu(Fp_powu(p,d,n), 1), n))) return Fp_sqrtn(x,n,p,zeta); } } x = scalarpol_shallow(x, get_FpX_var(T)); } return FpXQ_sqrtn(x,n,T,p,zeta); } struct _Fq_field { GEN T, p; }; static GEN _Fq_red(void *E, GEN x) { struct _Fq_field *s = (struct _Fq_field *)E; return Fq_red(x, s->T, s->p); } static GEN _Fq_add(void *E, GEN x, GEN y) { (void) E; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return addii(x,y); case 1: return ZX_Z_add(x,y); case 2: return ZX_Z_add(y,x); default: return ZX_add(x,y); } } static GEN _Fq_neg(void *E, GEN x) { (void) E; return typ(x)==t_POL?ZX_neg(x):negi(x); } static GEN _Fq_mul(void *E, GEN x, GEN y) { (void) E; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return mulii(x,y); case 1: return ZX_Z_mul(x,y); case 2: return ZX_Z_mul(y,x); default: return ZX_mul(x,y); } } static GEN _Fq_inv(void *E, GEN x) { struct _Fq_field *s = (struct _Fq_field *)E; return Fq_inv(x,s->T,s->p); } static int _Fq_equal0(GEN x) { return signe(x)==0; } static GEN _Fq_s(void *E, long x) { (void) E; return stoi(x); } static const struct bb_field Fq_field={_Fq_red,_Fq_add,_Fq_mul,_Fq_neg, _Fq_inv,_Fq_equal0,_Fq_s}; const struct bb_field *get_Fq_field(void **E, GEN T, GEN p) { GEN z = new_chunk(sizeof(struct _Fq_field)); struct _Fq_field *e = (struct _Fq_field *) z; e->T = T; e->p = p; *E = (void*)e; return &Fq_field; } /*******************************************************************/ /* */ /* Fq[X] */ /* */ /*******************************************************************/ /* P(X + c) */ GEN FpX_translate(GEN P, GEN c, GEN p) { pari_sp av = avma, lim; 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; k1) pari_warn(warnmem,"FpX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } return gerepilecopy(av, FpX_renormalize(Q, lg(Q))); } /* P(X + c), c an Fq */ GEN FqX_translate(GEN P, GEN c, GEN T, GEN p) { pari_sp av = avma, lim; GEN Q, *R; long i, k, n; /* signe works for t_(INT|POL) */ 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; k1) pari_warn(warnmem,"FqX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } return gerepilecopy(av, FpXQX_renormalize(Q, lg(Q))); } GEN FqV_roots_to_pol(GEN V, GEN T, GEN p, long v) { pari_sp ltop = avma; long k; GEN W; if (lgefint(p) == 3) { ulong pp = p[2]; GEN Tl = ZX_to_Flx(T, pp); GEN Vl = FqV_to_FlxV(V, T, p); Tl = FlxqV_roots_to_pol(Vl, Tl, pp, v); return gerepileupto(ltop, FlxX_to_ZXX(Tl)); } W = cgetg(lg(V),t_VEC); for(k=1; k < lg(V); k++) gel(W,k) = deg1pol_shallow(gen_1,Fq_neg(gel(V,k),T,p),v); return gerepileupto(ltop, FpXQXV_prod(W, T, p)); } GEN FqV_red(GEN z, GEN T, GEN p) { long i, l = lg(z); GEN res = cgetg(l, typ(z)); for(i=1;i=4) timer_start(&T); V = Flm_Frobenius(MA, r, p, U[1]); if (DEBUGLEVEL>=4) timer_printf(&T,"pol[Frobenius]"); M = FlxqV_Flx_Frobenius(V, U, P, p); if (p==2) A = F2m_to_Flm(F2m_ker(Flm_to_F2m(M))); else A = Flm_ker(M,p); if (DEBUGLEVEL>=4) timer_printf(&T,"matrix polcyclo"); if (lg(A)!=r+1) pari_err_IRREDPOL("FpX_ffintersect", Flx_to_ZX(P)); A = gerepileupto(ltop,A); /*The formula is * a_{r-1} = -\phi(a_0)/b_0 * a_{i-1} = \phi(a_i)+b_ia_{r-1} i=r-1 to 1 * Where a_0=A[1] and b_i=U[i+2] */ ib0 = Fl_inv(Fl_neg(U[2], p), p); R = cgetg(r+1,t_MAT); 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); return gerepileupto(ltop, Flm_to_FlxX(Flm_transpose(R),vp,vu)); } static GEN FpX_intersect_ker(GEN P, GEN MA, GEN U, GEN l) { pari_sp ltop = avma; long i, vp = varn(P), vu = varn(U), r = degpol(U); GEN V, A, R, ib0; pari_timer T; if (lgefint(l)==3) { ulong p = l[2]; GEN res = Flx_intersect_ker(ZX_to_Flx(P,p), ZM_to_Flm(MA,p), ZX_to_Flx(U,p), p); return gerepileupto(ltop, FlxX_to_ZXX(res)); } if (DEBUGLEVEL>=4) timer_start(&T); V = FpM_Frobenius(MA,r,l,vu); if (DEBUGLEVEL>=4) timer_printf(&T,"pol[Frobenius]"); A = FpM_ker(FpXQV_FpX_Frobenius(V, U, P, l), l); if (DEBUGLEVEL>=4) timer_printf(&T,"matrix polcyclo"); if (lg(A)!=r+1) pari_err_IRREDPOL("FpX_ffintersect", P); A = gerepileupto(ltop,A); /*The formula is * a_{r-1} = -\phi(a_0)/b_0 * a_{i-1} = \phi(a_i)+b_ia_{r-1} i=r-1 to 1 * Where a_0=A[1] and b_i=U[i+2] */ ib0 = Fp_inv(negi(gel(U,2)),l); R = cgetg(r+1,t_MAT); gel(R,1) = gel(A,1); gel(R,r) = FpM_FpC_mul(MA, FpC_Fp_mul(gel(A,1),ib0,l), l); for(i=r-1;i>1;i--) gel(R,i) = FpC_add(FpM_FpC_mul(MA,gel(R,i+1),l), FpC_Fp_mul(gel(R,r), gel(U,i+2), l),l); return gerepilecopy(ltop,RgM_to_RgXX(shallowtrans(R),vp,vu)); } /* n must divide both the degree of P and Q. Compute SP and SQ such that the subfield of FF_l[X]/(P) generated by SP and the subfield of FF_l[X]/(Q) generated by SQ are isomorphic of degree n. P and Q do not need to be of the same variable. if MA (resp. MB) is not NULL, must be the matrix of the Frobenius map in FF_l[X]/(P) (resp. FF_l[X]/(Q) ). */ /* Note on the implementation choice: * We assume the prime p is very large * so we handle Frobenius as matrices. */ void Flx_ffintersect(GEN P, GEN Q, long n, ulong l,GEN *SP, GEN *SQ, GEN MA, GEN MB) { pari_sp ltop = avma; long vp = P[1], vq = Q[1], np = degpol(P), nq = degpol(Q), e; ulong pg; GEN A, B, Ap, Bp; if (np<=0) pari_err_IRREDPOL("FpX_ffintersect", P); if (nq<=0) pari_err_IRREDPOL("FpX_ffintersect", Q); 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); A = Ap = pol0_Flx(vp); B = Bp = pol0_Flx(vq); if (pg > 1) { pari_timer T; GEN ipg = utoipos(pg); if (l%pg == 1) /* No need to use relative extension, so don't. (Well, now we don't * in the other case either, but this special case is more efficient) */ { GEN L; ulong z, An, Bn; z = Fl_neg(rootsof1_Fl(pg, l), l); if (DEBUGLEVEL>=4) timer_start(&T); A = Flm_ker(Flm_Fl_add(MA, z, l),l); if (lg(A)!=2) pari_err_IRREDPOL("FpX_ffintersect",P); A = Flv_to_Flx(gel(A,1),vp); B = Flm_ker(Flm_Fl_add(MB, z, l),l); if (lg(B)!=2) pari_err_IRREDPOL("FpX_ffintersect",Q); B = Flv_to_Flx(gel(B,1),vq); if (DEBUGLEVEL>=4) timer_printf(&T, "FpM_ker"); An = Flxq_powu(A,pg,P,l)[2]; Bn = Flxq_powu(B,pg,Q,l)[2]; if (!Bn) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fl_div(An,Bn,l); L = Fp_sqrtn(utoi(z),ipg,utoipos(l),NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T, "Fp_sqrtn"); B = Flx_Fl_mul(B,itou(L),l); } else { GEN L, An, Bn, z, U; U = gmael(Flx_factor(ZX_to_Flx(polcyclo(pg,MAXVARN),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); An = gel(FlxYqq_pow(A,ipg,P,U,l),2); Bn = gel(FlxYqq_pow(B,ipg,Q,U,l),2); if (DEBUGLEVEL>=4) timer_printf(&T,"pows [P,Q]"); z = Flxq_div(An,Bn,U,l); L = Flxq_sqrtn(z,ipg,U,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T,"FpXQ_sqrtn"); B = FlxqX_Flxq_mul(B,L,U,l); A = FlxY_evalx(A,0,l); B = FlxY_evalx(B,0,l); } } if (e) { GEN VP, VQ, Ay, By; ulong lmun = l-1; long j; MA = Flm_Fl_add(MA,lmun,l); MB = Flm_Fl_add(MB,lmun,l); Ay = pol1_Flx(vp); By = pol1_Flx(vq); VP = vecsmall_ei(np, 1); VQ = np == nq? VP: vecsmall_ei(nq, 1); /* save memory */ for(j=0;j 1) { GEN ipg = utoipos(pg); pari_timer T; if (umodiu(l,pg) == 1) /* No need to use relative extension, so don't. (Well, now we don't * in the other case either, but this special case is more efficient) */ { GEN L, An, Bn, z; z = negi( rootsof1u_Fp(pg, l) ); if (DEBUGLEVEL>=4) timer_start(&T); A = FpM_ker(RgM_Rg_add_shallow(MA, z),l); if (lg(A)!=2) pari_err_IRREDPOL("FpX_ffintersect",P); A = RgV_to_RgX(gel(A,1),vp); B = FpM_ker(RgM_Rg_add_shallow(MB, z),l); if (lg(B)!=2) pari_err_IRREDPOL("FpX_ffintersect",Q); B = RgV_to_RgX(gel(B,1),vq); if (DEBUGLEVEL>=4) timer_printf(&T, "FpM_ker"); An = gel(FpXQ_pow(A,ipg,P,l),2); Bn = gel(FpXQ_pow(B,ipg,Q,l),2); if (!signe(Bn)) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fp_div(An,Bn,l); L = Fp_sqrtn(z,ipg,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T, "Fp_sqrtn"); B = FpX_Fp_mul(B,L,l); } else { GEN L, An, Bn, z, U; U = gmael(FpX_factor(polcyclo(pg,MAXVARN),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); An = gel(FpXYQQ_pow(A,ipg,P,U,l),2); Bn = gel(FpXYQQ_pow(B,ipg,Q,U,l),2); if (DEBUGLEVEL>=4) timer_printf(&T,"pows [P,Q]"); if (!signe(Bn)) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fq_div(An,Bn,U,l); L = Fq_sqrtn(z,ipg,U,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T,"FpXQ_sqrtn"); B = FqX_Fq_mul(B,L,U,l); A = FpXY_evalx(A,gen_0,l); B = FpXY_evalx(B,gen_0,l); } } if (e) { GEN VP, VQ, Ay, By, lmun = addis(l,-1); long j; MA = RgM_Rg_add_shallow(MA,gen_m1); MB = RgM_Rg_add_shallow(MB,gen_m1); Ay = pol_1(vp); By = pol_1(vq); VP = col_ei(np, 1); VQ = np == nq? VP: col_ei(nq, 1); /* save memory */ for(j=0;j amod)? b - amod: p - (amod - b); /* (b - a) mod p */ (void)new_chunk(lgefint(pq)<<1); /* HACK */ ax = mului(Fl_mul(d,qinv,p), q); /* d mod p, 0 mod q */ avma = av; return addii(a, ax); /* in ]-q, pq[ assuming a in -]-q,q[ */ } GEN Z_init_CRT(ulong Hp, ulong p) { return stoi(Fl_center(Hp, p, p>>1)); } GEN ZX_init_CRT(GEN Hp, ulong p, long v) { long i, l = lg(Hp), lim = (long)(p>>1); GEN H = cgetg(l, t_POL); H[1] = evalsigne(1) | evalvarn(v); for (i=2; i 1 */ GEN ZM_init_CRT(GEN Hp, ulong p) { long i,j, m = lgcols(Hp), l = lg(Hp), lim = (long)(p>>1); GEN c,cp,H = cgetg(l, t_MAT); for (j=1; j 0) h = subii(h,qp); *H = h; stable = 0; } *ptq = qp; return stable; } static int ZX_incremental_CRT_raw(GEN *ptH, GEN Hp, GEN q, GEN qp, ulong p) { GEN H = *ptH, h, lim = shifti(qp,-1); ulong qinv = Fl_inv(umodiu(q,p), p); long i, l = lg(H), lp = lg(Hp); int stable = 1; if (l < lp) { /* degree increases */ GEN x = cgetg(lp, t_POL); for (i=1; i lp) { /* degree decreases */ GEN x = cgetg(l, t_VECSMALL); for (i=1; i 0) h = subii(h,qp); gel(H,i) = h; stable = 0; } } return stable; } int ZX_incremental_CRT(GEN *ptH, GEN Hp, GEN *ptq, ulong p) { GEN q = *ptq, qp = muliu(q,p); int stable = ZX_incremental_CRT_raw(ptH, Hp, q, qp, p); *ptq = qp; return stable; } int ZM_incremental_CRT(GEN *pH, GEN Hp, GEN *ptq, ulong p) { GEN h, H = *pH, q = *ptq, qp = muliu(q, p), lim = shifti(qp,-1); ulong qinv = Fl_inv(umodiu(q,p), p); long i,j, l = lg(H), m = lgcols(H); int stable = 1; for (j=1; j 0) h = subii(h,qp); gcoeff(H,i,j) = h; stable = 0; } } *ptq = qp; return stable; } /* record the degrees of Euclidean remainders (make them as large as * possible : smaller values correspond to a degenerate sequence) */ 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); if (lgpol(a)==0 || lgpol(b)==0) return; da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); } else if (!da) return; ind = 0; while (db) { GEN c = Flx_rem(a,b, p); a = b; b = c; dc = degpol(c); if (dc < 0) break; ind++; if (dc > dglist[ind]) dglist[ind] = dc; if (low_stack(lim,stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all"); gerepileall(av, 2, &a,&b); } db = dc; /* = degpol(b) */ } if (ind+1 > lg(dglist)) setlg(dglist,ind+1); avma = av; return; } /* assuming the PRS finishes on a degree 1 polynomial C0 + C1X, with * "generic" degree sequence as given by dglist, set *Ci and return * resultant(a,b). Modular version of Collins's subresultant */ static ulong 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); *C0 = 1; *C1 = 0; if (lgpol(a)==0 || lgpol(b)==0) return 0; da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); if (both_odd(da,db)) s = -s; } else if (!da) return 1; /* = a[2] ^ db, since 0 <= db <= da = 0 */ ind = 0; while (db) { /* sub-resultant algo., applied to ca * a and cb * b, ca,cb scalars, * da = deg a, db = deg b */ GEN c = Flx_rem(a,b, p); long delta = da - db; if (both_odd(da,db)) s = -s; lb = Fl_mul(b[db+2], cb, p); a = b; b = c; dc = degpol(c); ind++; if (dc != dglist[ind]) { avma = av; return 0; } /* degenerates */ if (g == h) { /* frequent */ ulong cc = Fl_mul(ca, Fl_powu(Fl_div(lb,g,p), delta+1, p), p); ca = cb; cb = cc; } else { ulong cc = Fl_mul(ca, Fl_powu(lb, delta+1, p), p); ulong ghdelta = Fl_mul(g, Fl_powu(h, delta, p), p); ca = cb; cb = Fl_div(cc, ghdelta, p); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ g = lb; if (delta == 1) h = g; /* frequent */ else h = Fl_mul(h, Fl_powu(Fl_div(g,h,p), delta, p), p); if (low_stack(lim,stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all"); gerepileall(av, 2, &a,&b); } } if (da > 1) return 0; /* Failure */ /* last non-constant polynomial has degree 1 */ *C0 = Fl_mul(ca, a[2], p); *C1 = Fl_mul(ca, a[3], p); res = Fl_mul(cb, b[2], p); if (s == -1) res = p - res; avma = av; return res; } /* u P(X) + v P(-X) */ static GEN pol_comp(GEN P, GEN u, GEN v) { long i, l = lg(P); GEN y = cgetg(l, t_POL); for (i=2; i1) pari_warn(warnmem,"polint_triv2 (i = %ld)",i); P = gerepileupto(av, P); } } return P? P: pol_0(0); } GEN 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); for (i=1; i1) pari_warn(warnmem,"FpV_polint"); P = gerepileupto(av, P); } } return P? P: pol_0(v); } static void Flv_polint_all(GEN xa, GEN ya, GEN C0, GEN C1, ulong p, GEN *pHp, GEN *pH0p, GEN *pH1p) { GEN T,Q = Flv_roots_to_pol(xa, p, 0); GEN dP = NULL, P = NULL; GEN dP0 = NULL, P0= NULL; GEN dP1 = NULL, P1= NULL; long i, n = lg(xa); ulong inv; for (i=1; i=2; i--) { GEN c = gel(Q,i); z = FqX_Fq_mul(z, y, T, p); z = typ(c) == t_INT? FqX_Fq_add(z,c,T,p): FqX_add(z,c,T,p); } return gerepileupto(av, z); } static GEN ZX_norml1(GEN x) { long i, l = lg(x); GEN s; if (l == 2) return gen_0; s = gel(x, l-1); /* != 0 */ for (i = l-2; i > 1; i--) { GEN xi = gel(x,i); if (!signe(x)) continue; s = addii_sign(s,1, xi,1); } return s; } /* Interpolate at roots of 1 and use Hadamard bound for univariate resultant: * bound = N_2(A)^degpol B N_2(B)^degpol(A), where * N_2(A) = sqrt(sum (N_1(Ai))^2) * Return e such that Res(A, B) < 2^e */ ulong ZX_ZXY_ResBound(GEN A, GEN B, GEN dB) { pari_sp av = avma; GEN a = gen_0, b = gen_0; long i , lA = lg(A), lB = lg(B); double loga, logb; for (i=2; i= 0 && lg(gel(x,0))==2); if (dx < dy) break; if (low_stack(lim,stack_lim(av2,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"FlxX_pseudorem dx = %ld >= %ld",dx,dy); gerepilecoeffs(av2,x,dx+1); } } if (dx < 0) return zero_Flx(0); lx = dx+3; x -= 2; x[0]=evaltyp(t_POL) | evallg(lx); x[1]=evalsigne(1) | evalvarn(vx); 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); for (i=2; i1) 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 (signh < 0) z = Flx_neg(z,p); return gerepileupto(av, z); } /* Warning: * This function switches between valid and invalid variable ordering*/ static GEN FlxY_to_FlyX(GEN b, long sv) { long i, n=-1; long sw = b[1]&VARNBITS; for(i=2;i= pp) z = FlxX_resultant(Fly_to_FlxY(a, sy), b, pp, sx); else z = Flx_FlyX_resultant_polint(a, b, pp, (ulong)dres, sy); return gerepileupto(ltop,z); } /* return a t_POL (in variable v >= 0) whose coeffs are the coeffs of b, * in variable v. This is an incorrect PARI object if initially varn(b) << v. * We could return a vector of coeffs, but it is convenient to have degpol() * and friends available. Even in that case, it will behave nicely with all * functions treating a polynomial as a vector of coeffs (eg poleval). * FOR INTERNAL USE! */ GEN swap_vars(GEN b0, long v) { long i, n = RgX_degree(b0, v); GEN b, x; if (n < 0) return pol_0(v); b = cgetg(n+3, t_POL); x = b + 2; b[1] = evalsigne(1) | evalvarn(v); for (i=0; i<=n; i++) gel(x,i) = polcoeff_i(b0, i, v); return b; } /* assume varn(b) << varn(a) */ /* return a FpY*/ GEN FpX_FpXY_resultant(GEN a, GEN b, GEN p) { long i,n,dres, vX = varn(b), vY = varn(a); GEN la,x,y; if (lgefint(p) == 3) { ulong pp = (ulong)p[2]; b = ZXX_to_FlxX(b, pp, vY); 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); la = leading_term(a); x = cgetg(dres+2, t_VEC); y = cgetg(dres+2, t_VEC); /* Evaluate at dres+ 1 points: 0 (if dres even) and +/- n, so that P_n(X) = * P_{-n}(-X), where P_i is Lagrange polynomial: P_i(j) = delta_{i,j} */ 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(x,++i) = subis(p,n); gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la); } if (i == dres) { gel(x,++i) = gen_0; gel(y,i) = FpX_FpXY_eval_resultant(a,b, gel(x,i), p,la); } return FpV_polint(x,y, p, vX); } GEN 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); } /* 0, 1, -1, 2, -2, ... */ #define next_lambda(a) (a>0 ? -a : 1-a) GEN 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); for (k = 1;; k = next_lambda(k)) { GEN x = deg1pol_shallow(gen_1, gmulsg(k, pol_x(MAXVARN)), 0); /* x + k y */ GEN C = FpX_FpXY_resultant(a, poleval(b,x),p); if (FpX_is_squarefree(C, p)) return C; } } #if 0 /* Return x such that theta(x) - theta(27448) >= ln(2)*bound */ /* NB: theta(27449) ~ 27225.387, theta(x) > 0.98 x for x>7481 * (Schoenfeld, 1976 for x > 1155901 + direct calculations) */ static ulong get_theta_x(ulong bound) { return (ulong)ceil((bound * LOG2 + 27225.388) / 0.98); } #endif /* 27449 = prime(3000) */ void init_modular(forprime_t *S) { u_forprime_init(S, 27449, ULONG_MAX); } /* Assume A in Z[Y], B in Q[Y][X], and Res_Y(A, B) in Z[X]. * If lambda = NULL, return Res_Y(A,B). * Otherwise, find a small lambda (start from *lambda, use the sequence above) * such that R(X) = Res_Y(A(Y), B(X + lambda Y)) is squarefree, reset *lambda * to the chosen value and return R * * If LERS is non-NULL, set it to the Last non-constant polynomial in the * Euclidean Remainder Sequence */ GEN ZX_ZXY_resultant_all(GEN A, GEN B0, long *plambda, GEN *LERS) { int checksqfree = plambda? 1: 0, delvar = 0, stable; long lambda = plambda? *plambda: 0, cnt = 0; ulong bound, p, dp; pari_sp av = avma, av2 = 0, lim; long i,n, lb, degA = degpol(A), dres = degA*degpol(B0); long vX = varn(B0), vY = varn(A); /* assume vX << vY */ 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; dglist = Hp = H0p = H1p = C0 = C1 = NULL; /* gcc -Wall */ if (LERS) { if (!checksqfree) pari_err_BUG("ZX_ZXY_resultant_all [LERS != NULL needs lambda]"); C0 = cgetg(dres+2, t_VECSMALL); C1 = cgetg(dres+2, t_VECSMALL); dglist = cgetg(dres+1, t_VECSMALL); } 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); /* make sure p large enough */ u_forprime_init(&S, maxuu(dres << 1, 27499), ULONG_MAX); INIT: /* allways 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 (degA <= 3) { /* sub-resultant faster for small degrees */ if (LERS) { /* implies checksqfree */ H = resultant_all(A,B,&q); if (typ(q) != t_POL || degpol(q)!=1) goto INIT; H0 = gel(q,2); if (typ(H0) == t_POL) setvarn(H0,vX); else H0 = scalarpol(H0,vX); H1 = gel(q,3); if (typ(H1) == t_POL) setvarn(H1,vX); else H1 = scalarpol(H1,vX); } else H = resultant(A,B); if (checksqfree && !ZX_is_squarefree(H)) goto INIT; goto END; } H = H0 = H1 = NULL; lb = lg(B); 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))) { if (dB) { dp = smodis(dB, p); if (!dp) continue; } a = ZX_to_Flx(A, p); b = ZXX_to_FlxX(B, p, varn(A)); if (LERS) { if (degpol(a) < degA || lg(b) < lb) continue; /* p | lc(A)lc(B) */ if (checksqfree) { /* find degree list for generic Euclidean Remainder Sequence */ long goal = minss(degpol(a), degpol(b)); /* longest possible */ for (n=1; n <= goal; n++) dglist[n] = 0; setlg(dglist, 1); for (n=0; n <= dres; n++) { ev = FlxY_evalx_drop(b, n, p); Flx_resultant_set_dglist(a, ev, dglist, p); if (lg(dglist)-1 == goal) break; } /* last pol in ERS has degree > 1 ? */ goal = lg(dglist)-1; if (degpol(B) == 1) { if (!goal) goto INIT; } else { if (goal <= 1) goto INIT; if (dglist[goal] != 0 || dglist[goal-1] != 1) goto INIT; } if (DEBUGLEVEL>4) err_printf("Degree list for ERS (trials: %ld) = %Ps\n",n+1,dglist); } for (i=0,n = 0; i <= dres; n++) { ev = FlxY_evalx_drop(b, n, p); x[++i] = n; y[i] = Flx_resultant_all(a, ev, C0+i, C1+i, dglist, p); if (!C1[i]) i--; /* C1(i) = 0. No way to recover C0(i) */ } Flv_polint_all(x,y,C0,C1, p, &Hp, &H0p, &H1p); } else { long dropa = degA - degpol(a), dropb = lb - lg(b); Hp = Flx_FlyX_resultant_polint(a, b, p, (ulong)dres, sX); if (dropa && dropb) Hp = zero_Flx(sX); else { if (dropa) { /* multiply by ((-1)^deg B lc(B))^(deg A - deg a) */ 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); if (!Flx_equal1(c)) Hp = Flx_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 = Flx_Fl_mul(Hp, c, p); } } } if (!H && degpol(Hp) != dres) continue; if (dp != 1) Hp = Flx_Fl_mul(Hp, Fl_powu(Fl_inv(dp,p), degA, p), p); if (checksqfree) { if (!Flx_is_squarefree(Hp, p)) goto INIT; if (DEBUGLEVEL>4) err_printf("Final lambda = %ld\n", lambda); checksqfree = 0; } if (!H) { /* initialize */ q = utoipos(p); stable = 0; H = ZX_init_CRT(Hp, p,vX); if (LERS) { H0= ZX_init_CRT(H0p, p,vX); H1= ZX_init_CRT(H1p, p,vX); } } else { if (LERS) { GEN qp = muliu(q,p); stable = ZX_incremental_CRT_raw(&H, Hp, q,qp, p) & ZX_incremental_CRT_raw(&H0,H0p, q,qp, p) & ZX_incremental_CRT_raw(&H1,H1p, q,qp, p); q = qp; } else stable = ZX_incremental_CRT(&H, Hp, &q, p); } /* could make it probabilistic for H ? [e.g if stable twice, etc] * Probabilistic anyway for H0, H1 */ 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 (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(); if (plambda) *plambda = lambda; if (LERS) { *LERS = mkvec2(H0,H1); gerepileall(av, 2, &H, LERS); return H; } return gerepilecopy(av, H); } GEN ZX_ZXY_rnfequation(GEN A, GEN B, long *lambda) { return ZX_ZXY_resultant_all(A, B, lambda, NULL); } /* If lambda = NULL, return caract(Mod(A, T)), T,A in Z[X]. * Otherwise find a small lambda such that caract (Mod(A + lambda X, T)) is * squarefree */ GEN ZXQ_charpoly_sqf(GEN A, GEN T, long *lambda, long v) { pari_sp av = avma; GEN R, a; long dA; int delvar; if (v < 0) v = 0; switch (typ(A)) { case t_POL: dA = degpol(A); if (dA > 0) break; A = dA? gel(A,2): gen_0; /* fall through */ default: if (lambda) { A = scalar_ZX_shallow(A,varn(T)); dA = 0; break;} return gerepileupto(av, gpowgs(gsub(pol_x(v), A), degpol(T))); } delvar = 0; if (varn(T) == 0) { long v0 = fetch_var(); delvar = 1; T = leafcopy(T); setvarn(T,v0); A = leafcopy(A); setvarn(A,v0); } R = ZX_ZXY_rnfequation(T, deg1pol_shallow(gen_1, gneg_i(A), 0), lambda); if (delvar) (void)delete_var(); setvarn(R, v); a = leading_term(T); if (!gequal1(a)) R = gdiv(R, powiu(a, dA)); return gerepileupto(av, R); } /* charpoly(Mod(A,T)), A may be in Q[X], but assume T and result are integral */ GEN ZXQ_charpoly(GEN A, GEN T, long v) { return (degpol(T) < 16) ? RgXQ_charpoly(A,T,v): ZXQ_charpoly_sqf(A,T, NULL, v); } static GEN trivial_case(GEN A, GEN B) { long d; if (typ(A) == t_INT) return powiu(A, degpol(B)); d = degpol(A); if (d == 0) return trivial_case(gel(A,2),B); if (d < 0) return gen_0; return NULL; } /* floating point resultant */ static GEN fp_resultant(GEN a, GEN b) { long da, db, dc; GEN res = gen_1; pari_sp av, lim; if (lgpol(a)==0 || lgpol(b)==0) return gen_0; da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); 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); while (db) { GEN lb = gel(b,db+2), c = RgX_rem(a,b); c = normalizepol_approx(c, lg(c)); /* kill leading zeroes without warning */ a = b; b = c; dc = degpol(c); if (dc < 0) { avma = av; return gen_0; } if (both_odd(da,db)) res = gneg(res); res = gmul(res, gpowgs(lb, da - dc)); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"fp_resultant"); gerepileall(av, 3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } return gerepileupto(av, gmul(res, gpowgs(gel(b,2), da))); } /* Res(A, B/dB), assuming the A,B in Z[X] and result is integer */ 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; 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); if (bound > 10000) { const long CNTMAX = 5; /* to avoid oo loops if R = 0 */ long bnd = 0, cnt; long prec = nbits2prec( maxss(gexpo(A), gexpo(B)) + 1 ); long bndden = dB? (long)(dbllog2(dB)*degA): 0; for(cnt = 1; cnt < CNTMAX; cnt++, prec = precdbl(prec)) { GEN R = fp_resultant(RgX_gtofp(A, prec), RgX_gtofp(B, prec)); bnd = gexpo(R) - bndden + 1; if (bnd >= 0 && bnd <= (long)bound && !gequal0(R)) { bound = bnd; break; } } } } 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))) { 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) { 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); } } if (DEBUGLEVEL>5) err_printf("done\n"); return gerepileuptoint(av, icopy(H)); } /* A0 and B0 in Q[X] */ GEN QX_resultant(GEN A0, GEN B0) { GEN s, a, b, A, B; pari_sp av = avma; A = Q_primitive_part(A0, &a); B = Q_primitive_part(B0, &b); s = ZX_resultant(A, B); if (!signe(s)) { avma = av; return gen_0; } if (a) s = gmul(s, gpowgs(a,degpol(B))); if (b) s = gmul(s, gpowgs(b,degpol(A))); return gerepileupto(av, s); } GEN ZX_resultant(GEN A, GEN B) { return ZX_resultant_all(A,B,NULL,0); } GEN QXQ_intnorm(GEN A, GEN B) { GEN c, n, R, lB; long dA = degpol(A), dB = degpol(B); pari_sp av = avma; if (dA < 0) return gen_0; A = Q_primitive_part(A, &c); if (!c || typ(c) == t_INT) { n = c; R = ZX_resultant(B, A); } else { n = gel(c,1); R = ZX_resultant_all(B, A, gel(c,2), 0); } if (n && !equali1(n)) R = mulii(R, powiu(n, dB)); lB = leading_term(B); if (!equali1(lB)) R = diviiexact(R, powiu(lB, dA)); return gerepileuptoint(av, R); } GEN QXQ_norm(GEN A, GEN B) { GEN c, R, lB; long dA = degpol(A), dB = degpol(B); pari_sp av = avma; if (dA < 0) return gen_0; A = Q_primitive_part(A, &c); R = ZX_resultant(B, A); if (c) R = gmul(R, gpowgs(c, dB)); lB = leading_term(B); if (!equali1(lB)) R = gdiv(R, gpowgs(lB, dA)); return gerepileupto(av, R); } /* assume x has integral coefficients */ GEN ZX_disc_all(GEN x, ulong bound) { pari_sp av = avma; GEN l, R; long s, d = degpol(x); 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); if (is_pm1(l)) { if (signe(l) < 0) s = -s; } else R = diviiexact(R,l); if (s == -1) togglesign_safe(&R); return gerepileuptoint(av,R); } GEN ZX_disc(GEN x) { return ZX_disc_all(x,0); } GEN QX_disc(GEN x) { pari_sp av = avma; GEN c, d = ZX_disc( Q_primitive_part(x, &c) ); if (c) d = gmul(d, gpowgs(c, 2*degpol(x) - 2)); return gerepileupto(av, d); } /* lift(1 / Mod(A,B)). B a ZX, A a scalar or a QX */ GEN QXQ_inv(GEN A, GEN B) { GEN D, cU, q, U, V; ulong p; pari_sp av2, av = avma, avlim = stack_lim(av, 1); forprime_t S; if (is_scalar_t(typ(A))) return scalarpol(ginv(A), varn(B)); /* A a QX, B a ZX */ if (degpol(A) < 15) return RgXQ_inv(A,B); A = Q_primitive_part(A, &D); /* A, B in Z[X] */ init_modular(&S); av2 = avma; U = NULL; while ((p = u_forprime_next(&S))) { GEN a, b, qp, Up, Vp; int stable; a = ZX_to_Flx(A, p); b = ZX_to_Flx(B, p); /* if p | Res(A/G, B/G), discard */ if (!Flx_extresultant(b,a,p, &Vp,&Up)) continue; if (!U) { /* First time */ U = ZX_init_CRT(Up,p,varn(A)); V = ZX_init_CRT(Vp,p,varn(A)); q = utoipos(p); continue; } if (DEBUGLEVEL>5) err_printf("QXQ_inv: mod %ld (bound 2^%ld)", p,expi(q)); qp = muliu(q,p); stable = ZX_incremental_CRT_raw(&U, Up, q,qp, p) & ZX_incremental_CRT_raw(&V, Vp, q,qp, p); if (stable) { /* all stable: check divisibility */ GEN res = ZX_add(ZX_mul(A,U), ZX_mul(B,V)); if (degpol(res) == 0) { res = gel(res,2); D = D? gmul(D, res): res; break; } /* DONE */ if (DEBUGLEVEL) err_printf("QXQ_inv: char 0 check failed"); } q = qp; if (low_stack(avlim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"QXQ_inv"); gerepileall(av2, 3, &q,&U,&V); } } if (!p) pari_err_OVERFLOW("QXQ_inv [ran out of primes]"); cU = ZX_content(U); if (!is_pm1(cU)) { U = Q_div_to_int(U, cU); D = gdiv(D, cU); } return gerepileupto(av, RgX_Rg_div(U, D)); } /************************************************************************ * * * IRREDUCIBLE POLYNOMIAL / Fp * * * ************************************************************************/ /* irreducible (unitary) polynomial of degree n over Fp */ GEN ffinit_rand(GEN p,long n) { for(;;) { pari_sp av = avma; GEN pol = ZX_add(monomial(gen_1, n, 0), random_FpX(n-1,0, p)); if (FpX_is_irred(pol, p)) return pol; avma = av; } } /* return an extension of degree 2^l of F_2, assume l > 0 * Not stack clean. */ static GEN f2init(long l) { long i; GEN Q, T, S; if (l == 1) return polcyclo(3, MAXVARN); 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) */ /* 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 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; } /* return an extension of degree p^l of F_p, assume l > 0 * Not stack clean. */ GEN ffinit_Artin_Shreier(GEN ip, long l) { long i, 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; } /* check if polsubcyclo(n,l,0) is irreducible modulo p */ static long fpinit_check(GEN p, long n, long l) { ulong q; if (!uisprime(n)) return 0; q = umodiu(p,n); if (!q) return 0; return cgcd((n-1)/Fl_order(q, n-1, n), l) == 1; } /* let k=2 if p%4==1, and k=4 else and assume k*p does not divide l. * Return an irreducible polynomial of degree l over F_p. * Variant of Adleman and Lenstra "Finding irreducible polynomials over * finite fields", ACM, 1986 (5) 350--355. * Not stack clean */ static GEN fpinit(GEN p, long l) { ulong n = 1+l; while (!fpinit_check(p,n,l)) n += l; if (DEBUGLEVEL>=4) err_printf("FFInit: using polsubcyclo(%ld, %ld)\n",n,l); return FpX_red(polsubcyclo(n,l,0),p); } static GEN ffinit_fact(GEN p, long n) { GEN P, F = gel(factoru_pow(n),3); long i; if (!odd(n) && equaliu(p, 2)) P = f2init(vals(n)); /* if n is even, F[1] = 2^vals(n)*/ else P = fpinit(p, F[1]); for (i = 2; i < lg(F); ++i) P = FpX_direct_compositum(fpinit(p, F[i]), P, p); return P; } static GEN ffinit_nofact(GEN p, long n) { GEN P, Q = NULL; if (lgefint(p)==3) { ulong pp = p[2], q; long v = u_lvalrem(n,pp,&q); if (v>0) { Q = (pp == 2)? f2init(v): fpinit(p,n/q); n = q; } } /* n coprime to p */ if (n==1) P = Q; else { P = fpinit(p, n); if (Q) P = FpX_direct_compositum(P, Q, p); } return P; } static GEN init_Fq_i(GEN p, long n, long v) { GEN P; if (n <= 0) pari_err_DOMAIN("ffinit", "degree", "<=", gen_0, stoi(n)); if (typ(p) != t_INT) pari_err_TYPE("ffinit",p); if (signe(p) <= 0) pari_err_PRIME("ffinit",p); if (v < 0) v = 0; if (n == 1) return pol_x(v); if (fpinit_check(p, n+1, n)) return polcyclo(n+1, v); if (lgefint(p)-2 <= expu(n)) P = ffinit_fact(p,n); else P = ffinit_nofact(p,n); setvarn(P, v); return P; } GEN init_Fq(GEN p, long n, long v) { pari_sp av = avma; return gerepileupto(av, init_Fq_i(p, n, v)); } GEN ffinit(GEN p, long n, long v) { pari_sp av = avma; return gerepileupto(av, FpX_to_mod(init_Fq_i(p, n, v), p)); } GEN ffnbirred(GEN p, long n) { pari_sp av = avma; long j; GEN s = gen_0, dk, pd; dk = divisorsu(n); for (j = 1; j < lg(dk); ++j) { long d = dk[j]; long m = moebiusu(d); if (!m) continue; pd = powiu(p, n/d); s = m>0 ? addii(s, pd): subii(s,pd); } return gerepileuptoint(av, divis(s, n)); } GEN ffsumnbirred(GEN p, long n) { pari_sp av = avma; long i,j; GEN v,q, t = gen_0; v = cgetg(n+1,t_VECSMALL); v[1] = 1; q = cgetg(n+1,t_VEC); gel(q,1) = p; for(i=2; i<=n; i++) { v[i] = moebiusu(i); gel(q,i) = mulii(gel(q,i-1), p); } for(i=1; i<=n; i++) { GEN s = gen_0; GEN dk = divisorsu(i); for (j = 1; j < lg(dk); ++j) { long d = dk[j], m = v[d]; if (!m) continue; s = m>0 ? addii(s, gel(q, i/d)): subii(s, gel(q, i/d)); } t = addii(t, divis(s, i)); } return gerepileuptoint(av, t); } GEN ffnbirred0(GEN p, long n, long flag) { if (typ(p) != t_INT) pari_err_TYPE("ffnbirred", p); if (n <= 0) pari_err_DOMAIN("ffnbirred", "degree", "<=", gen_0, stoi(n)); switch(flag) { case 0: return ffnbirred(p, n); case 1: return ffsumnbirred(p, n); default: pari_err_FLAG("ffnbirred"); } return NULL; /* NOT REACHED */ } pari-2.7.5/src/basemath/base1.c0000644000175000017500000022553712413013142014625 0ustar billbill/* 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. */ /**************************************************************/ /* */ /* NUMBER FIELDS */ /* */ /**************************************************************/ #include "pari.h" #include "paripriv.h" int new_galois_format = 0; void checkrnf(GEN rnf) { if (typ(rnf)!=t_VEC || lg(rnf)!=13) pari_err_TYPE("checkrnf",rnf); } GEN checkbnf_i(GEN X) { if (typ(X) == t_VEC) switch (lg(X)) { case 11: return X; case 7: return checkbnf_i(bnr_get_bnf(X)); } return NULL; } GEN checknf_i(GEN X) { if (typ(X)==t_VEC) switch(lg(X)) { case 10: return X; case 11: return checknf_i(bnf_get_nf(X)); case 7: return checknf_i(bnr_get_bnf(X)); case 3: if (typ(gel(X,2)) == t_POLMOD) return checknf_i(gel(X,1)); } return NULL; } GEN checkbnf(GEN x) { GEN bnf = checkbnf_i(x); if (!bnf) pari_err_TYPE("checkbnf [please apply bnfinit()]",x); return bnf; } GEN checknf(GEN x) { GEN nf = checknf_i(x); if (!nf) pari_err_TYPE("checknf [please apply nfinit()]",x); return nf; } void checkbnr(GEN bnr) { if (typ(bnr)!=t_VEC || lg(bnr)!=7) pari_err_TYPE("checkbnr [please apply bnrinit()]",bnr); (void)checkbnf(bnr_get_bnf(bnr)); } void checkbnrgen(GEN bnr) { checkbnr(bnr); if (lg(bnr_get_clgp(bnr))<=3) pari_err_TYPE("checkbnrgen [apply bnrinit(,,1), not bnrinit()]",bnr); } void checksqmat(GEN x, long N) { if (typ(x)!=t_MAT) pari_err_TYPE("checksqmat",x); if (lg(x) == 1 || lgcols(x) != N+1) pari_err_DIM("checksqmat"); } GEN checkbid_i(GEN bid) { GEN f; if (typ(bid)!=t_VEC || lg(bid)!=6) return NULL; f = bid_get_mod(bid); if (typ(f)!=t_VEC || lg(f)!=3) return NULL; return bid; } void checkbid(GEN bid) { if (!checkbid_i(bid)) pari_err_TYPE("checkbid",bid); } void checkabgrp(GEN v) { if (typ(v) == t_VEC) switch(lg(v)) { case 4: if (typ(gel(v,3)) != t_VEC) break; case 3: if (typ(gel(v,2)) != t_VEC) break; if (typ(gel(v,1)) != t_INT) break; return;/*OK*/ default: break; } pari_err_TYPE("checkabgrp",v); } GEN checknfelt_mod(GEN nf, GEN x, const char *s) { GEN T = gel(x,1), a = gel(x,2), Tnf = nf_get_pol(nf); if (!RgX_equal_var(T, Tnf)) pari_err_MODULUS(s, T, Tnf); return a; } void check_ZKmodule(GEN x, const char *s) { if (typ(x) != t_VEC || lg(x) < 3) pari_err_TYPE(s,x); if (typ(gel(x,1)) != t_MAT) pari_err_TYPE(s,gel(x,1)); if (typ(gel(x,2)) != t_VEC) pari_err_TYPE(s,gel(x,2)); if (lg(gel(x,2)) != lgcols(x)) pari_err_DIM(s); } GEN get_bnf(GEN x, long *t) { switch(typ(x)) { case t_POL: *t = typ_POL; return NULL; case t_QUAD: *t = typ_Q ; return NULL; case t_VEC: switch(lg(x)) { case 5: *t = typ_QUA; return NULL; case 6: if (typ(gel(x,1)) == t_VEC && typ(gel(x,3)) == t_MAT) { *t = typ_BID; return NULL; } if (typ(gel(x,2)) == t_COL && typ(gel(x,3)) == t_INT) { *t = typ_PRID; return NULL; } break; case 7: *t = typ_BNR; x = bnr_get_bnf(x); if (typ(x)!=t_VEC || lg(x)!=11) break; return x; case 9: x = gel(x,2); if (typ(x) == t_VEC && lg(x) == 4) *t = typ_GAL; return NULL; case 10: *t = typ_NF; return NULL; case 11: *t = typ_BNF; return x; case 13: *t = typ_RNF; return NULL; case 17: *t = typ_ELL; return NULL; } break; case t_COL: if (get_prid(x)) { *t = typ_MODPR; return NULL; } break; } *t = typ_NULL; return NULL; } GEN get_nf(GEN x, long *t) { switch(typ(x)) { case t_POL : *t = typ_POL; return NULL; case t_QUAD: *t = typ_Q ; return NULL; case t_VEC: switch(lg(x)) { case 3: if (typ(gel(x,2)) != t_POLMOD) break; return get_nf(gel(x,1),t); case 5: *t = typ_QUA; return NULL; case 6: if (typ(gel(x,1)) == t_VEC && typ(gel(x,3)) == t_MAT) { *t = typ_BID; return NULL; } if (typ(gel(x,2)) == t_COL && typ(gel(x,3)) == t_INT) { *t = typ_PRID; return NULL; } break; case 7: *t = typ_BNR; x = bnr_get_bnf(x); if (typ(x)!=t_VEC || lg(x)!=11) break; x = bnf_get_nf(x); if (typ(x)!=t_VEC || lg(x)!=10) break; return x; case 9: x = gel(x,2); if (typ(x) == t_VEC && lg(x) == 4) *t = typ_GAL; return NULL; case 10: *t = typ_NF; return x; case 11: *t = typ_BNF; x = bnf_get_nf(x); if (typ(x)!=t_VEC || lg(x)!=10) break; return x; case 13: *t = typ_RNF; return NULL; case 17: *t = typ_ELL; return NULL; } break; case t_COL: if (get_prid(x)) { *t = typ_MODPR; return NULL; } break; } *t = typ_NULL; return NULL; } long nftyp(GEN x) { switch(typ(x)) { case t_POL : return typ_POL; case t_QUAD: return typ_Q; case t_VEC: switch(lg(x)) { case 10: if (typ(gel(x,1))!=t_POL) break; return typ_NF; case 11: x = bnf_get_nf(x); if (typ(x)!=t_VEC || lg(x)!=10) break; return typ_BNF; case 7: x = bnr_get_bnf(x); if (typ(x)!=t_VEC || lg(x)!=11) break; x = bnf_get_nf(x); if (typ(x)!=t_VEC || lg(x)!=10) break; return typ_BNR; case 6: if (typ(gel(x,1)) != t_VEC || typ(gel(x,3)) != t_MAT) break; return typ_BID; case 9: x = gel(x,2); if (typ(x) == t_VEC && lg(x) == 4) return typ_GAL; case 17: return typ_ELL; } } return typ_NULL; } /*************************************************************************/ /** **/ /** GALOIS GROUP **/ /** **/ /*************************************************************************/ /* exchange elements i and j in vector x */ static GEN transroot(GEN x, int i, int j) { x = leafcopy(x); swap(gel(x,i), gel(x,j)); return x; } GEN tschirnhaus(GEN x) { pari_sp av = avma, av2; long a, v = varn(x); GEN u, y = cgetg(5,t_POL); if (typ(x)!=t_POL) pari_err_TYPE("tschirnhaus",x); if (lg(x) < 4) pari_err_CONSTPOL("tschirnhaus"); if (v) { u = leafcopy(x); setvarn(u,0); x=u; } y[1] = evalsigne(1)|evalvarn(0); do { a = random_bits(2); if (a==0) a = 1; gel(y,4) = stoi(a); a = random_bits(3); if (a>=4) a -= 8; gel(y,3) = stoi(a); a = random_bits(3); if (a>=4) a -= 8; gel(y,2) = stoi(a); u = RgXQ_charpoly(y,x,v); av2 = avma; } while (degpol(RgX_gcd(u,RgX_deriv(u)))); /* while u not separable */ if (DEBUGLEVEL>1) err_printf("Tschirnhaus transform. New pol: %Ps",u); avma=av2; return gerepileupto(av,u); } /* Assume pol in Z[X], monic of degree n. Find L in Z such that * POL = L^(-n) pol(L x) is monic in Z[X]. Return POL and set *ptk = L. * No GC. */ GEN ZX_Z_normalize(GEN pol, GEN *ptk) { long i,j, sk, n = degpol(pol); /* > 0 */ GEN k, fa, P, E, a, POL; a = pol + 2; k = gel(a,n-1); /* a[i] = coeff of degree i */ for (i = n-2; i >= 0; i--) { k = gcdii(k, gel(a,i)); if (is_pm1(k)) { if (ptk) *ptk = gen_1; return pol; } } sk = signe(k); if (!sk) { if (ptk) *ptk = gen_1; return pol; /* monomial! */ } fa = absi_factor_limit(k, 0); k = gen_1; P = gel(fa,1); E = gel(fa,2); POL = leafcopy(pol); a = POL+2; for (i = lg(P)-1; i > 0; i--) { GEN p = gel(P,i), pv, pvj; long vmin = itos(gel(E,i)); /* find v_p(k) = min floor( v_p(a[i]) / (n-i)) */ for (j=n-1; j>=0; j--) { long v; if (!signe(gel(a,j))) continue; v = Z_pval(gel(a,j), p) / (n - j); if (v < vmin) vmin = v; } if (!vmin) continue; pvj = pv = powiu(p,vmin); k = mulii(k, pv); /* a[j] /= p^(v*(n-j)) */ for (j=n-1; j>=0; j--) { if (j < n-1) pvj = mulii(pvj, pv); gel(a,j) = diviiexact(gel(a,j), pvj); } } if (ptk) *ptk = k; return POL; } /* Assume pol != 0 in Z[X]. Find C in Q, L in Z such that POL = C pol(x/L) monic * in Z[X]. Return POL and set *pL = L. Wasteful (but correct) if pol is not * primitive: better if caller used Q_primpart already. No GC. */ GEN ZX_primitive_to_monic(GEN pol, GEN *pL) { long i,j, n = degpol(pol); GEN lc = leading_term(pol), L, fa, P, E, a, POL; if (is_pm1(lc)) { if (pL) *pL = gen_1; return signe(lc) < 0? ZX_neg(pol): pol; } if (signe(lc) < 0) POL = ZX_neg(pol); else POL = leafcopy(pol); a = POL+2; lc = gel(a,n); fa = Z_factor_limit(lc,0); L = gen_1; P = gel(fa,1); E = gel(fa,2); for (i = lg(P)-1; i > 0; i--) { GEN p = gel(P,i), pk, pku; long v, j0, e = itos(gel(E,i)), k = e/n, d = k*n - e; if (d < 0) { k++; d += n; } /* k = ceil(e[i] / n); find d, k such that p^d pol(x / p^k) monic */ for (j=n-1; j>0; j--) { if (!signe(gel(a,j))) continue; v = Z_pval(gel(a,j), p); while (v + d < k * j) { k++; d += n; } } pk = powiu(p,k); j0 = d/k; L = mulii(L, pk); pku = powiu(p,d - k*j0); /* a[j] *= p^(d - kj) */ for (j=j0; j>=0; j--) { if (j < j0) pku = mulii(pku, pk); gel(a,j) = mulii(gel(a,j), pku); } j0++; pku = powiu(p,k*j0 - d); /* a[j] /= p^(kj - d) */ for (j=j0; j<=n; j++) { if (j > j0) pku = mulii(pku, pk); gel(a,j) = diviiexact(gel(a,j), pku); } } if (pL) *pL = L; return POL; } /* Assume pol != 0 in Z[X]. Find C,L in Q such that POL = C pol(x/L) * monic in Z[X]. Return POL and set *pL = L. * Wasteful (but correct) if pol is not primitive: better if caller used * Q_primpart already. No GC. */ GEN ZX_Q_normalize(GEN pol, GEN *pL) { GEN lc, POL = ZX_primitive_to_monic(pol, &lc); POL = ZX_Z_normalize(POL, pL); if (pL) *pL = gdiv(lc, *pL); return POL; } /* pol != 0 in Z[x], returns a monic polynomial POL in Z[x] generating the * same field: there exist C in Q, L in Z such that POL(x) = C pol(x/L). * Set *L = NULL if L = 1, and to L otherwise. No garbage collecting. */ GEN ZX_to_monic(GEN pol, GEN *L) { long n = lg(pol)-1; GEN lc = gel(pol,n); if (is_pm1(lc)) { *L = gen_1; return signe(lc) > 0? pol: ZX_neg(pol); } return ZX_primitive_to_monic(Q_primpart(pol), L); } /* x1*x2^2 + x2*x3^2 + x3*x4^2 + x4*x1^2 */ static GEN F4(GEN x) { return gadd( gmul(gel(x,1), gadd(gsqr(gel(x,2)), gmul(gel(x,4),gel(x,1)))), gmul(gel(x,3), gadd(gsqr(gel(x,4)), gmul(gel(x,2),gel(x,3))))); } static GEN roots_to_ZX(GEN z, long *e) { GEN a = roots_to_pol(z,0); GEN b = grndtoi(real_i(a),e); long e1 = gexpo(imag_i(a)); if (e1 > *e) *e = e1; return b; } static GEN polgaloisnames(long a, long b) { const char * const t[]={"S1", "S2", "A3", "S3", "C(4) = 4", "E(4) = 2[x]2", "D(4)", "A4", "S4", "C(5) = 5", "D(5) = 5:2", "F(5) = 5:4", "A5", "S5", "C(6) = 6 = 3[x]2", "D_6(6) = [3]2", "D(6) = S(3)[x]2", "A_4(6) = [2^2]3", "F_18(6) = [3^2]2 = 3 wr 2", "2A_4(6) = [2^3]3 = 2 wr 3", "S_4(6d) = [2^2]S(3)", "S_4(6c) = 1/2[2^3]S(3)", "F_18(6):2 = [1/2.S(3)^2]2", "F_36(6) = 1/2[S(3)^2]2", "2S_4(6) = [2^3]S(3) = 2 wr S(3)", "L(6) = PSL(2,5) = A_5(6)", "F_36(6):2 = [S(3)^2]2 = S(3) wr 2", "L(6):2 = PGL(2,5) = S_5(6)", "A6", "S6", "C(7) = 7", "D(7) = 7:2", "F_21(7) = 7:3", "F_42(7) = 7:6", "L(7) = L(3,2)", "A7", "S7"}; const long idx[]={0,1,2,4,9,14,30}; return strtoGENstr(t[idx[a-1]+b-1]); } static GEN galois_res(long d, long n, long s, long k) { long kk = k; GEN z = cgetg(5,t_VEC); if (!new_galois_format) { switch (d) { case 6: kk = (k == 6 || k == 2)? 2: 1; break; default: kk = 1; } } gel(z,1) = stoi(n); gel(z,2) = stoi(s); gel(z,3) = stoi(kk); gel(z,4) = polgaloisnames(d,k); return z; } GEN polgalois(GEN x, long prec) { pari_sp av = avma, av1; long i,j,k,n,f,l,l2,e,e1,pr,ind; GEN x1,p1,p2,p3,p4,p5,w,z,ee; const int ind5[20]={2,5,3,4, 1,3,4,5, 1,5,2,4, 1,2,3,5, 1,4,2,3}; const int ind6[60]={3,5,4,6, 2,6,4,5, 2,3,5,6, 2,4,3,6, 2,5,3,4, 1,4,5,6, 1,5,3,6, 1,6,3,4, 1,3,4,5, 1,6,2,5, 1,2,4,6, 1,5,2,4, 1,3,2,6, 1,2,3,5, 1,4,2,3}; if (typ(x)!=t_POL) pari_err_TYPE("galois",x); n=degpol(x); if (n>11) pari_err_IMPL("galois of degree higher than 11"); x = Q_primpart(x); RgX_check_ZX(x, "galois"); if (!ZX_is_irred(x)) pari_err_IRREDPOL("galois",x); if (n<4) { if (n == 1) { avma = av; return galois_res(n,1, 1,1); } if (n == 2) { avma = av; return galois_res(n,2,-1,1); } /* n = 3 */ f = Z_issquare(ZX_disc(x)); avma = av; return f? galois_res(n,3,1,1): galois_res(n,6,-1,2); } x1 = x = ZX_Q_normalize(x,NULL); av1=avma; if (n > 7) return galoisbig(x, prec); for(;;) { double cb = cauchy_bound(x); switch(n) { case 4: z = cgetg(7,t_VEC); prec = nbits2prec((long)(cb*(18./ LOG2)) + 64); for(;;) { p1=QX_complex_roots(x,prec); gel(z,1) = F4(p1); gel(z,2) = F4(transroot(p1,1,2)); gel(z,3) = F4(transroot(p1,1,3)); gel(z,4) = F4(transroot(p1,1,4)); gel(z,5) = F4(transroot(p1,2,3)); gel(z,6) = F4(transroot(p1,3,4)); p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2 = gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: f = Z_issquare(ZX_disc(x)); avma = av; return f? galois_res(n,12,1,4): galois_res(n,24,-1,5); case 2: avma = av; return galois_res(n,8,-1,3); case 3: avma = av; return (degpol(gel(p2,1))==2)? galois_res(n,4,1,2) : galois_res(n,4,-1,1); default: pari_err_BUG("galois (bug1)"); } case 5: z = cgetg(7,t_VEC); ee= cgetg(7,t_VECSMALL); w = cgetg(7,t_VECSMALL); prec = nbits2prec((long)(cb*(21. / LOG2)) + 64); for(;;) { for(;;) { p1=QX_complex_roots(x,prec); for (l=1; l<=6; l++) { p2=(l==1)?p1: ((l<6)?transroot(p1,1,l): transroot(p1,2,5)); p3=gen_0; for (k=0,i=1; i<=5; i++,k+=4) { p5 = gadd(gmul(gel(p2,ind5[k]),gel(p2,ind5[k+1])), gmul(gel(p2,ind5[k+2]),gel(p2,ind5[k+3]))); p3 = gadd(p3, gmul(gsqr(gel(p2,i)),p5)); } gel(w,l) = grndtoi(real_i(p3),&e); e1 = gexpo(imag_i(p3)); if (e1>e) e=e1; ee[l]=e; gel(z,l) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p3=gel(ZX_factor(p5),1); f=Z_issquare(ZX_disc(x)); if (lg(p3)-1==1) { avma = av; return f? galois_res(n,60,1,4): galois_res(n,120,-1,5); } if (!f) { avma = av; return galois_res(n,20,-1,3); } pr = - (prec2nbits(prec) >> 1); for (l=1; l<=6; l++) if (ee[l] <= pr && gequal0(poleval(p5,gel(w,l)))) break; if (l>6) pari_err_BUG("galois (bug4)"); p2=(l==6)? transroot(p1,2,5):transroot(p1,1,l); p3=gen_0; for (i=1; i<=5; i++) { j = (i == 5)? 1: i+1; p3 = gadd(p3,gmul(gmul(gel(p2,i),gel(p2,j)), gsub(gel(p2,j),gel(p2,i)))); } p5=gsqr(p3); p4=grndtoi(real_i(p5),&e); e1 = gexpo(imag_i(p5)); if (e1>e) e=e1; if (e <= -10) { if (gequal0(p4)) goto tchi; f = Z_issquare(p4); avma = av; return f? galois_res(n,5,1,1): galois_res(n,10,1,2); } prec = precdbl(prec); } case 6: z = cgetg(7, t_VEC); prec = nbits2prec((long) (cb * (42. / LOG2)) + 64); for(;;) { for(;;) { p1=QX_complex_roots(x,prec); for (l=1; l<=6; l++) { p2=(l==1)?p1:transroot(p1,1,l); p3=gen_0; k=0; for (i=1; i<=5; i++) for (j=i+1; j<=6; j++) { p5=gadd(gmul(gel(p2,ind6[k]),gel(p2,ind6[k+1])), gmul(gel(p2,ind6[k+2]),gel(p2,ind6[k+3]))); p3=gadd(p3,gmul(gsqr(gmul(gel(p2,i),gel(p2,j))),p5)); k += 4; } gel(z,l) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2=gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: z = cgetg(11,t_VEC); ind=0; p3=gadd(gmul(gmul(gel(p1,1),gel(p1,2)),gel(p1,3)), gmul(gmul(gel(p1,4),gel(p1,5)),gel(p1,6))); gel(z,++ind) = p3; for (i=1; i<=3; i++) for (j=4; j<=6; j++) { p2=transroot(p1,i,j); p3=gadd(gmul(gmul(gel(p2,1),gel(p2,2)),gel(p2,3)), gmul(gmul(gel(p2,4),gel(p2,5)),gel(p2,6))); gel(z,++ind) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) { if (!ZX_is_squarefree(p5)) goto tchi; p2 = gel(ZX_factor(p5),1); f = Z_issquare(ZX_disc(x)); avma = av; if (lg(p2)-1==1) return f? galois_res(n,360,1,15): galois_res(n,720,-1,16); else return f? galois_res(n,36,1,10): galois_res(n,72,-1,13); } prec = precdbl(prec); break; case 2: l2=degpol(gel(p2,1)); if (l2>3) l2=6-l2; switch(l2) { case 1: f = Z_issquare(ZX_disc(x)); avma = av; return f? galois_res(n,60,1,12): galois_res(n,120,-1,14); case 2: f = Z_issquare(ZX_disc(x)); if (f) { avma = av; return galois_res(n,24,1,7); } p3 = (degpol(gel(p2,1))==2)? gel(p2,2): gel(p2,1); f = Z_issquare(ZX_disc(p3)); avma = av; return f? galois_res(n,24,-1,6): galois_res(n,48,-1,11); case 3: f = Z_issquare(ZX_disc(gel(p2,1))) || Z_issquare(ZX_disc(gel(p2,2))); avma = av; return f? galois_res(n,18,-1,5): galois_res(n,36,-1,9); } case 3: for (l2=1; l2<=3; l2++) if (degpol(gel(p2,l2)) >= 3) p3 = gel(p2,l2); if (degpol(p3) == 3) { f = Z_issquare(ZX_disc(p3)); avma = av; return f? galois_res(n,6,-1,1): galois_res(n,12,-1,3); } else { f = Z_issquare(ZX_disc(x)); avma = av; return f? galois_res(n,12,1,4): galois_res(n,24,-1,8); } case 4: avma = av; return galois_res(n,6,-1,2); default: pari_err_BUG("galois (bug3)"); } } case 7: z = cgetg(36,t_VEC); prec = nbits2prec((long)(cb*(7. / LOG2)) + 64); for(;;) { ind = 0; p1=QX_complex_roots(x,prec); for (i=1; i<=5; i++) for (j=i+1; j<=6; j++) { GEN t = gadd(gel(p1,i),gel(p1,j)); for (k=j+1; k<=7; k++) gel(z,++ind) = gadd(t, gel(p1,k)); } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2=gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: f = Z_issquare(ZX_disc(x)); avma = av; return f? galois_res(n,2520,1,6): galois_res(n,5040,-1,7); case 2: f = degpol(gel(p2,1)); avma = av; return (f==7 || f==28)? galois_res(n,168,1,5): galois_res(n,42,-1,4); case 3: avma = av; return galois_res(n,21,1,3); case 4: avma = av; return galois_res(n,14,-1,2); case 5: avma = av; return galois_res(n,7,1,1); default: pari_err_BUG("galois (bug2)"); } } tchi: avma = av1; x = tschirnhaus(x1); } } #undef _res /* Evaluate pol in s using nfelt arithmetic and Horner rule */ GEN nfpoleval(GEN nf, GEN pol, GEN s) { pari_sp av=avma; long i=lg(pol)-1; GEN res; if (i==1) return gen_0; res = nf_to_scalar_or_basis(nf, gel(pol,i)); for (i-- ; i>=2; i--) res = nfadd(nf, nfmul(nf, s, res), gel(pol,i)); return gerepileupto(av, res); } static GEN QX_table_nfpoleval(GEN nf, GEN pol, GEN m) { pari_sp av = avma; long i = lg(pol)-1; GEN res, den; if (i==1) return gen_0; pol = Q_remove_denom(pol, &den); res = scalarcol_shallow(gel(pol,i), nf_get_degree(nf)); for (i-- ; i>=2; i--) res = ZC_Z_add(ZM_ZC_mul(m, res), gel(pol,i)); if (den) res = RgC_Rg_div(res, den); return gerepileupto(av, res); } GEN FpX_FpC_nfpoleval(GEN nf, GEN pol, GEN a, GEN p) { pari_sp av=avma; long i=lg(pol)-1, n=nf_get_degree(nf); GEN res, Ma; if (i==1) return zerocol(n); Ma = FpM_red(zk_multable(nf, a), p); res = scalarcol(gel(pol,i),n); for (i-- ; i>=2; i--) { res = FpM_FpC_mul(Ma, res, p); gel(res,1) = Fp_add(gel(res,1), gel(pol,i), p); } return gerepileupto(av, res); } /* compute s(x), not stack clean */ static GEN table_galoisapply(GEN nf, GEN m, GEN x) { x = nf_to_scalar_or_alg(nf, x); if (typ(x) != t_POL) return scalarcol(x, nf_get_degree(nf)); return QX_table_nfpoleval(nf, x, m); } /* compute s(x), not stack clean */ static GEN ZC_galoisapply(GEN nf, GEN s, GEN x) { x = nf_to_scalar_or_alg(nf, x); if (typ(x) != t_POL) return scalarcol(x, nf_get_degree(nf)); return QX_table_nfpoleval(nf, x, zk_multable(nf, s)); } static GEN QX_galoisapplymod(GEN nf, GEN pol, GEN S, GEN p) { GEN den, P = Q_remove_denom(pol,&den); GEN pe, pe1, denpe, R; if (den) { ulong e = Z_pval(den, p); pe = powiu(p, e); pe1 = mulii(pe, p); denpe = Fp_inv(diviiexact(den, pe), pe1); } else { pe = gen_1; pe1 = p; denpe = gen_1; } R = FpX_FpC_nfpoleval(nf, FpX_red(P, pe1), FpC_red(S, pe1), pe1); return gdivexact(FpC_Fp_mul(R, denpe, pe1), pe); } static GEN pr_galoisapply(GEN nf, GEN pr, GEN aut) { GEN p, t, u; if (typ(pr_get_tau(pr)) == t_INT) return pr; /* inert */ p = pr_get_p(pr); u = QX_galoisapplymod(nf, coltoliftalg(nf, pr_get_gen(pr)), aut, p); t = FpM_deplin(zk_multable(nf, u), p); t = zk_scalar_or_multable(nf, t); return mkvec5(p, u, gel(pr,3), gel(pr,4), t); } static GEN vecgaloisapply(GEN nf, GEN aut, GEN v) { long i, l; GEN V = cgetg_copy(v, &l); for (i = 1; i < l; i++) gel(V,i) = galoisapply(nf, aut, gel(v,i)); return V; } /* x: famat or standard algebraic number, aut automorphism in ZC form * simplified from general galoisapply */ static GEN elt_galoisapply(GEN nf, GEN aut, GEN x) { pari_sp av = avma; switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: x = gel(x,2); /* fall through */ case t_POL: { GEN y = basistoalg(nf, ZC_galoisapply(nf, aut, x)); return gerepileupto(av,y); } case t_COL: return gerepileupto(av, ZC_galoisapply(nf, aut, x)); case t_MAT: switch(lg(x)) { case 1: return cgetg(1, t_MAT); case 3: retmkmat2(vecgaloisapply(nf,aut,gel(x,1)), ZC_copy(gel(x,2))); } } pari_err_TYPE("galoisapply",x); return NULL; /* not reached */ } GEN galoisapply(GEN nf, GEN aut, GEN x) { pari_sp av = avma; long lx, j; GEN y; nf = checknf(nf); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: x = gel(x,2); /* fall through */ case t_POL: aut = algtobasis(nf, aut); y = basistoalg(nf, ZC_galoisapply(nf, aut, x)); return gerepileupto(av,y); case t_VEC: aut = algtobasis(nf, aut); switch(lg(x)) { case 6: return gerepilecopy(av, pr_galoisapply(nf, x, aut)); case 3: y = cgetg(3,t_VEC); gel(y,1) = galoisapply(nf, aut, gel(x,1)); gel(y,2) = elt_galoisapply(nf, aut, gel(x,2)); return gerepileupto(av, y); } break; case t_COL: aut = algtobasis(nf, aut); return gerepileupto(av, ZC_galoisapply(nf, aut, x)); case t_MAT: /* ideal */ lx = lg(x); if (lx==1) return cgetg(1,t_MAT); if (nbrows(x) != nf_get_degree(nf)) break; aut = zk_multable(nf, algtobasis(nf, aut)); y = cgetg(lx,t_MAT); for (j=1; j1) pari_err_DOMAIN("idealfrobenius","pr.e", ">", gen_1,pr); f = pr_get_f(pr); n = nf_get_degree(nf); if (f==1) { avma = av; return identity_perm(n); } modpr = zk_to_Fq_init(nf,&pr,&T,&p); g = idealquasifrob(nf, gal, pr, NULL, &S); a = pol_x(nf_get_varn(nf)); b = nf_to_Fq(nf, QX_galoisapplymod(nf, modpr_genFq(modpr), S, p), modpr); for (s=0; !ZX_equal(a, b); s++) a = Fq_pow(a, p, T, p); g = perm_pow(g, Fl_inv(s, f)); return gerepileupto(av, g); } static GEN idealinertiagroup(GEN nf, GEN gal, GEN pr) { long i, n = nf_get_degree(nf); GEN p, T, modpr = zk_to_Fq_init(nf,&pr,&T,&p); GEN b = modpr_genFq(modpr); long e = pr_get_e(pr), coprime = cgcd(e, pr_get_f(pr)) == 1; GEN grp = gal_get_group(gal), pi = pr_get_gen(pr); pari_sp ltop = avma; for (i=1; i<=n; i++) { GEN iso = gel(grp,i); if (perm_order(iso) == e) { GEN S = poltobasis(nf, galoispermtopol(gal, iso)); if (ZC_prdvd(nf, ZC_galoisapply(nf, S, pi), pr) && (coprime || gequalX(nf_to_Fq(nf, galoisapply(nf,S,b), modpr)))) return iso; avma = ltop; } } pari_err_BUG("idealinertiagroup [no isotropic element]"); return NULL; } static GEN idealramgroupstame(GEN nf, GEN gal, GEN pr) { pari_sp av = avma; GEN iso, frob, giso, isog, S, res; long e = pr_get_e(pr), f = pr_get_f(pr); if (e == 1) { if (f==1) return cgetg(1,t_VEC); frob = idealquasifrob(nf, gal, pr, NULL, &S); avma = av; res = cgetg(2, t_VEC); gel(res, 1) = cyclicgroup(frob, f); return res; } res = cgetg(3, t_VEC); av = avma; iso = idealinertiagroup(nf, gal, pr); avma = av; giso = cyclicgroup(iso, e); gel(res, 2) = giso; if (f==1) { gel(res, 1) = giso; return res; } av = avma; isog = group_set(giso, nf_get_degree(nf)); frob = idealquasifrob(nf, gal, pr, isog, &S); avma = av; gel(res, 1) = dicyclicgroup(iso,frob,e,f); return res; } static GEN idealramgroupindex(GEN nf, GEN gal, GEN pr) { pari_sp av = avma; GEN p, T, g, idx, modpr; long i, e, f, n; ulong nt,rorder; GEN grp = vecvecsmall_sort(gal_get_group(gal)); e = pr_get_e(pr); f = pr_get_f(pr); n = nf_get_degree(nf); modpr = zk_to_Fq_init(nf,&pr,&T,&p); (void) u_pvalrem(n,p,&nt); rorder = e*f*(n/nt); idx = const_vecsmall(n,-1); g = modpr_genFq(modpr); for (i=2; i<=n; i++) { GEN iso; long o; if (idx[i]>=0) continue; iso = gel(grp,i); o = perm_order(iso); if (rorder%o == 0) { GEN piso = iso; GEN S = poltobasis(nf, galoispermtopol(gal, iso)); GEN pi = pr_get_gen(pr); GEN spi = ZC_galoisapply(nf, S, pi); long j; idx[i] = idealval(nf, gsub(spi,pi), pr); if (idx[i] >=1) { if (f>1) { GEN b = nf_to_Fq(nf, QX_galoisapplymod(nf, g, S, p), modpr); if (!gequalX(b)) idx[i] = 0; } } else idx[i] = -1; for(j=2;j0; i--) { for(j=1;j<=n;j++) if (idx[j]==i-1) F2v_set(set,j); gel(res,i) = gel(sub, tableset_find_index(tbl, set)); } return gerepilecopy(av, res); } /* x = relative polynomial nf = absolute nf, bnf = absolute bnf */ GEN get_bnfpol(GEN x, GEN *bnf, GEN *nf) { *bnf = checkbnf_i(x); *nf = checknf_i(x); if (*nf) x = nf_get_pol(*nf); if (typ(x) != t_POL) pari_err_TYPE("get_bnfpol",x); return x; } GEN get_nfpol(GEN x, GEN *nf) { if (typ(x) == t_POL) { *nf = NULL; return x; } *nf = checknf(x); return nf_get_pol(*nf); } /* is isomorphism / inclusion (a \subset b) compatible with what we know about * basic invariants ? (degree, signature, discriminant) */ static int tests_OK(GEN a, GEN nfa, GEN b, GEN nfb, long fliso) { GEN da, db, fa, P, E, U; long i, nP, m = degpol(a), n = degpol(b), q = m / n; /* relative degree */ if (m <= 0) pari_err_IRREDPOL("nfisincl",a); if (n <= 0) pari_err_IRREDPOL("nfisincl",b); if (fliso) { if (n != m) return 0; } else { if (n % m) return 0; } if (m == 1) return 1; if (nfa && nfb) /* both nf structures available */ { long r1a = nf_get_r1(nfa), r1b = nf_get_r1(nfb) ; if (fliso) return (r1a == r1b && equalii(nf_get_disc(nfa), nf_get_disc(nfb))); else return (r1b <= r1a * q && dvdii(nf_get_disc(nfb), powiu(nf_get_disc(nfa), q))); } da = nfa? nf_get_disc(nfa): ZX_disc(a); if (!signe(da)) pari_err_IRREDPOL("nfisincl",a); db = nfb? nf_get_disc(nfb): ZX_disc(b); if (!signe(db)) pari_err_IRREDPOL("nfisincl",a); if (fliso) return issquare(gdiv(da,db)); if (odd(q) && signe(da) != signe(db)) return 0; fa = absi_factor_limit(da, 0); P = gel(fa,1); E = gel(fa,2); nP = lg(P) - 1; for (i=1; i 0) { fa = Z_factor(U); P = gel(fa,1); E = gel(fa,2); } else { P = mkvec(U); E = mkvec(gen_1); } nP = lg(P) - 1; for (i=1; i<=nP; i++) if (mod2(gel(E,i)) && !dvdii(db, powiu(gel(P,i),q))) return 0; } return 1; } /* if fliso test for isomorphism, for inclusion otherwise. */ static GEN nfiso0(GEN a, GEN b, long fliso) { pari_sp av = avma; long i, vb, lx; GEN nfa, nfb, y, la, lb; a = get_nfpol(a, &nfa); b = get_nfpol(b, &nfb); if (!nfa) { a = Q_primpart(a); RgX_check_ZX(a, "nsiso0"); } if (!nfb) { b = Q_primpart(b); RgX_check_ZX(b, "nsiso0"); } if (fliso && nfa && !nfb) { swap(a,b); nfb = nfa; nfa = NULL; } if (!tests_OK(a, nfa, b, nfb, fliso)) { avma = av; return gen_0; } 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); 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> 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; } GEN nf_get_allroots(GEN nf) { return embed_roots(nf_get_roots(nf), nf_get_r1(nf)); } /* For internal use. compute trace(x mod pol), sym=polsym(pol,deg(pol)-1) */ GEN quicktrace(GEN x, GEN sym) { GEN p1 = gen_0; long i; if (typ(x) != t_POL) return gmul(x, gel(sym,1)); if (signe(x)) { sym--; for (i=lg(x)-1; i>1; i--) p1 = gadd(p1, gmul(gel(x,i),gel(sym,i))); } return p1; } static GEN get_Tr(GEN mul, GEN x, GEN basden) { GEN t, bas = gel(basden,1), den = gel(basden,2); long i, j, n = lg(bas)-1; GEN T = cgetg(n+1,t_MAT), TW = cgetg(n+1,t_COL), sym = polsym(x, n-1); gel(TW,1) = utoipos(n); for (i=2; i<=n; i++) { t = quicktrace(gel(bas,i), sym); if (den && den[i]) t = diviiexact(t,gel(den,i)); gel(TW,i) = t; /* tr(w[i]) */ } gel(T,1) = TW; for (i=2; i<=n; i++) { gel(T,i) = cgetg(n+1,t_COL); gcoeff(T,1,i) = gel(TW,i); for (j=2; j<=i; j++) /* Tr(W[i]W[j]) */ gcoeff(T,i,j) = gcoeff(T,j,i) = ZV_dotproduct(gel(mul,j+(i-1)*n), TW); } return T; } /* return [bas[i]*denom(bas[i]), denom(bas[i])], denom 1 is given as NULL */ GEN get_bas_den(GEN bas) { GEN b,d,den, dbas = leafcopy(bas); long i, l = lg(bas); int power = 1; den = cgetg(l,t_VEC); for (i=1; i= prec [also holds for G] */ static void get_roots_for_M(nffp_t *F) { long n, eBD, PREC; if (F->extraprec < 0) { /* not initialized yet */ 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; if (er < 0) er = 0; F->extraprec = nbits2extraprec((long)(n*er + eBD + log2(n))-(BITS_IN_LONG-1));/*FIXME*/ } PREC = F->prec + F->extraprec; if (F->ro && gprecision(gel(F->ro,1)) >= PREC) return; F->ro = get_roots(F->x, F->r1, PREC); } /* [bas[i]/den[i]]= integer basis. roo = real part of the roots */ static void make_M(nffp_t *F, int trunc) { GEN bas = gel(F->basden,1), den = gel(F->basden,2), ro = F->ro; GEN m, d, M; long i, j, l = lg(ro), n = lg(bas); M = cgetg(n,t_MAT); gel(M,1) = const_col(l-1, gen_1); /* bas[1] = 1 */ for (j=2; jprec + F->extraprec); for (j=2; j F->prec) { M = gprec_w(M, F->prec); F->ro = gprec_w(ro,F->prec); } F->M = M; } /* return G real such that G~ * G = T_2 */ static void make_G(nffp_t *F) { GEN G, M = F->M; long i, j, k, r1 = F->r1, l = lg(M); G = cgetg(l, t_MAT); for (j=1; jG = G; } static void make_M_G(nffp_t *F, int trunc) { get_roots_for_M(F); make_M(F, trunc); make_G(F); } void remake_GM(GEN nf, nffp_t *F, long prec) { F->x = nf_get_pol(nf); F->ro = NULL; F->r1 = nf_get_r1(nf); F->basden = get_bas_den(nf_get_zk(nf)); F->extraprec = -1; F->prec = prec; make_M_G(F, 1); } static void nffp_init(nffp_t *F, nfbasic_t *T, GEN ro, long prec) { F->x = T->x; F->ro = ro; F->r1 = T->r1; if (!T->basden) T->basden = get_bas_den(T->bas); F->basden = T->basden; F->extraprec = -1; F->prec = prec; } static void get_nf_fp_compo(nfbasic_t *T, nffp_t *F, GEN ro, int trunc, long prec) { nffp_init(F,T,ro,prec); make_M_G(F, trunc); } static GEN get_sign(long r1, long n) { return mkvec2s(r1, (n-r1)>>1); } GEN nfbasic_to_nf(nfbasic_t *T, GEN ro, long prec) { GEN nf = cgetg(10,t_VEC); GEN x = T->x, absdK, Tr, D, TI, A, dA, MDI, mat = cgetg(9,t_VEC); long n = degpol(T->x); nffp_t F; get_nf_fp_compo(T, &F, ro, 0, prec); gel(nf,1) = T->x; gel(nf,2) = get_sign(T->r1, n); gel(nf,3) = T->dK; gel(nf,4) = T->index; gel(nf,6) = F.ro; gel(nf,5) = mat; gel(mat,1) = F.M; gel(mat,2) = F.G; nf_set_multable(nf, T->bas, F.basden); Tr = get_Tr(gel(nf,9), x, F.basden); absdK = T->dK; if (signe(absdK) < 0) absdK = negi(absdK); TI = ZM_inv(Tr, absdK); /* dK T^-1 */ A = Q_primitive_part(TI, &dA); gel(mat,6) = A; /* primitive part of codifferent, dA its content */ dA = dA? diviiexact(absdK, dA): absdK; A = ZM_hnfmodid(A, dA); MDI = idealtwoelt(nf, A); gel(MDI,2) = zk_scalar_or_multable(nf, gel(MDI,2)); gel(mat,7) = MDI; if (is_pm1(T->index)) /* principal ideal (x'), whose norm is |dK| */ { D = zk_scalar_or_multable(nf, ZX_deriv(x)); if (typ(D) == t_MAT) D = ZM_hnfmod(D, absdK); } else D = RgM_Rg_mul(idealinv(nf, A), dA); gel(mat,3) = RM_round_maxrank(F.G); gel(mat,4) = Tr; gel(mat,5) = D; gel(mat,8) = T->dKP? shallowtrans(T->dKP): cgetg(1,t_VEC); return nf; } static GEN primes_certify(GEN dK, GEN dKP) { pari_sp av = avma; long i, l = lg(dKP); GEN v, D = dK; v = vectrunc_init(l); for (i = 1; i < l; i++) { GEN p = gel(dKP,i); if (!isprime(p)) vectrunc_append(v, p); (void)Z_pvalrem(D, p, &D); } if (!is_pm1(D)) { if (signe(D) < 0) D = negi(D); if (!isprime(D)) vectrunc_append(v, D); } fixlg(v, lg(v)); return gerepilecopy(av, v); } GEN nfcertify(GEN nf) { nf = checknf(nf); return primes_certify(nf_get_disc(nf),gmael(nf, 5, 8)); } #if 0 /* used to check benches between HNF nf.zk and LLL-reduced nf.zk */ static GEN hnffromLLL(GEN nf) { GEN d, x; x = RgV_to_RgM(nf_get_zk(nf), nf_get_degree(nf)); x = Q_remove_denom(x, &d); if (!d) return x; /* power basis */ return RgM_solve(ZM_hnfmodid(x, d), x); } static GEN nfbasechange(GEN u, GEN x) { long i,lx; GEN y; switch(typ(x)) { case t_COL: /* nfelt */ return RgM_RgC_mul(u, x); case t_MAT: /* ideal */ y = cgetg_copy(x, &lx); for (i=1; ix */ static GEN get_red_G(nfbasic_t *T, GEN *pro) { GEN G, u, u0 = NULL; pari_sp av; long i, prec, n = degpol(T->x); nffp_t F; prec = nbits2prec(n+32); nffp_init(&F, T, NULL, prec); av = avma; for (i=1; ; i++) { F.prec = prec; make_M_G(&F, 0); G = F.G; if (u0) G = RgM_mul(G, u0); 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 (lg(u)-1 == n) break; /* singular ==> loss of accuracy */ if (u0) u0 = gerepileupto(av, RgM_mul(u0,u)); else u0 = gerepilecopy(av, u); } prec = precdbl(prec) + nbits2extraprec(gexpo(u0)); F.ro = NULL; if (DEBUGLEVEL) pari_warn(warnprec,"get_red_G", prec); } if (u0) u = RgM_mul(u0,u); *pro = F.ro; return u; } /* Compute an LLL-reduced basis for the integer basis of nf(T). * set *pro = roots of x if computed [NULL if not computed] */ static void set_LLL_basis(nfbasic_t *T, GEN *pro, double DELTA) { GEN B = T->bas; if (T->r1 == degpol(T->x)) { 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); B = gerepileupto(av, RgV_RgM_mul(B, u)); *pro = NULL; } else B = RgV_RgM_mul(B, get_red_G(T, pro)); T->bas = B; T->basden = get_bas_den(B); } static int cmp_abs_ZX(GEN x, GEN y) { return gen_cmp_RgX((void*)&absi_cmp, x, y); } /* current best: ZX x of discriminant *dx, is ZX y better than x ? * (if so update *dx) */ static int ZX_is_better(GEN y, GEN x, GEN *dx) { GEN d = ZX_disc(y); int cmp; if (!*dx) *dx = ZX_disc(x); cmp = absi_cmp(d, *dx); if (cmp < 0) { *dx = d; return 1; } if (cmp == 0) return cmp_abs_ZX(y, x) < 0; return 0; } static void polredbest_aux(nfbasic_t *T, GEN *pro, GEN *px, GEN *pdx, GEN *pa); /* Seek a simpler, polynomial pol defining the same number field as * x (assumed to be monic at this point) */ static GEN nfpolred(nfbasic_t *T, GEN *pro) { GEN x = T->x, dx, b, rev; long n = degpol(x), v = varn(x); if (n == 1) { T->x = deg1pol_shallow(gen_1, gen_m1, v); *pro = NULL; return pol_1(v); } polredbest_aux(T, pro, &x, &dx, &b); if (x == T->x) return NULL; /* no improvement */ if (DEBUGLEVEL>1) err_printf("xbest = %Ps\n",x); /* update T */ rev = QXQ_reverse(b, T->x); T->bas = QXV_QXQ_eval(T->bas, rev, x); (void)Z_issquareall(diviiexact(dx,T->dK), &(T->index)); T->basden = get_bas_den(T->bas); T->dx = dx; T->x = x; *pro = NULL; /* reset */ return rev; } /* let bas a t_VEC of QX giving a Z-basis of O_K. Return the index of the * basis. Assume bas[1] is 1 and that the leading coefficient of elements * of bas are of the form 1/b for a t_INT b */ GEN get_nfindex(GEN bas) { pari_sp av = avma; long n = lg(bas)-1, i; GEN D, d, mat; D = gen_1; /* assume bas[1] = 1 */ for (i = 2; i <= n; i++) { /* in most cases [e.g after nfbasis] basis is upper triangular! */ GEN B = gel(bas,i), lc; if (degpol(B) != i-1) break; lc = gel(B, i+1); switch (typ(lc)) { case t_INT: continue; case t_FRAC: lc = gel(lc,2); break; default: pari_err_TYPE("get_nfindex",lc); } D = mulii(D, lc); } if (i <= n) { /* not triangular after all */ bas = Q_remove_denom(bas, &d); if (!d) { avma = av; return D; } mat = RgV_to_RgM(bas, n); d = diviiexact(powiu(d, n), ZM_det(mat)); D = mulii(D,absi(d)); } return gerepileuptoint(av, D); } /* Either nf type or ZX or [monic ZX, data], where data is either an integral * basis (deprecated), or listP data (nfbasis input format) to specify * a set of primes at with the basis order must be maximal. * 1) nf type (or unrecognized): return t_VEC * 2) ZX or [ZX, listP]: return t_POL * 3) [ZX, order basis]: return 0 (deprecated) * incorrect: return -1 */ static long nf_input_type(GEN x) { GEN T, V; long i, d, v; switch(typ(x)) { case t_POL: return t_POL; case t_VEC: if (lg(x) != 3) return t_VEC; /* nf or incorrect */ T = gel(x,1); V = gel(x,2); if (typ(T) != t_POL) return -1; switch(typ(V)) { case t_INT: case t_MAT: return t_POL; case t_VEC: if (RgV_is_ZV(V)) return t_POL; break; default: return -1; } d = degpol(T); v = varn(T); if (d<1 || !RgX_is_ZX(T) || !isint1(gel(T,d+2)) || lg(V)-1!=d) return -1; for (i = 1; i <= d; i++) { /* check integer basis */ GEN c = gel(V,i); switch(typ(c)) { case t_INT: break; case t_POL: if (varn(c) == v && RgX_is_QX(c) && degpol(c) < d) break; /* fall through */ default: return -1; } } return 0; } return t_VEC; /* nf or incorrect */ } static void nfbasic_add_disc(nfbasic_t *T) { if (!T->index) T->index = get_nfindex(T->bas); if (!T->dx) T->dx = ZX_disc(T->x); if (!T->dK) T->dK = diviiexact(T->dx, sqri(T->index)); } static void nfbasic_init(GEN x, long flag, nfbasic_t *T) { GEN bas, dK, dx, index, unscale = gen_1; long r1; T->dKP = NULL; switch (nf_input_type(x)) { case t_POL: { nfmaxord_t S; nfmaxord(&S, x, flag); x = S.T; T->x0 = S.T0; T->dKP = S.dKP; dK = S.dK; index = S.index; bas = S.basis; dx = S.dT; unscale = S.unscale; r1 = sturm(x); break; } case t_VEC: { /* nf, bnf, bnr */ GEN nf = checknf(x); x = nf_get_pol(nf); dK = nf_get_disc(nf); index = nf_get_index(nf); bas = nf_get_zk(nf); T->x0 = x; dx = NULL; r1 = nf_get_r1(nf); break; } case 0: /* monic integral polynomial + integer basis */ bas = gel(x,2); x = gel(x,1); T->x0 = x; index = NULL; dx = NULL; dK = NULL; r1 = sturm(x); break; default: /* -1 */ pari_err_TYPE("nfbasic_init", x); return; } T->x = x; T->unscale = unscale; T->r1 = r1; T->dx = dx; T->dK = dK; T->bas = bas; T->basden= NULL; T->index = index; } /* Initialize the number field defined by the polynomial x (in variable v) * flag & nf_RED: try a polred first. * flag & nf_ORIG * do a polred and return [nfinit(x), Mod(a,red)], where * Mod(a,red) = Mod(v,x) (i.e return the base change). */ GEN nfinitall(GEN x, long flag, long prec) { const pari_sp av = avma; GEN nf, unscale; nfbasic_t T; 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)) { pari_warn(warner,"non-monic polynomial. Result of the form [nf,c]"); flag |= nf_RED | nf_ORIG; } unscale = T.unscale; if (!(flag & nf_RED) && !isint1(unscale)) { /* implies lc(x0) = 1 and L := 1/unscale is integral */ long d = degpol(T.x0); GEN L = ginv(unscale); /* x = L^(-deg(x)) x0(L X) */ GEN f= powiu(L, (d*(d-1)) >> 1); T.x = T.x0; /* restore original user-supplied x0, unscale data */ T.unscale = gen_1; T.dx = gmul(T.dx, sqri(f)); T.bas = RgXV_unscale(T.bas, unscale); T.index = gmul(T.index, f); } nfbasic_add_disc(&T); /* more expensive after set_LLL_basis */ if (flag & nf_RED) { GEN ro, rev; /* lie to polred: more efficient to update *after* modreverse, than to * unscale in the polred subsystem */ T.unscale = gen_1; rev = nfpolred(&T, &ro); nf = nfbasic_to_nf(&T, ro, prec); if (flag & nf_ORIG) { if (!rev) rev = pol_x(varn(T.x)); /* no improvement */ if (!isint1(unscale)) rev = RgX_Rg_div(rev, unscale); nf = mkvec2(nf, mkpolmod(rev, T.x)); } T.unscale = unscale; /* restore */ } else { GEN ro; set_LLL_basis(&T, &ro, 0.99); nf = nfbasic_to_nf(&T, ro, prec); } return gerepilecopy(av, nf); } GEN nfinitred(GEN x, long prec) { return nfinitall(x, nf_RED, prec); } GEN nfinitred2(GEN x, long prec) { return nfinitall(x, nf_RED|nf_ORIG, prec); } GEN nfinit(GEN x, long prec) { return nfinitall(x, 0, prec); } GEN nfinit0(GEN x, long flag,long prec) { switch(flag) { case 0: case 1: return nfinitall(x,0,prec); case 2: case 4: return nfinitall(x,nf_RED,prec); case 3: case 5: return nfinitall(x,nf_RED|nf_ORIG,prec); default: pari_err_FLAG("nfinit"); } return NULL; /* not reached */ } /* assume x a bnr/bnf/nf */ long nf_get_prec(GEN x) { GEN nf = checknf(x), ro = nf_get_roots(nf); return (typ(ro)==t_VEC)? precision(gel(ro,1)): DEFAULTPREC; } /* assume nf is an nf */ GEN nfnewprec_shallow(GEN nf, long prec) { GEN NF = leafcopy(nf); nffp_t F; gel(NF,5) = leafcopy(gel(NF,5)); remake_GM(NF, &F, prec); gel(NF,6) = F.ro; gmael(NF,5,1) = F.M; gmael(NF,5,2) = F.G; return NF; } GEN nfnewprec(GEN nf, long prec) { GEN z; switch(nftyp(nf)) { default: pari_err_TYPE("nfnewprec", nf); case typ_BNF: z = bnfnewprec(nf,prec); break; case typ_BNR: z = bnrnewprec(nf,prec); break; case typ_NF: { pari_sp av = avma; z = gerepilecopy(av, nfnewprec_shallow(checknf(nf), prec)); break; } } return z; } /********************************************************************/ /** **/ /** POLRED **/ /** **/ /********************************************************************/ GEN embednorm_T2(GEN x, long r1) { pari_sp av = avma; GEN p = RgV_sumpart(x, r1); GEN q = RgV_sumpart2(x,r1+1, lg(x)-1); if (q != gen_0) p = gadd(p, gmul2n(q,1)); return avma == av? gcopy(p): gerepileupto(av, p); } /* simplified version of gnorm for scalar, non-complex inputs, without GC */ static GEN real_norm(GEN x) { switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_FRAC: return sqrfrac(x); } pari_err_TYPE("real_norm", x); return NULL; } /* simplified version of gnorm, without GC */ static GEN complex_norm(GEN x) { return typ(x) == t_COMPLEX? cxnorm(x): real_norm(x); } /* return T2(x), argument r1 needed in case x has components whose type * is unexpected, e.g. all of them t_INT for embed(gen_1) */ GEN embed_T2(GEN x, long r1) { pari_sp av = avma; long i, l = lg(x); GEN c, s = NULL, t = NULL; if (typ(gel(x,1)) == t_INT) return muliu(gel(x,1), 2*(l-1)-r1); for (i = 1; i <= r1; i++) { c = real_norm(gel(x,i)); s = s? gadd(s, c): c; } for (; i < l; i++) { c = complex_norm(gel(x,i)); t = t? gadd(t, c): c; } if (t) { t = gmul2n(t,1); s = s? gadd(s,t): t; } return gerepileupto(av, s); } /* return N(x) */ GEN embed_norm(GEN x, long r1) { pari_sp av = avma; long i, l = lg(x); GEN c, s = NULL, t = NULL; if (typ(gel(x,1)) == t_INT) return powiu(gel(x,1), 2*(l-1)-r1); for (i = 1; i <= r1; i++) { c = gel(x,i); s = s? gmul(s, c): c; } for (; i < l; i++) { c = complex_norm(gel(x,i)); t = t? gmul(t, c): c; } if (t) s = s? gmul(s,t): t; return gerepileupto(av, s); } typedef struct { long r1, v, prec; GEN ZKembed; /* embeddings of fincke-pohst-reduced Zk basis */ GEN u; /* matrix giving fincke-pohst-reduced Zk basis */ GEN M; /* embeddings of initial (LLL-reduced) Zk basis */ GEN bound; /* T2 norm of the polynomial defining nf */ long expo_best_disc; /* expo(disc(x)), best generator so far */ } CG_data; /* characteristic pol of x (given by embeddings) */ static GEN get_pol(CG_data *d, GEN x) { long e; GEN g = grndtoi(roots_to_pol_r1(x, d->v, d->r1), &e); return (e > -5)? NULL: g; } /* characteristic pol of x (given as vector on (w_i)) */ static GEN get_polchar(CG_data *d, GEN x) { return get_pol(d, RgM_RgC_mul(d->ZKembed,x)); } /* Choose a canonical polynomial in the pair { z(X), (+/-)z(-X) }. * z a ZX with lc(z) > 0. We want to keep that property, while * ensuring that the leading coeff of the odd (resp. even) part of z is < 0 * if deg z is even (resp. odd). * Either leave z alone (return 1) or set z <-- (-1)^deg(z) z(-X). In place. */ static int ZX_canon_neg(GEN z) { long i,s; for (i = lg(z)-2; i >= 2; i -= 2) { /* examine the odd (resp. even) part of z if deg(z) even (resp. odd). */ s = signe(gel(z,i)); if (!s) continue; /* non trivial */ if (s < 0) break; /* the condition is already satisfied */ for (; i>=2; i-=2) gel(z,i) = negi(gel(z,i)); return 1; } return 0; } /* return a defining polynomial for Q(alpha), v = embeddings of alpha. * Return NULL on failure: discriminant too large or non primitive */ static GEN try_polmin(CG_data *d, nfbasic_t *T, GEN v, long flag, GEN *ai) { const long best = flag & nf_ABSOLUTE; long ed; pari_sp av = avma; GEN g; if (best) { ed = expo(embed_disc(v, d->r1, LOWDEFAULTPREC)); avma = av; if (d->expo_best_disc < ed) return NULL; } else ed = 0; g = get_pol(d, v); /* accuracy too low, compute algebraically */ if (!g) { avma = av; g = ZXQ_charpoly(*ai, T->x, varn(T->x)); } (void)ZX_gcd_all(g, ZX_deriv(g), &g); if (best && degpol(g) != degpol(T->x)) { avma = av; return NULL; } g = gerepilecopy(av, g); d->expo_best_disc = ed; if (flag & nf_ORIG) { if (ZX_canon_neg(g)) *ai = RgX_neg(*ai); if (!isint1(T->unscale)) *ai = RgX_unscale(*ai, T->unscale); } else (void)ZX_canon_neg(g); if (DEBUGLEVEL>3) err_printf("polred: generator %Ps\n", g); return g; } /* does x generate the correct field ? */ static GEN chk_gen(void *data, GEN x) { pari_sp av = avma, av1; GEN h, g = get_polchar((CG_data*)data,x); if (!g) pari_err_PREC("chk_gen"); av1 = avma; h = ZX_gcd(g, ZX_deriv(g)); if (degpol(h)) { avma = av; return NULL; } if (DEBUGLEVEL>3) err_printf(" generator: %Ps\n",g); avma = av1; return gerepileupto(av, g); } static long chk_gen_prec(long N, long bit) { return nbits2prec(10 + (long)log2((double)N) + bit); } /* Remove duplicate polynomials in P, updating A (same indices), in place. * Among elements having the same characteristic pol, choose the smallest * according to ZV_abscmp */ static void remove_duplicates(GEN P, GEN A) { long k, i, l = lg(P); pari_sp av = avma; GEN x, a; if (l < 2) return; (void)sort_factor_pol(mkmat2(P, A), cmpii); x = gel(P,1); a = gel(A,1); for (k=1,i=2; ix); double log2rho; 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; e = n * (long)(log2rho + log2((double)n)) + 1; if (e < 0) e = 0; /* can occur if n = 1 */ prec = chk_gen_prec(n, e); get_nf_fp_compo(T, F, ro, 1, prec); d->v = varn(T->x); d->expo_best_disc = -1; d->ZKembed = NULL; d->M = NULL; d->u = NULL; d->r1= T->r1; return prec; } static GEN findmindisc(GEN y, GEN *pa) { GEN a = *pa, x = gel(y,1), b = gel(a,1), dx = NULL; long i, l = lg(y); for (i = 2; i < l; i++) { GEN yi = gel(y,i); if (ZX_is_better(yi,x,&dx)) { x = yi; b = gel(a,i); } } *pa = b; return x; } /* filter [y,b] from polred_aux: keep a single polynomial of degree n in y * [ the best wrt discriminant ordering ], but keep all non-primitive * polynomials */ static void filter(GEN y, GEN b, long n) { GEN x, a, dx; long i, k = 1, l = lg(y); a = x = dx = NULL; for (i = 1; i < l; i++) { GEN yi = gel(y,i), ai = gel(b,i); if (degpol(yi) == n) { pari_sp av = avma; if (dx && !ZX_is_better(yi,x,&dx)) { avma = av; continue; } if (!dx) dx = ZX_disc(yi); x = yi; a = ai; continue; } gel(y,k) = yi; gel(b,k) = ai; k++; } if (dx) { gel(y,k) = x; gel(b,k) = a; k++; } setlg(y, k); setlg(b, k); } static GEN polred_aux(nfbasic_t *T, GEN *pro, long flag) { /* only keep polynomials of max degree and best discriminant */ const long best = flag & nf_ABSOLUTE; const long orig = flag & nf_ORIG; GEN M, b, y, x = T->x; long maxi, i, j, k, v = varn(x), n = lg(T->bas)-1; nffp_t F; CG_data d; if (n == 1) { if (!best) { GEN ch = deg1pol_shallow(gen_1, gen_m1, v); return orig? mkmat2(mkcol(ch),mkcol(gen_1)): mkvec(ch); } else return orig? trivial_fact(): cgetg(1,t_VEC); } (void)polred_init(T, &F, &d); *pro = F.ro; M = F.M; if (best) { if (!T->dx) T->dx = ZX_disc(T->x); d.expo_best_disc = expi(T->dx); } /* n + 2 sum_{1 <= i <= n} n-i = n + n(n-1) = n*n */ y = cgetg(n*n + 1, t_VEC); b = cgetg(n*n + 1, t_COL); k = 1; if (!best) { GEN ch = deg1pol_shallow(gen_1, gen_m1, v); gel(y,1) = ch; gel(b,1) = gen_1; k++; } for (i = 2; i <= n; i++) { GEN ch, ai; ai = gel(T->bas,i); ch = try_polmin(&d, T, gel(M,i), flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } } maxi = minss(n, 3); for (i = 1; i <= maxi; i++) for (j = i+1; j <= n; j++) { GEN ch, ai, v; ai = gadd(gel(T->bas,i), gel(T->bas,j)); v = RgV_add(gel(M,i), gel(M,j)); /* defining polynomial for Q(w_i+w_j) */ ch = try_polmin(&d, T, v, flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } ai = gsub(gel(T->bas,i), gel(T->bas,j)); v = RgV_sub(gel(M,i), gel(M,j)); /* defining polynomial for Q(w_i-w_j) */ ch = try_polmin(&d, T, v, flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } } setlg(y, k); setlg(b, k); filter(y, b, n); if (!orig) return gen_sort_uniq(y, (void*)cmpii, &gen_cmp_RgX); (void)sort_factor_pol(mkmat2(y, b), cmpii); settyp(y, t_COL); return mkmat2(b, y); } static GEN Polred(GEN x, long flag, GEN fa) { pari_sp av = avma; GEN ro; nfbasic_t T; nfbasic_init(fa? mkvec2(x,fa): x, flag & nf_PARTIALFACT, &T); return gerepilecopy(av, polred_aux(&T, &ro, flag)); } /* finds "best" polynomial in polred_aux list, defaulting to T->x if none of * them is primitive. *px is the ZX, characteristic polynomial of Mod(*pb,T->x), * *pdx its discriminant. Set *pro = polroots(T->x) [ NOT *px ]. */ static void polredbest_aux(nfbasic_t *T, GEN *pro, GEN *px, GEN *pdx, GEN *pb) { GEN y, x = T->x; /* default value */ long i, l; y = polred_aux(T, pro, pb? nf_ORIG|nf_ABSOLUTE: nf_ABSOLUTE); *pdx = T->dx; if (pb) { GEN a, b = deg1pol_shallow(T->unscale, gen_0, varn(x)); a = gel(y,1); l = lg(a); y = gel(y,2); for (i=1; i 1) pari_err_FLAG("polredbest"); T = T0; nfbasic_init(T, nf_PARTIALFACT, &S); polredbest_aux(&S, &ro, &T, &dT, flag? &a: NULL); if (flag) { /* charpoly(Mod(a,T0)) = T */ GEN b; if (T0 == T) b = pol_x(varn(T)); /* no improvement */ else b = QXQ_reverse(a, T0); /* charpoly(Mod(b,T)) = S.x */ b = (degpol(T) == 1)? gmodulo(b, T): mkpolmod(b,T); T = mkvec2(T, b); } return gerepilecopy(av, T); } /* DEPRECATED: backward compatibility */ GEN polred0(GEN x, long flag, GEN fa) { long fl = 0; if (flag & 1) fl |= nf_PARTIALFACT; if (flag & 2) fl |= nf_ORIG; return Polred(x, fl, fa); } GEN polredord(GEN x) { pari_sp av = avma; GEN v, lt; long i, n, vx; if (typ(x) != t_POL) pari_err_TYPE("polredord",x); x = Q_primpart(x); RgX_check_ZX(x,"polredord"); n = degpol(x); if (n <= 0) pari_err_CONSTPOL("polredord"); if (n == 1) return gerepilecopy(av, mkvec(x)); lt = leading_term(x); vx = varn(x); if (is_pm1(lt)) { if (signe(lt) < 0) x = ZX_neg(x); v = pol_x_powers(n, vx); } else { GEN L; /* basis for Dedekind order */ v = cgetg(n+1, t_VEC); gel(v,1) = scalarpol_shallow(lt, vx); for (i = 2; i <= n; i++) gel(v,i) = RgX_Rg_add(RgX_mulXn(gel(v,i-1), 1), gel(x,n+3-i)); gel(v,1) = pol_1(vx); x = ZX_Q_normalize(x, &L); v = gsubst(v, vx, monomial(ginv(L),1,vx)); for (i=2; i <= n; i++) if (Q_denom(gel(v,i)) == gen_1) gel(v,i) = monomial(gen_1, i-1, vx); } return gerepileupto(av, polred(mkvec2(x, v))); } GEN polred(GEN x) { return Polred(x, 0, NULL); } GEN smallpolred(GEN x) { return Polred(x, nf_PARTIALFACT, NULL); } GEN factoredpolred(GEN x, GEN fa) { return Polred(x, 0, fa); } GEN polred2(GEN x) { return Polred(x, nf_ORIG, NULL); } GEN smallpolred2(GEN x) { return Polred(x, nf_PARTIALFACT|nf_ORIG, NULL); } GEN factoredpolred2(GEN x, GEN fa) { return Polred(x, nf_PARTIALFACT, fa); } /********************************************************************/ /** **/ /** POLREDABS **/ /** **/ /********************************************************************/ /* set V[k] := matrix of multiplication by nk.zk[k] */ static GEN set_mulid(GEN V, GEN M, GEN Mi, long r1, long r2, long N, long k) { GEN v, Mk = cgetg(N+1, t_MAT); long i, e; for (i = 1; i < k; i++) gel(Mk,i) = gmael(V, i, k); for ( ; i <=N; i++) { v = vecmul(gel(M,k), gel(M,i)); v = RgM_RgC_mul(Mi, split_realimag(v, r1, r2)); gel(Mk,i) = grndtoi(v, &e); if (e > -5) return NULL; } gel(V,k) = Mk; return Mk; } static GEN ZM_image_shallow(GEN M, long *pr) { long j, k, r; GEN y, d = ZM_pivots(M, &k); r = lg(M)-1 - k; y = cgetg(r+1,t_MAT); for (j=k=1; j<=r; k++) if (d[k]) gel(y,j++) = gel(M,k); *pr = r; return y; } /* U = base change matrix, R = Cholesky form of the quadratic form [matrix * Q from algo 2.7.6] */ static GEN chk_gen_init(FP_chk_fun *chk, GEN R, GEN U) { CG_data *d = (CG_data*)chk->data; GEN P, V, D, inv, bound, S, M; long N = lg(U)-1, r1 = d->r1, r2 = (N-r1)>>1; long i, j, prec, firstprim = 0, skipfirst = 0; pari_sp av; d->u = U; d->ZKembed = M = RgM_mul(d->M, U); av = avma; bound = d->bound; D = cgetg(N+1, t_VECSMALL); for (i = 1; i <= N; i++) { pari_sp av2 = avma; P = get_pol(d, gel(M,i)); if (!P) pari_err_PREC("chk_gen_init"); (void)ZX_gcd_all(P, ZX_deriv(P), &P); P = gerepilecopy(av2, P); D[i] = degpol(P); if (D[i] == N) { /* primitive element */ GEN B = embed_T2(gel(M,i), r1); if (!firstprim) firstprim = i; /* index of first primitive element */ if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); if (gcmp(B,bound) < 0) bound = gerepileuptoleaf(av2, B); } else { if (DEBUGLEVEL>2) err_printf("chk_gen_init: subfield %Ps\n",P); if (firstprim) { /* cycle basis vectors so that primitive elements come last */ GEN u = d->u, e = M; GEN te = gel(e,i), tu = gel(u,i), tR = gel(R,i); long tS = D[i]; for (j = i; j > firstprim; j--) { u[j] = u[j-1]; e[j] = e[j-1]; R[j] = R[j-1]; D[j] = D[j-1]; } gel(u,firstprim) = tu; gel(e,firstprim) = te; gel(R,firstprim) = tR; D[firstprim] = tS; firstprim++; } } } if (!firstprim) { /* try (a little) to find primitive elements to improve bound */ GEN x = cgetg(N+1, t_VECSMALL); if (DEBUGLEVEL>1) err_printf("chk_gen_init: difficult field, trying random elements\n"); for (i = 0; i < 10; i++) { GEN e, B; for (j = 1; j <= N; j++) x[j] = (long)random_Fl(7) - 3; e = RgM_zc_mul(M, x); B = embed_T2(e, r1); if (gcmp(B,bound) >= 0) continue; P = get_pol(d, e); if (!P) pari_err_PREC( "chk_gen_init"); if (!ZX_is_squarefree(P)) continue; if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); bound = B ; } } if (firstprim != 1) { inv = ginv( split_realimag(M, r1, r2) ); /*TODO: use QR?*/ V = gel(inv,1); for (i = 2; i <= r1+r2; i++) V = gadd(V, gel(inv,i)); /* V corresponds to 1_Z */ V = grndtoi(V, &j); if (j > -5) pari_err_BUG("precision too low in chk_gen_init"); S = mkmat(V); /* 1 */ V = cgetg(N+1, t_VEC); for (i = 1; i <= N; i++,skipfirst++) { /* S = Q-basis of subfield generated by nf.zk[1..i-1] */ GEN Mx, M2; long j, k, h, rkM, dP = D[i]; if (dP == N) break; /* primitive */ Mx = set_mulid(V, M, inv, r1, r2, N, i); if (!Mx) break; /* prec. problem. Stop */ if (dP == 1) continue; rkM = lg(S)-1; M2 = cgetg(N+1, t_MAT); /* we will add to S the elts of M2 */ gel(M2,1) = col_ei(N, i); /* nf.zk[i] */ k = 2; for (h = 1; h < dP; h++) { long r; /* add to M2 the elts of S * nf.zk[i] */ for (j = 1; j <= rkM; j++) gel(M2,k++) = ZM_ZC_mul(Mx, gel(S,j)); setlg(M2, k); k = 1; S = ZM_image_shallow(shallowconcat(S,M2), &r); if (r == rkM) break; if (r > rkM) { rkM = r; if (rkM == N) break; } } if (rkM == N) break; /* Q(w[1],...,w[i-1]) is a strict subfield of nf */ } } /* x_1,...,x_skipfirst generate a strict subfield [unless N=skipfirst=1] */ chk->skipfirst = skipfirst; if (DEBUGLEVEL>2) err_printf("chk_gen_init: skipfirst = %ld\n",skipfirst); /* should be DEF + gexpo( max_k C^n_k (bound/k)^(k/2) ) */ bound = gerepileuptoleaf(av, bound); prec = chk_gen_prec(N, (gexpo(bound)*N)/2); if (DEBUGLEVEL) err_printf("chk_gen_init: new prec = %ld (initially %ld)\n", prec, d->prec); if (prec > d->prec) pari_err_BUG("polredabs (precision problem)"); if (prec < d->prec) d->ZKembed = gprec_w(M, prec); return bound; } /* z "small" minimal polynomial of Mod(a,x), deg z = deg x */ static GEN store(GEN x, GEN z, GEN a, nfbasic_t *T, long flag, GEN u) { GEN y, b; if (u) a = RgV_RgC_mul(T->bas, ZM_ZC_mul(u, a)); if (flag & (nf_ORIG|nf_ADDZK)) { b = QXQ_reverse(a, x); if (!isint1(T->unscale)) b = gdiv(b, T->unscale); /* not RgX_Rg_div */ } else b = NULL; if (flag & nf_RAW) y = mkvec2(z, a); else if (flag & nf_ORIG) /* store phi(b mod z). */ y = mkvec2(z, mkpolmod(b,z)); else y = z; if (flag & nf_ADDZK) { /* append integral basis for number field Q[X]/(z) to result */ long n = degpol(x); GEN t = RgV_RgM_mul(RgXQ_powers(b, n-1, z), RgV_to_RgM(T->bas,n)); y = mkvec2(y, t); } return y; } static GEN polredabs_aux(nfbasic_t *T, GEN *u) { long prec; GEN v; FP_chk_fun chk = { &chk_gen, &chk_gen_init, NULL, NULL, 0 }; nffp_t F; CG_data d; chk.data = (void*)&d; prec = polred_init(T, &F, &d); d.bound = embed_T2(F.ro, d.r1); if (realprec(d.bound) > prec) d.bound = rtor(d.bound, prec); for (;;) { GEN R = R_from_QR(F.G, prec); if (R) { d.prec = prec; d.M = F.M; v = fincke_pohst(mkvec(R),NULL,-1, 0, &chk); if (v) break; } prec = precdbl(prec); get_nf_fp_compo(T, &F, NULL, 1, prec); if (DEBUGLEVEL) pari_warn(warnprec,"polredabs0",prec); } *u = d.u; return v; } GEN polredabs0(GEN x, long flag) { pari_sp av = avma; long i, l, vx; GEN y, a, u; nfbasic_t T; nfbasic_init(x, flag & nf_PARTIALFACT, &T); x = T.x; vx = varn(x); if (degpol(x) == 1) { u = NULL; y = mkvec( pol_x(vx) ); a = mkvec( deg1pol_shallow(gen_1, negi(gel(x,2)), vx) ); l = 2; } else { GEN v; if (!(flag & nf_PARTIALFACT) && T.dKP && lg(primes_certify(T.dK, T.dKP)) != 1) return gen_0; v = polredabs_aux(&T, &u); y = gel(v,1); a = gel(v,2); l = lg(a); for (i=1; i1) timer_start(&ti); T = nf_get_pol(nf); relpol = RgX_nffix(f, T, relpol, 0); if (best || (flag & nf_PARTIALFACT)) { if (abs) { rnfeq = nf_rnfeq(nf, relpol); pol = gel(rnfeq,1); } else { long sa; pol = rnfequationall(nf, relpol, &sa, NULL); rnfeq = mkvec5(gen_0,gen_0,stoi(sa),T,liftpol_shallow(relpol)); } bas = listP? mkvec2(pol, listP): pol; if (best) { if (abs) red = polredbest(bas, 1); else { GEN ro, x, dx, a; nfbasic_t T; nfbasic_init(bas, nf_PARTIALFACT, &T); polredbest_aux(&T, &ro, &x, &dx, &a); red = mkvec2(x, a); } } else red = polredabs0(bas, (abs? nf_ORIG: nf_RAW)|nf_PARTIALFACT); } else { GEN rnf = rnfinit(nf, relpol), M = rnf_basM(rnf); rnfeq = rnf_get_map(rnf); pol = rnf_get_polabs(rnf); bas = mkvec2(pol, RgM_to_RgXV(M, varn(pol))); if (DEBUGLEVEL>1) timer_printf(&ti, "absolute basis"); red = polredabs0(bas, nf_RAW); } P = gel(red,1); A = gel(red,2); if (DEBUGLEVEL>1) err_printf("reduced absolute generator: %Ps\n",P); if (flag & nf_ABSOLUTE) { if (flag & nf_ORIG) { GEN a = gel(rnfeq,2); /* Mod(a,pol) root of T */ GEN k = gel(rnfeq,3); /* Mod(variable(relpol),relpol) + k*a root of pol */ a = RgX_RgXQ_eval(a, lift_intern(A), P); /* Mod(a, P) root of T */ P = mkvec3(P, mkpolmod(a,P), gsub(A, gmul(k,a))); } return gerepilecopy(av, P); } A = eltabstorel_lift(rnfeq, A); P = RgXQ_charpoly(A, relpol, varn(relpol)); P = lift_if_rational(P); if (flag & nf_ORIG) P = mkvec2(P, mkpolmod(RgXQ_reverse(A,relpol),P)); return gerepilecopy(av, P); } GEN rnfpolredabs(GEN nf, GEN relpol, long flag) { return rnfpolred_i(nf,relpol,flag, 0); } GEN rnfpolredbest(GEN nf, GEN relpol, long flag) { if (flag < 0 || flag > 3) pari_err_FLAG("rnfpolredbest"); return rnfpolred_i(nf,relpol,flag, 1); } pari-2.7.5/src/basemath/trans2.c0000644000175000017500000014210012573015517015042 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** (part 2) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, GEN *tau, pari_sp *av, GEN *res) { GEN s, p1; long l; if (typ(*s0)==t_COMPLEX && gequal0(gel(*s0,2))) *s0 = gel(*s0,1); s = *s0; l = precision(s); if (!l) l = *prec; if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC; *res = cgetc(l); *av = avma; if (typ(s) == t_COMPLEX) { /* s = sig + i t */ s = cxtofp(s, l+EXTRAPRECWORD); *sig = gel(s,1); *tau = gel(s,2); } else /* real number */ { *sig = s = gtofp(s, l+EXTRAPRECWORD); *tau = gen_0; p1 = trunc2nr(s, 0); if (!signe(subri(s,p1))) *s0 = p1; } *prec = l; return s; } /********************************************************************/ /** **/ /** ARCTANGENT **/ /** **/ /********************************************************************/ static GEN mpatan(GEN x) { long l, l1, l2, n, m, i, lp, e, s, sx = signe(x); pari_sp av0, av; double alpha, beta, delta; GEN y, p1, p2, p3, p4, p5, unr; int inv; if (!sx) return real_0_bit(expo(x)); l = lp = realprec(x); if (absrnz_equal1(x)) { /* |x| = 1 */ y = Pi2n(-2, l+EXTRAPRECWORD); if (sx < 0) setsigne(y,-1); return y; } if (l > AGM_ATAN_LIMIT) { av = avma; y = logagmcx(mkcomplex(gen_1, x), l); return gerepileuptoleaf(av, gel(y,2)); } e = expo(x); inv = (e >= 0); /* = (|x| > 1 ) */ if (e > 0) lp += nbits2extraprec(e); y = cgetr(lp); av0 = avma; p1 = rtor(x, l+EXTRAPRECWORD); setabssign(p1); /* p1 = |x| */ if (inv) p1 = invr(p1); e = expo(p1); if (e < -100) alpha = 1.65149612947 - e; /* log_2(Pi) - e */ else alpha = log2(PI / atan(rtodbl(p1))); beta = (double)(prec2nbits(l)>>1); delta = 1 + beta - alpha/2; if (delta <= 0) { n = 1; m = 0; } else { double fi = alpha-2; if (delta >= fi*fi) { double t = 1 + sqrt(delta); n = (long)t; m = (long)(t - fi); } else { n = (long)(1+beta/fi); m = 0; } } l2 = l + nbits2extraprec(m); p2 = rtor(p1, l2); av = avma; for (i=1; i<=m; i++) { p5 = addsr(1, sqrr(p2)); setprec(p5,l2); p5 = addsr(1, sqrtr_abs(p5)); setprec(p5,l2); affrr(divrr(p2,p5), p2); avma = av; } p3 = sqrr(p2); l1 = minss(LOWDEFAULTPREC+EXTRAPRECWORD, l2); /* l1 increases to l2 */; unr = real_1(l2); setprec(unr,l1); p4 = cgetr(l2); setprec(p4,l1); affrr(divru(unr,2*n+1), p4); s = 0; e = expo(p3); av = avma; for (i = n; i > 1; i--) /* n >= 1. i = 1 done outside for efficiency */ { setprec(p3,l1); p5 = mulrr(p4,p3); l1 += dvmdsBIL(s - e, &s); if (l1 > l2) l1 = l2; setprec(unr,l1); p5 = subrr(divru(unr,2*i-1), p5); setprec(p4,l1); affrr(p5,p4); avma = av; } setprec(p3, l2); p5 = mulrr(p4,p3); /* i = 1 */ setprec(unr,l2); p4 = subrr(unr, p5); p4 = mulrr(p2,p4); shiftr_inplace(p4, m); if (inv) p4 = subrr(Pi2n(-1, lp), p4); if (sx < 0) togglesign(p4); affrr_fixlg(p4,y); avma = av0; return y; } GEN gatan(GEN x, long prec) { pari_sp av; GEN a, y; switch(typ(x)) { case t_REAL: return mpatan(x); case t_COMPLEX: /* atan(x) = -i atanh(ix) */ if (ismpzero(gel(x,2))) return gatan(gel(x,1), prec); av = avma; return gerepilecopy(av, mulcxmI(gatanh(mulcxI(x),prec))); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err_DOMAIN("atan","valuation", "<", gen_0, x); if (lg(y)==2) return gerepilecopy(av, y); /* lg(y) > 2 */ a = integser(gdiv(derivser(y), gaddsg(1,gsqr(y)))); if (!valp(y)) a = gadd(a, gatan(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("atan",gatan,x,prec); } /********************************************************************/ /** **/ /** ARCSINE **/ /** **/ /********************************************************************/ /* |x| < 1, x != 0 */ static GEN mpasin(GEN x) { pari_sp av = avma; GEN z, a = sqrtr(subsr(1, sqrr(x))); if (realprec(x) > AGM_ATAN_LIMIT) { z = logagmcx(mkcomplex(a,x), realprec(x)); z = gel(z,2); } else z = mpatan(divrr(x, a)); return gerepileuptoleaf(av, z); } static GEN mpacosh(GEN x); GEN gasin(GEN x, long prec) { long sx; pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: sx = signe(x); if (!sx) return real_0_bit(expo(x)); if (absrnz_equal1(x)) { /* |x| = 1 */ if (sx > 0) return Pi2n(-1, realprec(x)); /* 1 */ y = Pi2n(-1, realprec(x)); setsigne(y, -1); return y; /* -1 */ } if (expo(x) < 0) return mpasin(x); y = cgetg(3,t_COMPLEX); gel(y,1) = Pi2n(-1, realprec(x)); gel(y,2) = mpacosh(x); if (sx < 0) togglesign(gel(y,1)); else togglesign(gel(y,2)); return y; case t_COMPLEX: /* asin(z) = -i asinh(iz) */ if (ismpzero(gel(x,2))) return gasin(gel(x,1), prec); av = avma; return gerepilecopy(av, mulcxmI(gasinh(mulcxI(x), prec))); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); /* lg(y) > 2*/ if (valp(y) < 0) pari_err_DOMAIN("asin","valuation", "<", gen_0, x); p1 = gsubsg(1,gsqr(y)); if (gequal0(p1)) { GEN t = Pi2n(-1,prec); if (gsigne(gel(y,2)) < 0) setsigne(t, -1); return gerepileupto(av, scalarser(t, varn(y), valp(p1)>>1)); } p1 = gdiv(derivser(y), gsqrt(p1,prec)); a = integser(p1); if (!valp(y)) a = gadd(a, gasin(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("asin",gasin,x,prec); } /********************************************************************/ /** **/ /** ARCCOSINE **/ /** **/ /********************************************************************/ static GEN acos0(long e) { return Pi2n(-1, nbits2prec(e<0? -e: 1)); } /* |x| < 1, x != 0 */ static GEN mpacos(GEN x) { pari_sp av = avma; GEN z, a = sqrtr(subsr(1, sqrr(x))); if (realprec(x) > AGM_ATAN_LIMIT) { z = logagmcx(mkcomplex(x,a), realprec(x)); z = gel(z,2); } else { z = mpatan(divrr(a, x)); if (signe(x) < 0) z = addrr(mppi(realprec(z)), z); } return gerepileuptoleaf(av, z); } GEN gacos(GEN x, long prec) { long sx; pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: sx = signe(x); if (!sx) return acos0(expo(x)); if (absrnz_equal1(x)) /* |x| = 1 */ return sx > 0? real_0_bit( -(bit_prec(x)>>1) ) : mppi(realprec(x)); if (expo(x) < 0) return mpacos(x); y = cgetg(3,t_COMPLEX); p1 = mpacosh(x); if (sx < 0) { gel(y,1) = mppi(realprec(x)); togglesign(p1); } else gel(y,1) = gen_0; gel(y,2) = p1; return y; case t_COMPLEX: if (ismpzero(gel(x,2))) return gacos(gel(x,1), prec); av = avma; p1 = gadd(x, mulcxI(gsqrt(gsubsg(1,gsqr(x)), prec))); y = glog(p1,prec); /* log(x + I*sqrt(1-x^2)) */ return gerepilecopy(av, mulcxmI(y)); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err_DOMAIN("acos","valuation", "<", gen_0, x); if (lg(y) > 2) { p1 = gsubsg(1,gsqr(y)); 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); } else p1 = y; a = (lg(y)==2 || valp(y))? Pi2n(-1, prec): gacos(gel(y,2),prec); return gerepileupto(av, gadd(a,p1)); } return trans_eval("acos",gacos,x,prec); } /********************************************************************/ /** **/ /** ARGUMENT **/ /** **/ /********************************************************************/ /* we know that x and y are not both 0 */ static GEN mparg(GEN x, GEN y) { long prec, sx = signe(x), sy = signe(y); GEN z; if (!sy) { if (sx > 0) return real_0_bit(expo(y) - expo(x)); return mppi(realprec(x)); } prec = realprec(y); if (prec < realprec(x)) prec = realprec(x); if (!sx) { z = Pi2n(-1, prec); if (sy < 0) setsigne(z,-1); return z; } if (expo(x)-expo(y) > -2) { z = mpatan(divrr(y,x)); if (sx > 0) return z; return addrr_sign(z, signe(z), mppi(prec), sy); } z = mpatan(divrr(x,y)); return addrr_sign(z, -signe(z), Pi2n(-1, prec), sy); } static GEN rfix(GEN x,long prec) { switch(typ(x)) { case t_INT: return itor(x, prec); case t_FRAC: return fractor(x, prec); case t_REAL: break; default: pari_err_TYPE("rfix (conversion to t_REAL)",x); } return x; } static GEN cxarg(GEN x, GEN y, long prec) { pari_sp av = avma; x = rfix(x,prec); y = rfix(y,prec); return gerepileuptoleaf(av, mparg(x,y)); } GEN garg(GEN x, long prec) { if (gequal0(x)) pari_err_DOMAIN("arg", "argument", "=", gen_0, x); switch(typ(x)) { case t_REAL: prec = realprec(x); /* fall through */ case t_INT: case t_FRAC: return (gsigne(x)>0)? real_0(prec): mppi(prec); case t_COMPLEX: return cxarg(gel(x,1),gel(x,2),prec); } return trans_eval("arg",garg,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ static GEN mpcosh(GEN x) { pari_sp av; GEN z; if (!signe(x)) { /* 1 + x */ long e = expo(x); return e >= 0? real_0_bit(e): real_1(nbits2prec(-e)); } av = avma; z = mpexp(x); z = addrr(z, invr(z)); shiftr_inplace(z, -1); return gerepileuptoleaf(av, z); } GEN gcosh(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: return mpcosh(x); case t_COMPLEX: if (isintzero(gel(x,1))) return gcos(gel(x,2),prec); /* fall through */ case t_PADIC: av = avma; p1 = gexp(x,prec); p1 = gadd(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y) && valp(y) == 0) return gerepilecopy(av, y); p1 = gexp(y,prec); p1 = gadd(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); } return trans_eval("cosh",gcosh,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC SINE **/ /** **/ /********************************************************************/ static GEN mpsinh(GEN x) { pari_sp av; long ex = expo(x), lx; GEN z, res; if (!signe(x)) return real_0_bit(ex); lx = realprec(x); res = cgetr(lx); av = avma; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lx + nbits2extraprec(-ex)-1); z = mpexp(x); z = subrr(z, invr(z)); shiftr_inplace(z, -1); affrr(z, res); avma = av; return res; } GEN gsinh(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: return mpsinh(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0, gsin(gel(x,2),prec)); /* fall through */ case t_PADIC: av = avma; p1 = gexp(x,prec); p1 = gsub(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y) && valp(y) == 0) return gerepilecopy(av, y); p1 = gexp(y, prec); p1 = gsub(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); } return trans_eval("sinh",gsinh,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ static GEN mptanh(GEN x) { long lx, s = signe(x); GEN y; if (!s) return real_0_bit(expo(x)); lx = realprec(x); if (absr_cmp(x, stor(prec2nbits(lx), LOWDEFAULTPREC)) >= 0) { y = real_1(lx); } else { pari_sp av = avma; long ex = expo(x); GEN t; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lx + nbits2extraprec(-ex)-1); t = exp1r_abs(gmul2n(x,1)); /* exp(|2x|) - 1 */ y = gerepileuptoleaf(av, divrr(t, addsr(2,t))); } if (s < 0) togglesign(y); /* tanh is odd */ return y; } GEN gtanh(GEN x, long prec) { pari_sp av; GEN y, t; switch(typ(x)) { case t_REAL: return mptanh(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0, gtan(gel(x,2),prec)); /* fall through */ case t_PADIC: av = avma; t = gexp(gmul2n(x,1),prec); t = gdivsg(-2, gaddgs(t,1)); return gerepileupto(av, gaddsg(1,t)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); t = gexp(gmul2n(y, 1),prec); t = gdivsg(-2, gaddgs(t,1)); return gerepileupto(av, gaddsg(1,t)); } return trans_eval("tanh",gtanh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC SINE **/ /** **/ /********************************************************************/ /* x != 0 */ static GEN mpasinh(GEN x) { GEN z, res; pari_sp av; long lx = realprec(x), ex = expo(x); res = cgetr(lx); av = avma; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lx + nbits2extraprec(-ex)-1); z = logr_abs( addrr_sign(x,1, sqrtr_abs( addrs(sqrr(x), 1) ), 1) ); if (signe(x) < 0) togglesign(z); affrr(z, res); avma = av; return res; } GEN gasinh(GEN x, long prec) { pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: if (!signe(x)) return rcopy(x); return mpasinh(x); case t_COMPLEX: if (ismpzero(gel(x,2))) return gasinh(gel(x,1), prec); av = avma; if (ismpzero(gel(x,1))) /* avoid cancellation */ return gerepilecopy(av, mulcxI(gasin(gel(x,2), prec))); p1 = gadd(x, gsqrt(gaddsg(1,gsqr(x)), prec)); y = glog(p1,prec); /* log (x + sqrt(1+x^2)) */ return gerepileupto(av, y); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valp(y) < 0) pari_err_DOMAIN("asinh","valuation", "<", gen_0, x); p1 = gaddsg(1,gsqr(y)); if (gequal0(p1)) { GEN t = PiI2n(-1,prec); if ( gsigne(imag_i(gel(y,2))) < 0 ) setsigne(gel(t,2), -1); return gerepileupto(av, scalarser(t, varn(y), valp(p1)>>1)); } p1 = gdiv(derivser(y), gsqrt(p1,prec)); a = integser(p1); if (!valp(y)) a = gadd(a, gasinh(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("asinh",gasinh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ /* |x| >= 1, return ach(|x|) */ static GEN mpacosh(GEN x) { pari_sp av = avma; GEN z; if (absrnz_equal1(x)) return real_0_bit(- bit_prec(x) >> 1); z = logr_abs( addrr_sign(x, 1, sqrtr( subrs(sqrr(x), 1) ), 1) ); return gerepileuptoleaf(av, z); } GEN gacosh(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: { long s = signe(x), e = expo(x); GEN a, b; if (s > 0 && e >= 0) return mpacosh(x); /* x < 1 */ y = cgetg(3,t_COMPLEX); a = gen_0; if (s == 0) b = acos0(e); else if (e < 0) b = mpacos(x); /* -1 < x < 1 */ else { if (!absrnz_equal1(x)) a = mpacosh(x); b = mppi(realprec(x)); } gel(y,1) = a; gel(y,2) = b; return y; } case t_COMPLEX: if (ismpzero(gel(x,2))) return gacosh(gel(x,1), prec); av = avma; p1 = gadd(x, gsqrt(gaddsg(-1,gsqr(x)), prec)); y = glog(p1,prec); /* log(x + sqrt(x^2-1)) */ if (signe(real_i(y)) < 0) y = gneg(y); return gerepileupto(av, y); default: { GEN a; long v; av = avma; if (!(y = toser_i(x))) break; v = valp(y); if (v < 0) pari_err_DOMAIN("acosh","valuation", "<", gen_0, x); if (gequal0(y)) { if (!v) return gerepilecopy(av, y); return gerepileupto(av, gadd(y, PiI2n(-1, prec))); } p1 = gsubgs(gsqr(y),1); if (gequal0(p1)) { avma = av; return zeroser(varn(y), valp(p1)>>1); } p1 = gdiv(derivser(y), gsqrt(p1,prec)); a = integser(p1); if (v) p1 = PiI2n(-1, prec); /* I Pi/2 */ else { p1 = gel(y,2); if (gequal1(p1)) return gerepileupto(av,a); p1 = gacosh(p1, prec); } return gerepileupto(av, gadd(p1,a)); } } return trans_eval("acosh",gacosh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ /* |x| < 1, x != 0 */ static GEN mpatanh(GEN x) { pari_sp av = avma; long ex = expo(x); GEN z; if (ex < 1 - BITS_IN_LONG) x = rtor(x, realprec(x) + nbits2extraprec(-ex)-1); z = invr( subsr(1,x) ); shiftr_inplace(z, 1); /* 2/(1-x)*/ z = logr_abs( addrs(z,-1) ); shiftr_inplace(z, -1); return gerepileuptoleaf(av, z); } GEN gatanh(GEN x, long prec) { long sx; pari_sp av; GEN a, y, z; switch(typ(x)) { case t_REAL: sx = signe(x); if (!sx) return real_0_bit(expo(x)); if (expo(x) < 0) return mpatanh(x); y = cgetg(3,t_COMPLEX); av = avma; z = subrs(x,1); if (!signe(z)) pari_err_DOMAIN("atanh", "argument", "=", gen_1, x); z = invr(z); shiftr_inplace(z, 1); /* 2/(x-1)*/ z = addrs(z,1); if (!signe(z)) pari_err_DOMAIN("atanh", "argument", "=", gen_m1, x); z = logr_abs(z); shiftr_inplace(z, -1); /* (1/2)log((1+x)/(x-1)) */ gel(y,1) = gerepileuptoleaf(av, z); gel(y,2) = Pi2n(-1, realprec(x)); if (sx > 0) togglesign(gel(y,2)); return y; case t_COMPLEX: /* 2/(1-z) - 1 = (1+z) / (1-z) */ if (ismpzero(gel(x,2))) return gatanh(gel(x,1), prec); av = avma; z = glog( gaddgs(gdivsg(2,gsubsg(1,x)),-1), prec ); return gerepileupto(av, gmul2n(z,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err_DOMAIN("atanh","valuation", "<", gen_0, x); z = gdiv(derivser(y), gsubsg(1,gsqr(y))); a = integser(z); if (!valp(y)) a = gadd(a, gatanh(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("atanh",gatanh,x,prec); } /********************************************************************/ /** **/ /** CACHE BERNOULLI NUMBERS B_2k **/ /** **/ /********************************************************************/ static GEN bern(GEN B, long pr) { if (typ(B) != t_REAL) return fractor(B, pr); if (realprec(B) < pr) return rtor(B,pr); return B; } static const long BERN_MINNB = 5; /* need B[2..2*nb] at least prec accuracy. If prec = 0, compute exactly */ void mpbern(long nb, long prec) { const pari_sp av = avma; long n, pr, n_is_small = 1, lbern = 0; GEN B; pari_timer T; /* pr = accuracy for computation, prec = required accuracy for result */ if (prec) { pr = prec; incrprec(pr); } else pr = prec = LONG_MAX; /* oo */ if (nb < BERN_MINNB) nb = BERN_MINNB; if (bernzone) { /* don't recompute known Bernoulli */ long i, min, max; lbern = lg(bernzone); if (lbern-1 < nb) { min = lbern-1; max = nb; } else { min = nb; max = lbern-1; } /* skip B_2, ..., B_{2*MINNB}, always included as t_FRAC */ for (n = BERN_MINNB+1; n <= min; n++) { GEN c = gel(bernzone,n); /* also stop if prec = 0 (compute exactly) */ if (typ(c) == t_REAL && realprec(c) < prec) break; } /* B[1..n-1] are OK */ if (n > nb) return; B = cgetg_block(max+1, t_VEC); for (i = 1; i < n; i++) gel(B,i) = gel(bernzone,i); /* keep B[nb+1..max] */ for (i = nb+1; i <= max; i++) gel(B,i) = gel(bernzone,i); } else { B = cgetg_block(nb+1, t_VEC); gel(B,1) = gclone(mkfrac(gen_1, utoipos(6))); gel(B,2) = gclone(mkfrac(gen_m1, utoipos(30))); gel(B,3) = gclone(mkfrac(gen_1, utoipos(42))); gel(B,4) = gel(B,2); gel(B,5) = gclone(mkfrac(utoipos(5), utoipos(66))); n = BERN_MINNB+1; } avma = av; if (DEBUGLEVEL) { err_printf("caching Bernoulli numbers 2 to 2*%ld, prec = %ld\n", nb, prec == LONG_MAX? 0: prec); timer_start(&T); } /* B_{2n} = (2n-1) / (4n+2) - * sum_{a = 1}^{n-1} (2n)...(2n+2-2a) / (2...(2a-1)2a) B_{2a} */ n_is_small = 1; for (; n <= nb; n++, avma = av) { /* compute and store B[n] = B_{2n} */ GEN S; if (n < lbern) { GEN b = gel(bernzone,n); if (typ(b)!=t_REAL || realprec(b)>=prec) { gel(B,n) = b; continue; } } /* Not cached, must compute */ /* huge accuracy ? May as well compute exactly */ if (n_is_small && (prec == LONG_MAX || 2*n * log(2*n) < prec2nbits_mul(prec, LOG2))) S = bernfrac_using_zeta(2*n); else { #ifdef LONG_IS_64BIT const ulong mul_overflow = 3037000500; #else const ulong mul_overflow = 46341; #endif ulong u = 8, v = 5, a = n-1, b = 2*n-3; n_is_small = 0; S = bern(gel(B,a), pr); /* B_2a */ for (;;) { /* b = 2a-1, u = 2v-2, 2a + v = 2n+3 */ if (a == 1) { S = mulri(S, muluu(u,v)); break; } /* a=b=1, v=2n+1, u=4n */ /* beware overflow */ S = (v <= mul_overflow)? mulru(S, u*v): mulri(S, muluu(u,v)); S = (a <= mul_overflow)? divru(S, a*b): divri(S, muluu(a,b)); u += 4; v += 2; a--; b -= 2; S = addrr(bern(gel(B,a), pr), S); if ((a & 127) == 0) S = gerepileuptoleaf(av, S); } S = divru(subsr(2*n, S), 2*n+1); shiftr_inplace(S, -2*n); if (realprec(S) != prec) S = rtor(S, prec); } gel(B,n) = gclone(S); /* S = B_2n */ } if (DEBUGLEVEL) timer_printf(&T, "Bernoulli"); swap(B, bernzone); if (B) { /* kill old non-reused values */ for (n = lbern-1; n; n--) { if (gel(B,n) != gel(bernzone,n)) gunclone(gel(B,n)); } killblock(B); } avma = av; } GEN bernfrac(long n) { long k; if (n < 0) pari_err_DOMAIN("bernfrac", "index", "<", gen_0, stoi(n)); if (n == 0) return gen_1; if (n == 1) return mkfrac(gen_m1,gen_2); if (odd(n)) return gen_0; k = n >> 1; if (!bernzone && k <= BERN_MINNB) mpbern(BERN_MINNB, 0); if (bernzone && k < lg(bernzone)) { GEN B = gel(bernzone, k), C; if (typ(B) != t_REAL) return B; C = bernfrac_using_zeta(n); gel(bernzone, k) = gclone(C); gunclone(B); return C; } return bernfrac_using_zeta(n); } /* mpbern as exact fractions */ static GEN bernvec_old(long nb) { long n, i; GEN y; if (nb < 0) return cgetg(1, t_VEC); if (nb > 46340 && BITS_IN_LONG == 32) pari_err_IMPL( "bernvec for n > 46340"); y = cgetg(nb+2, t_VEC); gel(y,1) = gen_1; for (n = 1; n <= nb; n++) { /* compute y[n+1] = B_{2n} */ pari_sp av = avma; GEN b = gmul2n(utoineg(2*n - 1), -1); /* 1 + (2n+1)B_1 = -(2n-1) /2 */ GEN c = gen_1; ulong u1 = 2*n + 1, u2 = n, d1 = 1, d2 = 1; for (i = 1; i < n; i++) { c = diviiexact(muliu(c, u1*u2), utoipos(d1*d2));/*= binomial(2n+1, 2*i) */ b = gadd(b, gmul(c, gel(y,i+1))); u1 -= 2; u2--; d1++; d2 += 2; } gel(y,n+1) = gerepileupto(av, gdivgs(b, -(1+2*n))); } return y; } GEN bernvec(long nb) { long i, l = nb+2; GEN y = cgetg(l, t_VEC); if (nb < 20) return bernvec_old(nb); for (i = 1; i < l; i++) gel(y,i) = bernfrac((i-1) << 1); return y; } /* x := pol_x(v); B_k(x) = \sum_{i=0}^k binomial(k, i) B_i x^{k-i} */ static GEN bernpol_i(long k, long v) { GEN B, C; long i; if (v < 0) v = 0; if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k)); mpbern(k >> 1, 0); /* cache B_2, ..., B_2[k/2] */ C = vecbinome(k); B = cgetg(k + 3, t_POL); for (i = 0; i <= k; ++i) gel(B, k-i+2) = gmul(gel(C,i+1), bernfrac(i)); B[1] = evalsigne(1) | evalvarn(v); return B; } GEN bernpol(long k, long v) { pari_sp av = avma; return gerepileupto(av, bernpol_i(k, v)); } /* x := pol_x(v); return 1^e + ... + x^e = x^e + (B_{e+1}(x) - B_{e+1})/(e+1) */ static GEN faulhaber(long e, long v) { GEN B; if (e == 0) return pol_x(v); B = RgX_integ(bernpol_i(e, v)); /* (B_{e+1}(x) - B_{e+1}) / (e+1) */ gel(B,e+2) = gaddgs(gel(B,e+2), 1); /* add x^e, in place */ return B; } /* sum_v T(v), T a polynomial expression in v */ GEN sumformal(GEN T, long v) { pari_sp av = avma, av2, lim; long i, t, d; GEN R; T = simplify_shallow(T); t = typ(T); if (is_scalar_t(t)) 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); R = gen_0; d = poldegree(T,v); for (i = d; i >= 0; i--) { 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(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d); R = gerepileupto(av2, R); } } return gerepileupto(av, R); } /********************************************************************/ /** **/ /** EULER'S GAMMA **/ /** **/ /********************************************************************/ /* x / (i*(i+1)) */ GEN divrunu(GEN x, ulong i) { if (i <= LOWMASK) /* i(i+1) < 2^BITS_IN_LONG*/ return divru(x, i*(i+1)); else return divru(divru(x, i), i+1); } /* x / (i*(i+1)) */ GEN divgunu(GEN x, ulong i) { #ifdef LONG_IS_64BIT if (i < 3037000500L) /* i(i+1) < 2^63 */ #else if (i < 46341L) /* i(i+1) < 2^31 */ #endif return gdivgs(x, i*(i+1)); else return gdivgs(gdivgs(x, i), i+1); } /* arg(s+it) */ double darg(double s, double t) { double x; if (!t) return (s>0)? 0.: PI; if (!s) return (t>0)? PI/2: -PI/2; x = atan(t/s); return (s>0)? x : ((t>0)? x+PI : x-PI); } void dcxlog(double s, double t, double *a, double *b) { *a = log(s*s + t*t) / 2; /* log |s| = Re(log(s)) */ *b = darg(s,t); /* Im(log(s)) */ } double dabs(double s, double t) { return sqrt( s*s + t*t ); } double dnorm(double s, double t) { return s*s + t*t; } #if 0 /* x, z t_REAL. Compute unique x in ]-z,z] congruent to x mod 2z */ static GEN red_mod_2z(GEN x, GEN z) { GEN Z = gmul2n(z, 1), d = subrr(z, x); /* require little accuracy */ if (!signe(d)) return x; setprec(d, nbits2prec(expo(d) - expo(Z))); return addrr(mulir(floorr(divrr(d, Z)), Z), x); } #endif static GEN 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; int funeq = 0; pari_timer T; if (DEBUGLEVEL>5) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); esig = expo(sig); et = signe(tau)? expo(tau): 0; if ((signe(sig) <= 0 || esig < -1) && et <= 16) { /* s <--> 1-s */ funeq = 1; s = gsubsg(1, s); sig = real_i(s); } /* find "optimal" parameters [lim, nn] */ if (esig > 300 || et > 300) { /* |s| is HUGE ! Play safe and avoid inf / NaN */ GEN S, iS, l2, la, u; double logla, l; S = gprec_w(s,LOWDEFAULTPREC); /* l2 ~ |lngamma(s))|^2 */ l2 = gnorm(gmul(S, glog(S, LOWDEFAULTPREC))); l = (prec2nbits_mul(prec, LOG2) - rtodbl(glog(l2,LOWDEFAULTPREC))/2) / 2.; if (l < 0) l = 0.; iS = imag_i(S); if (et > 0 && l > 0) { GEN t = gmul(iS, dbltor(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; } else logla = rtodbl(mplog(la)); } else { logla = log(3.); la = stoi(3); } lim = (long)ceil(l / (1.+ logla)); if (lim == 0) lim = 1; u = gmul(la, dbltor((lim-0.5)/PI)); l2 = gsub(gsqr(u), gsqr(iS)); if (signe(l2) > 0) { l2 = gsub(gsqrt(l2,3), sig); if (signe(l2) > 0) nn = itos( gceil(l2) ); else nn = 1; } else nn = 1; } else { /* |s| is moderate. Use floats */ double ssig = rtodbl(sig); double st = typ(s) == t_REAL? 0.0: rtodbl(imag_i(s)); double la, l,l2,u,v, rlogs, ilogs; if (dolog) { /* loggamma(1+u) ~ - Euler * u: cancellation if u is small */ if (fabs(ssig-1) + fabs(st) < 0.0001) { /* s ~ 1, take care */ long e = gexpo(gsubgs(s,1)); prec += nbits2nlong(-e); s = gprec_w(s, prec); } } dcxlog(ssig,st, &rlogs,&ilogs); /* Re (s - 1/2) log(s) */ u = (ssig - 0.5)*rlogs - st * ilogs; /* 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; v = v - st; l2 = u*u + v*v; if (l2 < 0.000001) l2 = 0.000001; l = (prec2nbits_mul(prec, LOG2) - log(l2)/2) / 2.; if (l < 0) l = 0.; la = 3.; /* FIXME: heuristic... */ if (st > 1 && l > 0) { double t = st * PI / l; la = t * log(t); if (la < 3) la = 3.; if (la > 150) la = t; } lim = (long)ceil(l / (1.+ log(la))); if (lim == 0) lim = 1; u = (lim-0.5) * la / PI; l2 = u*u - st*st; if (l2 > 0) { nn = (long)ceil(sqrt(l2) - ssig); if (nn < 1) nn = 1; } else nn = 1; if (DEBUGLEVEL>5) err_printf("lim, nn: [%ld, %ld], la = %lf\n",lim,nn,la); } incrprec(prec); av2 = avma; avlim = stack_lim(av2,3); y = s; if (typ(s0) == t_INT) { if (signe(s0) <= 0) pari_err_DOMAIN("gamma","argument", "=", strtoGENstr("non-positive integer"), s0); if (is_bigint(s0)) { for (i=1; i < nn; i++) { y = mulri(y, addis(s0, i)); if (low_stack(avlim,stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileuptoleaf(av2, y); } } } else { ulong ss = itou(s0); for (i=1; i < nn; i++) { y = mulru(y, ss + i); if (low_stack(avlim,stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileuptoleaf(av2, y); } } } if (dolog) y = logr_abs(y); } else if (!dolog || typ(s) == t_REAL) { /* Compute lngamma mod 2 I Pi */ for (i=1; i < nn; i++) { y = gmul(y, gaddgs(s,i)); if (low_stack(avlim,stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileupto(av2, y); } } if (dolog) y = logr_abs(y); } else { /* dolog && complex s: be careful with imaginary part */ y = glog(y, prec); for (i=1; i < nn; i++) { y = gadd(y, glog(gaddgs(s,i), prec)); if (low_stack(avlim,stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileupto(av2, y); } } } if (DEBUGLEVEL>5) timer_printf(&T,"product from 0 to N-1"); nnx = gaddgs(s, nn); a = ginv(nnx); invn2 = gsqr(a); av2 = avma; avlim = stack_lim(av2,3); mpbern(lim,prec); tes = divrunu(bernreal(2*lim,prec), 2*lim-1); /* B2l / (2l-1) 2l*/ if (DEBUGLEVEL>5) timer_printf(&T,"Bernoullis"); for (i = 2*lim-2; i > 1; i -= 2) { 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(DEBUGMEM>1) pari_warn(warnmem,"gamma"); tes = gerepileupto(av2, tes); } } if (DEBUGLEVEL>5) timer_printf(&T,"Bernoulli sum"); p1 = gsub(gmul(gsub(nnx, ghalf), glog(nnx,prec)), nnx); p1 = gadd(p1, gmul(tes, a)); pi = mppi(prec); pi2 = shiftr(pi, 1); sqrtpi2 = sqrtr(pi2); if (dolog) { if (funeq) { /* (recall that s = 1 - s0) */ /* We compute log(sin(Pi s0)) so that it has branch cuts along * (-oo, 0] and [1, oo). To do this in a numerically stable way * we must compute the log first then mangle its imaginary part. * The rounding operation below is stable because we're rounding * a number which is already within 1/4 of an integer. */ /* z = log( sin(Pi s0) / (sqrt(2Pi)/2) ) */ GEN z = glog(gdiv(gsin(gmul(pi,s0),prec), shiftr(sqrtpi2,-1)), prec); /* b = (2 Re(s) - 1) / 4 */ GEN b = shiftr(subrs(shiftr(sig, 1), 1), -2); y = gsub(y, z); if (gsigne(imag_i(s)) > 0) togglesign(b); /* z = 2Pi round( Im(z)/2Pi - b ) */ z = gmul(roundr(gsub(gdiv(imag_i(z), pi2), b)), pi2); if (signe(z)) { /* y += I*z */ if (typ(y) == t_COMPLEX) gel(y,2) = gadd(gel(y,2), z); else y = gadd(y, mkcomplex(gen_0, z)); } p1 = gneg(p1); } else /* y --> sqrt(2Pi) / y */ y = gsub(logr_abs(sqrtpi2), y); y = gadd(p1, y); } else { if (funeq) { /* y --> y Pi/(sin(Pi s) * sqrt(2Pi)) = y sqrt(Pi/2)/sin(Pi s) */ y = gdiv(gmul(shiftr(sqrtpi2,-1),y), gsin(gmul(pi,s0), prec)); /* don't use s above: sin(pi s0) = sin(pi s) and the former is * more accurate, esp. if s0 ~ 0 */ p1 = gneg(p1); } else /* y --> sqrt(2Pi) / y */ y = gdiv(sqrtpi2, y); y = gmul(gexp(p1, prec), y); } avma = av; return affc_fixlg(y, res); } /* Gamma((m+1) / 2) */ static GEN gammahs(long m, long prec) { GEN y = cgetr(prec), z; pari_sp av = avma; long ma = labs(m); if (ma > 200 + 50*(prec-2)) /* heuristic */ { z = stor(m + 1, prec); shiftr_inplace(z, -1); affrr(cxgamma(z,0,prec), y); avma = av; return y; } z = sqrtr( mppi(prec) ); if (m) { GEN p1 = mulu_interval(ma/2 + 1, ma); long v = vali(p1); p1 = shifti(p1, -v); v -= ma; if (m >= 0) z = mulri(z,p1); else { z = divri(z,p1); v = -v; if ((m&3) == 2) setsigne(z,-1); } shiftr_inplace(z, v); } affrr(z, y); avma = av; return y; } GEN ggammah(GEN x, long prec) { switch(typ(x)) { case t_INT: { long k = itos(x); if (labs(k) > 962353) pari_err_OVERFLOW("gammah"); return gammahs(k<<1, prec); } case t_REAL: case t_COMPLEX: case t_PADIC: case t_SER: { pari_sp av = avma; return gerepileupto(av, ggamma(gadd(x,ghalf), prec)); } } return trans_eval("gammah",ggammah,x,prec); } /* find n such that n+v_p(n!)>=k p^2/(p-1)^2 */ static long nboft(long k, long p) { pari_sp av = avma; long s, n; if (k <= 0) return 0; k = itou( gceil(gdiv(mului(k, sqru(p)), sqru(p-1))) ); avma = av; for (s=0, n=0; n+s < k; n++, s += u_lval(n, p)); return n; } /* Using Dwork's expansion, compute \Gamma(px+1)=-\Gamma(px) with x a unit. * See p-Adic Gamma Functions and Dwork Cohomology, Maurizio Boyarsky * Transactions of the AMS, Vol. 257, No. 2. (Feb., 1980), pp. 359-369. * Inspired by a GP script by Fernando Rodriguez-Villegas */ static GEN gadw(GEN x, long p) { pari_sp ltop = avma; GEN s, t, u = cgetg(p+1, t_VEC); long j, k, kp, n = nboft(precp(x)+valp(x)+1, p); t = s = gaddsg(1, zeropadic(gel(x,2), n)); gel(u, 1) = s; gel(u, 2) = s; for (j = 2; j < p; ++j) gel(u, j+1) = gdivgs(gel(u, j), j); for (k = 1, kp = p; k < n; ++k, kp += p) /* kp = k*p */ { GEN c; gel(u, 1) = gdivgs(gadd(gel(u, 1), gel(u, p)), kp); for (j = 1; j < p; ++j) gel(u, j+1) = gdivgs(gadd(gel(u, j), gel(u, j+1)), kp + j); t = gmul(t, gaddgs(x, k-1)); c = leafcopy(gel(u,1)); setvalp(c, valp(c) + k); /* c = u[1] * p^k */ s = gadd(s, gmul(c, t)); if ((k&0xFL)==0) gerepileall(ltop, 3, &u,&s,&t); } return gneg(s); } /*Use Dwork expansion*/ /*This is a O(p*e*log(pe)) algorithm, should be used when p small * If p==2 this is a O(pe) algorithm. */ static GEN Qp_gamma_Dwork(GEN x, long p) { pari_sp ltop = avma; long k = padic_to_Fl(x, p); GEN p1; long j; long px = precp(x); if (p==2 && px) { x = shallowcopy(x); setprecp(x, px+1); gel(x,3) = shifti(gel(x,3),1); } if (k) { GEN x_k = gsubgs(x,k); x = gdivgs(x_k, p); p1 = gadw(x, p); if (!odd(k)) p1 = gneg(p1); for (j = 1; j < k; ++j) p1 = gmul(p1, gaddgs(x_k, j)); } else p1 = gneg(gadw(gdivgs(x, p), p)); return gerepileupto(ltop, p1); } /* Compute Qp_gamma using the definition. This is a O(x*M(log(pe))) algorithm. * This should be used if x is very small. */ static GEN Qp_gamma_Morita(long n, GEN p, long e) { pari_sp ltop=avma; GEN p2 = gaddsg((n&1)?-1:1, zeropadic(p, e)); long i; long pp=is_bigint(p)? 0: itos(p); for (i = 2; i < n; i++) if (!pp || i%pp) { p2 = gmulgs(p2, i); if ((i&0xFL) == 0xFL) p2 = gerepileupto(ltop, p2); } return gerepileupto(ltop, p2); } /* x\in\N: Gamma(-x)=(-1)^(1+x+x\p)*Gamma(1+x) */ static GEN Qp_gamma_neg_Morita(long n, GEN p, long e) { GEN g = ginv(Qp_gamma_Morita(n+1, p, e)); return ((n^sdivsi(n,p)) & 1)? g: gneg(g); } /* p-adic Gamma function for x a p-adic integer */ /* If n < p*e : use Morita's definition. * Else : use Dwork's expansion. * If both n and p are big : itos(p) will fail. * TODO: handle p=2 better (Qp_gamma_Dwork is slow for p=2). */ GEN Qp_gamma(GEN x) { GEN n, m, N, p = gel(x,2); long s, e = precp(x); if (equaliu(p, 2) && e == 2) e = 1; if (valp(x) < 0) pari_err_DOMAIN("gamma","v_p(x)", "<", gen_0, x); n = gtrunc(x); m = gtrunc(gneg(x)); N = cmpii(n,m)<=0?n:m; s = itos_or_0(N); if (s && cmpsi(s, muliu(p,e)) < 0) /* s < p*e */ return (N == n) ? Qp_gamma_Morita(s,p,e): Qp_gamma_neg_Morita(s,p,e); return Qp_gamma_Dwork(x, itos(p)); } GEN ggamma(GEN x, long prec) { pari_sp av; long m; GEN y, z; switch(typ(x)) { case t_INT: if (signe(x) <= 0) pari_err_DOMAIN("gamma","argument", "=", strtoGENstr("non-positive integer"), x); if (cmpiu(x,481177) > 0) pari_err_OVERFLOW("gamma"); return mpfactr(itos(x) - 1, prec); case t_REAL: case t_COMPLEX: return cxgamma(x, 0, prec); case t_FRAC: if (!equaliu(gel(x,2),2)) break; z = gel(x,1); /* true argument is z/2 */ if (is_bigint(z) || labs(m = itos(z)) > 962354) { pari_err_OVERFLOW("gamma"); return NULL; /* not reached */ } return gammahs(m-1, prec); case t_PADIC: return Qp_gamma(x); default: av = avma; if (!(y = toser_i(x))) break; /* exp(lngamma) */ if (valp(y)>0 || lg(y) == 2) z = gdiv(gexp(glngamma(gaddgs(y,1),prec),prec),y); else { /* use fun eq. to avoid log singularity of lngamma at negative ints */ GEN Y = y, y0 = gel(y,2), t = ground(y0), pi = NULL; if (gequal(y0, t) && typ(t) == t_INT && signe(t) < 0) { pi = mppi(prec); Y = gsubsg(1, y); } z = gexp(glngamma(Y,prec),prec); if (pi) z = gdiv(mpodd(t)? negr(pi): pi, gmul(z, gsin(gmul(pi,serchop0(y)), prec))); } return gerepileupto(av, z); } return trans_eval("gamma",ggamma,x,prec); } GEN mpfactr(long n, long prec) { GEN f = cgetr(prec); pari_sp av = avma; if (n+1 > 350 + 70*(prec-2)) /* heuristic */ affrr(cxgamma(stor(n+1, prec), 0, prec), f); else affir(mpfact(n), f); avma = av; return f; } GEN glngamma(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_INT: if (signe(x) <= 0) pari_err_DOMAIN("lngamma","argument", "=", strtoGENstr("non-positive integer"), x); if (cmpiu(x,200 + 50*(prec-2)) > 0) /* heuristic */ return cxgamma(x, 1, prec); av = avma; return gerepileuptoleaf(av, logr_abs( itor(mpfact(itos(x) - 1), prec) )); case t_FRAC: { GEN a, b; long e1, e2; av = avma; a = gel(x,1); b = gel(x,2); e1 = expi(subii(a,b)); e2 = expi(b); if (e2 > e1) prec += nbits2nlong(e2 - e1); x = fractor(x, prec); return gerepileupto(av, cxgamma(x, 1, prec)); } case t_REAL: case t_COMPLEX: return cxgamma(x, 1, prec); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y)) pari_err_DOMAIN("lngamma","valuation", "!=", gen_0, x); /* (lngamma y)' = y' psi(y) */ p1 = integser(gmul(derivser(y), gpsi(y, prec))); if (!gequal1(gel(y,2))) p1 = gadd(p1, glngamma(gel(y,2),prec)); return gerepileupto(av, p1); case t_PADIC: av = avma; return gerepileupto(av, Qp_log(Qp_gamma(x))); } return trans_eval("lngamma",glngamma,x,prec); } /********************************************************************/ /** **/ /** PSI(x) = GAMMA'(x)/GAMMA(x) **/ /** **/ /********************************************************************/ GEN cxpsi(GEN s0, long prec) { pari_sp av, av2; GEN sum,z,a,res,tes,in2,sig,tau,s,unr; long lim,nn,k; const long la = 3; int funeq = 0; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); if (signe(sig) <= 0) { funeq = 1; s = gsub(gen_1, s); sig = real_i(s); } if (typ(s0) == t_INT && signe(s0) <= 0) pari_err_DOMAIN("psi","argument", "=", strtoGENstr("non-positive integer"), s0); if (expo(sig) > 300 || (typ(s) == t_COMPLEX && gexpo(gel(s,2)) > 300)) { /* |s| is HUGE. Play safe */ GEN L, S = gprec_w(s,LOWDEFAULTPREC), rS = real_i(S), iS = imag_i(S); double l; l = rtodbl( gnorm(glog(S, 3)) ); l = log(l) / 2.; 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 = gsub(dbltor(l*l), gsqr(iS)); if (signe(L) < 0) L = gen_0; L = gsub(gsqrt(L, 3), rS); if (signe(L) > 0) nn = (long)ceil(rtodbl(L)); else nn = 1; if (DEBUGLEVEL>2) err_printf("lim, nn: [%ld, %ld]\n",lim,nn); } else { double ssig = rtodbl(sig); double st = typ(s) == t_REAL? 0.0: rtodbl(imag_i(s)); double l; { double rlog, ilog; /* log (s - Euler) */ dcxlog(ssig - 0.57721566, st, &rlog,&ilog); l = dnorm(rlog,ilog); } if (l < 0.000001) l = 0.000001; l = log(l) / 2.; 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 = l*l - st*st; if (l < 0.) l = 0.; nn = (long)ceil( sqrt(l) - ssig ); if (nn < 1) nn = 1; if (DEBUGLEVEL>2) err_printf("lim, nn: [%ld, %ld]\n",lim,nn); } incrprec(prec); unr = real_1(prec); /* one extra word of precision */ a = gdiv(unr, gaddgs(s, nn)); /* 1 / (s+n) */ av2 = avma; sum = gmul2n(a,-1); for (k = 0; k < nn; k++) { sum = gadd(sum, gdiv(unr, gaddgs(s, k))); if ((k & 127) == 0) sum = gerepileupto(av2, sum); } z = gsub(glog(gaddgs(s, nn), prec), sum); if (DEBUGLEVEL>2) timer_printf(&T,"sum from 0 to N-1"); in2 = gsqr(a); mpbern(lim,prec); av2 = avma; tes = divru(bernreal(2*lim, prec), 2*lim); for (k=2*lim-2; k>=2; k-=2) { tes = gadd(gmul(in2,tes), divru(bernreal(k, prec), k)); if ((k & 255) == 0) tes = gerepileupto(av2, tes); } if (DEBUGLEVEL>2) timer_printf(&T,"Bernoulli sum"); z = gsub(z, gmul(in2,tes)); if (funeq) { GEN pi = mppi(prec); z = gadd(z, gmul(pi, gcotan(gmul(pi,s), prec))); } avma = av; return affc_fixlg(z, res); } /* psi(1+x) + O(x^n), x = pol_x(v) */ static GEN serpsi1(long n, long v, long prec) { long i, l = n+3; GEN g, s = cgetg(l, t_SER); s[1] = evalsigne(1)|evalvalp(0)|evalvarn(v); g = mpeuler(prec); setsigne(g, -1); gel(s,2) = g; for (i = 2; i < l-1; i++) { GEN c = szeta(i, prec); if (odd(i)) setsigne(c, -1); gel(s,i+1) = c; } return s; } /* T an RgX, return T(X + z0) + O(X^L) */ static GEN tr(GEN T, GEN z0, long L) { GEN s = RgX_to_ser(RgX_translate(T, z0), L+3); setvarn(s, 0); return s; } /* psi(z0+x) + O(x^n) */ static GEN serpsiz0(GEN z0, long L, long v, long prec) { pari_sp av, lim; GEN A,A1,A2, B,B1,B2, Q; long n; if (equali1(z0)) return serpsi1(L, v, prec); /* otherwise use Luke's rational approximations for psi(x) */ n = gprecision(z0); if (n) prec = n; 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); 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); B1 = mkpoln(2, utoipos(8), utoipos(28)); A = gdivgs(mkpoln(4, gen_1, utoipos(387), utoipos(2906), utoipos(1920)), 12); B = mkpoln(3, utoipos(14), utoipos(204), utoipos(310)); A2= tr(A2,z0, L); B2= tr(B2,z0, L); A1= tr(A1,z0, L); B1= tr(B1,z0, L); A = tr(A, z0, L); B = tr(B, z0, L); Q = gdiv(A, B); /* work with z0+x as a variable */ for (n = 4;; n++) { GEN Q0 = Q, a, b, r, c3,c2,c1,c0 = muluu(2*n-3, n+1); GEN u = subiu(muluu(n, 7*n-9), 6); GEN t = addiu(muluu(n, 7*n-19), 4); /* c1=(2*n-1)*(3*(n-1)*z+7*n^2-9*n-6); * c2=(2*n-3)*(z-n-1)*(-3*(n-1)*z+7*n^2-19*n+4); * c3=(2*n-1)*(n-3)*(z-n)*(z-(n+1))*(z+(n-4)); */ c1 = deg1pol_shallow(muluu(3*(n-1),2*n-1), muliu(u,2*n-1), 0); c2 = ZX_mul(deg1pol_shallow(utoipos(2*n-3), negi(muluu(2*n-3,n+1)), 0), deg1pol_shallow(utoineg(3*(n-1)), t, 0)); r = mkvec3(utoipos(n), utoipos(n+1), stoi(4-n)); c3 = ZX_Z_mul(roots_to_pol(r,0), muluu(2*n-1,n-3)); c1 = tr(c1, z0, L+3); c2 = tr(c2, z0, L+3); c3 = tr(c3, z0, L+3); /* A_{n+1}, B_{n+1} */ 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; A2 = A1; A1 = A; A = a; B2 = B1; B1 = B; B = b; if (low_stack(lim,stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"serpsiz0, n = %ld", n); gerepileall(av, 7, &A,&A1,&A2, &B,&B1,&B2, &Q); } } Q = gmul(Q, gmul2n(gsubsg(1, ginv(tr(pol_x(v),z0, L))), 1)); setvarn(Q, v); return gadd(negr(mpeuler(prec)), Q); } static GEN serpsi(GEN y, long prec) { GEN Q, z0, Y; long L = lg(y)-2, v = varn(y), vy = valp(y); int reflect; if (!L) pari_err_DOMAIN("psi", "argument", "=", gen_0,y); if (vy < 0) pari_err_DOMAIN("psi", "series valuation", "<", gen_0,y); if (vy) z0 = gen_0; else { GEN t; z0 = simplify_shallow(gel(y,2)); t = ground(z0); if (gequal(t,z0)) z0 = t; } reflect = (gcmp(real_i(z0),ghalf) < 0); /* use reflection formula */ if (reflect) { z0 = gsubsg(1,z0); Y = gsubsg(1,y); } else Y = y; Q = serpsiz0(z0, L, v, prec); Q = gsubst(Q, v, serchop0(Y)); /* psi(Y) */ if (reflect) { /* psi(y) = psi(Y) + Pi cotan(Pi Y) = psi(Y) - Pi cotan(Pi y) */ GEN pi = mppi(prec); if (equali1(z0)) Q = gsub(Q, gmul(pi, gcotan(gmul(pi,y), prec))); else Q = gadd(Q, gmul(pi, gcotan(gmul(pi,Y), prec))); } return Q; } GEN gpsi(GEN x, long prec) { pari_sp av; GEN y; switch(typ(x)) { case t_REAL: case t_COMPLEX: return cxpsi(x,prec); default: av = avma; if (!(y = toser_i(x))) break; return gerepileupto(av, serpsi(y,prec)); } return trans_eval("psi",gpsi,x,prec); } pari-2.7.5/src/basemath/bibli1.c0000644000175000017500000014347112610174612015001 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** LLL Algorithm and close friends **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** QR Factorization via Householder matrices **/ /********************************************************************/ static int no_prec_pb(GEN x) { return (typ(x) != t_REAL || realprec(x) > LOWDEFAULTPREC || expo(x) < BITS_IN_LONG/2); } /* Find a Householder transformation which, applied to x[k..#x], zeroes * x[k+1..#x]; fill L = (mu_{i,j}). Return 0 if precision problem [obtained * a 0 vector], 1 otherwise */ static int FindApplyQ(GEN x, GEN L, GEN B, long k, GEN Q, long prec) { long i, lx = lg(x)-1; GEN x2, x1, xd = x + (k-1); x1 = gel(xd,1); x2 = mpsqr(x1); if (k < lx) { long lv = lx - (k-1) + 1; GEN beta, Nx, v = cgetg(lv, t_VEC); for (i=2; i 1) r = ApplyAllQ(Q, r, j); if (!FindApplyQ(r, L, B, j, Q, prec)) return 0; } *pB = B; *pQ = Q; *pL = L; return 1; } /* x a square t_MAT with t_INT / t_REAL entries and maximal rank. Return * qfgaussred(x~*x) */ GEN gaussred_from_QR(GEN x, long prec) { long j, k = lg(x)-1; GEN B, Q, L; if (!QR_init(x, &B,&Q,&L, prec)) return NULL; for (j=1; j= |m1| * for any two columns m1 != m2, in M. * * Input: an integer matrix mat whose columns are linearly independent. Find * another matrix T such that mat * T is partially reduced. * * Output: mat * T if flag = 0; T if flag != 0, * * This routine is designed to quickly reduce lattices in which one row * is huge compared to the other rows. For example, when searching for a * polynomial of degree 3 with root a mod N, the four input vectors might * be the coefficients of * X^3 - (a^3 mod N), X^2 - (a^2 mod N), X - (a mod N), N. * All four constant coefficients are O(p) and the rest are O(1). By the * pigeon-hole principle, the coefficients of the smallest vector in the * lattice are O(p^(1/4)), hence significant reduction of vector lengths * can be anticipated. * * An improved algorithm would look only at the leading digits of dot*. It * would use single-precision calculations as much as possible. * * Original code: Peter Montgomery (1994) */ static GEN lllintpartialall(GEN m, long flag) { const long ncol = lg(m)-1; const pari_sp av = avma; GEN tm1, tm2, mid; if (ncol <= 1) return flag? matid(ncol): gcopy(m); tm1 = flag? matid(ncol): NULL; { const pari_sp av2 = avma; GEN dot11 = ZV_dotsquare(gel(m,1)); GEN dot22 = ZV_dotsquare(gel(m,2)); GEN dot12 = ZV_dotproduct(gel(m,1), gel(m,2)); GEN tm = matid(2); /* For first two columns only */ int progress = 0; long npass2 = 0; /* Row reduce the first two columns of m. Our best result so far is * (first two columns of m)*tm. * * Initially tm = 2 x 2 identity matrix. * Inner products of the reduced matrix are in dot11, dot12, dot22. */ while (npass2 < 2 || progress) { GEN dot12new, q = diviiround(dot12, dot22); npass2++; progress = signe(q); if (progress) {/* Conceptually replace (v1, v2) by (v1 - q*v2, v2), where v1 and v2 * represent the reduced basis for the first two columns of the matrix. * We do this by updating tm and the inner products. */ togglesign(q); dot12new = addii(dot12, mulii(q, dot22)); dot11 = addii(dot11, mulii(q, addii(dot12, dot12new))); dot12 = dot12new; ZC_lincomb1_inplace(gel(tm,1), gel(tm,2), q); } /* Interchange the output vectors v1 and v2. */ swap(dot11,dot22); swap(gel(tm,1), gel(tm,2)); /* Occasionally (including final pass) do garbage collection. */ if ((npass2 & 0xff) == 0 || !progress) gerepileall(av2, 4, &dot11,&dot12,&dot22,&tm); } /* while npass2 < 2 || progress */ { long i; GEN det12 = subii(mulii(dot11, dot22), sqri(dot12)); mid = cgetg(ncol+1, t_MAT); for (i = 1; i <= 2; i++) { GEN tmi = gel(tm,i); if (tm1) { GEN tm1i = gel(tm1,i); gel(tm1i,1) = gel(tmi,1); gel(tm1i,2) = gel(tmi,2); } gel(mid,i) = ZC_lincomb(gel(tmi,1),gel(tmi,2), gel(m,1),gel(m,2)); } for (i = 3; i <= ncol; i++) { GEN c = gel(m,i); GEN dot1i = ZV_dotproduct(gel(mid,1), c); GEN dot2i = ZV_dotproduct(gel(mid,2), c); /* ( dot11 dot12 ) (q1) ( dot1i ) * ( dot12 dot22 ) (q2) = ( dot2i ) * * Round -q1 and -q2 to nearest integer. Then compute * c - q1*mid[1] - q2*mid[2]. * This will be approximately orthogonal to the first two vectors in * the new basis. */ GEN q1neg = subii(mulii(dot12, dot2i), mulii(dot22, dot1i)); GEN q2neg = subii(mulii(dot12, dot1i), mulii(dot11, dot2i)); q1neg = diviiround(q1neg, det12); q2neg = diviiround(q2neg, det12); if (tm1) { gcoeff(tm1,1,i) = addii(mulii(q1neg, gcoeff(tm,1,1)), mulii(q2neg, gcoeff(tm,1,2))); gcoeff(tm1,2,i) = addii(mulii(q1neg, gcoeff(tm,2,1)), mulii(q2neg, gcoeff(tm,2,2))); } gel(mid,i) = ZC_add(c, ZC_lincomb(q1neg,q2neg, gel(mid,1),gel(mid,2))); } /* for i */ } /* local block */ } if (DEBUGLEVEL>6) { if (tm1) err_printf("tm1 = %Ps",tm1); err_printf("mid = %Ps",mid); /* = m * tm1 */ } gerepileall(av, tm1? 2: 1, &mid, &tm1); { /* 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); long i, j, npass = 0, e = LONG_MAX; GEN dot = cgetg(ncol+1, t_MAT); /* scalar products */ tm2 = matid(ncol); for (i=1; i <= ncol; i++) { gel(dot,i) = cgetg(ncol+1,t_COL); for (j=1; j <= i; j++) gcoeff(dot,j,i) = gcoeff(dot,i,j) = ZV_dotproduct(gel(mid,i),gel(mid,j)); } for(;;) { long reductions = 0, olde = e; for (i=1; i <= ncol; i++) { long ijdif; for (ijdif=1; ijdif < ncol; ijdif++) { long d, k1, k2; GEN codi, q; j = i + ijdif; if (j > ncol) j -= ncol; /* let k1, resp. k2, index of larger, resp. smaller, column */ if (cmpii(gcoeff(dot,i,i), gcoeff(dot,j,j)) > 0) { k1 = i; k2 = j; } else { k1 = j; k2 = i; } codi = gcoeff(dot,k2,k2); q = signe(codi)? diviiround(gcoeff(dot,k1,k2), codi): gen_0; if (!signe(q)) continue; /* Try to subtract a multiple of column k2 from column k1. */ reductions++; togglesign_safe(&q); ZC_lincomb1_inplace(gel(tm2,k1), gel(tm2,k2), q); ZC_lincomb1_inplace(gel(dot,k1), gel(dot,k2), q); gcoeff(dot,k1,k1) = addii(gcoeff(dot,k1,k1), 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(DEBUGMEM>1) pari_warn(warnmem,"lllintpartialall"); gerepileall(av3, 2, &dot,&tm2); } } /* for i */ if (!reductions) break; e = 0; for (i = 1; i <= ncol; i++) e += expi( gcoeff(dot,i,i) ); if (e == olde) break; if (DEBUGLEVEL>6) { npass++; err_printf("npass = %ld, red. last time = %ld, log_2(det) ~ %ld\n\n", npass, reductions, e); } } /* for(;;)*/ /* Sort columns so smallest comes first in m * tm1 * tm2. * Use insertion sort. */ for (i = 1; i < ncol; i++) { long j, s = i; for (j = i+1; j <= ncol; j++) if (cmpii(gcoeff(dot,s,s),gcoeff(dot,j,j)) > 0) s = j; if (i != s) { /* Exchange with proper column; only the diagonal of dot is updated */ swap(gel(tm2,i), gel(tm2,s)); 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)); } GEN lllintpartial(GEN mat) { return lllintpartialall(mat,1); } GEN lllintpartial_inplace(GEN mat) { return lllintpartialall(mat,0); } /********************************************************************/ /** **/ /** COPPERSMITH ALGORITHM **/ /** Finding small roots of univariate equations. **/ /** **/ /********************************************************************/ static int check_condition(double beta, double tau, double rho, long d, long delta, long t) { long dim = d*delta + t; double cond = d*delta*(delta+1)/2 - beta*delta*dim + rho*delta*(delta - 1) / 2 + rho * t * delta + tau*dim*(dim - 1)/2; if (DEBUGLEVEL >= 4) err_printf("delta = %d, t = %d, cond = %.1lf\n", delta, t, cond); return (cond <= 0); } static void choose_params(GEN P, GEN N, GEN X, GEN B, long *pdelta, long *pt) { long d = degpol(P); GEN P0 = leading_term(P); double logN = gtodouble(glog(N, DEFAULTPREC)); double tau, beta, rho; long delta, t; tau = gtodouble(glog(X, DEFAULTPREC)) / logN; beta = B? gtodouble(glog(B, DEFAULTPREC)) / logN: 1.; if (tau >= beta * beta / d) pari_err_OVERFLOW("zncoppersmith [bound too large]"); /* TODO : remove P0 completely ! */ rho = gtodouble(glog(P0, DEFAULTPREC)) / logN; /* Enumerate (delta,t) by increasing dimension of resulting lattice. * Not subtle, but o(1) for computing time */ t = d; delta = 0; for(;;) { t += d * delta + 1; delta = 0; while (t >= 0) { if (check_condition(beta, tau, rho, d, delta, t)) { *pdelta = delta; *pt = t; return; } delta++; t -= d; } } } static int sol_OK(GEN x, GEN N, GEN B) { return B? (cmpii(gcdii(x,N),B) >= 0): !signe(remii(x,N)); } /* deg(P) > 0, x >= 0. Find all j such that gcd(P(j), N) >= B, |j| <= x */ static GEN do_exhaustive(GEN P, GEN N, long x, GEN B) { GEN Pe, Po, sol = vecsmalltrunc_init(2*x + 2); pari_sp av; long j; RgX_even_odd(P, &Pe,&Po); av = avma; if (sol_OK(gel(P,2), N,B)) vecsmalltrunc_append(sol, 0); for (j = 1; j <= x; j++, avma = av) { GEN j2 = sqru(j), E = FpX_eval(Pe,j2,N), O = FpX_eval(Po,j2,N); if (sol_OK(addmuliu(E,O,j), N,B)) vecsmalltrunc_append(sol, j); if (sol_OK(submuliu(E,O,j), N,B)) vecsmalltrunc_append(sol,-j); } vecsmall_sort(sol); return zv_to_ZV(sol); } /* General Coppersmith, look for a root x0 <= p, p >= B, p | N, |x0| <= X. * B = N coded as NULL */ GEN zncoppersmith(GEN P0, GEN N, GEN X, GEN B) { GEN Q, R, N0, M, sh, short_pol, *Xpowers, sol, nsp, P, Z; long delta, i, j, row, d, l, dim, t, bnd = 10; const ulong X_SMALL = 1000; pari_sp av = avma; if (typ(P0) != t_POL) pari_err_TYPE("zncoppersmith",P0); if (typ(N) != t_INT) pari_err_TYPE("zncoppersmith",N); if (typ(X) != t_INT) { X = gfloor(X); if (typ(X) != t_INT) pari_err_TYPE("zncoppersmith",X); } if (signe(X) < 0) pari_err_DOMAIN("zncoppersmith", "X", "<", gen_0, X); d = degpol(P0); if (d == 0) { avma = av; return cgetg(1, t_VEC); } if (d < 0) pari_err_ROOTS0("zncoppersmith"); if (B && typ(B) != t_INT) B = gceil(B); if (cmpiu(X, X_SMALL) <= 0) return gerepileupto(av, do_exhaustive(P0, N, itos(X), B)); if (B && equalii(B,N)) B = NULL; if (B) bnd = 1; /* bnd-hack is only for the case B = N */ P = leafcopy(P0); if (!gequal1(gel(P,d+2))) { GEN r, z; gel(P,d+2) = bezout(gel(P,d+2), N, &z, &r); for (j = 0; j < d; j++) gel(P,j+2) = modii(mulii(gel(P,j+2), z), N); } if (DEBUGLEVEL >= 2) err_printf("Modified P: %Ps\n", P); choose_params(P, N, X, B, &delta, &t); if (DEBUGLEVEL >= 2) err_printf("Init: trying delta = %d, t = %d\n", delta, t); for(;;) { dim = d * delta + t; /* TODO: In case of failure do not recompute the full vector */ Xpowers = (GEN*)new_chunk(dim + 1); Xpowers[0] = gen_1; for (j = 1; j <= dim; j++) Xpowers[j] = mulii(Xpowers[j-1], X); /* TODO: in case of failure, use the part of the matrix already computed */ M = zeromatcopy(dim,dim); /* Rows of M correspond to the polynomials * N^delta, N^delta Xi, ... N^delta (Xi)^d-1, * N^(delta-1)P(Xi), N^(delta-1)XiP(Xi), ... N^(delta-1)P(Xi)(Xi)^d-1, * ... * P(Xi)^delta, XiP(Xi)^delta, ..., P(Xi)^delta(Xi)^t-1 */ for (j = 1; j <= d; j++) gcoeff(M, j, j) = gel(Xpowers,j-1); /* P-part */ if (delta) row = d + 1; else row = 0; Q = P; for (i = 1; i < delta; i++) { for (j = 0; j < d; j++,row++) for (l = j + 1; l <= row; l++) gcoeff(M, l, row) = mulii(Xpowers[l-1], gel(Q,l-j+1)); Q = ZX_mul(Q, P); } for (j = 0; j < t; row++, j++) for (l = j + 1; l <= row; l++) gcoeff(M, l, row) = mulii(Xpowers[l-1], gel(Q,l-j+1)); /* N-part */ row = dim - t; N0 = N; while (row >= 1) { for (j = 0; j < d; j++,row--) for (l = 1; l <= row; l++) gcoeff(M, l, row) = mulii(gmael(M, row, l), N0); if (row >= 1) N0 = mulii(N0, N); } /* Z is the upper bound for the L^1 norm of the polynomial, ie. N^delta if B = N, B^delta otherwise */ if (B) Z = powiu(B, delta); else Z = N0; if (DEBUGLEVEL >= 2) { if (DEBUGLEVEL >= 6) err_printf("Matrix to be reduced:\n%Ps\n", M); err_printf("Entering LLL\nbitsize bound: %ld\n", expi(Z)); err_printf("expected shvector bitsize: %ld\n", expi(ZM_det_triangular(M))/dim); } sh = ZM_lll(M, 0.75, LLL_INPLACE); /* Take the first vector if it is non constant */ short_pol = gel(sh,1); if (ZV_isscalar(short_pol)) short_pol = gel(sh, 2); nsp = gen_0; for (j = 1; j <= dim; j++) nsp = addii(nsp, absi(gel(short_pol,j))); if (DEBUGLEVEL >= 2) { err_printf("Candidate: %Ps\n", short_pol); err_printf("bitsize Norm: %ld\n", expi(nsp)); err_printf("bitsize bound: %ld\n", expi(mului(bnd, Z))); } if (cmpii(nsp, mului(bnd, Z)) < 0) break; /* SUCCESS */ /* Failed with the precomputed or supplied value */ t++; if (t == d) { delta++; t = 1; } if (DEBUGLEVEL >= 2) err_printf("Increasing dim, delta = %d t = %d\n", delta, t); } bnd = itos(divii(nsp, Z)) + 1; while (!signe(gel(short_pol,dim))) dim--; R = cgetg(dim + 2, t_POL); R[1] = P[1]; for (j = 1; j <= dim; j++) gel(R,j+1) = diviiexact(gel(short_pol,j), Xpowers[j-1]); gel(R,2) = subii(gel(R,2), mului(bnd - 1, N0)); sol = cgetg(1, t_VEC); for (i = -bnd + 1; i < bnd; i++) { GEN r = nfrootsQ(R); if (DEBUGLEVEL >= 2) err_printf("Roots: %Ps\n", r); for (j = 1; j < lg(r); j++) { GEN z = gel(r,j); if (typ(z) == t_INT && sol_OK(FpX_eval(P,z,N), N,B)) sol = shallowconcat(sol, z); } if (i < bnd) gel(R,2) = addii(gel(R,2), Z); } return gerepileupto(av, ZV_sort_uniq(sol)); } /********************************************************************/ /** **/ /** LINEAR & ALGEBRAIC DEPENDENCE **/ /** **/ /********************************************************************/ static int real_indep(GEN re, GEN im, long bitprec) { GEN p1 = gsub(gmul(gel(re,1),gel(im,2)), gmul(gel(re,2),gel(im,1))); return (!gequal0(p1) && gexpo(p1) > - bitprec); } GEN lindep2(GEN x, long bit) { long tx=typ(x), lx=lg(x), ly, i, j; pari_sp av = avma; GEN re, im, M; if (! is_vec_t(tx)) pari_err_TYPE("lindep2",x); if (lx<=2) { if (lx == 2 && gequal0(x)) return mkcol(gen_1); return cgetg(1,t_COL); } if (bit < 0) pari_err_DOMAIN("lindep2", "accuracy", "<", gen_0, stoi(bit)); if (!bit) { bit = gprecision(x); if (!bit) { x = primpart(x); bit = 32 + gexpo(x); } else bit = (long)prec2nbits_mul(bit, 0.8); } else bit = (long) (bit/LOG10_2); re = real_i(x); im = imag_i(x); /* independent over R ? */ if (lx == 3 && real_indep(re,im,bit)) { avma = av; return cgetg(1, t_COL); } if (gequal0(im)) im = NULL; ly = im? lx+2: lx+1; M = cgetg(lx,t_MAT); for (i=1; i= 0 */ for (i=1; i= 1 */ for (i=3; i<=n+1; i++) gel(y,i) = gmul(gel(y,i-1),x); if (typ(x) == t_PADIC) y = padic_lindep(y); else y = lindep2(y, bit); if (lg(y) == 1) pari_err(e_DOMAIN,"algdep", "degree(x)",">", stoi(n), x); y = RgV_to_RgX(y, 0); if (signe(leading_term(y)) > 0) return gerepilecopy(av, y); return gerepileupto(av, ZX_neg(y)); } GEN algdep(GEN x, long n) { return algdep0(x,n,0); } GEN seralgdep(GEN s, long p, long r) { pari_sp av = avma; long vy, i, m, n, prec; GEN S, v, D; if (typ(s) != t_SER) pari_err_TYPE("seralgdep",s); if (p <= 0) pari_err_DOMAIN("seralgdep", "p", "<=", gen_0, stoi(p)); if (r < 0) pari_err_DOMAIN("seralgdep", "r", "<", gen_0, stoi(r)); if (is_bigint(addiu(muluu(p, r), 1))) pari_err_OVERFLOW("seralgdep"); vy = varn(s); if (!vy) pari_err_PRIORITY("seralgdep", s, ">", 0); r++; p++; prec = valp(s) + lg(s)-2; if (r > prec) r = prec; S = cgetg(p+1, t_VEC); gel(S, 1) = s; for (i = 2; i <= p; i++) gel(S,i) = gmul(gel(S,i-1), s); v = cgetg(r*p+1, t_VEC); /* v[r*n+m+1] = s^n * y^m */ /* n = 0 */ for (m = 0; m < r; m++) gel(v, m + 1) = monomial(gen_1, m, vy); for(n=1; n < p; n++) for (m = 0; m < r; m++) { GEN c = gel(S,n); if (m) { c = shallowcopy(c); setvalp(c, valp(c) + m); } gel(v, r*n + m + 1) = c; } D = Xadic_lindep(v); if (lg(D) == 1) { avma = av; return gen_0; } v = cgetg(p+1, t_VEC); for (n = 0; n < p; n++) gel(v, n+1) = RgV_to_RgX(vecslice(D, r*n+1, r*n+r), vy); return gerepilecopy(av, RgV_to_RgX(v, 0)); } /********************************************************************/ /** **/ /** MINIM **/ /** **/ /********************************************************************/ void minim_alloc(long n, double ***q, GEN *x, double **y, double **z, double **v) { long i, s; *x = cgetg(n, t_VECSMALL); *q = (double**) new_chunk(n); s = n * sizeof(double); init_dalloc(); *y = dalloc(s); *z = dalloc(s); *v = dalloc(s); for (i=1; i6) { err_printf("adding vector = %Ps\n",V); err_printf("vector in new basis = %Ps\n",a); err_printf("list = %Ps\n",L); err_printf("base change matrix =\n%Ps\n", invp); } k = 1; while (ka = RgM_gtofp(a, DEFAULTPREC); r = qfgaussred_positive(qv->a); if (!r) { r = qfgaussred_positive(a); /* exact computation */ if (!r) err_minim(a); r = RgM_gtofp(r, DEFAULTPREC); } qv->r = r; qv->u = u; } static void forqfvec_init(struct qfvec *qv, GEN a) { forqfvec_init_dolll(qv, a, 1); } static void forqfvec(void *E, long (*fun)(void *, GEN, GEN, double), struct qfvec *qv, GEN BORNE) { GEN x, a = qv->a, r = qv->r, u = qv->u; long n = lg(a), i, j, k; double p,BOUND,*v,*y,*z,**q; const double eps = 0.0001; if (!BORNE) BORNE = gen_0; else { BORNE = gfloor(BORNE); if (typ(BORNE) != t_INT) pari_err_TYPE("minim0",BORNE); } if (n == 1) return; minim_alloc(n, &q, &x, &y, &z, &v); n--; for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k > 1); if (! x[1] && y[1]<=eps) break; p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x) */ if (fun(E, u, x, p)) break; } } static long _gp_forqf(void *E, GEN u, GEN x, double p/*unused*/) { pari_sp av = avma; (void)p; set_lex(-1, ZM_zc_mul(u, x)); closure_evalvoid((GEN)E); avma = av; return loop_break(); } void forqfvec0(GEN a, GEN BORNE, GEN code) { pari_sp av = avma; struct qfvec qv; forqfvec_init(&qv, a); push_lex(gen_0, code); forqfvec((void*) code, &_gp_forqf, &qv, BORNE); pop_lex(1); avma = av; } /* Minimal vectors for the integral definite quadratic form: a. * Result u: * u[1]= Number of vectors of square norm <= BORNE * u[2]= maximum norm found * u[3]= list of vectors found (at most STOCKMAX) * * If BORNE = gen_0: Minimal non-zero vectors. * flag = min_ALL, as above * flag = min_FIRST, exits when first suitable vector is found. * flag = min_PERF, only compute rank of the family of v.v~ (v min.) * flag = min_VECSMALL, return a t_VECSMALL of (half) the number of vectors for each norm * flag = min_VECSMALL2, same but count only vectors with even norm, and shift the answer */ static GEN 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; double p,maxnorm,BOUND,*v,*y,*z,**q; const double eps = 1e-10; int stockall = 0; struct qfvec qv; if (!BORNE) sBORNE = 0; else { BORNE = gfloor(BORNE); if (typ(BORNE) != t_INT) pari_err_TYPE("minim0",BORNE); if (is_bigint(BORNE)) pari_err_PREC( "qfminim"); sBORNE = itos(BORNE); avma = av; } if (!STOCKMAX) { stockall = 1; maxrank = 200; } else { STOCKMAX = gfloor(STOCKMAX); if (typ(STOCKMAX) != t_INT) pari_err_TYPE("minim0",STOCKMAX); maxrank = itos(STOCKMAX); if (maxrank < 0) pari_err_TYPE("minim0 [negative number of vectors]",STOCKMAX); } L = V = invp = NULL; /* gcc -Wall */ switch(flag) { case min_VECSMALL: case min_VECSMALL2: if (sBORNE <= 0) return cgetg(1, t_VECSMALL); L = zero_zv(sBORNE); if (flag == min_VECSMALL2) sBORNE <<= 1; if (n == 1) return L; break; case min_FIRST: if (n == 1) return cgetg(1,t_VEC); if (!sBORNE && BORNE) return cgetg(1, t_VEC); break; case min_PERF: if (n == 1) return gen_0; break; default: if (n == 1 || (!sBORNE && BORNE)) retmkvec3(gen_0, gen_0, cgetg(1, t_MAT)); break; } minim_alloc(n, &q, &x, &y, &z, &v); av1 = avma; forqfvec_init_dolll(&qv, a, dolll); r = qv.r; u = qv.u; n--; for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i> 1; L = zero_zv(maxrank); V = cgetg(1+maxrank, t_VECSMALL); } s = 0; av1 = avma; lim = stack_lim(av1,1); k = n; y[n] = z[n] = 0; x[n] = (long)sqrt(BOUND/v[n]); for(;;x[1]--) { do { if (k>1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k > 1); if (! x[1] && y[1]<=eps) break; p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x) */ if (maxnorm >= 0) { if (p > maxnorm) maxnorm = p; } else { /* maxnorm < 0 : only look for minimal vectors */ pari_sp av2 = avma; gnorme = roundr(dbltor(p)); if (cmpis(gnorme, sBORNE) >= 0) avma = av2; else { sBORNE = itos(gnorme); avma = av1; BOUND = sBORNE * (1+eps); s = 0; } } s++; switch(flag) { case min_FIRST: return gerepilecopy(av, mkvec2(roundr(dbltor(p)), ZM_zc_mul(u,x))); case min_ALL: if (s > maxrank && stockall) /* overflow */ { long maxranknew = maxrank << 1; GEN Lnew = new_chunk(1 + maxranknew); for (i=1; i<=maxrank; i++) Lnew[i] = L[i]; L = Lnew; maxrank = maxranknew; } if (s<=maxrank) gel(L,s) = leafcopy(x); break; case min_VECSMALL: { ulong norm = (ulong)(p + 0.5); L[norm]++; } break; case min_VECSMALL2: { ulong norm = (ulong)(p + 0.5); if ((norm&1) == 0) L[norm>>1]++; } break; case min_PERF: { pari_sp av2; long I; if (s == 1) { invp = matid(maxrank); for (i = 1; i <= maxrank; i++) L[i] = 0; } /* must go till the end in case we find a smallest vector last */ if (s > maxrank) { s = maxrank; continue; } av2 = avma; for (i = I = 1; i<=n; i++) for (j=i; j<=n; j++,I++) V[I] = x[i]*x[j]; if (! addcolumntomatrix(V,invp,L)) { if (DEBUGLEVEL>1) { err_printf("."); err_flush(); } s--; avma=av2; continue; } if (DEBUGLEVEL>1) { err_printf("*"); err_flush(); } if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"minim0, rank>=%ld",s); invp = gerepilecopy(av1, invp); } } } } switch(flag) { case min_FIRST: avma = av; return cgetg(1,t_VEC); case min_VECSMALL: case min_VECSMALL2: avma = (pari_sp)L; return L; case min_PERF: if (DEBUGLEVEL>1) { err_printf("\n"); err_flush(); } avma = av; return stoi(s); } r = (maxnorm >= 0) ? roundr(dbltor(maxnorm)): stoi(sBORNE); k = minss(s,maxrank); L[0] = evaltyp(t_MAT) | evallg(k + 1); if (dolll) for (j=1; j<=k; j++) gel(L,j) = ZM_zc_mul(u, gel(L,j)); return gerepilecopy(av, mkvec3(stoi(s<<1), r, L)); } static GEN minim0(GEN a, GEN BORNE, GEN STOCKMAX, long flag) { return minim0_dolll(a, BORNE, STOCKMAX, flag, 1); } GEN qfrep0(GEN a, GEN borne, long flag) { return minim0(a, borne, gen_0, (flag & 1)? min_VECSMALL2: min_VECSMALL); } GEN qfminim0(GEN a, GEN borne, GEN stockmax, long flag, long prec) { switch(flag) { case 0: return minim0(a,borne,stockmax,min_ALL); case 1: return minim0(a,borne,gen_0 ,min_FIRST); case 2: { long maxnum = -1; if (typ(a) != t_MAT) pari_err_TYPE("qfminim",a); if (stockmax) { if (typ(stockmax) != t_INT) pari_err_TYPE("qfminim",stockmax); maxnum = itos(stockmax); } a = fincke_pohst(a,borne,maxnum,prec,NULL); if (!a) pari_err_PREC("qfminim"); return a; } default: pari_err_FLAG("qfminim"); } return NULL; /* not reached */ } GEN minim(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_ALL); } GEN minim_raw(GEN a, GEN BORNE, GEN STOCKMAX) { return minim0_dolll(a, BORNE, STOCKMAX, min_ALL, 0); } GEN minim2(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_FIRST); } GEN perf(GEN a) { return minim0(a,NULL,NULL,min_PERF); } static GEN clonefill(GEN S, long s, long t) { /* initialize to dummy values */ GEN T = S, dummy = cgetg(1, t_STR); long i; for (i = s+1; i <= t; i++) gel(S,i) = dummy; S = gclone(S); if (isclone(T)) gunclone(T); return S; } /* increment ZV x, by incrementing cell of index k. Initial value x0[k] was * chosen to minimize qf(x) for given x0[1..k-1] and x0[k+1,..] = 0 * The last non-zero entry must be positive and goes through x0[k]+1,2,3,... * Others entries go through: x0[k]+1,-1,2,-2,...*/ INLINE void step(GEN x, GEN y, GEN inc, long k) { if (!signe(gel(y,k))) /* x[k+1..] = 0 */ gel(x,k) = addiu(gel(x,k), 1); /* leading coeff > 0 */ else { long i = inc[k]; gel(x,k) = addis(gel(x,k), i), inc[k] = (i > 0)? -1-i: 1-i; } } /* 1 if we are "sure" that x < y, up to few rounding errors, i.e. * x < y - epsilon. More precisely : * - sign(x - y) < 0 * - lgprec(x-y) > 3 || expo(x - y) - expo(x) > -24 */ static int mplessthan(GEN x, GEN y) { pari_sp av = avma; GEN z = mpsub(x, y); avma = av; if (typ(z) == t_INT) return (signe(z) < 0); if (signe(z) >= 0) return 0; if (realprec(z) > LOWDEFAULTPREC) return 1; return ( expo(z) - mpexpo(x) > -24 ); } /* 1 if we are "sure" that x > y, up to few rounding errors, i.e. * x > y + epsilon */ static int mpgreaterthan(GEN x, GEN y) { pari_sp av = avma; GEN z = mpsub(x, y); avma = av; if (typ(z) == t_INT) return (signe(z) > 0); if (signe(z) <= 0) return 0; if (realprec(z) > LOWDEFAULTPREC) return 1; return ( expo(z) - mpexpo(x) > -24 ); } /* x a t_INT, y t_INT or t_REAL */ INLINE GEN mulimp(GEN x, GEN y) { if (typ(y) == t_INT) return mulii(x,y); return signe(x) ? mulir(x,y): gen_0; } /* x + y*z, x,z two mp's, y a t_INT */ INLINE GEN addmulimp(GEN x, GEN y, GEN z) { if (!signe(y)) return x; if (typ(z) == t_INT) return mpadd(x, mulii(y, z)); return mpadd(x, mulir(y, z)); } /* yk + vk * (xk + zk)^2 */ static GEN norm_aux(GEN xk, GEN yk, GEN zk, GEN vk) { GEN t = mpadd(xk, zk); if (typ(t) == t_INT) { /* probably gen_0, avoid loss of accuracy */ yk = addmulimp(yk, sqri(t), vk); } else { yk = mpadd(yk, mpmul(sqrr(t), vk)); } return yk; } /* yk + vk * (xk + zk)^2 < B + epsilon */ static int check_bound(GEN B, GEN xk, GEN yk, GEN zk, GEN vk) { pari_sp av = avma; int f = mpgreaterthan(norm_aux(xk,yk,zk,vk), B); avma = av; return !f; } /* q(k-th canonical basis vector), where q is given in Cholesky form * q(x) = sum_{i = 1}^n q[i,i] (x[i] + sum_{j > i} q[i,j] x[j])^2. * Namely q(e_k) = q[k,k] + sum_{i < k} q[i,i] q[i,k]^2 * Assume 1 <= k <= n. */ static GEN cholesky_norm_ek(GEN q, long k) { GEN t = gcoeff(q,k,k); long i; for (i = 1; i < k; i++) t = norm_aux(gen_0, t, gcoeff(q,i,k), gcoeff(q,i,i)); return t; } /* q is the Cholesky decomposition of a quadratic form * Enumerate vectors whose norm is less than BORNE (Algo 2.5.7), * minimal vectors if BORNE = NULL (implies check = NULL). * If (check != NULL) consider only vectors passing the check, and assumes * we only want the smallest possible vectors */ 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; GEN inc, S, x, y, z, v, p1, alpha, norms; GEN norme1, normax1, borne1, borne2; GEN (*check)(void *,GEN) = CHECK? CHECK->f: NULL; void *data = CHECK? CHECK->data: NULL; const long skipfirst = CHECK? CHECK->skipfirst: 0; const int stockall = (maxnum == -1); alpha = dbltor(0.95); normax1 = gen_0; v = cgetg(N,t_VEC); inc = const_vecsmall(n, 1); av = avma; lim = stack_lim(av,2); stockmax = stockall? 2000: maxnum; norms = cgetg(check?(stockmax+1): 1,t_VEC); /* unused if (!check) */ S = cgetg(stockmax+1,t_VEC); x = cgetg(N,t_COL); y = cgetg(N,t_COL); z = cgetg(N,t_COL); for (i=1; i2) err_printf("smallvectors looking for norm < %P.4G\n",borne1); s = 0; k = n; for(;; step(x,y,inc,k)) /* main */ { /* x (supposedly) small vector, ZV. * For all t >= k, we have * z[t] = sum_{j > t} q[t,j] * x[j] * y[t] = sum_{i > t} q[i,i] * (x[i] + z[i])^2 * = 0 <=> x[i]=0 for all i>t */ do { int skip = 0; if (k > 1) { long l = k-1; av1 = avma; p1 = mulimp(gel(x,k), gcoeff(q,l,k)); for (j=k+1; j n) goto END; } if (low_stack(lim, stack_lim(av,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"smallvectors"); if (stockmax) S = clonefill(S, s, stockmax); if (check) { GEN dummy = cgetg(1, t_STR); for (i=s+1; i<=stockmax; i++) gel(norms,i) = dummy; } gerepileall(av,7,&x,&y,&z,&normax1,&borne1,&borne2,&norms); } } while (k > 1); if (!signe(gel(x,1)) && !signe(gel(y,1))) continue; /* exclude 0 */ av1 = avma; norme1 = norm_aux(gel(x,1),gel(y,1),gel(z,1),gel(v,1)); if (mpgreaterthan(norme1,borne1)) { avma = av1; continue; /* main */ } norme1 = gerepileuptoleaf(av1,norme1); if (check) { if (checkcnt < 5 && mpcmp(norme1, borne2) < 0) { if (!check(data,x)) { checkcnt++ ; continue; /* main */} if (DEBUGLEVEL>4) err_printf("New bound: %Ps", norme1); borne1 = norme1; borne2 = mulrr(borne1, alpha); s = 0; checkcnt = 0; } } else { if (!BORNE) /* find minimal vectors */ { if (mplessthan(norme1, borne1)) { /* strictly smaller vector than previously known */ borne1 = norme1; /* + epsilon */ s = 0; } } else if (mpcmp(norme1,normax1) > 0) normax1 = norme1; } if (++s > stockmax) continue; /* too many vectors: no longer remember */ if (check) gel(norms,s) = norme1; gel(S,s) = leafcopy(x); if (s != stockmax) continue; /* still room, get next vector */ /* overflow, eliminate vectors failing "check" */ if (check) { pari_sp av2 = avma; long imin, imax; GEN per = indexsort(norms); if (DEBUGLEVEL>2) err_printf("sorting... [%ld elts]\n",s); /* let N be the minimal norm so far for x satisfying 'check'. Keep * all elements of norm N */ for (i = 1; i <= s; i++) { long k = per[i]; if (check(data,gel(S,k))) { borne1 = gel(norms,k); break; } } imin = i; for (; i <= s; i++) if (mpgreaterthan(gel(norms,per[i]), borne1)) break; imax = i; for (i=imin, s=0; i < imax; i++) gel(S,++s) = gel(S,per[i]); avma = av2; if (s) { borne2 = mulrr(borne1, alpha); checkcnt = 0; } if (!stockall) continue; if (s > stockmax/2) stockmax <<= 1; norms = cgetg(stockmax+1, t_VEC); for (i = 1; i <= s; i++) gel(norms,i) = borne1; } else { if (!stockall && BORNE) goto END; if (!stockall) continue; stockmax <<= 1; } { GEN Snew = cgetg(stockmax + 1, t_VEC); for (i = 1; i <= s; i++) gel(Snew,i) = gel(S,i); Snew = clonefill(Snew, s, stockmax); if (isclone(S)) gunclone(S); S = Snew; } } END: if (s < stockmax) stockmax = s; if (check) { GEN per, alph, pols, p; if (DEBUGLEVEL>2) err_printf("final sort & check...\n"); setlg(norms,stockmax+1); per = indexsort(norms); alph = cgetg(stockmax+1,t_VEC); pols = cgetg(stockmax+1,t_VEC); for (j=0,i=1; i<=stockmax; i++) { long t = per[i]; GEN N = gel(norms,t); if (j && mpgreaterthan(N, borne1)) break; if ((p = check(data,gel(S,t)))) { if (!j) borne1 = N; j++; gel(pols,j) = p; gel(alph,j) = gel(S,t); } } setlg(pols,j+1); setlg(alph,j+1); if (stockmax && isclone(S)) { alph = gcopy(alph); gunclone(S); } return mkvec2(pols, alph); } if (stockmax) { setlg(S,stockmax+1); settyp(S,t_MAT); if (isclone(S)) { p1 = S; S = gcopy(S); gunclone(p1); } } else S = cgetg(1,t_MAT); return mkvec3(utoi(s<<1), borne1, S); } /* solve q(x) = x~.a.x <= bound, a > 0. * If check is non-NULL keep x only if check(x). * If a is a vector, assume a[1] is the LLL-reduced Cholesky form of q */ GEN fincke_pohst(GEN a, GEN B0, long stockmax, long PREC, FP_chk_fun *CHECK) { pari_sp av = avma; VOLATILE long i,j,l; VOLATILE GEN r,rinv,rinvtrans,u,v,res,z,vnorm,rperm,perm,uperm, bound = B0; if (typ(a) == t_VEC) { r = gel(a,1); u = NULL; } else { long prec = PREC; l = lg(a); if (l == 1) { if (CHECK) pari_err_TYPE("fincke_pohst [dimension 0]", a); retmkvec3(gen_0, gen_0, cgetg(1,t_MAT)); } u = lllfp(a, 0.75, LLL_GRAM); if (lg(u) != lg(a)) return NULL; r = qf_apply_RgM(a,u); i = gprecision(r); if (i) prec = i; else { prec = DEFAULTPREC + nbits2extraprec(gexpo(r)); if (prec < PREC) prec = PREC; } if (DEBUGLEVEL>2) err_printf("first LLL: prec = %ld\n", prec); r = qfgaussred_positive(r); if (!r) return NULL; for (i=1; i2) err_printf("Fincke-Pohst, final LLL: prec = %ld\n", gprecision(rinvtrans)); v = lll(rinvtrans); if (lg(v) != lg(rinvtrans)) return NULL; rinvtrans = RgM_mul(rinvtrans, v); v = ZM_inv(shallowtrans(v),gen_1); r = RgM_mul(r,v); u = u? ZM_mul(u,v): v; l = lg(r); vnorm = cgetg(l,t_VEC); for (j=1; jf_init) bound = CHECK->f_init(CHECK, r, u); q = gaussred_from_QR(r, gprecision(vnorm)); if (!q) pari_err_PREC("fincke_pohst"); res = smallvectors(q, bound, stockmax, CHECK); } pari_ENDCATCH; if (CHECK) { if (CHECK->f_post) res = CHECK->f_post(CHECK, res, u); return res; } if (!res) pari_err_PREC("fincke_pohst"); z = cgetg(4,t_VEC); gel(z,1) = gcopy(gel(res,1)); gel(z,2) = gcopy(gel(res,2)); gel(z,3) = ZM_mul(u, gel(res,3)); return gerepileupto(av,z); } pari-2.7.5/src/basemath/gen2.c0000644000175000017500000020306312573016510014464 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (second part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /*********************************************************************/ /** **/ /** MAP FUNCTIONS WITH GIVEN PROTOTYPES **/ /** **/ /*********************************************************************/ GEN map_proto_G(GEN f(GEN), GEN x) { if (is_matvec_t(typ(x))) { long lx, i; GEN y = cgetg_copy(x, &lx); for (i=1; i t_SER */ /* */ /*******************************************************************/ static GEN greffe_aux(GEN x, long l, long lx, long v) { GEN y = cgetg(l,t_SER); long i; if (l <= 2) pari_err_BUG("RgX_to_ser (l <= 2)"); y[1] = x[1]; setvalp(y, v); x += v; lx -= v; if (lx > l) { for (i = 2; i < l; i++) gel(y,i) = gel(x,i); } else { for (i = 2; i long */ /* */ /*******************************************************************/ long gtolong(GEN x) { switch(typ(x)) { case t_INT: return itos(x); case t_REAL: return (long)(rtodbl(x) + 0.5); case t_FRAC: { pari_sp av = avma; long y = itos(ground(x)); avma = av; return y; } case t_COMPLEX: if (gequal0(gel(x,2))) return gtolong(gel(x,1)); break; case t_QUAD: if (gequal0(gel(x,3))) return gtolong(gel(x,2)); break; } pari_err_TYPE("gtolong",x); return 0; /* not reached */ } /*******************************************************************/ /* */ /* COMPARISONS */ /* */ /*******************************************************************/ int isexactzero(GEN g) { long i, lx; switch (typ(g)) { case t_INT: return !signe(g); case t_INTMOD: return !signe(gel(g,2)); case t_COMPLEX: return isexactzero(gel(g,1)) && isexactzero(gel(g,2)); case t_FFELT: return FF_equal0(g); case t_QUAD: return isexactzero(gel(g,2)) && isexactzero(gel(g,3)); case t_POLMOD: return isexactzero(gel(g,2)); case t_POL: lx = lg(g); /* cater for Mod(0,2)*x^0 */ return lx == 2 || (lx == 3 && isexactzero(gel(g,2))); case t_RFRAC: return isexactzero(gel(g,1)); /* may occur: Mod(0,2)/x */ case t_VEC: case t_COL: case t_MAT: for (i=lg(g)-1; i; i--) if (!isexactzero(gel(g,i))) return 0; return 1; } return 0; } int isrationalzero(GEN g) { long i; switch (typ(g)) { case t_INT: return !signe(g); case t_COMPLEX: return isintzero(gel(g,1)) && isintzero(gel(g,2)); case t_QUAD: return isintzero(gel(g,2)) && isintzero(gel(g,3)); case t_POLMOD: return isrationalzero(gel(g,2)); case t_POL: return lg(g) == 2; case t_VEC: case t_COL: case t_MAT: for (i=lg(g)-1; i; i--) if (!isrationalzero(gel(g,i))) return 0; return 1; } return 0; } int gequal0(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_POL: case t_SER: return !signe(x); case t_INTMOD: return !signe(gel(x,2)); case t_FFELT: return FF_equal0(x); case t_COMPLEX: /* is 0 iff norm(x) would be 0 (can happen with Re(x) and Im(x) != 0 * only if Re(x) and Im(x) are of type t_REAL). See mp.c:addrr(). */ if (gequal0(gel(x,1))) { if (gequal0(gel(x,2))) return 1; if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0; return (expo(gel(x,1))>expo(gel(x,2))); } if (gequal0(gel(x,2))) { if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0; return (expo(gel(x,2))>expo(gel(x,1))); } return 0; case t_PADIC: return !signe(gel(x,4)); case t_QUAD: return gequal0(gel(x,2)) && gequal0(gel(x,3)); case t_POLMOD: return gequal0(gel(x,2)); case t_RFRAC: return gequal0(gel(x,1)); case t_VEC: case t_COL: case t_MAT: { long i; for (i=lg(x)-1; i; i--) if (!gequal0(gel(x,i))) return 0; return 1; } } return 0; } /* x a t_POL or t_SER, considered as having valuation v; let X(t) = t^(-v) x(t) * return 1 (true) if coeff(X,i) = 0 for all i != 0 and test(coeff(X, 0)) * is true. Return 0 (false) otherwise, or if x == 0 */ static int is_monomial_test(GEN x, long v, int(*test)(GEN)) { long d, i, l; if (!signe(x)) return 0; if (v > 0) return 0; l = lg(x); d = 2-v; if (l <= d) return 0; /* 2 <= d < l */ if (!test(gel(x,d))) return 0; for (i = 2; i < d; i++) if (!gequal0(gel(x,i))) return 0; for (i = d+1; i < l; i++) if (!gequal0(gel(x,i))) return 0; return 1; } static int col_test(GEN x, int(*test)(GEN)) { long i, l = lg(x); if (l == 1) return 0; if (!test(gel(x,1))) return 0; for (i = 2; i < l; i++) if (!gequal0(gel(x,i))) return 0; return 1; } static int mat_test(GEN x, int(*test)(GEN)) { long i, j, l = lg(x); if (l == 1) return 1; if (l != lgcols(x)) return 0; for (i = 1; i < l; i++) for (j = 1; j < l; j++) if (i == j) { if (!test(gcoeff(x,i,i))) return 0; } else { if (!gequal0(gcoeff(x,i,j))) return 0; } return 1; } /* returns 1 whenever x = 1, and 0 otherwise */ int gequal1(GEN x) { switch(typ(x)) { case t_INT: return equali1(x); case t_REAL: return signe(x) > 0 ? absrnz_equal1(x): 0; case t_INTMOD: case t_POLMOD: return gequal1(gel(x,2)); case t_FFELT: return FF_equal1(x); case t_FRAC: return 0; case t_COMPLEX: return gequal1(gel(x,1)) && gequal0(gel(x,2)); case t_PADIC: return !valp(x) && gequal1(gel(x,4)); case t_QUAD: return gequal1(gel(x,2)) && gequal0(gel(x,3)); case t_POL: return is_monomial_test(x, 0, &gequal1); case t_SER: return is_monomial_test(x, valp(x), &gequal1); case t_RFRAC: return gequal(gel(x,1), gel(x,2)); case t_COL: return col_test(x, &gequal1); case t_MAT: return mat_test(x, &gequal1); } return 0; } /* returns 1 whenever the x = -1, 0 otherwise */ int gequalm1(GEN x) { pari_sp av; long y; GEN p1; switch(typ(x)) { case t_INT: return equalim1(x); case t_REAL: return signe(x) < 0 ? absrnz_equal1(x): 0; case t_INTMOD: av=avma; y=equalii(addsi(1,gel(x,2)), gel(x,1)); avma=av; return y; case t_FRAC: return 0; case t_FFELT: return FF_equalm1(x); case t_COMPLEX: return gequalm1(gel(x,1)) && gequal0(gel(x,2)); case t_QUAD: return gequalm1(gel(x,2)) && gequal0(gel(x,3)); case t_PADIC: av=avma; y=equalii(addsi(1,gel(x,4)), gel(x,3)); avma=av; return y; case t_POLMOD: av=avma; p1 = gaddgs(gel(x,2), 1); y = signe(p1) && !gequal(p1,gel(x,1)); avma=av; return !y; case t_POL: return is_monomial_test(x, 0, &gequalm1); case t_SER: return is_monomial_test(x, valp(x), &gequalm1); case t_RFRAC: av=avma; y=gequal(gel(x,1), gneg_i(gel(x,2))); avma=av; return y; case t_COL: return col_test(x, &gequalm1); case t_MAT: return mat_test(x, &gequalm1); } return 0; } int gequalX(GEN x) { return typ(x) == t_POL && lg(x) == 4 && isintzero(gel(x,2)) && isint1(gel(x,3)); } static int cmp_str(const char *x, const char *y) { int f = strcmp(x, y); return f > 0? 1 : f? -1: 0; } static int cmp_universal_rec(GEN x, GEN y, long i0) { long i, lx = lg(x), ly = lg(y); if (lx < ly) return -1; if (lx > ly) return 1; for (i = i0; i < lx; i++) { int f = cmp_universal(gel(x,i), gel(y,i)); if (f) return f; } return 0; } /* Universal "meaningless" comparison function. Transitive, returns 0 iff * gidentical(x,y) */ int cmp_universal(GEN x, GEN y) { long lx, ly, i, tx = typ(x), ty = typ(y); if (tx < ty) return -1; if (ty < tx) return 1; switch(tx) { case t_INT: return cmpii(x,y); case t_STR: return cmp_str(GSTR(x),GSTR(y)); case t_REAL: case t_VECSMALL: lx = lg(x); ly = lg(y); if (lx < ly) return -1; if (lx > ly) return 1; for (i = 1; i < lx; i++) { if (x[i] < y[i]) return -1; if (x[i] > y[i]) return 1; } return 0; case t_POL: case t_SER: case t_FFELT: case t_CLOSURE: if (x[1] < y[1]) return -1; if (x[1] > y[1]) return 1; return cmp_universal_rec(x, y, 2); case t_LIST: x = list_data(x); y = list_data(y); if (!x) return y? -1: 0; if (!y) return 1; return cmp_universal_rec(x, y, 1); default: return cmp_universal_rec(x, y, lontyp[tx]); } } static int cmpfrac(GEN x, GEN y) { pari_sp av = avma; GEN a = gel(x,1), b = gel(x,2); GEN c = gel(y,1), d = gel(y,2); int r = cmpii(mulii(a, d), mulii(b, c)); avma = av; return r; } static int cmpifrac(GEN a, GEN y) { pari_sp av = avma; GEN c = gel(y,1), d = gel(y,2); int r = cmpii(mulii(a, d), c); avma = av; return r; } static int cmprfrac(GEN a, GEN y) { pari_sp av = avma; GEN c = gel(y,1), d = gel(y,2); int r = cmpri(mulri(a, d), c); avma = av; return r; } /* returns the sign of x - y when it makes sense. 0 otherwise */ int gcmp(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == ty) /* generic case */ switch(tx) { case t_INT: return cmpii(x, 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)); } switch(tx) { case t_INT: switch(ty) { case t_REAL: return cmpir(x, y); case t_FRAC: return cmpifrac(x, y); case t_STR: return -1; } break; case t_REAL: switch(ty) { case t_INT: return cmpri(x, y); case t_FRAC: return cmprfrac(x, y); case t_STR: return -1; } break; case t_FRAC: switch(ty) { case t_INT: return -cmpifrac(y, x); case t_REAL: return -cmprfrac(y, x); case t_STR: return -1; } break; case t_STR: return 1; } pari_err_TYPE2("comparison",x,y); return 0;/*not reached*/ } int gcmpsg(long s, GEN y) { long ty = typ(y); switch(ty) { case t_INT: return cmpsi(s,y); case t_REAL: return cmpsr(s,y); case t_FRAC: { pari_sp av = avma; GEN n = gel(y,1), d = gel(y,2); int f = cmpii(mulsi(s,d), n); avma = av; return f; } case t_STR: return -1; } pari_err_TYPE2("comparison",stoi(s),y); return 0; /* not reached */ } static long roughtype(GEN x) { switch(typ(x)) { case t_MAT: return t_MAT; case t_VEC: case t_COL: return t_VEC; case t_VECSMALL: return t_VECSMALL; default: return t_INT; } } static int lexcmpsg(long x, GEN y); static int lexcmpgs(GEN x, long y) { return -lexcmpsg(y,x); } /* lexcmp(stoi(x),y), y t_VEC/t_COL/t_MAT */ static int lexcmp_s_matvec(long x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmpsg(x,gel(y,1)); if (fl) return fl; return -1; } /* x a scalar, y a t_VEC/t_COL/t_MAT */ static int lexcmp_scal_matvec(GEN x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmp(x,gel(y,1)); if (fl) return fl; return -1; } /* x a scalar, y a t_VECSMALL */ static int lexcmp_scal_vecsmall(GEN x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmpgs(x, y[1]); if (fl) return fl; return -1; } /* tx = ty = t_MAT, or x and y are both vect_t */ static int lexcmp_similar(GEN x, GEN y) { long i, lx = lg(x), ly = lg(y), l = minss(lx,ly); for (i=1; i y[1])? 1: -1; default: return gcmpsg(x,y); } } /* as gcmp for vector/matrices, using lexicographic ordering on components */ int lexcmp(GEN x, GEN y) { const long tx = roughtype(x), ty = roughtype(y); if (tx == ty) switch(tx) { case t_MAT: case t_VEC: return lexcmp_similar(x,y); case t_VECSMALL: return vecsmall_lexcmp(x,y); default: return gcmp(x,y); } if (tx == t_VECSMALL) return lexcmp_vecsmall_other(x,y,ty); if (ty == t_VECSMALL) return -lexcmp_vecsmall_other(y,x,tx); if (tx == t_INT) return lexcmp_scal_matvec(x,y); /*scalar*/ if (ty == t_INT) return -lexcmp_scal_matvec(y,x); if (ty==t_MAT) return lexcmp_vec_mat(x,y); /*tx==t_MAT*/ return -lexcmp_vec_mat(y,x); } /*****************************************************************/ /* */ /* EQUALITY */ /* returns 1 if x == y, 0 otherwise */ /* */ /*****************************************************************/ /* x,y t_POL */ static int polidentical(GEN x, GEN y) { long lx; if (x[1] != y[1]) return 0; lx = lg(x); if (lg(y) != lg(x)) return 0; for (lx--; lx >= 2; lx--) if (!gidentical(gel(x,lx), gel(y,lx))) return 0; return 1; } /* x,y t_SER */ static int seridentical(GEN x, GEN y) { return polidentical(x,y); } /* typ(x) = typ(y) = t_VEC/COL/MAT */ static int vecidentical(GEN x, GEN y) { long i; if ((x[0] ^ y[0]) & (TYPBITS|LGBITS)) return 0; for (i = lg(x)-1; i; i--) if (! gidentical(gel(x,i),gel(y,i)) ) return 0; return 1; } static int identicalrr(GEN x, GEN y) { long i, lx = lg(x); if (lg(y) != lx) return 0; if (x[1] != y[1]) return 0; i=2; while (i ly) if (!gequal0(gel(x,--lx))) return 0; while (ly > lx) if (!gequal0(gel(y,--ly))) return 0; for (lx--; lx >= 2; lx--) if (!gequal(gel(x,lx), gel(y,lx))) return 0; return 1; } /* x,y t_POL */ static int serequal(GEN x, GEN y) { long lx; if ((x[1] ^ y[1]) & (VARNBITS | SIGNBITS | VALPBITS)) return 0; lx = minss(lg(x), lg(y)); for (lx--; lx >= 2; lx--) if (!gequal(gel(x,lx), gel(y,lx))) return 0; return 1; } /* typ(x) = typ(y) = t_VEC/COL/MAT */ static int vecequal(GEN x, GEN y) { long i; if ((x[0] ^ y[0]) & (TYPBITS|LGBITS)) return 0; for (i = lg(x)-1; i; i--) if (! gequal(gel(x,i),gel(y,i)) ) return 0; return 1; } static int gequal_try(GEN x, GEN y) { int i; pari_CATCH(CATCH_ALL) { GEN E = pari_err_last(); switch(err_get_num(E)) { case e_STACK: case e_MEM: case e_ALARM: pari_err(0, E); /* rethrow */ } return 0; } pari_TRY { i = gequal0(gadd(x, gneg_i(y))); } pari_ENDCATCH; return i; } int gequal(GEN x, GEN y) { pari_sp av; long tx, ty; long i; if (x == y) return 1; tx = typ(x); ty = typ(y); if (tx == ty) switch(tx) { case t_INT: return equalii(x,y); case t_REAL: return equalrr(x,y); case t_FRAC: case t_INTMOD: return equalii(gel(x,2), gel(y,2)) && equalii(gel(x,1), gel(y,1)); case t_COMPLEX: return gequal(gel(x,2),gel(y,2)) && gequal(gel(x,1),gel(y,1)); case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) return 0; av = avma; i = gequal0(gsub(x,y)); avma = av; return i; case t_POLMOD: return gequal(gel(x,2),gel(y,2)) && RgX_equal_var(gel(x,1),gel(y,1)); case t_POL: return polequal(x,y); case t_SER: return serequal(x,y); case t_FFELT: return FF_equal(x,y); case t_QFR: case t_QFI: return equalii(gel(x,1),gel(y,1)) && equalii(gel(x,2),gel(y,2)) && equalii(gel(x,3),gel(y,3)); case t_QUAD: return ZX_equal(gel(x,1),gel(y,1)) && gequal(gel(x,2),gel(y,2)) && gequal(gel(x,3),gel(y,3)); case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2), c = gel(y,1), d = gel(y,2); if (gequal(b,d)) return gequal(a,c); /* simple case */ av = avma; i = gequal(simplify_shallow(gmul(a,d)), simplify_shallow(gmul(b,c))); avma = av; return i; } case t_STR: return !strcmp(GSTR(x),GSTR(y)); case t_VEC: case t_COL: case t_MAT: return vecequal(x,y); case t_VECSMALL: return zv_equal(x,y); case t_LIST: x = list_data(x); y = list_data(y); if (!x) return y? 0: 1; if (!y) return 0; return gequal(x, y); case t_CLOSURE: return closure_identical(x,y); } (void)&av; /* emulate volatile */ av = avma; i = gequal_try(x, y); avma = av; return i; } int gequalsg(long s, GEN x) { pari_sp av = avma; int f = gequal(stoi(s), x); avma = av; return f; } /*******************************************************************/ /* */ /* VALUATION */ /* p is either a t_INT or a t_POL. */ /* returns the largest exponent of p dividing x when this makes */ /* sense : error for types real, integermod and polymod if p does */ /* not divide the modulus, q-adic if q!=p. */ /* */ /*******************************************************************/ static long minval(GEN x, GEN p) { long i,k, val = LONG_MAX, lx = lg(x); for (i=lontyp[typ(x)]; i 0) return 0; } return minval(x,p); } case t_SER: { if (tp == t_POL) { long vp = varn(p), vx = varn(x); if (vp == vx) { long val = RgX_val(p); if (!val) pari_err_DOMAIN("gvaluation", "p", "=", p, p); return (long)(valp(x) / val); } if (varncmp(vx, vp) > 0) return 0; } return minval(x,p); } case t_RFRAC: return gvaluation(gel(x,1),p) - gvaluation(gel(x,2),p); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: return minval(x,p); } pari_err_OP("valuation", x,p); return 0; /* not reached */ } /* x is non-zero */ long u_lvalrem(ulong x, ulong p, ulong *py) { ulong vx; if (p == 2) { vx = vals(x); *py = x >> vx; return vx; } for(vx = 0;;) { if (x % p) { *py = x; return vx; } x /= p; /* gcc is smart enough to make a single div */ vx++; } } long u_lval(ulong x, ulong p) { ulong vx; if (p == 2) return vals(x); for(vx = 0;;) { if (x % p) return vx; x /= p; /* gcc is smart enough to make a single div */ vx++; } } long z_lval(long s, ulong p) { return u_lval(labs(s), p); } long z_lvalrem(long s, ulong p, long *py) { long v; if (s < 0) { ulong u = (ulong)-s; v = u_lvalrem(u, p, &u); *py = -(long)u; } else { ulong u = (ulong)s; v = u_lvalrem(u, p, &u); *py = (long)u; } return v; } /* assume |p| > 1 */ long z_pval(long s, GEN p) { if (lgefint(p) > 3) return 0; return z_lval(s, (ulong)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 v_q(x) and set *py = x / q^v_q(x), using divide & conquer */ static long Z_pvalrem_DC(GEN x, GEN q, GEN *py) { GEN r, z = dvmdii(x, q, &r); long v; if (r != gen_0) { *py = x; return 0; } if (2 * lgefint(q) <= lgefint(z)+3) /* avoid squaring if pointless */ v = Z_pvalrem_DC(z, sqri(q), py) << 1; else { v = 0; *py = z; } z = dvmdii(*py, q, &r); if (r != gen_0) return v + 1; *py = z; return v + 2; } static const long VAL_DC_THRESHOLD = 16; long 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); av = avma; for(vx = 0;;) { ulong r; GEN q = diviu_rem(x, p, &r); if (r) break; vx++; x = q; if (vx == VAL_DC_THRESHOLD) { if (p == 1) pari_err_DOMAIN("Z_lval", "p", "=", gen_1, gen_1); vx += Z_pvalrem_DC(x, sqru(p), &x) << 1; q = diviu_rem(x, p, &r); if (!r) vx++; break; } } avma = av; return vx; } long Z_lvalrem(GEN x, ulong p, GEN *py) { long vx, sx; pari_sp av; 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); *py = signe(x) < 0? utoineg(u): utoipos(u); return vx; } av = avma; (void)new_chunk(lgefint(x)); sx = signe(x); for(vx = 0;;) { ulong r; GEN q = diviu_rem(x, p, &r); if (r) break; vx++; x = q; if (vx == VAL_DC_THRESHOLD) { if (p == 1) pari_err_DOMAIN("Z_lvalrem", "p", "=", gen_1, gen_1); vx += Z_pvalrem_DC(x, sqru(p), &x) << 1; q = diviu_rem(x, p, &r); if (!r) { vx++; x = q; } break; } } avma = av; *py = icopy(x); setsigne(*py, sx); return vx; } /* Is |q| <= p ? */ static int isless_iu(GEN q, ulong p) { long l = lgefint(q); return l==2 || (l == 3 && (ulong)q[2] <= p); } long u_lvalrem_stop(ulong *n, ulong p, int *stop) { ulong N = *n, q = N / p, r = N % p; /* gcc makes a single div */ long v = 0; if (!r) { do { v++; N = q; q = N / p; r = N % p; } while (!r); *n = N; } *stop = q <= p; return v; } /* Assume n > 0. Return v_p(n), set *n := n/p^v_p(n). Set 'stop' if now * n < p^2 [implies n prime if no prime < p divides n] */ long Z_lvalrem_stop(GEN *n, ulong p, int *stop) { pari_sp av; long v; ulong r; GEN N, q; if (lgefint(*n) == 3) { r = (*n)[2]; v = u_lvalrem_stop(&r, p, stop); if (v) *n = utoipos(r); return v; } av = avma; v = 0; q = diviu_rem(*n, p, &r); if (r) avma = av; else { do { v++; N = q; if (v == VAL_DC_THRESHOLD) { v += Z_pvalrem_DC(N,sqru(p),&N) << 1; q = diviu_rem(N, p, &r); if (!r) { v++; N = q; } break; } q = diviu_rem(N, p, &r); } while (!r); *n = N; } *stop = isless_iu(q,p); return v; } /* x is a non-zero integer, |p| > 1 */ long 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(x) == 3) { *py = icopy(x); return 0; } av = avma; vx = 0; (void)new_chunk(lgefint(x)); for(;;) { GEN r, q = dvmdii(x,p,&r); if (r != gen_0) { avma = av; *py = icopy(x); return vx; } vx++; x = q; } } long u_pvalrem(ulong x, GEN p, ulong *py) { if (lgefint(p) == 3) return u_lvalrem(x, (ulong)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]); return 0; } long Z_pval(GEN x, GEN p) { long vx; pari_sp av; if (lgefint(p) == 3) return Z_lval(x, (ulong)p[2]); if (lgefint(x) == 3) return 0; av = avma; vx = 0; for(;;) { GEN r, q = dvmdii(x,p,&r); if (r != gen_0) { avma = av; return vx; } vx++; x = q; } } /* return v_p(n!) = [n/p] + [n/p^2] + ... */ long factorial_lval(ulong n, ulong p) { ulong q = p, v = 0; do { v += n/q; q *= p; } while (n >= q); return (long)v; } /********** Same for "containers" ZX / ZV / ZC **********/ /* If the t_INT q divides the ZX/ZV x, return the quotient. Otherwise NULL. * Stack clean; assumes lg(x) > 1 */ static GEN gen_Z_divides(GEN x, GEN q, long imin) { long i, l; GEN y = cgetg_copy(x, &l); y[1] = x[1]; /* Needed for ZX; no-op if ZV, overwritten in first iteration */ for (i = imin; i < l; i++) { GEN r, xi = gel(x,i); if (!signe(xi)) { gel(y,i) = xi; continue; } gel(y,i) = dvmdii(xi, q, &r); if (r != gen_0) { avma = (pari_sp)(y+l); return NULL; } } return y; } /* If q divides the ZX/ZV x, return the quotient. Otherwise NULL. * Stack clean; assumes lg(x) > 1 */ static GEN gen_z_divides(GEN x, ulong q, long imin) { long i, l; GEN y = cgetg_copy(x, &l); y[1] = x[1]; /* Needed for ZX; no-op if ZV, overwritten in first iteration */ for (i = imin; i < l; i++) { ulong r; GEN xi = gel(x,i); if (!signe(xi)) { gel(y,i) = xi; continue; } gel(y,i) = diviu_rem(xi, q, &r); if (r) { avma = (pari_sp)(y+l); return NULL; } affectsign_safe(xi, &gel(y,i)); } return y; } /* return v_q(x) and set *py = x / q^v_q(x), using divide & conquer */ static long gen_pvalrem_DC(GEN x, GEN q, GEN *py, long imin) { pari_sp av = avma; long v, i, l, lz = LONG_MAX; GEN y = cgetg_copy(x, &l); y[1] = x[1]; for (i = imin; i < l; i++) { GEN r, xi = gel(x,i); if (!signe(xi)) { gel(y,i) = xi; continue; } gel(y,i) = dvmdii(xi, q, &r); if (r != gen_0) { avma = av; *py = x; return 0; } lz = minss(lz, lgefint(gel(y,i))); } if (2 * lgefint(q) <= lz+3) /* avoid squaring if pointless */ v = gen_pvalrem_DC(y, sqri(q), py, imin) << 1; else { v = 0; *py = y; } y = gen_Z_divides(*py, q, imin); if (!y) return v+1; *py = y; return v+2; } static long gen_2val(GEN x, long imin) { long i, lx = lg(x), v = LONG_MAX; for (i = imin; i < lx; i++) { GEN c = gel(x,i); long w; if (!signe(c)) continue; w = vali(c); if (w < v) { v = w; if (!v) break; } } return v; } static long gen_lval(GEN x, ulong p, long imin) { long i, lx, v; pari_sp av; GEN y; if (p == 2) return gen_2val(x, imin); av = avma; lx = lg(x); y = leafcopy(x); for(v = 0;; v++) for (i = imin; i < lx; i++) { ulong r; gel(y,i) = diviu_rem(gel(y,i), p, &r); if (r) { avma = av; return v; } } } long ZX_lval(GEN x, ulong p) { return gen_lval(x, p, 2); } long ZV_lval(GEN x, ulong p) { return gen_lval(x, p, 1); } static long gen_pval(GEN x, GEN p, long imin) { long i, lx, v; pari_sp av; GEN y; if (lgefint(p) == 3) return gen_lval(x, p[2], imin); av = avma; lx = lg(x); y = leafcopy(x); for(v = 0;; v++) { if (v == VAL_DC_THRESHOLD) { if (is_pm1(p)) pari_err_DOMAIN("gen_pval", "p", "=", p, p); v += gen_pvalrem_DC(y, p, &y, imin); avma = av; return v; } for (i = imin; i < lx; i++) { GEN r; gel(y,i) = dvmdii(gel(y,i), p, &r); if (r != gen_0) { avma = av; return v; } } } } long ZX_pval(GEN x, GEN p) { return gen_pval(x, p, 2); } long ZV_pval(GEN x, GEN p) { return gen_pval(x, p, 1); } /* v = 0 (mod p) */ int ZV_Z_dvd(GEN v, GEN p) { pari_sp av = avma; long i, l = lg(v); for (i=1; i=0)? stoi(s): gcopy(x); } GEN gmin(GEN x, GEN y) { return gcopy(gcmp(x,y)<0? x: y); } GEN gmings(GEN x, long s) { return (gcmpsg(s,x)>0)? gcopy(x): stoi(s); } long vecindexmax(GEN x) { long lx = lg(x), i0, i; GEN s; if (lx==1) pari_err_DOMAIN("vecindexmax", "empty argument", "=", x,x); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,i0=1); for (i=2; i 0) s = gel(x,i0=i); return i0; case t_VECSMALL: return vecsmall_indexmax(x); default: pari_err_TYPE("vecindexmax",x); } /* NOT REACHED */ return 0; } long vecindexmin(GEN x) { long lx = lg(x), i0, i; GEN s; if (lx==1) pari_err_DOMAIN("vecindexmin", "empty argument", "=", x,x); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,i0=1); for (i=2; i= vy) { avma = av; return gen_0; } z = gel(x,4); if (!signe(z) || vy > vx + precp(x)) pari_err_OP("",x, mkintmod(gen_1,Y)); if (vx) z = mulii(z, powiu(p,vx)); return gerepileuptoint(av, remii(z, Y)); } ulong padic_to_Fl(GEN x, ulong Y) { GEN p = gel(x,2); ulong u, z; long vy, vx = valp(x); vy = u_pvalrem(Y,p, &u); if (vx < 0 || u != 1) pari_err_OP("",x, mkintmodu(1,Y)); /* Y = p^vy */ if (vx >= vy) return 0; z = umodiu(gel(x,4), Y); if (!z || vy > vx + precp(x)) pari_err_OP("",x, mkintmodu(1,Y)); if (vx) { ulong pp = p[2]; z = Fl_mul(z, upowuu(pp,vx), Y); /* p^vx < p^vy = Y */ } return z; } static void croak(const char *s) { char *t; t = stack_sprintf("gaffect [overwriting universal object: %s]",s); pari_err_BUG(t); } void gaffect(GEN x, GEN y) { long vx, i, lx, ly, tx = typ(x), ty = typ(y); pari_sp av; GEN p1, num, den; if (tx == ty) switch(tx) { case t_INT: if (!is_universal_constant(y)) { affii(x,y); return; } /* y = gen_0, gnil, gen_1 or gen_2 */ if (y==gen_0) croak("gen_0"); if (y==gen_1) croak("gen_1"); if (y==gen_m1) croak("gen_m1"); if (y==gen_m2) croak("gen_m2"); if (y==gen_2) croak("gen_2"); croak("gnil)"); case t_REAL: affrr(x,y); return; case t_INTMOD: if (!dvdii(gel(x,1),gel(y,1))) pari_err_OP("",x,y); modiiz(gel(x,2),gel(y,1),gel(y,2)); return; case t_FRAC: affii(gel(x,1),gel(y,1)); affii(gel(x,2),gel(y,2)); return; case t_COMPLEX: gaffect(gel(x,1),gel(y,1)); gaffect(gel(x,2),gel(y,2)); return; case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("",x,y); modiiz(gel(x,4),gel(y,3),gel(y,4)); setvalp(y,valp(x)); return; case t_QUAD: if (! ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("",x,y); affii(gel(x,2),gel(y,2)); affii(gel(x,3),gel(y,3)); return; case t_VEC: case t_COL: case t_MAT: lx = lg(x); if (lx != lg(y)) pari_err_DIM("gaffect"); for (i=1; i REAL, COMPLEX OR P-ADIC */ /* */ /*******************************************************************/ GEN quadtofp(GEN x, long prec) { GEN z, Q, u = gel(x,2), v = gel(x,3); pari_sp av; if (prec < LOWDEFAULTPREC) prec = LOWDEFAULTPREC; if (isintzero(v)) return cxcompotor(u, prec); av = avma; Q = gel(x,1); z = itor(quad_disc(x), prec); if (signe(gel(Q,2)) < 0) /* Q[2] = -D/4 or (1-D)/4 */ { z = subri(sqrtr(z), gel(Q,3)); shiftr_inplace(z, -1); } else { z = sqrtr_abs(z); shiftr_inplace(z, -1); z = mkcomplex(gmul2n(negi(gel(Q,3)),-1), z); }/* z = (-b + sqrt(D)) / 2 */ return gerepileupto(av, gadd(u, gmul(v,z))); } static GEN qtop(GEN x, GEN p, long d) { GEN z, D, P, b, u = gel(x,2), v = gel(x,3); pari_sp av; if (gequal0(v)) return cvtop(u, p, d); P = gel(x,1); b = gel(P,3); av = avma; D = quad_disc(x); if (equaliu(p,2)) d += 2; z = Qp_sqrt(cvtop(D,p,d)); if (!z) pari_err_SQRTN("Qp_sqrt",D); z = gmul2n(gsub(z, b), -1); z = gadd(u, gmul(v, z)); if (typ(z) != t_PADIC) /* t_INTMOD for t_QUAD of t_INTMODs... */ z = cvtop(z, p, d); return gerepileupto(av, z); } static GEN ctop(GEN x, GEN p, long d) { pari_sp av = avma; GEN z, u = gel(x,1), v = gel(x,2); if (isrationalzero(v)) return cvtop(u, p, d); z = Qp_sqrt(cvtop(gen_m1, p, d - gvaluation(v, p))); /* = I */ z = gadd(u, gmul(v, z)); if (typ(z) != t_PADIC) /* t_INTMOD for t_COMPLEX of t_INTMODs... */ z = cvtop(z, p, d); return gerepileupto(av, z); } /* cvtop2(stoi(s), y) */ GEN cvstop2(long s, GEN y) { GEN z, p = gel(y,2); long v, d = signe(gel(y,4))? precp(y): 0; if (!s) return zeropadic(p, d); v = z_pvalrem(s, p, &s); if (d <= 0) return zeropadic(p, v); z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = p; gel(z,3) = gel(y,3); gel(z,4) = modsi(s, gel(y,3)); return z; } /* cvtop(x, gel(y,2), precp(y)), internal, not memory-clean */ GEN cvtop2(GEN x, GEN y) { GEN z, p = gel(y,2); long v, d = signe(gel(y,4))? precp(y): 0; switch(typ(x)) { case t_INT: if (!signe(x)) return zeropadic(p, d); v = Z_pvalrem(x, p, &x); if (d <= 0) return zeropadic(p, v); z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = p; gel(z,3) = gel(y,3); gel(z,4) = modii(x, gel(y,3)); return z; case t_INTMOD: v = Z_pval(gel(x,1),p); if (v > d) v = d; return cvtop(gel(x,2), p, v); case t_FRAC: { GEN num = gel(x,1), den = gel(x,2); if (!signe(num)) return zeropadic(p, d); v = Z_pvalrem(num, p, &num); if (!v) v = -Z_pvalrem(den, p, &den); /* assume (num,den) = 1 */ if (d <= 0) return zeropadic(p, v); z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = p; gel(z,3) = gel(y,3); if (!is_pm1(den)) num = mulii(num, Fp_inv(den, gel(y,3))); gel(z,4) = modii(num, gel(y,3)); return z; } case t_COMPLEX: return ctop(x, p, d); case t_QUAD: return qtop(x, p, d); } pari_err_TYPE("cvtop2",x); return NULL; /* not reached */ } /* assume is_const_t(tx) */ GEN cvtop(GEN x, GEN p, long d) { GEN z; long v; if (typ(p) != t_INT) pari_err_TYPE("cvtop",p); switch(typ(x)) { case t_INT: if (!signe(x)) return zeropadic(p, d); v = Z_pvalrem(x, p, &x); if (d <= 0) return zeropadic(p, v); z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = icopy(p); gel(z,3) = powiu(p, d); gel(z,4) = modii(x, gel(z,3)); return z; /* not memory-clean */ case t_INTMOD: v = Z_pval(gel(x,1),p); if (v > d) v = d; return cvtop(gel(x,2), p, v); case t_FRAC: { GEN num = gel(x,1), den = gel(x,2); if (!signe(num)) return zeropadic(p, d); v = Z_pvalrem(num, p, &num); if (!v) v = -Z_pvalrem(den, p, &den); /* assume (num,den) = 1 */ if (d <= 0) return zeropadic(p, v); z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = icopy(p); gel(z,3) = powiu(p, d); if (!is_pm1(den)) num = mulii(num, Fp_inv(den, gel(z,3))); gel(z,4) = modii(num, gel(z,3)); return z; /* not memory-clean */ } case t_COMPLEX: return ctop(x, p, d); case t_PADIC: return gprec(x,d); case t_QUAD: return qtop(x, p, d); } pari_err_TYPE("cvtop",x); return NULL; /* not reached */ } GEN gcvtop(GEN x, GEN p, long r) { long i, lx; GEN y; switch(typ(x)) { case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; if) f=e; } return f; case t_VEC: case t_COL: case t_MAT: lx = lg(x); f = -(long)HIGHEXPOBIT; for (i=1; if) f=e; } return f; } pari_err_TYPE("gexpo",x); return 0; /* not reached */ } long sizedigit(GEN x) { return gequal0(x)? 0: (long) ((gexpo(x)+1) * LOG10_2) + 1; } /* normalize series. avma is not updated */ GEN normalize(GEN x) { long i, lx = lg(x), vx=varn(x), vp=valp(x); GEN y, z; if (typ(x) != t_SER) pari_err_TYPE("normalize",x); if (lx==2) { setsigne(x,0); return x; } for (i=2; i1; i--) if (! gequal0(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i!=1); return x; } GEN normalizepol_lg(GEN x, long lx) { long i, LX = 0; GEN KEEP = NULL; for (i = lx-1; i>1; i--) { GEN z = gel(x,i); if (! gequal0(z) ) { if (!LX) LX = i+1; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX)); x[0] = evaltyp(t_POL) | evallg(LX); setsigne(x,1); return x; } else if (!isexactzero(z)) { if (!LX) LX = i+1; /* to be kept as leading coeff */ } else if (!isrationalzero(z)) KEEP = z; /* to be kept iff all other coeffs are exact 0s */ } if (!LX) { if (KEEP) { /* e.g. Pol(Mod(0,2)) */ gel(x,2) = KEEP; LX = 3; } else LX = 2; /* Pol(0) */ } stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX)); x[0] = evaltyp(t_POL) | evallg(LX); setsigne(x,0); return x; } /* normalize polynomial x in place */ GEN normalizepol(GEN x) { return normalizepol_lg(x, lg(x)); } int gsigne(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: return signe(x); case t_FRAC: return signe(gel(x,1)); } pari_err_TYPE("gsigne",x); return 0; /* not reached */ } /*******************************************************************/ /* */ /* LISTS */ /* */ /*******************************************************************/ /* make sure L can hold l elements, at least doubling the previous max number * of components. */ static void ensure_nb(GEN L, long l) { long nmax = list_nmax(L); GEN v; if (l <= nmax) return; if (nmax) { nmax <<= 1; if (l > nmax) nmax = l; v = (GEN)pari_realloc(list_data(L), (nmax+1) * sizeof(long)); } else /* unallocated */ { nmax = 32; if (list_data(L)) pari_err(e_MISC, "store list in variable before appending elements"); v = (GEN)pari_malloc((nmax+1) * sizeof(long)); v[0] = evaltyp(t_VEC) | _evallg(1); } list_data(L) = v; list_nmax(L) = nmax; } void listkill(GEN L) { if (typ(L) != t_LIST) pari_err_TYPE("listkill",L); if (list_nmax(L)) { GEN v = list_data(L); long i, l = lg(v); for (i=1; i= l) { ensure_nb(L, l); z = list_data(L); /* it may change ! */ index = l; l++; } else gunclone_deep( gel(z, index) ); gel(z,index) = gclone(x); z[0] = evaltyp(t_VEC) | evallg(l); /*must be after gel(z,index) is set*/ return gel(z,index); } GEN listinsert(GEN L, GEN x, long index) { long l, i; GEN z; if (typ(L) != t_LIST) pari_err_TYPE("listinsert",L); z = list_data(L); l = z? lg(z): 1; if (index <= 0) pari_err_COMPONENT("listinsert", "<=", gen_0, stoi(index)); if (index > l) pari_err_COMPONENT("listinsert", ">", stoi(l), stoi(index)); ensure_nb(L, l); z = list_data(L); for (i=l; i > index; i--) gel(z,i) = gel(z,i-1); z[0] = evaltyp(t_VEC) | evallg(l+1); return gel(z,index) = gclone(x); } void listpop(GEN L, long index) { long l, i; GEN z; if (typ(L) != t_LIST) pari_err_TYPE("listinsert",L); if (index < 0) pari_err_COMPONENT("listpop", "<", gen_0, stoi(index)); z = list_data(L); if (!z || (l = lg(z)-1) == 0) return; if (!index || index > l) index = l; gunclone_deep( gel(z, index) ); z[0] = evaltyp(t_VEC) | evallg(l); for (i=index; i < l; i++) z[i] = z[i+1]; } /* return a list with single element x, allocated on stack */ GEN mklistcopy(GEN x) { GEN y = listcreate(); list_data(y) = mkveccopy(x); return y; } /* return a copy fully allocated on stack. gclone from changevalue is * supposed to malloc() it */ GEN gtolist(GEN x) { GEN y; if (!x) return listcreate(); switch(typ(x)) { case t_VEC: case t_COL: y = listcreate(); if (lg(x) == 1) return y; list_data(y) = gcopy(x); settyp(list_data(y), t_VEC); return y; case t_LIST: y = listcreate(); list_data(y) = list_data(x)? gcopy(list_data(x)): NULL; return y; default: return mklistcopy(x); } } void listsort(GEN L, long flag) { long i, l; pari_sp av = avma; GEN perm, v, vnew; if (typ(L) != t_LIST) pari_err_TYPE("listsort",L); v = list_data(L); l = v? lg(v): 1; if (l < 3) return; if (flag) { long lnew; perm = gen_indexsort_uniq(L, (void*)&cmp_universal, cmp_nodata); lnew = lg(perm); /* may have changed since 'uniq' */ vnew = cgetg(lnew,t_VEC); for (i=1; i 1) err_printf("conjugate %ld: %Ps\n", i, y[nbauto]); } } } if (nbauto < nbmax) pari_warn(warner, "conjugates list may be incomplete in nfgaloisconj"); setlg(y, 1 + nbauto); return gerepileupto(av, gen_sort(y, (void*)&gcmp, &gen_cmp_RgX)); } static GEN galoisconj2(GEN nf, long prec) { long i, n, nbauto, nbmax; pari_sp av = avma; GEN T = get_nfpol(nf,&nf), y, w, polr, p1, p2; if (!nf) return galoisconj2pol(T, prec); n = degpol(T); if (n <= 0) return cgetg(1, t_VEC); nbmax = numberofconjugates(T, 2); y = cgetg(nbmax + 1, t_COL); gel(y,1) = pol_x(varn(T)); /* accuracy in decimal digits */ prec = (long)prec2nbits_mul(nf_get_prec(nf), LOG10_2 * 0.75); nbauto = 1; polr = nf_get_allroots(nf); p2 = nf_get_M(nf); w = cgetg(n + 2, t_VEC); for (i = 1; i <= n; i++) gel(w,i) = gcoeff(p2, 1, i); for (i = 2; i <= n && nbauto < nbmax; i++) { gel(w,n+1) = gel(polr,i); p1 = lindep2(w, prec); if (signe(gel(p1,n+1))) { p1[0] = evallg(n+1) | evaltyp(t_COL); p2 = gdiv(coltoliftalg(nf, p1), negi(gel(p1, n+1))); if (gdvd(poleval(T, p2), T)) { gel(y,++nbauto) = p2; if (DEBUGLEVEL > 1) err_printf("conjugate %ld: %Ps\n", i, y[nbauto]); } } } if (nbauto < nbmax) pari_warn(warner, "conjugates list may be incomplete in nfgaloisconj"); setlg(y, 1 + nbauto); return gerepileupto(av, gen_sort(y, (void*)&gcmp, &gen_cmp_RgX)); } /*************************************************************************/ /** **/ /** GALOISCONJ4 **/ /** **/ /*************************************************************************/ /*DEBUGLEVEL: 1: timing 2: outline 4: complete outline 6: detail 7: memory 9: complete detail */ struct galois_borne { GEN l; long valsol; long valabs; GEN bornesol; GEN ladicsol; GEN ladicabs; }; struct galois_lift { GEN T; GEN den; GEN p; GEN L; GEN Lden; long e; GEN Q; GEN TQ; struct galois_borne *gb; }; struct galois_testlift { long n; long f; long g; GEN bezoutcoeff; GEN pauto; GEN C; GEN Cd; }; struct galois_test { /* data for permutation test */ GEN order; /* order of tests pour galois_test_perm */ GEN borne, lborne; /* coefficient bounds */ GEN ladic; GEN PV; /* NULL or vector of test matrices (Vmatrix) */ GEN TM; /* transpose of M */ GEN L; /* p-adic roots, known mod ladic */ GEN M; /* vandermonde inverse */ }; /* result of the study of Frobenius degrees */ enum ga_code {ga_all_normal=1,ga_ext_2=2,ga_non_wss=4}; struct galois_analysis { long p; /* prime to be lifted */ long deg; /* degree of the lift */ long ord; long l; /* l: prime number such that T is totally split mod l */ long p4; enum ga_code group; }; struct galois_frobenius { long p; long fp; long deg; GEN Tmod; GEN psi; }; GEN vandermondeinverseprep(GEN L) { long i, j, n = lg(L); GEN V; V = cgetg(n, t_VEC); for (i = 1; i < n; i++) { pari_sp ltop = avma; GEN W = cgetg(n-1,t_VEC); long k = 1; for (j = 1; j < n; j++) if (i != j) gel(W, k++) = gsub(gel(L,i),gel(L,j)); gel(V,i) = gerepileupto(ltop,divide_conquer_prod(W,&gmul)); } return V; } /* Compute the inverse of the van der Monde matrix of T multiplied by den */ GEN vandermondeinverse(GEN L, GEN T, GEN den, GEN prep) { pari_sp ltop = avma; long i, n = lg(L)-1; GEN M, P; if (!prep) prep = vandermondeinverseprep(L); M = cgetg(n+1, t_MAT); 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); } return den? gerepileupto(ltop, gmul(den, M)): gerepilecopy(ltop, M); } /* #r = r1 + r2 */ GEN embed_roots(GEN ro, long r1) { long r2 = lg(ro)-1-r1; GEN L; if (!r2) L = ro; else { long i,j, N = r1+2*r2; L = cgetg(N+1, t_VEC); for (i = 1; i <= r1; i++) gel(L,i) = gel(ro,i); for (j = i; j <= N; i++) { GEN z = gel(ro,i); gel(L,j++) = z; gel(L,j++) = mkcomplex(gel(z,1), gneg(gel(z,2))); } } return L; } GEN embed_disc(GEN z, long r1, long prec) { pari_sp av = avma; GEN t = real_1(prec); long i, j, n = lg(z)-1, r2 = n-r1; for (i = 1; i < r1; i++) { GEN zi = gel(z,i); for (j = i+1; j <= r1; j++) t = gmul(t, gsub(zi, gel(z,j))); } for (j = r1+1; j <= n; j++) { GEN zj = gel(z,j), a = gel(zj,1), b = gel(zj,2), b2 = gsqr(b); for (i = 1; i <= r1; i++) { GEN zi = gel(z,i); t = gmul(t, gadd(gsqr(gsub(zi, a)), b2)); } t = gmul(t, b); } if (r2) t = gmul2n(t, r2); if (r2 > 1) { GEN T = real_1(prec); for (i = r1+1; i < n; i++) { GEN zi = gel(z,i), a = gel(zi,1), b = gel(zi,2); for (j = i+1; j <= n; j++) { GEN zj = gel(z,j), c = gel(zj,1), d = gel(zj,2); GEN f = gsqr(gsub(a,c)), g = gsqr(gsub(b,d)), h = gsqr(gadd(b,d)); T = gmul(T, gmul(gadd(f,g), gadd(f,h))); } } t = gmul(t, T); } t = gsqr(t); if (odd(r2)) t = gneg(t); return gerepileupto(av, t); } /* Compute bound for the coefficients of automorphisms. * T a ZX, dn a t_INT denominator or NULL */ GEN initgaloisborne(GEN T, GEN dn, long prec, GEN *ptL, GEN *ptprep, GEN *ptdis) { GEN L, prep, den, nf, r; pari_timer ti; if (DEBUGLEVEL>=4) timer_start(&ti); T = get_nfpol(T, &nf); r = nf ? nf_get_roots(nf) : NULL; if (nf && precision(gel(r, 1)) >= prec) L = embed_roots(r, nf_get_r1(nf)); else L = QX_complex_roots(T, prec); if (DEBUGLEVEL>=4) timer_printf(&ti,"roots"); prep = vandermondeinverseprep(L); if (!dn) { GEN dis, res = divide_conquer_prod(gabs(prep,prec), mpmul); /*Add +2 to cater for accuracy error in res */ dis = ZX_disc_all(T, 2+expi(ceil_safe(res))); den = indexpartial(T,dis); if (ptdis) *ptdis = dis; } else { if (typ(dn) != t_INT || signe(dn) <= 0) pari_err_TYPE("initgaloisborne [incorrect denominator]", dn); den = dn; } if (ptprep) *ptprep = prep; *ptL = L; return den; } /* ||| M ||| with respect to || x ||_oo. Assume M square t_MAT */ GEN matrixnorm(GEN M, long prec) { long i,j, n = lg(M); GEN B = real_0(prec); for (i = 1; i < n; i++) { GEN z = gabs(gcoeff(M,i,1), prec); for (j = 2; j < n; j++) z = gadd(z, gabs(gcoeff(M,i,j), prec)); if (gcmp(z, B) > 0) B = z; } return B; } static GEN galoisborne(GEN T, GEN dn, struct galois_borne *gb, long d) { pari_sp ltop = avma, av2; GEN borne, borneroots, borneabs; long prec; GEN L, M, prep, den; pari_timer ti; prec = nbits2prec(bit_accuracy(ZX_max_lg(T))); den = initgaloisborne(T,dn,prec, &L,&prep,NULL); if (!dn) den = gclone(den); if (DEBUGLEVEL>=4) timer_start(&ti); M = vandermondeinverse(L, RgX_gtofp(T, prec), den, prep); if (DEBUGLEVEL>=4) timer_printf(&ti,"vandermondeinverse"); borne = matrixnorm(M, prec); borneroots = gsupnorm(L, prec); /*t_REAL*/ borneabs = ceil_safe(gmul(borne,gmulsg(d, powru(borneroots, d)))); borneroots = ceil_safe(gmul(borne, borneroots)); av2 = avma; /*We use d-1 test, so we must overlift to 2^BITS_IN_LONG*/ gb->valsol = logint(shifti(borneroots,2+BITS_IN_LONG), gb->l,NULL); 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); avma = av2; gb->bornesol = gerepileuptoint(ltop, shifti(borneroots,1)); if (DEBUGLEVEL >= 9) err_printf("GaloisConj: Bound %Ps\n",borneroots); gb->ladicsol = powiu(gb->l, gb->valsol); gb->ladicabs = powiu(gb->l, gb->valabs); if (!dn) { dn = icopy(den); gunclone(den); } return dn; } static GEN makeLden(GEN L,GEN den, struct galois_borne *gb) { return FpC_Fp_mul(L, den, gb->ladicsol); } /* Initialize the galois_lift structure */ static void initlift(GEN T, GEN den, GEN p, GEN L, GEN Lden, struct galois_borne *gb, struct galois_lift *gl) { pari_sp av = avma; long e; gl->gb = gb; gl->T = T; gl->den = is_pm1(den)? gen_1: den; gl->p = p; gl->L = L; gl->Lden = Lden; e = logint(shifti(gb->bornesol, 2+BITS_IN_LONG),p,NULL); avma = av; if (e < 2) e = 2; gl->e = e; gl->Q = powiu(p, e); gl->TQ = FpX_red(T,gl->Q); } /* Check whether f is (with high probability) a solution and compute its * permutation */ static int poltopermtest(GEN f, struct galois_lift *gl, GEN pf) { pari_sp av; GEN fx, fp, B = gl->gb->bornesol; long i, j, ll; for (i = 2; i < lg(f); i++) if (absi_cmp(gel(f,i),B) > 0) { if (DEBUGLEVEL>=4) err_printf("GaloisConj: Solution too large.\n"); if (DEBUGLEVEL>=8) err_printf("f=%Ps\n borne=%Ps\n",f,B); return 0; } ll = lg(gl->L); fp = const_vecsmall(ll-1, 1); /* left on stack */ av = avma; for (i = 1; i < ll; i++, avma = av) { fx = FpX_eval(f, gel(gl->L,i), gl->gb->ladicsol); for (j = 1; j < ll; j++) if (fp[j] && equalii(fx, gel(gl->Lden,j))) { pf[i]=j; fp[j]=0; break; } if (j == ll) return 0; } return 1; } static long monoratlift(GEN S, GEN q, GEN qm1old,struct galois_lift *gl, GEN frob) { GEN tlift = FpX_ratlift(S,q,qm1old,qm1old,gl->den); if (tlift) { pari_sp ltop = avma; if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: trying early solution %Ps\n",tlift); if (gl->den != gen_1) { 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(DEBUGLEVEL>=4) err_printf("MonomorphismLift: true early solution.\n"); avma = ltop; return 1; } avma = ltop; if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: false early solution.\n"); } return 0; } 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()"); return S; } /* Let T be a polynomial in Z[X] , p a prime number, S in Fp[X]/(T) so * that T(S)=0 [p,T]. Lift S in S_0 so that T(S_0)=0 [T,p^e] * Unclean stack */ static GEN 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); return gerepileupto(av, automorphismlift(S, gl, frob)); } static void inittestlift(GEN plift, GEN Tmod, struct galois_lift *gl, struct galois_testlift *gt) { pari_timer ti; gt->n = lg(gl->L) - 1; gt->g = lg(Tmod) - 1; gt->f = gt->n / gt->g; gt->bezoutcoeff = bezout_lift_fact(gl->T, Tmod, gl->p, gl->e); if (DEBUGLEVEL >= 2) timer_start(&ti); gt->pauto = FpXQ_autpowers(plift, gt->f-1, gl->TQ, gl->Q); if (DEBUGLEVEL >= 2) timer_printf(&ti, "Frobenius power"); } /* Explanation of the intheadlong technique: * Let C be a bound, B = BITS_IN_LONG, M > C*2^B a modulus and 0 <= a_i < M for * i=1,...,n where n < 2^B. We want to test if there exist k,l, |k| < C < M/2^B, * such that sum a_i = k + l*M * We write a_i*2^B/M = b_i+c_i with b_i integer and 0<=c_i<1, so that * sum b_i - l*2^B = k*2^B/M - sum c_i * Since -1 < k*2^B/M < 1 and 0<=c_i<1, it follows that * -n-1 < sum b_i - l*2^B < 1 i.e. -n <= sum b_i -l*2^B <= 0 * So we compute z = - sum b_i [mod 2^B] and check if 0 <= z <= n. */ /* Assume 0 <= x < mod. */ long intheadlong(GEN x, GEN mod) { pari_sp av = avma; long res = (long) itou(divii(shifti(x,BITS_IN_LONG),mod)); avma = av; return res; } static GEN vecheadlong(GEN W, GEN mod) { long i, l = lg(W); GEN V = cgetg(l, t_VECSMALL); for(i=1; in+2)? intheadlong(gel(P,n+2),mod): 0; } #define headlongisint(Z,N) (-(ulong)(Z)<=(ulong)(N)) static long frobeniusliftall(GEN sg, long el, GEN *psi, struct galois_lift *gl, struct galois_testlift *gt, GEN frob) { pari_sp av, ltop2, ltop = avma; long i,j,k, c = lg(sg)-1, n = lg(gl->L)-1, m = gt->g, d = m / c; GEN pf, u, v, C, Cd, SG, cache; long N1, N2, R1, Ni, Z, ord = gt->f, c_idx = gt->g-1; long hop = 0; GEN NN, NQ; pari_timer ti; *psi = pf = cgetg(m, t_VECSMALL); 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); N1=10000000; NQ=divis_rem(NN,N1,&R1); if (cmpiu(NQ,1000000000)>0) { pari_warn(warner,"Combinatorics too hard : would need %Ps tests!\n" "I will skip it, but it may induce an infinite loop",NN); avma = ltop; *psi = NULL; return 0; } N2=itos(NQ); if(!N2) N1=R1; if (DEBUGLEVEL>=4) timer_start(&ti); avma = ltop2; C = gt->C; Cd= gt->Cd; v = FpXQ_mul(gel(gt->pauto, 1+el%ord), gel(gt->bezoutcoeff, m),gl->TQ,gl->Q); if (gl->den != gen_1) v = FpX_Fp_mul(v, gl->den, gl->Q); SG = cgetg(lg(sg),t_VECSMALL); for(i=1; iQ); Z = polheadlong(v,2,gl->Q); for (i = 1; i < m; i++) pf[i] = 1 + i/d; av = avma; for (Ni = 0, i = 0; ;i++) { for (j = c_idx ; j > 0; j--) { long h = SG[pf[j]]; if (!mael(C,h,j)) { pari_sp av3 = avma; GEN r = FpXQ_mul(gel(gt->pauto,h), gel(gt->bezoutcoeff,j),gl->TQ,gl->Q); if (gl->den != gen_1) r = FpX_Fp_mul(r, gl->den, gl->Q); gmael(C,h,j) = gclone(r); mael(Cd,h,j) = polheadlong(r,1,gl->Q); avma = av3; } uel(cache,j) = uel(cache,j+1)+umael(Cd,h,j); } if (headlongisint(uel(cache,1),n)) { long ZZ = Z; for (j = 1; j < m; j++) ZZ += polheadlong(gmael(C,SG[pf[j]],j),2,gl->Q); if (headlongisint(ZZ,n)) { u = v; for (j = 1; j < m; j++) u = ZX_add(u, gmael(C,SG[pf[j]],j)); u = FpX_center(FpX_red(u, gl->Q), gl->Q, shifti(gl->Q,-1)); if (poltopermtest(u, gl, frob)) { if (DEBUGLEVEL >= 4) { timer_printf(&ti, ""); err_printf("GaloisConj: %d hops on %Ps tests\n",hop,addis(mulss(Ni,N1),i)); } avma = ltop2; return 1; } if (DEBUGLEVEL >= 4) err_printf("M"); } else hop++; } if (DEBUGLEVEL >= 4 && i % maxss(N1/20, 1) == 0) timer_printf(&ti, "GaloisConj:Testing %Ps", addis(mulss(Ni,N1),i)); avma = av; if (i == N1-1) { if (Ni==N2-1) N1 = R1; if (Ni==N2) break; Ni++; i = 0; if (DEBUGLEVEL>=4) timer_start(&ti); } for (j = 2; j < m && pf[j-1] >= pf[j]; j++) /*empty*/; /* to kill clang Warning */ for (k = 1; k < j-k && pf[k] != pf[j-k]; k++) { lswap(pf[k], pf[j-k]); } for (k = j - 1; pf[k] >= pf[j]; k--) /*empty*/; lswap(pf[j], pf[k]); c_idx = j; } if (DEBUGLEVEL>=4) err_printf("GaloisConj: not found, %d hops \n",hop); *psi = NULL; avma = ltop; return 0; } /* Compute the test matrix for the i-th line of V. Clone. */ static GEN Vmatrix(long i, struct galois_test *td) { pari_sp av = avma; GEN m = gclone( matheadlong(FpC_FpV_mul(td->L, row(td->M,i), td->ladic), td->ladic)); avma = av; return m; } /* Initialize galois_test */ static void 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"); td->order = p; for (i = 1; i <= n-2; i++) p[i] = i+2; p[n-1] = 1; p[n] = 2; td->borne = borne; td->lborne = subii(ladic, borne); td->ladic = ladic; td->L = L; td->M = M; td->TM = shallowtrans(M); td->PV = zero_zv(n); gel(td->PV, 2) = Vmatrix(2, td); } /* Free clones stored inside galois_test */ static void freetest(struct galois_test *td) { long i; for (i = 1; i < lg(td->PV); i++) if (td->PV[i]) { gunclone(gel(td->PV,i)); td->PV[i] = 0; } } /* Check if the integer P seen as a p-adic number is close to an integer less * than td->borne in absolute value */ static long padicisint(GEN P, struct galois_test *td) { pari_sp ltop = avma; GEN U = modii(P, td->ladic); long r = cmpii(U, td->borne) <= 0 || cmpii(U, td->lborne) >= 0; avma = ltop; return r; } /* Check if the permutation pf is valid according to td. * If not, update td to make subsequent test faster (hopefully) */ static long galois_test_perm(struct galois_test *td, GEN pf) { pari_sp av = avma; long i, j, n = lg(td->L)-1; GEN V, P = NULL; for (i = 1; i < n; i++) { long ord = td->order[i]; GEN PW = gel(td->PV, ord); if (PW) { ulong Z = umael(PW,1,pf[1]); for (j = 2; j <= n; j++) Z += umael(PW,j,pf[j]); if (!headlongisint(Z,n)) break; } else { if (!P) P = vecpermute(td->L, pf); V = FpV_dotproduct(gel(td->TM,ord), P, td->ladic); if (!padicisint(V, td)) { gel(td->PV, ord) = Vmatrix(ord, td); if (DEBUGLEVEL >= 4) err_printf("M"); break; } } } if (i == n) { avma = av; return 1; } if (DEBUGLEVEL >= 4) err_printf("%d.", i); if (i > 1) { long z = td->order[i]; for (j = i; j > 1; j--) td->order[j] = td->order[j-1]; td->order[1] = z; if (DEBUGLEVEL >= 8) err_printf("%Ps", td->order); } avma = av; return 0; } /*Compute a*b/c when a*b will overflow*/ static long muldiv(long a,long b,long c) { return (long)((double)a*(double)b/c); } /* F = cycle decomposition of sigma, * B = cycle decomposition of cl(tau). * Check all permutations pf who can possibly correspond to tau, such that * tau*sigma*tau^-1 = sigma^s and tau^d = sigma^t, where d = ord cl(tau) * x: vector of choices, * G: vector allowing linear access to elts of F. * Choices multiple of e are not changed. */ static GEN testpermutation(GEN F, GEN B, GEN x, long s, long e, long cut, struct galois_test *td) { pari_sp av, avm = avma; long a, b, c, d, n, p1, p2, p3, p4, p5, p6, l1, l2, N1, N2, R1; long i, j, cx, hop = 0, start = 0; GEN pf, ar, G, W, NN, NQ; pari_timer ti; if (DEBUGLEVEL >= 1) timer_start(&ti); a = lg(F)-1; b = lg(gel(F,1))-1; c = lg(B)-1; d = lg(gel(B,1))-1; n = a*b; s = (b+s) % b; pf = cgetg(n+1, t_VECSMALL); av = avma; ar = cgetg(a+2, t_VECSMALL); ar[a+1]=0; G = cgetg(a+1, t_VECSMALL); W = gel(td->PV, td->order[n]); for (cx=1, i=1, j=1; cx <= a; cx++, i++) { gel(G,cx) = gel(F, coeff(B,i,j)); 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); 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); return identity_perm(n); } N2 = itos(NQ); for (l2 = 0; l2 <= N2; l2++) { long nbiter = (l2= 2 && N2) err_printf("%d%% ", muldiv(l2,100,N2)); for (l1 = 0; l1 < nbiter; l1++) { if (start) { for (i=1, j=e; i < a;) { if ((++(x[i])) != b) break; x[i++] = 0; if (i == j) { i++; j += e; } } } else { start=1; i = a-1; } /* intheadlong test: overflow in + is OK, we compute mod 2^BIL */ for (p1 = i+1, p5 = p1%d - 1 ; p1 >= 1; p1--, p5--) /* p5 = (p1%d) - 1 */ { ulong V = 0; if (p5 == - 1) { p5 = d - 1; p6 = p1 + 1 - d; } else p6 = p1 + 1; p4 = p5 ? x[p1-1] : 0; V = 0; for (p2 = 1+p4, p3 = 1 + x[p1]; p2 <= b; p2++) { V += umael(W,mael(G,p6,p3),mael(G,p1,p2)); p3 += s; if (p3 > b) p3 -= b; } p3 = 1 + x[p1] - s; if (p3 <= 0) p3 += b; for (p2 = p4; p2 >= 1; p2--) { V += umael(W,mael(G,p6,p3),mael(G,p1,p2)); p3 -= s; if (p3 <= 0) p3 += b; } ar[p1] = ar[p1+1] + V; } if (!headlongisint(uel(ar,1),n)) continue; /* intheadlong succeeds. Full computation */ for (p1=1, p5=d; p1 <= a; p1++, p5++) { if (p5 == d) { p5 = 0; p4 = 0; } else p4 = x[p1-1]; if (p5 == d-1) p6 = p1+1-d; else p6 = p1+1; for (p2 = 1+p4, p3 = 1 + x[p1]; p2 <= b; p2++) { pf[mael(G,p1,p2)] = mael(G,p6,p3); p3 += s; if (p3 > b) p3 -= b; } p3 = 1 + x[p1] - s; if (p3 <= 0) p3 += b; for (p2 = p4; p2 >= 1; p2--) { pf[mael(G,p1,p2)] = mael(G,p6,p3); p3 -= s; if (p3 <= 0) p3 += b; } } if (galois_test_perm(td, pf)) { if (DEBUGLEVEL >= 1) { 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); } avma = av; return pf; } hop++; } } if (DEBUGLEVEL >= 1) { timer_printf(&ti, "testpermutation(%Ps)", NN); if (DEBUGLEVEL >= 2 && hop) err_printf("GaloisConj:%d hop over %Ps iterations\n", hop, NN); } avma = avm; return NULL; } /* List of subgroups of (Z/mZ)^* whose order divide o, and return the list * of their elements, sorted by increasing order */ GEN listznstarelts(long m, long o) { pari_sp av = avma; GEN L, zn, zns, res; long i, phi, ind, l; if (m == 2) { res = cgetg(2, t_VEC); gel(res,1) = mkvecsmall(1); return res; } zn = znstar(stoi(m)); phi = itos(gel(zn,1)); o = ugcd(o, phi); /* do we impose this on input ? */ zns = znstar_small(zn); L = cgetg(o+1, t_VEC); for (i=1,ind = phi; ind; ind -= phi/o, i++) /* by *decreasing* exact index */ gel(L,i) = subgrouplist(gel(zn,2), mkvec(utoipos(ind))); L = shallowconcat1(L); l = lg(L); for (i = 1; i < l; i++) gel(L,i) = znstar_hnf_elts(zns, gel(L,i)); return gerepilecopy(av, L); } /* A sympol is a symmetric polynomial * * Currently sympol are couple of t_VECSMALL [v,w] * v[1]...v[k], w[1]...w[k] represent the polynomial sum(i=1,k,v[i]*s_w[i]) * where s_i(X_1,...,X_n) = sum(j=1,n,X_j^i) */ /*Return s_e*/ static GEN sympol_eval_newtonsum(long e, GEN O, GEN mod) { long f = lg(O), g = lg(gel(O,1)), i, j; GEN PL = cgetg(f, t_COL); for(i=1; i 1) f = FpX_FpXQV_eval(f,pows,Tp,p); for(j=1; j=4) err_printf("FixedField: Weight: %Ps\n",W); for (i=0; i=6) err_printf("FixedField: Sym: %Ps\n",sym); L = sympol_eval(sym,NS); if (!vec_is1to1(FpC_red(L,l))) continue; P = FpX_center(FpV_roots_to_pol(L,mod,v),mod,mod2); if (!p || FpX_is_squarefree(P,p)) return mkvec3(mkvec2(sym,W),L,P); avma = av; } return NULL; } /*Check whether the line of NS are pair-wise distinct.*/ static long sympol_is1to1_lg(GEN NS, long n) { long i, j, k, l = lgcols(NS); for (i=1; i=n) return 0; } return 1; } /* Let O a set of orbits of roots (see fixedfieldorbits) modulo mod, * l | mod and p two prime numbers. Return a vector [sym,s,P] where: * sym is a sympol, s is the set of images of sym on O and * P is the polynomial with roots s. */ static GEN fixedfieldsympol(GEN O, GEN mod, GEN l, GEN p, long v) { pari_sp ltop=avma; const long n=(BITS_IN_LONG>>1)-1; GEN NS = cgetg(n+1,t_MAT), sym = NULL, W = cgetg(n+1,t_VECSMALL); long i, e=1; if (DEBUGLEVEL>=4) err_printf("FixedField: Size: %ldx%ld\n",lg(O)-1,lg(gel(O,1))-1); for (i=1; !sym && i<=n; i++) { GEN L = sympol_eval_newtonsum(e++, O, mod); if (lg(O)>2) while (vec_isconst(L)) L = sympol_eval_newtonsum(e++, O, mod); W[i] = e-1; gel(NS,i) = L; if (sympol_is1to1_lg(NS,i+1)) sym = fixedfieldsurmer(mod,l,p,v,NS,vecsmall_shorten(W,i)); } if (!sym) pari_err_BUG("fixedfieldsympol [p too small]"); if (DEBUGLEVEL>=2) err_printf("FixedField: Found: %Ps\n",gel(sym,1)); return gerepilecopy(ltop,sym); } /* Let O a set of orbits as indices and L the corresponding roots. * Return the set of orbits as roots. */ static GEN fixedfieldorbits(GEN O, GEN L) { GEN S = cgetg(lg(O), t_MAT); long i; for (i = 1; i < lg(O); i++) gel(S,i) = vecpermute(L, gel(O,i)); return S; } static GEN fixedfieldinclusion(GEN O, GEN PL) { long i, j, f = lg(O)-1, g = lg(gel(O,1))-1; GEN S = cgetg(f*g + 1, t_COL); for (i = 1; i <= f; i++) { GEN Oi = gel(O,i); for (j = 1; j <= g; j++) gel(S, Oi[j]) = gel(PL, i); } return S; } /*Usually mod > den so there is no need to reduce it.*/ GEN vandermondeinversemod(GEN L, GEN T, GEN den, GEN mod) { pari_sp av; long i, n = lg(L); GEN P, Tp, M = cgetg(n, t_MAT); av = avma; Tp = gclone(FpX_deriv(T,mod)); /*clone*/ avma = av; for (i = 1; i < n; i++) { GEN z; av = avma; 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)); } gunclone(Tp); /*unclone*/ return M; } /* Polynomial associated to a vector of conjugates. Not stack clean */ static GEN vectopol(GEN v, GEN M, GEN den , GEN mod, GEN mod2, long x) { long l = lg(v)+1, i; GEN z = cgetg(l,t_POL); z[1] = evalsigne(1)|evalvarn(x); for (i=2; i=6) err_printf("%d ",i); gel(aut,i) = permtopol(gel(res,i), L, M, den, mod, mod2, v); } return aut; } static void notgalois(long p, struct galois_analysis *ga) { if (DEBUGLEVEL >= 2) err_printf("GaloisAnalysis:non Galois for p=%ld\n", p); ga->p = p; ga->deg = 0; } #define numberof(x) (long)(sizeof(x) / sizeof((x)[0])) /*Gather information about the group*/ static long init_group(long n, long np, GEN Fp, GEN Fe, long *porder) { /*TODO: complete the table to at least 200*/ const long prim_nonss_orders[] = { 36,48,56,60,72,75,80,96,108,120,132 }; long i, phi_order = 1, order = 1, group = 0; /* non-WSS groups of this order? */ for (i=0; i < numberof(prim_nonss_orders); i++) if (n % prim_nonss_orders[i] == 0) { group |= ga_non_wss; break; } if (np == 2 && Fp[2] == 3 && Fe[2] == 1 && Fe[1] > 2) group |= ga_ext_2; for (i = np; i > 0; i--) { long p = Fp[i]; if (phi_order % p == 0) { group |= ga_all_normal; break; } order *= p; phi_order *= p-1; if (Fe[i] > 1) break; } *porder = order; return group; } /*is a "better" than b ? (if so, update karma) */ static int improves(long a, long b, long plift, long p, long n, long *karma) { if (!plift || a > b) { *karma = ugcd(p-1,n); return 1; } if (a == b) { long k = ugcd(p-1,n); if (k > *karma) { *karma = k; return 1; } } return 0; /* worse */ } /* return 0 if not galois or not wss */ static int galoisanalysis(GEN T, struct galois_analysis *ga, long calcul_l) { pari_sp ltop = avma, av; long group, linf, n, p, i, karma = 0; GEN F, Fp, Fe, Fpe, O; long np, order, plift, nbmax, nbtest, deg; pari_timer ti; forprime_t S; if (DEBUGLEVEL >= 1) timer_start(&ti); n = degpol(T); O = zero_zv(n); F = factoru_pow(n); Fp = gel(F,1); np = lg(Fp)-1; Fe = gel(F,2); Fpe= gel(F,3); group = init_group(n, np, Fp, Fe, &order); /*Now we study the orders of the Frobenius elements*/ deg = Fp[np]; /* largest prime | n */ plift = 0; nbtest = 0; nbmax = 8+(n>>1); u_forprime_init(&S, n*maxss(expu(n)-3, 2), ULONG_MAX); av = avma; while (!plift || (nbtest < nbmax && (nbtest <=8 || order < (n>>1))) || (n == 24 && O[6] == 0 && O[4] == 0) || ((group&ga_non_wss) && order == Fp[np])) { long d, o, norm_o = 1; GEN D, Tp; if ((group&ga_non_wss) && nbtest >= 3*nbmax) break; /* in all cases */ nbtest++; avma = av; p = u_forprime_next(&S); if (!p) pari_err_OVERFLOW("galoisanalysis [ran out of primes]"); Tp = ZX_to_Flx(T,p); if (!Flx_is_squarefree(Tp,p)) { if (!--nbtest) nbtest = 1; continue; } D = Flx_nbfact_by_degree(Tp, &d, p); o = n / d; /* d factors, all should have degree o */ if (D[o] != d) { notgalois(p, ga); avma = ltop; return 0; } if (!O[o]) O[o] = p; if (o % deg) goto ga_end; /* NB: deg > 1 */ if ((group&ga_all_normal) && o < order) goto ga_end; /*Frob_p has order o > 1, find a power which generates a normal subgroup*/ if (o * Fp[1] >= n) norm_o = o; /*subgroups of smallest index are normal*/ else { for (i = np; i > 0; i--) { if (o % Fpe[i]) break; norm_o *= Fpe[i]; } } /* Frob_p^(o/norm_o) generates a normal subgroup of order norm_o */ if (norm_o != 1) { if (!(group&ga_all_normal) || o > order) karma = ugcd(p-1,n); else if (!improves(norm_o, deg, plift,p,n, &karma)) goto ga_end; /* karma0=0, deg0<=norm_o -> the first improves() returns 1 */ deg = norm_o; group |= ga_all_normal; /* STORE */ } else if (group&ga_all_normal) goto ga_end; else if (!improves(o, order, plift,p,n, &karma)) goto ga_end; order = o; plift = p; /* STORE */ ga_end: if (DEBUGLEVEL >= 5) err_printf("GaloisAnalysis:Nbtest=%ld,p=%ld,o=%ld,n_o=%d,best p=%ld,ord=%ld,k=%ld\n", nbtest, p, o, norm_o, plift, order,karma); } /* To avoid looping on non-wss group. * TODO: check for large groups. Would it be better to disable this check if * we are in a good case (ga_all_normal && !(ga_ext_2) (e.g. 60)) ?*/ ga->p = plift; if (!plift || ((group&ga_non_wss) && order == Fp[np])) { pari_warn(warner,"Galois group almost certainly not weakly super solvable"); return 0; } /*linf=(n*(n-1))>>2;*/ linf = n; if (calcul_l && O[1] <= linf) { pari_sp av2; forprime_t S2; ulong p; u_forprime_init(&S2, linf+1,ULONG_MAX); av2 = avma; while ((p = u_forprime_next(&S2))) { /*find a totally split prime l > linf*/ GEN Tp = ZX_to_Flx(T, p); long nb = Flx_nbroots(Tp, p); if (nb == n) { O[1] = p; break; } if (nb && Flx_is_squarefree(Tp,p)) { notgalois(p,ga); avma = ltop; return 0; } avma = av2; } if (!p) pari_err_OVERFLOW("galoisanalysis [ran out of primes]"); } ga->group = (enum ga_code)group; ga->deg = deg; ga->ord = order; ga->l = O[1]; ga->p4 = n >= 4 ? O[4] : 0; if (DEBUGLEVEL >= 4) err_printf("GaloisAnalysis:p=%ld l=%ld group=%ld deg=%ld ord=%ld\n", plift, O[1], group, deg, order); if (DEBUGLEVEL >= 1) timer_printf(&ti, "galoisanalysis()"); avma = ltop; return 1; } static GEN a4galoisgen(struct galois_test *td) { const long n = 12; pari_sp ltop = avma, av, av2; long i, j, k, N, hop = 0; GEN MT, O,O1,O2,O3, ar, mt, t, u, res, orb, pft, pfu, pfv; res = cgetg(3, t_VEC); pft = cgetg(n+1, t_VECSMALL); pfu = cgetg(n+1, t_VECSMALL); pfv = cgetg(n+1, t_VECSMALL); gel(res,1) = mkvec3(pft,pfu,pfv); gel(res,2) = mkvecsmall3(2,2,3); av = avma; ar = cgetg(5, t_VECSMALL); mt = gel(td->PV, td->order[n]); t = identity_perm(n) + 1; /* Sorry for this hack */ u = cgetg(n+1, t_VECSMALL) + 1; /* too lazy to correct */ MT = cgetg(n+1, t_MAT); for (j = 1; j <= n; j++) gel(MT,j) = cgetg(n+1, t_VECSMALL); for (j = 1; j <= n; j++) for (i = 1; i < j; i++) ucoeff(MT,i,j) = ucoeff(MT,j,i) = ucoeff(mt,i,j)+ucoeff(mt,j,i); /* MT(i,i) unused */ av2 = avma; /* 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); 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); uel(ar,1) = uel(ar,2) + umael(MT,5,6); for (i = 0; i < N; i++) { long g; if (i) { long a, x = i, y = 1; do { y += 2; a = x%y; x = x/y; } while (!a); switch (y) { case 3: lswap(t[2], t[2-a]); break; case 5: x = t[0]; t[0] = t[2]; t[2] = t[1]; t[1] = x; lswap(t[4], t[4-a]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 7: x = t[0]; t[0] = t[4]; t[4] = t[3]; t[3] = t[1]; t[1] = t[2]; t[2] = x; lswap(t[6], t[6-a]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 9: x = t[0]; t[0] = t[6]; t[6] = t[5]; t[5] = t[3]; t[3] = x; lswap(t[1], t[4]); lswap(t[8], t[8-a]); uel(ar,3) = uel(ar,4) + umael(MT,t[8],t[9]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 11: x = t[0]; t[0] = t[8]; t[8] = t[7]; t[7] = t[5]; t[5] = t[1]; t[1] = t[6]; t[6] = t[3]; t[3] = t[2]; t[2] = t[4]; t[4] = x; lswap(t[10], t[10-a]); uel(ar,4) = umael(MT,t[10],t[11]); uel(ar,3) = uel(ar,4) + umael(MT,t[8],t[9]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); } } g = uel(ar,1)+umael(MT,t[0],t[1])+umael(MT,t[2],t[3]); if (headlongisint(g,n)) { for (k = 0; k < n; k += 2) { pft[t[k]] = t[k+1]; pft[t[k+1]] = t[k]; } if (galois_test_perm(td, pft)) break; hop++; } avma = av2; } if (DEBUGLEVEL >= 1 && hop) err_printf("A4GaloisConj: %ld hop over %ld iterations\n", hop, N); 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); for (k = 0; k < n; k += 4) { u[k+3] = t[k+3]; u[k+2] = t[k+1]; u[k+1] = t[k+2]; u[k] = t[k]; } for (i = 0; i < N; i++) { ulong g = 0; if (i) { long a, x = i, y = -2; do { y += 4; a = x%y; x = x/y; } while (!a); lswap(u[0],u[2]); switch (y) { case 2: break; case 6: lswap(u[4],u[6]); if (!(a & 1)) { a = 4 - (a>>1); lswap(u[6], u[a]); lswap(u[4], u[a-2]); } break; case 10: x = u[6]; u[6] = u[3]; u[3] = u[2]; u[2] = u[4]; u[4] = u[1]; u[1] = u[0]; u[0] = x; if (a >= 3) a += 2; a = 8 - a; lswap(u[10],u[a]); lswap(u[8], u[a-2]); break; } } for (k = 0; k < n; k += 2) g += mael(MT,u[k],u[k+1]); if (headlongisint(g,n)) { for (k = 0; k < n; k += 2) { pfu[u[k]] = u[k+1]; pfu[u[k+1]] = u[k]; } if (galois_test_perm(td, pfu)) break; hop++; } avma = av2; } 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); 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); } av2 = avma; O1 = gel(O,1); O2 = gel(O,2); O3 = gel(O,3); for (j = 0; j < 2; j++) { pfv[O1[1]] = O2[1]; pfv[O1[2]] = O2[3+j]; pfv[O1[3]] = O2[4 - (j << 1)]; pfv[O1[4]] = O2[2+j]; for (i = 0; i < 4; i++) { ulong g = 0; switch (i) { case 0: break; case 1: lswap(O3[1], O3[2]); lswap(O3[3], O3[4]); break; case 2: lswap(O3[1], O3[4]); lswap(O3[2], O3[3]); break; case 3: lswap(O3[1], O3[2]); lswap(O3[3], O3[4]); break; } pfv[O2[1]] = O3[1]; pfv[O2[3+j]] = O3[4-j]; pfv[O2[4 - (j<<1)]] = O3[2 + (j<<1)]; pfv[O2[2+j]] = O3[3-j]; pfv[O3[1]] = O1[1]; pfv[O3[4-j]] = O1[2]; pfv[O3[2 + (j<<1)]] = O1[3]; pfv[O3[3-j]] = O1[4]; for (k = 1; k <= n; k++) g += mael(mt,k,pfv[k]); if (headlongisint(g,n) && galois_test_perm(td, pfv)) { avma = av; if (DEBUGLEVEL >= 1) err_printf("A4GaloisConj:%ld hop over %d iterations max\n", hop, 10395 + 68); return res; } hop++; avma = av2; } } avma = ltop; return gen_0; /* Fail */ } /* S4 */ static void s4makelift(GEN u, struct galois_lift *gl, GEN liftpow) { GEN s = automorphismlift(u, gl, NULL); long i; gel(liftpow,1) = s; for (i = 2; i < lg(liftpow); i++) gel(liftpow,i) = FpXQ_mul(gel(liftpow,i-1), s, gl->TQ, gl->Q); } static long s4test(GEN u, GEN liftpow, struct galois_lift *gl, GEN phi) { pari_sp av = avma; GEN res, Q, Q2; long bl, i, d = lg(u)-2; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); if (!d) return 0; Q = gl->Q; Q2 = shifti(Q,-1); res = gel(u,2); for (i = 1; i < d; i++) if (lg(gel(liftpow,i))>2) res = addii(res, mulii(gmael(liftpow,i,2), gel(u,i+2))); res = remii(res,Q); if (gl->den != gen_1) res = mulii(res, gl->den); res = centermodii(res, Q,Q2); if (absi_cmp(res, gl->gb->bornesol) > 0) { avma = av; return 0; } res = scalar_ZX_shallow(gel(u,2),varn(u)); for (i = 1; i < d ; i++) if (lg(gel(liftpow,i))>2) res = ZX_add(res, ZX_Z_mul(gel(liftpow,i), gel(u,i+2))); res = FpX_red(res, Q); if (gl->den != gen_1) res = FpX_Fp_mul(res, gl->den, Q); res = FpX_center(res, Q, shifti(Q,-1)); bl = poltopermtest(res, gl, phi); if (DEBUGLEVEL >= 6) timer_printf(&ti, "s4test()"); avma = av; return bl; } static GEN aux(long a, long b, GEN T, GEN M, GEN p, GEN *pu) { *pu = FpX_mul(gel(T,b), gel(T,a),p); return FpX_chinese_coprime(gmael(M,a,b), gmael(M,b,a), gel(T,b), gel(T,a), *pu, p); } static GEN s4releveauto(GEN misom,GEN Tmod,GEN Tp,GEN p,long a1,long a2,long a3,long a4,long a5,long a6) { pari_sp av = avma; GEN u4,u5; GEN pu1, pu2, pu3, pu4; GEN u1 = aux(a1, a2, Tmod, misom, p, &pu1); GEN u2 = aux(a3, a4, Tmod, misom, p, &pu2); GEN u3 = aux(a5, a6, Tmod, misom, p, &pu3); pu4 = FpX_mul(pu1,pu2,p); u4 = FpX_chinese_coprime(u1,u2,pu1,pu2,pu4,p); u5 = FpX_chinese_coprime(u4,u3,pu4,pu3,Tp,p); return gerepileupto(av, u5); } static GEN lincomb(GEN A, GEN B, GEN pauto, long j) { long k = (-j) & 3; if (j == k) return ZX_mul(ZX_add(A,B), gel(pauto, j+1)); return ZX_add(ZX_mul(A, gel(pauto, j+1)), ZX_mul(B, gel(pauto, k+1))); } /* FIXME: could use the intheadlong technique */ static GEN s4galoisgen(struct galois_lift *gl) { const long n = 24; struct galois_testlift gt; pari_sp av, ltop2, ltop = avma; long i, j; GEN sigma, tau, phi, res, r1,r2,r3,r4, pj, p = gl->p, Q = gl->Q, TQ = gl->TQ; GEN sg, Tp, Tmod, isom, isominv, misom, Bcoeff, pauto, liftpow, aut; res = cgetg(3, t_VEC); r1 = cgetg(n+1, t_VECSMALL); r2 = cgetg(n+1, t_VECSMALL); r3 = cgetg(n+1, t_VECSMALL); r4 = cgetg(n+1, t_VECSMALL); gel(res,1)= mkvec4(r1,r2,r3,r4); gel(res,2) = mkvecsmall4(2,2,3,2); ltop2 = avma; sg = identity_perm(6); pj = zero_zv(6); sigma = cgetg(n+1, t_VECSMALL); tau = cgetg(n+1, t_VECSMALL); phi = cgetg(n+1, t_VECSMALL); Tp = FpX_red(gl->T,p); Tmod = gel(FpX_factor(Tp,p), 1); isom = cgetg(lg(Tmod), t_VEC); isominv = cgetg(lg(Tmod), t_VEC); misom = cgetg(lg(Tmod), t_MAT); aut = galoisdolift(gl, NULL); inittestlift(aut, Tmod, gl, >); Bcoeff = gt.bezoutcoeff; pauto = gt.pauto; for (i = 1; i < lg(isom); i++) { 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, gel(isom,i)); gel(isominv,i) = FpXQ_ffisom_inv(gel(isom,i), gel(Tmod,i),p); } for (i = 1; i < lg(isom); i++) for (j = 1; j < lg(isom); j++) gmael(misom,i,j) = FpX_FpXQ_eval(gel(isominv,i),gel(isom,j), gel(Tmod,j),p); liftpow = cgetg(24, t_VEC); av = avma; for (i = 0; i < 3; i++, avma = av) { pari_sp av1, av2, av3; GEN u, u1, u2, u3; long j1, j2, j3; if (i) { if (i == 1) { lswap(sg[2],sg[3]); } else { lswap(sg[1],sg[3]); } } u = s4releveauto(misom,Tmod,Tp,p,sg[1],sg[2],sg[3],sg[4],sg[5],sg[6]); s4makelift(u, gl, liftpow); av1 = avma; for (j1 = 0; j1 < 4; j1++, avma = av1) { u1 = lincomb(gel(Bcoeff,sg[5]),gel(Bcoeff,sg[6]), pauto,j1); u1 = FpX_rem(u1, TQ, Q); av2 = avma; for (j2 = 0; j2 < 4; j2++, avma = av2) { u2 = lincomb(gel(Bcoeff,sg[3]),gel(Bcoeff,sg[4]), pauto,j2); u2 = FpX_rem(FpX_add(u1, u2, Q), TQ,Q); av3 = avma; for (j3 = 0; j3 < 4; j3++, avma = av3) { 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", i,j1,j2,j3, sg); if (s4test(u3, liftpow, gl, sigma)) { pj[1] = j3; pj[2] = j2; pj[3] = j1; goto suites4; } } } } } 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); avma = av; for (j = 1; j <= 3; j++) { pari_sp av2, av3; GEN u; long w, l, z; z = sg[1]; sg[1] = sg[3]; sg[3] = sg[5]; sg[5] = z; z = sg[2]; sg[2] = sg[4]; sg[4] = sg[6]; sg[6] = z; z = pj[1]; pj[1] = pj[2]; pj[2] = pj[3]; pj[3] = z; for (l = 0; l < 2; l++, avma = av) { u = s4releveauto(misom,Tmod,Tp,p,sg[1],sg[3],sg[2],sg[4],sg[5],sg[6]); s4makelift(u, gl, liftpow); av2 = avma; for (w = 0; w < 4; w += 2, avma = av2) { GEN uu; pj[6] = (w + pj[3]) & 3; uu = lincomb(gel(Bcoeff,sg[5]),gel(Bcoeff,sg[6]), pauto, pj[6]); uu = FpX_rem(FpX_red(uu,Q), TQ, Q); av3 = avma; for (i = 0; i < 4; i++, avma = av3) { GEN u; 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", 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])); u = FpX_rem(FpX_add(uu,u,Q), TQ, Q); if (s4test(u, liftpow, gl, tau)) goto suites4_2; } } lswap(sg[3], sg[4]); pj[2] = (-pj[2]) & 3; } } avma = ltop; return gen_0; suites4_2: avma = av; { long abc = (pj[1] + pj[2] + pj[3]) & 3; long abcdef = ((abc + pj[4] + pj[5] - pj[6]) & 3) >> 1; GEN u; pari_sp av2; u = s4releveauto(misom,Tmod,Tp,p,sg[1],sg[4],sg[2],sg[5],sg[3],sg[6]); s4makelift(u, gl, liftpow); av2 = avma; for (j = 0; j < 8; j++) { long h, g, i; h = j & 3; g = (abcdef + ((j & 4) >> 1)) & 3; i = (h + abc - g) & 3; u = ZX_add( lincomb(gel(Bcoeff,sg[1]), gel(Bcoeff,sg[4]), pauto, g), lincomb(gel(Bcoeff,sg[2]), gel(Bcoeff,sg[5]), pauto, h)); 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); if (s4test(u, liftpow, gl, phi)) break; avma = av2; } } if (j == 8) { avma = ltop; return gen_0; } for (i = 1; i <= n; i++) { r1[i] = sigma[tau[i]]; r2[i] = phi[sigma[tau[phi[i]]]]; r3[i] = phi[sigma[i]]; r4[i] = sigma[i]; } avma = ltop2; return res; } static GEN galoisfindgroups(GEN lo, GEN sg, long f) { pari_sp ltop = avma; long i, j, k; GEN V = cgetg(lg(lo), t_VEC); for(j=1,i=1; iden != gen_1) tlift = FpX_Fp_mul(tlift, gl->den, gl->Q); tlift = FpX_center(tlift, gl->Q, shifti(gl->Q,-1)); res = poltopermtest(tlift, gl, frob); avma = av; return res; } static GEN galoismakepsi(long g, GEN sg, GEN pf) { GEN psi=cgetg(g+1,t_VECSMALL); long i; for (i = 1; i < g; i++) psi[i] = sg[pf[i]]; psi[g] = sg[1]; return psi; } static GEN galoisfrobeniuslift(GEN T, GEN den, GEN L, GEN Lden, struct galois_frobenius *gf, struct galois_borne *gb) { pari_sp ltop=avma, av2; struct galois_testlift gt; 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); aut = galoisdolift(&gl, res); if (!aut || galoisfrobeniustest(aut,&gl,res)) { avma = av2; gf->deg = gf->fp; return res; } inittestlift(aut,gf->Tmod, &gl, >); gt.C = cgetg(gf->fp+1,t_VEC); gt.Cd= cgetg(gf->fp+1,t_VEC); for (i = 1; i <= gf->fp; i++) { gel(gt.C,i) = zero_zv(gt.g); gel(gt.Cd,i) = zero_zv(gt.g); } F =factoru(gf->fp); Fp = gel(F,1); Fe = gel(F,2); frob = cgetg(lg(L), t_VECSMALL); for(k=lg(Fp)-1;k>=1;k--) { pari_sp btop=avma; GEN psi=NULL, fres=NULL, sg = identity_perm(1); long el=gf->fp, dg=1, dgf=1, e, pr; for(e=1; e<=Fe[k]; e++) { GEN lo, pf; long l; dg *= Fp[k]; el /= Fp[k]; if (DEBUGLEVEL>=4) err_printf("Trying degre %d.\n",dg); if (galoisfrobeniustest(gel(gt.pauto,el+1),&gl,frob)) { psi = const_vecsmall(g,1); dgf = dg; fres = gcopy(frob); continue; } lo = listznstarelts(dg, n / gf->fp); if (e!=1) lo = galoisfindgroups(lo, sg, dgf); if (DEBUGLEVEL>=4) err_printf("Galoisconj:Subgroups list:%Ps\n", lo); for (l = 1; l < lg(lo); l++) if (lg(gel(lo,l))>2 && frobeniusliftall(gel(lo,l), el, &pf,&gl,>, frob)) { sg = gcopy(gel(lo,l)); psi = galoismakepsi(g,sg,pf); dgf = dg; fres = gcopy(frob); break; } if (l == lg(lo)) break; } if (dgf == 1) { avma = btop; continue; } pr = deg*dgf; if (deg == 1) { for(i=1;ipsi[i]=psi[i]; } else { GEN cp = perm_mul(res,fres); for(i=1;ipsi[i] = (dgf*gf->psi[i] + deg*psi[i]) % pr; } deg = pr; avma = btop; } for (i = 1; i <= gf->fp; i++) for (j = 1; j <= gt.g; j++) if (mael(gt.C,i,j)) gunclone(gmael(gt.C,i,j)); if (DEBUGLEVEL>=4 && res) err_printf("Best lift: %d\n",deg); if (deg==1) { avma = ltop; return NULL; } else { /* Normalize result so that psi[g]=1 */ long im = Fl_inv(gf->psi[g], deg); GEN cp = perm_pow(res, im); for(i=1;ipsi);i++) gf->psi[i] = Fl_mul(im, gf->psi[i], deg); avma = av2; gf->deg = deg; return res; } } /* return NULL if not Galois */ static GEN galoisfindfrobenius(GEN T, GEN L, GEN den, struct galois_frobenius *gf, struct galois_borne *gb, const struct galois_analysis *ga) { pari_sp ltop = avma, av; long Try = 0, n = degpol(T), deg, gmask = (ga->group&ga_ext_2)? 3: 1; GEN frob, Lden = makeLden(L,den,gb); forprime_t S; u_forprime_init(&S, ga->p, ULONG_MAX); av = avma; deg = gf->deg = ga->deg; while ((gf->p = u_forprime_next(&S))) { pari_sp lbot; GEN Ti, Tp; long nb, d; avma = av; Tp = ZX_to_Flx(T, gf->p); if (!Flx_is_squarefree(Tp, gf->p)) continue; Ti = gel(Flx_factor(Tp, gf->p), 1); nb = lg(Ti)-1; d = degpol(gel(Ti,1)); if (nb > 1 && degpol(gel(Ti,nb)) != d) { avma = ltop; return NULL; } if (((gmask&1)==0 || d % deg) && ((gmask&2)==0 || odd(d))) continue; if (DEBUGLEVEL >= 1) err_printf("GaloisConj: Trying p=%ld\n", gf->p); FlxV_to_ZXV_inplace(Ti); gf->fp = d; gf->Tmod = Ti; lbot = avma; frob = galoisfrobeniuslift(T, den, L, Lden, gf, gb); if (frob) { GEN *gptr[3]; gf->Tmod = gcopy(Ti); gptr[0]=&gf->Tmod; gptr[1]=&gf->psi; gptr[2]=&frob; gerepilemanysp(ltop,lbot,gptr,3); return frob; } if ((ga->group&ga_all_normal) && d % deg == 0) gmask &= ~1; /* The first prime degree is always divisible by deg, so we don't * have to worry about ext_2 being used before regular supersolvable*/ if (!gmask) { avma = ltop; return NULL; } if ((ga->group&ga_non_wss) && ++Try > ((3*n)>>1)) { pari_warn(warner,"Galois group probably not weakly super solvable"); return NULL; } } if (!gf->p) pari_err_OVERFLOW("galoisfindfrobenius [ran out of primes]"); return NULL; } /* compute g such that tau(Pmod[#])= tau(Pmod[g]) */ static long get_image(GEN tau, GEN P, GEN Pmod, GEN p) { pari_sp av = avma; long g, gp = lg(Pmod)-1; tau = RgX_to_FpX(tau, p); tau = FpX_FpXQ_eval(gel(Pmod, gp), tau, P, p); tau = FpX_normalize(FpX_gcd(P, tau, p), p); for (g = 1; g <= gp; g++) if (ZX_equal(tau, gel(Pmod,g))) { avma = av; return g; } avma = av; return 0; } static GEN galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb, const struct galois_analysis *ga); static GEN galoisgenfixedfield(GEN Tp, GEN Pmod, GEN V, GEN ip, struct galois_borne *gb) { GEN P, PL, Pden, PM, Pp; GEN tau, PG, Pg; long g, lP; long x=varn(Tp); P=gel(V,3); PL=gel(V,2); Pp = FpX_red(P,ip); if (DEBUGLEVEL>=6) err_printf("GaloisConj: Fixed field %Ps\n",P); if (degpol(P)==2) { PG=cgetg(3,t_VEC); gel(PG,1) = mkvec( mkvecsmall2(2,1) ); gel(PG,2) = mkvecsmall(2); tau = deg1pol_shallow(gen_m1, negi(gel(P,3)), x); g = get_image(tau, Pp, Pmod, ip); if (!g) return NULL; Pg = mkvecsmall(g); } else { struct galois_analysis Pga; struct galois_borne Pgb; GEN mod, mod2; long j; if (!galoisanalysis(P, &Pga, 0)) return NULL; Pgb.l = gb->l; Pden = galoisborne(P, NULL, &Pgb, degpol(P)); if (Pgb.valabs > gb->valabs) { if (DEBUGLEVEL>=4) 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); } else if (Pgb.valabs < gb->valabs) PL = FpC_red(PL, Pgb.ladicabs); PM = vandermondeinversemod(PL, P, Pden, Pgb.ladicabs); PG = galoisgen(P, PL, PM, Pden, &Pgb, &Pga); if (PG == gen_0) return NULL; lP = lg(gel(PG,1)); mod = Pgb.ladicabs; mod2 = shifti(mod, -1); Pg = cgetg(lP, t_VECSMALL); for (j = 1; j < lP; j++) { pari_sp btop=avma; tau = permtopol(gmael(PG,1,j), PL, PM, Pden, mod, mod2, x); g = get_image(tau, Pp, Pmod, ip); if (!g) return NULL; Pg[j] = g; avma = btop; } } return mkvec2(PG,Pg); } /* Let sigma^m=1, tau*sigma*tau^-1=sigma^s. * Compute n so that (sigma*tau)^e = sigma^n*tau^e * We have n = sum_{k=0}^{e-1} s^k mod m. * so n*(1-s) = 1-s^e mod m * Unfortunately (1-s) might not invertible mod m. */ static long stpow(long s, long e, long m) { long i; long n = 1; for (i = 1; i < e; i++) n = (1 + n * s) % m; return n; } static GEN wpow(long s, long m, long e, long n) { GEN w = cgetg(n+1,t_VECSMALL); long si = s; long i; w[1] = 1; for(i=2; i<=n; i++) w[i] = w[i-1]*e; for(i=n; i>=1; i--) { si = Fl_powu(si,e,m); w[i] = Fl_mul(s-1, stpow(si, w[i], m), m); } return w; } static GEN galoisgenliftauto(GEN O, GEN gj, long s, long n, struct galois_test *td) { pari_sp av = avma; long sr, k; long deg = lg(gel(O,1))-1; GEN X = cgetg(lg(O), t_VECSMALL); GEN oX = cgetg(lg(O), t_VECSMALL); GEN B = perm_cycles(gj); long oj = lg(gel(B,1)) - 1; GEN F = factoru(oj); GEN Fp = gel(F,1); GEN Fe = gel(F,2); GEN pf = identity_perm(n); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: %Ps of relative order %d\n", gj, oj); for (k=lg(Fp)-1; k>=1; k--) { long f, dg = 1, el = oj, osel = 1, a = 0; long p = Fp[k], e = Fe[k], op = oj / upowuu(p,e); long i; GEN pf1 = NULL, w, wg, Be = cgetg(e+1,t_VEC); gel(Be,e) = cyc_pow(B, op); for(i=e-1; i>=1; i--) gel(Be,i) = cyc_pow(gel(Be,i+1), p); w = wpow(Fl_powu(s,op,deg),deg,p,e); wg = cgetg(e+2,t_VECSMALL); wg[e+1] = deg; for (i=e; i>=1; i--) wg[i] = ugcd(wg[i+1], w[i]); for (i=1; i= 6) err_printf("GaloisConj: B=%Ps\n", Bel); sr = cgcd(stpow(sel,p,deg),deg); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: exp %d: s=%ld [%ld] a=%ld w=%ld wg=%ld sr=%ld\n", dg, sel, deg, a, w[f], wg[f+1], sr); for (t = 0; t < sr; t++) if ((a+t*w[f])%wg[f+1]==0) { long i, j, k, st; for (i = 1; i < lg(X); i++) X[i] = 0; for (i = 0; i < lg(X)-1; i+=dg) for (j = 1, k = p, st = t; k <= dg; j++, k += p) { X[k+i] = (oX[j+i] + st)%deg; st = (t + st*osel)%deg; } pf1 = testpermutation(O, Bel, X, sel, p, sr, td); if (pf1) break; } if (!pf1) return NULL; for (i=1; ideg) return gen_0; x = varn(T); 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"); inittest(L, M, gb->bornesol, gb->ladicsol, &td); PG = a4galoisgen(&td); freetest(&td); if (PG != gen_0) return gerepileupto(ltop, PG); avma = av; } if (n == 24 && ga->ord==3) { /* 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"); initlift(T, den, stoi(ga->p4), L, makeLden(L,den,gb), gb, &gl); PG = s4galoisgen(&gl); if (PG != gen_0) return gerepileupto(ltop, PG); avma = av; } frob = galoisfindfrobenius(T, L, den, &gf, gb, ga); if (!frob) { avma=ltop; return gen_0; } p = gf.p; ip = utoipos(p); Tmod = gf.Tmod; O = perm_cycles(frob); deg = lg(gel(O,1))-1; if (DEBUGLEVEL >= 9) err_printf("GaloisConj:Orbite:%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); { pari_sp btop=avma; GEN V, Tp, Sp, Pmod; GEN OL = fixedfieldorbits(O,L); V = fixedfieldsympol(OL, gb->ladicabs, gb->l, ip, x); Tp = FpX_red(T,ip); Sp = sympol_aut_evalmod(gel(V,1),deg,sigma,Tp,ip); 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); PG=gerepilecopy(btop, PG); } inittest(L, M, gb->bornesol, gb->ladicsol, &td); PG1 = gmael(PG, 1, 1); lP = lg(PG1); PG2 = gmael(PG, 1, 2); Pg = gel(PG, 2); res = cgetg(3, t_VEC); gel(res,1) = res1 = cgetg(lP + 1, t_VEC); gel(res,2) = vecsmall_prepend(PG2, deg); gel(res1, 1) = vecsmall_copy(frob); for (j = 1; j < lP; j++) { GEN pf = galoisgenliftauto(O, gel(PG1, j), gf.psi[Pg[j]], n, &td); if (!pf) { freetest(&td); avma = ltop; return gen_0; } gel(res1, j+1) = pf; } if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Fini!\n"); freetest(&td); return gerepileupto(ltop, res); } /* T = polcyclo(N) */ static GEN conjcyclo(GEN T, long N) { pari_sp av = avma; long i, k = 1, d = eulerphiu(N), v = varn(T); GEN L = cgetg(d+1,t_COL); for (i=1; i<=N; i++) if (ugcd(i, N)==1) { GEN s = monomial(gen_1, i, v); if (i >= d) s = ZX_rem(s, T); gel(L,k++) = s; } return gerepileupto(av, gen_sort(L, (void*)&gcmp, &gen_cmp_RgX)); } /* T: polynomial or nf, den multiple of common denominator of solutions or * NULL (unknown). If T is nf, and den unknown, use den = denom(nf.zk) */ static GEN galoisconj4_main(GEN T, GEN den, long flag) { pari_sp ltop = avma; GEN nf, G, L, M, aut; struct galois_analysis ga; struct galois_borne gb; long n; pari_timer ti; T = get_nfpol(T, &nf); n = poliscyclo(T); if (n) return flag? galoiscyclo(n, varn(T)): conjcyclo(T, n); n = degpol(T); if (nf) { if (!den) den = Q_denom(nf_get_zk(nf)); } else { if (n <= 0) pari_err_IRREDPOL("galoisinit",T); RgX_check_ZX(T, "galoisinit"); if (!ZX_is_squarefree(T)) pari_err_DOMAIN("galoisinit","issquarefree(pol)","=",gen_0,T); if (!gequal1(gel(T,n+2))) pari_err_IMPL("galoisinit(non-monic)"); } if (n == 1) { if (!flag) { G = cgetg(2, t_COL); gel(G,1) = pol_x(varn(T)); return G;} ga.l = 3; ga.deg = 1; den = gen_1; } else if (!galoisanalysis(T, &ga, 1)) { avma = ltop; return utoipos(ga.p); } if (den) { if (typ(den) != t_INT) pari_err_TYPE("galoisconj4 [2nd arg integer]", den); den = absi(den); } gb.l = utoipos(ga.l); 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()"); M = vandermondeinversemod(L, T, den, gb.ladicabs); if (DEBUGLEVEL >= 1) timer_printf(&ti, "vandermondeinversemod()"); if (n == 1) { G = cgetg(3, t_VEC); gel(G,1) = cgetg(1, t_VEC); gel(G,2) = cgetg(1, t_VECSMALL); } else G = galoisgen(T, L, M, den, &gb, &ga); 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) { GEN grp = cgetg(9, t_VEC); gel(grp,1) = ZX_copy(T); gel(grp,2) = mkvec3(utoipos(ga.l), utoipos(gb.valabs), icopy(gb.ladicabs)); gel(grp,3) = ZC_copy(L); gel(grp,4) = ZM_copy(M); gel(grp,5) = icopy(den); gel(grp,6) = group_elts(G,n); gel(grp,7) = gcopy(gel(G,1)); gel(grp,8) = gcopy(gel(G,2)); return gerepileupto(ltop, grp); } aut = galoisgrouptopol(group_elts(G, n),L,M,den,gb.ladicsol, varn(T)); if (DEBUGLEVEL >= 1) timer_printf(&ti, "Computation of polynomials"); return gerepileupto(ltop, gen_sort(aut, (void*)&gcmp, &gen_cmp_RgX)); } /* Heuristic computation of #Aut(T), pinit = first prime to be tested */ long numberofconjugates(GEN T, long pinit) { pari_sp av = avma; long c, nbtest, nbmax, n = degpol(T); ulong p; forprime_t S; if (n == 1) return 1; 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 */ #else c = n; #endif u_forprime_init(&S, pinit, ULONG_MAX); while((p = u_forprime_next(&S))) { GEN L, Tp = ZX_to_Flx(T,p); long i, nb; if (!Flx_is_squarefree(Tp, p)) continue; /* unramified */ nbtest++; L = Flx_nbfact_by_degree(Tp, &nb, p); /* L[i] = #factors of degree i */ if (L[n/nb] == nb) { if (c == n && nbtest > 10) break; /* probably Galois */ } else { c = ugcd(c, L[1]); for (i = 2; i <= n; i++) if (L[i]) { c = ugcd(c, L[i]*i); if (c == 1) break; } if (c == 1) break; } if (nbtest == nbmax) break; if (DEBUGLEVEL >= 6) err_printf("NumberOfConjugates [%ld]:c=%ld,p=%ld\n", nbtest,c,p); avma = av; } if (DEBUGLEVEL >= 2) err_printf("NumberOfConjugates:c=%ld,p=%ld\n", c, p); avma = av; return c; } static GEN galoisconj4(GEN nf, GEN d) { pari_sp av = avma; GEN G, T; G = galoisconj4_main(nf, d, 0); if (typ(G) != t_INT) return G; /* Success */ avma = av; T = get_nfpol(nf, &nf); G = cgetg(2, t_COL); gel(G,1) = pol_x(varn(T)); return G; /* Fail */ } /* d multipllicative bound for the automorphism's denominators */ GEN galoisconj(GEN nf, GEN d) { pari_sp av = avma; GEN G = galoisconj4_main(nf, d, 0); if (typ(G) != t_INT) return G; /* Success */ avma = av; return galoisconj1(nf); } GEN galoisconj0(GEN nf, long flag, GEN d, long prec) { switch(flag) { case 0: return galoisconj(nf, d); case 1: return galoisconj1(nf); case 2: return galoisconj2(nf, prec); case 4: return galoisconj4(nf, d); } pari_err_FLAG("nfgaloisconj"); return NULL; /*not reached*/ } /******************************************************************************/ /* Galois theory related algorithms */ /******************************************************************************/ GEN checkgal(GEN gal) { if (typ(gal) == t_POL) pari_err_TYPE("checkgal [apply galoisinit first]",gal); if (typ(gal) != t_VEC || lg(gal) != 9) pari_err_TYPE("checkgal",gal); return gal; } GEN galoisinit(GEN nf, GEN den) { GEN G = galoisconj4_main(nf, den, 1); return (typ(G) == t_INT)? gen_0: G; } static GEN galoispermtopol_i(GEN gal, GEN perm, GEN mod, GEN mod2) { long t = typ(perm), i; GEN v; switch (t) { case t_VECSMALL: { long v = varn(gel(gal,1)); return permtopol(perm, gal_get_roots(gal), gal_get_invvdm(gal), gal_get_den(gal), mod, mod2, v); } case t_VEC: case t_COL: case t_MAT: v = cgetg(lg(perm), t); if (DEBUGLEVEL>=4) err_printf("GaloisPermToPol:"); for (i = 1; i < lg(v); i++) { gel(v,i) = galoispermtopol_i(gal, gel(perm,i), mod, mod2); if (DEBUGLEVEL>=4) err_printf("%ld ",i); } if (DEBUGLEVEL>=4) err_printf("\n"); return v; } pari_err_TYPE("galoispermtopol", perm); return NULL; /* not reached */ } GEN galoispermtopol(GEN gal, GEN perm) { pari_sp av = avma; GEN mod, mod2; gal = checkgal(gal); mod = gal_get_mod(gal); mod2 = shifti(mod,-1); return gerepilecopy(av, galoispermtopol_i(gal, perm, mod, mod2)); } GEN galoiscosets(GEN O, GEN perm) { long i, j, k, u, f, l = lg(O); GEN RC, C = cgetg(l,t_VECSMALL), o = gel(O,1); pari_sp av = avma; f = lg(o); u = o[1]; RC = zero_zv(lg(perm)-1); for(i=1,j=1; j=4) err_printf("GaloisFixedField:cosets=%Ps \n",cosets); if (DEBUGLEVEL>=6) err_printf("GaloisFixedField:den=%Ps mod=%Ps \n",den,mod); V = cgetg(l,t_COL); res = cgetg(l,t_VEC); for (i = 1; i < l; i++) { pari_sp av = avma; GEN G = cgetg(l,t_VEC), Lp = vecpermute(L, gel(perm, cosets[i])); for (k = 1; k < l; k++) gel(G,k) = FpV_roots_to_pol(vecpermute(Lp, gel(O,k)), mod, x); for (j = 1; j < lo; j++) { for(k = 1; k < l; k++) gel(V,k) = gmael(G,k,j+1); gel(F,j) = vectopol(V, M, den, mod, mod2, y); } gel(res,i) = gerepileupto(av,gtopolyrev(F,x)); } return gerepileupto(ltop,res); } static void chk_perm(GEN perm, long n) { if (typ(perm) != t_VECSMALL || lg(perm)!=n+1) pari_err_TYPE("galoisfixedfield", perm); } static int is_group(GEN g) { return typ(g)==t_VEC && lg(g)==3 && typ(gel(g,1))==t_VEC && typ(gel(g,2))==t_VECSMALL; } GEN galoisfixedfield(GEN gal, GEN perm, long flag, long y) { pari_sp ltop = avma; GEN T, L, P, S, PL, O, res, mod, mod2; long vT, n, i; if (flag<0 || flag>2) pari_err_FLAG("galoisfixedfield"); gal = checkgal(gal); T = gal_get_pol(gal); vT = varn(T); L = gal_get_roots(gal); n = lg(L)-1; mod = gal_get_mod(gal); if (typ(perm) == t_VEC) { if (is_group(perm)) perm = gel(perm, 1); for (i = 1; i < lg(perm); i++) chk_perm(gel(perm,i), n); O = vecperm_orbits(perm, n); } else { chk_perm(perm, n); O = perm_cycles(perm); } { GEN OL= fixedfieldorbits(O,L); GEN V = fixedfieldsympol(OL, mod, gal_get_p(gal), NULL, vT); PL= gel(V,2); P = gel(V,3); } if (flag==1) return gerepileupto(ltop,P); mod2 = shifti(mod,-1); S = fixedfieldinclusion(O, PL); S = vectopol(S, gal_get_invvdm(gal), gal_get_den(gal), mod, mod2, vT); if (flag==0) res = cgetg(3, t_VEC); else { GEN PM, Pden; struct galois_borne Pgb; long val = itos(gal_get_e(gal)); Pgb.l = gal_get_p(gal); Pden = galoisborne(P, NULL, &Pgb, degpol(T)/degpol(P)); if (Pgb.valabs > val) { if (DEBUGLEVEL>=4) 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 (varncmp(y, vT) <= 0) pari_err_PRIORITY("galoisfixedfield", T, "<=", y); res = cgetg(4, t_VEC); gel(res,3) = fixedfieldfactor(L,O,gal_get_group(gal), PM,Pden,mod,mod2,vT,y); } gel(res,1) = gcopy(P); gel(res,2) = gmodulo(S, T); return gerepileupto(ltop, res); } /* gal a galois group output the underlying wss group */ GEN galois_group(GEN gal) { return mkvec2(gal_get_gen(gal), gal_get_orders(gal)); } GEN checkgroup(GEN g, GEN *S) { if (is_group(g)) { *S = NULL; return g; } g = checkgal(g); *S = gal_get_group(g); return galois_group(g); } GEN galoisisabelian(GEN gal, long flag) { pari_sp av = avma; GEN S, G = checkgroup(gal,&S); if (!group_isabelian(G)) { avma=av; return gen_0; } switch(flag) { case 0: return gerepileupto(av, group_abelianHNF(G,S)); case 1: avma=av; return gen_1; case 2: return gerepileupto(av, group_abelianSNF(G,S)); default: pari_err_FLAG("galoisisabelian"); } return NULL; /* not reached */ } long galoisisnormal(GEN gal, GEN sub) { pari_sp av = avma; GEN S, G = checkgroup(gal, &S), H = checkgroup(sub, &S); long res = group_subgroup_isnormal(G, H); avma = av; return res; } GEN galoissubgroups(GEN gal) { pari_sp av = avma; GEN S, G = checkgroup(gal,&S); return gerepileupto(av, group_subgroups(G)); } GEN galoissubfields(GEN G, long flag, long v) { pari_sp av = avma; GEN L = galoissubgroups(G); long i, l = lg(L); GEN S = cgetg(l, t_VEC); for (i = 1; i < l; ++i) gel(S,i) = galoisfixedfield(G, gmael(L,i,1), flag, v); return gerepileupto(av, S); } GEN galoisexport(GEN gal, long format) { pari_sp av = avma; GEN S, G = checkgroup(gal,&S); return gerepileupto(av, group_export(G,format)); } GEN galoisidentify(GEN gal) { pari_sp av = avma; GEN S, G = checkgroup(gal,&S); long idx = group_ident(G,S), card = group_order(G); avma = av; return mkvec2s(card, idx); } pari-2.7.5/src/basemath/trans3.c0000644000175000017500000025657112572003473015062 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FONCTIONS **/ /** (part 3) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define HALF_E 1.3591409 /* Exponential / 2 */ /***********************************************************************/ /** **/ /** BESSEL FUNCTIONS **/ /** **/ /***********************************************************************/ /* n! sum_{k=0}^m Z^k / (k!*(k+n)!), with Z := (-1)^flag*z^2/4 */ static GEN _jbessel(GEN n, GEN z, long flag, long m) { pari_sp av, lim; GEN Z,s; long k; Z = gmul2n(gsqr(z),-2); if (flag & 1) Z = gneg(Z); if (typ(z) == t_SER) { long v = valp(z); if (v < 0) pari_err_DOMAIN("besselj","valuation", "<", gen_0, z); k = lg(Z)-2 - v; if (v == 0) pari_err_IMPL("besselj around a!=0"); if (k <= 0) return scalarser(gen_1, varn(z), 2*v); setlg(Z, k+2); } s = gen_1; av = avma; lim = stack_lim(av,1); 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 (DEBUGMEM>1) pari_warn(warnmem,"besselj"); s = gerepileupto(av, s); } } return s; } /* return L * approximate solution to x log x = B */ static long bessel_get_lim(double B, double L) { long lim; double x = 1 + B; /* 3 iterations are enough except in pathological cases */ x = (x + B)/(log(x)+1); x = (x + B)/(log(x)+1); x = (x + B)/(log(x)+1); x = L*x; lim = (long)x; if (lim < 2) lim = 2; return lim; } static GEN jbesselintern(GEN n, GEN z, long flag, long prec); static GEN kbesselintern(GEN n, GEN z, long flag, long prec); static GEN jbesselvec(GEN n, GEN x, long fl, long prec) { long i, l; GEN y = cgetg_copy(x, &l); for (i=1; i= 1.0) precnew += nbits2extraprec((long)(L/(HALF_E*LOG2) + BITS_IN_LONG)); if (issmall(n,&ki)) { k = labs(ki); n = utoi(k); } else { i = precision(n); if (i && i < precnew) n = gtofp(n,precnew); } z = gtofp(z,precnew); B = prec2nbits_mul(prec, LOG2/2) / L; lim = bessel_get_lim(B, L); p1 = gprec_wtrunc(_jbessel(n,z,flag,lim), prec); return gerepileupto(av, gmul(p2,p1)); } case t_VEC: case t_COL: case t_MAT: return jbesselvec(n, z, flag, prec); case t_POLMOD: y = jbesselvec(n, polmod_to_embed(z, prec), flag, prec); return gerepileupto(av,y); case t_PADIC: pari_err_IMPL("p-adic jbessel function"); default: if (!(y = toser_i(z))) break; if (issmall(n,&ki)) n = utoi(labs(ki)); return gerepileupto(av, _jbessel(n,y,flag,lg(y)-2)); } pari_err_TYPE("jbessel",z); return NULL; /* not reached */ } GEN jbessel(GEN n, GEN z, long prec) { return jbesselintern(n,z,1,prec); } GEN ibessel(GEN n, GEN z, long prec) { return jbesselintern(n,z,0,prec); } static GEN _jbesselh(long k, GEN z, long prec) { GEN s,c,p0,p1,p2, zinv = ginv(z); long i; gsincos(z,&s,&c,prec); p1 = gmul(zinv,s); if (k) { p0 = p1; p1 = gmul(zinv,gsub(p0,c)); for (i=2; i<=k; i++) { p2 = gsub(gmul(gmulsg(2*i-1,zinv),p1), p0); p0 = p1; p1 = p2; } } return p1; } /* J_{n+1/2}(z) */ GEN jbesselh(GEN n, GEN z, long prec) { long k, i; pari_sp av; GEN y; if (typ(n)!=t_INT) pari_err_TYPE("jbesselh",n); k = itos(n); if (k < 0) return jbessel(gadd(ghalf,n), z, prec); switch(typ(z)) { case t_INT: case t_FRAC: case t_QUAD: case t_REAL: case t_COMPLEX: { long bits, precnew, gz, pr; GEN p1; if (gequal0(z)) { av = avma; p1 = gmul(gsqrt(gdiv(z,mppi(prec)),prec),gpowgs(z,k)); p1 = gdiv(p1, mulu_interval(k+1, 2*k+1)); /* x k! / (2k+1)! */ return gerepileupto(av, gmul2n(p1,2*k)); } gz = gexpo(z); if ( (pr = precision(z)) ) prec = pr; y = cgetc(prec); bits = -2*k*gz + BITS_IN_LONG; av = avma; if (bits <= 0) precnew = prec; else { precnew = prec + nbits2extraprec(bits); if (pr) z = gtofp(z, precnew); } p1 = gmul(_jbesselh(k,z,prec), gsqrt(gdiv(z,Pi2n(-1,prec)),prec)); avma = av; return affc_fixlg(p1, y); } case t_VEC: case t_COL: case t_MAT: return jbesselhvec(n, z, prec); case t_POLMOD: av = avma; return gerepileupto(av, jbesselhvec(n, polmod_to_embed(z,prec), prec)); case t_PADIC: pari_err_IMPL("p-adic jbesselh function"); default: { GEN p1, v; av = avma; if (!(y = toser_i(z))) break; if (gequal0(y)) return gerepileupto(av, gpowgs(y,k)); if (valp(y) < 0) pari_err_DOMAIN("besseljh","valuation", "<", gen_0, y); y = gprec(y, lg(y)-2 + (2*k+1)*valp(y)); p1 = gdiv(_jbesselh(k,y,prec),gpowgs(y,k)); v = cgetg(k+1, t_VECSMALL); for (i=1; i<=k; i++) v[i] = 2*i+1; p1 = gmul(p1, zv_prod_Z(v)); return gerepilecopy(av,p1); } } pari_err_TYPE("besseljh",z); return NULL; /* not reached */ } static GEN kbessel2(GEN nu, GEN x, long prec) { pari_sp av = avma; GEN p1, x2, a; if (typ(x)==t_REAL) prec = realprec(x); x2 = gshift(x,1); a = gtofp(gaddgs(gshift(nu,1), 1), prec); p1 = hyperu(gshift(a,-1),a,x2,prec); p1 = gmul(gmul(p1,gpow(x2,nu,prec)), sqrtr(mppi(prec))); return gerepileupto(av, gmul(p1,gexp(gneg(x),prec))); } static GEN kbessel1(GEN nu, GEN gx, long prec) { GEN x, y, p1, zf, zz, r, s, t, u, ak, pitemp, nu2; long l, lnew, k, k2, l1, n2, n, ex; pari_sp av; if (typ(nu)==t_COMPLEX) return kbessel2(nu,gx,prec); l = (typ(gx)==t_REAL)? realprec(gx): prec; ex = gexpo(gx); if (ex < 0) { long rab = nbits2extraprec(-ex); lnew = l + rab; prec += rab; } else lnew = l; 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; n2 = n<<1; pitemp=mppi(l1); r = gmul2n(x,1); if (cmprs(x, n) < 0) { GEN q = stor(n2, l1), v, c, e, f; pari_sp av1, av2; u=cgetr(l1); v=cgetr(l1); e=cgetr(l1); f=cgetr(l1); av1 = avma; zf = sqrtr(divru(pitemp,n2)); zz = invr(stor(n2<<2, prec)); s = real_1(prec); t = real_0(prec); for (k=n2,k2=2*n2-1; k > 0; k--,k2-=2) { p1 = addri(nu2, sqrs(k2)); ak = divrs(mulrr(p1,zz),-k); s = addsr(1, mulrr(ak,s)); t = addsr(k2,mulrr(ak,t)); } mulrrz(zf, s, u); shiftr_inplace(t, -1); divrsz(addrr(mulrr(t,zf),mulrr(u,nu)),-n2,v); for(;; avma = av1) { GEN d = real_1(l1); c = divur(5,q); if (expo(c) >= -1) c = real2n(-1,l1); p1 = subsr(1,divrr(r,q)); if (cmprr(c,p1)>0) c = p1; togglesign(c); affrr(u,e); affrr(v,f); av2 = avma; for (k=1;; k++, avma=av2) { GEN w = addrr(gmul2n(mulur(2*k-1,u), -1), mulrr(subrs(q,k),v)); w = addrr(w, mulrr(nu, subrr(u,gmul2n(v,1)))); divrsz(mulrr(q,v),k,u); divrsz(w,k,v); mulrrz(d,c,d); addrrz(e,mulrr(d,u),e); p1=mulrr(d,v); addrrz(f,p1,f); if (gexpo(p1) - gexpo(f) <= 1-prec2nbits(precision(p1))) break; } swap(e, u); swap(f, v); affrr(mulrr(q,addrs(c,1)), q); if (expo(subrr(q,r)) - expo(r) <= 1-prec2nbits(lnew)) break; } u = mulrr(u, gpow(divru(x,n),nu,prec)); } else { zf = sqrtr(divrr(pitemp,r)); zz = ginv(gmul2n(r,2)); s = real_1(prec); for (k=n2,k2=2*n2-1; k > 0; k--,k2-=2) { p1 = addri(nu2, sqrs(k2)); ak = divru(mulrr(p1,zz), k); s = subsr(1, mulrr(ak,s)); } u = mulrr(s, zf); } affrr(mulrr(u, mpexp(mpneg(x))), y); avma = av; return y; } /* sum_{k=0}^m Z^k (H(k)+H(k+n)) / (k! (k+n)!) * + sum_{k=0}^{n-1} (-Z)^(k-n) (n-k-1)!/k! with Z := (-1)^flag*z^2/4. * Warning: contrary to _jbessel, no n! in front. * When flag > 1, compute exactly the H(k) and factorials (slow) */ static GEN _kbessel1(long n, GEN z, long flag, long m, long prec) { GEN Z, p1, p2, s, H; pari_sp av, lim; long k; Z = gmul2n(gsqr(z),-2); if (flag & 1) Z = gneg(Z); if (typ(z) == t_SER) { long v = valp(z); if (v < 0) pari_err_DOMAIN("_kbessel1","valuation", "<", gen_0, z); k = lg(Z)-2 - v; if (v == 0) pari_err_IMPL("Bessel K around a!=0"); if (k <= 0) return gadd(gen_1, zeroser(varn(z), 2*v)); setlg(Z, k+2); } H = cgetg(m+n+2,t_VEC); gel(H,1) = gen_0; if (flag <= 1) { gel(H,2) = s = real_1(prec); for (k=2; k<=m+n; k++) gel(H,k+1) = s = divru(addsr(1,mulur(k,s)),k); } else { gel(H,2) = s = gen_1; 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); 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 (DEBUGMEM>1) pari_warn(warnmem,"_kbessel1"); s = gerepileupto(av, s); } } p1 = (flag <= 1) ? mpfactr(n,prec) : mpfact(n); s = gdiv(s,p1); if (n) { Z = gneg(ginv(Z)); p2 = gmulsg(n, gdiv(Z,p1)); s = gadd(s,p2); for (k=n-1; k>0; k--) { p2 = gmul(p2, gmul(mulss(k,n-k),Z)); s = gadd(s,p2); } } return s; } /* flag = 0: K / flag = 1: N */ static GEN kbesselintern(GEN n, GEN z, long flag, long prec) { const char *f = flag? "besseln": "besselk"; const long flK = (flag == 0); long i, k, ki, lim, precnew, fl2, ex; pari_sp av = avma; GEN p1, p2, y, p3, pp, pm, s, c; double B, L; switch(typ(z)) { case t_INT: case t_FRAC: case t_QUAD: case t_REAL: case t_COMPLEX: if (gequal0(z)) pari_err_DOMAIN(f, "argument", "=", gen_0, z); i = precision(z); if (i) prec = i; i = precision(n); if (i && prec > i) prec = i; ex = gexpo(z); /* experimental */ if (!flag && !gequal0(n) && ex > prec2nbits(prec)/16 + gexpo(n)) return kbessel1(n,z,prec); L = HALF_E * gtodouble(gabs(z,prec)); precnew = prec; if (L >= HALF_E) { long rab = nbits2extraprec((long) (L/(HALF_E*LOG2))); if (flK) rab *= 2; precnew += 1 + rab; } z = gtofp(z, precnew); if (issmall(n,&ki)) { GEN z2 = gmul2n(z, -1); k = labs(ki); B = prec2nbits_mul(prec,LOG2/2) / L; if (flK) B += 0.367879; lim = bessel_get_lim(B, L); p1 = gmul(gpowgs(z2,k), _kbessel1(k,z,flag,lim,precnew)); p2 = gadd(mpeuler(precnew), glog(z2,precnew)); p3 = jbesselintern(stoi(k),z,flag,precnew); p2 = gsub(gmul2n(p1,-1),gmul(p2,p3)); p2 = gprec_wtrunc(p2, prec); if (flK) { if (k & 1) p2 = gneg(p2); } else { p2 = gdiv(p2, Pi2n(-1,prec)); if (ki >= 0 || (k&1)==0) p2 = gneg(p2); } return gerepilecopy(av, p2); } n = gtofp(n, precnew); gsincos(gmul(n,mppi(precnew)), &s,&c,precnew); ex = gexpo(s); if (ex < 0) { long rab = nbits2extraprec(-ex); if (flK) rab *= 2; precnew += rab; } if (i && i < precnew) { n = gtofp(n,precnew); z = gtofp(z,precnew); gsincos(gmul(n,mppi(precnew)), &s,&c,precnew); } pp = jbesselintern(n, z,flag,precnew); pm = jbesselintern(gneg(n),z,flag,precnew); if (flK) p1 = gmul(gsub(pm,pp), Pi2n(-1,precnew)); else p1 = gsub(gmul(c,pp),pm); p1 = gdiv(p1, s); return gerepilecopy(av, gprec_wtrunc(p1,prec)); case t_VEC: case t_COL: case t_MAT: return kbesselvec(n,z,flag,prec); case t_POLMOD: y = kbesselvec(n,polmod_to_embed(z,prec),flag,prec); return gerepileupto(av, y); case t_PADIC: pari_err_IMPL(stack_strcat("p-adic ",f)); default: if (!(y = toser_i(z))) break; if (issmall(n,&ki)) { k = labs(ki); return gerepilecopy(av, _kbessel1(k,y,flag+2,lg(y)-2,prec)); } if (!issmall(gmul2n(n,1),&ki)) pari_err_DOMAIN(f, "2n mod Z", "!=", gen_0,n); k = labs(ki); n = gmul2n(stoi(k),-1); fl2 = (k&3)==1; pm = jbesselintern(gneg(n),y,flag,prec); if (flK) { pp = jbesselintern(n,y,flag,prec); p2 = gpowgs(y,-k); if (fl2 == 0) p2 = gneg(p2); p3 = gmul2n(diviiexact(mpfact(k + 1),mpfact((k + 1) >> 1)),-(k + 1)); p3 = gdivgs(gmul2n(gsqr(p3),1),k); p2 = gmul(p2,p3); p1 = gsub(pp,gmul(p2,pm)); } else p1 = pm; return gerepileupto(av, fl2? gneg(p1): gcopy(p1)); } pari_err_TYPE(f,z); return NULL; /* not reached */ } GEN kbessel(GEN n, GEN z, long prec) { return kbesselintern(n,z,0,prec); } GEN nbessel(GEN n, GEN z, long prec) { return kbesselintern(n,z,1,prec); } /* J + iN */ GEN hbessel1(GEN n, GEN z, long prec) { pari_sp av = avma; return gerepileupto(av, gadd(jbessel(n,z,prec), mulcxI(nbessel(n,z,prec)))); } /* J - iN */ GEN hbessel2(GEN n, GEN z, long prec) { pari_sp av = avma; return gerepileupto(av, gadd(jbessel(n,z,prec), mulcxmI(nbessel(n,z,prec)))); } /***********************************************************************/ /* **/ /** FONCTION U(a,b,z) GENERALE **/ /** ET CAS PARTICULIERS **/ /** **/ /***********************************************************************/ /* Assume gx > 0 and a,b complex */ /* This might one day be extended to handle complex gx */ /* see Temme, N. M. "The numerical computation of the confluent */ /* hypergeometric function U(a,b,z)" in Numer. Math. 41 (1983), */ /* no. 1, 63--82. */ GEN hyperu(GEN a, GEN b, GEN gx, long prec) { GEN S, P, T, x, p1, zf, u, a1, mb = gneg(b); const int ex = iscomplex(a) || iscomplex(b); long k, n, l = (typ(gx)==t_REAL)? realprec(gx): prec, l1 = l+EXTRAPRECWORD; GEN y = ex? cgetc(l): cgetr(l); pari_sp av = avma; if (gsigne(gx) <= 0) pari_err_IMPL("non-positive third argument in hyperu"); 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))); S = gadd(a1, a); if (cmprs(x,n) < 0) { GEN q = stor(n, l1), s = gen_1, t = gen_0, v, c, e, f; pari_sp av1, av2; if (ex) { u=cgetc(l1); v=cgetc(l1); e=cgetc(l1); f=cgetc(l1); } else { u=cgetr(l1); v=cgetr(l1); e=cgetr(l1); f=cgetr(l1); } av1 = avma; zf = gpow(stoi(n),gneg_i(a),l1); T = gadd(gadd(P, gmulsg(n-1, S)), sqrs(n-1)); for (k=n-1; k>=0; k--) { /* T = (a+k)*(a1+k) = a*a1 + k(a+a1) + k^2 = previous(T) - S - 2k + 1 */ p1 = gdiv(T, mulss(-n, k+1)); s = gaddgs(gmul(p1,s), 1); t = gadd( gmul(p1,t), gaddgs(a,k)); if (!k) break; T = gsubgs(gsub(T, S), 2*k-1); } gmulz(zf, s, u); gmulz(zf, gdivgs(t,-n), v); for(;; avma = av1) { GEN d = real_1(l1), p3 = gadd(q,mb); c = divur(5,q); if (expo(c)>= -1) c = real2n(-1, l1); p1 = subsr(1,divrr(x,q)); if (cmprr(c,p1)>0) c = p1; togglesign(c); gaffect(u,e); gaffect(v,f); av2 = avma; for(k=1;;k++, avma = av2) { GEN w = gadd(gmul(gaddgs(a,k-1),u), gmul(gaddgs(p3,1-k),v)); gmulz(divru(q,k),v, u); gaffect(gdivgs(w,k), v); mulrrz(d,c,d); gaddz(e,gmul(d,u),e); p1=gmul(d,v); gaddz(f,p1,f); if (gequal0(p1) || gexpo(p1) - gexpo(f) <= 1-prec2nbits(precision(p1))) break; } swap(e, u); swap(f, v); affrr(mulrr(q, addrs(c,1)), q); if (expo(subrr(q,x)) - expo(x) <= 1-prec2nbits(l)) break; } } else { GEN zz = invr(x), s = gen_1; togglesign(zz); /* -1/x */ zf = gpow(x,gneg_i(a),l1); T = gadd(gadd(P, gmulsg(n-1, S)), sqrs(n-1)); for (k=n-1; k>=0; k--) { p1 = gmul(T,divru(zz,k+1)); s = gaddsg(1, gmul(p1,s)); if (!k) break; T = gsubgs(gsub(T, S), 2*k-1); } u = gmul(s,zf); } gaffect(u,y); avma = av; return y; } /* incgam(0, x, prec) = eint1(x); typ(x) = t_REAL, x > 0 */ static GEN incgam_0(GEN x, GEN expx) { pari_sp av; long l = realprec(x), n, i; double mx = rtodbl(x), L = prec2nbits_mul(l,LOG2); GEN z; if (!mx) pari_err_DOMAIN("eint1", "x","=",gen_0, x); if (mx > L) { double m = (L + mx)/4; n = (long)(1+m*m/mx); av = avma; z = divsr(-n, addsr(n<<1,x)); for (i=n-1; i >= 1; i--) { z = divsr(-i, addrr(addsr(i<<1,x), mulur(i,z))); /* -1 / (2 + z + x/i) */ if ((i & 0x1ff) == 0) z = gerepileuptoleaf(av, z); } return divrr(addrr(real_1(l),z), mulrr(expx? expx: mpexp(x), x)); } else { long prec = l + nbits2extraprec((mx+log(mx))/LOG2); GEN S, t, H, run = real_1(prec); n = -prec2nbits(prec); x = rtor(x, prec); av = avma; S = z = t = H = run; for (i = 2; expo(t) - expo(S) >= n; i++) { H = addrr(H, divru(run,i)); /* H = sum_{k<=i} 1/k */ z = divru(mulrr(x,z), i); /* z = x^(i-1)/i! */ t = mulrr(z, H); S = addrr(S, t); if ((i & 0x1ff) == 0) gerepileall(av, 4, &z,&t,&S,&H); } return subrr(mulrr(x, divrr(S,expx? expx: mpexp(x))), addrr(mplog(x), mpeuler(prec))); } } /* incgam using the continued fraction. x a t_REAL or t_COMPLEX, mx ~ |x|. * Assume precision(s), precision(x) >= prec */ static GEN incgam_cf(GEN s, GEN x, double mx, long prec) { GEN x_s, S, y; long n, i; pari_sp av = avma, av2, avlim; double m; m = (prec2nbits_mul(prec,LOG2) + mx)/4; n = (long)(1+m*m/mx); if (typ(s) == t_INT) /* y = x^(s-1) exp(-x) */ y = gmul(gexp(gneg(x), prec), powgi(x,subis(s,1))); 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); 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(DEBUGMEM>1) pari_warn(warnmem,"incgam_cf"); S = gerepileupto(av2, S); } } return gerepileupto(av, gmul(y, gaddsg(1,S))); } /* use exp(-x) * (x^s/s) * sum_{k >= 0} x^k / prod(i=1, k, s+i) */ GEN incgamc(GEN s, GEN x, long prec) { GEN S, t, y; long l, n, i, ex; pari_sp av = avma, av2, avlim; if (typ(x) != t_REAL) x = gtofp(x, prec); if (gequal0(x)) return gcopy(x); l = precision(x); n = -prec2nbits(l)-1; ex = gexpo(x); if (ex > 0 && ex > gexpo(s)) { /* take cancellation into account */ long p = LOWDEFAULTPREC; double X = rtodbl(gabs(gtofp(x, p), p)); p = l + nbits2extraprec(X*log(X)); x = gtofp(x, p); if (isinexactreal(s)) s = gtofp(s, p); } av2 = avma; avlim = stack_lim(av2,3); 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(DEBUGMEM>1) pari_warn(warnmem,"incgamc"); gerepileall(av2, 2, &S, &t); } } if (typ(s)==t_INT) y = gmul(gexp(gneg(x), prec), powgi(x,s)); else y = gexp(gsub(gmul(s, glog(x, prec)), x), prec); return gerepileupto(av, gmul(gdiv(y,s), t)); } /* incgamma using asymptotic expansion: * exp(-x)x^(s-1)(1 + (s-1)/x + (s-1)(s-2)/x^2 + ...) */ static GEN incgam_asymp(GEN s, GEN x, long prec) { pari_sp av = avma, av2, lim; 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); q = gmul(gsubgs(s, 1), invx); S = gaddgs(q, 1); for (j = 2;; j++) { eq = gexpo(q); if (eq < esx) break; if ((j & 3) == 0) { /* guard against divergence */ if (eq > oldeq) { avma = av; return NULL; } /* regressing, abort */ oldeq = eq; } 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 (typ(s) == t_INT) /* exp(-x) x^(s-1) */ cox = gmul(gexp(gneg(x), prec), powgi(x, subis(s, 1))); else cox = gexp(gsub(gmul(gsubgs(s, 1), glog(x,prec)), x), prec); return gerepileupto(av, gmul(cox, S)); } static GEN gexp1(GEN x, long prec) { if (typ(x) != t_REAL) x = gtofp(x, prec); return mpexpm1(x); } /* assume s != 0 */ static GEN incgamspec(GEN s, GEN x, GEN g, long prec) { pari_sp av = avma; GEN q, S, cox, P, sk, S1, S2, S3, F2, F3, logx, mx; long esk, n, k = itos(ground(gneg(real_i(s)))); sk = gaddgs(s, k); logx = glog(x, prec); mx = gneg(x); cox = gexp(gadd(mx, gmul(s, logx)), prec); /* x^s exp(-x) */ if (k == 0) { S = gen_0; P = gen_1; } else { long j; q = ginv(s); S = q; P = s; for (j = 1; j < k; j++) { GEN sj = gaddgs(s, j); q = gmul(q, gdiv(x, sj)); S = gadd(S, q); P = gmul(P, sj); } S = gmul(S, gneg(cox)); } if (k && gequal0(sk)) return gerepileupto(av, gadd(S, gdiv(eint1(x, prec), P))); esk = gexpo(sk); if (esk > -7) { GEN a, b, PG = gmul(sk, P); if (g) g = gmul(g, PG); a = incgam0(gaddgs(sk,1), x, g, prec); b = gmul(gpowgs(x, k), cox); return gerepileupto(av, gadd(S, gdiv(gsub(a, b), PG))); } else if (2*esk > -prec2nbits(prec) - 4) { if (typ(sk) != t_REAL) sk = gtofp(sk, prec); S1 = gdiv(gexp1(glngamma(gaddgs(sk, 1), prec), prec), sk); F3 = gexp1(gmul(sk, logx), prec); F2 = gneg(gdiv(F3, sk)); F3 = gaddsg(1, F3); } else { GEN EUL = mpeuler(prec); S1 = gadd(negr(EUL), gmul(gdivgs(sk, 2), addrr(szeta(2,prec), sqrr(EUL)))); F2 = gmul(gneg(logx), gaddsg(1, gmul(gdivgs(sk, 2), logx))); F3 = gexp(gmul(sk, logx), prec); } S2 = gmul(F2, gadd(gexp(mx, prec), gdiv(incgamc(gaddgs(sk,1), x, prec), F3))); S3 = gdiv(x, gaddsg(1,sk)); q = x; n = 1; while (gexpo(q) > -prec2nbits(prec)) { n++; q = gmul(q, gdivgs(mx, n)); S3 = gadd(S3, gdiv(q, gaddsg(n, sk))); } return gerepileupto(av, gadd(S, gdiv(gadd(gadd(S1, S2), S3), P))); } #if 0 static long precision2(GEN x, GEN y) { long px = precision(x), py = precision(y); if (!px) return py; if (!py) return px; return minss(px, py); } #endif /* return |x| */ static double dblmodulus(GEN x) { if (typ(x) == t_COMPLEX) { double a = gtodouble(gel(x,1)); double b = gtodouble(gel(x,2)); return sqrt(a*a + b*b); } else return fabs(gtodouble(x)); } /* Driver routine. If g != NULL, assume that g=gamma(s,prec). */ GEN incgam0(GEN s, GEN x, GEN g, long prec) { pari_sp av; long E, es, l; double mx; GEN z, rs; if (gequal0(x)) return g? gcopy(g): ggamma(s,prec); if (gequal0(s)) return eint1(x, prec); av = avma; l = precision(s); if (!l) l = prec; E = prec2nbits(l) + 1; if (typ(x) != t_REAL) x = gtofp(x, l); /* avoid overflow in dblmodulus */ if (gexpo(x) > E) mx = E; else mx = dblmodulus(x); /* use asymptotic expansion */ if (2*mx > E) { z = incgam_asymp(s, x, l); if (z) return z; } /* use continued fraction */ if (12.1*mx > E) return incgam_cf(s, x, mx, l); rs = real_i(s); if (gsigne(rs) > 0 && gexpo(rs) >= -1) { /* use complementary incomplete gamma */ es = gexpo(s); if (es < 0) { l += nbits2extraprec(-es) + 1; s = gtofp(s, l); x = gtofp(x, l); } if (!g) g = ggamma(s,l); z = gsub(g, incgamc(s,x,l)); return gerepileupto(av, z); } /* use power series */ return gerepilecopy(av, incgamspec(s, x, g, l)); } GEN incgam(GEN s, GEN x, long prec) { return incgam0(s, x, NULL, prec); } /* x >= 0 a t_REAL */ GEN mpeint1(GEN x, GEN expx) { GEN z = cgetr(lg(x)); pari_sp av = avma; affrr(incgam_0(x, expx), z); avma = av; return z; } static GEN cxeint1(GEN x, long prec) { pari_sp av = avma; GEN q, S1, S2, S3, logx, mx; long n, E = prec2nbits(prec), ex = gexpo(x); if (ex > E || dblmodulus(x) > 3*E/4) { GEN z = incgam_asymp(gen_0, x, prec); if (z) return z; } logx = glog(x, prec); S1 = negr(mpeuler(prec)); S2 = gneg(logx); if (ex > 0) { /* take cancellation into account, log2(\sum |x|^n / n!) = |x| / log(2) */ long p = LOWDEFAULTPREC; double X = rtodbl(gabs(gtofp(x, p), p)); x = gtofp(x, prec + nbits2extraprec(X / LOG2)); } q = S3 = x; n = 1; mx = gneg(x); while (gexpo(q) > -E) { n++; q = gmul(q, gdivgs(mx, n)); S3 = gadd(S3, gdivgs(q, n)); } return gerepileupto(av, gadd(gadd(S1, S2), S3)); } GEN eint1(GEN x, long prec) { long l, n, i; pari_sp av; GEN p1, t, S, y, res; if (typ(x) != t_REAL) { x = gtofp(x, prec); if (typ(x) != t_REAL) return cxeint1(x, prec); } if (signe(x) >= 0) return mpeint1(x,NULL); /* rewritten from code contributed by Manfred Radimersky */ res = cgetg(3, t_COMPLEX); av = avma; l = lg(x); n = prec2nbits(l); y = negr(x); if (cmprs(y, (3*n)/4) < 0) { p1 = t = S = y; for (i = 2; expo(t) - expo(S) >= -n; i++) { p1 = mulrr(y, divru(p1, i)); /* (-x)^i/i! */ t = divru(p1, i); S = addrr(S, t); } y = addrr(S, addrr(logr_abs(x), mpeuler(l))); } else { /* asymptotic expansion */ p1 = t = invr(y); S = addrs(t, 1); for (i = 2; expo(t) - expo(S) >= -n; i++) { t = mulrr(p1, mulru(t, i)); S = addrr(S, t); } y = mulrr(S, mulrr(p1, mpexp(y))); } gel(res, 1) = gerepileuptoleaf(av, negr(y)); y = mppi(prec); setsigne(y, -1); gel(res, 2) = y; return res; } GEN veceint1(GEN C, GEN nmax, long prec) { if (!nmax) return eint1(C,prec); if (typ(nmax) != t_INT) pari_err_TYPE("veceint1",nmax); if (typ(C) != t_REAL) { C = gtofp(C, prec); if (typ(C) != t_REAL) pari_err_TYPE("veceint1",C); } if (signe(C) <= 0) pari_err_DOMAIN("veceint1", "argument", "<=", gen_0,C); return mpveceint1(C, NULL, itos(nmax)); } /* j > 0, a t_REAL. Return sum_{m >= 0} a^m / j(j+1)...(j+m)). * Stop when expo(summand) < E; note that s(j-1) = (a s(j) + 1) / (j-1). */ static GEN mp_sum_j(GEN a, long j, long E, long prec) { pari_sp av = avma; GEN q = divru(real_1(prec), j), s = q; long m; for (m = 0;; m++) { if (expo(q) < E) break; q = mulrr(q, divru(a, m+j)); s = addrr(s, q); } return gerepileuptoleaf(av, s); } /* Return the s_a(j), j <= J */ static GEN sum_jall(GEN a, long J, long prec) { GEN s = cgetg(J+1, t_VEC); long j, E = -bit_accuracy(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); return s; } /* T a dense t_POL with t_REAL coeffs. Return T(n) [faster than poleval] */ static GEN rX_s_eval(GEN T, long n) { long i = lg(T)-1; GEN c = gel(T,i); for (i--; i>=2; i--) c = gadd(mulrs(c,n),gel(T,i)); return c; } /* C>0 t_REAL, eC = exp(C). Return eint1(n*C) for 1<=n<=N. Absolute accuracy */ GEN mpveceint1(GEN C, GEN eC, long N) { const long prec = realprec(C); long Nmin = 15; /* >= 1. E.g. between 10 and 30, but little effect */ GEN en, v, w = cgetg(N+1, t_VEC); pari_sp av0; double DL; long n, j, jmax, jmin; if (!N) return w; for (n = 1; n <= N; n++) gel(w,n) = cgetr(prec); av0 = avma; if (N < Nmin) Nmin = N; if (!eC) eC = mpexp(C); en = eC; affrr(incgam_0(C, en), gel(w,1)); for (n = 2; n <= Nmin; n++) { pari_sp av2; en = mulrr(en,eC); /* exp(n C) */ av2 = avma; affrr(incgam_0(mulru(C,n), en), gel(w,n)); avma = av2; } if (Nmin == N) { avma = av0; return w; } DL = bit_accuracy_mul(prec, LOG2) + 5; jmin = ceil(DL/log(N)) + 1; jmax = ceil(DL/log(Nmin)) + 1; v = sum_jall(C, jmax, prec); en = powrs(eC, -N); /* exp(-N C) */ affrr(incgam_0(mulru(C,N), invr(en)), gel(w,N)); for (j = jmin, n = N-1; j <= jmax; j++) { long limN = maxss((long)ceil(exp(DL/j)), Nmin); GEN polsh; setlg(v, j+1); polsh = RgV_to_RgX_reverse(v, 0); for (; n >= limN; n--) { pari_sp av2 = avma; GEN S = divri(mulrr(en, rX_s_eval(polsh, -n)), powuu(n,j)); /* w[n+1] - exp(-n C) * polsh(-n) / (-n)^j */ GEN c = odd(j)? addrr(gel(w,n+1), S) : subrr(gel(w,n+1), S); affrr(c, gel(w,n)); avma = av2; en = mulrr(en,eC); /* exp(-n C) */ } } 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) { 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; pari_sp av = avma; { double t = exp(-2*PI*PI/D); /* ~exp(-2*h^2) */ v = 30; /* bits that fit in both long and double mantissa */ u = (long)floor(t*(1L<= 0) { if (cmprs(xr, 1) > 0) /* use numerical integration */ z = cxerfc_r1(x, prec); else { /* erfc(x) = incgam(1/2,x^2)/sqrt(Pi) */ GEN sqrtpi = sqrtr(mppi(prec)); z = incgam0(ghalf, gsqr(x), sqrtpi, prec); z = gdiv(z, sqrtpi); } } else { /* erfc(-x)=2-erfc(x) */ /* FIXME could decrease prec long size = nbits2extraprec(ceil((pow(rtodbl(gimag(x)),2)-pow(rtodbl(greal(x)),2))/LOG2))); prec = size > 0 ? prec : prec + size; */ /* NOT gsubsg(2, ...) : would create a result of * huge accuracy if re(x)>>1, rounded to 2 by subsequent affc_fixlg... */ z = gsub(real2n(1,prec+EXTRAPRECWORD), gerfc(gneg(x), prec)); } avma = av; return affc_fixlg(z, res); } /***********************************************************************/ /** **/ /** FONCTION ZETA DE RIEMANN **/ /** **/ /***********************************************************************/ static const double log2PI = 1.83787706641; static double get_xinf(double beta) { const double maxbeta = 0.06415003; /* 3^(-2.5) */ double x0, y0, x1; if (beta < maxbeta) return beta + pow(3*beta, 1.0/3.0); x0 = beta + PI/2.0; for(;;) { y0 = x0*x0; x1 = (beta+atan(x0)) * (1+y0) / y0 - 1/x0; if (0.99*x0 < x1) return x1; x0 = x1; } } /* optimize for zeta( s + it, prec ), assume |s-1| > 0.1 * (if gexpo(u = s-1) < -5, we use the functional equation s->1-s) */ static void optim_zeta(GEN S, long prec, long *pp, long *pn) { double s, t, alpha, beta, n, B; long p; if (typ(S) == t_REAL) { s = rtodbl(S); t = 0.; } else { s = rtodbl(gel(S,1)); t = fabs( rtodbl(gel(S,2)) ); } B = prec2nbits_mul(prec, LOG2); if (s > 0 && !t) /* positive real input */ { beta = B + 0.61 + s*(log2PI - log(s)); if (beta > 0) { p = (long)ceil(beta / 2.0); n = fabs(s + 2*p-1)/(2*PI); } else { p = 0; n = exp((B - LOG2) / s); } } else if (s <= 0 || t < 0.01) /* s < 0 may occur if s ~ 0 */ { /* TODO: the crude bounds below are generally valid. Optimize ? */ double l,l2, la = 1.; /* heuristic */ double rlog, ilog; dcxlog(s-1,t, &rlog,&ilog); l2 = (s - 0.5)*rlog - t*ilog; /* = Re( (S - 1/2) log (S-1) ) */ l = (B - l2 + s*log2PI) / (2. * (1.+ log((double)la))); 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; } else { double sn = dabs(s, t), L = log(sn/s); alpha = B - 0.39 + L + s*(log2PI - log(sn)); beta = (alpha+s)/t - atan(s/t); p = 0; if (beta > 0) { beta = 1.0 - s + t * get_xinf(beta); if (beta > 0) p = (long)ceil(beta / 2.0); } else if (s < 1.0) p = 1; n = p? dabs(s + 2*p-1, t) / (2*PI) : exp((B-LOG2+L) / s); } *pp = p; *pn = (long)ceil(n); if (*pp < 0 || *pn < 0) pari_err_OVERFLOW("zeta"); if (DEBUGLEVEL) err_printf("lim, nn: [%ld, %ld]\n", *pp, *pn); } /* 1/zeta(n) using Euler product. Assume n > 0. * if (lba != 0) it is log(prec2nbits) we _really_ require */ GEN inv_szeta_euler(long n, double lba, long prec) { GEN z, res; pari_sp av, av2, avlim; double A, D; ulong p, lim; forprime_t S; if (n > prec2nbits(prec)) return real_1(prec); if (!lba) lba = prec2nbits_mul(prec, LOG2); D = exp((lba - log(n-1)) / (n-1)); 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); 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); GEN h; if (l < 3) l = 3; else if (l > prec) l = prec; h = divrr(z, rpowuu(p, (ulong)n, l)); z = subrr(z, h); if (low_stack(avlim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim); z = gerepileuptoleaf(av2, z); } } affrr(z, res); avma = av; return res; } /* assume n even > 0, if iz != NULL, assume iz = 1/zeta(n) */ GEN bernreal_using_zeta(long n, GEN iz, long prec) { long l = prec+EXTRAPRECWORD; GEN z; if (!iz) iz = inv_szeta_euler(n, 0., l); z = divrr(mpfactr(n, l), mulrr(powru(Pi2n(1, l), n), iz)); shiftr_inplace(z, 1); /* 2 * n! * zeta(n) / (2Pi)^n */ if ((n & 3) == 0) setsigne(z, -1); return z; } /* assume n even > 0. Faster than standard bernfrac for n >= 6 */ GEN bernfrac_using_zeta(long n) { pari_sp av = avma; GEN iz, a, d, D = divisorsu(n >> 1); long i, prec, l = lg(D); double t, u; d = utoipos(6); /* 2 * 3 */ for (i = 2; i < l; i++) /* skip 1 */ { /* Clausen - von Staudt */ ulong p = 2*D[i] + 1; if (uisprime(p)) d = muliu(d, p); } /* 1.712086 = ??? */ t = log( gtodouble(d) ) + (n + 0.5) * log(n) - n*(1+log2PI) + 1.712086; u = t / LOG2; prec = nbits2prec((long)ceil(u) + BITS_IN_LONG); iz = inv_szeta_euler(n, t, prec); a = roundr( mulir(d, bernreal_using_zeta(n, iz, prec)) ); 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) { if (bernzone && (k>>1)+1 < lg(bernzone)) { GEN B = gel(bernzone,(k>>1)+1); if (typ(B) != t_REAL || realprec(B) >= prec) return 0; } return (k * (log(k) - 2.83) > prec2nbits_mul(prec, LOG2)); } /* Return B_n */ GEN bernreal(long n, long prec) { GEN B, storeB; long k, lbern; if (n < 0) pari_err_DOMAIN("bernreal", "index", "<", gen_0, stoi(n)); if (n == 0) return real_1(prec); if (n == 1) return real_m2n(-1,prec); /*-1/2*/ if (odd(n)) return real_0(prec); k = n >> 1; if (!bernzone && k < 100) mpbern(k, prec); lbern = bernzone? lg(bernzone): 0; if (k < lbern) { B = gel(bernzone,k); if (typ(B) != t_REAL) return fractor(B, prec); if (realprec(B) >= prec) return rtor(B, prec); } /* not cached, must compute */ if (n * log(n) > prec2nbits_mul(prec, LOG2)) B = storeB = bernreal_using_zeta(n, NULL, prec); else { storeB = bernfrac_using_zeta(n); B = fractor(storeB, prec); } if (k < lbern) { GEN old = gel(bernzone, k); gel(bernzone, k) = gclone(storeB); gunclone(old); } return B; } /* assume k != 1 */ GEN szeta(long k, long prec) { pari_sp av = avma; GEN y; /* treat trivial cases */ if (!k) { y = real2n(-1, prec); setsigne(y,-1); return y; } if (k < 0) { if ((k&1) == 0) return gen_0; /* the one value such that k < 0 and 1 - k < 0, due to overflow */ if ((ulong)k == (HIGHBIT | 1)) pari_err_OVERFLOW("zeta [large negative argument]"); k = 1-k; y = bernreal(k, prec); togglesign(y); return gerepileuptoleaf(av, divru(y, k)); } if (k > prec2nbits(prec)+1) return real_1(prec); if ((k&1) == 0) { if (bernreal_use_zeta(k, prec)) y = invr( inv_szeta_euler(k, 0, prec) ); else { y = mulrr(powru(Pi2n(1, prec), k), bernreal(k, prec)); y = divrr(y, mpfactr(k,prec)); setsigne(y, 1); shiftr_inplace(y, -1); } return gerepileuptoleaf(av, y); } /* k > 1 odd */ if (k * log(k) > prec2nbits_mul(prec, LOG2)) /* heuristic */ return gerepileuptoleaf(av, invr( inv_szeta_euler(k, 0, prec) )); return szeta_odd(k, prec); } /* return n^-s, n > 1 odd. tab[q] := q^-s, q prime power */ static GEN n_s(ulong n, GEN *tab) { GEN x, f = factoru(n), P = gel(f,1), E = gel(f,2); long i, l = lg(P); x = tab[ upowuu(P[1], E[1]) ]; for (i = 2; i < l; i++) x = gmul(x, tab[ upowuu(P[i], E[i]) ]); return x; } /* s0 a t_INT, t_REAL or t_COMPLEX. * If a t_INT, assume it's not a trivial case (i.e we have s0 > 1, odd) * */ GEN czeta(GEN s0, long prec) { GEN s, u, a, y, res, tes, sig, tau, invn2, unr; GEN sim, *tab, tabn, funeq_factor = NULL; ulong p, sqn; long i, nn, lim, lim2, ct; pari_sp av0 = avma, av, av2, avlim; pari_timer T; forprime_t S; if (DEBUGLEVEL>2) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); if (typ(s0) == t_INT) return gerepileupto(av, gzeta(s0, prec)); if (!signe(tau)) /* real */ { long e = expo(sig); if (e >= -5 && (signe(sig) <= 0 || e < -1)) { /* s < 1/2 */ s = subsr(1, s); funeq_factor = gen_1; } } else { u = gsubsg(1, s); /* temp */ if (gexpo(u) < -5 || ((signe(sig) <= 0 || expo(sig) < -1) && gexpo(s) > -5)) { /* |1-s| < 1/32 || (real(s) < 1/2 && |imag(s)| > 1/32) */ s = u; funeq_factor = gen_1; } } if (funeq_factor) { /* s <--> 1-s */ GEN t; sig = real_i(s); /* Gamma(s) (2Pi)^-s 2 cos(Pi s/2) */ t = gmul(ggamma(gprec_w(s,prec),prec), gpow(Pi2n(1,prec), gneg(s), prec)); funeq_factor = gmul2n(gmul(t, gcos(gmul(Pi2n(-1,prec),s), prec)), 1); } if (gcmpgs(sig, prec2nbits(prec) + 1) > 0) { /* zeta(s) = 1 */ if (!funeq_factor) { avma = av0; return real_1(prec); } return gerepileupto(av0, funeq_factor); } optim_zeta(s, prec, &lim, &nn); u_forprime_init(&S, 2, nn-1); incrprec(prec); unr = real_1(prec); /* one extra word of precision */ tab = (GEN*)cgetg(nn, t_VEC); /* table of q^(-s), q = p^e */ { /* general case */ GEN ms = gneg(s), rp = cgetr(prec); while ((p = u_forprime_next(&S))) { affur(p, rp); tab[p] = gexp(gmul(ms, mplog(rp)), prec); } affsr(nn, rp); a = gexp(gmul(ms, mplog(rp)), prec); } sqn = (ulong)sqrt(nn-1.); u_forprime_init(&S, 3, sqn); /* fill in odd prime powers */ while ((p = u_forprime_next(&S))) { ulong oldq = p, q = p*p; while (q<(ulong)nn) { tab[q] = gmul(tab[p], tab[oldq]); oldq = q; q *= p; } } if (DEBUGLEVEL>2) timer_printf(&T,"tab[q^-s] from 1 to N-1"); tabn = cgetg(nn, t_VECSMALL); ct = 0; for (i = nn-1; i; i>>=1) tabn[++ct] = (i-1)>>1; sim = y = unr; /* compute 1 + 2^-s + ... + n^-s = P(2^-s) using Horner's scheme */ for (i=ct; i > 1; i--) { long j; av2 = avma; for (j=tabn[i]+1; j<=tabn[i-1]; j++) sim = gadd(sim, n_s(2*j+1, tab)); sim = gerepileupto(av2, sim); y = gadd(sim, gmul(tab[2],y)); } y = gadd(y, gmul2n(a,-1)); if (DEBUGLEVEL>2) timer_printf(&T,"sum from 1 to N-1"); invn2 = divri(unr, mulss(nn,nn)); lim2 = lim<<1; mpbern(lim,prec); tes = bernreal(lim2, prec); { GEN s1, s2, s3, s4, s5; s1 = gsub(gmul2n(s,1), unr); s2 = gmul(s, gsub(s,unr)); s3 = gmul2n(invn2,3); av2 = avma; avlim = stack_lim(av2,3); 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) { 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(DEBUGMEM>1) pari_warn(warnmem,"czeta"); gerepileall(av2,3, &tes,&s5,&s4); } } u = gmul(gmul(tes,invn2), gmul2n(s2, -1)); tes = gmulsg(nn, gaddsg(1, u)); } if (DEBUGLEVEL>2) timer_printf(&T,"Bernoulli sum"); /* y += tes n^(-s) / (s-1) */ y = gadd(y, gmul(tes, gdiv(a, gsub(s, unr)))); if (funeq_factor) y = gmul(y, funeq_factor); avma = av; return affc_fixlg(y,res); } /* return P mod x^n where P is polynomial in x */ static GEN pol_mod_xn(GEN P, long n) { long j, l = lg(P), N = n+2; GEN R; if (l > N) l = N; R = cgetg(N, t_POL); R[1] = evalvarn(0); for (j = 2; j < l; j++) gel(R,j) = gel(P,j); return normalizepol_lg(R, n+2); } /* compute the values of the twisted partial zeta function Z_f(a, c, s) for a in va */ 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")); GEN cyc, psm, rep, eta, etaf; cyc = gdiv(gsubgs(gpowgs(y, c), 1), gsubgs(y, 1)); psm = polsym(cyc, degpol(cyc) - 1); eta = mkpolmod(y, cyc); etaf = gpowgs(eta,f); av = avma; Ax = gsubgs(gpowgs(gaddgs(x, 1), f), 1); Ax = gdiv(gmul(Ax, etaf), gsubsg(1, etaf)); Ax = gerepileupto(av, RgX_to_FqX(Ax, cyc, q)); Cx = Ax; Bx = gen_1; av = avma; lim = stack_lim(av, 1); for (j = 2; j <= N; j++) { Bx = gadd(Bx, Cx); Bx = FpXQX_red(Bx, cyc, q); 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(DEBUGMEM>1) pari_warn(warnmem, "twistpartialzeta (1), j = %ld/%ld", j, N); gerepileall(av, 2, &Cx, &Bx); } } Bx = lift(gmul(ginv(gsubsg(1, etaf)), Bx)); 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); for (j = lva; j > 1; j--) { GEN Ex; long e = va[j] - va[j-1]; if (e == 1) Ex = Cx; else /* e is very small in general and actually very rarely different to 1, it is always 1 for zetap (so it should be OK not to store 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(DEBUGMEM>1) pari_warn(warnmem, "twistpartialzeta (2), j = %ld/%ld", lva-j, lva); Dx = gerepileupto(av2, FpXQX_red(Dx, cyc, q)); } } 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); 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(DEBUGMEM>1) pari_warn(warnmem, "twistpartialzeta (3), j = %ld/%ld", k, N); rep = gerepileupto(av2, rep); } } return rep; } #if 0 /* initialize the roots of unity for the computation of the Teichmuller character (also the values of f and c) */ GEN init_teich(ulong p, GEN q, long prec) { GEN vz, gp = utoipos(p); pari_sp av = avma; long j; if (p == 2UL) return NULL; else { /* primitive (p-1)-th root of 1 */ GEN z, z0 = Zp_sqrtnlift(gen_1, utoipos(p-1), pgener_Fp(gp), gp, prec); z = z0; vz = cgetg(p, t_VEC); for (j = 1; j < (long)p-2; j++) { gel(vz, umodiu(z, p)) = z; /* z = z0^i */ z = modii(mulii(z, z0), q); } gel(vz, umodiu(z, p)) = z; /* z = z0^(p-2) */ gel(vz,1) = gen_1; /* z0^(p-1) */ } return gerepileupto(av, gcopy(vz)); } /* compute phi^(m)_s(x); s must be an integer */ GEN phi_ms(ulong p, GEN q, long m, GEN s, long x, GEN vz) { long xp = x % p; GEN p1, p2; if (!xp) return gen_0; if (vz) p1 =gel(vz,xp); /* vz[x] = Teichmuller(x) */ else p1 = (x & 2)? gen_m1: gen_1; p1 = Fp_pow(p1, addis(s, m), q); p2 = Fp_pow(stoi(x), negi(s), q); return modii(mulii(p1,p2), q); } /* compute the first N coefficients of the Mahler expansion of phi^m_s skipping the first one (which is zero) */ 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; long k, j; av = avma; lim = stack_lim(av, 2); 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(DEBUGMEM>1) pari_warn(warnmem, "coeff_of_phi_ms (1), k = %ld/%ld", N-k, N); cff = gerepileupto(av, gcopy(cff)); } } for (j = N; j > 1; j--) { 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(DEBUGMEM>1) pari_warn(warnmem, "coeff_of_phi_ms (2), j = %ld/%ld", N-j, N); cff = gerepileupto(av, gcopy(cff)); } } for (k = 1; k < N; k++) for (j = N; j > k; j--) { 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(DEBUGMEM>1) pari_warn(warnmem, "coeff_of_phi_ms (3), (k,j) = (%ld,%ld)/%ld", k, N-j, N); cff = gerepileupto(av, gcopy(cff)); } } k = N; while(gequal0(gel(cff, k))) k--; setlg(cff, k+1); if (DEBUGLEVEL > 2) err_printf(" coeff_of_phi_ms: %ld coefficients kept out of %ld\n", k, N); return gerepileupto(av, cff); } static long valfact(long N, ulong p) { long f = 0; while (N > 1) { N /= p; f += N; } return f; } static long number_of_terms(ulong p, long prec) { long N, f; if (prec == 0) return p; N = (long)((p-1)*prec + (p>>1)*(log2(prec)/log2(p))); N = p*(N/p); f = valfact(N, p); while (f > prec) { N = p*(N/p) - 1; f -= u_lval(N+1, p); } while (f < prec) { N = p*(N/p+1); f += u_lval(N, p); } return N; } static GEN zetap(GEN s) { ulong p; long N, f, c, prec = precp(s); pari_sp av = avma; GEN gp, q, vz, is, cff, val, va, cft; if (valp(s) < 0) pari_err_DOMAIN("zetap", "v_p(s)", "<", gen_0, s); if (!prec) prec = 1; gp = gel(s,2); p = itou(gp); is = gtrunc(s); /* make s an integer */ N = number_of_terms(p, prec); q = powiu(gp, prec); /* initialize the roots of unity for the computation of the Teichmuller character (also the values of f and c) */ if (DEBUGLEVEL > 1) err_printf("zetap: computing (p-1)th roots of 1\n"); vz = init_teich(p, q, prec); if (p == 2UL) { f = 4; c = 3; } else { f = (long)p; c = 2; } /* compute the first N coefficients of the Mahler expansion of phi^(-1)_s skipping the first one (which is zero) */ if (DEBUGLEVEL > 1) err_printf("zetap: computing Mahler expansion of phi^(-1)_s\n"); cff = coeff_of_phi_ms(p, q, -1, is, N, vz); /* compute the coefficients of the power series corresponding to the twisted partial zeta function Z_f(a, c, s) for a in va */ /* The line below looks a bit stupid but it is to keep the possibility of later adding p-adic Dirichlet L-functions */ va = identity_perm(f - 1); if (DEBUGLEVEL > 1) err_printf("zetap: computing values of twisted partial zeta functions\n"); val = twistpartialzeta(q, f, c, va, cff); /* sum over all a's the coefficients of the twisted partial zeta functions and integrate */ if (DEBUGLEVEL > 1) err_printf("zetap: multiplying by correcting factor\n"); /* multiply by the corrective factor */ cft = gsubgs(gmulsg(c, phi_ms(p, q, -1, is, c, vz)), 1); val = gdiv(val, cft); /* adjust the precision and return */ return gerepileupto(av, cvtop(val, gp, prec)); } #else static GEN hurwitz_p(GEN cache, GEN s, GEN x, GEN p, long prec) { GEN S, x2, x2j, s_1 = gsubgs(s,1); long j, J = lg(cache)-2; x = ginv(gadd(x, zeropadic(p, prec))); x2 = gsqr(x); S = gmul2n(gmul(s_1, x), -1); x2j = gen_1; for (j = 0;; j++) { S = gadd(S, gmul(gel(cache, j+1), x2j)); if (j == J) break; x2j = gmul(x2, x2j); } return gmul(gdiv(S, s_1), Qp_exp(gmul(s_1, Qp_log(x)))); } static GEN init_cache(long J, GEN s) { GEN C = gen_1, cache = bernvec(J); long j; for (j = 1; j <= J; j++) { /* B_{2j} * binomial(1-s, 2j) */ GEN t = gmul(gaddgs(s, 2*j-3), gaddgs(s, 2*j-2)); C = gdiv(gmul(C, t), mulss(2*j, 2*j-1)); gel(cache, j+1) = gmul(gel(cache, j+1), C); } return cache; } static GEN zetap(GEN s) { pari_sp av = avma; GEN cache, S, gp = gel(s,2); ulong a, p = itou(gp); long J, prec = valp(s) + precp(s); if (prec <= 0) prec = 1; if (p == 2) { J = ((long)(1+ceil((prec+1.)/2))) >> 1; cache = init_cache(J, s); S = gmul2n(hurwitz_p(cache, s, gmul2n(gen_1, -2), gen_2, prec), -1); } else { J = (prec+2) >> 1; cache = init_cache(J, s); S = gen_0; for (a = 1; a <= (p-1)>>1; a++) S = gadd(S, hurwitz_p(cache, s, gdivsg(a, gp), gp, prec)); S = gdiv(gmul2n(S, 1), gp); } return gerepileupto(av, S); } #endif GEN gzeta(GEN x, long prec) { if (gequal1(x)) pari_err_DOMAIN("zeta", "argument", "=", gen_1, x); switch(typ(x)) { case t_INT: if (is_bigint(x)) { if (signe(x) > 0) return real_1(prec); if (signe(x) < 0 && mod2(x) == 0) return real_0(prec); pari_err_OVERFLOW("zeta [large negative argument]"); } return szeta(itos(x),prec); case t_REAL: case t_COMPLEX: return czeta(x,prec); case t_PADIC: return zetap(x); case t_SER: pari_err_IMPL("zeta(t_SER)"); } return trans_eval("zeta",gzeta,x,prec); } /***********************************************************************/ /** **/ /** FONCTIONS POLYLOGARITHME **/ /** **/ /***********************************************************************/ /* returns H_n = 1 + 1/2 + ... + 1/n, as a rational number (n "small") */ static GEN Harmonic(long n) { GEN h = gen_1; long i; for (i=2; i<=n; i++) h = gadd(h, mkfrac(gen_1, utoipos(i))); return h; } /* m >= 2. Validity domain contains | log |x| | < 5, best for |x| ~ 1. * Li_m(x = e^z) = sum_{n >= 0} zeta(m-n) z^n / n! * with zeta(1) := H_m - log(-z) */ static GEN cxpolylog(long m, GEN x, long prec) { long li, n; GEN z, h, q, s; int real; if (gequal1(x)) return szeta(m,prec); /* x real <= 1 ==> Li_m(x) real */ real = (typ(x) == t_REAL && (expo(x) < 0 || signe(x) <= 0)); z = glog(x,prec); /* n = 0 */ q = gen_1; s = szeta(m,prec); for (n=1; n < m-1; n++) { q = gdivgs(gmul(q,z),n); s = gadd(s, gmul(szeta(m-n,prec), real? real_i(q): q)); } /* n = m-1 */ q = gdivgs(gmul(q,z),n); /* multiply by "zeta(1)" */ h = gmul(q, gsub(Harmonic(m-1), glog(gneg_i(z),prec))); s = gadd(s, real? real_i(h): h); /* n = m */ q = gdivgs(gmul(q,z),m); s = gadd(s, gmul(szeta(0,prec), real? real_i(q): q)); /* n = m+1 */ q = gdivgs(gmul(q,z),m+1); s = gadd(s, gmul(szeta(-1,prec), real? real_i(q): q)); z = gsqr(z); li = -(prec2nbits(prec)+1); /* n = m+3, m+5, ...; note that zeta(- even integer) = 0 */ for(n = m+3;; n += 2) { GEN zet = szeta(m-n,prec); q = divgunu(gmul(q,z), n-1); s = gadd(s, gmul(zet, real? real_i(q): q)); if (gexpo(q) + expo(zet) < li) break; } return s; } static GEN polylog(long m, GEN x, long prec) { long l, e, i, G, sx; pari_sp av, av1, limpile; GEN X, Xn, z, p1, p2, y, res; if (m < 0) pari_err_DOMAIN("polylog", "index", "<", gen_0, stoi(m)); if (!m) return mkfrac(gen_m1,gen_2); if (gequal0(x)) return gcopy(x); if (m==1) { av = avma; return gerepileupto(av, gneg(glog(gsub(gen_1,x), prec))); } l = precision(x); if (!l) l = prec; res = cgetc(l); av = avma; x = gtofp(x, l+EXTRAPRECWORD); e = gexpo(gnorm(x)); if (!e || e == -1) { y = cxpolylog(m,x,prec); avma = av; return affc_fixlg(y, res); } X = (e > 0)? ginv(x): x; G = -prec2nbits(l); av1 = avma; limpile = stack_lim(av1,1); y = Xn = X; for (i=2; ; i++) { Xn = gmul(X,Xn); p2 = gdiv(Xn,powuu(i,m)); y = gadd(y,p2); if (gexpo(p2) <= G) break; if (low_stack(limpile, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"polylog"); gerepileall(av1,2, &y, &Xn); } } if (e < 0) { avma = av; return affc_fixlg(y, res); } sx = gsigne(imag_i(x)); if (!sx) { if (m&1) sx = gsigne(gsub(gen_1, real_i(x))); else sx = - gsigne(real_i(x)); } z = divri(mppi(l), mpfact(m-1)); setsigne(z, sx); z = mkcomplex(gen_0, z); if (m == 2) { /* same formula as below, written more efficiently */ y = gneg_i(y); if (typ(x) == t_REAL && signe(x) < 0) p1 = logr_abs(x); else p1 = gsub(glog(x,l), z); p1 = gmul2n(gsqr(p1), -1); /* = (log(-x))^2 / 2 */ p1 = gadd(p1, divru(sqrr(mppi(l)), 6)); p1 = gneg_i(p1); } else { GEN logx = glog(x,l), logx2 = gsqr(logx); p1 = mkfrac(gen_m1,gen_2); for (i=m-2; i>=0; i-=2) p1 = gadd(szeta(m-i,l), gmul(p1,gdivgs(logx2,(i+1)*(i+2)))); if (m&1) p1 = gmul(logx,p1); else y = gneg_i(y); p1 = gadd(gmul2n(p1,1), gmul(z,gpowgs(logx,m-1))); if (typ(x) == t_REAL && signe(x) < 0) p1 = real_i(p1); } y = gadd(y,p1); avma = av; return affc_fixlg(y, res); } GEN dilog(GEN x, long prec) { return gpolylog(2, x, prec); } /* x a floating point number, t_REAL or t_COMPLEX of t_REAL */ static GEN logabs(GEN x) { GEN y; if (typ(x) == t_COMPLEX) { y = logr_abs( cxnorm(x) ); shiftr_inplace(y, -1); } else y = logr_abs(x); return y; } static GEN polylogD(long m, GEN x, long flag, long prec) { long k, l, fl, m2; pari_sp av; GEN p1, p2, y; if (gequal0(x)) return gcopy(x); m2 = m&1; if (gequal1(x) && m>=2) return m2? szeta(m,prec): gen_0; av = avma; l = precision(x); if (!l) { l = prec; x = gtofp(x,l); } p1 = logabs(x); k = signe(p1); if (k > 0) { x = ginv(x); fl = !m2; } else { setabssign(p1); fl = 0; } /* |x| <= 1, p1 = - log|x| >= 0 */ p2 = gen_1; y = polylog(m,x,l); y = m2? real_i(y): imag_i(y); for (k=1; k=2) return m2? szeta(m,prec): gen_0; av = avma; l = precision(x); if (!l) { l = prec; x = gtofp(x,l); } p1 = logabs(x); if (signe(p1) > 0) { x = ginv(x); fl = !m2; setsigne(p1, -1); } else fl = 0; /* |x| <= 1 */ y = polylog(m,x,l); y = m2? real_i(y): imag_i(y); if (m==1) { shiftr_inplace(p1, -1); /* log |x| / 2 */ y = gadd(y, p1); } else { /* m >= 2, \sum_{0 <= k <= m} 2^k B_k/k! (log |x|)^k Li_{m-k}(x), with Li_0(x) := -1/2 */ GEN u, t; t = polylog(m-1,x,l); u = gneg_i(p1); /* u = 2 B1 log |x| */ y = gadd(y, gmul(u, m2?real_i(t):imag_i(t))); if (m > 2) { GEN p2; shiftr_inplace(p1, 1); /* p1 = 2log|x| <= 0 */ mpbern(m>>1, l); p1 = sqrr(p1); p2 = shiftr(p1,-1); for (k=2; k 2) p2 = divgunu(gmul(p2,p1),k-1); /* p2 = 2^k/k! log^k |x|*/ t = polylog(m-k,x,l); u = gmul(p2, bernreal(k, prec)); y = gadd(y, gmul(u, m2?real_i(t):imag_i(t))); } } } if (fl) y = gneg(y); return gerepileupto(av, y); } GEN gpolylog(long m, GEN x, long prec) { long i, n, v; pari_sp av = avma; GEN a, y, p1; if (m <= 0) { GEN t = mkpoln(2, gen_m1, gen_1); /* 1 - X */ p1 = pol_x(0); for (i=2; i <= -m; i++) p1 = RgX_shift_shallow(gadd(gmul(t,ZX_deriv(p1)), gmulsg(i,p1)), 1); p1 = gdiv(p1, gpowgs(t,1-m)); return gerepileupto(av, poleval(p1,x)); } switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: return polylog(m,x,prec); case t_POLMOD: return gerepileupto(av, polylogvec(m, polmod_to_embed(x, prec), prec)); case t_INTMOD: case t_PADIC: pari_err_IMPL( "padic polylogarithm"); case t_VEC: case t_COL: case t_MAT: return polylogvec(m, x, prec); default: av = avma; if (!(y = toser_i(x))) break; if (!m) { avma = av; return mkfrac(gen_m1,gen_2); } if (m==1) return gerepileupto(av, gneg( glog(gsub(gen_1,y),prec) )); if (gequal0(y)) return gerepilecopy(av, y); v = valp(y); if (v < 0) pari_err_DOMAIN("polylog","valuation", "<", gen_0, x); if (v > 0) { n = (lg(y)-3 + v) / v; a = zeroser(varn(y), lg(y)-2); for (i=n; i>=1; i--) a = gmul(y, gadd(a, powis(utoipos(i),-m))); } else { /* v == 0 */ long vy = varn(y); GEN a0 = polcoeff0(y, 0, -1), yprimeovery = gdiv(derivser(y), y); a = gneg( glog(gsub(gen_1,y), prec) ); for (i=2; i<=m; i++) a = gadd(gpolylog(i, a0, prec), integ(gmul(yprimeovery, a), vy)); } return gerepileupto(av, a); } pari_err_TYPE("gpolylog",x); return NULL; /* not reached */ } GEN polylog0(long m, GEN x, long flag, long prec) { switch(flag) { case 0: return gpolylog(m,x,prec); case 1: return polylogD(m,x,0,prec); case 2: return polylogD(m,x,1,prec); case 3: return polylogP(m,x,prec); default: pari_err_FLAG("polylog"); } return NULL; /* not reached */ } static GEN upper_half(GEN x, long *prec) { long tx = typ(x), l; if (tx == t_QUAD) { x = quadtofp(x, *prec); tx = typ(x); } switch(tx) { case t_COMPLEX: if (gsigne(gel(x,2)) > 0) break; /*fall through*/ case t_REAL: case t_INT: case t_FRAC: pari_err_DOMAIN("modular function", "Im(argument)", "<=", gen_0, x); default: pari_err_TYPE("modular function", x); } l = precision(x); if (l) *prec = l; return x; } /* sqrt(3)/2 */ static GEN sqrt32(long prec) { GEN z = sqrtr_abs(stor(3,prec)); setexpo(z, -1); return z; } /* exp(i x), x = k pi/12 */ static GEN e12(ulong k, long prec) { int s, sPi, sPiov2; GEN z, t; k %= 24; if (!k) return gen_1; if (k == 12) return gen_m1; if (k >12) { s = 1; k = 24 - k; } else s = 0; /* x -> 2pi - x */ if (k > 6) { sPi = 1; k = 12 - k; } else sPi = 0; /* x -> pi - x */ if (k > 3) { sPiov2 = 1; k = 6 - k; } else sPiov2 = 0; /* x -> pi/2 - x */ z = cgetg(3, t_COMPLEX); switch(k) { case 0: gel(z,1) = icopy(gen_1); gel(z,2) = gen_0; break; case 1: t = gmul2n(addrs(sqrt32(prec), 1), -1); gel(z,1) = sqrtr(t); gel(z,2) = gmul2n(invr(gel(z,1)), -2); break; case 2: gel(z,1) = sqrt32(prec); gel(z,2) = real2n(-1, prec); break; case 3: gel(z,1) = sqrtr_abs(real2n(-1,prec)); gel(z,2) = rcopy(gel(z,1)); break; } if (sPiov2) swap(gel(z,1), gel(z,2)); if (sPi) togglesign(gel(z,1)); if (s) togglesign(gel(z,2)); return z; } /* z a t_FRAC */ static GEN eiPi_frac(GEN z, long prec) { GEN n, d; ulong q, r; n = gel(z,1); d = gel(z,2); q = udivui_rem(12, d, &r); if (!r) /* relatively frequent case */ return e12(q * umodiu(n, 24), prec); n = centermodii(n, shifti(d,1), d); return expIr(divri(mulri(mppi(prec), n), d)); } /* exp(i Pi z), z a t_INT or t_FRAC */ static GEN exp_IPiQ(GEN z, long prec) { if (typ(z) == t_INT) return mpodd(z)? gen_m1: gen_1; return eiPi_frac(z, prec); } /* z a t_COMPLEX */ static GEN exp_IPiC(GEN z, long prec) { GEN r, x = gel(z,1), y = gel(z,2); GEN pi, mpi = mppi(prec); togglesign(mpi); /* mpi = -Pi */ r = gexp(gmul(mpi, y), prec); switch(typ(x)) { case t_INT: if (mpodd(x)) togglesign(r); return r; case t_FRAC: return gmul(r, eiPi_frac(x, prec)); default: pi = mpi; togglesign(mpi); /* pi = Pi */ return gmul(r, expIr(gmul(pi, x))); } } static GEN qq(GEN x, long prec) { long tx = typ(x); GEN y; if (is_scalar_t(tx)) { if (tx == t_PADIC) return x; x = upper_half(x, &prec); return exp_IPiC(gmul2n(x,1), prec); /* e(x) */ } if (! ( y = toser_i(x)) ) pari_err_TYPE("modular function", x); return y; } /* return (y * X^d) + x. Assume d > 0, x != 0, valp(x) = 0 */ static GEN ser_addmulXn(GEN y, GEN x, long d) { long i, lx, ly, l = valp(y) + d; /* > 0 */ GEN z; lx = lg(x); ly = lg(y) + l; if (lx < ly) ly = lx; if (l > lx-2) return gcopy(x); z = cgetg(ly,t_SER); for (i=2; i<=l+1; i++) gel(z,i) = gel(x,i); for ( ; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i-l)); z[1] = x[1]; return z; } /* q a t_POL */ static GEN inteta_pol(GEN q, long v, long l) { pari_sp av = avma, lim = stack_lim(av, 1); GEN qn, ps, y; ulong vps, vqn, n; y = qn = ps = pol_1(0); vps = vqn = 0; for(n = 0;; n++) { /* qn = q^n, ps = (-1)^n q^(n(3n+1)/2), * vps, vqn valuation of ps, qn HERE */ pari_sp av2 = avma; ulong vt = vps + 2*vqn + v; /* valuation of t at END of loop body */ long k1, k2; GEN t; vqn += v; vps = vt + vqn; /* valuation of qn, ps at END of body */ k1 = l-2 + v - vt + 1; 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 = RgX_mul(ps,t); t = RgX_modXn_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); if (k2 <= 0) break; qn = RgX_mul(qn,q); ps = RgX_mul(t,qn); ps = RgX_modXn_shallow(ps, k2); y = addmulXn(ps, y, vps); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"eta, n = %ld", n); gerepileall(av, 3, &y, &qn, &ps); } } setvarn(y, varn(q)); return RgX_to_ser(y, l+v); } static GEN inteta(GEN q) { long tx = typ(q); GEN ps, qn, y; y = gen_1; qn = gen_1; ps = gen_1; if (tx==t_PADIC) { if (valp(q) <= 0) pari_err_DOMAIN("eta", "v_p(q)", "<=",gen_0,q); for(;;) { GEN t = gneg_i(gmul(ps,gmul(q,gsqr(qn)))); y = gadd(y,t); qn = gmul(qn,q); ps = gmul(t,qn); t = y; y = gadd(y,ps); if (gequal(t,y)) return y; } } if (tx == t_SER) { ulong vps, vqn; long l = lg(q), v, n; pari_sp av, lim; v = valp(q); /* handle valuation separately to avoid overflow */ if (v <= 0) pari_err_DOMAIN("eta", "v_p(q)", "<=",gen_0,q); y = ser2pol_i(q, l); /* t_SER inefficient when input has low degree */ 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); setvalp(q, 0); y = scalarser(gen_1, varn(q), l+v); vps = vqn = 0; for(n = 0;; n++) { /* qn = q^n, ps = (-1)^n q^(n(3n+1)/2) */ ulong vt = vps + 2*vqn + v; long k; GEN t; t = gneg_i(gmul(ps,gmul(q,gsqr(qn)))); /* t = (-1)^(n+1) q^(n(3n+1)/2 + 2n+1) */ y = ser_addmulXn(t, y, vt); qn = gmul(qn,q); ps = gmul(t,qn); vqn += v; vps = vt + vqn; k = l+v - vps; if (k <= 2) return y; y = ser_addmulXn(ps, y, vps); setlg(q, k); setlg(qn, k); setlg(ps, k); if (low_stack(lim, stack_lim(av,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"eta"); gerepileall(av, 3, &y, &qn, &ps); } } } { long l; /* gcc -Wall */ pari_sp av = avma, lim = stack_lim(av, 3); l = -prec2nbits(precision(q)); for(;;) { GEN t = gneg_i(gmul(ps,gmul(q,gsqr(qn)))); /* qn = q^n * ps = (-1)^n q^(n(3n+1)/2) * t = (-1)^(n+1) q^(n(3n+1)/2 + 2n+1) */ 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(DEBUGMEM>1) pari_warn(warnmem,"eta"); gerepileall(av, 3, &y, &qn, &ps); } } } } GEN eta(GEN x, long prec) { pari_sp av = avma; GEN z = inteta( qq(x,prec) ); if (typ(z) == t_SER) return gerepilecopy(av, z); return gerepileupto(av, z); } /* s(h,k) = sum(n = 1, k-1, (n/k)*(frac(h*n/k) - 1/2)) * Knuth's algorithm. h integer, k integer > 0, (h,k) = 1 */ GEN 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) { ulong kk = k[2], hh = umodiu(h, kk); long s1, s2; GEN v; if (signe(k) < 0) { k = negi(k); hh = Fl_neg(hh, kk); } v = u_sumdedekind_coprime(hh, kk); s1 = v[1]; s2 = v[2]; return gerepileupto(av, gdiv(addis(mulis(k,s1), s2), muluu(12, kk))); } s = 1; s1 = gen_0; p = gen_1; pp = gen_0; s2 = h = modii(h, k); while (signe(h)) { GEN r, nexth, a = dvmdii(k, h, &nexth); if (is_pm1(h)) s2 = s == 1? addii(s2, p): subii(s2, p); s1 = s == 1? addii(s1, a): subii(s1, a); s = -s; k = h; h = nexth; r = addii(mulii(a,p), pp); pp = p; p = r; } /* at this point p = original k */ if (s == -1) s1 = subis(s1, 3); return gerepileupto(av, gdiv(addii(mulii(p,s1), s2), muliu(p,12))); } /* as above, for ulong arguments. * k integer > 0, 0 <= h < k, (h,k) = 1. Returns [s1,s2] such that * s(h,k) = (s2 + k s1) / (12k). Requires max(h + k/2, k) < LONG_MAX * to avoid overflow, in particular k <= LONG_MAX * 2/3 is fine */ GEN u_sumdedekind_coprime(long h, long k) { long s = 1, s1 = 0, s2 = h, p = 1, pp = 0; while (h) { long r, nexth = k % h, a = k / h; /* a >= 1, a >= 2 if h = 1 */ if (h == 1) s2 += p * s; /* occurs exactly once, last step */ s1 += a * s; s = -s; k = h; h = nexth; r = a*p + pp; pp = p; p = r; /* p >= pp >= 0 */ } /* in the above computation, p increases from 1 to original k, * -k/2 <= s2 <= h + k/2, and |s1| <= k */ if (s < 0) s1 -= 3; /* |s1| <= k+3 ? */ /* But in fact, |s2 + p s1| <= k^2 + 1/2 - 3k; if (s < 0), we have * |s2| <= k/2 and it follows that |s1| < k here as well */ /* p = k; s(h,k) = (s2 + p s1)/12p. */ return mkvecsmall2(s1, s2); } GEN sumdedekind(GEN h, GEN k) { pari_sp av = avma; GEN d; if (typ(h) != t_INT) pari_err_TYPE("sumdedekind",h); if (typ(k) != t_INT) pari_err_TYPE("sumdedekind",k); d = gcdii(h,k); if (!is_pm1(d)) { h = diviiexact(h, d); k = diviiexact(k, d); } return gerepileupto(av, sumdedekind_coprime(h,k)); } /* eta(x); assume Im x >> 0 (e.g. x in SL2's standard fundamental domain) */ static GEN eta_reduced(GEN x, long prec) { GEN z = exp_IPiC(gdivgs(x, 12), prec); /* e(x/24) */ if (24 * gexpo(z) >= -prec2nbits(prec)) z = gmul(z, inteta( gpowgs(z,24) )); return z; } /* x = U.z (flag = 1), or x = U^(-1).z (flag = 0) * Return [s,t] such that eta(z) = eta(x) * sqrt(s) * exp(I Pi t) */ static GEN eta_correction(GEN x, GEN U, long flag) { GEN a,b,c,d, s,t; long sc; a = gcoeff(U,1,1); b = gcoeff(U,1,2); c = gcoeff(U,2,1); d = gcoeff(U,2,2); /* replace U by U^(-1) */ if (flag) { swap(a,d); togglesign_safe(&b); togglesign_safe(&c); } sc = signe(c); if (!sc) { if (signe(d) < 0) togglesign_safe(&b); s = gen_1; t = gdivgs(utoi(umodiu(b, 24)), 12); } else { if (sc < 0) { togglesign_safe(&a); togglesign_safe(&b); togglesign_safe(&c); togglesign_safe(&d); } /* now c > 0 */ s = mulcxmI(gadd(gmul(c,x), d)); t = gadd(gdiv(addii(a,d),muliu(c,12)), sumdedekind_coprime(negi(d),c)); /* correction : exp(I Pi (((a+d)/12c) + s(-d,c)) ) sqrt(-i(cx+d)) */ } return mkvec2(s, t); } /* returns the true value of eta(x) for Im(x) > 0, using reduction to * standard fundamental domain */ GEN trueeta(GEN x, long prec) { pari_sp av = avma; GEN U, st, s, t; if (!is_scalar_t(typ(x))) pari_err_TYPE("trueeta",x); x = upper_half(x, &prec); x = redtausl2(x, &U); st = eta_correction(x, U, 1); x = eta_reduced(x, prec); s = gel(st, 1); t = gel(st, 2); x = gmul(x, exp_IPiQ(t, prec)); if (s != gen_1) x = gmul(x, gsqrt(s, prec)); return gerepileupto(av, x); } GEN eta0(GEN x, long flag,long prec) { return flag? trueeta(x,prec): eta(x,prec); } #if 0 /* U = [a,b;c,d], return c*z +d */ static GEN aut_factor(GEN U, GEN z) { GEN c = gcoeff(U,2,1), d = gcoeff(U,2,2); return signe(c)? gadd(gmul(c,z), d): d; } #endif /* j(q) = \sum_{n >= -1} c(n)q^n, * \sum_{n = -1}^{N-1} c(n) (-10n \sigma_3(N-n) + 21 \sigma_5(N-n)) * = c(N) (N+1)/24 */ static GEN ser_j(long prec) { GEN j, J, K = mkvecsmall2(3,5), S = cgetg(prec+1, t_VEC); long i, n; for (n = 1; n <= prec; n++) { GEN s = usumdivkvec(n, K); gel(s,2) = mului(21, gel(s,2)); gel(S,n) = s; } J = cgetg(prec+2, t_SER), J[1] = evalvarn(0)|evalsigne(1)|evalvalp(-1); j = J+3; gel(j,-1) = gen_1; gel(j,0) = utoipos(744); gel(j,1) = utoipos(196884); for (n = 2; n < prec; n++) { pari_sp av = avma; GEN c, s = gel(S,n+1), s3 = gel(s,1), s5 = gel(s,2); c = addii(mului(10, s3), s5); for (i = 0; i < n; i++) { s = gel(S,n-i); s3 = gel(s,1); s5 = gel(s,2); c = addii(c, mulii(gel(j,i), addii(mulsi(-10*i,s3), s5))); } gel(j,n) = gerepileuptoint(av, diviuexact(muliu(c,24), n+1)); } return J; } GEN jell(GEN x, long prec) { long tx = typ(x); pari_sp av = avma; GEN q, h, U; if (!is_scalar_t(tx)) { if (gequalX(x)) { h = ser_j(precdl); setvarn(h, varn(x)); return h; } q = toser_i(x); if (!q) pari_err_TYPE("ellj",x); h = ser_j(lg(q) - 2); return gerepileupto(av, gsubst(h, 0, q)); } if (tx == t_PADIC) { GEN p2, p1 = gdiv(inteta(gsqr(x)), inteta(x)); p1 = gmul2n(gsqr(p1),1); p1 = gmul(x,gpowgs(p1,12)); p2 = gaddsg(768,gadd(gsqr(p1),gdivsg(4096,p1))); p1 = gmulsg(48,p1); return gerepileupto(av, gadd(p2,p1)); } /* Let h = Delta(2x) / Delta(x), then j(x) = (1 + 256h)^3 / h */ x = upper_half(x, &prec); x = redtausl2(x, &U); /* forget about Ua : j has weight 0 */ { /* cf eta_reduced, raised to power 24 * Compute * t = (inteta(q(2x)) / inteta(q(x))) ^ 24; * then * h = t * (q(2x) / q(x) = t * q(x); * 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)); 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; else { GEN t = gdiv(inteta(gsqr(q)), inteta(q)); h = gmul(q, gpowgs(t, 24)); } } /* real_1 important ! gaddgs(, 1) could increase the accuracy ! */ return gerepileupto(av, gdiv(gpowgs(gadd(gmul2n(h,8), real_1(prec)), 3), h)); } static GEN to_form(GEN a, GEN w, GEN C) { return mkvec3(a, w, diviiexact(C, a)); } static GEN form_to_quad(GEN f, GEN sqrtD) { long a = itos(gel(f,1)), a2 = a << 1; GEN b = gel(f,2); return mkcomplex(gdivgs(b, -a2), gdivgs(sqrtD, a2)); } static GEN eta_form(GEN f, GEN sqrtD, GEN *s_t, long prec) { GEN U, t = form_to_quad(redimagsl2(f, &U), sqrtD); *s_t = eta_correction(t, U, 0); return eta_reduced(t, prec); } /* eta(t/p)eta(t/q) / (eta(t)eta(t/pq)), t = (-w + sqrt(D)) / 2a */ GEN double_eta_quotient(GEN a, GEN w, GEN D, long p, long q, GEN pq, GEN sqrtD) { GEN C = shifti(subii(sqri(w), D), -2); GEN d, t, z, zp, zq, zpq, s_t, s_tp, s_tpq, s, sp, spq; long prec = realprec(sqrtD); z = eta_form(to_form(a, w, C), sqrtD, &s_t, prec); s = gel(s_t, 1); zp = eta_form(to_form(mului(p, a), w, C), sqrtD, &s_tp, prec); sp = gel(s_tp, 1); zpq = eta_form(to_form(mulii(pq, a), w, C), sqrtD, &s_tpq, prec); spq = gel(s_tpq, 1); if (p == q) { z = gdiv(gsqr(zp), gmul(z, zpq)); t = gsub(gmul2n(gel(s_tp,2), 1), gadd(gel(s_t,2), gel(s_tpq,2))); if (sp != gen_1) z = gmul(z, sp); } else { GEN s_tq, sq; zq = eta_form(to_form(mului(q, a), w, C), sqrtD, &s_tq, prec); sq = gel(s_tq, 1); z = gdiv(gmul(zp, zq), gmul(z, zpq)); t = gsub(gadd(gel(s_tp,2), gel(s_tq,2)), gadd(gel(s_t,2), gel(s_tpq,2))); if (sp != gen_1) z = gmul(z, gsqrt(sp, prec)); if (sq != gen_1) z = gmul(z, gsqrt(sq, prec)); } d = NULL; if (s != gen_1) d = gsqrt(s, prec); if (spq != gen_1) { GEN x = gsqrt(spq, prec); d = d? gmul(d, x): x; } if (d) z = gdiv(z, d); return gmul(z, exp_IPiQ(t, prec)); } typedef struct { GEN u; long v, t; } cxanalyze_t; /* typ(x) = t_INT, t_FRAC or t_REAL */ INLINE GEN R_abs_shallow(GEN x) { return (typ(x) == t_FRAC)? absfrac_shallow(x): mpabs_shallow(x); } /* Check whether a t_COMPLEX, t_REAL or t_INT z != 0 can be written as * z = u * 2^(v/2) * exp(I Pi/4 t), u > 0, v = 0,1 and -3 <= t <= 4. * Allow z t_INT/t_REAL to simplify handling of eta_correction() output */ static int cxanalyze(cxanalyze_t *T, GEN z) { GEN a, b; long ta, tb; T->v = 0; if (is_intreal_t(typ(z))) { T->u = mpabs_shallow(z); T->t = signe(z) < 0? 4: 0; return 1; } a = gel(z,1); ta = typ(a); b = gel(z,2); tb = typ(b); T->t = 0; if (ta == t_INT && !signe(a)) { T->u = R_abs_shallow(b); T->t = gsigne(b) < 0? -2: 2; return 1; } if (tb == t_INT && !signe(b)) { T->u = R_abs_shallow(a); T->t = gsigne(a) < 0? 4: 0; return 1; } if (ta != tb || ta == t_REAL) { T->u = z; return 0; } /* a,b both non zero, both t_INT or t_FRAC */ if (ta == t_INT) { if (!absi_equal(a, b)) return 0; T->u = absi_shallow(a); T->v = 1; if (signe(a) == signe(b)) { T->t = signe(a) < 0? -3: 1; } else { T->t = signe(a) < 0? 3: -1; } } else { if (!absi_equal(gel(a,2), gel(b,2)) || !absi_equal(gel(a,1),gel(b,1))) return 0; T->u = absfrac_shallow(a); T->v = 1; a = gel(a,1); b = gel(b,1); if (signe(a) == signe(b)) { T->t = signe(a) < 0? -3: 1; } else { T->t = signe(a) < 0? 3: -1; } } return 1; } /* z * sqrt(st_b) / sqrt(st_a) exp(I Pi (t + t0)). Assume that * sqrt2 = gsqrt(gen_2, prec) or NULL */ static GEN apply_eta_correction(GEN z, GEN st_a, GEN st_b, GEN t0, GEN sqrt2, long prec) { GEN t, s_a = gel(st_a, 1), s_b = gel(st_b, 1); cxanalyze_t Ta, Tb; int ca, cb; t = gsub(gel(st_b,2), gel(st_a,2)); if (t0 != gen_0) t = gadd(t, t0); ca = cxanalyze(&Ta, s_a); cb = cxanalyze(&Tb, s_b); if (ca || cb) { /* compute sqrt(s_b) / sqrt(s_a) in a more efficient way: * sb = ub sqrt(2)^vb exp(i Pi/4 tb) */ GEN u = gdiv(Tb.u,Ta.u); switch(Tb.v - Ta.v) { case -1: u = gmul2n(u,-1); /* fall through: write 1/sqrt2 = sqrt2/2 */ case 1: u = gmul(u, sqrt2? sqrt2: sqrtr_abs(real2n(1, prec))); } if (!isint1(u)) z = gmul(z, gsqrt(u, prec)); t = gadd(t, gmul2n(stoi(Tb.t - Ta.t), -3)); } else { z = gmul(z, gsqrt(s_b, prec)); z = gdiv(z, gsqrt(s_a, prec)); } return gmul(z, exp_IPiQ(t, prec)); } /* sqrt(2) eta(2x) / eta(x) */ GEN weberf2(GEN x, long prec) { pari_sp av = avma; GEN z, sqrt2, a,b, Ua,Ub, st_a,st_b; x = upper_half(x, &prec); a = redtausl2(x, &Ua); b = redtausl2(gmul2n(x,1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); st_b = eta_correction(b, Ub, 1); sqrt2 = sqrtr_abs(real2n(1, prec)); z = apply_eta_correction(z, st_a, st_b, gen_0, sqrt2, prec); return gerepileupto(av, gmul(z, sqrt2)); } /* eta(x/2) / eta(x) */ GEN weberf1(GEN x, long prec) { pari_sp av = avma; GEN z, a,b, Ua,Ub, st_a,st_b; x = upper_half(x, &prec); a = redtausl2(x, &Ua); b = redtausl2(gmul2n(x,-1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); st_b = eta_correction(b, Ub, 1); z = apply_eta_correction(z, st_a, st_b, gen_0, NULL, prec); return gerepileupto(av, z); } /* exp(-I*Pi/24) * eta((x+1)/2) / eta(x) */ GEN weberf(GEN x, long prec) { pari_sp av = avma; GEN z, t0, a,b, Ua,Ub, st_a,st_b; x = upper_half(x, &prec); a = redtausl2(x, &Ua); b = redtausl2(gmul2n(gaddgs(x,1),-1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); 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(x))) z = gerepilecopy(av, gel(z,1)); else z = gerepileupto(av, z); return z; } GEN weber0(GEN x, long flag,long prec) { switch(flag) { case 0: return weberf(x,prec); case 1: return weberf1(x,prec); case 2: return weberf2(x,prec); default: pari_err_FLAG("weber"); } return NULL; /* not reached */ } /* check |q| < 1 */ static GEN check_unit_disc(const char *fun, GEN q, long prec) { GEN Q = gtofp(q, prec), Qlow; Qlow = (prec > LOWDEFAULTPREC)? gtofp(Q,LOWDEFAULTPREC): Q; if (gcmp(gnorm(Qlow), gen_1) >= 0) pari_err_DOMAIN(fun, "abs(q)", ">=", gen_1, q); return Q; } GEN theta(GEN q, GEN z, long prec) { long l, n; pari_sp av = avma, av2, lim; GEN s, c, snz, cnz, s2z, c2z, ps, qn, y, zy, ps2, k, zold; l = precision(q); n = precision(z); if (n && n < l) l = n; if (l) prec = l; z = gtofp(z, prec); q = check_unit_disc("theta", q, prec); zold = NULL; /* gcc -Wall */ zy = imag_i(z); if (gequal0(zy)) k = gen_0; else { GEN lq = glog(q,prec); k = roundr(divrr(zy, real_i(lq))); if (signe(k)) { zold = z; z = gadd(z, mulcxmI(gmul(lq,k))); } } qn = gen_1; ps2 = gsqr(q); ps = gneg_i(ps2); gsincos(z, &s, &c, prec); s2z = gmul2n(gmul(s,c),1); /* sin 2z */ c2z = gsubgs(gmul2n(gsqr(c),1), 1); /* cos 2z */ snz = s; cnz = c; y = s; av2 = avma; lim = stack_lim(av2,2); for (n = 3;; n += 2) { long e; s = gadd(gmul(snz, c2z), gmul(cnz,s2z)); qn = gmul(qn,ps); y = gadd(y, gmul(qn, s)); e = gexpo(s); if (e < 0) e = 0; if (gexpo(qn) + e < -prec2nbits(prec)) break; ps = gmul(ps,ps2); 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 (DEBUGMEM>1) pari_warn(warnmem,"theta (n = %ld)", n); gerepileall(av2, 5, &snz, &cnz, &ps, &qn, &y); } } if (signe(k)) { y = gmul(y, gmul(powgi(q,sqri(k)), gexp(gmul(mulcxI(zold),shifti(k,1)), prec))); if (mod2(k)) y = gneg_i(y); } return gerepileupto(av, gmul(y, gmul2n(gsqrt(gsqrt(q,prec),prec),1))); } GEN thetanullk(GEN q, long k, long prec) { long l, n; pari_sp av = avma; GEN p1, ps, qn, y, ps2; if (k < 0) pari_err_DOMAIN("thetanullk", "k", "<", gen_0, stoi(k)); l = precision(q); if (l) prec = l; q = check_unit_disc("thetanullk", q, prec); if (!(k&1)) { avma = av; return gen_0; } qn = gen_1; ps2 = gsqr(q); ps = gneg_i(ps2); y = gen_1; for (n = 3;; n += 2) { GEN t; qn = gmul(qn,ps); ps = gmul(ps,ps2); t = gmul(qn, powuu(n, k)); y = gadd(y, t); if (gexpo(t) < -prec2nbits(prec)) break; } p1 = gmul2n(gsqrt(gsqrt(q,prec),prec),1); if (k&2) y = gneg_i(y); return gerepileupto(av, gmul(p1, y)); } /* q2 = q^2 */ 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); const long bit = prec2nbits(prec); long i, n; ps = gneg_i(q2); for (n = 3;; n += 2) { GEN t = NULL/*-Wall*/, P = utoipos(n), N2 = sqru(n); qn = gmul(qn,ps); ps = gmul(ps,q2); for (i = 1; i <= k; i++) { t = gmul(qn, P); gel(y,i) = gadd(gel(y,i), t); P = mulii(P, N2); } if (gexpo(t) < -bit) return y; if (low_stack(lim, stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"vecthetanullk_loop, n = %ld",n); gerepileall(av, 3, &qn, &ps, &y); } } } /* [d^i theta/dz^i(q, 0), i = 1, 3, .., 2*k - 1] */ GEN vecthetanullk(GEN q, long k, long prec) { long i, l = precision(q); pari_sp av = avma; GEN p1, y; if (l) prec = l; q = check_unit_disc("vecthetanullk", q, prec); y = vecthetanullk_loop(gsqr(q), k, prec); p1 = gmul2n(gsqrt(gsqrt(q,prec),prec),1); for (i = 2; i <= k; i+=2) gel(y,i) = gneg_i(gel(y,i)); return gerepileupto(av, gmul(p1, y)); } /* [d^i theta/dz^i(q, 0), i = 1, 3, .., 2*k - 1], q = exp(2iPi tau) */ GEN vecthetanullk_tau(GEN tau, long k, long prec) { long i, l = precision(tau); pari_sp av = avma; GEN p1, q4, y; if (l) prec = l; if (typ(tau) != t_COMPLEX || gsigne(gel(tau,2)) <= 0) pari_err_DOMAIN("vecthetanullk_tau", "imag(tau)", "<=", gen_0, tau); q4 = expIxy(Pi2n(-1, prec), tau, prec); /* q^(1/4) */ y = vecthetanullk_loop(gpowgs(q4,8), k, prec); p1 = gmul2n(q4,1); for (i = 2; i <= k; i+=2) gel(y,i) = gneg_i(gel(y,i)); return gerepileupto(av, gmul(p1, y)); } /* -theta^(3)(tau/2) / theta^(1)(tau/2). Assume that Im tau > 0 */ GEN trueE2(GEN tau, long prec) { long l = precision(tau); pari_sp av = avma; GEN q2, y; if (l) prec = l; q2 = expIxy(Pi2n(1, prec), tau, prec); y = vecthetanullk_loop(q2, 3, prec); return gerepileupto(av, gdiv(gel(y,2), gel(y,1))); } /* Lambert W function : solution x of x*exp(x)=y, using Newton. y >= 0 t_REAL. * Good for low accuracy: the precision remains constant. Not memory-clean */ static GEN mplambertW0(GEN y) { long bitprec = bit_prec(y) - 2; GEN x, tmp; x = mplog(addrs(y,1)); do { tmp = x; /* f(x) = log(x)+x-log(y), f'(x) = (1+1/x) * x *= (1-log(x/y))/(x+1) */ 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 mplambertW(GEN y) { pari_sp av = avma; GEN x; long p = 1, s = signe(y); ulong mask = quadratic_prec_mask(lg(y)-1); if (s<0) pari_err_DOMAIN("Lw", "y", "<", gen_0, y); if(s==0) return rcopy(y); x = mplambertW0(rtor(y, LOWDEFAULTPREC)); while (mask!=1) { p <<= 1; if (mask & 1) p--; mask >>= 1; x = rtor(x, p+2); x = mulrr(x, divrr(subsr(1, mplog(divrr(x,y))),addrs(x,1))); } return gerepileuptoleaf(av,x); } GEN glambertW(GEN y, long prec) { switch(typ(y)) { case t_REAL: return mplambertW(y); case t_COMPLEX: pari_err_IMPL("lambert(t_COMPLEX)"); } return trans_eval("lambert",glambertW,y,prec); } #if 0 /* Another Lambert-like function: solution of exp(x)/x=y, y >= e t_REAL, * using Newton with constant prec. Good for low accuracy */ GEN mplambertX(GEN y) { long bitprec = bit_prec(y)-2; GEN tmp, x = mplog(y); if (typ(x) != t_REAL || signe(subrs(x,1))<0) pari_err(e_MISC,"Lx : argument less than e"); do { tmp = x; /* f(x)=x-log(xy), f'(x)=1-1/x */ /* x *= (log(x*y)-1)/(x-1) */ x = mulrr(x, divrr(subrs(mplog(mulrr(x,y)),1), subrs(x,1))); } while(expo(tmp)-expo(subrr(x,tmp)) < bitprec); return x; } #endif pari-2.7.5/src/basemath/random.c0000644000175000017500000001570712405547147015130 0ustar billbill/* 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. */ /********************************************************************/ /* */ /* PSEUDO-RANDOM INTEGERS */ /* */ /********************************************************************/ #include "pari.h" #include "paripriv.h" /********************************************************************/ /* XORGEN (Richard P. Brent) */ /* http://wwwmaths.anu.edu.au/~brent/random.html */ /* (initial adaptation to PARI/GP by Randall Rathbun) */ /********************************************************************/ /* 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 */ #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 */ #endif static void init_xor4096i(ulong seed) { ulong t, 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 */ v ^= v<<4; v ^= v>>13; } 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<>b; v = state[(xorgen_i+(r-s))&(r-1)]; v ^= v<>d; state[xorgen_i] = t^v; } } void pari_init_rand(void) { init_xor4096i(1); } /* 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<>b; /* (I + L^a)(I + R^b) */ 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)); } 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); } GEN getrand(void) { GEN x, xd; 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; } /********************************************************************/ /* */ /* GENERIC ROUTINES */ /* */ /********************************************************************/ /* assume n > 0 */ ulong random_Fl(ulong n) { ulong d; int shift; 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); for (;;) { d = pari_rand() >> shift; /* d < 2^(BIL-shift) uniformly distributed */ /* reject strategy: proba success = n 2^(shift-BIL), in [1/2, 1[ */ if (d < n) return d; } } /* assume N > 0, see random_Fl() for algorithm */ GEN randomi(GEN N) { long lx = lgefint(N); GEN d, NMSW; pari_sp av; 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--; } } 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 randomr(long prec) { pari_sp av; long b; GEN x, y; if (prec <= 2) return real_0_bit(0); x = cgetr(prec); av = avma; b = prec2nbits(prec); y = randomi(int2n(b)); if (!signe(y)) return real_0_bit(b); affir(y, x); shiftr_inplace(x, - b); avma = av; return x; } static GEN polrandom(GEN N) /* assume N!=0 */ { long i, d = lg(N); GEN z = leading_term(N); GEN y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(varn(N)); for (i=2; i b)", N); return gerepileuptoint(av, addii(a, randomi(addis(d,1)))); } return ellrandom(N); default: pari_err_TYPE("genrand",N); return NULL;/*not reached*/ } } pari-2.7.5/src/basemath/subgroup.c0000644000175000017500000003770612366172547015525 0ustar billbill/* 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" typedef struct slist { struct slist *next; long *data; long prec; } slist; typedef struct { GEN cyc, gen; ulong count; slist *list; } sublist_t; /* SUBGROUPS * G = Gp x I, with Gp a p-Sylow (I assumed small). * Compute subgroups of I by recursive calls * Loop through subgroups Hp of Gp using Birkhoff's algorithm. * If (I is non trivial) * lift Hp to G (mul by exponent of I) * for each subgp of I, lift it to G (mult by exponent of Gp) * consider the group generated by the two subgroups (concat) * * type(H) = mu --> H = Z/p^mu[1] x ... x Z/p^mu[len(mu)] */ typedef struct subgp_iter { long *M, *L; /* mu = p-subgroup type, lambda = p-group type */ GEN *powlist; /* [i] = p^i, i = 0.. */ long *c, *maxc; GEN *a, *maxa, **g, **maxg; long *available; GEN **H; /* p-subgroup of type mu, in matrix form */ GEN cyc; /* cyclic factors of G */ GEN subq;/* subgrouplist(I) */ GEN subqpart; /* J in subq s.t [I:J][Gp:Hp] <= indexbound */ GEN bound; /* if != NULL, impose a "bound" on [G:H] (see boundtype) */ long boundtype; long countsub; /* number of subgroups of type M (so far) */ long count; /* number of p-subgroups so far [updated when M completed] */ GEN expoI; /* exponent of I */ long(*fun)(void*, GEN); /* callback applied to each subgroup */ void *fundata; /* data for fun */ long stop; } subgp_iter; /* MAX: [G:H] <= bound, EXACT: [G:H] = bound, TYPE: type(H) = bound */ enum { b_NONE, b_MAX, b_EXACT, b_TYPE }; #define len(x) (x)[0] #define setlen(x,l) len(x)=(l) static void printtyp(const long *typ) /*Used only for ddebugging */ { long i, l = len(typ); for (i=1; i<=l; i++) err_printf(" %ld ",typ[i]); err_printf("\n"); } /* compute conjugate partition of typ */ static long* conjugate(long *typ) { long *t, i, k = len(typ), l, last; if (!k) { t = new_chunk(1); setlen(t,0); return t; } l = typ[1]; t = new_chunk(l+2); t[1] = k; last = k; for (i=2; i<=l; i++) { while (typ[last] < i) last--; t[i] = last; } t[i] = 0; setlen(t,l); return t; } /* ----subgp_iter 'fun' associated to subgrouplist ------------- */ static void addcell(sublist_t *S, GEN H) { long *pt,i,j,L, n = lg(H)-1; slist *cell; L = 3; for (j=1; j<=n; j++) { /* H in HNF, largest entries are on diagonal */ long l = lgefint(gcoeff(H,j,j)); if (l > L) L = l; } L -= 2; cell = (slist*) pari_malloc(sizeof(slist) + ((n*(n+1)) >> 1) * sizeof(long) * L); S->list->next = cell; cell->data = pt = (long*) (cell + 1); cell->prec = L; for (j=1; j<=n; j++) for(i=1; i<=j; i++) { GEN z = gcoeff(H,i,j); long h, lz = lgefint(z) - 2; for (h = 0; h < L - lz; h++) *pt++ = 0; for (h = 0; h < lz; h++) *pt++ = z[h+2]; } S->list = cell; S->count++; } static long list_fun(void *E, GEN x) { sublist_t *S = (sublist_t*)E; GEN H = ZM_hnfmodid(x, S->cyc); if (!S->gen || subgroup_conductor_ok(H, S->gen)) addcell(S, H); return 0; } /* -------------------------------------------------------------- */ /* treat subgroup Hp (not in HNF, T->fun should do it if desired) */ static void treatsub(subgp_iter *T, GEN H) { long i; if (!T->subq) {T->stop = T->fun(T->fundata, H); T->countsub++; } else { /* not a p group, add the trivial part */ GEN Hp = gmul(T->expoI, H); /* lift H to G */ long n = lg(T->subqpart)-1; for (i=1; i<=n; i++) if (T->fun(T->fundata, shallowconcat(Hp, gel(T->subqpart,i)))) { T->stop = 1; break; } T->countsub += n; } } /* x a t_INT, x++. Could be optimized... */ static void inc(GEN x) { affii(addis(x,1), x); } /* assume t>0 and l>1 */ static void dogroup(subgp_iter *T) { const GEN *powlist = T->powlist; long *M = T->M; long *L = T->L; long *c = T->c; GEN *a = T->a, *maxa = T->maxa; GEN **g = T->g, **maxg = T->maxg; GEN **H = T->H; pari_sp av; long i,j,k,r,n,t2,ind, t = len(M), l = len(L); t2 = (l==t)? t-1: t; n = t2 * l - (t2*(t2+1))/2; /* number of gamma_ij */ for (i=1, r=t+1; ; i++) { if (T->available[i]) c[r++] = i; if (r > l) break; } if (DEBUGLEVEL>6) { err_printf(" column selection:"); printtyp(c); } /* a/g and maxa/maxg access the same data indexed differently */ for (ind=0,i=1; i<=t; ind+=(l-i),i++) { maxg[i] = maxa + (ind - (i+1)); /* only access maxg[i][i+1..l] */ g[i] = a + (ind - (i+1)); for (r=i+1; r<=l; r++) if (c[r] < c[i]) maxg[i][r] = powlist[M[i]-M[r]-1]; else if (L[c[r]] < M[i]) maxg[i][r] = powlist[L[c[r]]-M[r]]; else maxg[i][r] = powlist[M[i]-M[r]]; } /* allocate correct lg */ for (i = 0; i<= n-1; i++) a[i] = icopy(maxa[i]); affui(0, a[n-1]); for (i=0; istop;) { inc(a[n-1]); if (cmpii(a[n-1], maxa[n-1]) > 0) { j=n-2; while (j>=0 && equalii(a[j], maxa[j])) j--; if (j < 0) return; inc(a[j]); for (k=j+1; k 0) e = mulii(e, powlist[d]); H[i][c[r]] = e; } } treatsub(T, (GEN)H); avma = av; } } /* T->c[1],...,T->c[r-1] filled */ static void loop(subgp_iter *T, long r) { long j; if (r > len(T->M)) { pari_sp av = avma; dogroup(T); avma = av; return; } if (r!=1 && (T->M[r-1] == T->M[r])) j = T->c[r-1]+1; else j = 1; for ( ; j<=T->maxc[r]; j++) if (T->available[j]) { T->c[r] = j; T->available[j] = 0; loop(T, r+1); T->available[j] = 1; } } static void dopsubtyp(subgp_iter *T) { pari_sp av = avma; long i,r, l = len(T->L), t = len(T->M); if (!t) { treatsub(T, mkmat( zerocol(l) )); avma = av; return; } if (l==1) /* imply t = 1 */ { GEN p1 = gtomat(T->powlist[T->L[1]-T->M[1]]); treatsub(T, p1); avma = av; return; } T->c = new_chunk(l+1); setlen(T->c, l); T->maxc = new_chunk(l+1); T->available = new_chunk(l+1); T->a = (GEN*)new_chunk(l*(t+1)); T->maxa= (GEN*)new_chunk(l*(t+1)); T->g = (GEN**)new_chunk(t+1); T->maxg = (GEN**)new_chunk(t+1); if (DEBUGLEVEL>4) { err_printf(" subgroup:"); printtyp(T->M); } for (i=1; i<=t; i++) { for (r=1; r<=l; r++) if (T->M[i] > T->L[r]) break; T->maxc[i] = r-1; } T->H = (GEN**)cgetg(t+1, t_MAT); for (i=1; i<=t; i++) T->H[i] = (GEN*)cgetg(l+1, t_COL); for (i=1; i<=l; i++) T->available[i]=1; for (i=1; i<=t; i++) T->c[i]=0; /* go through all column selections */ loop(T, 1); avma = av; return; } static long weight(long *typ) { long i, l = len(typ), w = 0; for (i=1; i<=l; i++) w += typ[i]; return w; } static void dopsub(subgp_iter *T, GEN p, GEN indexsubq) { long *M, *L = T->L; long w,i,j,k,lsubq, wG = weight(L), wmin = 0, wmax = wG, n = len(L); if (DEBUGLEVEL>4) { err_printf("\ngroup:"); printtyp(L); } T->count = 0; switch(T->boundtype) { case b_MAX: /* upper bound */ wmin = (long) (wG - (log(gtodouble(T->bound)) / log(gtodouble(p)))); if (cmpii(powiu(p, wG - wmin), T->bound) > 0) wmin++; break; case b_EXACT: /* exact value */ wmin = wmax = wG - Z_pval(T->bound, p); break; } T->M = M = new_chunk(n+1); if (T->subq) { lsubq = lg(T->subq); T->subqpart = T->bound? cgetg(lsubq, t_VEC): T->subq; } else lsubq = 0; /* -Wall */ M[1] = -1; for (i=2; i<=n; i++) M[i]=0; for(;!T->stop;) /* go through all vectors mu_{i+1} <= mu_i <= lam_i */ { M[1]++; if (M[1] > L[1]) { for (j=2; j<=n; j++) if (M[j] < L[j] && M[j] < M[j-1]) break; if (j > n) return; M[j]++; for (k=1; k= wmin && w <= wmax) { GEN p1 = gen_1; if (T->subq && T->bound) /* G not a p-group */ { pari_sp av = avma; GEN indexH = powiu(p, wG - w); GEN B = divii(T->bound, indexH); k = 1; for (i=1; isubqpart[k++] = T->subq[i]; setlg(T->subqpart, k); avma = av; } if (DEBUGLEVEL>4) { long *Lp = conjugate(L); long *Mp = conjugate(M); GEN BINMAT = matqpascal(len(L)+1, p); if (DEBUGLEVEL>7) { err_printf(" lambda = "); printtyp(L); err_printf(" lambda'= "); printtyp(Lp); err_printf(" mu = "); printtyp(M); err_printf(" mu'= "); printtyp(Mp); } for (j=1; j<=len(Mp); j++) { p1 = mulii(p1, powiu(p, Mp[j+1]*(Lp[j]-Mp[j]))); p1 = mulii(p1, gcoeff(BINMAT, Lp[j]-Mp[j+1]+1, Mp[j]-Mp[j+1]+1)); } err_printf(" alpha_lambda(mu,p) = %Ps\n",p1); } T->countsub = 0; dopsubtyp(T); T->count += T->countsub; if (DEBUGLEVEL>4) { err_printf(" countsub = %ld\n", T->countsub); if (T->subq) p1 = muliu(p1,lg(T->subqpart)-1); if (!equaliu(p1,T->countsub)) { err_printf(" alpha = %Ps\n",p1); pari_err_BUG("forsubgroup (alpha != countsub)"); } } } } } static void parse_bound(subgp_iter *T) { GEN b, B = T->bound; if (!B) { T->boundtype = b_NONE; return; } switch(typ(B)) { case t_INT: /* upper bound */ T->boundtype = b_MAX; break; case t_VEC: /* exact value */ b = gel(B,1); if (lg(B) != 2 || typ(b) != t_INT) pari_err_TYPE("subgroup", B); T->boundtype = b_EXACT; T->bound = b; break; case t_COL: /* exact type */ pari_err_IMPL("exact type in subgrouplist"); if (lg(B) > len(T->L)+1) pari_err_TYPE("subgroup",B); T->boundtype = b_TYPE; break; default: pari_err_TYPE("subgroup",B); } if (signe(T->bound) <= 0) pari_err_DOMAIN("subgroup", "index bound", "<=", gen_0, T->bound); } static GEN expand_sub(GEN x, long n) { long i,j, m = lg(x); GEN p = matid(n-1), q,c; for (i=1; icyc; long i,j,k,imax,lprim, n = lg(cyc); if (typ(cyc) != t_VEC) { if (typ(cyc) != t_MAT) pari_err_TYPE("forsubgroup",cyc); cyc = RgM_diagonal_shallow(cyc); } for (i=1; iboundtype) { case b_EXACT: if (!is_pm1(T->bound)) break; default: T->fun(T->fundata, cyc); } avma = av; return; } if (!signe(gel(cyc,1))) pari_err_TYPE("forsubgroup [infinite group]", cyc); fa = Z_factor(gel(cyc,1)); primlist = gel(fa,1); listL = cgetg_copy(primlist, &lprim); imax = k = 0; for (i=1; i k) { k = j; imax = i; } gel(listL,i) = L; } L = gel(listL,imax); p = gel(primlist,imax); k = L[1]; T->L = L; T->powlist = (GEN*)init_powlist(k, p); B = T->bound; parse_bound(T); if (lprim == 2) { T->subq = NULL; if (T->boundtype == b_EXACT) { (void)Z_pvalrem(T->bound,p,&B); if (!is_pm1(B)) { avma = av; return; } } } else { /* not a p-group */ GEN cycI = leafcopy(cyc); long lsubq; for (i=1; ipowlist[L[i]]); if (is_pm1(gel(cycI,i))) break; } setlg(cycI, i); /* cyclic factors of I */ if (T->boundtype == b_EXACT) { (void)Z_pvalrem(T->bound,p,&B); B = mkvec(B); } T->expoI = gel(cycI,1); T->subq = subgrouplist_i(cycI, B, T->expoI, NULL); lsubq = lg(T->subq); for (i=1; isubq,i) = expand_sub(gel(T->subq,i), n); if (T->bound) { indexsubq = cgetg(lsubq,t_VEC); for (i=1; isubq,i)); } /* lift subgroups of I to G */ for (i=1; isubq,i) = gmul(T->powlist[k],gel(T->subq,i)); if (DEBUGLEVEL>6) 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); avma = av; } static GEN get_snf(GEN x, long *N) { GEN cyc; long n; switch(typ(x)) { case t_MAT: if (!RgM_isdiagonal(x)) return NULL; cyc = RgM_diagonal_shallow(x); break; case t_VEC: if (lg(x) == 4 && typ(gel(x,2)) == t_VEC) x = gel(x,2); case t_COL: cyc = leafcopy(x); break; default: return NULL; } *N = lg(cyc)-1; for (n = *N; n > 0; n--) /* take care of trailing 1s */ { GEN c = gel(cyc,n); if (typ(c) != t_INT || signe(c) <= 0) return NULL; if (!is_pm1(c)) break; } setlg(cyc, n+1); for ( ; n > 0; n--) { GEN c = gel(cyc,n); if (typ(c) != t_INT || signe(c) <= 0) return NULL; } return cyc; } void forsubgroup(void *E, long call(void*, GEN), GEN cyc, GEN bound) { subgp_iter T; long N; T.fun = call; T.cyc = get_snf(cyc,&N); if (!T.cyc) pari_err_TYPE("forsubgroup",cyc); T.bound = bound; T.fundata = E; T.stop = 0; subgroup_engine(&T); } void forsubgroup0(GEN cyc, GEN bound, GEN code) { push_lex(gen_0, code); forsubgroup((void*)code, &gp_evalvoid, cyc, bound); pop_lex(1); } static GEN packtoi(long *pt, long L) { long i, l; GEN z; for (i=0; inext; pari_free(list); pt = sublist->data; L = sublist->prec; H = cgetg(N+1,t_MAT); gel(z,ii) = H; for (j=1; j<=n; j++) { gel(H,j) = cgetg(N+1, t_COL); for (i=1; i<=j; i++) { gcoeff(H,i,j) = packtoi(pt, L); pt += L; } for ( ; i<=N; i++) gcoeff(H,i,j) = gen_0; } for ( ; j<=N; j++) gel(H,j) = col_ei(N, j); } pari_free(sublist); return z; } GEN subgrouplist(GEN cyc, GEN bound) { return subgrouplist_i(cyc,bound,NULL,NULL); } GEN subgroupcondlist(GEN cyc, GEN bound, GEN L) { return subgrouplist_i(cyc,bound,NULL,L); } pari-2.7.5/src/basemath/FlxqE.c0000644000175000017500000011520412453020222014637 0ustar billbill/* Copyright (C) 2012 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 Fq, small characteristic. */ /***********************************************************************/ /** **/ /** FlxqE **/ /** **/ /***********************************************************************/ /* Theses functions deal with point over elliptic curves over Fq 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. */ GEN RgE_to_FlxqE(GEN x, GEN T, ulong p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_Flxq(gel(x,1),T,p),Rg_to_Flxq(gel(x,2),T,p)); } GEN FlxqE_changepoint(GEN x, GEN ch, GEN T, ulong p) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = Flxq_inv(u, T, p); v2 = Flxq_sqr(v, T, p); v3 = Flxq_mul(v,v2, T, p); p1 = Flx_sub(gel(x,1),r, p); z = cgetg(3,t_VEC); gel(z,1) = Flxq_mul(v2, p1, T, p); gel(z,2) = Flxq_mul(v3, Flx_sub(gel(x,2), Flx_add(Flxq_mul(s, p1, T, p),t, p), p), T, p); return gerepileupto(av, z); } GEN FlxqE_changepointinv(GEN x, GEN ch, GEN T, ulong p) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = Flxq_sqr(u, T, p); u3 = Flxq_mul(u,u2, T, p); u2X = Flxq_mul(u2,X, T, p); z = cgetg(3, t_VEC); gel(z,1) = Flx_add(u2X,r, p); gel(z,2) = Flx_add(Flxq_mul(u3,Y, T, p), Flx_add(Flxq_mul(s,u2X, T, p), t, p), p); return z; } static GEN FlxqE_dbl_slope(GEN P, GEN a4, GEN T, ulong p, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P) || !lgpol(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); if (p==3UL) *slope = typ(a4)==t_VEC ? Flxq_div(Flxq_mul(x, gel(a4, 1), T, p), y, T, p) : Flxq_div(a4, Flx_neg(y, p), T, p); else { GEN sx = Flx_add(Flx_triple(Flxq_sqr(x, T, p), p), a4, p); *slope = Flxq_div(sx, Flx_double(y, p), T, p); } Q = cgetg(3,t_VEC); gel(Q, 1) = Flx_sub(Flxq_sqr(*slope, T, p), Flx_double(x, p), p); if (typ(a4)==t_VEC) gel(Q, 1) = Flx_sub(gel(Q, 1), gel(a4, 1), p); gel(Q, 2) = Flx_sub(Flxq_mul(*slope, Flx_sub(x, gel(Q, 1), p), T, p), y, p); return Q; } GEN FlxqE_dbl(GEN P, GEN a4, GEN T, ulong p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FlxqE_dbl_slope(P,a4, T, p,&slope)); } static GEN FlxqE_add_slope(GEN P, GEN Q, GEN a4, GEN T, ulong p, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (Flx_equal(Px, Qx)) { if (Flx_equal(Py, Qy)) return FlxqE_dbl_slope(P, a4, T, p, slope); else return ellinf(); } *slope = Flxq_div(Flx_sub(Py, Qy, p), Flx_sub(Px, Qx, p), T, p); R = cgetg(3,t_VEC); gel(R, 1) = Flx_sub(Flx_sub(Flxq_sqr(*slope, T, p), Px, p), Qx, p); if (typ(a4)==t_VEC) gel(R, 1) = Flx_sub(gel(R, 1),gel(a4, 1), p); gel(R, 2) = Flx_sub(Flxq_mul(*slope, Flx_sub(Px, gel(R, 1), p), T, p), Py, p); return R; } GEN FlxqE_add(GEN P, GEN Q, GEN a4, GEN T, ulong p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FlxqE_add_slope(P,Q,a4, T, p,&slope)); } static GEN FlxqE_neg_i(GEN P, ulong p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), Flx_neg(gel(P,2), p)); } GEN FlxqE_neg(GEN P, GEN T, ulong p) { (void) T; if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), Flx_neg(gel(P,2), p)); } GEN FlxqE_sub(GEN P, GEN Q, GEN a4, GEN T, ulong p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FlxqE_add_slope(P, FlxqE_neg_i(Q, p), a4, T, p, &slope)); } struct _FlxqE { GEN a4, a6; GEN T; ulong p; }; static GEN _FlxqE_dbl(void *E, GEN P) { struct _FlxqE *ell = (struct _FlxqE *) E; return FlxqE_dbl(P, ell->a4, ell->T, ell->p); } static GEN _FlxqE_add(void *E, GEN P, GEN Q) { struct _FlxqE *ell=(struct _FlxqE *) E; return FlxqE_add(P, Q, ell->a4, ell->T, ell->p); } static GEN _FlxqE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FlxqE *e=(struct _FlxqE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = FlxqE_neg(P, e->T, e->p); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepileupto(av, gen_pow(P, n, e, &_FlxqE_dbl, &_FlxqE_add)); } GEN FlxqE_mul(GEN P, GEN n, GEN a4, GEN T, ulong p) { struct _FlxqE E; E.a4= a4; E.T = T; E.p = p; return _FlxqE_mul(&E, P, n); } /* 3*x^2+2*a2*x = -a2*x, and a2!=0 */ /* Finds a random non-singular point on E */ static GEN random_F3xqE(GEN a2, GEN a6, GEN T) { pari_sp ltop = avma; GEN x, y, rhs; const ulong p=3; do { avma= ltop; x = random_Flx(get_Flx_degree(T),get_Flx_var(T),p); rhs = Flx_add(Flxq_mul(Flxq_sqr(x, T, p), Flx_add(x, a2, p), T, p), a6, p); } while ((!lgpol(rhs) && !lgpol(x)) || !Flxq_issquare(rhs, T, p)); y = Flxq_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_F3xqE", T); return gerepilecopy(ltop, mkvec2(x, y)); } /* Finds a random non-singular point on E */ GEN random_FlxqE(GEN a4, GEN a6, GEN T, ulong p) { pari_sp ltop = avma; GEN x, x2, y, rhs; if (typ(a4)==t_VEC) return random_F3xqE(gel(a4,1), a6, T); do { avma= ltop; x = random_Flx(get_Flx_degree(T),get_Flx_var(T),p); x2 = Flxq_sqr(x, T, p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ rhs = Flx_add(Flxq_mul(x, Flx_add(x2, a4, p), T, p), a6, p); } while ((!lgpol(rhs) && !lgpol(Flx_add(Flx_triple(x2, p), a4, p))) || !Flxq_issquare(rhs, T, p)); y = Flxq_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_FlxqE", T); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _FlxqE_rand(void *E) { struct _FlxqE *ell=(struct _FlxqE *) E; return random_FlxqE(ell->a4, ell->a6, ell->T, ell->p); } static const struct bb_group FlxqE_group={_FlxqE_add,_FlxqE_mul,_FlxqE_rand,hash_GEN,zvV_equal,ell_is_inf, NULL}; const struct bb_group * get_FlxqE_group(void ** pt_E, GEN a4, GEN a6, GEN T, ulong p) { struct _FlxqE *e = (struct _FlxqE *) stack_malloc(sizeof(struct _FlxqE)); e->a4 = a4; e->a6 = a6; e->T = Flx_get_red(T, p); e->p = p; *pt_E = (void *) e; return &FlxqE_group; } GEN FlxqE_order(GEN z, GEN o, GEN a4, GEN T, ulong p) { pari_sp av = avma; struct _FlxqE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &FlxqE_group)); } GEN FlxqE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, ulong p) { pari_sp av = avma; struct _FlxqE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &FlxqE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN FlxqE_vert(GEN P, GEN Q, GEN T, ulong p) { if (ell_is_inf(P)) return pol1_Flx(get_Flx_var(T)); return Flx_sub(gel(Q, 1), gel(P, 1), p); } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN FlxqE_tangent_update(GEN R, GEN Q, GEN a4, GEN T, ulong p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol1_Flx(get_Flx_var(T)); } else if (!lgpol(gel(R,2))) { *pt_R = ellinf(); return FlxqE_vert(R, Q, T, p); } else { GEN slope, tmp1, tmp2; *pt_R = FlxqE_dbl_slope(R, a4, T, p, &slope); tmp1 = Flx_sub(gel(Q, 1), gel(R, 1), p); tmp2 = Flx_add(Flxq_mul(tmp1, slope, T, p), gel(R,2), p); return Flx_sub(gel(Q, 2), tmp2, p); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN FlxqE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN T, ulong p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FlxqE_vert(P, Q, T, p); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FlxqE_vert(R, Q, T, p); } else if (Flx_equal(gel(P, 1), gel(R, 1))) { if (Flx_equal(gel(P, 2), gel(R, 2))) return FlxqE_tangent_update(R, Q, a4, T, p, pt_R); else { *pt_R = ellinf(); return FlxqE_vert(R, Q, T, p); } } else { GEN slope, tmp1, tmp2; *pt_R = FlxqE_add_slope(P, R, a4, T, p, &slope); tmp1 = Flxq_mul(Flx_sub(gel(Q, 1), gel(R, 1), p), slope, T, p); tmp2 = Flx_add(tmp1, gel(R, 2), p); return Flx_sub(gel(Q, 2), tmp2, p); } } /* Returns the Miller function f_{m, Q} evaluated at the point P using the standard Miller algorithm. */ struct _FlxqE_miller { ulong p; GEN T, a4, P; }; static GEN FlxqE_Miller_dbl(void* E, GEN d) { struct _FlxqE_miller *m = (struct _FlxqE_miller *)E; ulong p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line; GEN num = Flxq_sqr(gel(d,1), T, p); GEN denom = Flxq_sqr(gel(d,2), T, p); GEN point = gel(d,3); line = FlxqE_tangent_update(point, P, a4, T, p, &point); num = Flxq_mul(num, line, T, p); v = FlxqE_vert(point, P, T, p); denom = Flxq_mul(denom, v, T, p); return mkvec3(num, denom, point); } static GEN FlxqE_Miller_add(void* E, GEN va, GEN vb) { struct _FlxqE_miller *m = (struct _FlxqE_miller *)E; ulong p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN num = Flxq_mul(na, nb, T, p); GEN denom = Flxq_mul(da, db, T, p); line = FlxqE_chord_update(pa, pb, P, a4, T, p, &point); num = Flxq_mul(num, line, T, p); v = FlxqE_vert(point, P, T, p); denom = Flxq_mul(denom, v, T, p); return mkvec3(num, denom, point); } static GEN FlxqE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN T, ulong p) { pari_sp ltop = avma; struct _FlxqE_miller d; GEN v, num, denom, g1; d.a4 = a4; d.T = T; d.p = p; d.P = P; g1 = pol1_Flx(get_Flx_var(T)); v = gen_pow(mkvec3(g1,g1,Q), m, (void*)&d, FlxqE_Miller_dbl, FlxqE_Miller_add); num = gel(v,1); denom = gel(v,2); if (!lgpol(num) || !lgpol(denom)) { avma = ltop; return NULL; } return gerepileupto(ltop, Flxq_div(num, denom, T, p)); } GEN FlxqE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p) { pari_sp ltop = avma; GEN num, denom, result; if (ell_is_inf(P) || ell_is_inf(Q) || Flx_equal(P,Q)) return pol1_Flx(get_Flx_var(T)); num = FlxqE_Miller(P, Q, m, a4, T, p); if (!num) return pol1_Flx(get_Flx_var(T)); denom = FlxqE_Miller(Q, P, m, a4, T, p); if (!denom) {avma = ltop; return pol1_Flx(get_Flx_var(T)); } result = Flxq_div(num, denom, T, p); if (mpodd(m)) result = Flx_neg(result, p); return gerepileupto(ltop, result); } GEN FlxqE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p) { GEN num; if (ell_is_inf(P) || ell_is_inf(Q)) return pol1_Flx(get_Flx_var(T)); num = FlxqE_Miller(P, Q, m, a4, T, p); return num? num: pol1_Flx(get_Flx_var(T)); } static GEN _FlxqE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FlxqE *e = (struct _FlxqE *) E; return Flxq_order(FlxqE_weilpairing(P,Q,m,e->a4,e->T,e->p), F, e->T, e->p); } GEN Flxq_ellgroup(GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pt_m) { struct _FlxqE e; GEN q = powuu(p, get_Flx_degree(T)); e.a4=a4; e.a6=a6; e.T=T; e.p=p; return gen_ellgroup(N, subis(q,1), pt_m, (void*)&e, &FlxqE_group, _FlxqE_pairorder); } GEN Flxq_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p) { GEN P; pari_sp av = avma; struct _FlxqE e; e.a4=a4; e.a6=a6; e.T=T; e.p=p; switch(lg(D)-1) { case 1: P = gen_gener(gel(D,1), (void*)&e, &FlxqE_group); P = mkvec(FlxqE_changepoint(P, ch, T, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FlxqE_group, _FlxqE_pairorder); gel(P,1) = FlxqE_changepoint(gel(P,1), ch, T, p); gel(P,2) = FlxqE_changepoint(gel(P,2), ch, T, p); break; } return gerepilecopy(av, P); } /***********************************************************************/ /** **/ /** Point counting **/ /** **/ /***********************************************************************/ static GEN _can_invl(void *E, GEN V) {(void) E; return V; } static GEN _can_lin(void *E, GEN F, GEN V, GEN q) { GEN v = RgX_splitting(V, 3); (void) E; return FpX_sub(V,ZXV_dotproduct(v, F), q); } static GEN _can_iter(void *E, GEN f, GEN q) { GEN h = RgX_splitting(f,3); GEN h1s = ZX_sqr(gel(h,1)), h2s = ZX_sqr(gel(h,2)), h3s = ZX_sqr(gel(h,3)); GEN h12 = ZX_mul(gel(h,1), gel(h,2)); GEN h13 = ZX_mul(gel(h,1), gel(h,3)); GEN h23 = ZX_mul(gel(h,2), gel(h,3)); GEN h1c = ZX_mul(gel(h,1), h1s); GEN h3c = ZX_mul(gel(h,3), h3s); GEN th = ZX_mul(ZX_sub(h2s,ZX_mulu(h13,3)),gel(h,2)); GEN y = FpX_sub(f,ZX_add(RgX_shift_shallow(h3c,2),ZX_add(RgX_shift_shallow(th,1),h1c)),q); (void) E; return mkvecn(7,y,h1s,h2s,h3s,h12,h13,h23); } static GEN _can_invd(void *E, GEN V, GEN v, GEN qM, long M) { GEN h1s=gel(v,2), h2s=gel(v,3), h3s=gel(v,4); GEN h12=gel(v,5), h13=gel(v,6), h23=gel(v,7); GEN F = mkvec3(ZX_sub(h1s,RgX_shift_shallow(h23,1)),RgX_shift_shallow(ZX_sub(h2s,h13),1), ZX_sub(RgX_shift_shallow(h3s,2),RgX_shift_shallow(h12,1))); (void)E; return gen_ZpX_Dixon(ZXV_Z_mul(F, utoi(3)), V, qM, utoi(3), M, NULL, _can_lin, _can_invl); } static GEN F3x_canonlift(GEN P, long n) { return gen_ZpX_Newton(Flx_to_ZX(P),utoi(3), n, NULL, _can_iter, _can_invd); } static GEN _can5_invl(void *E, GEN V) {(void) E; return V; } static GEN _can5_lin(void *E, GEN F, GEN V, GEN q) { ulong p = *(ulong*)E; GEN v = RgX_splitting(V, p); return FpX_sub(V,ZXV_dotproduct(v, F), q); } /* P(X,t) -> P(X*t^n,t) mod (t^p-1) */ static GEN _shift(GEN P, long n, ulong p, long v) { long i, l=lg(P); GEN r = cgetg(l,t_POL); r[1] = P[1]; for(i=2;ip, get_FpX_var(d->T)); GEN c = FpXQX_mul(a, bn, d->T, d->q); return mkvec2(c, addii(gel(A,2), gel(B,2))); } static GEN _can5_sqr(void *E, GEN A) { return _can5_mul(E,A,A); } static GEN _can5_iter(void *E, GEN f, GEN q) { pari_sp av = avma; struct _can_mul D; ulong p = *(ulong*)E; long i; GEN N, P, d, V, fs; D.q = q; D.T = ZX_Z_sub(monomial(gen_1,p,MAXVARN),gen_1); D.p = p; fs = mkvec2(_shift(f, 1, p, MAXVARN), 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)); P = FpX_mul(N,f,q); P = RgX_deflate(P, p); d = RgX_splitting(N, p); V = cgetg(p+1,t_VEC); 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)); } static GEN _can5_invd(void *E, GEN H, GEN v, GEN qM, long M) { ulong p = *(long*)E; return gen_ZpX_Dixon(gel(v,2), H, qM, utoi(p), M, E, _can5_lin, _can5_invl); } static GEN Flx_canonlift(GEN P, long n, ulong p) { return p==3 ? F3x_canonlift(P,n): gen_ZpX_Newton(Flx_to_ZX(P),utoi(p), n, &p, _can5_iter, _can5_invd); } /* assume a and n are coprime */ static GEN RgX_circular_shallow(GEN P, long a, long n) { long i, l = lgpol(P); GEN Q = cgetg(2+n,t_POL); Q[1] = P[1]; for(i=0; iTp; ulong p = d->p; GEN xai = Flxq_mul(ZX_to_Flx(x, p), d->ai, T, p); return Flx_to_ZX(Flxq_lroot_fast(xai, d->sqx, T, p)); } static GEN _lift_lin(void *E, GEN F, GEN x2, GEN q) { struct _lift_lin *d = (struct _lift_lin *) E; pari_sp av = avma; GEN T = gel(F,3), Xm = gel(F,4); GEN y2 = ZpXQ_frob(x2, Xm, T, q, d->p); GEN lin = FpX_add(ZX_mul(gel(F,1), y2), ZX_mul(gel(F,2), x2), q); return gerepileupto(av, FpX_rem(lin, T, q)); } static GEN FpM_FpXV_bilinear(GEN P, GEN X, GEN Y, GEN p) { pari_sp av = avma; GEN s = ZX_mul(FpXV_FpC_mul(X,gel(P,1),p),gel(Y,1)); long i, l = lg(P); for(i=2; ip; 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 V = FpM_FpXQV_bilinear(d->phi,xp,yp,TN,q); return mkvec3(V,xp,yp); } static GEN _lift_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _lift_iso *d = (struct _lift_iso *) E; struct _lift_lin e; ulong p = d->p; GEN TM = FpXT_red(d->T, qM), XM = FpXV_red(d->Xm, qM); GEN xp = FpXV_red(gel(v,2), qM); GEN yp = FpXV_red(gel(v,3), qM); GEN Dx = FpM_FpXQV_bilinear(d->phi, FpXC_powderiv(xp, qM), yp, TM, qM); GEN Dy = FpM_FpXQV_bilinear(d->phi, xp, FpXC_powderiv(yp, qM), TM, qM); GEN F = mkvec4(Dy, Dx, TM, XM); e.ai = Flxq_inv(ZX_to_Flx(Dy,p),d->Tp,p); e.sqx = d->sqx; e.Tp = d->Tp; e.p=p; e.Xm = XM; return gen_ZpX_Dixon(F,V,qM,utoi(p),M,(void*) &e, _lift_lin, _lift_invl); } static GEN lift_isogeny(GEN phi, GEN x0, long n, GEN Xm, GEN T, GEN sqx, GEN Tp, ulong p) { struct _lift_iso d; d.phi=phi; d.Xm=Xm; d.T=T; d.sqx=sqx; d.Tp=Tp; d.p=p; return gen_ZpX_Newton(x0, utoi(p), n,(void*)&d, _lift_iter, _lift_invd); } static GEN getc2(GEN act, GEN X, GEN T, GEN q, ulong p, long N) { GEN A1 = RgV_to_RgX(gel(act,1),0), A2 = RgV_to_RgX(gel(act,2),0); long n = brent_kung_optpow(maxss(degpol(A1),degpol(A2)),2,1); GEN xp = FpXQ_powers(X,n,T,q); GEN P = FpX_FpXQV_eval(A1, xp, T, q); GEN Q = FpX_FpXQV_eval(A2, xp, T, q); return FpXQ_mul(P,ZpXQ_inv(Q,T,utoi(p),N),T,q); } struct _ZpXQ_norm { long n; GEN T, p; }; static GEN ZpXQ_norm_mul(void *E, GEN x, GEN y) { struct _ZpXQ_norm *D = (struct _ZpXQ_norm*)E; GEN P = gel(x,1), Q = gel(y,1); long a = mael(x,2,1), b = mael(y,2,1); retmkvec2(FpXQ_mul(P,ZpXQ_frob_cyc(Q, D->T, D->p, a), D->T, D->p), mkvecsmall((a*b)%D->n)); } static GEN ZpXQ_norm_sqr(void *E, GEN x) { return ZpXQ_norm_mul(E, x, x); } /* Assume T = Phi_(n) and n prime */ GEN ZpXQ_norm_pcyc(GEN x, GEN T, GEN q, GEN p) { GEN z; struct _ZpXQ_norm D; long d = get_FpX_degree(T); D.T = T; D.p = q; D.n = d+1; if (d==1) return ZX_copy(x); z = mkvec2(x,mkvecsmall(p[2])); z = gen_powu(z,d,(void*)&D,ZpXQ_norm_sqr,ZpXQ_norm_mul); return gmael(z,1,2); } /* Assume T = Phi_(n) and n prime */ static GEN ZpXQ_sqrtnorm_pcyc(GEN x, GEN T, GEN q, GEN p, long e) { GEN z = ZpXQ_norm_pcyc(x, T, q, p); return Zp_sqrtlift(z,Fp_sqrt(z,p),p,e); } /* Assume a = 1 [p], return the square root of the norm */ static GEN ZpXQ_sqrtnorm(GEN a, GEN T, GEN q, GEN p, long e) { GEN s = Fp_div(FpXQ_trace(ZpXQ_log(a, T, p, e), T, q), gen_2, q); return modii(gel(Qp_exp(cvtop(s, p, e-1)),4), q); } struct _teich_lin { ulong p; GEN sqx, Tp; long m; }; static GEN _teich_invl(void *E, GEN x) { struct _teich_lin *d = (struct _teich_lin *) E; ulong p = d->p; GEN T = d->Tp; return Flx_to_ZX(Flxq_lroot_fast(ZX_to_Flx(x, p), d->sqx, T, p)); } static GEN _teich_lin(void *E, GEN F, GEN x2, GEN q) { struct _teich_lin *d = (struct _teich_lin *) E; pari_sp av = avma; GEN T = gel(F,2), Xm = gel(F,3); GEN y2 = ZpXQ_frob(x2, Xm, T, q, d->p); GEN lin = FpX_sub(y2, ZX_mulu(ZX_mul(gel(F,1), x2), d->p), q); return gerepileupto(av, FpX_rem(lin, T, q)); } struct _teich_iso { GEN Xm, T; GEN sqx, Tp; ulong p; }; static GEN _teich_iter(void *E, GEN x2, GEN q) { struct _teich_iso *d = (struct _teich_iso *) E; ulong p = d->p; GEN TN = FpXT_red(d->T, q), XN = FpXV_red(d->Xm, q); GEN y2 = ZpXQ_frob(x2, XN, TN, q, d->p); GEN x1 = FpXQ_powu(x2, p-1, TN, q); GEN xp = FpXQ_mul(x2, x1, TN, q); GEN V = FpX_sub(y2,xp,q); return mkvec2(V,x1); } static GEN _teich_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _teich_iso *d = (struct _teich_iso *) E; struct _teich_lin e; ulong p = d->p; GEN TM = FpXT_red(d->T, qM), XM = FpXV_red(d->Xm, qM); GEN x1 = FpX_red(gel(v,2), qM); GEN F = mkvec3(x1, TM, XM); e.sqx = d->sqx; e.Tp = d->Tp; e.p=p; return gen_ZpX_Dixon(F,V,qM,utoi(p),M,(void*) &e, _teich_lin, _teich_invl); } static GEN Teichmuller_lift(GEN x, GEN Xm, GEN T, GEN sqx, GEN Tp, ulong p, long N) { struct _teich_iso d; d.Xm = Xm; d.T = T; d.sqx = sqx; d.Tp = Tp; d.p = p; return gen_ZpX_Newton(x,utoi(p), N,(void*)&d, _teich_iter, _teich_invd); } static GEN get_norm(GEN a4, GEN a6, GEN T, ulong p, long N) { long sv=T[1]; GEN a; if (p==3) a = gel(a4,1); else { GEN P = mkpoln(4, pol1_Flx(sv), pol0_Flx(sv), a4, a6); a = gel(FlxqX_pow(P,p>>1,T,p),2+p-1); } return Zp_sqrtnlift(gen_1,subss(p,1),utoi(Flxq_norm(a,T,p)),utoi(p), N); } static GEN fill_pols(long n, const long *v, long m, const long *vn, const long *vd, GEN *act) { long i, j; long d = upowuu(n,12/(n-1)); GEN N, D, M = zeromatcopy(n+1,n+1); gmael(M,1,n+1) = gen_1; for(i=2;i<=n+1;i++) for(j=i-1;j<=n;j++) gmael(M,i,j) = mulis(powuu(d,i-2),v[j-i+1]); N = cgetg(m+1,t_COL); D = cgetg(m+1,t_COL); for(i=1;i<=m;i++) { gel(N,i) = stoi(*vn++); gel(D,i) = stoi(*vd++); } *act = mkmat2(N,D); return M; } /* These polynomials were extracted from the ECHIDNA databases available at and computed by David R. Kohel. Return the matrix of the modular polynomial, set act to the parametrization, and set dj to the opposite of the supersingular j-invariant. */ static GEN get_Kohel_polynomials(ulong p, GEN *act, long *dj) { const long mat3[] = {-1,-36,-270}; const long num3[] = {1,-483,-21141,-59049}; const long den3[] = {1,261, 4347, -6561}; const long mat5[] = {-1,-30,-315,-1300,-1575}; const long num5[] = {-1,490,20620,158750,78125}; const long den5[] = {-1,-254,-4124,-12250,3125}; const long mat7[] = {-1,-28,-322,-1904,-5915,-8624,-4018}; const long num7[] = {1,-485,-24058,-343833,-2021642,-4353013,-823543}; const long den7[] = {1,259,5894,49119,168406,166355,-16807}; const long mat13[]= {-1,-26,-325,-2548,-13832,-54340,-157118,-333580,-509366, -534820,-354536,-124852,-15145}; const long num13[]= {1,-487,-24056,-391463,-3396483,-18047328,-61622301, -133245853,-168395656,-95422301,-4826809}; const long den13[]= {1,257,5896,60649,364629,1388256,3396483,5089019,4065464, 1069939,-28561}; switch(p) { case 3: *dj = 0; return fill_pols(3,mat3,4,num3,den3,act); case 5: *dj = 0; return fill_pols(5,mat5,5,num5,den5,act); case 7: *dj = 1; return fill_pols(7,mat7,7,num7,den7,act); case 13: *dj = 8; return fill_pols(13,mat13,11,num13,den13,act); } *dj=0; *act = NULL; return NULL; } long zx_is_pcyc(GEN T) { long i, n = degpol(T); if (!uisprime(n+1)) return 0; for (i=0; i<=n; i++) if (T[i+2]!=1UL) return 0; return 1; } 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+4)/2, dj; GEN q = powuu(p, N); GEN T2, Xm, s1, c2, t, lr; GEN S1, sqx; GEN Nc2, Np; GEN act, phi = get_Kohel_polynomials(p, &act, &dj); long ispcyc = 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); s1 = Flxq_inv(Flx_Fl_add(Flxq_ellj(a4,a6,T,p),dj, p),T,p); lr = Flxq_lroot(polx_Flx(get_Flx_var(T)), T, p); sqx = Flxq_powers(lr, p-1, T, p); S1 = lift_isogeny(phi, Flx_to_ZX(s1), N, Xm, T2, sqx, T ,p); if (DEBUGLEVEL) timer_printf(&ti,"Lift isogeny"); c2 = getc2(act, S1, T2, q, p, N); if (DEBUGLEVEL) timer_printf(&ti,"c^2"); if (p>3 && !ispcyc) { GEN c2p = Flx_to_ZX(Flxq_inv(ZX_to_Flx(c2,p),T,p)); GEN tc2 = Teichmuller_lift(c2p,Xm, T2,sqx,T,p,N); if (DEBUGLEVEL) timer_printf(&ti,"Teichmuller/Fq"); c2 = FpX_rem(FpX_mul(tc2,c2,q),T2,q); } c2 = gerepileupto(av2, c2); if (DEBUGLEVEL) timer_printf(&ti,"tc2"); 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 (p>3 && 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 */ /* */ /***************************************************************************/ /* Return the lift of a (mod b), which is closest to h */ static GEN closest_lift(GEN a, GEN b, GEN h) { return addii(a, mulii(b, diviiround(subii(h,a), b))); } 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_timer Ti; long s = itos( gceil(gsqrt(gdiv(bound,B),DEFAULTPREC)) ) >> 1; GEN tx, ti; GEN fh = FlxqE_mul(f, h, a4, T, p); GEN F, P = fh, fg; long i; if (DEBUGLEVEL) timer_start(&Ti); if (ell_is_inf(fh)) return h; F = FlxqE_mul(f, B, a4, T, p); if (s < 3) { /* we're nearly done: naive search */ GEN Q = P; for (i=1;; i++) { 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))); Q = FlxqE_sub(Q, F, a4, T, p); /* h.f - i.F */ if (ell_is_inf(Q)) return gerepileupto(av, subii(h, mului(i,B))); } } tx = cgetg(s+1,t_VECSMALL); /* Baby Step/Giant Step */ av1 = avma; lim = stack_lim(av1,3); 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(DEBUGMEM>1) pari_warn(warnmem,"[ellap3] baby steps, i=%ld",i); P = gerepileupto(av1,P); } } if (DEBUGLEVEL) timer_printf(&Ti, "[ellap3] baby steps, s = %ld",s); /* giant steps: fg = s.F */ fg = gerepileupto(av1, FlxqE_sub(P, fh, a4, T, p)); if (ell_is_inf(fg)) return gerepileupto(av,mului(s,B)); 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); for (P=fg, i=1; ; i++) { long k = hash_GEN(gel(P,1)); long r = zv_search(tx, k); if (r) { while (r && tx[r] == k) r--; for (r++; r <= s && tx[r] == k; r++) { long j = ti[r]-1; GEN Q = FlxqE_add(FlxqE_mul(F, stoi(j), a4, T, p), fh, a4, T, p); if (DEBUGLEVEL) timer_printf(&Ti, "[ellap3] giant steps, i = %ld",i); if (Flx_equal(gel(P,1), gel(Q,1))) { if (Flx_equal(gel(P,2), gel(Q,2))) i = -i; return gerepileupto(av,addii(h, mulii(addis(mulss(s,i), j), B))); } } } P = FlxqE_add(P,fg,a4,T,p); if (low_stack(lim, stack_lim(av1,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"[ellap3] giants steps, i=%ld",i); P = gerepileupto(av1,P); } } } static void Flx_next(GEN t, ulong p) { long i; for(i=2;;i++) if ((ulong)t[i]==p-1) t[i]=0; else { t[i]++; break; } } static void Flx_renormalize_ip(GEN x, long lx) { long i; for (i = lx-1; i>=2; i--) if (x[i]) break; setlg(x, i+1); } static ulong F3xq_ellcard_naive(GEN a2, GEN a6, GEN T) { pari_sp av = avma; long i, d = get_Flx_degree(T), lx = d+2; long q = upowuu(3, d), a; GEN x = zero_zv(lx); x[1] = get_Flx_var(T); for(a=1, i=0; i= bound, it is completely determined */ /* how many 2-torsion points ? */ switch(FlxqX_nbroots(mkpoln(4, pol1_Flx(vn), pol0_Flx(vn), a4, a6), T, p)) { case 3: A = gen_0; B = utoipos(4); break; case 1: A = gen_0; B = gen_2; break; default: A = gen_1; B = gen_2; break; /* 0 */ } h = closest_lift(A, B, q1p); 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; /* [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(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) */ 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 * 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; } return gerepileuptoint(av, twistp? h: subii(shifti(q1p,1),h)); } static GEN F3xq_ellcard(GEN a2, GEN a6, GEN T) { long n = get_Flx_degree(T); if (n <= 2) return utoi(F3xq_ellcard_naive(a2, a6, T)); else { GEN q1 = addis(powuu(3, get_Flx_degree(T)), 1), t; GEN a = Flxq_div(a6,Flxq_powu(a2,3,T,3),T,3); if (Flx_equal1(Flxq_powu(a, 8, T, 3))) { GEN P = Flxq_minpoly(a,T,3); long dP = degpol(P); /* dP <= 2 */ ulong q = upowuu(3,dP); GEN A2 = pol1_Flx(P[1]), A6 = Flx_rem(polx_Flx(P[1]), P, 3); long tP = q + 1 - F3xq_ellcard_naive(A2, A6, P); t = elltrace_extension(stoi(tP), n/dP, utoi(q)); 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); } } static GEN Flxq_ellcard_Satoh(GEN a4, GEN a6, 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); } else return Flxq_ellcard_Harley(a4, a6, T, p); } } GEN Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av=avma; if (p==3) { GEN J; if (typ(a4)!=t_VEC) return pol0_Flx(get_Flx_var(T)); J = Flxq_div(Flxq_powu(gel(a4,1),3, T, p),Flx_neg(a6,p), T, p); return gerepileuptoleaf(av, J); } else { pari_sp av=avma; GEN a43 = Flxq_mul(a4,Flxq_sqr(a4,T,p),T,p); GEN a62 = Flxq_sqr(a6,T,p); GEN num = Flx_mulu(a43,6912,p); GEN den = Flx_add(Flx_mulu(a43,4,p),Flx_mulu(a62,27,p),p); return gerepileuptoleaf(av, Flxq_div(num, den, T, p)); } } static GEN F3xq_ellcardj(GEN a4, GEN a6, GEN T, GEN q, long n) { const ulong p = 3; ulong t; GEN q1 = addis(q,1); GEN na4 = Flx_neg(a4,p), ra4; if (!Flxq_issquare(na4,T,p)) return q1; ra4 = Flxq_sqrt(na4,T,p); t = Flxq_trace(Flxq_div(a6,Flxq_mul(na4,ra4,T,p),T,p),T,p); if (n%2==1) { GEN q3; if (t==0) return q1; q3 = powuu(p,(n+1)>>1); return (t==1)^(n%4==1) ? subii(q1,q3): addii(q1,q3); } else { GEN q22, q2 = powuu(p,n>>1); GEN W = Flxq_pow(a4,shifti(q,-2),T,p); long s = (W[2]==1)^(n%4==2); if (t!=0) return s ? addii(q1,q2): subii(q1, q2); q22 = shifti(q2,1); return s ? subii(q1,q22): addii(q1, q22); } } static GEN Flxq_ellcardj(GEN a4, GEN a6, ulong j, GEN T, GEN q, ulong p, long n) { GEN q1 = addis(q,1); if (j==0) { ulong w; GEN W, t, N; if (umodiu(q,6)!=1) return q1; N = Fp_ffellcard(gen_0,gen_1,q,n,utoi(p)); t = subii(q1, N); W = Flxq_pow(a6,diviuexact(shifti(q,-1), 3),T,p); if (degpol(W)>0) /*p=5 mod 6*/ return Flx_equal1(Flxq_powu(W,3,T,p)) ? addii(q1,shifti(t,-1)): subii(q1,shifti(t,-1)); w = W[2]; if (w==1) return N; if (w==p-1) return addii(q1,t); else /*p=1 mod 6*/ { GEN u = shifti(t,-1), v = sqrtint(diviuexact(subii(q,sqri(u)),3)); GEN a = addii(u,v), b = shifti(v,1); if (Fl_powu(w,3,p)==1) { if (Fl_add(umodiu(a,p),Fl_mul(w,umodiu(b,p),p),p)==0) return subii(q1,subii(shifti(b,1),a)); else return addii(q1,addii(a,b)); } else { if (Fl_sub(umodiu(a,p),Fl_mul(w,umodiu(b,p),p),p)==0) return subii(q1,subii(a,shifti(b,1))); else return subii(q1,addii(a,b)); } } } else if (j==1728%p) { ulong w; GEN W, N, t; if (mod4(q)==3) return q1; W = Flxq_pow(a4,shifti(q,-2),T,p); if (degpol(W)>0) return q1; /*p=3 mod 4*/ w = W[2]; N = Fp_ffellcard(gen_1,gen_0,q,n,utoi(p)); if(w==1) return N; t = subii(q1, N); if(w==p-1) return addii(q1, t); else /*p=1 mod 4*/ { GEN u = shifti(t,-1), v = sqrtint(subii(q,sqri(u))); if (Fl_add(umodiu(u,p),Fl_mul(w,umodiu(v,p),p),p)==0) return subii(q1,shifti(v,1)); else return addii(q1,shifti(v,1)); } } else { ulong g = Fl_div(j, Fl_sub(1728%p, j, p), p); GEN l = Flxq_div(Flx_triple(a6,p),Flx_double(a4,p),T,p); GEN N = Fp_ffellcard(utoi(Fl_triple(g,p)),utoi(Fl_double(g,p)),q,n,utoi(p)); if (Flxq_issquare(l,T,p)) return N; return subii(shifti(q1,1),N); } } GEN Flxq_ellcard(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av = avma; long n = get_Flx_degree(T); GEN J, r, q = powuu(p, n); if (typ(a4)==t_VEC) r = F3xq_ellcard(gel(a4,1), a6, T); else if (p==3) r = F3xq_ellcardj(a4, a6, T, q, n); else if (degpol(a4)<=0 && degpol(a6)<=0) 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 (cmpis(q,100)<0) r = utoi(Flxq_ellcard_naive(a4, a6, T, p)); else if (expi(q)<=62) r = Flxq_ellcard_Shanks(a4, a6, q, T, p); else { r = Fq_ellcard_SEA(Flx_to_ZX(a4),Flx_to_ZX(a6),q,Flx_to_ZX(T),utoi(p),0); if (!r) pari_err_PACKAGE("seadata"); } return gerepileuptoint(av, r); } pari-2.7.5/src/basemath/FpE.c0000644000175000017500000014432312453020470014303 0ustar billbill/* Copyright (C) 2009 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 Fp */ /***********************************************************************/ /** **/ /** 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 * 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. */ GEN RgE_to_FpE(GEN x, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_Fp(gel(x,1),p),Rg_to_Fp(gel(x,2),p)); } GEN FpE_to_mod(GEN x, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Fp_to_mod(gel(x,1),p),Fp_to_mod(gel(x,2),p)); } GEN FpE_changepoint(GEN x, GEN ch, GEN p) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = Fp_inv(u, p); v2 = Fp_sqr(v,p); v3 = Fp_mul(v,v2,p); p1 = Fp_sub(gel(x,1),r,p); z = cgetg(3,t_VEC); gel(z,1) = Fp_mul(v2, p1, p); gel(z,2) = Fp_mul(v3, Fp_sub(gel(x,2), Fp_add(Fp_mul(s,p1, p),t, p),p),p); return gerepileupto(av, z); } GEN FpE_changepointinv(GEN x, GEN ch, GEN p) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = Fp_sqr(u, p); u3 = Fp_mul(u,u2,p); u2X = Fp_mul(u2,X, p); z = cgetg(3, t_VEC); gel(z,1) = Fp_add(u2X,r,p); gel(z,2) = Fp_add(Fp_mul(u3,Y,p), Fp_add(Fp_mul(s,u2X,p), t, p), p); return z; } static GEN FpE_dbl_slope(GEN P, GEN a4, GEN p, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P) || !signe(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); *slope = Fp_div(Fp_add(Fp_mulu(Fp_sqr(x,p), 3, p), a4, p), Fp_mulu(y, 2, p), p); Q = cgetg(3,t_VEC); gel(Q, 1) = Fp_sub(Fp_sqr(*slope, p), Fp_mulu(x, 2, p), p); gel(Q, 2) = Fp_sub(Fp_mul(*slope, Fp_sub(x, gel(Q, 1), p), p), y, p); return Q; } GEN FpE_dbl(GEN P, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_dbl_slope(P,a4,p,&slope)); } static GEN FpE_add_slope(GEN P, GEN Q, GEN a4, GEN p, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (equalii(Px, Qx)) { if (equalii(Py, Qy)) return FpE_dbl_slope(P, a4, p, slope); else return ellinf(); } *slope = Fp_div(Fp_sub(Py, Qy, p), Fp_sub(Px, Qx, p), p); R = cgetg(3,t_VEC); gel(R, 1) = Fp_sub(Fp_sub(Fp_sqr(*slope, p), Px, p), Qx, p); gel(R, 2) = Fp_sub(Fp_mul(*slope, Fp_sub(Px, gel(R, 1), p), p), Py, p); return R; } GEN FpE_add(GEN P, GEN Q, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_add_slope(P,Q,a4,p,&slope)); } static GEN FpE_neg_i(GEN P, GEN p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), Fp_neg(gel(P,2), p)); } GEN FpE_neg(GEN P, GEN p) { if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), Fp_neg(gel(P,2), p)); } GEN FpE_sub(GEN P, GEN Q, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_add_slope(P, FpE_neg_i(Q, p), a4, p, &slope)); } struct _FpE { GEN a4,a6; GEN p; }; static GEN _FpE_dbl(void *E, GEN P) { struct _FpE *ell = (struct _FpE *) E; return FpE_dbl(P, ell->a4, ell->p); } static GEN _FpE_add(void *E, GEN P, GEN Q) { struct _FpE *ell=(struct _FpE *) E; return FpE_add(P, Q, ell->a4, ell->p); } static GEN _FpE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FpE *e=(struct _FpE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = FpE_neg(P, e->p); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepileupto(av, gen_pow(P, n, e, &_FpE_dbl, &_FpE_add)); } GEN FpE_mul(GEN P, GEN n, GEN a4, GEN p) { struct _FpE E; E.a4= a4; E.p = p; return _FpE_mul(&E, P, n); } /* Finds a random non-singular point on E */ GEN random_FpE(GEN a4, GEN a6, GEN p) { pari_sp ltop = avma; GEN x, x2, y, rhs; do { avma= ltop; x = randomi(p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ x2 = Fp_sqr(x, p); rhs = Fp_add(Fp_mul(x, Fp_add(x2, a4, p), p), a6, p); } while ((!signe(rhs) && !signe(Fp_add(Fp_mulu(x2,3,p),a4,p))) || kronecker(rhs, p) < 0); y = Fp_sqrt(rhs, p); if (!y) pari_err_PRIME("random_FpE", p); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _FpE_rand(void *E) { struct _FpE *e=(struct _FpE *) E; return random_FpE(e->a4, e->a6, e->p); } static const struct bb_group FpE_group={_FpE_add,_FpE_mul,_FpE_rand,hash_GEN,ZV_equal,ell_is_inf,NULL}; const struct bb_group * get_FpE_group(void ** pt_E, GEN a4, GEN a6, GEN p) { struct _FpE *e = (struct _FpE *) stack_malloc(sizeof(struct _FpE)); e->a4 = a4; e->a6 = a6; e->p = p; *pt_E = (void *) e; return &FpE_group; } GEN 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 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)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN FpE_vert(GEN P, GEN Q, GEN p) { if (ell_is_inf(P)) return gen_1; return Fp_sub(gel(Q, 1), gel(P, 1), p); } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN FpE_tangent_update(GEN R, GEN Q, GEN a4, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return gen_1; } else if (signe(gel(R,2)) == 0) { *pt_R = ellinf(); return FpE_vert(R, Q, p); } else { GEN slope, tmp1, tmp2; *pt_R = FpE_dbl_slope(R, a4, p, &slope); tmp1 = Fp_sub(gel(Q, 1), gel(R, 1), p); tmp2 = Fp_add(Fp_mul(tmp1, slope, p), gel(R,2), p); return Fp_sub(gel(Q, 2), tmp2, p); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN FpE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FpE_vert(P, Q, p); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FpE_vert(R, Q, p); } else if (equalii(gel(P, 1), gel(R, 1))) { if (equalii(gel(P, 2), gel(R, 2))) return FpE_tangent_update(R, Q, a4, p, pt_R); else { *pt_R = ellinf(); return FpE_vert(R, Q, p); } } else { GEN slope, tmp1, tmp2; *pt_R = FpE_add_slope(P, R, a4, p, &slope); tmp1 = Fp_mul(Fp_sub(gel(Q, 1), gel(R, 1), p), slope, p); tmp2 = Fp_add(tmp1, gel(R, 2), p); return Fp_sub(gel(Q, 2), tmp2, p); } } /* Returns the Miller function f_{m, Q} evaluated at the point P using the standard Miller algorithm. */ struct _FpE_miller { GEN p, a4, P; }; static GEN FpE_Miller_dbl(void* E, GEN d) { struct _FpE_miller *m = (struct _FpE_miller *)E; GEN p = m->p, a4 = m->a4, P = m->P; GEN v, line; GEN num = Fp_sqr(gel(d,1), p); GEN denom = Fp_sqr(gel(d,2), p); GEN point = gel(d,3); line = FpE_tangent_update(point, P, a4, p, &point); num = Fp_mul(num, line, p); v = FpE_vert(point, P, p); denom = Fp_mul(denom, v, p); return mkvec3(num, denom, point); } static GEN FpE_Miller_add(void* E, GEN va, GEN vb) { struct _FpE_miller *m = (struct _FpE_miller *)E; GEN p = m->p, a4= m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN num = Fp_mul(na, nb, p); GEN denom = Fp_mul(da, db, p); line = FpE_chord_update(pa, pb, P, a4, p, &point); num = Fp_mul(num, line, p); v = FpE_vert(point, P, p); denom = Fp_mul(denom, v, p); return mkvec3(num, denom, point); } static GEN FpE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN p) { pari_sp ltop = avma; struct _FpE_miller d; GEN v, num, denom; d.a4 = a4; d.p = p; d.P = P; v = gen_pow(mkvec3(gen_1,gen_1,Q), m, (void*)&d, FpE_Miller_dbl, FpE_Miller_add); num = gel(v,1); denom = gel(v,2); if (!signe(num) || !signe(denom)) { avma = ltop; return NULL; } return gerepileupto(ltop, Fp_div(num, denom, p)); } GEN FpE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN p) { pari_sp ltop = avma; GEN num, denom, result; if (ell_is_inf(P) || ell_is_inf(Q) || ZV_equal(P,Q)) return gen_1; num = FpE_Miller(P, Q, m, a4, p); if (!num) return gen_1; denom = FpE_Miller(Q, P, m, a4, p); if (!denom) { avma = ltop; return gen_1; } result = Fp_div(num, denom, p); if (mpodd(m)) result = Fp_neg(result, p); return gerepileupto(ltop, result); } GEN FpE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN p) { GEN num; if (ell_is_inf(P) || ell_is_inf(Q)) return gen_1; num = FpE_Miller(P, Q, m, a4, p); return num? num: gen_1; } /***********************************************************************/ /** **/ /** Cardinal **/ /** **/ /***********************************************************************/ /*assume a4,a6 reduced mod p and 3 < p < 1627 */ static ulong Fl_ellcard_naive(ulong a4, ulong a6, ulong p) { ulong i; long a = p+1; for(i=0; i= k */ static void _fix(GEN x, long k) { GEN y = (GEN)*x; 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 */ static GEN closest_lift(GEN a, GEN b, GEN h) { return addii(a, mulii(b, diviiround(subii(h,a), b))); } static long get_table_size(GEN pordmin, GEN B) { pari_sp av = avma; GEN t = ceilr( sqrtr( divri(itor(pordmin, DEFAULTPREC), B) ) ); if (is_bigint(t)) pari_err_OVERFLOW("ellap [large prime: install the 'seadata' package]"); avma = av; return itos(t) >> 1; } /* 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; 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; tx = NULL; ty = ti = NULL; /* gcc -Wall */ 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; /* how many 2-torsion points ? */ switch(FpX_nbroots(mkpoln(4, gen_1, gen_0, c4, c6), p)) { case 3: A = gen_0; B = utoipos(4); break; 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); } 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 */ tx = newblock(3*(s+1)); ty = tx + (s+1); ti = ty + (s+1); } F = FpE_mul(f,B,a4,p); *tx = CODE; /* F = B.f */ P = gcopy(fh); if (s < 3) { /* we're nearly done: naive search */ GEN q1 = P, mF = FpE_neg(F, p); /* -F */ for (i=1;; i++) { P = FpE_add(P,F,a4,p); /* h.f + i.F */ if (ell_is_inf(P)) { h = addii(h, mului(i,B)); goto FOUND; } q1 = FpE_add(q1,mF,a4,p); /* h.f - i.F */ if (ell_is_inf(q1)) { h = subii(h, mului(i,B)); goto FOUND; } } } /* Baby Step/Giant Step */ nb = minss(128, s >> 1); /* > 0. Will do nb pts at a time: faster inverse */ pts = cgetg(nb+1, t_VEC); j = lgefint(p); for (i=1; i<=nb; i++) { /* baby steps */ gel(pts,i) = P; /* h.f + (i-1).F */ _fix(P+1, j); tx[i] = mod2BIL(gel(P,1)); _fix(P+2, j); ty[i] = mod2BIL(gel(P,2)); P = FpE_add(P,F,a4,p); /* h.f + i.F */ if (ell_is_inf(P)) { h = addii(h, mului(i,B)); goto FOUND; } } mfh = FpE_neg(fh, p); fg = FpE_add(P,mfh,a4,p); /* h.f + nb.F - h.f = nb.F */ if (ell_is_inf(fg)) { h = mului(nb,B); goto FOUND; } u = cgetg(nb+1, t_VEC); av2 = avma; /* more baby steps, nb points at a time */ while (i <= s) { long maxj; for (j=1; j<=nb; j++) /* adding nb.F (part 1) */ { P = gel(pts,j); /* h.f + (i-nb-1+j-1).F */ gel(u,j) = subii(gel(fg,1), gel(P,1)); if (!signe(gel(u,j))) /* sum = 0 or doubling */ { long k = i+j-2; if (equalii(gel(P,2),gel(fg,2))) k -= 2*nb; /* fg == P */ h = addii(h, mulsi(k,B)); goto FOUND; } } v = FpV_inv(u, p); maxj = (i-1 + nb <= s)? nb: s % nb; for (j=1; j<=maxj; j++,i++) /* adding nb.F (part 2) */ { P = gel(pts,j); FpE_add_ip(P,fg, a4,p, gel(v,j)); tx[i] = mod2BIL(gel(P,1)); ty[i] = mod2BIL(gel(P,2)); } avma = av2; } P = FpE_add(gel(pts,j-1),mfh,a4,p); /* = (s-1).F */ if (ell_is_inf(P)) { h = mului(s-1,B); goto FOUND; } if (DEBUGLEVEL) timer_printf(&T, "[Fp_ellcard_Shanks] baby steps, s = %ld",s); /* giant steps: fg = s.F */ fg = FpE_add(P,F,a4,p); if (ell_is_inf(fg)) { h = mului(s,B); goto FOUND; } pfinal = mod2BIL(p); av2 = avma; /* Goal of the following: sort points by increasing x-coordinate hash. * Done in a complicated way to avoid allocating a large temp vector */ p1 = vecsmall_indexsort(tx); /* = permutation sorting tx */ for (i=1; i<=s; i++) ti[i] = tx[p1[i]]; /* ti = tx sorted */ for (i=1; i<=s; i++) { tx[i] = ti[i]; ti[i] = ty[p1[i]]; } /* tx is sorted. ti = ty sorted */ for (i=1; i<=s; i++) { ty[i] = ti[i]; ti[i] = p1[i]; } /* ty is sorted. ti = permutation sorting tx */ if (DEBUGLEVEL) timer_printf(&T, "[Fp_ellcard_Shanks] sorting"); avma = av2; gaffect(fg, gel(pts,1)); for (j=2; j<=nb; j++) /* pts[j] = j.fg = (s*j).F */ { P = FpE_add(gel(pts,j-1),fg,a4,p); if (ell_is_inf(P)) { h = mulii(mulss(s,j), B); goto FOUND; } gaffect(P, gel(pts,j)); } /* replace fg by nb.fg since we do nb points at a time */ avma = av2; fg = gcopy(gel(pts,nb)); /* copy: we modify (temporarily) pts[nb] below */ av2 = avma; for (i=1,j=1; ; i++) { GEN ftest = gel(pts,j); long m, l = 1, r = s+1; long k, k2, j2; avma = av2; k = mod2BIL(gel(ftest,1)); while (l < r) { m = (l+r) >> 1; if (tx[m] < k) l = m+1; else r = m; } if (r <= s && tx[r] == k) { while (r && tx[r] == k) r--; k2 = mod2BIL(gel(ftest,2)); for (r++; r <= s && tx[r] == k; r++) if (ty[r] == k2 || ty[r] == pfinal - k2) { /* [h+j2] f == +/- ftest (= [i.s] f)? */ j2 = ti[r] - 1; if (DEBUGLEVEL) timer_printf(&T, "[Fp_ellcard_Shanks] giant steps, i = %ld",i); P = FpE_add(FpE_mul(F,stoi(j2),a4,p),fh,a4,p); if (equalii(gel(P,1), gel(ftest,1))) { if (equalii(gel(P,2), gel(ftest,2))) i = -i; h = addii(h, mulii(addis(mulss(s,i), j2), B)); goto FOUND; } } } if (++j > nb) { /* compute next nb points */ long save = 0; /* gcc -Wall */; for (j=1; j<=nb; j++) { P = gel(pts,j); gel(u,j) = subii(gel(fg,1), gel(P,1)); if (gel(u,j) == gen_0) /* occurs once: i = j = nb, P == fg */ { gel(u,j) = shifti(gel(P,2),1); save = fg[1]; fg[1] = P[1]; } } v = FpV_inv(u, p); for (j=1; j<=nb; j++) FpE_add_ip(gel(pts,j),fg,a4,p, gel(v,j)); if (i == nb) { fg[1] = save; } j = 1; } } 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 * 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; } if (tx) killblock(tx); return gerepileuptoint(av, KRO==1? h: subii(shifti(p1p,1),h)); } typedef struct { ulong x,y,i; } multiple; static int compare_multiples(multiple *a, multiple *b) { return a->x > b->x? 1:a->xx?-1:0; } static long sclosest_lift(long A, long B, ulong p2p) { return A + B * (((ulong)(p2p + B - (A << 1))) / (B << 1)); } /* assume p > 99 and e has good reduction at p. Should use Montgomery. * 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; pari_sp av = avma; multiple *table; pordmin = (long)(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, 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) { 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); } 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 (!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]; table[i].y = fh[2]; table[i].i = i; if (Fle_add_inplace(fh, F, cp4, p)) { h += B*(i+1); goto FOUND; } } qsort(table,s,sizeof(multiple),(QSCOMP)compare_multiples); fg = Fle_mulu(F, s, cp4, p); ftest = zv_copy(fg); if (ell_is_inf(ftest)) { if (!uisprime(p)) pari_err_PRIME("ellap",utoi(p)); pari_err_BUG("ellap (f^(i*s) = 1)"); } for (i=1; ; i++) { l=0; r=s; while (l> 1; if (table[m].x < (ulong) ftest[1]) l=m+1; else r=m; } if (r < s && table[r].x == (ulong) 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; else { 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; } /* h = A mod B, closest lift to p+1 */ h = sclosest_lift(A, B, p2p); avma = av; if (!i) break; } return KRO==1? h: 2*p1p-h; } /** ellap from CM (original code contributed by Mark Watkins) **/ static ulong Mod16(GEN x) { long s = signe(x); ulong m; if (!s) return 0; m = mod16(x); if (!m) return m; if (s < 0) m = 16 - m; return m; } #define Mod2(x) (Mod16(x) & 1) #define Mod4(x) (Mod16(x) & 3) #define Mod8(x) (Mod16(x) & 7) static GEN ap_j0(GEN a6,GEN p) { GEN a, b, e, d; if (umodiu(p,3) != 1) return gen_0; (void)cornacchia2(utoipos(27),p, &a,&b); if (umodiu(a, 3) == 1) a = negi(a); d = mulis(a6,-108); e = diviuexact(shifti(p,-1), 3); /* (p-1) / 6 */ return centermod(mulii(a, Fp_pow(d, e, p)), p); } static GEN ap_j1728(GEN a4,GEN p) { GEN a, b, e; if (mod4(p) != 1) return gen_0; (void)cornacchia2(utoipos(4),p, &a,&b); if (Mod4(a)==0) a = b; if (Mod2(a)==1) a = shifti(a,1); if (Mod8(a)==6) a = negi(a); e = shifti(p,-2); /* (p-1) / 4 */ return centermod(mulii(a, Fp_pow(a4, e, p)), p); } static GEN ap_j8000(GEN a6, GEN p) { GEN a, b; long r = mod8(p), s = 1; if (r != 1 && r != 3) return gen_0; (void)cornacchia2(utoipos(8),p, &a,&b); switch(Mod16(a)) { case 2: case 6: if (Mod4(b)) s = -s; break; case 10: case 14: if (!Mod4(b)) s = -s; break; } if (kronecker(mulis(a6, 42), p) < 0) s = -s; return s > 0? a: negi(a); } static GEN ap_j287496(GEN a6, GEN p) { GEN a, b; long s = 1; if (mod4(p) != 1) return gen_0; (void)cornacchia2(utoipos(4),p, &a,&b); if (Mod4(a)==0) a = b; if (Mod2(a)==1) a = shifti(a,1); if (Mod8(a)==6) s = -s; if (krosi(2,p) < 0) s = -s; if (kronecker(mulis(a6, -14), p) < 0) s = -s; return s > 0? a: negi(a); } static GEN ap_cm(int CM, long A6B, GEN a6, GEN p) { GEN a, b; long s = 1; if (krosi(CM,p) < 0) return gen_0; (void)cornacchia2(utoipos(-CM),p, &a, &b); if ((CM&3) == 0) CM >>= 2; if ((krois(a, -CM) > 0) ^ (CM == -7)) s = -s; 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) { switch(CM) { case -3: return ap_j0(a6, p); case -4: return ap_j1728(a4, p); case -8: return ap_j8000(a6, p); case -16: return ap_j287496(a6, p); case -7: return ap_cm(CM, -2, a6, p); case -11: return ap_cm(CM, 21, a6, p); case -12: return ap_cm(CM, 22, a6, p); case -19: return ap_cm(CM, 1, a6, p); case -27: return ap_cm(CM, 253, a6, p); case -28: return ap_cm(-7, -114, a6, p); /* yes, -7 ! */ case -43: return ap_cm(CM, 21, a6, p); case -67: return ap_cm(CM, 217, a6, p); case -163:return ap_cm(CM, 185801, a6, 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) { GEN a43 = Fp_mulu(Fp_powu(a4, 3, p), 4, p); GEN a62 = Fp_mulu(Fp_sqr(a6, p), 27, p); return mkvec2(Fp_mulu(a43, 1728, p), Fp_add(a43, a62, p)); } GEN Fp_ellj(GEN a4, GEN a6, GEN p) { pari_sp av=avma; GEN z = Fp_ellj_nodiv(a4, a6, p); return gerepileuptoint(av,Fp_div(gel(z,1),gel(z,2),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; } GEN Fp_ellcard(GEN a4, GEN a6, GEN p) { long lp = expi(p); ulong pp = p[2]; if (lp < 7) return utoi(Fl_ellcard_naive(umodiu(a4,pp), umodiu(a6,pp), pp)); { 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) 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); } 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; } static GEN _FpE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FpE *e = (struct _FpE *) E; return Fp_order(FpE_weilpairing(P,Q,m,e->a4,e->p), F, e->p); } GEN Fp_ellgroup(GEN a4, GEN a6, GEN N, GEN p, GEN *pt_m) { struct _FpE e; e.a4=a4; e.a6=a6; e.p=p; return gen_ellgroup(N, subis(p, 1), pt_m, (void*)&e, &FpE_group, _FpE_pairorder); } GEN Fp_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p) { GEN P; pari_sp av = avma; struct _FpE e; e.a4=a4; e.a6=a6; e.p=p; switch(lg(D)-1) { case 1: P = gen_gener(gel(D,1), (void*)&e, &FpE_group); P = mkvec(FpE_changepoint(P, ch, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FpE_group, _FpE_pairorder); gel(P,1) = FpE_changepoint(gel(P,1), ch, p); gel(P,2) = FpE_changepoint(gel(P,2), ch, p); break; } return gerepilecopy(av, P); } /* Not so fast arithmetic with points over elliptic curves over FpXQ */ /***********************************************************************/ /** **/ /** FpXQE **/ /** **/ /***********************************************************************/ /* Theses functions deal with point over elliptic curves over FpXQ 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. */ GEN RgE_to_FpXQE(GEN x, GEN T, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_FpXQ(gel(x,1),T,p),Rg_to_FpXQ(gel(x,2),T,p)); } GEN FpXQE_changepoint(GEN x, GEN ch, GEN T, GEN p) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = FpXQ_inv(u, T, p); v2 = FpXQ_sqr(v, T, p); v3 = FpXQ_mul(v,v2, T, p); p1 = FpX_sub(gel(x,1),r, p); z = cgetg(3,t_VEC); gel(z,1) = FpXQ_mul(v2, p1, T, p); gel(z,2) = FpXQ_mul(v3, FpX_sub(gel(x,2), FpX_add(FpXQ_mul(s,p1, T, p),t, p), p), T, p); return gerepileupto(av, z); } GEN FpXQE_changepointinv(GEN x, GEN ch, GEN T, GEN p) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = FpXQ_sqr(u, T, p); u3 = FpXQ_mul(u,u2, T, p); u2X = FpXQ_mul(u2,X, T, p); z = cgetg(3, t_VEC); gel(z,1) = FpX_add(u2X,r, p); gel(z,2) = FpX_add(FpXQ_mul(u3,Y, T, p), FpX_add(FpXQ_mul(s,u2X, T, p), t, p), p); return z; } static GEN FpXQE_dbl_slope(GEN P, GEN a4, GEN T, GEN p, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P) || !signe(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); *slope = FpXQ_div(FpX_add(FpX_mulu(FpXQ_sqr(x, T, p), 3, p), a4, p), FpX_mulu(y, 2, p), T, p); Q = cgetg(3,t_VEC); gel(Q, 1) = FpX_sub(FpXQ_sqr(*slope, T, p), FpX_mulu(x, 2, p), p); gel(Q, 2) = FpX_sub(FpXQ_mul(*slope, FpX_sub(x, gel(Q, 1), p), T, p), y, p); return Q; } GEN FpXQE_dbl(GEN P, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_dbl_slope(P,a4,T,p,&slope)); } static GEN FpXQE_add_slope(GEN P, GEN Q, GEN a4, GEN T, GEN p, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (ZX_equal(Px, Qx)) { if (ZX_equal(Py, Qy)) return FpXQE_dbl_slope(P, a4, T, p, slope); else return ellinf(); } *slope = FpXQ_div(FpX_sub(Py, Qy, p), FpX_sub(Px, Qx, p), T, p); R = cgetg(3,t_VEC); gel(R, 1) = FpX_sub(FpX_sub(FpXQ_sqr(*slope, T, p), Px, p), Qx, p); gel(R, 2) = FpX_sub(FpXQ_mul(*slope, FpX_sub(Px, gel(R, 1), p), T, p), Py, p); return R; } GEN FpXQE_add(GEN P, GEN Q, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_add_slope(P,Q,a4,T,p,&slope)); } static GEN FpXQE_neg_i(GEN P, GEN p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), FpX_neg(gel(P,2), p)); } GEN FpXQE_neg(GEN P, GEN T, GEN p) { (void) T; if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), FpX_neg(gel(P,2), p)); } GEN FpXQE_sub(GEN P, GEN Q, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_add_slope(P, FpXQE_neg_i(Q, p), a4, T, p, &slope)); } struct _FpXQE { GEN a4,a6; GEN T,p; }; static GEN _FpXQE_dbl(void *E, GEN P) { struct _FpXQE *ell = (struct _FpXQE *) E; return FpXQE_dbl(P, ell->a4, ell->T, ell->p); } static GEN _FpXQE_add(void *E, GEN P, GEN Q) { struct _FpXQE *ell=(struct _FpXQE *) E; return FpXQE_add(P, Q, ell->a4, ell->T, ell->p); } static GEN _FpXQE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FpXQE *e=(struct _FpXQE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = FpXQE_neg(P, e->T, e->p); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepileupto(av, gen_pow(P, n, e, &_FpXQE_dbl, &_FpXQE_add)); } GEN FpXQE_mul(GEN P, GEN n, GEN a4, GEN T, GEN p) { struct _FpXQE E; E.a4= a4; E.T = T; E.p = p; return _FpXQE_mul(&E, P, n); } /* Finds a random non-singular point on E */ GEN random_FpXQE(GEN a4, GEN a6, GEN T, GEN p) { pari_sp ltop = avma; GEN x, x2, y, rhs; long v = get_FpX_var(T), d = get_FpX_degree(T); do { avma= ltop; x = random_FpX(d,v,p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ x2 = FpXQ_sqr(x, T, p); rhs = FpX_add(FpXQ_mul(x, FpX_add(x2, a4, p), T, p), a6, p); } while ((!signe(rhs) && !signe(FpX_add(FpX_mulu(x2,3,p), a4, p))) || !FpXQ_issquare(rhs, T, p)); y = FpXQ_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_FpE", p); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _FpXQE_rand(void *E) { struct _FpXQE *e=(struct _FpXQE *) E; return random_FpXQE(e->a4, e->a6, e->T, e->p); } static const struct bb_group FpXQE_group={_FpXQE_add,_FpXQE_mul,_FpXQE_rand,hash_GEN,ZXV_equal,ell_is_inf}; const struct bb_group * get_FpXQE_group(void ** pt_E, GEN a4, GEN a6, GEN T, GEN p) { struct _FpXQE *e = (struct _FpXQE *) stack_malloc(sizeof(struct _FpXQE)); e->a4 = a4; e->a6 = a6; e->T = T; e->p = p; *pt_E = (void *) e; return &FpXQE_group; } GEN FpXQE_order(GEN z, GEN o, GEN a4, GEN T, GEN p) { pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &FpXQE_group)); } GEN FpXQE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, GEN p) { pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &FpXQE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN FpXQE_vert(GEN P, GEN Q, GEN T, GEN p) { if (ell_is_inf(P)) return pol_1(get_FpX_var(T)); return FpX_sub(gel(Q, 1), gel(P, 1), p); } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN FpXQE_tangent_update(GEN R, GEN Q, GEN a4, GEN T, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol_1(get_FpX_var(T)); } else if (!signe(gel(R,2))) { *pt_R = ellinf(); return FpXQE_vert(R, Q, T, p); } else { GEN slope, tmp1, tmp2; *pt_R = FpXQE_dbl_slope(R, a4, T, p, &slope); tmp1 = FpX_sub(gel(Q, 1), gel(R, 1), p); tmp2 = FpX_add(FpXQ_mul(tmp1, slope, T, p), gel(R,2), p); return FpX_sub(gel(Q, 2), tmp2, p); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN FpXQE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN T, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FpXQE_vert(P, Q, T, p); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FpXQE_vert(R, Q, T, p); } else if (ZX_equal(gel(P, 1), gel(R, 1))) { if (ZX_equal(gel(P, 2), gel(R, 2))) return FpXQE_tangent_update(R, Q, a4, T, p, pt_R); else { *pt_R = ellinf(); return FpXQE_vert(R, Q, T, p); } } else { GEN slope, tmp1, tmp2; *pt_R = FpXQE_add_slope(P, R, a4, T, p, &slope); tmp1 = FpXQ_mul(FpX_sub(gel(Q, 1), gel(R, 1), p), slope, T, p); tmp2 = FpX_add(tmp1, gel(R, 2), p); return FpX_sub(gel(Q, 2), tmp2, p); } } /* Returns the Miller function f_{m, Q} evaluated at the point P using the standard Miller algorithm. */ struct _FpXQE_miller { GEN p; GEN T, a4, P; }; static GEN FpXQE_Miller_dbl(void* E, GEN d) { struct _FpXQE_miller *m = (struct _FpXQE_miller *)E; GEN p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line; GEN num = FpXQ_sqr(gel(d,1), T, p); GEN denom = FpXQ_sqr(gel(d,2), T, p); GEN point = gel(d,3); line = FpXQE_tangent_update(point, P, a4, T, p, &point); num = FpXQ_mul(num, line, T, p); v = FpXQE_vert(point, P, T, p); denom = FpXQ_mul(denom, v, T, p); return mkvec3(num, denom, point); } static GEN FpXQE_Miller_add(void* E, GEN va, GEN vb) { struct _FpXQE_miller *m = (struct _FpXQE_miller *)E; GEN p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN num = FpXQ_mul(na, nb, T, p); GEN denom = FpXQ_mul(da, db, T, p); line = FpXQE_chord_update(pa, pb, P, a4, T, p, &point); num = FpXQ_mul(num, line, T, p); v = FpXQE_vert(point, P, T, p); denom = FpXQ_mul(denom, v, T, p); return mkvec3(num, denom, point); } static GEN FpXQE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN T, GEN p) { pari_sp ltop = avma; struct _FpXQE_miller d; GEN v, num, denom, g1; d.a4 = a4; d.T = T; d.p = p; d.P = P; g1 = pol_1(get_FpX_var(T)); v = gen_pow(mkvec3(g1,g1,Q), m, (void*)&d, FpXQE_Miller_dbl, FpXQE_Miller_add); num = gel(v,1); denom = gel(v,2); if (!signe(num) || !signe(denom)) { avma = ltop; return NULL; } return gerepileupto(ltop, FpXQ_div(num, denom, T, p)); } GEN FpXQE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, GEN p) { pari_sp ltop = avma; GEN num, denom, result; if (ell_is_inf(P) || ell_is_inf(Q) || ZXV_equal(P,Q)) return pol_1(get_FpX_var(T)); num = FpXQE_Miller(P, Q, m, a4, T, p); if (!num) return pol_1(get_FpX_var(T)); denom = FpXQE_Miller(Q, P, m, a4, T, p); if (!denom) { avma = ltop; return pol_1(get_FpX_var(T)); } result = FpXQ_div(num, denom, T, p); if (mpodd(m)) result = FpX_neg(result, p); return gerepileupto(ltop, result); } GEN FpXQE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, GEN p) { GEN num; if (ell_is_inf(P) || ell_is_inf(Q)) return pol_1(get_FpX_var(T)); num = FpXQE_Miller(P, Q, m, a4, T, p); return num? num: pol_1(get_FpX_var(T)); } /***********************************************************************/ /** **/ /** Point counting **/ /** **/ /***********************************************************************/ GEN FpXQ_ellj(GEN a4, GEN a6, GEN T, GEN p) { if (equaliu(p,3)) return pol_0(get_FpX_var(T)); else { pari_sp av=avma; GEN a43 = FpXQ_mul(a4,FpXQ_sqr(a4,T,p),T,p); GEN a62 = FpXQ_sqr(a6,T,p); GEN num = FpX_mulu(a43,6912,p); GEN den = FpX_add(FpX_mulu(a43,4,p),FpX_mulu(a62,27,p),p); return gerepileuptoleaf(av, FpXQ_div(num, den, T, p)); } } 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 te = addii(shifti(gel(v,1),1), mulii(t,gel(v,2))); return gerepileuptoint(av, te); } GEN Fp_ffellcard(GEN a4, GEN a6, GEN q, long n, GEN p) { pari_sp av = avma; GEN ap = subii(addis(p, 1), Fp_ellcard(a4, a6, p)); GEN te = elltrace_extension(ap, n, p); return gerepileuptoint(av, subii(addis(q, 1), te)); } static GEN FpXQ_ellcardj(GEN a4, GEN a6, GEN j, GEN T, GEN q, GEN p, long n) { GEN q1 = addis(q,1); if (signe(j)==0) { GEN W, w, t, N; if (umodiu(q,6)!=1) return q1; N = Fp_ffellcard(gen_0,gen_1,q,n,p); t = subii(q1, N); W = FpXQ_pow(a6,diviuexact(shifti(q,-1), 3),T,p); if (degpol(W)>0) /*p=5 mod 6*/ return ZX_equal1(FpXQ_powu(W,3,T,p)) ? addii(q1,shifti(t,-1)): subii(q1,shifti(t,-1)); w = modii(gel(W,2),p); if (equali1(w)) return N; if (equalii(w,subiu(p,1))) return addii(q1,t); else /*p=1 mod 6*/ { GEN u = shifti(t,-1), v = sqrtint(diviuexact(subii(q,sqri(u)),3)); GEN a = addii(u,v), b = shifti(v,1); if (equali1(Fp_powu(w,3,p))) { if (signe(Fp_add(modii(a,p),Fp_mul(w,modii(b,p),p),p))==0) return subii(q1,subii(shifti(b,1),a)); else return addii(q1,addii(a,b)); } else { if (signe(Fp_sub(modii(a,p),Fp_mul(w,modii(b,p),p),p))==0) return subii(q1,subii(a,shifti(b,1))); else return subii(q1,addii(a,b)); } } } else if (equalii(j,modsi(1728,p))) { GEN w, W, N, t; if (mod4(q)==3) return q1; W = FpXQ_pow(a4,shifti(q,-2),T,p); if (degpol(W)>0) return q1; /*p=3 mod 4*/ w = modii(gel(W,2),p); N = Fp_ffellcard(gen_1,gen_0,q,n,p); if (equali1(w)) return N; t = subii(q1, N); if (equalii(w,subiu(p,1))) return addii(q1,t); else /*p=1 mod 4*/ { GEN u = shifti(t,-1), v = sqrtint(subii(q,sqri(u))); if (signe(Fp_add(modii(u,p),Fp_mul(w,modii(v,p),p),p))==0) return subii(q1,shifti(v,1)); else return addii(q1,shifti(v,1)); } } else { GEN g = Fp_div(j, Fp_sub(utoi(1728), j, p), p); GEN l = FpXQ_div(FpX_mulu(a6,3,p),FpX_mulu(a4,2,p),T,p); GEN N = Fp_ffellcard(Fp_mulu(g,3,p),Fp_mulu(g,2,p),q,n,p); if (FpXQ_issquare(l,T,p)) return N; return subii(shifti(q1,1),N); } } GEN FpXQ_ellcard(GEN a4, GEN a6, GEN T, GEN p) { pari_sp av = avma; long n = get_FpX_degree(T); GEN q = powiu(p, n), r, J; if (degpol(a4)<=0 && degpol(a6)<=0) r = Fp_ffellcard(constant_term(a4),constant_term(a6),q,n,p); else if (lgefint(p)==3) { ulong pp = p[2]; r = Flxq_ellcard(ZX_to_Flx(a4,pp),ZX_to_Flx(a6,pp),ZX_to_Flx(T,pp),pp); } else if (degpol(J=FpXQ_ellj(a4,a6,T,p))<=0) r = FpXQ_ellcardj(a4,a6,constant_term(J),T,q,p,n); else { r = Fq_ellcard_SEA(a4, a6, q, T, p, 0); if (!r) pari_err_PACKAGE("seadata"); } return gerepileuptoint(av, r); } static GEN _FpXQE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FpXQE *e = (struct _FpXQE *) E; return FpXQ_order(FpXQE_weilpairing(P,Q,m,e->a4,e->T,e->p), F, e->T, e->p); } GEN FpXQ_ellgroup(GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pt_m) { struct _FpXQE e; GEN q = powiu(p, get_FpX_degree(T)); e.a4=a4; e.a6=a6; e.T=T; e.p=p; return gen_ellgroup(N, subis(q,1), pt_m, (void*)&e, &FpXQE_group, _FpXQE_pairorder); } GEN FpXQ_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p) { GEN P; pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.a6=a6; e.T=T; e.p=p; switch(lg(D)-1) { case 1: P = gen_gener(gel(D,1), (void*)&e, &FpXQE_group); P = mkvec(FpXQE_changepoint(P, ch, T, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FpXQE_group, _FpXQE_pairorder); gel(P,1) = FpXQE_changepoint(gel(P,1), ch, T, p); gel(P,2) = FpXQE_changepoint(gel(P,2), ch, T, p); break; } return gerepilecopy(av, P); } /***********************************************************************/ /** **/ /** n-division polynomial **/ /** **/ /***********************************************************************/ struct divpol_red { GEN h, T, p; }; INLINE GEN _red(GEN x, struct divpol_red *r) { return r->h ? FqX_rem(x,r->h,r->T,r->p): gcopy(x); } INLINE GEN _rsqr(GEN x, struct divpol_red *r) { GEN h=r->h, T=r->T, p=r->p; return h ? FqXQ_sqr(x,h,T,p): FqX_sqr(x,T,p); } INLINE GEN _rmul(GEN x, GEN y, struct divpol_red *r) { GEN h=r->h, T=r->T, p=r->p; return h ? FqXQ_mul(x,y,h,T,p): FqX_mul(x,y,T,p); } static GEN divpol(GEN t, GEN a4, GEN a6, GEN r2, long n, struct divpol_red *r); static GEN divpol_f2(GEN t, GEN a4, GEN a6, GEN r2, long n, struct divpol_red *r) { if (gmael(t,2,n)) return gmael(t,2,n); if (n<=2) return scalarpol(gen_1,0); gmael(t,2,n) = _rsqr(divpol(t,a4,a6,r2,n,r),r); return gmael(t,2,n); } static GEN divpol_ff(GEN t, GEN a4, GEN a6, GEN r2, long n, struct divpol_red *r) { if(gmael(t,3,n)) return gmael(t,3,n); if (n<=4) return divpol(t,a4,a6,r2,n,r); gmael(t,3,n) = _rmul(divpol(t,a4,a6,r2,n,r), divpol(t,a4,a6,r2,n-2,r),r); return gmael(t,3,n); } static GEN divpol(GEN t, GEN a4, GEN a6, GEN r2, long n, struct divpol_red *r) { long m = n/2; GEN res; GEN T=r->T, p=r->p; if (gmael(t,1,n)) return gmael(t,1,n); switch(n) { case 1: case 2: res = scalarpol(gen_1,0); break; case 3: res = _red(mkpoln(5, utoi(3), gen_0, Fq_mulu(a4, 6, T, p), Fq_mulu(a6, 12, T, p), Fq_neg(Fq_sqr(a4, T, p), T, p)), r); break; case 4: { GEN a42 = Fq_sqr(a4, T, p); res = _red(FqX_mulu(mkpoln(7, gen_1, gen_0, Fq_mulu(a4, 5, T, p), Fq_mulu(a6, 20, T, p), Fq_Fp_mul(a42,stoi(-5), T, p), Fq_Fp_mul(Fq_mul(a4, a6, T, p), stoi(-4), T, p), Fq_sub(Fq_Fp_mul(Fq_sqr(a6, T, p), stoi(-8), T, p), Fq_mul(a4,a42, T, p), T, p)), 2, T, p), r); } break; default: if (odd(n)) if (odd(m)) res = FqX_sub(_rmul(divpol_ff(t,a4,a6,r2,m+2,r), divpol_f2(t,a4,a6,r2,m,r), r), _rmul(r2, _rmul(divpol_ff(t,a4,a6,r2,m+1,r), divpol_f2(t,a4,a6,r2,m+1,r), r), r), T, p); else res = FqX_sub(_rmul(r2, _rmul(divpol_ff(t,a4,a6,r2,m+2,r), divpol_f2(t,a4,a6,r2,m,r), r), r), _rmul(divpol_ff(t,a4,a6,r2,m+1,r), divpol_f2(t,a4,a6,r2,m+1,r), r), T, p); else res = FqX_sub(_rmul(divpol_ff(t,a4,a6,r2,m+2,r), divpol_f2(t,a4,a6,r2,m-1,r), r), _rmul(divpol_ff(t,a4,a6,r2,m,r), divpol_f2(t,a4,a6,r2,m+1,r), r), T, p); } gmael(t,1,n) = res; return res; } /*Computes the n-division polynomial modulo the polynomial h \in Fq[x] */ GEN Fq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, GEN p) { struct divpol_red r; pari_sp ltop = avma; GEN t, rhs, r2; if (n <= 2) return scalarpol(gen_1,0); r.h=h; r.T=T; r.p=p; t = mkvec3(const_vec(n, NULL),const_vec(n, NULL),const_vec(n, NULL)); rhs = FqX_mulu(_red(mkpoln(4, gen_1, gen_0, a4, a6), &r), 4, T, p); r2 = _rsqr(rhs,&r); return gerepilecopy(ltop, divpol(t,a4,a6,r2,n,&r)); } GEN FpXQ_elldivpol(GEN a4, GEN a6, long n, GEN T, GEN p) { return Fq_elldivpolmod(a4,a6,n,NULL,T,p); } GEN Fp_elldivpol(GEN a4, GEN a6, long n, GEN p) { return Fq_elldivpolmod(a4,a6,n,NULL,NULL,p); } pari-2.7.5/src/basemath/Qfb.c0000644000175000017500000011201312405547147014344 0ustar billbill/* Copyright (C) 2000-2005 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" /*******************************************************************/ /* */ /* QUADRATIC POLYNOMIAL ASSOCIATED TO A DISCRIMINANT */ /* */ /*******************************************************************/ void check_quaddisc(GEN x, long *s, long *r, const char *f) { if (typ(x) != t_INT) pari_err_TYPE(f,x); *s = signe(x); if (Z_issquare(x)) pari_err_DOMAIN(f,"issquare(disc)","=", gen_1,x); *r = mod4(x); if (*s < 0 && *r) *r = 4 - *r; if (*r > 1) pari_err_DOMAIN(f,"disc % 4",">", gen_1,x); } void check_quaddisc_real(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx < 0) pari_err_DOMAIN(f, "disc","<",gen_0,x); } void check_quaddisc_imag(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx > 0) pari_err_DOMAIN(f, "disc",">",gen_0,x); } /* X^2 + b X + c is the canonical quadratic t_POL of discriminant D. * Dodd is non-zero iff D is odd */ static void quadpoly_bc(GEN D, long Dodd, GEN *b, GEN *c) { if (Dodd) { pari_sp av = avma; *b = gen_m1; *c = gerepileuptoint(av, shifti(subui(1,D), -2)); } else { *b = gen_0; *c = shifti(D,-2); togglesign(*c); } } /* X^2 - X - (D-1)/4 or X^2 - D/4 */ GEN quadpoly(GEN D) { long Dmod4, s; GEN b, c, y = cgetg(5,t_POL); check_quaddisc(D, &s, &Dmod4, "quadpoly"); y[1] = evalsigne(1) | evalvarn(0); quadpoly_bc(D, Dmod4, &b,&c); gel(y,2) = c; gel(y,3) = b; gel(y,4) = gen_1; return y; } GEN quadpoly0(GEN x, long v) { GEN T = quadpoly(x); if (v > 0) setvarn(T, v); return T; } GEN quadgen(GEN x) { retmkquad(quadpoly(x), gen_0, gen_1); } /***********************************************************************/ /** **/ /** BINARY QUADRATIC FORMS **/ /** **/ /***********************************************************************/ GEN qfi(GEN x, GEN y, GEN z) { if (signe(x) < 0) pari_err_IMPL("negative definite t_QFI"); retmkqfi(icopy(x),icopy(y),icopy(z)); } GEN qfr(GEN x, GEN y, GEN z, GEN d) { if (typ(d) != t_REAL) pari_err_TYPE("qfr",d); retmkqfr(icopy(x),icopy(y),icopy(z),rcopy(d)); } GEN Qfb0(GEN x, GEN y, GEN z, GEN d, long prec) { pari_sp av = avma; GEN D; long s, r; if (typ(x)!=t_INT) pari_err_TYPE("Qfb",x); if (typ(y)!=t_INT) pari_err_TYPE("Qfb",y); if (typ(z)!=t_INT) pari_err_TYPE("Qfb",z); D = qfb_disc3(x,y,z); check_quaddisc(D, &s, &r, "Qfb"); avma = av; if (s < 0) return qfi(x, y, z); d = d? gtofp(d,prec): real_0(prec); return qfr(x,y,z,d); } /* composition */ static void qfb_sqr(GEN z, GEN x) { GEN c, d1, x2, v1, v2, c3, m, p1, r; d1 = bezout(gel(x,2),gel(x,1),&x2, NULL); /* usually 1 */ c = gel(x,3); m = mulii(c,x2); if (is_pm1(d1)) v1 = v2 = gel(x,1); else { v1 = diviiexact(gel(x,1),d1); v2 = mulii(v1, gcdii(d1,c)); /* = v1 iff x primitive */ c = mulii(c, d1); } togglesign(m); r = modii(m,v2); p1 = mulii(r, v1); c3 = addii(c, mulii(r,addii(gel(x,2),p1))); gel(z,1) = mulii(v1,v2); gel(z,2) = addii(gel(x,2), shifti(p1,1)); gel(z,3) = diviiexact(c3,v2); } /* z <- x * y */ static void qfb_comp(GEN z, GEN x, GEN y) { GEN n, c, d, y1, v1, v2, c3, m, p1, r; if (x == y) { qfb_sqr(z,x); return; } n = shifti(subii(gel(y,2),gel(x,2)), -1); v1 = gel(x,1); v2 = gel(y,1); c = gel(y,3); d = bezout(v2,v1,&y1,NULL); if (is_pm1(d)) m = mulii(y1,n); else { GEN s = subii(gel(y,2), n); GEN x2, y2, d1 = bezout(s,d,&x2,&y2); /* x2 s + y2 (x1 v1 + y1 v2) = d1 */ if (!is_pm1(d1)) { v1 = diviiexact(v1,d1); v2 = diviiexact(v2,d1); /* gcd = 1 iff x or y primitive */ v1 = mulii(v1, gcdii(c,gcdii(gel(x,3),gcdii(d1,n)))); c = mulii(c, d1); } m = addii(mulii(mulii(y1,y2),n), mulii(gel(y,3),x2)); } togglesign(m); r = modii(m, v1); p1 = mulii(r, v2); c3 = addii(c, mulii(r,addii(gel(y,2),p1))); gel(z,1) = mulii(v1,v2); gel(z,2) = addii(gel(y,2), shifti(p1,1)); gel(z,3) = diviiexact(c3,v1); } static GEN redimag_av(pari_sp av, GEN q); static GEN qficomp0(GEN x, GEN y, int raw) { pari_sp av = avma; GEN z = cgetg(4,t_QFI); qfb_comp(z, x,y); if (raw) return gerepilecopy(av,z); return redimag_av(av, z); } static GEN qfrcomp0(GEN x, GEN y, int raw) { pari_sp av = avma; GEN z = cgetg(5,t_QFR); qfb_comp(z, x,y); gel(z,4) = addrr(gel(x,4),gel(y,4)); if (raw) return gerepilecopy(av,z); return gerepileupto(av, redreal(z)); } GEN qfrcomp(GEN x, GEN y) { return qfrcomp0(x,y,0); } GEN qfrcompraw(GEN x, GEN y) { return qfrcomp0(x,y,1); } GEN qficomp(GEN x, GEN y) { return qficomp0(x,y,0); } GEN qficompraw(GEN x, GEN y) { return qficomp0(x,y,1); } GEN qfbcompraw(GEN x, GEN y) { long tx = typ(x); if (typ(y) != tx) pari_err_TYPE2("*",x,y); switch(tx) { case t_QFI: return qficompraw(x,y); case t_QFR: return qfrcompraw(x,y); } pari_err_TYPE("composition",x); return NULL; /* not reached */ } static GEN qfisqr0(GEN x, long raw) { pari_sp av = avma; GEN z = cgetg(4,t_QFI); if (typ(x)!=t_QFI) pari_err_TYPE("composition",x); qfb_sqr(z,x); if (raw) return gerepilecopy(av,z); return redimag_av(av, z); } static GEN qfrsqr0(GEN x, long raw) { pari_sp av = avma; GEN z = cgetg(5,t_QFR); if (typ(x)!=t_QFR) pari_err_TYPE("composition",x); qfb_sqr(z,x); gel(z,4) = shiftr(gel(x,4),1); if (raw) return gerepilecopy(av,z); return gerepileupto(av, redreal(z)); } GEN qfrsqr(GEN x) { return qfrsqr0(x,0); } GEN qfrsqrraw(GEN x) { return qfrsqr0(x,1); } GEN qfisqr(GEN x) { return qfisqr0(x,0); } GEN qfisqrraw(GEN x) { return qfisqr0(x,1); } static GEN qfr_1_by_disc(GEN D, long prec) { GEN y = cgetg(5,t_QFR), isqrtD; pari_sp av = avma; long r; check_quaddisc_real(D, &r, "qfr_1_by_disc"); gel(y,1) = gen_1; isqrtD = sqrti(D); if ((r & 1) != mod2(isqrtD)) /* we know isqrtD > 0 */ isqrtD = gerepileuptoint(av, addsi(-1,isqrtD)); gel(y,2) = isqrtD; av = avma; gel(y,3) = gerepileuptoint(av, shifti(subii(sqri(isqrtD), D),-2)); gel(y,4) = real_0(prec); return y; } GEN qfr_1(GEN x) { if (typ(x) != t_QFR) pari_err_TYPE("qfr_1",x); return qfr_1_by_disc(qfb_disc(x), precision(gel(x,4))); } static void qfr_1_fill(GEN y, struct qfr_data *S) { pari_sp av = avma; GEN y2 = S->isqrtD; gel(y,1) = gen_1; if (mod2(S->D) != mod2(y2)) y2 = addsi(-1,y2); gel(y,2) = y2; av = avma; gel(y,3) = gerepileuptoint(av, shifti(subii(sqri(y2), S->D),-2)); } static GEN qfr5_1(struct qfr_data *S, long prec) { GEN y = cgetg(6, t_VEC); qfr_1_fill(y, S); gel(y,4) = gen_0; gel(y,5) = real_1(prec); return y; } static GEN qfr3_1(struct qfr_data *S) { GEN y = cgetg(4, t_VEC); qfr_1_fill(y, S); return y; } /* Assume D < 0 is the discriminant of a t_QFI */ static GEN qfi_1_by_disc(GEN D) { GEN b,c, y = cgetg(4,t_QFI); quadpoly_bc(D, mod2(D), &b,&c); gel(y,1) = gen_1; gel(y,2) = b; gel(y,3) = c; return y; } GEN qfi_1(GEN x) { if (typ(x) != t_QFI) pari_err_TYPE("qfi_1",x); return qfi_1_by_disc(qfb_disc(x)); } static GEN invraw(GEN x) { GEN y = gcopy(x); if (typ(y) == t_QFR) togglesign(gel(y,4)); togglesign(gel(y,2)); return y; } GEN qfrpowraw(GEN x, long n) { pari_sp av = avma; long m; GEN y; if (typ(x) != t_QFR) pari_err_TYPE("qfrpowraw",x); if (!n) return qfr_1(x); if (n== 1) return gcopy(x); if (n==-1) return invraw(x); y = NULL; m = labs(n); for (; m>1; m>>=1) { if (m&1) y = y? qfrcompraw(y,x): x; x = qfrsqrraw(x); } y = y? qfrcompraw(y,x): x; if (n < 0) y = invraw(y); return gerepileupto(av,y); } GEN qfipowraw(GEN x, long n) { pari_sp av = avma; long m; GEN y; if (typ(x) != t_QFI) pari_err_TYPE("qfipow",x); if (!n) return qfi_1(x); if (n== 1) return gcopy(x); if (n==-1) return invraw(x); y = NULL; m = labs(n); for (; m>1; m>>=1) { if (m&1) y = y? qficompraw(y,x): x; x = qfisqrraw(x); } y = y? qficompraw(y,x): x; if (n < 0) y = invraw(y); return gerepileupto(av,y); } GEN qfbpowraw(GEN x, long n) { return (typ(x)==t_QFI)? qfipowraw(x,n): qfrpowraw(x,n); } static long parteucl(GEN L, GEN *d, GEN *v3, GEN *v, GEN *v2) { long z; *v = gen_0; *v2 = gen_1; for (z=0; absi_cmp(*v3,L) > 0; z++) { GEN t3, t2 = subii(*v, mulii(truedvmdii(*d,*v3,&t3),*v2)); *v = *v2; *d = *v3; *v2 = t2; *v3 = t3; } return z; } /* composition: Shanks' NUCOMP & NUDUPL */ /* L = floor((|d|/4)^(1/4)) */ GEN nucomp(GEN x, GEN y, GEN L) { pari_sp av = avma; long z; GEN a, a1, a2, b2, b, d, d1, g, n, p1, q1, q2, s, u, u1, v, v2, v3, Q; if (x==y) return nudupl(x,L); if (typ(x) != t_QFI) pari_err_TYPE("nucomp",x); if (typ(y) != t_QFI) pari_err_TYPE("nucomp",y); if (absi_cmp(gel(x,1),gel(y,1)) < 0) swap(x, y); s = shifti(addii(gel(x,2),gel(y,2)), -1); n = subii(gel(y,2), s); a1 = gel(x,1); a2 = gel(y,1); d = bezout(a2,a1,&u,&v); if (is_pm1(d)) { a = negi(mulii(u,n)); d1 = d; } else if (remii(s,d) == gen_0) /* d | s */ { a = negi(mulii(u,n)); d1 = d; a1 = diviiexact(a1, d1); a2 = diviiexact(a2, d1); s = diviiexact(s, d1); } else { GEN p2, l; d1 = bezout(s,d,&u1,NULL); if (!is_pm1(d1)) { a1 = diviiexact(a1,d1); a2 = diviiexact(a2,d1); s = diviiexact(s,d1); d = diviiexact(d,d1); } p1 = remii(gel(x,3),d); p2 = remii(gel(y,3),d); l = modii(mulii(negi(u1), addii(mulii(u,p1),mulii(v,p2))), d); a = subii(mulii(l,diviiexact(a1,d)), mulii(u,diviiexact(n,d))); } a = modii(a,a1); p1 = subii(a,a1); if (absi_cmp(a,p1) > 0) a = p1; d = a1; v3 = a; z = parteucl(L, &d,&v3, &v,&v2); Q = cgetg(4,t_QFI); if (!z) { g = diviiexact(addii(mulii(v3,s),gel(y,3)), d); b = a2; b2 = gel(y,2); v2 = d1; gel(Q,1) = mulii(d,b); } else { GEN e, q3, q4; if (z&1) { v3 = negi(v3); v2 = negi(v2); } b = diviiexact(addii(mulii(a2,d), mulii(n,v)), a1); e = diviiexact(addii(mulii(s,d),mulii(gel(y,3),v)), a1); q3 = mulii(e,v2); q4 = subii(q3,s); b2 = addii(q3,q4); g = diviiexact(q4,v); if (!is_pm1(d1)) { v2 = mulii(d1,v2); v = mulii(d1,v); b2 = mulii(d1,b2); } gel(Q,1) = addii(mulii(d,b), mulii(e,v)); } q1 = mulii(b, v3); q2 = addii(q1,n); gel(Q,2) = addii(b2, z? addii(q1,q2): shifti(q1, 1)); gel(Q,3) = addii(mulii(v3,diviiexact(q2,d)), mulii(g,v2)); return redimag_av(av, Q); } GEN nudupl(GEN x, GEN L) { pari_sp av = avma; long z; GEN u, v, d, d1, p1, a, b, c, a2, b2, c2, Q, v2, v3, g; if (typ(x) != t_QFI) pari_err_TYPE("nudupl",x); a = gel(x,1); b = gel(x,2); d1 = bezout(b,a, &u,NULL); if (!is_pm1(d1)) { a = diviiexact(a, d1); b = diviiexact(b, d1); } c = modii(negi(mulii(u,gel(x,3))), a); p1 = subii(c,a); if (absi_cmp(c,p1) > 0) c = p1; d = a; v3 = c; z = parteucl(L, &d,&v3, &v,&v2); a2 = sqri(d); c2 = sqri(v3); Q = cgetg(4,t_QFI); if (!z) { g = diviiexact(addii(mulii(v3,b),gel(x,3)), d); b2 = gel(x,2); v2 = d1; gel(Q,1) = a2; } else { GEN e; if (z&1) { v = negi(v); d = negi(d); } e = diviiexact(addii(mulii(gel(x,3),v), mulii(b,d)), a); g = diviiexact(subii(mulii(e,v2), b), v); b2 = addii(mulii(e,v2), mulii(v,g)); if (!is_pm1(d1)) { b2 = mulii(d1,b2); v = mulii(d1,v); v2 = mulii(d1,v2); } gel(Q,1) = addii(a2, mulii(e,v)); } gel(Q,2) = addii(b2, subii(sqri(addii(d,v3)), addii(a2,c2))); gel(Q,3) = addii(c2, mulii(g,v2)); return redimag_av(av, Q); } static GEN mul_nucomp(void *l, GEN x, GEN y) { return nucomp(x, y, (GEN)l); } static GEN mul_nudupl(void *l, GEN x) { return nudupl(x, (GEN)l); } GEN nupow(GEN x, GEN n) { pari_sp av; GEN y, D; if (typ(n) != t_INT) pari_err_TYPE("nupow",n); if (typ(x) != t_QFI) pari_err_TYPE("nupow",x); if (gequal1(n)) return gcopy(x); av = avma; D = qfb_disc(x); y = qfi_1_by_disc(D); if (!signe(n)) return y; y = gen_pow(x, n, (void*)sqrtnint(absi(D), 4), &mul_nudupl, &mul_nucomp); if (signe(n) < 0 && !absi_equal(gel(y,1),gel(y,2)) && !absi_equal(gel(y,1),gel(y,3))) togglesign(gel(y,2)); return gerepileupto(av, y); } /* Reduction */ /* assume a > 0. Write b = q*2a + r, with -a < r <= a */ static GEN dvmdii_round(GEN b, GEN a, GEN *r) { GEN a2 = shifti(a, 1), q = dvmdii(b, a2, r); if (signe(b) >= 0) { if (absi_cmp(*r, a) > 0) { q = addis(q, 1); *r = subii(*r, a2); } } else { /* r <= 0 */ if (absi_cmp(*r, a) >= 0){ q = addis(q, -1); *r = addii(*r, a2); } } return q; } /* Assume 0 < a <= LONG_MAX. Ensure no overflow */ static long dvmdsu_round(long b, ulong a, long *r) { ulong a2 = a << 1, q, ub, ur; if (b >= 0) { ub = b; q = ub / a2; ur = ub % a2; if (ur > a) { ur -= a; q++; *r = (long)ur; *r -= (long)a; } else *r = (long)ur; return (long)q; } else { /* r <= 0 */ ub = (ulong)-b; /* |b| */ q = ub / a2; ur = ub % a2; if (ur >= a) { ur -= a; q++; *r = (long)ur; *r = (long)a - *r; } else *r = -(long)ur; return -(long)q; } } /* reduce b mod 2*a. Update b,c */ static void REDB(GEN a, GEN *b, GEN *c) { GEN r, q = dvmdii_round(*b, a, &r); if (!signe(q)) return; *c = subii(*c, mulii(q, shifti(addii(*b, r),-1))); *b = r; } /* Assume a > 0. Reduce b mod 2*a. Update b,c */ static void sREDB(ulong a, long *b, ulong *c) { long r, q; ulong uz; if (a > LONG_MAX) return; /* b already reduced */ q = dvmdsu_round(*b, a, &r); if (q == 0) return; /* Final (a,r,c2) satisfies |r| <= |b| hence c2 <= c, c2 = c - q*z, * where z = (b+r) / 2, representable as long, has the same sign as q. */ if (*b < 0) { /* uz = -z >= 0, q < 0 */ if (r >= 0) /* different signs=>no overflow, exact division */ uz = (ulong)-((*b + r)>>1); else { ulong ub = (ulong)-*b, ur = (ulong)-r; uz = (ub + ur) >> 1; } *c -= (-q) * uz; /* c -= qz */ } else { /* uz = z >= 0, q > 0 */ if (r <= 0) uz = (*b + r)>>1; else { ulong ub = (ulong)*b, ur = (ulong)r; uz = ((ub + ur) >> 1); } *c -= q * uz; /* c -= qz */ } *b = r; } static void REDBU(GEN a, GEN *b, GEN *c, GEN u1, GEN *u2) { /* REDB(a,b,c) */ GEN r, q = dvmdii_round(*b, a, &r); *c = subii(*c, mulii(q, shifti(addii(*b, r),-1))); *b = r; *u2 = subii(*u2, mulii(q, u1)); } /* q t_QFI, return reduced representative and set base change U in Sl2(Z) */ GEN redimagsl2(GEN q, GEN *U) { GEN Q = cgetg(4, t_QFI); pari_sp av = avma, av2, lim = stack_lim(av, 1); 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) */ (void)new_chunk(2*(lgefint(a) + lgefint(b) + lgefint(c) + 3)); av2 = avma; u1 = gen_1; u2 = gen_0; cmp = absi_cmp(a, b); if (cmp < 0) REDBU(a,&b,&c, u1,&u2); else if (cmp == 0 && signe(b) < 0) { /* b = -a */ b = negi(b); u2 = gen_1; } for(;;) { cmp = absi_cmp(a, c); if (cmp <= 0) break; 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 (DEBUGMEM>1) pari_warn(warnmem, "redimagsl2"); gerepileall(av2, 5, &a,&b,&c, &u1,&u2); } } if (cmp == 0 && signe(b) < 0) { b = negi(b); z = u1; u1 = u2; u2 = negi(z); } avma = av; a = icopy(a); gel(Q,1) = a; b = icopy(b); gel(Q,2) = b; c = icopy(c); gel(Q,3) = c; u1 = icopy(u1); u2 = icopy(u2); av = avma; /* Let q = (A,B,C). q o [u1,u2; v1,v2] = Q implies * [v1,v2] = (1/C) [(b-B)/2 u1 - a u2, c u1 - (b+B)/2 u2] */ z = shifti(subii(b, gel(q,2)), -1); v1 = subii(mulii(z, u1), mulii(a, u2)); v1 = diviiexact(v1, gel(q,3)); z = subii(z, b); v2 = addii(mulii(z, u2), mulii(c, u1)); v2 = diviiexact(v2, gel(q,3)); avma = av; v1 = icopy(v1); v2 = icopy(v2); *U = mkmat2(mkcol2(u1,v1), mkcol2(u2,v2)); return Q; } static GEN setq_b0(ulong a, ulong c) { retmkqfi( utoipos(a), gen_0, utoipos(c) ); } /* assume |sb| = 1 */ static GEN setq(ulong a, ulong b, ulong c, long sb) { retmkqfi( utoipos(a), sb == 1? utoipos(b): utoineg(b), utoipos(c) ); } /* 0 < a, c < 2^BIL, b = 0 */ static GEN redimag_1_b0(ulong a, ulong c) { return (a <= c)? setq_b0(a, c): setq_b0(c, a); } /* 0 < a, c < 2^BIL: single word affair */ static GEN redimag_1(pari_sp av, GEN a, GEN b, GEN c) { ulong ua, ub, uc; long sb; for(;;) { /* 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; REDB(a,&b,&c); if ((ulong)a[2] <= (ulong)c[2]) { /* lg(b) <= 3 but may be too large for itos */ long s = signe(b); avma = av; if (!s) return redimag_1_b0(a[2], c[2]); if (a[2] == c[2]) s = 1; return setq(a[2], b[2], c[2], s); } swap(a,c); b = negi(b); } /* b != 0 */ avma = av; ua = a[2]; ub = sb = b[2]; if (signe(b) < 0) sb = -sb; uc = c[2]; if (ua < ub) sREDB(ua, &sb, &uc); else if (ua == ub && sb < 0) sb = (long)ub; while(ua > uc) { lswap(ua,uc); sb = -sb; sREDB(ua, &sb, &uc); } if (!sb) return setq_b0(ua, uc); else { long s = 1; if (sb < 0) { sb = -sb; if (ua != uc) s = -1; } return setq(ua, sb, uc, s); } } static GEN redimag_av(pari_sp av, GEN q) { GEN a = gel(q,1), b = gel(q,2), c = gel(q,3); long cmp, lc = lgefint(c); if (lgefint(a) == 3 && lc == 3) return redimag_1(av, a, b, c); cmp = absi_cmp(a, b); if (cmp < 0) REDB(a,&b,&c); else if (cmp == 0 && signe(b) < 0) b = negi(b); for(;;) { cmp = absi_cmp(a, c); if (cmp <= 0) break; lc = lgefint(a); /* lg(future c): we swap a & c next */ if (lc == 3) return redimag_1(av, a, b, c); swap(a,c); b = negi(b); /* apply rho */ REDB(a,&b,&c); } if (cmp == 0 && signe(b) < 0) b = negi(b); /* size of reduced Qfb(a,b,c) <= 3 lg(c) + 4 <= 4 lg(c) */ (void)new_chunk(lc<<2); a = icopy(a); b = icopy(b); c = icopy(c); avma = av; retmkqfi(icopy(a), icopy(b), icopy(c)); } GEN redimag(GEN q) { return redimag_av(avma, q); } static GEN rhoimag(GEN x) { GEN a = gel(x,1), b = gel(x,2), c = gel(x,3); int fl = absi_cmp(a, c); if (fl <= 0) { int fg = absi_cmp(a, b); if (fg >= 0) { x = qfi(a,b,c); if ((!fl || !fg) && signe(gel(x,2)) < 0) setsigne(gel(x,2), 1); return x; } } x = cgetg(4, t_QFI); (void)new_chunk(lgefint(a) + lgefint(b) + lgefint(c) + 3); swap(a,c); b = negi(b); REDB(a, &b, &c); avma = (pari_sp)x; gel(x,1) = icopy(a); gel(x,2) = icopy(b); gel(x,3) = icopy(c); return x; } /* qfr3 / qfr5 */ /* t_QFR are unusable: D, sqrtD, isqrtD are recomputed all the time and the * logarithmic Shanks's distance is costly and hard to control. * qfr3 / qfr5 routines take a container of t_INTs (e.g a t_VEC) as argument, * at least 3 (resp. 5) components [it is a feature that they do not check the * precise type or length of the input]. They return a vector of length 3 * (resp. 5). A qfr3 [a,b,c] contains the form coeffs, in a qfr5 [a,b,c, e,d] * the t_INT e is a binary exponent, d a t_REAL, coding the distance in * multiplicative form: the true distance is obtained from qfr5_dist. * All other qfr routines are obsolete (inefficient) wrappers */ /* static functions are not stack-clean. Unless mentionned otherwise, public * functions are. */ #define EMAX 22 static void fix_expo(GEN x) { if (expo(gel(x,5)) >= (1L << EMAX)) { gel(x,4) = addsi(1, gel(x,4)); shiftr_inplace(gel(x, 5), - (1L << EMAX)); } } /* (1/2) log (d * 2^{e * 2^EMAX}). Not stack clean if e != 0 */ GEN qfr5_dist(GEN e, GEN d, long prec) { GEN t = logr_abs(d); if (signe(e)) { GEN u = mulir(e, mplog2(prec)); shiftr_inplace(u, EMAX); t = addrr(t, u); } shiftr_inplace(t, -1); return t; } static void rho_get_BC(GEN *B, GEN *C, GEN b, GEN c, struct qfr_data *S) { GEN t, u; u = shifti(c,1); t = (absi_cmp(S->isqrtD,c) >= 0)? S->isqrtD: c; u = remii(addii_sign(t,1, b,signe(b)), u); *B = addii_sign(t, 1, u, -signe(u)); /* |t| - (|t|+b) % |2c| */ if (*B == gen_0) { u = shifti(S->D, -2); setsigne(u, -1); } else u = shifti(addii_sign(sqri(*B),1, S->D,-1), -2); *C = diviiexact(u, c); /* = (B^2-D)/4c */ } /* Not stack-clean */ GEN qfr3_rho(GEN x, struct qfr_data *S) { GEN B, C, b = gel(x,2), c = gel(x,3); rho_get_BC(&B, &C, b, c, S); return mkvec3(c,B,C); } /* Not stack-clean */ GEN qfr5_rho(GEN x, struct qfr_data *S) { GEN B, C, y, b = gel(x,2), c = gel(x,3); long sb = signe(b); rho_get_BC(&B, &C, b, c, S); y = mkvec5(c,B,C, gel(x,4), gel(x,5)); if (sb) { GEN t = subii(sqri(b), S->D); if (sb < 0) t = divir(t, sqrr(subir(b,S->sqrtD))); else t = divri(sqrr(addir(b,S->sqrtD)), t); /* t = (b + sqrt(D)) / (b - sqrt(D)), evaluated stably */ gel(y,5) = mulrr(t, gel(y,5)); fix_expo(y); } return y; } /* Not stack-clean */ GEN qfr_to_qfr5(GEN x, long prec) { return mkvec5(gel(x,1),gel(x,2),gel(x,3),gen_0,real_1(prec)); } /* d0 = initial distance, x = [a,b,c, expo(d), d], d = exp(2*distance) */ GEN qfr5_to_qfr(GEN x, GEN d0) { GEN y; if (lg(x) == 6) { GEN n = gel(x,4), d = absr(gel(x,5)); if (signe(n)) { n = addis(shifti(n, EMAX), expo(d)); setexpo(d, 0); d = logr_abs(d); if (signe(n)) d = addrr(d, mulir(n, mplog2(lg(d0)))); shiftr_inplace(d, -1); d0 = addrr(d0, d); } else if (!gequal1(d)) /* avoid loss of precision */ { d = logr_abs(d); shiftr_inplace(d, -1); d0 = addrr(d0, d); } } y = cgetg(5, t_QFR); gel(y,1) = gel(x,1); gel(y,2) = gel(x,2); gel(y,3) = gel(x,3); gel(y,4) = d0; return y; } /* Not stack-clean */ GEN qfr3_to_qfr(GEN x, GEN d) { GEN z = cgetg(5, t_QFR); gel(z,1) = gel(x,1); gel(z,2) = gel(x,2); gel(z,3) = gel(x,3); gel(z,4) = d; return z; } static int ab_isreduced(GEN a, GEN b, GEN isqrtD) { if (signe(b) > 0 && absi_cmp(b, isqrtD) <= 0) { GEN t = addii_sign(isqrtD,1, shifti(a,1),-1); long l = absi_cmp(b, t); /* compare |b| and |floor(sqrt(D)) - |2a|| */ if (l > 0 || (l == 0 && signe(t) < 0)) return 1; } return 0; } INLINE int qfr_isreduced(GEN x, GEN isqrtD) { return ab_isreduced(gel(x,1),gel(x,2),isqrtD); } /* Not stack-clean */ GEN qfr5_red(GEN x, struct qfr_data *S) { while (!qfr_isreduced(x,S->isqrtD)) x = qfr5_rho(x,S); return x; } /* Not stack-clean */ GEN qfr3_red(GEN x, struct qfr_data *S) { while (!qfr_isreduced(x, S->isqrtD)) x = qfr3_rho(x, S); return x; } static void get_disc(GEN x, struct qfr_data *S) { if (!S->D) S->D = qfb_disc(x); else if (typ(S->D) != t_INT) pari_err_TYPE("qfr_init",S->D); if (!signe(S->D)) pari_err_DOMAIN("qfr_init", "disc", "=", gen_0,x); } void qfr_data_init(GEN D, long prec, struct qfr_data *S) { S->D = D; S->sqrtD = sqrtr(itor(S->D,prec)); S->isqrtD = truncr(S->sqrtD); } 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; x = qfr_to_qfr5(x,prec); get_disc(x, S); if (!S->sqrtD) S->sqrtD = sqrtr(itor(S->D,prec)); else if (typ(S->sqrtD) != t_REAL) pari_err_TYPE("qfr_init",S->sqrtD); if (!S->isqrtD) { pari_sp av=avma; long e; S->isqrtD = gcvtoi(S->sqrtD,&e); if (e>-2) { avma = av; S->isqrtD = sqrti(S->D); } } else if (typ(S->isqrtD) != t_INT) pari_err_TYPE("qfr_init",S->isqrtD); return x; } static GEN qfr3_init(GEN x, struct qfr_data *S) { get_disc(x, S); if (!S->isqrtD) S->isqrtD = sqrti(S->D); else if (typ(S->isqrtD) != t_INT) pari_err_TYPE("qfr_init",S->isqrtD); return x; } #define qf_NOD 2 #define qf_STEP 1 static GEN redreal0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD) { pari_sp av = avma; struct qfr_data S; GEN d; if (typ(x) != t_QFR) pari_err_TYPE("redreal",x); d = gel(x,4); S.D = D; S.sqrtD = sqrtD; S.isqrtD = isqrtD; x = (flag & qf_NOD)? qfr3_init(x, &S): qfr5_init(x, &S); switch(flag) { case 0: x = qfr5_red(x,&S); break; case qf_NOD: x = qfr3_red(x,&S); break; case qf_STEP: x = qfr5_rho(x,&S); break; case qf_STEP|qf_NOD: x = qfr3_rho(x,&S); break; default: pari_err_FLAG("qfbred"); } return gerepilecopy(av, qfr5_to_qfr(x,d)); } GEN redreal(GEN x) { return redreal0(x,0,NULL,NULL,NULL); } GEN rhoreal(GEN x) { return redreal0(x,qf_STEP,NULL,NULL,NULL); } GEN redrealnod(GEN x, GEN isqrtD) { return redreal0(x,qf_NOD,NULL,isqrtD,NULL); } GEN rhorealnod(GEN x, GEN isqrtD) { return redreal0(x,qf_STEP|qf_NOD,NULL,isqrtD,NULL); } GEN qfbred0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD) { if (typ(x) == t_QFI) return (flag & qf_STEP)? rhoimag(x): redimag(x); return redreal0(x,flag,D,isqrtD,sqrtD); } GEN qfr5_comp(GEN x, GEN y, struct qfr_data *S) { pari_sp av = avma; GEN z = cgetg(6,t_VEC); qfb_comp(z,x,y); if (x == y) { gel(z,4) = shifti(gel(x,4),1); gel(z,5) = sqrr(gel(x,5)); } else { gel(z,4) = addii(gel(x,4),gel(y,4)); gel(z,5) = mulrr(gel(x,5),gel(y,5)); } fix_expo(z); z = qfr5_red(z,S); return gerepilecopy(av,z); } /* Not stack-clean */ GEN qfr3_comp(GEN x, GEN y, struct qfr_data *S) { GEN z = cgetg(4,t_VEC); qfb_comp(z,x,y); return qfr3_red(z, S); } /* valid for t_QFR, qfr3, qfr5 */ static GEN qfr_inv(GEN x) { GEN z = shallowcopy(x); gel(z,2) = negi(gel(z,2)); return z; } /* return x^n. Not stack-clean */ GEN qfr5_pow(GEN x, GEN n, struct qfr_data *S) { GEN y = NULL; long i, m, s = signe(n); if (!s) return qfr5_1(S, lg(gel(x,5))); for (i=lgefint(n)-1; i>1; i--) { m = n[i]; for (; m; m>>=1) { if (m&1) y = y? qfr5_comp(y,x,S): x; if (m == 1 && i == 2) break; x = qfr5_comp(x,x,S); } } return y; } /* return x^n. Not stack-clean */ GEN qfr3_pow(GEN x, GEN n, struct qfr_data *S) { GEN y = NULL; long i, m, s = signe(n); if (!s) return qfr3_1(S); if (s < 0) x = qfr_inv(x); for (i=lgefint(n)-1; i>1; i--) { m = n[i]; for (; m; m>>=1) { if (m&1) y = y? qfr3_comp(y,x,S): x; if (m == 1 && i == 2) break; x = qfr3_comp(x,x,S); } } return y; } GEN qfrpow(GEN x, GEN n) { struct qfr_data S = { NULL, NULL, NULL }; long s = signe(n); pari_sp av = avma; GEN d0; if (!s) return qfr_1(x); if (is_pm1(n)) return s > 0? redreal(x): ginv(x); if (s < 0) x = qfr_inv(x); d0 = gel(x,4); if (!signe(d0)) { x = qfr3_init(x, &S); x = qfr3_pow(x, n, &S); x = qfr3_to_qfr(x, d0); } else { x = qfr5_init(x, &S); x = qfr5_pow(qfr_to_qfr5(x, lg(S.sqrtD)), n, &S); x = qfr5_to_qfr(x, mulri(d0,n)); } return gerepilecopy(av, x); } /* Prime forms associated to prime ideals of degree 1 */ /* assume x != 0 a t_INT, p > 0 * Return a t_QFI, but discriminant sign is not checked: can be used for * real forms as well */ GEN primeform_u(GEN x, ulong p) { GEN c, y = cgetg(4, t_QFI); pari_sp av = avma; ulong b; long s; s = mod8(x); if (signe(x) < 0 && s) s = 8-s; /* 2 or 3 mod 4 */ if (s & 2) pari_err_DOMAIN("primeform", "disc % 4", ">",gen_1, x); if (p == 2) { switch(s) { case 0: b = 0; break; case 1: b = 1; break; case 4: b = 2; break; default: pari_err_SQRTN("primeform", mkintmod(x,utoi(p)) ); b = 0; /* -Wall */ } c = shifti(subsi(s,x), -3); } else { b = Fl_sqrt(umodiu(x,p), p); if (b == ~0UL) pari_err_SQRTN("primeform", mkintmod(x,utoi(p)) ); /* mod(b) != mod2(x) ? */ if ((b ^ s) & 1) b = p - b; c = diviuexact(shifti(subii(sqru(b), x), -2), p); } gel(y,3) = gerepileuptoint(av, c); gel(y,2) = utoi(b); gel(y,1) = utoipos(p); return y; } /* special case: p = 1 return unit form */ GEN primeform(GEN x, GEN p, long prec) { const char *f = "primeform"; pari_sp av; long s, sx = signe(x), sp = signe(p); GEN y, b, absp; if (typ(x) != t_INT) pari_err_TYPE(f,x); if (typ(p) != t_INT) pari_err_TYPE(f,p); if (!sp) pari_err_DOMAIN(f,"p","=",gen_0,p); if (!sx) pari_err_DOMAIN(f,"D","=",gen_0,x); if (lgefint(p) == 3) { ulong pp = p[2]; if (pp == 1) { if (sx < 0) { long r; if (sp < 0) pari_err_IMPL("negative definite t_QFI"); r = mod4(x); if (r && r != 3) pari_err_DOMAIN(f,"disc % 4",">", gen_1,x); return qfi_1_by_disc(x); } y = qfr_1_by_disc(x,prec); if (sp < 0) { gel(y,1) = gen_m1; togglesign(gel(y,3)); } return y; } y = primeform_u(x, pp); if (sx < 0) { if (sp < 0) pari_err_IMPL("negative definite t_QFI"); return y; } if (sp < 0) { togglesign(gel(y,1)); togglesign(gel(y,3)); } return gcopy( qfr3_to_qfr(y, real_0(prec)) ); } s = mod8(x); if (sx < 0) { if (sp < 0) pari_err_IMPL("negative definite t_QFI"); if (s) s = 8-s; y = cgetg(4, t_QFI); } else { y = cgetg(5, t_QFR); gel(y,4) = real_0(prec); } /* 2 or 3 mod 4 */ if (s & 2) pari_err_DOMAIN(f, "disc % 4", ">",gen_1, x); absp = absi(p); av = avma; b = Fp_sqrt(x, absp); if (!b) pari_err_SQRTN(f, mkintmod(x,absp)); s &= 1; /* s = x mod 2 */ /* mod(b) != mod2(x) ? [Warning: we may have b == 0] */ if ((!signe(b) && s) || mod2(b) != s) b = gerepileuptoint(av, subii(absp,b)); av = avma; gel(y,3) = gerepileuptoint(av, diviiexact(shifti(subii(sqri(b), x), -2), p)); gel(y,2) = b; gel(y,1) = icopy(p); return y; } /* Let M and N in SL2(Z), return (N*M^-1)[,1] */ static GEN SL2_div_mul_e1(GEN N, GEN M) { GEN b = gcoeff(M,2,1), d = gcoeff(M,2,2); GEN p = subii(mulii(gcoeff(N,1,1), d), mulii(gcoeff(N,1,2), b)); GEN q = subii(mulii(gcoeff(N,2,1), d), mulii(gcoeff(N,2,2), b)); return mkvec2(p,q); } /* Let M and N in SL2(Z), return (N*[1,0;0,-1]*M^-1)[,1] */ static GEN SL2_swap_div_mul_e1(GEN N, GEN M) { GEN b = gcoeff(M,2,1), d = gcoeff(M,2,2); GEN p = addii(mulii(gcoeff(N,1,1), d), mulii(gcoeff(N,1,2), b)); GEN q = addii(mulii(gcoeff(N,2,1), d), mulii(gcoeff(N,2,2), b)); return mkvec2(p,q); } /* Test equality modulo GL2 of two reduced forms */ static int GL2_qfb_equal(GEN a, GEN b) { return equalii(gel(a,1),gel(b,1)) && absi_equal(gel(a,2),gel(b,2)) && equalii(gel(a,3),gel(b,3)); } static GEN qfbsolve_cornacchia(GEN c, GEN p, int swap) { pari_sp av = avma; GEN M, N; if (kronecker(negi(c), p) < 0 || !cornacchia(c, p, &M,&N)) { avma = av; return gen_0; } return gerepilecopy(av, swap? mkvec2(N,M): mkvec2(M,N)); } GEN qfisolvep(GEN Q, GEN p) { GEN M, N, x,y, a,b,c, d; pari_sp av = avma; if (!signe(gel(Q,2))) { a = gel(Q,1); c = gel(Q,3); /* if principal form, use faster cornacchia */ if (equali1(a)) return qfbsolve_cornacchia(c, p, 0); if (equali1(c)) return qfbsolve_cornacchia(a, p, 1); } d = qfb_disc(Q); if (kronecker(d,p) < 0) return gen_0; a = redimagsl2(Q, &N); if (is_pm1(gel(a,1))) /* principal form */ { long r; if (!signe(gel(a,2))) { a = qfbsolve_cornacchia(gel(a,3), p, 0); if (a == gen_0) { avma = av; return gen_0; } a = ZM_ZC_mul(N, a); a[0] = evaltyp(t_VEC) | _evallg(3); /* transpose */ return gerepileupto(av, a); } /* x^2 + xy + ((1-d)/4)y^2 = p <==> (2x + y)^2 - d y^2 = 4p */ if (!cornacchia2(negi(d), p, &x, &y)) { avma = av; return gen_0; } x = divis_rem(subii(x,y), 2, &r); if (r) { avma = av; return gen_0; } a = ZM_ZC_mul(N, mkvec2(x,y)); a[0] = evaltyp(t_VEC) | _evallg(3); /* transpose */ return gerepileupto(av, a); } b = redimagsl2(primeform(d, p, 0), &M); if (!GL2_qfb_equal(a,b)) { avma = av; return gen_0; } if (signe(gel(a,2))==signe(gel(b,2))) x = SL2_div_mul_e1(N,M); else x = SL2_swap_div_mul_e1(N,M); return gerepilecopy(av, x); } GEN 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); if (signe(a) < 0) togglesign(q); N = mkmat2(gel(M,2), mkcol2(subii(mulii(q, gcoeff(M, 1, 2)), gcoeff(M, 1, 1)), subii(mulii(q, gcoeff(M, 2, 2)), gcoeff(M, 2, 1)))); return gerepilecopy(ltop, mkvec2(mkvec3(a,b,c),N)); } GEN redrealsl2(GEN V, GEN d, GEN rd) { pari_sp ltop = avma, st_lim = stack_lim(ltop, 1); 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); 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 (DEBUGMEM>1) pari_warn(warnmem,"redrealsl2"); gerepileall(ltop, 7, &a,&b,&c,&u1,&u2,&v1,&v2); } } M = mkmat2(mkcol2(u1,u2), mkcol2(v1,v2)); return gerepilecopy(ltop, mkvec2(mkvec3(a,b,c), M)); } GEN qfrsolvep(GEN Q, GEN p) { pari_sp ltop = avma, btop, st_lim; GEN N, P, P1, P2, M, rd, d = qfb_disc(Q); if (kronecker(d, p) < 0) { avma = ltop; return gen_0; } rd = sqrti(d); M = N = redrealsl2(Q, d,rd); P = primeform(d, p, DEFAULTPREC); P1 = redrealsl2(P, d,rd); togglesign( gel(P,2) ); P2 = redrealsl2(P, d,rd); btop = avma; st_lim = stack_lim(btop, 1); 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); } return gerepilecopy(ltop, SL2_div_mul_e1(gel(M,2),N)); } GEN qfbsolve(GEN Q,GEN n) { if (typ(n)!=t_INT) pari_err_TYPE("qfbsolve",n); switch(typ(Q)) { case t_QFI: return qfisolvep(Q,n); case t_QFR: return qfrsolvep(Q,n); default: pari_err_TYPE("qfbsolve",Q); return NULL; /* NOT REACHED */ } } /* 1 if there exists x,y such that x^2 + dy^2 = p [prime], 0 otherwise */ long cornacchia(GEN d, GEN p, GEN *px, GEN *py) { pari_sp av = avma, av2, lim; GEN a, b, c, L, r; if (typ(d) != t_INT) pari_err_TYPE("cornacchia", d); if (typ(p) != t_INT) pari_err_TYPE("cornacchia", p); if (signe(d) <= 0) pari_err_DOMAIN("cornacchia", "d","<=",gen_0,d); *px = *py = gen_0; b = subii(p, d); if (signe(b) < 0) return 0; if (signe(b) == 0) { avma = av; *py = gen_1; return 1; } b = Fp_sqrt(b, p); /* sqrt(-d) */ 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); while (absi_cmp(b, L) > 0) { r = remii(a, b); a = b; b = r; if (low_stack(lim, stack_lim(av2, 1))) { if (DEBUGMEM>1) pari_warn(warnmem,"cornacchia"); gerepileall(av2, 2, &a,&b); } } a = subii(p, sqri(b)); c = dvmdii(a, d, &r); if (r != gen_0 || !Z_issquareall(c, &c)) { avma = av; return 0; } avma = av; *px = icopy(b); *py = icopy(c); return 1; } /* 1 if there exists x,y such that x^2 + dy^2 = 4p [p prime], 0 otherwise */ long cornacchia2(GEN d, GEN p, GEN *px, GEN *py) { pari_sp av = avma, av2, lim; GEN a, b, c, L, r, px4; long k; if (typ(d) != t_INT) pari_err_TYPE("cornacchia2", d); if (typ(p) != t_INT) pari_err_TYPE("cornacchia2", p); if (signe(d) <= 0) pari_err_DOMAIN("cornacchia2", "d","<=",gen_0,d); *px = *py = gen_0; k = mod4(d); if (k == 1 || k == 2) pari_err_DOMAIN("cornacchia2","-d mod 4", ">",gen_1,d); px4 = shifti(p,2); if (absi_cmp(px4, d) < 0) { avma = av; return 0; } if (equaliu(p, 2)) { avma = av; switch (itou_or_0(d)) { case 4: *px = gen_2; break; case 7: *px = gen_1; break; default: return 0; } *py = gen_1; return 1; } b = Fp_sqrt(negi(d), p); if (!b) { avma = av; return 0; } if (!signe(b)) { /* d = p,2p,3p,4p */ avma = av; if (absi_equal(d, px4)){ *py = gen_1; return 1; } if (absi_equal(d, p)) { *py = gen_2; return 1; } return 0; } if (mod2(b) != (k & 1)) b = subii(p,b); a = shifti(p,1); L = sqrti(px4); av2 = avma; lim = stack_lim(av2, 1); while (cmpii(b, L) > 0) { r = remii(a, b); a = b; b = r; if (low_stack(lim, stack_lim(av2, 1))) { if (DEBUGMEM>1) pari_warn(warnmem,"cornacchia"); gerepileall(av2, 2, &a,&b); } } a = subii(px4, sqri(b)); c = dvmdii(a, d, &r); if (r != gen_0 || !Z_issquareall(c, &c)) { avma = av; return 0; } avma = av; *px = icopy(b); *py = icopy(c); return 1; } pari-2.7.5/src/basemath/FpXX.c0000644000175000017500000006734512413013142014460 0ustar billbill/* Copyright (C) 2012 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 polynomials over FpX */ /*******************************************************************/ /* */ /* FpXX */ /* */ /*******************************************************************/ /*Polynomials whose coefficients are either polynomials or integers*/ 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]; 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); *pt_T = ZXT_to_FlxT(T, pp); return pp; } static GEN ZXX_copy(GEN a) { return gcopy(a); } GEN FpXX_red(GEN z, GEN p) { GEN res; long i, l = lg(z); res = cgetg(l,t_POL); res[1] = z[1]; for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_POL); z[1]=x[1]; for (i=2; i=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = Fq_sub(p1, Fq_mul(gel(z,j),gel(y,i-j),NULL,p),NULL,p); if (lead) p1 = Fq_mul(p1, lead, NULL,p); tetpil=avma; gel(z,i-dy) = gerepile(av,tetpil,Fq_red(p1,T,p)); } if (!pr) { if (lead) gunclone(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = Fq_sub(p1, Fq_mul(gel(z,j),gel(y,i-j),NULL,p),NULL,p); tetpil=avma; p1 = Fq_red(p1, T, p); if (signe(p1)) { sx = 1; break; } if (!i) break; avma=av; } if (pr == ONLY_DIVIDES) { if (lead) gunclone(lead); if (sx) { avma=av0; return NULL; } avma = (pari_sp)rem; return z-2; } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | evallg(lr); rem[1] = z[-1]; p1 = gerepile((pari_sp)rem,tetpil,p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = Fq_sub(p1, Fq_mul(gel(z,j),gel(y,i-j), NULL,p), NULL,p); tetpil=avma; gel(rem,i) = gerepile(av,tetpil, Fq_red(p1, T, p)); } rem -= 2; if (lead) gunclone(lead); if (!sx) (void)FpXQX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } GEN FpXQX_gcd(GEN P, GEN Q, GEN T, GEN p) { pari_sp av=avma, av0; GEN R; if (lgefint(p) == 3) { GEN Pl, Ql, Tl, U; ulong pp = to_FlxqX(P, Q, T, p, &Pl, &Ql, &Tl); U = FlxqX_gcd(Pl, Ql, Tl, pp); return gerepileupto(av, FlxX_to_ZXX(U)); } P = FpXX_red(P, p); av0 = avma; Q = FpXX_red(Q, p); while (signe(Q)) { av0 = avma; R = FpXQX_rem(P,Q,T,p); P=Q; Q=R; } avma = av0; return gerepileupto(av, P); } /* x and y in Z[Y][X], return lift(gcd(x mod T,p, y mod T,p)). Set u and v st * ux + vy = gcd (mod T,p) */ GEN FpXQX_extgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv) { GEN a, b, q, r, u, v, d, d1, v1; long vx = varn(x); pari_sp ltop=avma; if (lgefint(p) == 3) { GEN Pl, Ql, Tl, Dl; ulong pp = to_FlxqX(x, y, T, p, &Pl, &Ql, &Tl); Dl = FlxqX_extgcd(Pl, Ql, Tl, pp, ptu, ptv); if (ptu) *ptu = FlxX_to_ZXX(*ptu); *ptv = FlxX_to_ZXX(*ptv); d = FlxX_to_ZXX(Dl); } else { a = FpXQX_red(x, T, p); b = FpXQX_red(y, T, p); d = a; d1 = b; v = pol_0(vx); v1 = pol_1(vx); while (signe(d1)) { q = FpXQX_divrem(d,d1,T,p, &r); v = FpXX_sub(v, FpXQX_mul(q,v1, T,p), p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; } if (ptu) *ptu = FpXQX_div(FpXX_sub(d, FpXQX_mul(b,v, T,p), p),a, T,p); *ptv = v; } gerepileall(ltop,ptu?3:2,&d,ptv,ptu); return d; } /***********************************************************************/ /** **/ /** Barrett reduction **/ /** **/ /***********************************************************************/ /* Return new lgpol */ static long ZXX_lgrenormalizespec(GEN x, long lx) { long i; for (i = lx-1; i>=0; i--) if (signe(gel(x,i))) break; return i+1; } static GEN FpXQX_invBarrett_basecase(GEN S, GEN T, GEN p) { long i, l=lg(S)-1, lr = l-1, k; GEN r=cgetg(lr, t_POL); r[1]=S[1]; gel(r,2) = gen_1; for (i=3; i 2 */ for (i=0;i1) gel(q,1) = Fq_red(gel(q,1), T, p); if (lQ>1 && signe(gel(q,1))) { GEN u = gel(q, 1); if (!gequal1(gel(x,0))) u = Fq_mul(u, Fq_sqr(gel(x,0), T, p), T, p); gel(x,1) = Fq_neg(u, T, p); lx = 2; } else lx = 1; nold = 1; for (; mask > 1; ) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = ZXX_lgrenormalizespec(q, minss(lQ,lnew)); z = FpXQX_mulspec(x, q, T, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (signe(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = ZXX_lgrenormalizespec (z+i, lz-i); z = FpXQX_mulspec(x, z+i, T, p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = ZXX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Fq_neg(gel(z,i), T, p); } x -= 2; setlg(x, lx + 2); x[1] = S[1]; return gerepilecopy(av, x); } const long FpXQX_INVBARRETT_LIMIT = 50; const long FpXQX_DIVREM_BARRETT_LIMIT = 50; const long FpXQX_REM_BARRETT_LIMIT = 50; /* 1/polrecip(S)+O(x^(deg(S)-1)) */ GEN FpXQX_invBarrett(GEN S, GEN T, GEN p) { pari_sp ltop = avma; long l = lg(S); GEN r; if (l<5) return pol_0(varn(S)); if (l<=FpXQX_INVBARRETT_LIMIT) { GEN c = gel(S,l-1), ci=gen_1; if (!gequal1(c)) { ci = Fq_inv(c, T, p); S = FqX_Fq_mul(S, ci, T, p); r = FpXQX_invBarrett_basecase(S, T, p); r = FqX_Fq_mul(r, ci, T, p); } else r = FpXQX_invBarrett_basecase(S, T, p); } else r = FpXQX_invBarrett_Newton(S, T, p); return gerepileupto(ltop, r); } /* Compute x mod S where 2 <= degpol(S) <= l+1 <= 2*(degpol(S)-1) * and mg is the Barrett inverse of S. */ static GEN FpXQX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN S, GEN T, GEN p, GEN *pr) { GEN q, r; long lt = degpol(S); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = ZXX_lgrenormalizespec(S+2,lt); lmg = ZXX_lgrenormalizespec(mg+2,lm); q = FpXQX_recipspec(x+lt,ld,ld); /* q = rec(x) lq<=ld*/ q = FpXQX_mulspec(q+2,mg+2,T,p,lgpol(q),lmg); /* q = rec(x) * mg lq<=ld+lm*/ q = FpXQX_recipspec(q+2,minss(ld,lgpol(q)),ld); /* q = rec (rec(x) * mg) lq<=ld*/ if (!pr) return q; r = FpXQX_mulspec(q+2,S+2,T,p,lgpol(q),lT); /* r = q*pol lr<=ld+lt*/ r = FpXX_subspec(x,r+2,p,lt,minss(lt,lgpol(r))); /* r = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN FpXQX_divrem_Barrett_noGC(GEN x, GEN mg, GEN S, GEN T, GEN p, GEN *pr) { long l = lgpol(x), lt = degpol(S), lm = 2*lt-1; GEN q = NULL, r; long i; if (l <= lt) { if (pr == ONLY_REM) return ZXX_copy(x); if (pr == ONLY_DIVIDES) return signe(x)? NULL: pol_0(varn(x)); if (pr) *pr = ZXX_copy(x); return pol_0(varn(x)); } if (lt <= 1) return FpXQX_divrem_basecase(x,S,T,p,pr); if (pr != ONLY_REM && l>lm) { q = cgetg(l-lt+2, t_POL); for (i=0;ilm ? shallowcopy(x): x; while (l>lm) { GEN zr, zq = FpXQX_divrem_Barrettspec(r+2+l-lm,lm,mg,S,T,p,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) { GEN zq = FpXQX_divrem_Barrettspec(r+2,l,mg,S,T,p,&r); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i lt) (void) FpXQX_divrem_Barrettspec(r+2,l,mg,S,T,p,&r); else { setlg(r, l+2); r = ZXX_copy(r); } r[1] = x[1]; return FpXQX_renormalize(r, lg(r)); } if (pr) { r[1] = x[1]; r = FpXQX_renormalize(r, lg(r)); } q[1] = x[1]; q = FpXQX_renormalize(q, lg(q)); if (pr == ONLY_DIVIDES) return signe(r)? NULL: q; if (pr) *pr = r; return q; } GEN FpXQX_divrem_Barrett(GEN x, GEN B, GEN S, GEN T, GEN p, GEN *pr) { pari_sp av = avma; GEN q = FpXQX_divrem_Barrett_noGC(x,B,S,T,p,pr); if (!q) {avma=av; return NULL;} if (!pr || pr==ONLY_REM || pr==ONLY_DIVIDES) return gerepilecopy(av, q); gerepileall(av,2,&q,pr); return q; } GEN FpXQX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *pr) { long dy = degpol(y), dx = degpol(x), d = dx-dy; if (pr==ONLY_REM) return FpXQX_rem(x, y, T, p); if (d+3 < FpXQX_DIVREM_BARRETT_LIMIT) return FpXQX_divrem_basecase(x,y,T,p,pr); else { pari_sp av=avma; GEN mg = FpXQX_invBarrett(y, T, p); GEN q = FpXQX_divrem_Barrett_noGC(x,mg,y,T,p,pr); if (!q) {avma=av; return NULL;} if (!pr || pr==ONLY_DIVIDES) return gerepilecopy(av, q); gerepileall(av,2,&q,pr); return q; } } GEN FpXQX_rem_Barrett(GEN x, GEN mg, GEN S, GEN T, GEN p) { pari_sp av = avma; return gerepileupto(av, FpXQX_divrem_Barrett_noGC(x,mg,S, T, p, ONLY_REM)); } GEN FpXQX_rem(GEN x, GEN y, GEN T, GEN p) { long dy = degpol(y), dx = degpol(x), d = dx-dy; if (d < 0) return FpXQX_red(x, T, p); if (d+3 < FpXQX_REM_BARRETT_LIMIT) return FpXQX_divrem_basecase(x,y, T, p, ONLY_REM); else { pari_sp av=avma; GEN mg = FpXQX_invBarrett(y, T, p); GEN r = FpXQX_divrem_Barrett_noGC(x, mg, y, T, p, ONLY_REM); return gerepileupto(av, r); } } 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); } GEN FpXQXV_prod(GEN V, GEN T, GEN p) { if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = p[2]; GEN Tl = ZXT_to_FlxT(T, pp); GEN Vl = ZXXV_to_FlxXV(V, pp, get_FpX_var(T)); Tl = FlxqXV_prod(Vl, Tl, pp); return gerepileupto(av, FlxX_to_ZXX(Tl)); } else { struct _FpXQX d; d.p=p; d.T=T; return divide_conquer_assoc(V, (void*)&d, &_FpXQX_mul); } } /* Q an FpXY (t_POL with FpX coeffs), evaluate at X = x */ GEN FpXY_evalx(GEN Q, GEN x, GEN p) { long i, lb = lg(Q); GEN z; z = cgetg(lb, t_POL); z[1] = Q[1]; for (i=2; i=2; i--) z = Fq_add(gel(Q,i), FpX_Fp_mul(z, y, p), NULL, p); return gerepileupto(av, z); } /* Q an FpXY, evaluate at (X,Y) = (x,y) */ GEN FpXY_eval(GEN Q, GEN y, GEN x, GEN p) { pari_sp av = avma; return gerepileuptoint(av, FpX_eval(FpXY_evalx(Q, x, p), y, p)); } GEN FpXY_FpXQ_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; iT, D->p),D->S,D->T,D->p); } static GEN FpXYQQ_mul(void *data, GEN x, GEN y) { FpXYQQ_muldata *D = (FpXYQQ_muldata*)data; return FpXYQQ_redswap(FpXQX_mul(x,y, D->T, D->p),D->S,D->T,D->p); } /* x in Z[X,Y], S in Z[X] over Fq = Z[Y]/(p,T); compute lift(x^n mod (S,T,p)) */ GEN FpXYQQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p) { pari_sp av = avma; FpXYQQ_muldata D; GEN y; if (lgefint(p) == 3) { ulong pp = to_FlxqX(x, NULL, T, p, &x, NULL, &T); S = ZX_to_Flx(S, pp); y = FlxX_to_ZXX( FlxYqq_pow(x, n, S, T, pp) ); } else { D.S = S; D.T = T; D.p = p; y = gen_pow(x, n, (void*)&D, &FpXYQQ_sqr, &FpXYQQ_mul); } return gerepileupto(av, y); } GEN FpXQXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p) { return FpXQX_rem(FpXQX_mul(x, y, T, p), S, T, p); } GEN FpXQXQ_sqr(GEN x, GEN S, GEN T, GEN p) { return FpXQX_rem(FpXQX_sqr(x, T, p), S, T, p); } /* Inverse of x in Z/pZ[X]/(pol) or NULL if inverse doesn't exist * return lift(1 / (x mod (p,pol))) */ GEN FpXQXQ_invsafe(GEN x, GEN S, GEN T, GEN p) { GEN V, z = FpXQX_extgcd(S, x, T, p, NULL, &V); if (degpol(z)) return NULL; z = gel(z,2); z = typ(z)==t_INT ? Fp_invsafe(z,p) : FpXQ_invsafe(z,T,p); if (!z) return NULL; return typ(z)==t_INT ? FpXX_Fp_mul(V, z, p): FpXQX_FpXQ_mul(V, z, T, p); } GEN FpXQXQ_inv(GEN x, GEN S, GEN T,GEN p) { pari_sp av = avma; GEN U = FpXQXQ_invsafe(x, S, T, p); if (!U) pari_err_INV("FpXQXQ_inv",x); return gerepileupto(av, U); } GEN FpXQXQ_div(GEN x,GEN y,GEN S, GEN T,GEN p) { pari_sp av = avma; return gerepileupto(av, FpXQXQ_mul(x, FpXQXQ_inv(y,S,T,p),S,T,p)); } typedef struct { GEN T, S; GEN p; } FpXQXQ_muldata; static GEN _FpXQXQ_add(void *data, GEN x, GEN y) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return FpXX_add(x,y, d->p); } static GEN _FpXQXQ_cmul(void *data, GEN P, long a, GEN x) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; GEN y = gel(P,a+2); return typ(y)==t_INT ? FpXX_Fp_mul(x,y, d->p): FpXX_FpX_mul(x,y,d->p); } static GEN _FpXQXQ_red(void *data, GEN x) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return FpXQX_red(x, d->T, d->p); } static GEN _FpXQXQ_mul(void *data, GEN x, GEN y) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return FpXQXQ_mul(x,y, d->S,d->T, d->p); } static GEN _FpXQXQ_sqr(void *data, GEN x) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return FpXQXQ_sqr(x, d->S,d->T, d->p); } static GEN _FpXQXQ_one(void *data) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return pol_1(varn(d->S)); } static GEN _FpXQXQ_zero(void *data) { FpXQXQ_muldata *d = (FpXQXQ_muldata*) data; return pol_0(varn(d->S)); } static struct bb_algebra FpXQXQ_algebra = { _FpXQXQ_red,_FpXQXQ_add,_FpXQXQ_mul,_FpXQXQ_sqr,_FpXQXQ_one,_FpXQXQ_zero }; /* x over Fq, return lift(x^n) mod S */ GEN FpXQXQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p) { pari_sp ltop = avma; GEN y; FpXQXQ_muldata D; long s = signe(n); if (!s) return pol_1(varn(x)); if (is_pm1(n)) /* +/- 1 */ return (s < 0)? FpXQXQ_inv(x,S,T,p): ZXX_copy(x); if (lgefint(p) == 3) { ulong pp = to_FlxqX(x, S, T, p, &x, &S, &T); GEN z = FlxqXQ_pow(x, n, S, T, pp); y = FlxX_to_ZXX(z); } else { D.S = S; D.T = T; D.p = p; if (s < 0) x = FpXQXQ_inv(x,S,T,p); y = gen_pow(x, n, (void*)&D,&_FpXQXQ_sqr,&_FpXQXQ_mul); } return gerepileupto(ltop, y); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN FpXQXQ_powers(GEN x, long l, GEN S, GEN T, GEN p) { FpXQXQ_muldata D; int use_sqr = (degpol(x)<<1) >= degpol(S); D.S = S; D.T = T; D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_FpXQXQ_sqr, &_FpXQXQ_mul,&_FpXQXQ_one); } GEN FpXQXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p) { return RgXV_to_RgM(FpXQXQ_powers(y,m-1,S,T,p),n); } GEN FpXQX_FpXQXQV_eval(GEN P, GEN V, GEN S, GEN T, GEN p) { FpXQXQ_muldata D; D.S=S; D.T=T; D.p=p; return gen_bkeval_powers(P, degpol(P), V, (void*)&D, &FpXQXQ_algebra, _FpXQXQ_cmul); } GEN FpXQX_FpXQXQ_eval(GEN Q, GEN x, GEN S, GEN T, GEN p) { FpXQXQ_muldata D; int use_sqr = (degpol(x)<<1) >= degpol(S); D.S=S; D.T=T; D.p=p; return gen_bkeval(Q, degpol(Q), x, use_sqr, (void*)&D, &FpXQXQ_algebra, _FpXQXQ_cmul); } static GEN FpXQXQ_autpow_sqr(void * T, GEN x) { FpXQXQ_muldata *D = (FpXQXQ_muldata *)T; 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); return mkvec2(phi2, S2); } static GEN FpXQXQ_autpow_mul(void * T, GEN x, GEN y) { FpXQXQ_muldata *D = (FpXQXQ_muldata *)T; 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); return mkvec2(phi3, S3); } GEN FpXQXQV_autpow(GEN aut, long n, GEN S, GEN T, GEN p) { FpXQXQ_muldata D; D.S=S; D.T=T; D.p=p; return gen_powu(aut,n,&D,FpXQXQ_autpow_sqr,FpXQXQ_autpow_mul); } static GEN FpXQXQ_autsum_mul(void * T, GEN x, GEN y) { FpXQXQ_muldata *D = (FpXQXQ_muldata *)T; 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 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); return mkvec3(phi3, S3, a3); } static GEN FpXQXQ_autsum_sqr(void * T, GEN x) { return FpXQXQ_autsum_mul(T,x,x); } GEN FpXQXQV_autsum(GEN aut, long n, GEN S, GEN T, GEN p) { FpXQXQ_muldata D; D.S=S; D.T=T; D.p=p; return gen_powu(aut,n,&D,FpXQXQ_autsum_sqr,FpXQXQ_autsum_mul); } pari-2.7.5/src/basemath/buch3.c0000644000175000017500000021055212405547147014647 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* RAY CLASS FIELDS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* Faster than Buchray (because it can use nfsign_units: easier nfarchstar) */ GEN buchnarrow(GEN bnf) { GEN nf, cyc, gen, A, NO, GD, v, invpi, logs, R, basecl, met, u1, archp; long r1, j, ngen, t, RU; pari_sp av = avma; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); r1 = nf_get_r1(nf); if (!r1) return gcopy( bnf_get_clgp(bnf) ); /* simplified version of nfsign_units; r1 > 0 so bnf.tu = -1 */ archp = identity_perm(r1); A = bnf_get_logfu(bnf); RU = lg(A)+1; invpi = invr( mppi(nf_get_prec(nf)) ); v = cgetg(RU,t_MAT); gel(v, 1) = const_vecsmall(r1, 1); /* nfsign(-1) */ for (j=2; j 1 */ basecl = cgetg(l,t_VEC); G = cgetg(3,t_VEC); gel(G,2) = cgetg(1,t_MAT); for (j=1; j 0) { avma = av; return x; } a = set_sign_mod_divisor(nf, NULL, A, divisor, sarch); if (a != A && too_big(nf,A) > 0) { avma = av; return x; } return idealmul(nf, a, x); } GEN idealmoddivisor(GEN bnr, GEN x) { GEN bid = bnr_get_bid(bnr), fa2 = gel(bid,4); GEN sarch = gel(fa2,lg(fa2)-1); return idealmoddivisor_aux(checknf(bnr), x, bid_get_mod(bid), sarch); } /* v_pr(L0 * cx) */ static long fast_val(GEN nf,GEN L0,GEN cx,GEN pr) { pari_sp av = avma; long v = typ(L0) == t_INT? 0: ZC_nfval(nf,L0,pr); if (cx) { long w = Q_pval(cx, pr_get_p(pr)); if (w) v += w * pr_get_e(pr); } avma = av; return v; } /* x coprime to fZ, return y = x mod fZ, y integral */ static GEN make_integral_Z(GEN x, GEN fZ) { GEN d, y = Q_remove_denom(x, &d); if (d) y = FpC_Fp_mul(y, Fp_inv(d, fZ), fZ); return y; } /* p pi^(-1) mod f */ static GEN get_pinvpi(GEN nf, GEN fZ, GEN p, GEN pi, GEN *v) { if (!*v) { GEN invpi = nfinv(nf, pi); *v = make_integral_Z(RgC_Rg_mul(invpi, p), mulii(p, fZ)); } return *v; } /* p pi^(-1) mod f */ static GEN get_pi(GEN F, GEN pr, GEN *v) { if (!*v) *v = unif_mod_fZ(pr, F); return *v; } static GEN compute_raygen(GEN nf, GEN u1, GEN gen, GEN bid) { GEN f, fZ, basecl, module, fa, fa2, pr, t, EX, sarch, cyc, F; GEN listpr, vecpi, vecpinvpi; long i,j,l,lp; if (lg(u1) == 1) return cgetg(1, t_VEC); /* basecl = generators in factored form */ basecl = compute_fact(nf,u1,gen); module = bid_get_mod(bid); cyc = bid_get_cyc(bid); EX = gel(cyc,1); /* exponent of (O/f)^* */ f = gel(module,1); fZ = gcoeff(f,1,1); fa = gel(bid,3); fa2 = gel(bid,4); sarch = gel(fa2, lg(fa2)-1); listpr = gel(fa,1); F = init_unif_mod_fZ(listpr); lp = lg(listpr); vecpinvpi = cgetg(lp, t_VEC); vecpi = cgetg(lp, t_VEC); for (i=1; i 0) { pinvpi = get_pinvpi(nf, fZ, p, pi, &gel(vecpinvpi,j)); t = nfpow_u(nf,pinvpi, (ulong)v); LL = nfmul(nf, LL, t); LL = RgC_Rg_div(LL, powiu(p, v)); } else { t = nfpow_u(nf,pi,(ulong)(-v)); LL = nfmul(nf, LL, t); } } LL = make_integral(nf,LL,f,listpr); gel(newL,k) = typ(LL) == t_INT? LL: FpC_red(LL, fZ); } av = avma; /* G in nf, = L^e mod f */ G = famat_to_nf_modideal_coprime(nf, newL, e, f, EX); if (mulI) { G = nfmuli(nf, G, mulI); G = ZC_hnfrem(G, ZM_Z_mul(f, dmulI)); } G = set_sign_mod_divisor(nf,A,G,module,sarch); I = idealmul(nf,I,G); if (dmulI) I = ZM_Z_divexact(I, dmulI); /* more or less useless, but cheap at this point */ I = idealmoddivisor_aux(nf,I,module,sarch); gel(basecl,i) = gerepilecopy(av, I); } return basecl; } /********************************************************************/ /** **/ /** INIT RAY CLASS GROUP **/ /** **/ /********************************************************************/ static GEN check_subgroup(GEN bnr, GEN H, GEN *clhray, int triv_is_NULL) { GEN h, cyc = bnr_get_cyc(bnr); if (H && gequal0(H)) H = NULL; if (H) { if (typ(H) != t_MAT) pari_err_TYPE("check_subgroup",H); RgM_check_ZM(H, "check_subgroup"); H = ZM_hnfmodid(H, cyc); h = ZM_det_triangular(H); if (equalii(h, *clhray)) H = NULL; else *clhray = h; } if (!H && !triv_is_NULL) H = diagonal_shallow(cyc); return H; } static GEN get_dataunit(GEN bnf, GEN bid) { GEN D, cyc = bid_get_cyc(bid), U = init_units(bnf), nf = bnf_get_nf(bnf); long i, l; zlog_S S; init_zlog_bid(&S, bid); D = nfsign_units(bnf, S.archp, 1); l = lg(D); for (i = 1; i < l; i++) { GEN v = zlog(nf, gel(U,i),gel(D,i), &S); gel(D,i) = vecmodii(ZM_ZC_mul(S.U, v), cyc); } return D; } GEN Buchray(GEN bnf, GEN module, long flag) { GEN nf, cyc, gen, Gen, u, clg, logs, p1, h, met, u1, u2, U, cycgen; GEN bid, cycbid, genbid, y, funits, H, Hi, c1, c2, El; long RU, Ri, j, ngen, lh; const long add_gen = flag & nf_GEN; const long do_init = flag & nf_INIT; pari_sp av = avma; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); funits = bnf_get_fu(bnf); RU = lg(funits); El = Gen = NULL; /* gcc -Wall */ cyc = bnf_get_cyc(bnf); gen = bnf_get_gen(bnf); ngen = lg(cyc)-1; bid = checkbid_i(module); if (!bid) bid = Idealstar(nf,module,nf_GEN|nf_INIT); cycbid = bid_get_cyc(bid); genbid = bid_get_gen(bid); Ri = lg(cycbid)-1; lh = ngen+Ri; if (Ri || add_gen || do_init) { GEN fx = gel(bid,3); El = cgetg(ngen+1,t_VEC); for (j=1; j<=ngen; j++) { p1 = idealcoprimefact(nf, gel(gen,j), fx); if (RgV_isscalar(p1)) p1 = gel(p1,1); gel(El,j) = p1; } } if (add_gen) { Gen = cgetg(lh+1,t_VEC); for (j=1; j<=ngen; j++) gel(Gen,j) = idealmul(nf, gel(El,j), gel(gen,j)); for ( ; j<=lh; j++) gel(Gen,j) = gel(genbid, j-ngen); } if (!Ri) { clg = cgetg(add_gen? 4: 3,t_VEC); if (add_gen) gel(clg,3) = Gen; gel(clg,1) = bnf_get_no(bnf); gel(clg,2) = cyc; if (!do_init) return gerepilecopy(av,clg); y = cgetg(7,t_VEC); gel(y,1) = bnf; gel(y,2) = bid; gel(y,3) = El; gel(y,4) = matid(ngen); gel(y,5) = clg; gel(y,6) = mkvec3(cgetg(1,t_MAT), matid(RU), gen_1); return gerepilecopy(av,y); } cycgen = check_and_build_cycgen(bnf); /* (log(Units)|D) * u = (0 | H) */ if (do_init) { GEN D = shallowconcat(get_dataunit(bnf, bid), diagonal_shallow(cycbid)); H = ZM_hnfall(D, do_init? &u: NULL, 1); } else H = ZM_hnfmodid(get_dataunit(bnf, bid), cycbid); logs = cgetg(ngen+1, t_MAT); /* FIXME: cycgen[j] is not necessarily coprime to bid, but it is made coprime * in famat_zlog using canonical uniformizers [from bid data]: no need to * correct it here. The same ones will be used in bnrisprincipal. Hence * modification by El is useless. */ for (j=1; j<=ngen; j++) { p1 = gel(cycgen,j); if (typ(gel(El,j)) != t_INT) /* <==> != 1 */ { GEN F = to_famat_shallow(gel(El,j), gel(cyc,j)); p1 = famat_mul(F, p1); } gel(logs,j) = ideallog(nf, p1, bid); /* = log(Gen[j]) */ } /* [ cyc 0 ] * [-logs H ] = relation matrix for Cl_f */ h = shallowconcat( vconcat(diagonal_shallow(cyc), gneg_i(logs)), vconcat(zeromat(ngen, Ri), H) ); met = ZM_snf_group(ZM_hnf(h), &U, add_gen? &u1: NULL); clg = cgetg(add_gen? 4: 3, t_VEC); gel(clg,1) = detcyc(met, &j); gel(clg,2) = met; if (add_gen) gel(clg,3) = compute_raygen(nf,u1,Gen,bid); if (!do_init) return gerepilecopy(av, clg); u2 = cgetg(Ri+1,t_MAT); u1 = cgetg(RU+1,t_MAT); for (j=1; j<=RU; j++) { gel(u1,j) = gel(u,j); setlg(u[j],RU+1); } u += RU; for (j=1; j<=Ri; j++) { gel(u2,j) = gel(u,j); setlg(u[j],RU+1); } /* log(Units) U2 = H (mod D) * log(Units) U1 = 0 (mod D) */ u1 = ZM_lll(u1, 0.99, LLL_INPLACE); Hi = Q_primitive_part(RgM_inv_upper(H), &c1); u2 = Q_primitive_part(ZM_mul(ZM_reducemodmatrix(u2,u1), Hi), &c2); c1 = mul_content(c1, c2); if (!c1) c2 = gen_1; else if (typ(c1) == t_INT) { if (!is_pm1(c1)) u2 = ZM_Z_mul(u2, c1); c2 = gen_1; } else /* t_FRAC */ { c2 = gel(c1,2); c1 = gel(c1,1); if (!is_pm1(c1)) u2 = ZM_Z_mul(u2, c1); } y = cgetg(7,t_VEC); gel(y,1) = bnf; gel(y,2) = bid; gel(y,3) = El; gel(y,4) = U; gel(y,5) = clg; gel(y,6) = mkvec3(u2,u1,c2); /* u2/c2 = H^(-1) (mod Im u1) */ return gerepilecopy(av,y); } GEN bnrinit0(GEN bnf, GEN ideal, long flag) { switch(flag) { case 0: flag = nf_INIT; break; case 1: flag = nf_INIT | nf_GEN; break; default: pari_err_FLAG("bnrinit"); } return Buchray(bnf,ideal,flag); } GEN bnrclassno(GEN bnf,GEN ideal) { GEN nf, h, D, bid, cycbid; pari_sp av = avma; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); h = bnf_get_no(bnf); /* class number */ bid = checkbid_i(ideal); if (!bid) bid = Idealstar(nf,ideal,nf_INIT); cycbid = bid_get_cyc(bid); if (lg(cycbid) == 1) { avma = av; return icopy(h); } D = get_dataunit(bnf, bid); /* (Z_K/f)^* / units ~ Z^n / D */ D = ZM_hnfmodid(D,cycbid); return gerepileuptoint(av, mulii(h, ZM_det_triangular(D))); } GEN bnrclassno0(GEN A, GEN B, GEN C) { pari_sp av = avma; GEN h, H = NULL; /* adapted from ABC_to_bnr, avoid costly bnrinit if possible */ if (typ(A) == t_VEC) switch(lg(A)) { case 7: /* bnr */ checkbnr(A); H = B; break; case 11: /* bnf */ if (!B) pari_err_TYPE("bnrclassno [bnf+missing conductor]",A); if (!C) return bnrclassno(A, B); A = Buchray(A, B, nf_INIT); H = C; break; default: checkbnf(A);/*error*/ } else checkbnf(A);/*error*/ h = bnr_get_no(A); H = check_subgroup(A, H, &h, 1); if (!H) { avma = av; return icopy(h); } return gerepileuptoint(av, h); } GEN bnrisprincipal(GEN bnr, GEN x, long flag) { pari_sp av = avma; GEN bnf, nf, bid, U, El, ep, L, idep, ex, cycray, cycbid, alpha; checkbnr(bnr); cycray = bnr_get_cyc(bnr); if (lg(cycray) == 1 && !(flag & nf_GEN)) return cgetg(1,t_COL); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); bid = bnr_get_bid(bnr); cycbid = bid_get_cyc(bid); El = gel(bnr,3); U = gel(bnr,4); if (typ(x) == t_VEC && lg(x) == 3) { idep = gel(x,2); x = gel(x,1); } /* precomputed */ else idep = bnfisprincipal0(bnf, x, nf_FORCE|nf_GENMAT); ep = gel(idep,1); if (lg(cycbid) > 1) { GEN beta = gel(idep,2); long i, j = lg(ep); for (i=1; i El.gen (coprime to bid) */ if (typ(gel(El,i)) != t_INT && signe(gel(ep,i))) /* <==> != 1 */ beta = famat_mul(to_famat_shallow(gel(El,i), negi(gel(ep,i))), beta); ep = shallowconcat(ep, ideallog(nf,beta,bid)); } ex = vecmodii(ZM_ZC_mul(U, ep), cycray); if (!(flag & nf_GEN)) return gerepileupto(av, ex); /* compute generator */ L = isprincipalfact(bnf, x, bnr_get_gen(bnr), ZC_neg(ex), nf_GENMAT|nf_GEN_IF_PRINCIPAL|nf_FORCE); if (L == gen_0) pari_err_BUG("isprincipalray"); alpha = nffactorback(nf, L, NULL); if (lg(cycbid) > 1) { GEN v = gel(bnr,6), u2 = gel(v,1), u1 = gel(v,2), du2 = gel(v,3); GEN y = ZM_ZC_mul(u2, ideallog(nf, L, bid)); if (!is_pm1(du2)) y = ZC_Z_divexact(y,du2); y = ZC_reducemodmatrix(y, u1); alpha = nfdiv(nf, alpha, nffactorback(nf, init_units(bnf), y)); } return gerepilecopy(av, mkvec2(ex,alpha)); } GEN isprincipalray(GEN bnr, GEN x) { return bnrisprincipal(bnr,x,0); } GEN isprincipalraygen(GEN bnr, GEN x) { return bnrisprincipal(bnr,x,nf_GEN); } /* N! / N^N * (4/pi)^r2 * sqrt(|D|) */ GEN minkowski_bound(GEN D, long N, long r2, long prec) { pari_sp av = avma; GEN c = divri(mpfactr(N,prec), powuu(N,N)); if (r2) c = mulrr(c, powru(divur(4,mppi(prec)), r2)); c = mulrr(c, gsqrt(absi(D),prec)); return gerepileuptoleaf(av, c); } /* DK = |dK| */ static GEN zimmertbound(long N,long R2,GEN DK) { pari_sp av = avma; GEN w; if (N < 2) return gen_1; if (N < 21) { const double c[19][11] = { {/*2*/ 0.6931, 0.45158}, {/*3*/ 1.71733859, 1.37420604}, {/*4*/ 2.91799837, 2.50091538, 2.11943331}, {/*5*/ 4.22701425, 3.75471588, 3.31196660}, {/*6*/ 5.61209925, 5.09730381, 4.60693851, 4.14303665}, {/*7*/ 7.05406203, 6.50550021, 5.97735406, 5.47145968}, {/*8*/ 8.54052636, 7.96438858, 7.40555445, 6.86558259, 6.34608077}, {/*9*/ 10.0630022, 9.46382812, 8.87952524, 8.31139202, 7.76081149}, {/*10*/11.6153797, 10.9966020, 10.3907654, 9.79895170, 9.22232770, 8.66213267}, {/*11*/13.1930961, 12.5573772, 11.9330458, 11.3210061, 10.7222412, 10.1378082}, {/*12*/14.7926394, 14.1420915, 13.5016616, 12.8721114, 12.2542699, 11.6490374, 11.0573775}, {/*13*/16.4112395, 15.7475710, 15.0929680, 14.4480777, 13.8136054, 13.1903162, 12.5790381}, {/*14*/18.0466672, 17.3712806, 16.7040780, 16.0456127, 15.3964878, 14.7573587, 14.1289364, 13.5119848}, {/*15*/19.6970961, 19.0111606, 18.3326615, 17.6620757, 16.9999233, 16.3467686, 15.7032228, 15.0699480}, {/*16*/21.3610081, 20.6655103, 19.9768082, 19.2953176, 18.6214885, 17.9558093, 17.2988108, 16.6510652, 16.0131906}, {/*17*/23.0371259, 22.3329066, 21.6349299, 20.9435607, 20.2591899, 19.5822454, 18.9131878, 18.2525157, 17.6007672}, {/*18*/24.7243611, 24.0121449, 23.3056902, 22.6053167, 21.9113705, 21.2242247, 20.5442836, 19.8719830, 19.2077941, 18.5522234}, {/*19*/26.4217792, 25.7021950, 24.9879497, 24.2793271, 23.5766321, 22.8801952, 22.1903709, 21.5075437, 20.8321263, 20.1645647}, {/*20*/28.1285704, 27.4021674, 26.6807314, 25.9645140, 25.2537867, 24.5488420, 23.8499943, 23.1575823, 22.4719720, 21.7935548, 21.1227537} }; w = mulrr(dbltor(exp(-c[N-2][R2])), gsqrt(DK,DEFAULTPREC)); } else { w = minkowski_bound(DK, N, R2, DEFAULTPREC); } return gerepileuptoint(av, ceil_safe(w)); } /* return \gamma_n^n if known, an upper bound otherwise */ static GEN hermiteconstant(long n) { GEN h,h1; pari_sp av; switch(n) { case 1: return gen_1; case 2: return mkfrac(utoipos(4), utoipos(3)); case 3: return gen_2; case 4: return utoipos(4); case 5: return utoipos(8); case 6: return mkfrac(utoipos(64), utoipos(3)); case 7: return utoipos(64); case 8: return utoipos(256); } av = avma; h = powru(divur(2,mppi(DEFAULTPREC)), n); h1 = sqrr(ggamma(gdivgs(utoipos(n+4),2),DEFAULTPREC)); return gerepileuptoleaf(av, mulrr(h,h1)); } /* 1 if L (= nf != Q) primitive for sure, 0 if MAYBE imprimitive (may have a * subfield K) */ static long isprimitive(GEN nf) { long p, i, l, ep, N = nf_get_degree(nf); GEN D, fa; p = ucoeff(factoru(N), 1,1); /* smallest prime | N */ if (p == N) return 1; /* prime degree */ /* N = [L:Q] = product of primes >= p, same is true for [L:K] * d_L = t d_K^[L:K] --> check that some q^p divides d_L */ D = nf_get_disc(nf); fa = gel(absi_factor_limit(D,0),2); /* list of v_q(d_L). Don't check large primes */ if (mod2(D)) i = 1; else { /* q = 2 */ ep = itos(gel(fa,1)); if ((ep>>1) >= p) return 0; /* 2 | d_K ==> 4 | d_K */ i = 2; } l = lg(fa); for ( ; i < l; i++) { ep = itos(gel(fa,i)); if (ep >= p) return 0; } return 1; } static GEN dft_bound(void) { if (DEBUGLEVEL>1) err_printf("Default bound for regulator: 0.2\n"); return dbltor(0.2); } static GEN regulatorbound(GEN bnf) { long N, R1, R2, R; GEN nf, dK, p1, c1; nf = bnf_get_nf(bnf); N = nf_get_degree(nf); if (!isprimitive(nf)) return dft_bound(); dK = absi(nf_get_disc(nf)); nf_get_sign(nf, &R1, &R2); R = R1+R2-1; c1 = (!R2 && N<12)? int2n(N & (~1UL)): powuu(N,N); if (cmpii(dK,c1) <= 0) return dft_bound(); p1 = sqrr(glog(gdiv(dK,c1),DEFAULTPREC)); p1 = divru(gmul2n(powru(divru(mulru(p1,3),N*(N*N-1)-6*R2),R),R2), N); p1 = sqrtr(gdiv(p1, hermiteconstant(R))); if (DEBUGLEVEL>1) err_printf("Mahler bound for regulator: %Ps\n",p1); return gmax(p1, dbltor(0.2)); } static int is_unit(GEN M, long r1, GEN x) { pari_sp av = avma; GEN Nx = ground( embed_norm(RgM_zc_mul(M,x), r1) ); int ok = is_pm1(Nx); avma = av; return ok; } /* FIXME: should use smallvectors */ static GEN minimforunits(GEN nf, long BORNE, ulong w) { const long prec = MEDDEFAULTPREC; long n, r1, i, j, k, s, *x, cnt = 0; pari_sp av = avma; GEN u, r, M; double p, norme, normin, normax; double **q,*v,*y,*z; double eps=0.000001, BOUND = BORNE * 1.00001; if (DEBUGLEVEL>=2) { err_printf("Searching minimum of T2-form on units:\n"); if (DEBUGLEVEL>2) err_printf(" BOUND = %ld\n",BORNE); err_flush(); } n = nf_get_degree(nf); r1 = nf_get_r1(nf); minim_alloc(n+1, &q, &x, &y, &z, &v); M = gprec_w(nf_get_M(nf), prec); r = gaussred_from_QR(nf_get_G(nf), prec); for (j=1; j<=n; j++) { v[j] = gtodouble(gcoeff(r,j,j)); for (i=1; i1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k>1); if (!x[1] && y[1]<=eps) break; if (DEBUGLEVEL>8){ err_printf("."); err_flush(); } if (++cnt == 5000) return NULL; /* too expensive */ p = (double)x[1] + z[1]; norme = y[1] + p*p*v[1] + eps; if (norme > 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 (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; } #undef NBMAX static int is_zero(GEN x, long bitprec) { return (gexpo(x) < -bitprec); } static int is_complex(GEN x, long bitprec) { return !is_zero(imag_i(x), bitprec); } /* assume M_star t_REAL * FIXME: what does this do ? To be rewritten */ static GEN compute_M0(GEN M_star,long N) { long m1,m2,n1,n2,n3,lr,lr1,lr2,i,j,l,vx,vy,vz,vM; GEN pol,p1,p2,p3,p4,p5,p6,p7,p8,p9,u,v,w,r,r1,r2,M0,M0_pro,S,P,M; GEN f1,f2,f3,g1,g2,g3,pg1,pg2,pg3,pf1,pf2,pf3,X,Y,Z; 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); M0 = NULL; m1 = N/3; for (n1=1; n1<=m1; n1++) /* 1 <= n1 <= n2 <= n3 < N */ { m2 = (N-n1)>>1; for (n2=n1; n2<=m2; n2++) { pari_sp av = avma; n3=N-n1-n2; if (n1==n2 && n1==n3) /* n1 = n2 = n3 = m1 = N/3 */ { p1 = divru(M_star, m1); p4 = sqrtr_abs( mulrr(addsr(1,p1),subrs(p1,3)) ); p5 = subrs(p1,1); u = gen_1; v = gmul2n(addrr(p5,p4),-1); w = gmul2n(subrr(p5,p4),-1); M0_pro=gmul2n(mulur(m1,addrr(sqrr(logr_abs(v)),sqrr(logr_abs(w)))), -2); if (DEBUGLEVEL>2) { err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); err_flush(); } if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } else if (n1==n2 || n2==n3) { /* n3 > N/3 >= n1 */ long k = N - 2*n2; p2 = deg1pol_shallow(stoi(-n2), M_star, vx); /* M* - n2 X */ p3 = gmul(powuu(k,k), gpowgs(gsubgs(RgX_Rg_mul(p2, M_star), k*k), n2)); pol = gsub(p3, RgX_mul(monomial(powuu(n2,n2), n2, vx), gpowgs(p2, N-n2))); r = roots(pol, DEFAULTPREC); lr = lg(r); for (i=1; i2) { err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); err_flush(); } if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } } else { f1 = gsub(gadd(gmulsg(n1,X),gadd(gmulsg(n2,Y),gmulsg(n3,Z))), M); f2 = gmulsg(n1,gmul(Y,Z)); f2 = gadd(f2,gmulsg(n2,gmul(X,Z))); f2 = gadd(f2,gmulsg(n3,gmul(X,Y))); f2 = gsub(f2,gmul(M,gmul(X,gmul(Y,Z)))); f3 = gsub(gmul(gpowgs(X,n1),gmul(gpowgs(Y,n2),gpowgs(Z,n3))), gen_1); /* f1 = n1 X + n2 Y + n3 Z - M */ /* f2 = n1 YZ + n2 XZ + n3 XY */ /* f3 = X^n1 Y^n2 Z^n3 - 1*/ g1=resultant(f1,f2); g1=primpart(g1); g2=resultant(f1,f3); g2=primpart(g2); g3=resultant(g1,g2); g3=primpart(g3); pf1=gsubst(f1,vM,M_star); pg1=gsubst(g1,vM,M_star); pf2=gsubst(f2,vM,M_star); pg2=gsubst(g2,vM,M_star); pf3=gsubst(f3,vM,M_star); pg3=gsubst(g3,vM,M_star); /* g3 = Res_Y,Z(f1,f2,f3) */ r = roots(pg3,DEFAULTPREC); lr = lg(r); for (i=1; i2) { err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); err_flush(); } if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } } } } if (!M0) avma = av; else M0 = gerepilecopy(av, M0); } } for (i=1;i<=4;i++) (void)delete_var(); return M0? M0: gen_0; } static GEN lowerboundforregulator(GEN bnf, GEN units) { long i, N, R2, RU = lg(units)-1; GEN nf, M0, M, G, bound, minunit, vecminim; if (!RU) return gen_1; nf = bnf_get_nf(bnf); N = nf_get_degree(nf); R2 = nf_get_r2(nf); G = nf_get_G(nf); minunit = gnorml2(RgM_RgC_mul(G, gel(units,1))); /* T2(units[1]) */ for (i=2; i<=RU; i++) { GEN t = gnorml2(RgM_RgC_mul(G, gel(units,i))); if (gcmp(t,minunit) < 0) minunit = t; } 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); 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; M = sqrtr(M); if (DEBUGLEVEL>1) err_printf("(lower bound for regulator) M = %.28Pg\n",M); return M; } /* upper bound for the index of bnf.fu in the full unit group */ static GEN bound_unit_index(GEN bnf, GEN units) { pari_sp av = avma; GEN x = lowerboundforregulator(bnf, units); if (!x) { avma = av; x = regulatorbound(bnf); } return gerepileuptoint(av, ground(gdiv(bnf_get_reg(bnf), x))); } /* Compute a square matrix of rank #beta associated to a family * (P_i), 1<=i<=#beta, of primes s.t. N(P_i) = 1 mod p, and * (P_i,beta[j]) = 1 for all i,j */ static void primecertify(GEN bnf, GEN beta, ulong p, GEN bad) { long i, j, nbcol, lb, nbqq, ra; GEN nf,mat,gq,LQ,newcol,g,ord,modpr; ulong q; ord = NULL; /* gcc -Wall */ nbcol = 0; nf = bnf_get_nf(bnf); lb = lg(beta)-1; mat = cgetg(1,t_MAT); q = 1UL; for(;;) { q += 2*p; if (!umodiu(bad,q) || !uisprime(q)) continue; gq = utoipos(q); LQ = idealprimedec(bnf,gq); 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 */ if (!g) { g = gener_Flxq(pol_x(0), q, &ord); g = utoipos(g[2]); /* from Flx of degree 0 to t_INT */ } modpr = zkmodprinit(nf, Q); newcol = cgetg(lb+1,t_COL); for (j=1; j<=lb; j++) { GEN t = to_Fp_simple(nf, gel(beta,j), modpr); gel(newcol,j) = Fp_log(t,g,ord,gq); } if (DEBUGLEVEL>3) { if (i==1) err_printf(" generator of (Zk/Q)^*: %Ps\n", g); err_printf(" prime ideal Q: %Ps\n",Q); err_printf(" column #%ld of the matrix log(b_j/Q): %Ps\n", nbcol, newcol); } mat1 = shallowconcat(mat,newcol); ra = ZM_rank(mat1); if (ra==nbcol) continue; if (DEBUGLEVEL>2) err_printf(" new rank: %ld\n",ra); if (++nbcol == lb) return; mat = mat1; } } } struct check_pr { long w; /* #mu(K) */ GEN mu; /* generator of mu(K) */ GEN fu; GEN cyc; GEN cycgen; GEN bad; /* p | bad <--> p | some element occurring in cycgen */ }; static void check_prime(ulong p, GEN bnf, struct check_pr *S) { pari_sp av = avma; long i,b, lc = lg(S->cyc), lf = lg(S->fu); GEN beta = cgetg(lf+lc, t_VEC); if (DEBUGLEVEL>1) err_printf(" *** testing p = %lu\n",p); for (b=1; bcyc,b), p)) break; /* p \nmid cyc[b] */ if (b==1 && DEBUGLEVEL>2) err_printf(" p divides h(K)\n"); gel(beta,b) = gel(S->cycgen,b); } if (S->w % p == 0) { if (DEBUGLEVEL>2) err_printf(" p divides w(K)\n"); gel(beta,b++) = S->mu; } for (i=1; ifu,i); setlg(beta, b); /* beta = [cycgen[i] if p|cyc[i], tu if p|w, fu] */ if (DEBUGLEVEL>3) {err_printf(" Beta list = %Ps\n",beta); err_flush();} primecertify(bnf,beta,p,S->bad); avma = av; } static void init_bad(struct check_pr *S, GEN nf, GEN gen) { long i, l = lg(gen); GEN bad = gen_1; for (i=1; i < l; i++) bad = lcmii(bad, gcoeff(gel(gen,i),1,1)); for (i = 1; i < l; i++) { GEN c = gel(S->cycgen,i); long j; if (typ(c) == t_MAT) { GEN g = gel(c,1); for (j = 1; j < lg(g); j++) { GEN h = idealhnf_shallow(nf, gel(g,j)); bad = lcmii(bad, gcoeff(h,1,1)); } } } S->bad = bad; } long bnfcertify0(GEN bnf, long flag) { pari_sp av = avma; long i, N; GEN nf, cyc, B; ulong bound, p; struct check_pr S; forprime_t T; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); if (N==1) return 1; testprimes(bnf, zimmertbound(N, nf_get_r2(nf), absi(nf_get_disc(nf)))); if (flag) return 1; cyc = bnf_get_cyc(bnf); S.w = bnf_get_tuN(bnf); S.mu = nf_to_scalar_or_basis(nf, bnf_get_tuU(bnf)); S.fu= matalgtobasis(nf, bnf_get_fu(bnf)); S.cyc = cyc; S.cycgen = check_and_build_cycgen(bnf); init_bad(&S, nf, bnf_get_gen(bnf)); B = bound_unit_index(bnf, S.fu); if (DEBUGLEVEL) { err_printf("PHASE 2 [UNITS]: are all primes good ?\n"); err_printf(" Testing primes <= %Ps\n", B); err_flush(); } bound = itou_or_0(B); if (!bound) pari_err_OVERFLOW("bnfcertify [too many primes to check]"); if (u_forprime_init(&T, 2, bound)) while ( (p = u_forprime_next(&T)) ) check_prime(p,bnf, &S); if (lg(cyc) > 1) { GEN f = Z_factor(gel(cyc,1)), P = gel(f,1); long l = lg(P); if (DEBUGLEVEL>1) { err_printf(" Testing primes | h(K)\n\n"); err_flush(); } for (i=1; i bound) check_prime(p,bnf, &S); } } avma = av; return 1; } long bnfcertify(GEN bnf) { return bnfcertify0(bnf, 0); } /*******************************************************************/ /* */ /* RAY CLASS FIELDS: CONDUCTORS AND DISCRIMINANTS */ /* */ /*******************************************************************/ /* Let bnr1 with generators, bnr2 be such that mod(bnr2) | mod(bnr1), compute * the matrix of the surjective map Cl(bnr1) ->> Cl(bnr2) */ GEN bnrsurjection(GEN bnr1, GEN bnr2) { long l, i; GEN M, gen = bnr_get_gen(bnr1); l = lg(gen); M = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(M,i) = isprincipalray(bnr2, gel(gen,i)); return M; } /* s: = Cl_f --> Cl_f2 --> 0, H subgroup of Cl_f (generators given as * HNF on [gen]). Return subgroup s(H) in Cl_f2. bnr must include generators */ static GEN imageofgroup(GEN bnr, GEN bnr2, GEN H) { GEN H2, cyc2 = bnr_get_cyc(bnr2); if (!H) return diagonal_shallow(cyc2); H2 = ZM_mul(bnrsurjection(bnr, bnr2), H); return ZM_hnfmodid(H2, cyc2); /* s(H) in Cl_n */ } /* convert A,B,C to [bnr, H] */ GEN ABC_to_bnr(GEN A, GEN B, GEN C, GEN *H, int gen) { if (typ(A) == t_VEC) switch(lg(A)) { case 7: /* bnr */ *H = B; return A; case 11: /* bnf */ if (!B) pari_err_TYPE("ABC_to_bnr [bnf+missing conductor]",A); *H = C; return Buchray(A,B, gen? nf_INIT | nf_GEN: nf_INIT); } pari_err_TYPE("ABC_to_bnr",A); *H = NULL; return NULL; /* not reached */ } GEN bnrconductor0(GEN A, GEN B, GEN C, long flag) { GEN H, bnr = ABC_to_bnr(A,B,C,&H, flag > 0); return bnrconductor(bnr, H, flag); } long bnrisconductor0(GEN A,GEN B,GEN C) { GEN H, bnr = ABC_to_bnr(A,B,C,&H, 0); return bnrisconductor(bnr, H); } /* return bnrisprincipal(bnr, (x)), assuming z = ideallog(x) */ static GEN ideallog_to_bnr(GEN bnr, GEN z) { GEN U = gel(bnr,4), divray = bnr_get_cyc(bnr); long j, l, lU, lz; int col; if (lg(z) == 1) return z; col = (typ(z) == t_COL); /* else t_MAT */ lz = col? lg(z): lgcols(z); lU = lg(U); if (lz != lU) { if (lz == 1) return zerocol(nbrows(U)); /* lU != 1 */ U = vecslice(U, lU-lz+1, lU-1); /* remove Cl(K) part */ } if (col) { z = ZM_ZC_mul(U, z); z = vecmodii(z, divray); } else { z = ZM_mul(U, z); l = lg(z); for (j = 1; j < l; j++) gel(z,j) = vecmodii(gel(z,j), divray); } return z; } static GEN bnr_log_gen_pr(GEN bnr, zlog_S *S, GEN nf, long e, long index) { return ideallog_to_bnr(bnr, log_gen_pr(S, index, nf, e)); } static GEN bnr_log_gen_arch(GEN bnr, zlog_S *S, long index) { return ideallog_to_bnr(bnr, log_gen_arch(S, index)); } /* A \subset H ? Allow H = NULL = trivial subgroup */ static int contains(GEN H, GEN A) { return H? (hnf_solve(H, A) != NULL): gequal0(A); } /* (see also Discrayrel). Given a number field bnf=bnr[1], a ray class * group structure bnr (with generators if flag > 0), and a subgroup H of the * ray class group, compute the conductor of H if flag=0. If flag > 0, compute * furthermore the corresponding H' and output * if flag = 1: [[ideal,arch],[hm,cyc,gen],H'] * if flag = 2: [[ideal,arch],newbnr,H'] */ GEN bnrconductor(GEN bnr, GEN H0, long flag) { pari_sp av = avma; long j, k, l; GEN bnf, nf, bid, ideal, archp, clhray, bnr2, e2, e, mod, H; int iscond0 = 1, iscondinf = 1; zlog_S S; checkbnr(bnr); bnf = bnr_get_bnf(bnr); bid = bnr_get_bid(bnr); init_zlog_bid(&S, bid); clhray = bnr_get_no(bnr); nf = bnf_get_nf(bnf); H = check_subgroup(bnr, H0, &clhray, 1); archp = S.archp; e = S.e; l = lg(e); e2 = cgetg(l, t_COL); for (k = 1; k < l; k++) { for (j = itos(gel(e,k)); j > 0; j--) { if (!contains(H, bnr_log_gen_pr(bnr, &S, nf, j, k))) break; iscond0 = 0; } gel(e2,k) = stoi(j); } l = lg(archp); for (k = 1; k < l; k++) { if (!contains(H, bnr_log_gen_arch(bnr, &S, k))) continue; archp[k] = 0; iscondinf = 0; } if (!iscondinf) { for (j = k = 1; k < l; k++) if (archp[k]) archp[j++] = archp[k]; setlg(archp, j); } ideal = iscond0? bid_get_ideal(bid): factorbackprime(nf, S.P, e2); mod = mkvec2(ideal, indices_to_vec01(archp, nf_get_r1(nf))); if (!flag) return gerepilecopy(av, mod); if (iscond0 && iscondinf) { bnr2 = bnr; if (!H) H = diagonal_shallow(bnr_get_cyc(bnr)); } else { bnr2 = Buchray(bnf, mod, nf_INIT | nf_GEN); H = imageofgroup(bnr, bnr2, H); } return gerepilecopy(av, mkvec3(mod, (flag == 1)? gel(bnr2,5): bnr2, H)); } long bnrisconductor(GEN bnr, GEN H0) { pari_sp av = avma; long j, k, l; GEN bnf, nf, bid, archp, clhray, e, H; zlog_S S; checkbnr(bnr); bnf = bnr_get_bnf(bnr); bid = bnr_get_bid(bnr); init_zlog_bid(&S, bid); clhray = bnr_get_no(bnr); nf = bnf_get_nf(bnf); H = check_subgroup(bnr, H0, &clhray, 1); archp = S.archp; e = S.e; l = lg(e); for (k = 1; k < l; k++) { j = itos(gel(e,k)); if (contains(H, bnr_log_gen_pr(bnr, &S, nf, j, k))) { avma = av; return 0; } } l = lg(archp); for (k = 1; k < l; k++) if (contains(H, bnr_log_gen_arch(bnr, &S, k))) { avma = av; return 0; } 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) { long i, j, reldeg, nfac, k; pari_sp av = avma; GEN bnf, index, discnf, nf, group, detgroup, fa, greldeg; GEN fac, col, cnd; forprime_t S; ulong p; checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); cnd = gel(bnr_get_mod(bnr), 1); polrel = RgX_nffix("rnfnormgroup", nf_get_pol(nf),polrel,1); if (!gequal1(leading_term(polrel))) pari_err_IMPL("rnfnormgroup for non-monic polynomials"); 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 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 */ polr = nfX_to_FqX(polrel, nf, modpr); /* in Fp[X] */ polr = ZX_to_Flx(polr, p); if (!Flx_is_squarefree(polr, p)) { oldf = 0; continue; } fac = gel(Flx_factor(polr, p), 1); f = degpol(gel(fac,1)); 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 (oldf < 0) oldf = f; else if (oldf != f) oldf = 0; if (f == reldeg) continue; /* reldeg-th powers already included */ if (oldf && i == lfa && !umodiu(discnf, p)) pr = utoipos(p); /* 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); } } } return NULL; } GEN nf_deg1_prime(GEN nf) { GEN z, T = nf_get_pol(nf), D = nf_get_disc(nf), f = nf_get_index(nf); long degnf = degpol(T); forprime_t S; pari_sp av; ulong p; u_forprime_init(&S, degnf, ULONG_MAX); av = avma; while ( (p = u_forprime_next(&S)) ) { ulong r; if (!umodiu(D, p) || !umodiu(f, p)) continue; r = Flx_oneroot(ZX_to_Flx(T,p), p); if (r != p) { z = utoi(Fl_neg(r, p)); z = deg1pol_shallow(gen_1, z, varn(T)); return primedec_apply_kummer(nf, z, 1, utoipos(p)); } avma = av; } return NULL; } long rnfisabelian(GEN nf, GEN pol) { GEN modpr, pr, T, Tnf, pp, ro, nfL, C, z, a, sig, eq; long i, j, l, v; ulong p, k, ka; if (typ(nf) == t_POL) Tnf = nf; else { nf = checknf(nf); Tnf = nf_get_pol(nf); } v = varn(Tnf); pol = RgX_nffix("rnfisabelian",Tnf,pol,1); eq = nf_rnfeq(nf,pol); /* init L := K[x]/(pol), nf associated to K */ C = gel(eq,1); setvarn(C, v); /* L = Q[t]/(C) */ a = gel(eq,2); setvarn(a, v); /* root of K.pol in L */ z = nfroots_split(C, QXX_QXQ_eval(pol, a, C)); if (!z) return 0; ro = gel(z,1); l = lg(ro)-1; /* small groups are abelian, as are groups of prime order */ if (l < 6 || uisprime(l)) return 1; nfL = gel(z,2); pr = nf_deg1_prime(nfL); modpr = nf_to_Fq_init(nfL, &pr, &T, &pp); p = itou(pp); k = umodiu(gel(eq,3), p); ka = (k * itou(nf_to_Fq(nfL, a, modpr))) % p; sig= cgetg(l+1, t_VECSMALL); /* image of c = ro[1] + k a [distinguished root of C] by the l automorphisms * sig[i]: ro[1] -> ro[i] */ for (i = 1; i <= l; i++) sig[i] = Fl_add(ka, itou(nf_to_Fq(nfL, gel(ro,i), modpr)), p); ro = Q_primpart(ro); for (i=2; i<=l; i++) { /* start at 2, since sig[1] = identity */ gel(ro,i) = ZX_to_Flx(gel(ro,i), p); for (j=2; j 0; j--) { GEN z = bnr_log_gen_pr(bnr, &S, nf, j, k); H = ZM_hnf(shallowconcat(H, z)); clhss = ZM_det_triangular(H); if (flcond && j==ep && equalii(clhss,clhray)) { avma = av; return gen_0; } if (is_pm1(clhss)) { sum = addis(sum, j); break; } sum = addii(sum, clhss); } dlk = flrel? idealdivpowprime(nf, dlk, pr, sum) : diviiexact(dlk, powii(pr_norm(pr),sum)); } l = lg(archp); nz = nf_get_r1(nf) - (l-1); for (k = 1; k < l; k++) { if (!contains(H0, bnr_log_gen_arch(bnr, &S, k))) continue; if (flcond) { avma = av; return gen_0; } nz++; } return gerepilecopy(av, mkvec3(clhray, stoi(nz), dlk)); } GEN bnrdisc(GEN bnr, GEN H, long flag) { pari_sp av = avma; long clhray, n, R1; GEN z, p1, D, dk, nf, dkabs; D = Discrayrel(bnr, H, flag); if ((flag & rnf_REL) || D == gen_0) return D; nf = checknf(bnr); dkabs = absi(nf_get_disc(nf)); clhray = itos(gel(D,1)); p1 = powiu(dkabs, clhray); n = clhray * nf_get_degree(nf); R1= clhray * itos(gel(D,2)); dk = gel(D,3); if (((n-R1)&3) == 2) dk = negi(dk); /* (2r2) mod 4 = 2 : r2(relext) is odd */ z = cgetg(4,t_VEC); gel(z,1) = utoipos(n); gel(z,2) = stoi(R1); gel(z,3) = mulii(dk,p1); return gerepileupto(av, z); } GEN bnrdisc0(GEN A, GEN B, GEN C, long flag) { GEN H, bnr = ABC_to_bnr(A,B,C,&H, 0); return bnrdisc(bnr,H,flag); } GEN discrayrel(GEN bnr, GEN H) { return bnrdisc(bnr,H,rnf_REL); } GEN discrayrelcond(GEN bnr, GEN H) { return bnrdisc(bnr,H,rnf_REL | rnf_COND); } GEN discrayabs(GEN bnr, GEN H) { return bnrdisc(bnr,H,0); } GEN discrayabscond(GEN bnr, GEN H) { return bnrdisc(bnr,H,rnf_COND); } /* chi character of abelian G: chi[i] = chi(z_i), where G = \oplus Z/cyc[i] z_i. * Return Ker chi [ NULL = trivial subgroup of G ] */ static GEN KerChar(GEN chi, GEN cyc) { long i, l = lg(cyc); GEN m, U, d1; if (typ(chi) != t_VEC) pari_err_TYPE("KerChar",chi); if (lg(chi) != l) pari_err_DIM("KerChar [incorrect character length]"); if (l == 1) return NULL; /* trivial subgroup */ d1 = gel(cyc,1); m = cgetg(l+1,t_MAT); for (i=1; i 1) { GEN z = gel(L,1); if (typ(z) != t_VEC) pari_err_TYPE(s,z); if (lg(z) == 1) return; z = gel(z,1); /* [bid,U] */ if (typ(z) != t_VEC || lg(z) != 3) pari_err_TYPE(s,z); checkbid(gel(z,1)); } } /* Given lists of [bid, unit ideallogs], return lists of ray class * numbers */ GEN bnrclassnolist(GEN bnf,GEN L) { pari_sp av = avma; long i, j, lz, l = lg(L); GEN v, z, V, h; chk_listBU(L, "bnrclassnolist"); if (l == 1) return cgetg(1, t_VEC); bnf = checkbnf(bnf); h = bnf_get_no(bnf); V = cgetg(l,t_VEC); for (i = 1; i < l; i++) { z = gel(L,i); lz = lg(z); gel(V,i) = v = cgetg(lz,t_VEC); for (j=1; j 0) { gel(P,c) = gel(P1,i); gel(E,c) = p1; c++; } } } setlg(P, c); setlg(E, c); return mkmat2(P, E); } /* remove index k */ static GEN factorsplice(GEN fa, long k) { GEN p = gel(fa,1), e = gel(fa,2), P, E; long i, l = lg(p) - 1; P = cgetg(l, typ(p)); E = cgetg(l, typ(e)); for (i=1; iidealrelinit; GEN mod = gel(z,3), Fa = gel(z,1); GEN P = gel(Fa,1), E = gel(Fa,2); long k, nz, clhray = z[2], lP = lg(P); for (k=1; kbnf, gel(mod,1), gel(mod,2), clhray); return get_NR1D(N, clhray, D->degk, nz, D->fadk, idealrel); } /* Given a list of bids and associated unit log matrices, return the * list of discrayabs. Only keep moduli which are conductors. */ GEN discrayabslist(GEN bnf, GEN L) { pari_sp av = avma; long i, l = lg(L); GEN nf, V, D, h; disc_data ID; chk_listBU(L, "discrayabslist"); if (l == 1) return cgetg(1, t_VEC); ID.bnf = bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); h = bnf_get_no(bnf); ID.degk = nf_get_degree(nf); ID.fadk = absi_factor(nf_get_disc(nf)); ID.idealrelinit = trivial_fact(); V = cgetg(l, t_VEC); D = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN z = gel(L,i), v, d; long j, lz = lg(z); gel(V,i) = v = cgetg(lz,t_VEC); gel(D,i) = d = cgetg(lz,t_VEC); for (j=1; j>SHLGVINT) + 1; } INLINE long vext1(ulong i) { return i & (LGVINT-1); } #define bigel(v,i) gmael((v), vext0(i), vext1(i)) /* allocate an extended vector (t_VEC of t_VEC) for N _true_ components */ static GEN bigcgetvec(long N) { long i, nv = vext0(N); GEN v = cgetg(nv+1,t_VEC); for (i=1; inbgen? zeromat(nbgen, lg(U2)-1): ZM_mul(vecslice(U, l1, nbgen), U2) ); } else { U = zeromat(0, lg(U1)+lg(U2)-2); cyc = cgetg(1,t_VEC); } fa = fasmall_append(fa, prcode, e); return gerepilecopy(av, mkvec4(fa, cyc, U, vconcat(gel(b,4),embunit))); } /* B a zsimp */ static GEN bnrclassnointern(GEN B, GEN h) { long lx = lg(B), j; GEN L = cgetg(lx,t_VEC); for (j=1; j>=1) if (kk&1) rowsel[nba++] = nc + jj; setlg(rowsel, nba); rowselect_p(m, mm, rowsel, nc+1); H[k+1] = itou( mulii(h, ZM_det_triangular(ZM_hnf(mm))) ); } gel(L,j) = mkvec2(gel(b,1), H); } return L; } GEN decodemodule(GEN nf, GEN fa) { long n, nn, k; pari_sp av = avma; GEN G, E, id, pr; nf = checknf(nf); if (typ(fa)!=t_MAT || lg(fa)!=3) pari_err_TYPE("decodemodule [not a factorization]", fa); n = nf_get_degree(nf); nn = n*n; id = NULL; G = gel(fa,1); E = gel(fa,2); for (k=1; k15) pari_err_IMPL("r1>15 in discrayabslistarch"); nba = r1; } else { matarchunit = NULL; for (nba=0,k=1; k<=r1; k++) if (signe(gel(arch,k))) nba++; } empty = cgetg(1,t_VEC); /* what follows was rewritten from Ideallist */ p = cgetipos(3); u_forprime_init(&S, 2, bound); av = avma; lim = stack_lim(av,1); sqbou = (ulong)sqrt((double)bound) + 1; Z = bigcgetvec(bound); for (i=2; i<=bound; i++) bigel(Z,i) = empty; embunit = zlog_units(nf, U, sgnU, bidp); bigel(Z,1) = mkvec(zsimp(bidp,embunit)); if (DEBUGLEVEL>1) err_printf("Starting zidealstarunits computations\n"); /* The goal is to compute Ray (lists of bnrclassno). Z contains "zsimps", * simplified bid, from which bnrclassno is easy to compute. * Once p > sqbou, delete Z[i] for i > sqbou and compute directly Ray */ Ray = Z; while ((p[2] = u_forprime_next(&S))) { if (!flbou && (ulong)p[2] > sqbou) { GEN z; flbou = 1; if (DEBUGLEVEL>1) err_printf("\nStarting bnrclassno computations\n"); Z = gerepilecopy(av,Z); av1 = avma; Ray = bigcgetvec(bound); for (i=1; i<=bound; i++) bigel(Ray,i) = bnrclassnointernarch(bigel(Z,i),h,matarchunit); Ray = gerepilecopy(av1,Ray); z = bigcgetvec(sqbou); for (i=1; i<=sqbou; i++) bigel(z,i) = bigel(Z,i); Z = z; } fa = idealprimedec(nf,p); for (j=1; j 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; q = Q; ideal = pr; for (l=1;; l++) /* Q <= bound */ { ulong iQ; bidp = Idealstar(nf,ideal, nf_INIT); embunit = zlog_units_noarch(nf, U, bidp); for (iQ = Q, i = 1; iQ <= bound; iQ += Q, i++) { GEN pz, p2, p1 = bigel(Z,i); long lz = lg(p1); if (lz == 1) continue; p2 = cgetg(lz,t_VEC); c = 0; for (k=1; k 1 && v[lv-1] == prcode) break; gel(p2,++c) = zsimpjoin(z,bidp,embunit,prcode,l); } setlg(p2, c+1); pz = bigel(Ray,iQ); if (flbou) p2 = bnrclassnointernarch(p2,h,matarchunit); if (lg(pz) > 1) p2 = shallowconcat(pz,p2); bigel(Ray,iQ) = p2; } Q = itou_or_0( muluu(Q, q) ); if (!Q || Q > bound) break; ideal = idealmul(nf,ideal,pr); } } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"[1]: discrayabslistarch"); gerepileall(av, flbou? 2: 1, &Z, &Ray); } } if (!flbou) /* occurs iff bound = 1,2,4 */ { if (DEBUGLEVEL>1) err_printf("\nStarting bnrclassno computations\n"); Ray = bigcgetvec(bound); for (i=1; i<=bound; i++) bigel(Ray,i) = bnrclassnointernarch(bigel(Z,i),h,matarchunit); } Ray = gerepilecopy(av, Ray); if (DEBUGLEVEL>1) err_printf("Starting discrayabs computations\n"); if (allarch) nbarch = 1L<>=1) if (ka & 1) nba++; for (k2=1,k=1; k<=r1; k++,k2<<=1) if (karch&k2 && clhrayall[karch-k2+1] == clhray) { res = EMPTY; goto STORE; } } idealrel = idealrelinit; for (k=1; k1) pari_warn(warnmem,"[2]: discrayabslistarch"); for (jj=j+1; jj (N,<) on P */ static long Flx_cindex(GEN P, ulong p) { long d = degpol(P), i; ulong s = 0, p2 = (p-1)>>1; for (i = 0; i <= d; ++i) { ulong x = P[d-i+2]; if (x<=p2) x = 2*x; else x = 1+2*(p-1-x); s = p*s+x; } return s; } /* Compute the polynomial immediately after t for the [[ order */ static void Flx_cnext(GEN t, ulong p) { long i; long p2 = p>>1; for(i=2;;i++) if (t[i]==p2) t[i]=0; else { t[i] = t[i]>1) : x>>1; c/=p; } return Flx_renormalize(P, d+3); } static GEN factorel(GEN h, ulong p) { GEN F = Flx_factcantor(h, p, 0); GEN F1 = gel(F, 1), F2 = gel(F, 2); long i, l1 = lg(F1)-1; GEN p2 = cgetg(l1+1, t_VECSMALL); GEN e2 = cgetg(l1+1, t_VECSMALL); for (i = 1; i <= l1; ++i) { p2[i] = Flx_cindex(gel(F1, i), p); e2[i] = F2[i]; } return mkmat2(p2, e2); } static long Flx_addifsmooth3(pari_sp *av, struct Flxq_log_rel *r, GEN h, long u, long v, long w, ulong p) { long off = r->off; r->nbtest++; if (Flx_is_smooth(h, r->r, p)) { GEN z = factorel(h, p); if (v<0) z = mkmat2(vecsmall_append(gel(z,1),off+u),vecsmall_append(gel(z,2),-1)); else z = famatsmall_reduce(mkmat2( vecsmall_concat(gel(z,1),mkvecsmall3(off+u,off+v,off+w)), vecsmall_concat(gel(z,2),mkvecsmall3(-1,-1,-1)))); gel(r->rel,++r->nbrel) = gerepilecopy(*av,z); if (DEBUGLEVEL && (r->nbrel&511UL)==0) err_printf("%ld%% ",r->nbrel*100/r->nbexp); *av = avma; } else avma = *av; return r->nbrel==r->nb || r->nbrel==r->nbmax; } static void Flx_renormalize_inplace(GEN x, long lx) { long i; for (i = lx-1; i>1; i--) if (x[i]) break; setlg(x, i+1); } /* Let T*X^e=C^3-R a+b+c = 0 (C+a)*(C+b)*(C+c) = C^3+ (a*b+a*c+b*c)*C+a*b*c = R + (a*b+a*c+b*c)*C+a*b*c = R + (a*b-c^2)*C+a*b*c */ static void Flxq_log_cubic(struct Flxq_log_rel *r, GEN C, GEN R, ulong p) { long l = lg(C); GEN a = zero_zv(l); /*We allocate one extra word to catch overflow*/ GEN b = zero_zv(l); pari_sp av = avma; long i,j,k, dh=0; for(i=0; ; i++, Flx_cnext(a, p)) { Flx_renormalize_inplace(a, l+1); r->nb++; if (Flx_addifsmooth3(&av, r, Flx_add(a, C, p), i, -1, -1, p)) return; for(j=2; j<=l; j++) b[j] = 0; for(j=0; j<=i; j++, Flx_cnext(b, p)) { GEN h,c; GEN pab,pabc,pabc2; Flx_renormalize_inplace(b, l+1); c = Flx_neg(Flx_add(a,b,p),p); k = Flx_cindex(c, p); if (k > j) continue; pab = Flx_mul(a, b, p); pabc = Flx_mul(pab,c,p); pabc2= Flx_sub(pab,Flx_sqr(c,p),p); h = Flx_add(R,Flx_add(Flx_mul(C,pabc2,p),pabc,p), p); h = Flx_normalize(h, p); dh = maxss(dh,degpol(h)); if (Flx_addifsmooth3(&av, r, h, i, j, k, p)) return; } } } 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); while (1) { GEN M; *g = Flxq_mul(*g, b, T, p); (*e)++; M = Flx_halfgcd(*g,T,p); if (Flx_is_smooth(gcoeff(M,1,1), r, p)) { GEN z = Flx_add(Flx_mul(gcoeff(M,1,1),*g,p), Flx_mul(gcoeff(M,1,2),T,p),p); if (Flx_is_smooth(z, r, p)) { GEN F = factorel(z, p); GEN G = factorel(gcoeff(M,1,1), p); GEN rel = mkmat2(vecsmall_concat(gel(F, 1),gel(G, 1)), vecsmall_concat(gel(F, 2),zv_neg(gel(G, 2)))); gerepileall(av,2,g,&rel); return rel; } } if (low_stack(lim, stack_lim(av,2))) { if (DEBUGMEM>1) pari_warn(warnmem,"Flxq_log_find_rel"); *g = gerepilecopy(av, *g); } } } /* Generalised Odlyzko formulae ( EUROCRYPT '84, LNCS 209, pp. 224-314, 1985. ) */ /* Return the number of monic, k smooth, degree n polynomials for k=1..r */ static GEN smoothness_vec(ulong p, long r, long n) { long i,j,k; GEN R = cgetg(r+1, t_VEC); GEN V = cgetg(n+1, t_VEC); for (j = 1; j <= n; ++j) gel(V, j) = binomialuu(p+j-1,j); gel(R, 1) = gel(V, n); for (k = 2; k <= r; ++k) { GEN W = cgetg(n+1, t_VEC); GEN Ik = ffnbirred(utoi(p),k); for (j = 1; j <= n; ++j) { long l = j/k; GEN s = gen_0; pari_sp av2 = avma; if (l*k == j) { s = binomial(addis(Ik,l-1), l); l--; } for (i = 0; i <= l; ++i) s = addii(s, mulii(gel(V, j-k*i), binomial(addis(Ik,i-1), i))); gel(W, j) = gerepileuptoint(av2, s); } V = W; gel(R, k) = gel(V, n); } return R; } /* Solve N^2*pr/6 + N*prC = N+fb N^2*pr/6 + N*(prC-1) -fb = 0 */ static GEN smooth_cost(GEN fb, GEN pr, GEN prC) { GEN a = gdivgs(pr,6); GEN b = gsubgs(prC,1); GEN c = gneg(fb); GEN vD = gsqrt(gsub(gsqr(b),gmul2n(gmul(a,c),2)),BIGDEFAULTPREC); return ceil_safe(gdiv(gsub(vD,b),gmul2n(a,1))); } /* Return best choice of r. We loop over d until there is sufficiently many triples (a,b,c) (a+b+c=0) of degree <=d with respect to the probability of smoothness of (a*b-c^2)*C */ static GEN smooth_best(long p, long n, long *pt_r, long *pt_nb) { pari_sp av = avma, av2; GEN bestc = NULL; long bestr = 0, bestFB = 0; long r,d, dC = (n+2)/3; for (r = 1; r < dC; ++r) { GEN fb = ffsumnbirred(utoi(p), r); GEN smoothC = smoothness_vec(p,r,dC); GEN prC = gdiv(gel(smoothC,r), powuu(p,dC)); ulong rels = 0; av2 = avma; for(d=0; d= 0) { rels = itou_or_0(addui(rels, gceil(gmul(gdivgs(sqri(Nmax),6),pr)))); if (!rels) rels = ULONG_MAX; avma = av2; continue; } c = gdivgs(addii(powuu(p,2*d),sqri(N)),6); FB = addii(FB,N); if ((!bestc || gcmp(gmul2n(c,r), gmul2n(bestc,bestr)) < 0)) { if (DEBUGLEVEL) err_printf("r=%ld d=%ld fb=%Ps early rels=%lu P=%.5Pe -> C=%.5Pe \n", r, dt, FB, rels, pr, c); bestc = c; bestr = r; bestFB = itos_or_0(FB); } break; } } *pt_r=bestr; *pt_nb=bestFB; return bestc ? gerepileupto(av, gceil(bestc)): NULL; } static GEN check_kernel(long r, GEN M, long nbi, long nbrow, GEN T, ulong p, GEN m) { pari_sp av = avma; long N = 3*upowuu(p, r); GEN K = FpMs_leftkernel_elt(M, nbrow, m); long i, f=0; long lm = lgefint(m), u=1; GEN g; GEN idx = diviiexact(subis(powuu(p,degpol(T)),1),m); pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); while (signe(gel(K,u))==0) u++; K = FpC_Fp_mul(K, Fp_inv(gel(K, u), m), m); g = Flxq_pow(cindex_Flx(u, r, p, T[1]), idx, T, p); setlg(K, N); for (i=1; i1) timer_printf(&ti,"%ld-smooth element",r); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i=0) { avma = av; return NULL; } nbi = itos(ffsumnbirred(stoi(p), r)); if (DEBUGLEVEL) { err_printf("Size FB=%ld, looking for %ld relations, %Ps tests needed\n", nbi, nb,cost); timer_start(&ti); } T = smallirred_Flx(p,n,get_Flx_var(T0)); for(;;) { S = Flx_ffisom(T0,T,p); a = Flx_Flxq_eval(a0, S, T, p); b = Flx_Flxq_eval(b0, S, T, p); C = Flx_shift(pol1_Flx(get_Flx_var(T)), (n+2)/3); R = Flxq_powu(C,3,T,p); if (DEBUGLEVEL) timer_printf(&ti," model change: %Ps",Flx_to_ZX(T)); rel.nbmax=2*nb; M = cgetg(rel.nbmax+1, t_VEC); rel.rel = M; rel.nbrel = 0; rel.r = r; rel.off = 3*upowuu(p,r); rel.nb = nbi; rel.nbexp = nb; rel.nbtest=0; Flxq_log_cubic(&rel, C, R, p); setlg(M,1+rel.nbrel); if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&ti," %ld relations, %ld generators (%ld tests)",rel.nbrel,rel.nb,rel.nbtest); } W = check_kernel(r, M, nbi, rel.off + rel.nb - nbi, T, p, m); if (W) break; if (DEBUGLEVEL) timer_start(&ti); smallirred_Flx_next(T,p); } if (DEBUGLEVEL) timer_start(&ti); Ao = Flxq_log_rec(W, a, r, T, p, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth element"); Bo = Flxq_log_rec(W, b, r, T, p, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth generator"); e = Fp_div(Ao, Bo, m); if (!Flx_equal(Flxq_pow(b0, e, T0, p), a0)) pari_err_BUG("Flxq_log"); return gerepileupto(av, e); } INLINE GEN Flx_frob(GEN u, ulong p) { return Flx_inflate(u, p); } static GEN rel_Coppersmith(long r, GEN u, GEN v, long h, GEN R, long d, ulong p) { GEN a, b, F, G, M; if (degpol(Flx_gcd(u,v,p))) return NULL; a = Flx_add(Flx_shift(u, h), v, p); if (lgpol(a)==0 || !Flx_is_smooth(a, r, p)) return NULL; b = Flx_add(Flx_mul(R, Flx_frob(u, p), p), Flx_shift(Flx_frob(v, p),d), p); if (!Flx_is_smooth(b, r, p)) return NULL; F = factorel(a, p); G = factorel(b, p); M = mkmat2(vecsmall_concat(gel(F, 1), vecsmall_append(gel(G, 1), 2*p)), vecsmall_concat(zv_z_mul(gel(F, 2),p), vecsmall_append(zv_neg(gel(G, 2)),d))); return famatsmall_reduce(M); } static GEN Flxq_log_Coppersmith(long nbrel, long r, GEN T, ulong p) { long dT = degpol(T); long h = dT/p, d = dT-(h*p); GEN R = Flx_sub(Flx_shift(pol1_Flx(T[1]), dT), T, p); GEN u = zero_zv(dT+2), v = zero_zv(dT+2); long nbtest = 0, rel = 0; GEN M = cgetg(nbrel+1, t_VEC); pari_sp av = avma; long i, j; if (DEBUGLEVEL) err_printf("Coppersmith (R = %ld): ",degpol(R)); for (i=1; ; i++) { Flx_cnext(u, p); Flx_renormalize_inplace(u, dT+2); for(j=2; jnbrel) break; } if (i==j) continue; if (Flx_lead(v)==1) { z = rel_Coppersmith(r, v, u, h, R, d, p); nbtest++; if (z) { gel(M,++rel) = gerepilecopy(av, z); av = avma; if (DEBUGLEVEL && (rel&511UL)==0) err_printf("%ld%%[%ld] ",rel*100/nbrel,i); } if (rel>nbrel) break; } } if (rel>nbrel) break; } if (DEBUGLEVEL) err_printf(": %ld tests\n", nbtest); return M; } static GEN Flxq_log_Coppersmith_d(GEN W, GEN g, long r, GEN T, ulong p, GEN mo); static GEN Flxq_log_from_rel(GEN W, GEN rel, long r, GEN T, ulong p, GEN m) { pari_sp av = avma; GEN F = gel(rel,1), E = gel(rel,2), o = gen_0; long i, l = lg(F); for(i=1; i1) err_printf("Found %lu\n", g[2]); } return gerepileuptoint(av, l); } } avma = av; return NULL; } static GEN Flxq_log_Coppersmith_rec(GEN W, long r2, GEN a, long r, GEN T, ulong p, GEN m) { GEN b = polx_Flx(T[1]); long AV = 0; GEN g = a, bad = pol0_Flx(T[1]); pari_timer ti; while(1) { long i, l; GEN V, F, E, Ao; timer_start(&ti); V = Flxq_log_find_rel(b, r2, T, p, &g, &AV); if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r2); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i41)) return Flxq_log_index_Coppersmith(a, b, m, T, p); else return Flxq_log_index_cubic(a, b, m, T, p); } pari-2.7.5/src/basemath/buch1.c0000644000175000017500000007417212405547147014653 0ustar billbill/* 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" /*******************************************************************/ /* */ /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */ /* QUADRATIC FIELDS */ /* */ /*******************************************************************/ /* For largeprime() hashtable. Note that hashed pseudoprimes are odd (unless * 2 | index), hence the low order bit is not useful. So we hash * HASHBITS bits starting at bit 1, not bit 0 */ #define HASHBITS 10 static const long HASHT = 1L << HASHBITS; static long hash(long q) { return (q & ((1L << (HASHBITS+1)) - 1)) >> 1; } #undef HASHBITS /* See buch2.c: * B->subFB contains split p such that \prod p > sqrt(B->Disc) * B->powsubFB contains powers of forms in B->subFB */ #define RANDOM_BITS 4 static const long CBUCH = (1L< Cl (a > 0) */ static GEN qfr3_canon(GEN x, struct qfr_data *S) { GEN a = gel(x,1), c = gel(x,3); if (signe(a) < 0) { if (absi_equal(a,c)) return qfr3_rho(x, S); setsigne(a, 1); setsigne(c,-1); } return x; } static GEN qfr3_canon_safe(GEN x, struct qfr_data *S) { GEN a = gel(x,1), c = gel(x,3); if (signe(a) < 0) { if (absi_equal(a,c)) return qfr3_rho(x, S); gel(x,1) = negi(a); gel(x,3) = negi(c); } return x; } static GEN qfr5_canon(GEN x, struct qfr_data *S) { GEN a = gel(x,1), c = gel(x,3); if (signe(a) < 0) { if (absi_equal(a,c)) return qfr5_rho(x, S); setsigne(a, 1); setsigne(c,-1); } return x; } static GEN QFR5_comp(GEN x,GEN y, struct qfr_data *S) { return qfr5_canon(qfr5_comp(x,y,S), S); } static GEN QFR3_comp(GEN x, GEN y, struct qfr_data *S) { return qfr3_canon(qfr3_comp(x,y,S), S); } /* compute rho^n(x) */ static GEN qfr5_rho_pow(GEN x, long n, struct qfr_data *S) { long i; pari_sp av = avma, lim = stack_lim(av, 1); for (i=1; i<=n; i++) { x = qfr5_rho(x,S); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"qfr5_rho_pow"); x = gerepilecopy(av, x); } } return gerepilecopy(av, x); } static GEN qfr5_pf(struct qfr_data *S, long p, long prec) { GEN y = primeform_u(S->D,p); return qfr5_canon(qfr5_red(qfr_to_qfr5(y,prec), S), S); } static GEN qfr3_pf(struct qfr_data *S, long p) { GEN y = primeform_u(S->D,p); return qfr3_canon(qfr3_red(y, S), S); } #define qfi_pf primeform_u /* Warning: ex[0] not set in general */ static GEN init_form(struct buch_quad *B, GEN ex, GEN (*comp)(GEN,GEN,struct qfr_data *S)) { long i, l = lg(B->powsubFB); GEN F = NULL; for (i=1; ipowsubFB,i,ex[i]); F = F? comp(F, t, B->QFR): t; } return F; } static GEN qfr5_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFR5_comp); } static GEN QFI_comp(GEN x, GEN y, struct qfr_data *S) { (void)S; return qficomp(x,y); } static GEN qfi_factorback(struct buch_quad *B, GEN ex) { return init_form(B, ex, &QFI_comp); } static GEN random_form(struct buch_quad *B, GEN ex, GEN (*comp)(GEN,GEN, struct qfr_data *S)) { long i, l = lg(ex); pari_sp av = avma; GEN F; for(;;) { for (i=1; i= LIMCMAX) pari_err_BUG("Buchmann's algorithm"); if (LIMC <= LIMCMAX/40) /* cbach <= 0.3 */ LIMC *= 2; else if (LIMCMAX < 60) /* \Delta_K <= 9 */ LIMC++; else LIMC += LIMCMAX / 60; /* cbach += 0.2 */ if (LIMC > LIMCMAX) LIMC = LIMCMAX; return LIMC; } /* Is |q| <= p ? */ static int isless_iu(GEN q, ulong p) { long l = lgefint(q); return l==2 || (l == 3 && (ulong)q[2] <= p); } static long factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp) { ulong X; long i, lo = 0; GEN x = gel(f,1), FB = B->FB, P = B->primfact, E = B->exprimfact; for (i=1; lgefint(x) > 3; i++) { ulong p = (ulong)FB[i], r; GEN q = diviu_rem(x, p, &r); if (!r) { long k = 0; do { k++; x = q; q = diviu_rem(x, p, &r); } while (!r); lo++; P[lo] = p; E[lo] = k; } if (isless_iu(q,p)) { if (lgefint(x) == 3) { X = (ulong)x[2]; goto END; } return 0; } if (i == nFB) return 0; } X = (ulong)x[2]; if (X == 1) { P[0] = 0; return 1; } for (;; i++) { /* single precision affair, split for efficiency */ ulong p = (ulong)FB[i]; ulong q = X / p, r = X % p; /* gcc makes a single div */ if (!r) { long k = 0; do { k++; X = q; q = X / p; r = X % p; } while (!r); lo++; P[lo] = p; E[lo] = k; } if (q <= p) break; if (i == nFB) return 0; } END: if (X > B->limhash) return 0; if (X != 1 && X <= limp) { if (B->badprim && ugcd(X, umodiu(B->badprim,X)) > 1) return 0; lo++; P[lo] = X; E[lo] = 1; X = 1; } P[0] = lo; return X; } /* Check for a "large prime relation" involving q; q may not be prime */ static long * largeprime(struct buch_quad *B, long q, GEN ex, long np, long nrho) { const long hashv = hash(q); long *pt, i, l = lg(B->subFB); for (pt = B->hashtab[hashv]; ; pt = (long*) pt[0]) { if (!pt) { pt = (long*) pari_malloc((l+3) * sizeof(long)); *pt++ = nrho; /* nrho = pt[-3] */ *pt++ = np; /* np = pt[-2] */ *pt++ = q; /* q = pt[-1] */ pt[0] = (long)B->hashtab[hashv]; for (i=1; ihashtab[hashv]=pt; return NULL; } if (pt[-1] == q) break; } for(i=1; iprimes + S->nprimes-1)->p; } /* ensure that S->primes can hold at least nb primes */ void GRH_ensure(GRHcheck_t *S, long nb) { if (S->maxprimes <= nb) { do S->maxprimes *= 2; while (S->maxprimes <= nb); S->primes = (GRHprime_t*)pari_realloc((void*)S->primes, S->maxprimes*sizeof(*S->primes)); } } /* cache data for all primes up to the LIM */ static void cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D) { GRHprime_t *pr; double nb; if (S->limp >= LIM) return; nb = primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */ GRH_ensure(S, nb+1); /* room for one extra prime */ for (pr = S->primes + S->nprimes;;) { ulong p = u_forprime_next(&(S->P)); pr->p = p; pr->logp = log((double)p); pr->dec = (GEN)kroiu(D,p); S->nprimes++; pr++; /* store up to nextprime(LIM) included */ if (p >= LIM) { S->limp = p; break; } } } static GEN compute_invresquad(GRHcheck_t *S) { 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 limp = log(LIMC) / 2; for (; i > 0; pr++, i--) { long s = (long)pr->dec; if (s) { ulong p = pr->p; if (s>0 || pr->logp <= limp) /* Both p and P contribute */ invres = mulur(p - s, divru(invres, p)); else if (s<0) /* Only p contributes */ invres = mulur(p, divru(invres, p - 1)); } } return gerepileuptoleaf(av, invres); } /* p | conductor of order of disc D ? */ static int is_bad(GEN D, ulong p) { pari_sp av = avma; int r; if (p == 2) { r = mod16(D) >> 1; if (r && signe(D) < 0) r = 8-r; return (r < 4); } r = (remii(D, sqru(p)) == gen_0); /* p^2 | D ? */ avma = av; return r; } /* returns the n-th suitable ideal for the factorbase */ static long nthidealquad(GEN D, long n) { pari_sp av = avma; forprime_t S; ulong p; (void)u_forprime_init(&S, 2, ULONG_MAX); while (n > 0) { p = u_forprime_next(&S); if (!is_bad(D, p) && kroiu(D, p) >= 0) n--; } avma = av; return p; } static int quadGRHchk(GEN D, GRHcheck_t *S, ulong LIMC) { double logC = log((double)LIMC), SA = 0, SB = 0; long i; cache_prime_quad(S, LIMC, D); for (i = 0;; i++) { GRHprime_t *pr = S->primes+i; ulong p = pr->p; long M; double logNP, q, A, B; if (p > LIMC) break; if ((long)pr->dec < 0) { logNP = 2 * pr->logp; q = 1/(double)p; } else { logNP = pr->logp; q = 1/sqrt((double)p); } A = logNP * q; B = logNP * A; M = (long)(logC/logNP); if (M > 1) { double inv1_q = 1 / (1-q); A *= (1 - pow(q, M)) * inv1_q; B *= (1 - pow(q, M)*(M+1 - M*q)) * inv1_q * inv1_q; } if ((long)pr->dec>0) { SA += 2*A;SB += 2*B; } else { SA += A; SB += B; } } return GRHok(S, logC, SA, SB); } /* create B->FB, B->numFB; set B->badprim. Return L(kro_D, 1) */ static void FBquad(struct buch_quad *B, ulong C2, ulong C1, GRHcheck_t *S) { GEN D = B->QFR->D; long i; pari_sp av; GRHprime_t *pr; cache_prime_quad(S, C2, D); pr = S->primes; B->numFB = cgetg(C2+1, t_VECSMALL); B->FB = cgetg(C2+1, t_VECSMALL); av = avma; B->KC = 0; i = 0; B->badprim = gen_1; for (;; pr++) /* p <= C2 */ { ulong p = pr->p; if (!B->KC && p > C1) B->KC = i; if (p > C2) break; switch ((long)pr->dec) { case -1: break; /* inert */ case 0: /* ramified */ if (is_bad(D, p)) { B->badprim = muliu(B->badprim, p); break; } /* fall through */ default: /* split */ i++; B->numFB[p] = i; B->FB[i] = p; break; } } B->KC2 = i; setlg(B->FB, B->KC2+1); if (B->badprim != gen_1) B->badprim = gerepileuptoint(av, B->badprim); else { B->badprim = NULL; avma = av; } } /* create B->vperm, return B->subFB */ static GEN subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB) { long i, j, lgsub = 1, ino = 1, lv = B->KC+1; double prod = 1.; pari_sp av; GEN no; B->vperm = cgetg(lv, t_VECSMALL); av = avma; no = cgetg(lv, t_VECSMALL); for (j = 1; j < lv; j++) { ulong p = B->FB[j]; if (!umodiu(D, p)) no[ino++] = j; /* ramified */ else { B->vperm[lgsub++] = j; prod *= p; if (lgsub > minSFB && prod > PROD) break; } } /* lgsub >= 1 otherwise quadGRHchk is false */ i = lgsub; for (j = 1; j < ino;i++,j++) B->vperm[i] = no[j]; for ( ; i < lv; i++) B->vperm[i] = i; no = gclone(vecslice(B->vperm, 1, lgsub-1)); avma = av; return no; } /* assume n >= 1, x[i][j] = B->subFB[i]^j, for j = 1..n */ static GEN powsubFBquad(struct buch_quad *B, long n) { pari_sp av = avma; long i,j, l = lg(B->subFB); GEN F, y, x = cgetg(l, t_VEC), D = B->QFR->D; if (B->PRECREG) /* real */ { for (i=1; iQFR, B->FB[B->subFB[i]], B->PRECREG); y = cgetg(n+1, t_VEC); gel(x,i) = y; gel(y,1) = F; for (j=2; j<=n; j++) gel(y,j) = QFR5_comp(gel(y,j-1), F, B->QFR); } } else /* imaginary */ { for (i=1; iFB[B->subFB[i]]); y = cgetg(n+1, t_VEC); gel(x,i) = y; gel(y,1) = F; for (j=2; j<=n; j++) gel(y,j) = qficomp(gel(y,j-1), F); } } x = gclone(x); avma = av; return x; } static void sub_fact(struct buch_quad *B, GEN col, GEN F) { GEN b = gel(F,2); long i; for (i=1; i<=B->primfact[0]; i++) { ulong p = B->primfact[i], k = B->numFB[p]; long e = B->exprimfact[i]; if (umodiu(b, p<<1) > p) e = -e; col[k] -= e; } } static void add_fact(struct buch_quad *B, GEN col, GEN F) { GEN b = gel(F,2); long i; for (i=1; i<=B->primfact[0]; i++) { ulong p = B->primfact[i], k = B->numFB[p]; long e = B->exprimfact[i]; if (umodiu(b, p<<1) > p) e = -e; col[k] += e; } } static GEN get_clgp(struct buch_quad *B, GEN W, GEN *ptD, long prec) { GEN res, init, u1, D = ZM_snf_group(W,NULL,&u1), Z = prec? real_0(prec): NULL; long i, j, l = lg(W), c = lg(D); res=cgetg(c,t_VEC); init = cgetg(l,t_VEC); for (i=1; iQFR->D, B->FB[B->vperm[i]]); for (j=1; jQFR); g = g? qfr3_comp(g, t, B->QFR): t; } g = qfr3_to_qfr(qfr3_canon_safe(qfr3_red(g, B->QFR), B->QFR), Z); } else { for (i=1; iQFR->D; for (i = 1; i <= B->KC; i++) { /* ramified prime ==> trivial relation */ if (umodiu(D, B->FB[i])) continue; col = zero_zv(B->KC); col[i] = 2; j++; gel(mat,j) = col; gel(C,j) = gen_0; } return j; } static void dbg_all(pari_timer *T, const char *phase, long s, long n) { err_printf("\n"); timer_printf(T, "%s rel [#rel/#test = %ld/%ld]", phase,s,n); } /* Imaginary Quadratic fields */ static void imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat) { pari_timer T; long lgsub = lg(B->subFB), current = *pc, nbtest = 0, s = 0; long i, fpc; pari_sp av; GEN col, form, ex = cgetg(lgsub, t_VECSMALL); if (!current) current = 1; if (DEBUGLEVEL) timer_start(&T); av = avma; for(;;) { if (s >= need) break; avma = av; form = qfi_random(B,ex); form = qficomp(form, qfi_pf(B->QFR->D, B->FB[current])); nbtest++; fpc = factorquad(B,form,B->KC,LIMC); if (!fpc) { if (DEBUGLEVEL>1) err_printf("."); if ((nbtest & 0xff) == 0 && ++current > B->KC) current = 1; continue; } if (fpc > 1) { long *fpd = largeprime(B,fpc,ex,current,0); ulong b1, b2, p; GEN form2; if (!fpd) { if (DEBUGLEVEL>1) err_printf("."); continue; } form2 = qficomp(qfi_factorback(B,fpd), qfi_pf(B->QFR->D, B->FB[fpd[-2]])); p = fpc << 1; b1 = umodiu(gel(form2,2), p); b2 = umodiu(gel(form,2), p); if (b1 != b2 && b1+b2 != p) continue; col = gel(mat,++s); add_fact(B,col, form); (void)factorquad(B,form2,B->KC,LIMC); if (b1==b2) { for (i=1; isubFB[i]] += fpd[i]-ex[i]; sub_fact(B, col, form2); col[fpd[-2]]++; } else { for (i=1; isubFB[i]] += -fpd[i]-ex[i]; add_fact(B, col, form2); col[fpd[-2]]--; } if (DEBUGLEVEL) err_printf(" %ldP",s); } else { col = gel(mat,++s); for (i=1; isubFB[i]] = -ex[i]; add_fact(B, col, form); if (DEBUGLEVEL) err_printf(" %ld",s); } col[current]--; if (++current > B->KC) current = 1; } if (DEBUGLEVEL) dbg_all(&T, "random", s, nbtest); *pc = current; } static int imag_be_honest(struct buch_quad *B) { long p, fpc, s = B->KC, nbtest = 0; GEN F, ex = cgetg(lg(B->subFB), t_VECSMALL); pari_sp av = avma; while (sKC2) { p = B->FB[s+1]; if (DEBUGLEVEL) 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++; } else if (++nbtest > 40) return 0; avma = av; } return 1; } /* Real Quadratic fields */ static void real_relations(struct buch_quad *B, long need, long *pc, long lim, ulong LIMC, GEN mat, GEN C) { pari_timer T; long lgsub = lg(B->subFB), prec = B->PRECREG, current = *pc, nbtest=0, s=0; long i, fpc, endcycle, rhoacc, rho; /* 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; GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL); if (DEBUGLEVEL) timer_start(&T); if (!current) current = 1; if (lim > need) lim = need; av = avma; limstack = stack_lim(av,1); for(;;) { if (s >= need) break; if (first && s >= lim) { first = 0; if (DEBUGLEVEL) dbg_all(&T, "initial", s, nbtest); } avma = av; form = qfr3_random(B, ex); if (!first) form = QFR3_comp(form, qfr3_pf(B->QFR, B->FB[current]), B->QFR); av1 = avma; form0 = form; form1 = NULL; endcycle = rhoacc = 0; rho = -1; CYCLE: if (endcycle || rho > 5000) { if (++current > B->KC) current = 1; continue; } if (low_stack(limstack, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"real_relations"); gerepileall(av1, form1? 2: 1, &form, &form1); } if (rho < 0) rho = 0; /* first time in */ else { form = qfr3_rho(form, B->QFR); rho++; rhoacc++; if (first) endcycle = (absi_equal(gel(form,1),gel(form0,1)) && equalii(gel(form,2),gel(form0,2))); else { if (absi_equal(gel(form,1), gel(form,3))) /* a = -c */ { if (absi_equal(gel(form,1),gel(form0,1)) && equalii(gel(form,2),gel(form0,2))) continue; form = qfr3_rho(form, B->QFR); rho++; rhoacc++; } else { setsigne(form[1],1); setsigne(form[3],-1); } if (equalii(gel(form,1),gel(form0,1)) && equalii(gel(form,2),gel(form0,2))) continue; } } nbtest++; fpc = factorquad(B,form,B->KC,LIMC); if (!fpc) { if (DEBUGLEVEL>1) err_printf("."); goto CYCLE; } if (fpc > 1) { /* look for Large Prime relation */ long *fpd = largeprime(B,fpc,ex,first? 0: current,rhoacc); ulong b1, b2, p; GEN form2; if (!fpd) { if (DEBUGLEVEL>1) err_printf("."); goto CYCLE; } if (!form1) { form1 = qfr5_factorback(B,ex); if (!first) form1 = QFR5_comp(form1, qfr5_pf(B->QFR, B->FB[current], prec), B->QFR); } form1 = qfr5_rho_pow(form1, rho, B->QFR); rho = 0; form2 = qfr5_factorback(B,fpd); if (fpd[-2]) form2 = QFR5_comp(form2, qfr5_pf(B->QFR, B->FB[fpd[-2]], prec), B->QFR); form2 = qfr5_rho_pow(form2, fpd[-3], B->QFR); if (!absi_equal(gel(form2,1),gel(form2,3))) { setsigne(form2[1], 1); setsigne(form2[3],-1); } p = fpc << 1; b1 = umodiu(gel(form2,2), p); b2 = umodiu(gel(form1,2), p); if (b1 != b2 && b1+b2 != p) goto CYCLE; col = gel(mat,++s); add_fact(B, col, form1); (void)factorquad(B,form2,B->KC,LIMC); if (b1==b2) { for (i=1; isubFB[i]] += fpd[i]-ex[i]; sub_fact(B,col, form2); if (fpd[-2]) col[fpd[-2]]++; d = qfr5_dist(subii(gel(form1,4),gel(form2,4)), divrr(gel(form1,5),gel(form2,5)), prec); } else { for (i=1; isubFB[i]] += -fpd[i]-ex[i]; add_fact(B, col, form2); if (fpd[-2]) col[fpd[-2]]--; d = qfr5_dist(addii(gel(form1,4),gel(form2,4)), mulrr(gel(form1,5),gel(form2,5)), prec); } if (DEBUGLEVEL) err_printf(" %ldP",s); } else { /* standard relation */ if (!form1) { form1 = qfr5_factorback(B, ex); if (!first) form1 = QFR5_comp(form1, qfr5_pf(B->QFR, B->FB[current], prec), B->QFR); } form1 = qfr5_rho_pow(form1, rho, B->QFR); rho = 0; col = gel(mat,++s); for (i=1; isubFB[i]] = -ex[i]; add_fact(B, col, form1); d = qfr5_dist(gel(form1,4), gel(form1,5), prec); if (DEBUGLEVEL) err_printf(" %ld",s); } affrr(d, gel(C,s)); if (first) { if (s >= lim) continue; goto CYCLE; } else { col[current]--; if (++current > B->KC) current = 1; } } if (DEBUGLEVEL) dbg_all(&T, "random", s, nbtest); *pc = current; } static int real_be_honest(struct buch_quad *B) { long p, fpc, s = B->KC, nbtest = 0; GEN F,F0, ex = cgetg(lg(B->subFB), t_VECSMALL); pari_sp av = avma; while (sKC2) { p = B->FB[s+1]; if (DEBUGLEVEL) err_printf(" %ld",p); F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->QFR, p), B->QFR); for (F0 = F;;) { fpc = factorquad(B,F,s,p-1); if (fpc == 1) { nbtest=0; s++; break; } if (++nbtest > 40) return 0; F = qfr3_canon(qfr3_rho(F, B->QFR), B->QFR); if (equalii(gel(F,1),gel(F0,1)) && equalii(gel(F,2),gel(F0,2))) break; } avma = av; } return 1; } static GEN gcdreal(GEN a,GEN b) { if (!signe(a)) return mpabs(b); if (!signe(b)) return mpabs(a); if (typ(a)==t_INT) { if (typ(b)==t_INT) return gcdii(a,b); a = itor(a, lg(b)); } else if (typ(b)==t_INT) b = itor(b, lg(a)); if (expo(a)<-5) return absr(b); if (expo(b)<-5) return absr(a); a = absr(a); b = absr(b); while (expo(b) >= -5 && signe(b)) { long e; GEN r, q = gcvtoi(divrr(a,b),&e); if (e > 0) return NULL; r = subrr(a, mulir(q,b)); a = b; b = r; } return absr(a); } static int get_R(struct buch_quad *B, GEN C, long sreg, GEN z, GEN *ptR) { GEN R = gen_1; double c; long i; if (B->PRECREG) { R = mpabs(gel(C,1)); for (i=2; i<=sreg; i++) { R = gcdreal(gel(C,i), R); if (!R) return fupb_PRECI; } if (gexpo(R) <= -3) { if (DEBUGLEVEL) err_printf("regulator is zero.\n"); return fupb_RELAT; } if (DEBUGLEVEL) err_printf("#### Tentative regulator: %Ps\n",R); } c = gtodouble(gmul(z, R)); if (c < 0.8 || c > 1.3) return fupb_RELAT; *ptR = R; return fupb_NONE; } static int quad_be_honest(struct buch_quad *B) { int r; if (B->KC2 <= B->KC) return 1; if (DEBUGLEVEL) 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"); return r; } GEN Buchquad(GEN D, double cbach, double cbach2, long prec) { const long MAXRELSUP = 7, SFB_MAX = 3; pari_timer T; pari_sp av0 = avma, av, av2; const long RELSUP = 5; long i, s, current, triv, sfb_trials, nrelsup, nreldep, need, nsubFB, minSFB; ulong low, high, LIMC0, LIMC, LIMC2, LIMCMAX, cp; GEN W, cyc, res, gen, dep, mat, C, extraC, B, R, invhr, h = NULL; /*-Wall*/ double drc, sdrc, lim, LOGD, LOGD2; GRHcheck_t GRHcheck; struct qfr_data QFR; struct buch_quad BQ; int FIRST = 1; check_quaddisc(D, &s, /*junk*/&i, "Buchquad"); R = NULL; /* -Wall */ BQ.QFR = &QFR; QFR.D = D; if (s < 0) { if (cmpiu(QFR.D,4) <= 0) { GEN z = cgetg(5,t_VEC); gel(z,1) = gel(z,4) = gen_1; gel(z,2) = gel(z,3) = cgetg(1,t_VEC); return z; } BQ.PRECREG = 0; } else { BQ.PRECREG = maxss(prec+EXTRAPRECWORD, nbits2prec(2*expi(QFR.D) + 128)); } if (DEBUGLEVEL) timer_start(&T); BQ.primfact = new_chunk(100); BQ.exprimfact = new_chunk(100); BQ.hashtab = (long**) new_chunk(HASHT); for (i=0; i 6.) { if (cbach2 < cbach) cbach2 = cbach; cbach = 6.; } if (cbach < 0.) pari_err_DOMAIN("Buchquad","Bach constant","<",gen_0,dbltor(cbach)); av = avma; BQ.powsubFB = BQ.subFB = NULL; minSFB = (expi(D) > 15)? 3: 2; init_GRHcheck(&GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD); high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1); LIMCMAX = (long)(6.*LOGD2); /* 97/1223 below to ensure a good enough approximation of residue */ cache_prime_quad(&GRHcheck, expi(D) < 16 ? 97: 1223, D); while (!quadGRHchk(D, &GRHcheck, high)) { low = high; high *= 2; } while (high - low > 1) { long test = (low+high)/2; if (quadGRHchk(D, &GRHcheck, test)) high = test; else low = test; } if (high == LIMC0+1 && quadGRHchk(D, &GRHcheck, LIMC0)) LIMC2 = LIMC0; else LIMC2 = high; if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX; LIMC0 = (long)(cbach*LOGD2); LIMC = cbach ? LIMC0 : LIMC2; LIMC = maxss(LIMC, nthidealquad(D, 2)); /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */ START: do { if (!FIRST) LIMC = check_LIMC(LIMC,LIMCMAX); if (DEBUGLEVEL && LIMC > LIMC0) err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2); FIRST = 0; avma = av; if (BQ.subFB) gunclone(BQ.subFB); if (BQ.powsubFB) gunclone(BQ.powsubFB); clearhash(BQ.hashtab); if (LIMC < cp) LIMC = cp; if (LIMC2 < LIMC) LIMC2 = LIMC; if (BQ.PRECREG) qfr_data_init(QFR.D, BQ.PRECREG, &QFR); FBquad(&BQ, LIMC2, LIMC, &GRHcheck); if (DEBUGLEVEL) timer_printf(&T, "factor base"); BQ.subFB = subFBquad(&BQ, QFR.D, lim + 0.5, minSFB); if (DEBUGLEVEL) 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)); BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1); if (DEBUGLEVEL) timer_printf(&T, "powsubFBquad"); BQ.limhash = (LIMC & HIGHMASK)? (HIGHBIT>>1): LIMC*LIMC; need = BQ.KC + RELSUP - 2; current = 0; W = NULL; sfb_trials = nreldep = nrelsup = 0; s = nsubFB + RELSUP; av2 = avma; do { if ((nreldep & 3) == 1 || (nrelsup & 7) == 1) { if (DEBUGLEVEL) 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"); clearhash(BQ.hashtab); } need += 2; mat = cgetg(need+1, t_MAT); extraC = cgetg(need+1, t_VEC); 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); } else { triv = 0; if (DEBUGLEVEL) err_printf("...need %ld more relations\n", need); } if (BQ.PRECREG) { for (i = triv+1; i<=need; i++) { gel(mat,i) = zero_zv(BQ.KC); gel(extraC,i) = cgetr(BQ.PRECREG); } real_relations(&BQ, need - triv, ¤t, s,LIMC,mat + triv,extraC + triv); } else { for (i = triv+1; i<=need; i++) { gel(mat,i) = zero_zv(BQ.KC); gel(extraC,i) = gen_0; } imag_relations(&BQ, need - triv, ¤t, LIMC,mat + triv); } if (!W) W = hnfspec_i(mat,BQ.vperm,&dep,&B,&C,nsubFB); else W = hnfadd_i(W,BQ.vperm,&dep,&B,&C, mat,extraC); gerepileall(av2, 4, &W,&C,&B,&dep); need = BQ.KC - (lg(W)-1) - (lg(B)-1); if (need) { if (++nreldep > 15 && cbach < 1) goto START; continue; } h = ZM_det_triangular(W); if (DEBUGLEVEL) 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)) { case fupb_PRECI: BQ.PRECREG = precdbl(BQ.PRECREG); FIRST = 1; goto START; case fupb_RELAT: if (++nrelsup > MAXRELSUP) { if (++sfb_trials > SFB_MAX && cbach <= 1) goto START; if (nsubFB < minss(10,BQ.KC)) nsubFB++; } need = minss(BQ.KC, nrelsup); } } while (need); /* DONE */ if (!quad_be_honest(&BQ)) goto START; if (DEBUGLEVEL) timer_printf(&T, "be honest"); clearhash(BQ.hashtab); free_GRHcheck(&GRHcheck); gen = get_clgp(&BQ,W,&cyc,BQ.PRECREG); gunclone(BQ.subFB); gunclone(BQ.powsubFB); res = cgetg(5,t_VEC); gel(res,1) = h; gel(res,2) = cyc; gel(res,3) = gen; gel(res,4) = R; return gerepilecopy(av0,res); } GEN buchimag(GEN D, GEN c, GEN c2, GEN REL) { (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),0); } GEN buchreal(GEN D, GEN flag, GEN c, GEN c2, GEN REL, long prec) { if (signe(flag)) pari_err_IMPL("narrow class group"); (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),prec); } GEN quadclassunit0(GEN x, long flag, GEN data, long prec) { long lx; double c1 = 0.0, c2 = 0.0; if (!data) lx=1; else { lx = lg(data); if (typ(data)!=t_VEC) pari_err_TYPE("quadclassunit", data); if (lx > 7) pari_err_DIM("quadclassunit [tech vector]"); if (lx > 3) lx = 3; } switch(lx) { case 3: c2 = gtodouble(gel(data,2)); case 2: c1 = gtodouble(gel(data,1)); } if (flag) pari_err_IMPL("narrow class group"); return Buchquad(x,c1,c2,prec); } pari-2.7.5/src/basemath/polarit2.c0000644000175000017500000024075612414214040015367 0ustar billbill/* 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. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (second part) **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #define addshift(x,y) addshiftpol((x),(y),1) /* compute Newton sums S_1(P), ... , S_n(P). S_k(P) = sum a_j^k, a_j root of P * If N != NULL, assume p-adic roots and compute mod N [assume integer coeffs] * If T != NULL, compute mod (T,N) [assume integer coeffs if N != NULL] * If y0!= NULL, precomputed i-th powers, i=1..m, m = length(y0). * Not memory clean in the latter case */ GEN polsym_gen(GEN P, GEN y0, long n, GEN T, GEN N) { long dP=degpol(P), i, k, m; pari_sp av1, av2; GEN s,y,P_lead; if (n<0) pari_err_IMPL("polsym of a negative n"); if (typ(P) != t_POL) pari_err_TYPE("polsym",P); if (!signe(P)) pari_err_ROOTS0("polsym"); y = cgetg(n+2,t_COL); if (y0) { if (typ(y0) != t_COL) pari_err_TYPE("polsym_gen",y0); m = lg(y0)-1; for (i=1; i<=m; i++) gel(y,i) = gel(y0,i); /* not memory clean */ } else { m = 1; gel(y,1) = stoi(dP); } P += 2; /* strip codewords */ P_lead = gel(P,dP); if (gequal1(P_lead)) P_lead = NULL; if (P_lead) { if (N) P_lead = Fq_inv(P_lead,T,N); else if (T) P_lead = QXQ_inv(P_lead,T); } for (k=m; k<=n; k++) { av1 = avma; s = (dP>=k)? gmulsg(k,gel(P,dP-k)): gen_0; for (i=1; i 0) y = subii(y, p); break; case -1: if (!po2 || absi_cmp(y,po2) > 0) y = addii(y, p); break; } return y; } static long s_centermod(long x, ulong pp, ulong pps2) { long y = x % (long)pp; if (y < 0) y += pp; return Fl_center(y, pp,pps2); } /* for internal use */ GEN centermod_i(GEN x, GEN p, GEN ps2) { long i, lx; pari_sp av; GEN y; if (!ps2) ps2 = shifti(p,-1); switch(typ(x)) { case t_INT: return centermodii(x,p,ps2); case t_POL: lx = lg(x); y = cgetg(lx,t_POL); y[1] = x[1]; for (i=2; i> tsh; *t2 = (x & ((1L<= tsh; } long RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa) { long t[16]; long tx = typ(x), lx, i, j, s, pa = LONG_MAX; GEN pcx=NULL, p=NULL, pol=NULL, ff=NULL; 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 */ lx = lg(x); for (i=2; i (impose imag(x) >= 0) */ static GEN gauss_normal(GEN x) { if (typ(x) != t_COMPLEX) return (signe(x) < 0)? absi(x): x; if (signe(gel(x,1)) < 0) x = gneg(x); if (signe(gel(x,2)) < 0) x = mulcxI(x); return x; } static GEN gauss_factor(GEN x) { pari_sp av = avma; GEN a = gel(x,1), b = gel(x,2), d = gen_1, n, y, fa, P, E, P2, E2; long t1 = typ(a); long t2 = typ(b), i, j, l, exp = 0; if (t1 == t_FRAC) d = gel(a,2); if (t2 == t_FRAC) d = lcmii(d, gel(b,2)); if (d == gen_1) y = x; else { y = gmul(x, d); a = gel(y,1); t1 = typ(a); b = gel(y,2); t2 = typ(b); } if (t1 != t_INT || t2 != t_INT) return NULL; y = gauss_primpart(y, &n); fa = factor(cxnorm(y)); P = gel(fa,1); E = gel(fa,2); l = lg(P); P2 = cgetg(l, t_COL); E2 = cgetg(l, t_COL); for (j = 1, i = l-1; i > 0; i--) /* remove largest factors first */ { /* either p = 2 (ramified) or those factors split in Q(i) */ GEN p = gel(P,i), w, w2, t, we, pe; long v, e = itos(gel(E,i)); int is2 = equaliu(p, 2); w = is2? mkcomplex(gen_1,gen_1): gauss_factor_p(p); w2 = gauss_normal( gconj(w) ); /* w * w2 * I^3 = p, w2 = gconj(w) * I */ pe = powiu(p, e); we = gpowgs(w, e); t = gauss_primpart_try( gmul(y, gconj(we)), pe ); if (t) y = t; /* y /= w^e */ else { /* y /= conj(w)^e, should be y /= w2^e */ y = gauss_primpart_try( gmul(y, we), pe ); swap(w, w2); exp -= e; /* += 3*e mod 4 */ } gel(P,i) = w; v = Z_pvalrem(n, p, &n); if (v) { exp -= v; /* += 3*v mod 4 */ if (is2) v <<= 1; /* 2 = w^2 I^3 */ else { gel(P2,j) = w2; gel(E2,j) = utoipos(v); j++; } gel(E,i) = stoi(e + v); } v = Z_pvalrem(d, p, &d); if (v) { exp += v; /* -= 3*v mod 4 */ if (is2) v <<= 1; /* 2 is ramified */ else { gel(P2,j) = w2; gel(E2,j) = utoineg(v); j++; } gel(E,i) = stoi(e - v); } exp &= 3; } if (j > 1) { long k = 1;; GEN P1 = cgetg(l, t_COL); GEN E1 = cgetg(l, t_COL); /* remove factors with exponent 0 */ for (i = 1; i < l; i++) if (signe(gel(E,i))) { gel(P1,k) = gel(P,i); gel(E1,k) = gel(E,i); k++; } setlg(P1, k); setlg(E1, k); setlg(P2, j); setlg(E2, j); fa = famat_mul_shallow(mkmat2(P1,E1), mkmat2(P2,E2)); } if (!is_pm1(n) || !is_pm1(d)) { GEN Fa = factor(gdiv(n, d)); P = gel(Fa,1); l = lg(P); E = gel(Fa,2); for (i = 1; i < l; i++) { GEN w, p = gel(P,i); long e; int is2; switch(mod4(p)) { case 3: continue; case 2: is2 = 1; break; default:is2 = 0; break; } e = itos(gel(E,i)); w = is2? mkcomplex(gen_1,gen_1): gauss_factor_p(p); gel(P,i) = w; if (is2) gel(E,i) = stoi(e << 1); else { P = shallowconcat(P, gauss_normal( gconj(w) )); E = shallowconcat(E, gel(E,i)); } exp -= e; /* += 3*e mod 4 */ exp &= 3; } gel(Fa,1) = P; gel(Fa,2) = E; fa = famat_mul_shallow(fa, Fa); } fa = sort_factor(fa, (void*)&gauss_cmp, &cmp_nodata); y = gmul(y, powIs(exp)); if (!gequal1(y)) { gel(fa,1) = shallowconcat(mkcol(y), gel(fa,1)); gel(fa,2) = shallowconcat(gen_1, gel(fa,2)); } return gerepilecopy(av, fa); } GEN factor(GEN x) { long tx=typ(x), lx, i, pa, v, r1; pari_sp av, tetpil; GEN y, p, p1, p2, pol; if (gequal0(x)) switch(tx) { case t_INT: case t_COMPLEX: case t_POL: case t_RFRAC: return prime_fact(x); default: pari_err_TYPE("factor",x); } av = avma; switch(tx) { case t_INT: return Z_factor(x); case t_FRAC: p1 = Z_factor(gel(x,1)); p2 = Z_factor(gel(x,2)); gel(p2,2) = gneg_i(gel(p2,2)); return gerepilecopy(av, merge_factor_i(p1,p2)); case t_POL: tx=RgX_type(x,&p,&pol,&pa); switch(tx) { case 0: pari_err_IMPL("factor for general polynomials"); case t_INT: return QX_factor(x); case t_INTMOD: return factmod(x,p); case t_COMPLEX: y=cgetg(3,t_MAT); lx=lg(x)-2; av = avma; p1 = roots(x,pa); tetpil = avma; p1 = deg1_from_roots(p1, varn(x)); gel(y,1) = gerepile(av,tetpil,p1); gel(y,2) = const_col(lx-1, gen_1); return y; case t_REAL: y=cgetg(3,t_MAT); lx=lg(x)-2; v=varn(x); av=avma; p1=cleanroots(x,pa); tetpil=avma; for(r1=1; r1>1; p2=cgetg(lx,t_COL); for(i=1; i MONIC POLYNOMIAL */ /* */ /*******************************************************************/ static GEN normalized_mul(GEN x, GEN y) { long a = gel(x,1)[1], b = gel(y,1)[1]; return mkvec2(mkvecsmall(a + b), RgX_mul_normalized(gel(x,2),a, gel(y,2),b)); } /* L = [Vecsmall([a]), A], with a > 0, A an RgX, deg(A) < a; return X^a + A */ static GEN normalized_to_RgX(GEN L) { long i, a = gel(L,1)[1]; GEN A = gel(L,2); GEN z = cgetg(a + 3, t_POL); z[1] = evalsigne(1) | evalvarn(varn(A)); for (i = 2; i < lg(A); i++) gel(z,i) = gcopy(gel(A,i)); for ( ; i < a+2; i++) gel(z,i) = gen_0; gel(z,i) = gen_1; return z; } /* compute prod (x - a[i]) */ GEN roots_to_pol(GEN a, long v) { pari_sp av = avma; long i, k, lx = lg(a); GEN L; if (lx == 1) return pol_1(v); L = cgetg(lx, t_VEC); for (k=1,i=1; i 2) { if (DEBUGLEVEL>7) err_printf("prod: remaining objects %ld\n",k-1); lx = k; k = 1; for (i=1; i 5) return 0; return gsigne(RgX_disc(x)) > 0; } y = factor(x); return (lg(gcoeff(y,1,1))==l); } static int RgX_is_irred(GEN x) { pari_sp av = avma; int r = RgX_is_irred_i(x); avma = av; return r; } long isirreducible(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 0; case t_POL: return RgX_is_irred(x); } pari_err_TYPE("isirreducible",x); return 0; } /*******************************************************************/ /* */ /* GENERIC GCD */ /* */ /*******************************************************************/ /* x is a COMPLEX or a QUAD */ static GEN triv_cont_gcd(GEN x, GEN y) { pari_sp av = avma; GEN c; if (typ(x)==t_COMPLEX) { GEN a = gel(x,1), b = gel(x,2); if (typ(a) == t_REAL || typ(b) == t_REAL) return gen_1; c = ggcd(a,b); } else c = ggcd(gel(x,2),gel(x,3)); return gerepileupto(av, ggcd(c,y)); } /* y is a PADIC, x a rational number or an INTMOD */ static GEN padic_gcd(GEN x, GEN y) { GEN p = gel(y,2); long v = gvaluation(x,p), w = valp(y); if (w < v) v = w; return powis(p, v); } /* x,y in Z[i], at least one of which is t_COMPLEX */ static GEN gauss_gcd(GEN x, GEN y) { pari_sp av = avma; GEN dx, dy; dx = denom(x); x = gmul(x, dx); dy = denom(y); y = gmul(y, dy); while (!gequal0(y)) { GEN z = gsub(x, gmul(ground(gdiv(x,y)), y)); x = y; y = z; } x = gauss_normal(x); if (typ(x) == t_COMPLEX) { if (gequal0(gel(x,2))) x = gel(x,1); else if (gequal0(gel(x,1))) x = gel(x,2); } return gerepileupto(av, gdiv(x, lcmii(dx, dy))); } static int is_rational(GEN x) { long t = typ(x); return is_rational_t(t); } static int c_is_rational(GEN x) { return (is_rational(gel(x,1)) && is_rational(gel(x,2))); } static GEN c_zero_gcd(GEN c) { GEN x = gel(c,1), y = gel(c,2); long tx = typ(x), ty = typ(y); if (tx == t_REAL || ty == t_REAL) return gen_1; if (tx == t_PADIC || tx == t_INTMOD || ty == t_PADIC || ty == t_INTMOD) return ggcd(x, y); return gauss_gcd(c, gen_0); } /* y == 0 */ static GEN zero_gcd(GEN x, long tx) { pari_sp av; switch(tx) { case t_INT: return absi(x); case t_FRAC: return absfrac(x); case t_COMPLEX: return c_zero_gcd(x); case t_REAL: return gen_1; case t_PADIC: return powis(gel(x,2), valp(x)); case t_SER: return monomial(gen_1, valp(x), varn(x)); case t_POLMOD: { GEN d = gel(x,2); if (typ(d) == t_POL && varn(d) == varn(gel(x,1))) return content(d); return isinexact(d)? zero_gcd(d, typ(d)): gcopy(d); } case t_POL: if (!isinexact(x)) break; av = avma; return gerepileupto(av, monomialcopy(content(x), RgX_val(x), varn(x)) ); case t_RFRAC: if (!isinexact(x)) break; av = avma; return gerepileupto(av, gdiv(zero_gcd(gel(x,1), typ(gel(x,1))), gel(x,2)) ); } return gcopy(x); } /* tx = t_RFRAC, y considered as constant */ static GEN cont_gcd_rfrac(GEN x, GEN y) { pari_sp av = avma; GEN cx; x = primitive_part(x, &cx); return gerepileupto(av, gred_rfrac_simple(ggcd(cx? cx: gen_1, y), gel(x,2))); } /* tx = t_POL, y considered as constant */ static GEN cont_gcd_pol(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, scalarpol(ggcd(content(x),y), varn(x))); } /* !is_const_t(tx), tx != t_POL,t_RFRAC, y considered as constant */ static GEN cont_gcd_gen(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, ggcd(content(x),y)); } /* !is_const(tx), y considered as constant */ static GEN cont_gcd(GEN x, long tx, GEN y) { switch(tx) { case t_RFRAC: return cont_gcd_rfrac(x,y); case t_POL: return cont_gcd_pol(x,y); default: return cont_gcd_gen(x,y); } } static GEN gcdiq(GEN x, GEN y) { GEN z; if (!signe(x)) return Q_abs(y); z = cgetg(3,t_FRAC); gel(z,1) = gcdii(x,gel(y,1)); gel(z,2) = icopy(gel(y,2)); return z; } static GEN gcdqq(GEN x, GEN y) { GEN z = cgetg(3,t_FRAC); gel(z,1) = gcdii(gel(x,1), gel(y,1)); gel(z,2) = lcmii(gel(x,2), gel(y,2)); return z; } /* assume x,y t_INT or t_FRAC */ GEN Q_gcd(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == t_INT) { return (ty == t_INT)? gcdii(x,y): gcdiq(x,y); } else { return (ty == t_INT)? gcdiq(y,x): gcdqq(x,y); } } GEN ggcd(GEN x, GEN y) { long l, i, vx, vy, tx = typ(x), ty = typ(y); pari_sp av, tetpil; GEN p1,z; if (is_noncalc_t(tx) || is_noncalc_t(ty)) pari_err_TYPE2("gcd",x,y); if (is_matvec_t(ty)) { z = cgetg_copy(y, &l); for (i=1; ity) { swap(x,y); lswap(tx,ty); } /* tx <= ty */ if (isrationalzero(x)) return zero_gcd(y, ty); if (isrationalzero(y)) return zero_gcd(x, tx); if (is_const_t(tx)) { if (ty == tx) switch(tx) { case t_INT: return gcdii(x,y); case t_INTMOD: z=cgetg(3,t_INTMOD); if (equalii(gel(x,1),gel(y,1))) gel(z,1) = icopy(gel(x,1)); else gel(z,1) = gcdii(gel(x,1),gel(y,1)); if (gequal1(gel(z,1))) gel(z,2) = gen_0; else { av = avma; p1 = gcdii(gel(z,1),gel(x,2)); if (!is_pm1(p1)) { p1 = gcdii(p1,gel(y,2)); if (equalii(p1, gel(z,1))) { cgiv(p1); p1 = gen_0; } else p1 = gerepileuptoint(av, p1); } gel(z,2) = p1; } return z; case t_FRAC: return gcdqq(x,y); case t_FFELT: if (!FF_samefield(x,y)) pari_err_OP("gcd",x,y); return FF_equal0(x) && FF_equal0(y)? FF_zero(y): FF_1(y); case t_COMPLEX: if (c_is_rational(x) && c_is_rational(y)) return gauss_gcd(x,y); return triv_cont_gcd(y,x); case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) return gen_1; return powis(gel(y,2), minss(valp(x), valp(y))); case t_QUAD: av=avma; p1=gdiv(x,y); if (gequal0(gel(p1,3))) { p1=gel(p1,2); if (typ(p1)==t_INT) { avma=av; return gcopy(y); } tetpil=avma; return gerepile(av,tetpil, gdiv(y,gel(p1,2))); } if (typ(gel(p1,2))==t_INT && typ(gel(p1,3))==t_INT) {avma=av; return gcopy(y);} p1 = ginv(p1); avma=av; if (typ(gel(p1,2))==t_INT && typ(gel(p1,3))==t_INT) return gcopy(x); return triv_cont_gcd(y,x); default: return gen_1; /* t_REAL */ } if (is_const_t(ty)) switch(tx) { case t_INT: switch(ty) { case t_INTMOD: z = cgetg(3,t_INTMOD); gel(z,1) = icopy(gel(y,1)); av = avma; p1 = gcdii(gel(y,1),gel(y,2)); if (!is_pm1(p1)) { p1 = gcdii(x,p1); if (equalii(p1, gel(z,1))) { cgiv(p1); p1 = gen_0; } else p1 = gerepileuptoint(av, p1); } gel(z,2) = p1; return z; case t_REAL: return gen_1; case t_FRAC: return gcdiq(x,y); case t_COMPLEX: if (c_is_rational(y)) return gauss_gcd(x,y); return triv_cont_gcd(y,x); case t_FFELT: if (!FF_equal0(y)) return FF_1(y); return dvdii(x, gel(y,4))? FF_zero(y): FF_1(y); case t_PADIC: return padic_gcd(x,y); case t_QUAD: return triv_cont_gcd(y,x); default: pari_err_TYPE2("gcd",x,y); } case t_REAL: switch(ty) { case t_INTMOD: case t_FFELT: case t_PADIC: pari_err_TYPE2("gcd",x,y); default: return gen_1; } case t_INTMOD: switch(ty) { case t_FRAC: av = avma; p1=gcdii(gel(x,1),gel(y,2)); avma = av; if (!is_pm1(p1)) pari_err_OP("gcd",x,y); return ggcd(gel(y,1), x); case t_FFELT: { GEN p = gel(y,4); if (!dvdii(gel(x,1), p)) pari_err_OP("gcd",x,y); if (!FF_equal0(y)) return FF_1(y); return dvdii(gel(x,2),p)? FF_zero(y): FF_1(y); } case t_COMPLEX: case t_QUAD: return triv_cont_gcd(y,x); case t_PADIC: return padic_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_FRAC: switch(ty) { case t_COMPLEX: if (c_is_rational(y)) return gauss_gcd(x,y); case t_QUAD: return triv_cont_gcd(y,x); case t_FFELT: { GEN p = gel(y,4); if (dvdii(gel(x,2), p)) pari_err_OP("gcd",x,y); if (!FF_equal0(y)) return FF_1(y); return dvdii(gel(x,1),p)? FF_zero(y): FF_1(y); } case t_PADIC: return padic_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_FFELT: switch(ty) { case t_PADIC: { GEN p = gel(y,2); long v = valp(y); if (!equalii(p, gel(x,4)) || v < 0) pari_err_OP("gcd",x,y); return (v && FF_equal0(x))? FF_zero(x): FF_1(x); } default: pari_err_TYPE2("gcd",x,y); } case t_COMPLEX: switch(ty) { case t_PADIC: case t_QUAD: return triv_cont_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_PADIC: switch(ty) { case t_QUAD: return triv_cont_gcd(y,x); default: pari_err_TYPE2("gcd",x,y); } default: return gen_1; /* tx = t_REAL */ } return cont_gcd(y,ty, x); } if (tx == t_POLMOD) { if (ty == t_POLMOD) { GEN T = gel(x,1); z = cgetg(3,t_POLMOD); T = RgX_equal_var(T,gel(y,1))? RgX_copy(T): RgX_gcd(T, gel(y,1)); gel(z,1) = T; if (degpol(T) <= 0) gel(z,2) = gen_0; else { GEN X, Y, d; av = avma; X = gel(x,2); Y = gel(y,2); d = ggcd(content(X), content(Y)); if (!gequal1(d)) { X = gdiv(X,d); Y = gdiv(Y,d); } p1 = ggcd(T, X); gel(z,2) = gerepileupto(av, gmul(d, ggcd(p1, Y))); } return z; } vx = varn(gel(x,1)); switch(ty) { case t_POL: vy = varn(y); if (varncmp(vy,vx) < 0) return cont_gcd_pol(y, x); z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(gel(x,1)); av = avma; p1 = ggcd(gel(x,1),gel(x,2)); gel(z,2) = gerepileupto(av, ggcd(p1,y)); return z; case t_RFRAC: vy = varn(gel(y,2)); if (varncmp(vy,vx) < 0) return cont_gcd_rfrac(y, x); av = avma; p1 = ggcd(gel(x,1),gel(y,2)); if (degpol(p1)) pari_err_OP("gcd",x,y); avma = av; return gdiv(ggcd(gel(y,1),x), content(gel(y,2))); } } vx = gvar(x); vy = gvar(y); if (varncmp(vy, vx) < 0) return cont_gcd(y,ty, x); if (varncmp(vy, vx) > 0) return cont_gcd(x,tx, y); /* vx = vy: same main variable */ switch(tx) { case t_POL: switch(ty) { case t_POL: return RgX_gcd(x,y); case t_SER: z = ggcd(content(x), content(y)); return monomialcopy(z, minss(valp(y),gval(x,vx)), vx); case t_RFRAC: return cont_gcd_rfrac(y, x); } break; case t_SER: z = ggcd(content(x), content(y)); switch(ty) { case t_SER: return monomialcopy(z, minss(valp(x),valp(y)), vx); case t_RFRAC: return monomialcopy(z, minss(valp(x),gval(y,vx)), vx); } break; case t_RFRAC: { GEN xd = gel(x,2), yd = gel(y,2); if (ty != t_RFRAC) pari_err_TYPE2("gcd",x,y); z = cgetg(3,t_RFRAC); av = avma; gel(z,2) = gerepileupto(av, RgX_mul(xd, RgX_div(yd, RgX_gcd(xd, yd)))); gel(z,1) = ggcd(gel(x,1), gel(y,1)); return z; } } pari_err_TYPE2("gcd",x,y); return NULL; /* not reached */ } GEN ggcd0(GEN x, GEN y) { return y? ggcd(x,y): content(x); } /* x a t_VEC,t_COL or t_MAT */ static GEN vec_lcm(GEN x) { if (typ(x) == t_MAT) { long i, l = lg(x); GEN z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = glcm0(gel(x,i), NULL); x = z; } return glcm0(x, NULL); } static GEN scal_lcm(GEN x, GEN y) { pari_sp av = avma; long tx = typ(x), ty = typ(y); if (is_matvec_t(tx)) x = vec_lcm(x); if (is_matvec_t(ty)) y = vec_lcm(y); return gerepileupto(av, glcm(x, y)); } static GEN fix_lcm(GEN x) { GEN t; switch(typ(x)) { case t_INT: if (signe(x)<0) x = negi(x); break; case t_POL: if (lg(x) <= 2) break; t = leading_term(x); if (typ(t) == t_INT && signe(t) < 0) x = gneg(x); } return x; } GEN glcm0(GEN x, GEN y) { if (!y && lg(x) == 2) { long tx = typ(x); if (is_vec_t(tx)) { x = gel(x,1); tx = typ(x); return is_matvec_t(tx)? vec_lcm(x): fix_lcm(x); } } return gassoc_proto(scal_lcm,x,y); } GEN glcm(GEN x, GEN y) { long tx, ty, i, l; pari_sp av; GEN p1, z; ty = typ(y); if (is_matvec_t(ty)) { z = cgetg_copy(y, &l); for (i=1; i1) pari_warn(warnmem,"RgX_gcd_simple"); gerepileall(av,2, &x,&y); } } } GEN RgX_extgcd_simple(GEN a, GEN b, GEN *pu, GEN *pv) { pari_sp av = avma; GEN q, r, d, d1, u, v, v1; int exact = !(isinexactreal(a) || isinexactreal(b)); d = a; d1 = b; v = gen_0; v1 = gen_1; for(;;) { if (pol_approx0(d1, a, exact)) break; q = poldivrem(d,d1, &r); v = gsub(v, gmul(q,v1)); u=v; v=v1; v1=u; u=r; d=d1; d1=u; } u = gsub(d, gmul(b,v)); u = RgX_div(u,a); gerepileall(av, 3, &u,&v,&d); *pu = u; *pv = v; return d; } /*******************************************************************/ /* */ /* CONTENT / PRIMITIVE PART */ /* */ /*******************************************************************/ GEN content(GEN x) { long lx, i, t, tx = typ(x); pari_sp av = avma; GEN c; if (is_scalar_t(tx)) return zero_gcd(x, tx); switch(tx) { case t_RFRAC: { GEN n = gel(x,1), d = gel(x,2); /* -- varncmp(vn, vd) < 0 can't happen * -- if n is POLMOD, its main variable (in the sense of gvar2) * has lower priority than denominator */ if (typ(n) == t_POLMOD || varncmp(gvar(n), varn(d)) > 0) n = isinexact(n)? zero_gcd(n, typ(n)): gcopy(n); else n = content(n); return gerepileupto(av, gdiv(n, content(d))); } case t_VEC: case t_COL: lx = lg(x); if (lx==1) return gen_1; break; case t_MAT: { long hx, j; lx = lg(x); if (lx == 1) return gen_1; hx = lgcols(x); if (hx == 1) return gen_1; 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)); for (j=2; j lx) { /* integer coeffs */ while (lx-- > lontyp[tx]) { c = gcdii(c, gel(x,lx)); if (is_pm1(c)) { avma=av; return gen_1; } } } else { if (isinexact(c)) c = zero_gcd(c, typ(c)); while (lx-- > lontyp[tx]) { GEN d = gel(x,lx); t = typ(d); if (is_matvec_t(t)) d = content(d); c = ggcd(c, d); } if (isinexact(c)) { avma=av; return gen_1; } } switch(typ(c)) { case t_INT: if (signe(c) < 0) c = negi(c); break; case t_VEC: case t_COL: case t_MAT: pari_err_TYPE("content",x); } return av==avma? gcopy(c): gerepileupto(av,c); } GEN primitive_part(GEN x, GEN *ptc) { pari_sp av = avma; GEN c = content(x); if (gequal1(c)) { avma = av; c = NULL; } else if (!gequal0(c)) x = gdiv(x,c); if (ptc) *ptc = c; return x; } GEN primpart(GEN x) { return primitive_part(x, NULL); } /* As content(), but over Q. Treats polynomial as elts of Q[x1,...xn], instead * of Q(x2,...,xn)[x1] */ GEN Q_content(GEN x) { long i, l; GEN d; pari_sp av; switch(typ(x)) { case t_INT: return absi(x); case t_FRAC: return absfrac(x); case t_VEC: case t_COL: case t_MAT: l = lg(x); if (l == 1) return gen_1; av = avma; d = Q_content(gel(x,1)); for (i=2; i 3); } /* compute U, V s.t Ux + Vy = resultant(x,y) */ static GEN subresext_i(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av, av2, lim; long dx, dy, du, signh, tx = typ(x), ty = typ(y); GEN r, z, g, h, p1, cu, cv, u, v, um1, uze, vze; if (!is_extscalar_t(tx)) pari_err_TYPE("subresext",x); if (!is_extscalar_t(ty)) pari_err_TYPE("subresext",y); if (gequal0(x) || gequal0(y)) { *U = *V = gen_0; return gen_0; } if (tx != t_POL) { if (ty != t_POL) { *U = ginv(x); *V = gen_0; return gen_1; } return scalar_res(y,x,V,U); } if (ty != t_POL) return scalar_res(x,y,U,V); if (varn(x) != varn(y)) return varncmp(varn(x), varn(y)) < 0? scalar_res(x,y,U,V) : scalar_res(y,x,V,U); dx = degpol(x); dy = degpol(y); signh = 1; if (dx < dy) { pswap(U,V); lswap(dx,dy); swap(x,y); if (both_odd(dx, dy)) signh = -signh; } if (dy == 0) { *V = gpowgs(gel(y,2),dx-1); *U = gen_0; return gmul(*V,gel(y,2)); } 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); 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(DEBUGMEM>1) pari_warn(warnmem,"subresext, dr = %ld", degpol(v)); gerepileall(av2,6, &u,&v,&g,&h,&uze,&um1); } } /* uze an RgX */ if (!u) { *U = *V = gen_0; avma = av; return gen_0; } z = gel(v,2); du = degpol(u); if (du > 1) { /* z = gdivexact(gpowgs(z,du), gpowgs(h,du-1)); */ p1 = gpowgs(gdiv(z,h),du-1); z = gmul(z,p1); uze = RgX_Rg_mul(uze, p1); } if (signh < 0) { z = gneg_i(z); uze = RgX_neg(uze); } vze = RgX_divrem(Rg_RgX_sub(z, RgX_mul(uze,x)), y, &r); if (signe(r)) pari_warn(warner,"inexact computation in subresext"); /* uze ppart(x) + vze ppart(y) = z = resultant(ppart(x), ppart(y)), */ p1 = gen_1; if (cu) p1 = gmul(p1, gpowgs(cu,dy)); if (cv) p1 = gmul(p1, gpowgs(cv,dx)); cu = cu? gdiv(p1,cu): p1; cv = cv? gdiv(p1,cv): p1; z = gmul(z,p1); *U = RgX_Rg_mul(uze,cu); *V = RgX_Rg_mul(vze,cv); return z; } GEN subresext(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av = avma; GEN z = subresext_i(x, y, U, V); gerepileall(av, 3, &z, U, V); return z; } static GEN zero_extgcd(GEN y, GEN *U, GEN *V, long vx) { GEN x=content(y); *U=pol_0(vx); *V = scalarpol(ginv(x), vx); return gmul(y,*V); } static int must_negate(GEN x) { GEN t = leading_term(x); switch(typ(t)) { case t_INT: case t_REAL: return (signe(t) < 0); case t_FRAC: return (signe(gel(t,1)) < 0); } return 0; } /* compute U, V s.t Ux + Vy = GCD(x,y) using subresultant */ GEN RgX_extgcd(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av, av2, tetpil, lim; 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]; if (tx!=t_POL) pari_err_TYPE("RgX_extgcd",x); if (ty!=t_POL) pari_err_TYPE("RgX_extgcd",y); if ( varncmp(varn(x),varn(y))) pari_err_VAR("RgX_extgcd",x,y); vx=varn(x); if (!signe(x)) { if (signe(y)) return zero_extgcd(y,U,V,vx); *U = pol_0(vx); *V = pol_0(vx); return pol_0(vx); } if (!signe(y)) return zero_extgcd(x,V,U,vx); dx = degpol(x); dy = degpol(y); if (dx < dy) { pswap(U,V); lswap(dx,dy); swap(x,y); } if (dy==0) { *U=pol_0(vx); *V=ginv(y); return pol_1(vx); } 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); 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(DEBUGMEM>1) pari_warn(warnmem,"RgX_extgcd, dr = %ld",degpol(v)); gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1); } } if (uze != gen_0) { GEN r; vze = RgX_divrem(RgX_sub(v, RgX_mul(uze,x)), y, &r); if (signe(r)) pari_warn(warner,"inexact computation in RgX_extgcd"); if (cu) uze = RgX_Rg_div(uze,cu); if (cv) vze = RgX_Rg_div(vze,cv); p1 = ginv(content(v)); } else /* y | x */ { vze = cv ? RgX_Rg_div(pol_1(vx),cv): pol_1(vx); uze = pol_0(vx); p1 = gen_1; } if (must_negate(v)) p1 = gneg(p1); tetpil = avma; z = RgX_Rg_mul(v,p1); *U = RgX_Rg_mul(uze,p1); *V = RgX_Rg_mul(vze,p1); gptr[0] = &z; gptr[1] = U; gptr[2] = V; gerepilemanysp(av,tetpil,gptr,3); return z; } int RgXQ_ratlift(GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q) { pari_sp av = avma, av2, tetpil, lim; long signh; /* junk */ long vx; GEN g, h, p1, cu, cv, u, v, um1, uze, *gptr[2]; if (typ(x)!=t_POL) pari_err_TYPE("RgXQ_ratlift",x); if (typ(T)!=t_POL) pari_err_TYPE("RgXQ_ratlift",T); if ( varncmp(varn(x),varn(T)) ) pari_err_VAR("RgXQ_ratlift",x,T); if (bmax < 0) pari_err_DOMAIN("ratlift", "bmax", "<", gen_0, stoi(bmax)); if (!signe(T)) { if (degpol(x) <= amax) { *P = RgX_copy(x); *Q = pol_1(varn(x)); return 1; } return 0; } if (amax+bmax >= degpol(T)) pari_err_DOMAIN("ratlift", "amax+bmax", ">=", stoi(degpol(T)), mkvec3(stoi(amax), stoi(bmax), T)); 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); 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(DEBUGMEM>1) pari_warn(warnmem,"RgXQ_ratlift, dr = %ld", degpol(v)); gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1); } } if (uze == gen_0) { avma = av; *P = pol_0(vx); *Q = pol_1(vx); return 1; } if (cu) uze = RgX_Rg_div(uze,cu); p1 = ginv(content(v)); if (must_negate(v)) p1 = gneg(p1); tetpil = avma; *P = RgX_Rg_mul(v,p1); *Q = RgX_Rg_mul(uze,p1); gptr[0] = P; gptr[1] = Q; gerepilemanysp(av,tetpil,gptr,2); return 1; } /*******************************************************************/ /* */ /* RESULTANT USING DUCOS VARIANT */ /* */ /*******************************************************************/ /* x^n / y^(n-1), assume n > 0 */ static GEN Lazard(GEN x, GEN y, long n) { long a; GEN c; if (n == 1) return x; a = 1 << expu(n); /* a = 2^k <= n < 2^(k+1) */ c=x; n-=a; while (a>1) { a>>=1; c=gdivexact(gsqr(c),y); if (n>=a) { c=gdivexact(gmul(c,x),y); n -= a; } } return c; } /* F (x/y)^(n-1), assume n >= 1 */ static GEN Lazard2(GEN F, GEN x, GEN y, long n) { if (n == 1) return F; return RgX_Rg_divexact(RgX_Rg_mul(F, Lazard(x,y,n-1)), y); } static GEN RgX_neg_i(GEN x, long lx) { long i; GEN y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i 1 && gequal0(gel(x,i))) i--; return i+1; } /* delta = deg(P) - deg(Q) > 0, deg(Q) > 0, P,Q,Z t_POL in the same variable, * s "scalar". Return prem(P, -Q) / s^delta lc(P) */ static GEN 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; 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); /* H = RgX_neg(reductum(Z)) optimized, using Q ~ Z */ H = RgX_neg_i(Z, lQ); /* deg H < q */ A = (q+2 < lP)? RgX_Rg_mul_i(H, gel(P,q+2), lQ): NULL; for (j = q+1; j < p; j++) { if (degpol(H) == q-1) { /* h0 = coeff of degree q-1 = leading coeff */ h0 = gel(H,q+1); (void)normalizepol_lg(H, q+1); H = addshift(H, RgX_Rg_divexact(RgX_Rg_mul_i(Q, gneg(h0), lQ), q0)); } else H = RgX_shift_shallow(H, 1); if (j+2 < lP) { 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(DEBUGMEM>1) pari_warn(warnmem,"nextSousResultant j = %ld/%ld",j,p); gerepileall(av,A?2:1,&H,&A); } } if (q+2 < lP) lP = reductum_lg(P, q+3); TMP = RgX_Rg_mul_i(P, z0, lP); A = A? RgX_add(A, TMP): TMP; A = RgX_Rg_divexact(A, p0); if (degpol(H) == q-1) { h0 = gel(H,q+1); (void)normalizepol_lg(H, q+1); /* destroy old H */ A = RgX_add(RgX_Rg_mul(addshift(H,A),q0), RgX_Rg_mul_i(Q, gneg(h0), lQ)); } else A = RgX_Rg_mul(addshift(H,A), q0); return RgX_Rg_divexact(A, s); } /* Ducos's subresultant */ GEN RgX_resultant_all(GEN P, GEN Q, GEN *sol) { pari_sp av, av2, lim; long dP, dQ, delta, sig = 1; GEN cP, cQ, Z, s; dP = degpol(P); dQ = degpol(Q); delta = dP - dQ; if (delta < 0) { if (both_odd(dP, dQ)) sig = -1; swap(P,Q); lswap(dP, dQ); delta = -delta; } if (sol) *sol = gen_0; av = avma; if (dQ <= 0) { if (dQ < 0) return RgX_get_0(P); s = gpowgs(gel(Q,2), dP); if (sig == -1) s = gerepileupto(av, gneg(s)); return s; } P = primitive_part(P, &cP); Q = primitive_part(Q, &cQ); av2 = avma; lim = stack_lim(av2,1); s = gpowgs(leading_term(Q),delta); if (both_odd(dP, dQ)) sig = -sig; Z = Q; Q = RgX_pseudorem(P, Q); P = Z; while(degpol(Q) > 0) { delta = degpol(P) - degpol(Q); /* > 0 */ Z = Lazard2(Q, leading_term(Q), s, delta); 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(DEBUGMEM>1) pari_warn(warnmem,"resultant_all, degpol Q = %ld",degpol(Q)); gerepileall(av2,2,&P,&Q); } s = leading_term(P); } if (!signe(Q)) { avma = av; return RgX_get_0(Q); } 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 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. * Uses Sylvester's matrix if P or Q inexact, a modular algorithm if they * are in Q[X], and Ducos/Lazard optimization of the subresultant algorithm * in the "generic" case. */ GEN resultant_all(GEN P, GEN Q, GEN *sol) { long TP, TQ; GEN s; if (sol) *sol = gen_0; if ((s = init_resultant(P,Q))) return s; if ((TP = RgX_simpletype(P)) == t_REAL || (TQ = RgX_simpletype(Q)) == t_REAL) return resultant2(P,Q); /* inexact */ if (TP && TQ) /* rational */ { if (TP == t_INT && TQ == t_INT) return ZX_resultant(P,Q); return QX_resultant(P,Q); } return RgX_resultant_all(P, Q, sol); } /*******************************************************************/ /* */ /* RESULTANT USING SYLVESTER MATRIX */ /* */ /*******************************************************************/ static GEN _pol_0(void) { GEN x = cgetg(3,t_POL); x[1] = 0; gel(x,2) = gen_0; return x; } static GEN sylvester_col(GEN x, long j, long d, long D) { GEN c = cgetg(d+1,t_COL); long i; for (i=1; i< j; i++) gel(c,i) = gen_0; for ( ; i<=D; i++) gel(c,i) = gel(x,D-i+2); for ( ; i<=d; i++) gel(c,i) = gen_0; return c; } GEN sylvestermatrix_i(GEN x, GEN y) { long j,d,dx,dy; GEN M; dx = degpol(x); if (dx < 0) { dx = 0; x = _pol_0(); } dy = degpol(y); if (dy < 0) { dy = 0; y = _pol_0(); } d = dx+dy; M = cgetg(d+1,t_MAT); for (j=1; j<=dy; j++) gel(M,j) = sylvester_col(x,j,d,j+dx); for (j=1; j<=dx; j++) gel(M,j+dy) = sylvester_col(y,j,d,j+dy); return M; } GEN sylvestermatrix(GEN x, GEN y) { long i,j,lx; if (typ(x)!=t_POL) pari_err_TYPE("sylvestermatrix",x); if (typ(y)!=t_POL) pari_err_TYPE("sylvestermatrix",y); if (varn(x) != varn(y)) pari_err_VAR("sylvestermatrix",x,y); x = sylvestermatrix_i(x,y); lx = lg(x); for (i=1; i v, return scalarpol(x, 0) */ static GEN fix_pol(GEN x, long v, long *mx) { long vx; if (typ(x) != t_POL) return x; vx = varn(x); if (v == vx) { if (v) { x = leafcopy(x); setvarn(x, 0); } 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; } return scalarpol_shallow(x, 0); } /* resultant of x and y with respect to variable v, or with respect to their * main variable if v < 0. */ GEN polresultant0(GEN x, GEN y, long v, long flag) { long m = 0; pari_sp av = avma; if (v >= 0) { x = fix_pol(x,v, &m); y = fix_pol(y,v, &m); } switch(flag) { case 2: case 0: x=resultant_all(x,y,NULL); break; case 1: x=resultant2(x,y); break; default: pari_err_FLAG("polresultant"); } if (m) x = gsubst(x,MAXVARN,pol_x(0)); return gerepileupto(av,x); } GEN polresultantext0(GEN x, GEN y, long v) { GEN R, U, V; long m = 0; pari_sp av = avma; if (v >= 0) { x = fix_pol(x,v, &m); y = fix_pol(y,v, &m); } 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 (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)); } return gerepilecopy(av, mkvec3(U,V,R)); } GEN polresultantext(GEN x, GEN y) { return polresultantext0(x,y,-1); } /*******************************************************************/ /* */ /* CHARACTERISTIC POLYNOMIAL USING RESULTANT */ /* */ /*******************************************************************/ /* (v - x)^d */ static GEN caract_const(pari_sp av, GEN x, long v, long d) { return gerepileupto(av, gpowgs(deg1pol_shallow(gen_1, gneg_i(x), v), d)); } /* return caract(Mod(x,T)) in variable v */ GEN RgXQ_charpoly(GEN x, GEN T, long v) { pari_sp av = avma; long d = degpol(T), dx, vx, vp; GEN ch, L; if (typ(x) != t_POL) return caract_const(av, x, v, d); vx = varn(x); vp = varn(T); if (varncmp(vx, vp) > 0) return caract_const(av, x, v, d); if (varncmp(vx, vp) < 0) pari_err_PRIORITY("RgXQ_charpoly", x, "<", vp); dx = degpol(x); if (dx <= 0) return dx? monomial(gen_1, d, v): caract_const(av, gel(x,2), v, d); 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)); 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)); } /* test for silly input: x mod (deg 0 polynomial) */ if (typ(ch) != t_POL) { avma = av; return pol_1(v); } L = leading_term(ch); if (!gequal1(L)) ch = RgX_Rg_div(ch, L); return gerepileupto(av, ch); } /* characteristic polynomial (in v) of x over nf, where x is an element of the * algebra nf[t]/(Q(t)) */ GEN rnfcharpoly(GEN nf, GEN Q, GEN x, long v) { const char *f = "rnfcharpoly"; long dQ = degpol(Q); pari_sp av = avma; GEN T; if (v < 0) v = 0; nf = checknf(nf); T = nf_get_pol(nf); Q = RgX_nffix(f, T,Q,0); switch(typ(x)) { case t_INT: case t_FRAC: return caract_const(av, x, v, dQ); case t_POLMOD: x = polmod_nffix2(f,T,Q, x,0); break; case t_POL: x = varn(x) == varn(T)? Rg_nffix(f,T,x,0): RgX_nffix(f, T,x,0); break; default: pari_err_TYPE(f,x); } if (typ(x) != t_POL) return caract_const(av, x, v, dQ); /* x a t_POL in variable vQ */ if (degpol(x) >= dQ) x = RgX_rem(x, Q); if (dQ <= 1) return caract_const(av, constant_term(x), v, 1); return gerepilecopy(av, lift_if_rational( RgXQ_charpoly(x, Q, v) )); } /*******************************************************************/ /* */ /* GCD USING SUBRESULTANT */ /* */ /*******************************************************************/ static int inexact(GEN x, int *simple, int *rational); static int isinexactall(GEN x, int *simple, int *rational) { long i, lx = lg(x); for (i=2; i 0) x = RgX_gcd_simple(x,y); else { dx = lg(x); dy = lg(y); if (dx < dy) { swap(x,y); lswap(dx,dy); } if (dy==3) { d = ggcd(gel(y,2), content(x)); return gerepileupto(av, scalarpol(d, varn(x))); } 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); g = h = gen_1; for(;;) { GEN r = RgX_pseudorem(u,v); long degq, du, dv, dr = lg(r); if (!signe(r)) break; if (dr <= 3) { avma = av1; return gerepileupto(av, scalarpol(d, varn(x))); } if (DEBUGLEVEL > 9) err_printf("RgX_gcd: dr = %ld\n", degpol(r)); du = lg(u); dv = lg(v); degq = du-dv; u = v; p1 = g; g = leading_term(u); switch(degq) { case 0: break; case 1: p1 = gmul(h,p1); h = g; break; default: p1 = gmul(gpowgs(h,degq), p1); h = gdiv(gpowgs(g,degq), gpowgs(h,degq-1)); } v = RgX_Rg_div(r,p1); if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_gcd"); gerepileall(av1,4, &u,&v,&g,&h); } } x = RgX_Rg_mul(primpart(v), d); } if (must_negate(x)) x = RgX_neg(x); return gerepileupto(av,x); } static GEN RgX_disc_aux(GEN x) { long dx = degpol(x), Tx; GEN D, L, y, p; if (!signe(x) || !dx) return RgX_get_0(x); if (dx == 1) return RgX_get_1(x); if (dx == 2) { GEN a = gel(x,4), b = gel(x,3), c = gel(x,2); return gsub(gsqr(b), gmul2n(gmul(a,c),2)); } Tx = RgX_simpletype(x); if (Tx == t_INT) return ZX_disc(x); if (Tx == t_FRAC) return QX_disc(x); p = NULL; if (RgX_is_FpX(x, &p) && p) return Fp_to_mod(FpX_disc(RgX_to_FpX(x,p), p), p); y = RgX_deriv(x); if (!signe(y)) return RgX_get_0(y); if (Tx == t_REAL) D = resultant2(x,y); else { D = RgX_resultant_all(x, y, NULL); if (D == gen_0) return RgX_get_0(y); } L = leading_term(x); if (!gequal1(L)) D = gdiv(D,L); if (dx & 2) D = gneg(D); return D; } GEN 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); D = RgX_disc_aux(x); if (i) D = gsubst(D, MAXVARN, pol_x(0)); return gerepileupto(av, D); case t_COMPLEX: return utoineg(4); case t_QUAD: return quad_disc(x); case t_POLMOD: return poldisc0(gel(x,1), v); case t_QFR: case t_QFI: av = avma; return gerepileuptoint(av, qfb_disc(x)); case t_VEC: case t_COL: case t_MAT: 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 */ } GEN reduceddiscsmith(GEN x) { long j, n = degpol(x); pari_sp av = avma; GEN xp, M; if (typ(x) != t_POL) pari_err_TYPE("poldiscreduced",x); if (n<=0) pari_err_CONSTPOL("poldiscreduced"); RgX_check_ZX(x,"poldiscreduced"); if (!gequal1(gel(x,n+2))) pari_err_IMPL("non-monic polynomial in poldiscreduced"); M = cgetg(n+1,t_MAT); xp = ZX_deriv(x); for (j=1; j<=n; j++) { gel(M,j) = RgX_to_RgV(xp, n); if (j 0) { d = (vx == NO_VARIABLE)? ginv(x): gred_rfrac_simple(gen_1, x); return scalarpol(d, vy); } if (lg(x)!=3) pari_err_INV("RgXQ_inv",mkpolmod(x,y)); x = gel(x,2); vx = gvar(x); } av = avma; d = subresext_i(x,y,&u,&v/*junk*/); if (gequal0(d)) pari_err_INV("RgXQ_inv",mkpolmod(x,y)); d = gdiv(u,d); if (typ(d) != t_POL || varn(d) != vy) d = scalarpol(d, vy); return gerepileupto(av, d); } /*Assume x is a polynomial and y is not */ static GEN scalar_bezout(GEN x, GEN y, GEN *U, GEN *V) { long vx = varn(x); int xis0 = signe(x)==0, yis0 = gequal0(y); if (xis0 && yis0) { *U = *V = pol_0(vx); return pol_0(vx); } if (yis0) { *U=pol_1(vx); *V = pol_0(vx); return RgX_copy(x);} *U=pol_0(vx); *V= ginv(y); return pol_1(vx); } /* Assume x==0, y!=0 */ static GEN zero_bezout(GEN y, GEN *U, GEN *V) { *U=gen_0; *V = ginv(y); return gen_1; } GEN gbezout(GEN x, GEN y, GEN *u, GEN *v) { long tx=typ(x), ty=typ(y), vx; if (tx == t_INT && ty == t_INT) return bezout(x,y,u,v); if (tx != t_POL) { if (ty == t_POL) return scalar_bezout(y,x,v,u); else { int xis0 = gequal0(x), yis0 = gequal0(y); if (xis0 && yis0) { *u = *v = gen_0; return gen_0; } if (xis0) return zero_bezout(y,u,v); else return zero_bezout(x,v,u); } } else if (ty != t_POL) return scalar_bezout(x,y,u,v); vx = varn(x); if (vx != varn(y)) return varncmp(vx, varn(y)) < 0? scalar_bezout(x,y,u,v) : scalar_bezout(y,x,v,u); return RgX_extgcd(x,y,u,v); } GEN gcdext0(GEN x, GEN y) { GEN z=cgetg(4,t_VEC); gel(z,3) = gbezout(x,y,(GEN*)(z+1),(GEN*)(z+2)); return z; } /*******************************************************************/ /* */ /* GENERIC (modular) INVERSE */ /* */ /*******************************************************************/ GEN ginvmod(GEN x, GEN y) { long tx=typ(x); switch(typ(y)) { case t_POL: if (tx==t_POL) return RgXQ_inv(x,y); if (is_scalar_t(tx)) return ginv(x); break; case t_INT: if (tx==t_INT) return Fp_inv(x,y); if (tx==t_POL) return gen_0; } pari_err_TYPE2("ginvmod",x,y); return NULL; /* not reached */ } /***********************************************************************/ /** **/ /** NEWTON POLYGON **/ /** **/ /***********************************************************************/ /* assume leading coeff of x is non-zero */ GEN newtonpoly(GEN x, GEN p) { GEN y; long n,ind,a,b,c,u1,u2,r1,r2; long *vval, num[] = {evaltyp(t_INT) | _evallg(3), 0, 0}; if (typ(x)!=t_POL) pari_err_TYPE("newtonpoly",x); n=degpol(x); if (n<=0) return cgetg(1,t_VEC); y = cgetg(n+1,t_VEC); x += 2; /* now x[i] = term of degree i */ vval = (long *) pari_malloc(sizeof(long)*(n+1)); for (a=0; a<=n; a++) vval[a] = gvaluation(gel(x,a),p); for (a=0, ind=1; a> vals(q); } GEN odd_prime_divisors(GEN q) { return gel(Z_factor(remove2(q)), 1); } static GEN u_odd_prime_divisors(ulong q) { return gel(factoru(u_remove2(q)), 1); } /* p odd prime, q=(p-1)/2; L0 list of (some) divisors of q = (p-1)/2 or NULL * (all prime divisors of q); return the q/l, l in L0 */ static GEN is_gener_expo(GEN p, GEN L0) { GEN L, q = shifti(p,-1); long i, l; if (L0) { l = lg(L0); L = cgetg(l, t_VEC); } else { L0 = L = odd_prime_divisors(q); l = lg(L); } for (i=1; i> 1; long i, l; GEN L; if (L0) { l = lg(L0); L = cgetg(l, t_VECSMALL); } else { L0 = L = u_odd_prime_divisors(q); l = lg(L); } for (i=1; i= 0) return 0; for (i=lg(L)-1; i; i--) { ulong t = Fl_powu(x, (ulong)L[i], p); if (t == p_1 || t == 1) return 0; } return 1; } /* assume p prime */ ulong pgener_Fl_local(ulong p, GEN L0) { const pari_sp av = avma; const ulong p_1 = p-1; long x; GEN L; if (p <= 19) switch(p) { /* quick trivial cases */ case 2: return 1; case 7: case 17: return 3; default: return 2; } L = u_is_gener_expo(p,L0); for (x=2;;x++) { if (is_gener_Fl(x,p,p_1,L)) break; } avma = av; return x; } ulong pgener_Fl(ulong p) { return pgener_Fl_local(p, NULL); } /* L[i] = set of (p-1)/2l, l ODD prime divisor of p-1 (l=2 can be included, * but wasteful) */ 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); if (t >= 0) return 0; for (i = lg(L)-1; i; i--) { GEN t = Fp_pow(x, gel(L,i), p); if (equalii(t, p_1) || equali1(t)) return 0; } return 1; } /* assume p prime, return a generator of all L[i]-Sylows in F_p^*. */ GEN pgener_Fp_local(GEN p, GEN L0) { pari_sp av0 = avma; GEN x, p_1, L; if (lgefint(p) == 3) { ulong z; if (p[2] == 2) return gen_1; if (L0) L0 = ZV_to_nv(L0); z = pgener_Fl_local((ulong)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]); } GEN pgener_Fp(GEN p) { return pgener_Fp_local(p, NULL); } ulong pgener_Zl(ulong p) { if (p == 2) pari_err_DOMAIN("pgener_Zl","p","=",gen_2,gen_2); /* only p < 2^32 such that znprimroot(p) != znprimroot(p^2) */ if (p == 40487) return 10; #ifndef LONG_IS_64BIT return pgener_Fl(p); #else if (p < (1UL<<32)) return pgener_Fl(p); else { const pari_sp av = avma; const ulong p_1 = p-1; long x ; GEN p2 = sqru(p), L = u_is_gener_expo(p, NULL); for (x=2;;x++) if (is_gener_Fl(x,p,p_1,L) && !is_pm1(Fp_powu(utoipos(x),p_1,p2))) break; avma = av; return x; } #endif } /* p prime. Return a primitive root modulo p^e, e > 1 */ GEN pgener_Zp(GEN p) { if (lgefint(p) == 3) return utoipos(pgener_Zl(p[2])); else { const pari_sp av = avma; GEN p_1 = subis(p,1), p2 = sqri(p), L = is_gener_expo(p,NULL); 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]); } } static GEN gener_Zp(GEN q, GEN F) { GEN p = NULL; long e = 0; if (F) { GEN P = gel(F,1), E = gel(F,2); long i, l = lg(P); for (i = 1; i < l; i++) { p = gel(P,i); if (equaliu(p, 2)) continue; if (i < l-1) pari_err_DOMAIN("znprimroot", "argument","=",F,F); e = itos(gel(E,i)); } if (!p) pari_err_DOMAIN("znprimroot", "argument","=",F,F); } else e = Z_isanypower(q, &p); return e > 1? pgener_Zp(p): pgener_Fp(q); } GEN znprimroot(GEN N) { pari_sp av = avma; GEN x, n, F; if ((F = check_arith_non0(N,"znprimroot"))) { F = clean_Z_factor(F); N = typ(N) == t_VEC? gel(N,1): factorback(F); } if (signe(N) < 0) N = absi(N); if (cmpiu(N, 4) <= 0) { avma = av; return mkintmodu(N[2]-1,N[2]); } switch(mod4(N)) { case 0: /* N = 0 mod 4 */ pari_err_DOMAIN("znprimroot", "argument","=",N,N); x = NULL; break; case 2: /* N = 2 mod 4 */ n = shifti(N,-1); /* becomes odd */ x = gener_Zp(n,F); if (!mod2(x)) x = addii(x,n); break; default: /* N odd */ x = gener_Zp(N,F); break; } return gerepilecopy(av, mkintmod(x, N)); } /* n | (p-1), returns a primitive n-th root of 1 in F_p^* */ GEN rootsof1_Fp(GEN n, GEN p) { pari_sp av = avma; GEN L = odd_prime_divisors(n); /* 2 implicit in pgener_Fp_local */ GEN z = pgener_Fp_local(p, L); z = Fp_pow(z, diviiexact(subis(p,1), n), p); /* prim. n-th root of 1 */ return gerepileuptoint(av, z); } GEN rootsof1u_Fp(ulong n, GEN p) { pari_sp av = avma; GEN z, L = u_odd_prime_divisors(n); /* 2 implicit in pgener_Fp_local */ z = pgener_Fp_local(p, Flv_to_ZV(L)); z = Fp_pow(z, diviuexact(subis(p,1), n), p); /* prim. n-th root of 1 */ return gerepileuptoint(av, z); } ulong rootsof1_Fl(ulong n, ulong p) { pari_sp av = avma; GEN L = u_odd_prime_divisors(n); /* 2 implicit in pgener_Fl_local */ ulong z = pgener_Fl_local(p, L); z = Fl_powu(z, (p-1) / n, p); /* prim. n-th root of 1 */ avma = av; return z; } GEN znstar(GEN N) { GEN F = NULL, P, E, cyc, gen, mod; long i, j, nbp, sizeh; pari_sp av = avma; if ((F = check_arith_all(N,"znstar"))) { F = clean_Z_factor(F); N = typ(N) == t_VEC? gel(N,1): factorback(F); } if (!signe(N)) { avma = av; retmkvec3(gen_2, mkvec(gen_2), mkvec(gen_m1)); } if (signe(N) < 0) N = absi(N); if (cmpiu(N,2) <= 0) { avma = av; retmkvec3(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC)); } if (!F) F = Z_factor(N); P = gel(F,1); E = gel(F,2); nbp = lg(P)-1; cyc = cgetg(nbp+2,t_VEC); gen = cgetg(nbp+2,t_VEC); mod = cgetg(nbp+2,t_VEC); switch(mod8(N)) { case 0: { long v2 = itos(gel(E,1)); gel(cyc,1) = int2n(v2-2); gel(cyc,2) = gen_2; gel(gen,1) = utoipos(5); gel(gen,2) = addis(int2n(v2-1), -1); gel(mod,1) = gel(mod,2) = int2n(v2); sizeh = nbp+1; i = 3; j = 2; break; } case 4: gel(cyc,1) = gen_2; gel(gen,1) = utoipos(3); gel(mod,1) = utoipos(4); sizeh = nbp; i = j = 2; break; case 2: case 6: sizeh = nbp-1; i=1; j=2; break; default: /* 1, 3, 5, 7 */ sizeh = nbp; i = j = 1; } for ( ; j<=nbp; i++,j++) { long e = itos(gel(E,j)); GEN p = gel(P,j), q = powiu(p, e-1), Q = mulii(p, q); gel(cyc,i) = subii(Q, q); /* phi(p^e) */ gel(gen,i) = e > 1? pgener_Zp(p): pgener_Fp(p); gel(mod,i) = Q; } setlg(gen, sizeh+1); setlg(cyc, sizeh+1); if (nbp > 1) for (i=1; i<=sizeh; i++) { GEN Q = gel(mod,i), g = gel(gen,i), qinv = Fp_inv(Q, diviiexact(N,Q)); g = addii(g, mulii(mulii(subsi(1,g),qinv),Q)); gel(gen,i) = modii(g, N); } /*The cyc[i] are > 1. They remain so in the loop*/ for (i=sizeh; i>=2; i--) { GEN ci = gel(cyc,i), gi = gel(gen,i); for (j=i-1; j>=1; j--) /* we want cyc[i] | cyc[j] */ { GEN cj = gel(cyc,j), gj, qj, v, d; d = bezout(ci,cj,NULL,&v); /* > 1 */ if (absi_equal(ci, d)) continue; /* ci | cj */ if (absi_equal(cj, d)) { /* cj | ci */ swap(gel(gen,j),gel(gen,i)); gi = gel(gen,i); swap(gel(cyc,j),gel(cyc,i)); ci = gel(cyc,i); continue; } gj = gel(gen,j); qj = diviiexact(cj,d); gel(cyc,j) = mulii(ci,qj); gel(cyc,i) = d; /* [1,v*cj/d; 0,1]*[1,0;-1,1]*diag(cj,ci)*[ci/d,-v; cj/d,u] * = diag(lcm,gcd), with u ci + v cj = d */ /* (gj, gi) *= [1,0; -1,1]^-1 */ gj = Fp_mul(gj, gi, N); /* order ci*qj = lcm(ci,cj) */ /* (gj,gi) *= [1,v*qj; 0,1]^-1 */ togglesign_safe(&v); if (signe(v) < 0) v = modii(v,ci); /* >= 0 to avoid inversions */ gi = Fp_mul(gi, Fp_pow(gj, mulii(qj, v), N), N); gel(gen,i) = gi; gel(gen,j) = gj; ci = d; if (equaliu(ci, 2)) break; } } return gerepilecopy(av, mkvec3(ZV_prod(cyc), cyc, FpV_to_mod(gen,N))); } /*********************************************************************/ /** **/ /** INVERSE TOTIENT FUNCTION **/ /** **/ /*********************************************************************/ /* N t_INT, L a ZV containing all prime divisors of N, and possibly other * primes. Return factor(N) */ GEN Z_factor_listP(GEN N, GEN L) { long i, k, l = lg(L); GEN P = cgetg(l, t_COL), E = cgetg(l, t_COL); for (i = k = 1; i < l; i++) { GEN p = gel(L,i); long v = Z_pvalrem(N, p, &N); if (v) { gel(P,k) = p; gel(E,k) = utoipos(v); k++; } } setlg(P, k); setlg(E, k); return mkmat2(P,E); } /* look for x such that phi(x) = n, p | x => p > m (if m = NULL: no condition). * L is a list of primes containing all prime divisors of n. */ static long istotient_i(GEN n, GEN m, GEN L, GEN *px) { pari_sp av = avma, av2; GEN k, D; long i, v; if (m && mod2(n)) { if (!equali1(n)) return 0; if (px) *px = gen_1; return 1; } D = divisors(Z_factor_listP(shifti(n, -1), L)); /* loop through primes p > m, d = p-1 | n */ av2 = avma; if (!m) { /* special case p = 2, d = 1 */ k = n; for (v = 1;; v++) { if (istotient_i(k, gen_2, L, px)) { if (px) *px = shifti(*px, v); return 1; } if (mod2(k)) break; k = shifti(k,-1); } avma = av2; } for (i = 1; i < lg(D); ++i) { GEN p, d = shifti(gel(D, i), 1); /* even divisors of n */ if (m && cmpii(d, m) < 0) continue; p = addiu(d, 1); if (!isprime(p)) continue; k = diviiexact(n, d); for (v = 1;; v++) { GEN r; if (istotient_i(k, p, L, px)) { if (px) *px = mulii(*px, powiu(p, v)); return 1; } k = dvmdii(k, p, &r); if (r != gen_0) break; } avma = av2; } avma = av; return 0; } /* find x such that phi(x) = n */ long istotient(GEN n, GEN *px) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("istotient", n); if (signe(n) < 1) return 0; if (mod2(n)) { if (!equali1(n)) return 0; if (px) *px = gen_1; return 1; } if (istotient_i(n, NULL, gel(Z_factor(n), 1), px)) { if (!px) avma = av; else *px = gerepileuptoint(av, *px); return 1; } avma = av; return 0; } /*********************************************************************/ /** **/ /** INTEGRAL LOGARITHM **/ /** **/ /*********************************************************************/ /* y > 1 and B > 0 integers. Return e such that y^(e-1) <= B < y^e, i.e * e = 1 + floor(log_y B). Set *ptq = y^e if non-NULL */ long logint(GEN B, GEN y, GEN *ptq) { pari_sp av = avma, av2; long eB, ey, e, i, fl; GEN q,pow2, r = y; if (typ(B) != t_INT) B = ceil_safe(B); eB = expi(B); /* 2^eB <= B < 2^(eB + 1) */ ey = expi(y); /* result e satisfies e > eB / (ey+1) */ if (eB <= 13 * ey) /* e small, be naive */ { for (e=1;; e++) { /* here, r = y^e */ fl = cmpii(r, B); if (fl > 0) goto END; r = mulii(r,y); } } /* e > 13 ey / (ey + 1) >= 6.5 */ /* binary splitting: compute bits of e one by one */ /* compute pow2[i] = y^(2^i) [i < crude upper bound for log_2 log_y(B)] */ pow2 = new_chunk((long)log2(eB)+2); gel(pow2,0) = y; for (i=0,q=r;; ) { /* r = y^2^i */ fl = cmpii(r,B); if (!fl) { e = 1L< 0) break; q = r; r = sqri(q); i++; gel(pow2,i) = r; } av2 = avma; for (i--, e=1L< 0) e++; break; } r = mulii(q, gel(pow2,i)); fl = cmpii(r, B); if (fl <= 0) { e += (1L<>1))) { avma = av; return 0; } y[1] = evalsigne(1) | evalvarn(varn(x)); goto END; } else { for (i = 2; i < lx; i+=2) if (!issquare(gel(x,i))) { avma = av; return 0; } avma = av; return 1; } } else { x = RgX_Rg_div(x,a); y = gtrunc(gsqrt(RgX_to_ser(x,lg(x)-1),0)); if (!RgX_equal(gsqr(y), x)) { avma = av; return 0; } if (!pt) { avma = av; return 1; } if (!gequal1(a)) y = gmul(b, y); } END: *pt = v? gerepilecopy(av, RgX_shift_shallow(y, v >> 1)): gerepileupto(av, y); return 1; } /* b unit mod p */ static int Up_ispower(GEN b, GEN K, GEN p, long d, GEN *pt) { if (d == 1) { /* mod p: faster */ if (!Fp_ispower(b, K, p)) return 0; if (pt) *pt = Fp_sqrtn(b, K, p, NULL); } else { /* mod p^{2 +} */ if (!ispower(cvtop(b, p, d), K, pt)) return 0; if (pt) *pt = gtrunc(*pt); } return 1; } /* We're studying whether a mod (q*p^e) is a K-th power, (q,p) = 1. * Decide mod p^e, then reduce a mod q unless q = NULL. */ static int handle_pe(GEN *pa, GEN q, GEN L, GEN K, GEN p, long e) { GEN t, A; long v = Z_pvalrem(*pa, p, &A), d = e - v; if (d <= 0) t = gen_0; else { ulong r; v = udivui_rem(v, K, &r); if (r || !Up_ispower(A, K, p, d, L? &t: NULL)) return 0; if (L && v) t = mulii(t, powiu(p, v)); } if (q) *pa = modii(*pa, q); if (L) vectrunc_append(L, mkintmod(t, powiu(p, e))); return 1; } long Zn_ispower(GEN a, GEN q, GEN K, GEN *pt) { GEN L, N; pari_sp av; long e, i, l; ulong pp; forprime_t S; if (!signe(a)) { if (pt) { GEN t = cgetg(3, t_INTMOD); gel(t,1) = icopy(q); gel(t,2) = gen_0; *pt = t; } return 1; } /* a != 0 */ av = avma; if (typ(q) != t_INT) /* integer factorization */ { GEN P = gel(q,1), E = gel(q,2); l = lg(P); L = pt? vectrunc_init(l): NULL; for (i = 1; i < l; i++) { GEN p = gel(P,i); long e = itos(gel(E,i)); if (!handle_pe(&a, NULL, L, K, p, e)) { avma = av; return 0; } } goto END; } if (!mod2(K) && kronecker(a, shifti(q,-vali(q))) == -1) { avma = av; return 0; } L = pt? vectrunc_init(expi(q)+1): NULL; u_forprime_init(&S, 2, tridiv_bound(q)); while ((pp = u_forprime_next(&S))) { int stop; e = Z_lvalrem_stop(&q, pp, &stop); if (!e) continue; if (!handle_pe(&a, q, L, K, utoipos(pp), e)) { avma = av; return 0; } if (stop) { if (!is_pm1(q) && !handle_pe(&a, q, L, K, q, 1)) { avma = av; return 0; } goto END; } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); e = Z_pvalrem(q, p, &q); if (!e) continue; if (!handle_pe(&a, q, L, K, p, e)) { avma = av; return 0; } if (is_pm1(q)) goto END; } N = gcdii(a,q); if (!is_pm1(N)) { if (ifac_isprime(N)) { e = Z_pvalrem(q, N, &q); if (!handle_pe(&a, q, L, K, N, e)) { avma = av; return 0; } } else { GEN part = ifac_start(N, 0); for(;;) { long e; GEN p; if (!ifac_next(&part, &p, &e)) break; e = Z_pvalrem(q, p, &q); if (!handle_pe(&a, q, L, K, p, e)) { avma = av; return 0; } } } } if (!is_pm1(q)) { if (ifac_isprime(q)) { if (!handle_pe(&a, q, L, K, q, 1)) { avma = av; return 0; } } else { GEN part = ifac_start(q, 0); for(;;) { long e; GEN p; if (!ifac_next(&part, &p, &e)) break; if (!handle_pe(&a, q, L, K, p, e)) { avma = av; return 0; } } } } END: if (pt) *pt = gerepileupto(av, chinese1_coprime_Z(L)); return 1; } long issquareall(GEN x, GEN *pt) { long tx = typ(x); GEN F; pari_sp av; if (!pt) return issquare(x); switch(tx) { case t_INT: return Z_issquareall(x, pt); case t_FRAC: av = avma; F = cgetg(3, t_FRAC); if ( !Z_issquareall(gel(x,1), &gel(F,1)) || !Z_issquareall(gel(x,2), &gel(F,2))) { avma = av; return 0; } *pt = F; return 1; case t_POL: return polissquareall(x,pt); case t_RFRAC: av = avma; F = cgetg(3, t_RFRAC); if ( !issquareall(gel(x,1), &gel(F,1)) || !polissquareall(gel(x,2), &gel(F,2))) { avma = av; return 0; } *pt = F; return 1; case t_REAL: case t_COMPLEX: case t_PADIC: case t_SER: if (!issquare(x)) return 0; *pt = gsqrt(x, DEFAULTPREC); return 1; case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), gen_2, pt); case t_FFELT: return FF_issquareall(x, pt); } pari_err_TYPE("issquareall",x); return 0; /* not reached */ } long issquare(GEN x) { pari_sp av; GEN a, p; long i, v; switch(typ(x)) { case t_INT: return Z_issquare(x); case t_REAL: return (signe(x)>=0); case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), gen_2, NULL); case t_FRAC: return Z_issquare(gel(x,1)) && Z_issquare(gel(x,2)); case t_FFELT: return FF_issquareall(x, NULL); case t_COMPLEX: return 1; case t_PADIC: a = gel(x,4); if (!signe(a)) return 1; if (valp(x)&1) return 0; p = gel(x,2); if (!equaliu(p, 2)) return (kronecker(a,p) != -1); v = precp(x); /* here p=2, a is odd */ if ((v>=3 && mod8(a) != 1 ) || (v==2 && mod4(a) != 1)) return 0; return 1; case t_POL: return polissquareall(x,NULL); case t_SER: if (!signe(x)) return 1; if (valp(x)&1) return 0; return issquare(gel(x,2)); case t_RFRAC: av = avma; i = issquare(gmul(gel(x,1),gel(x,2))); avma = av; return i; } pari_err_TYPE("issquare",x); return 0; /* not reached */ } GEN gissquare(GEN x) { return issquare(x)? gen_1: gen_0; } GEN gissquareall(GEN x, GEN *pt) { return issquareall(x,pt)? gen_1: gen_0; } long ispolygonal(GEN x, GEN S, GEN *N) { pari_sp av = avma; GEN D, d, n; if (typ(x) != t_INT) pari_err_TYPE("ispolygonal", x); if (typ(S) != t_INT) pari_err_TYPE("ispolygonal", S); if (cmpiu(S,3) < 0) pari_err_DOMAIN("ispolygonal","s","<", utoipos(3),S); if (signe(x) < 0) return 0; if (signe(x) == 0) { if (N) *N = gen_0; return 1; } if (is_pm1(x)) { if (N) *N = gen_1; return 1; } /* n = (sqrt( (8s - 16) x + (s-4)^2 ) + s - 4) / 2(s - 2) */ if (cmpiu(S, 1<<16) < 0) /* common case ! */ { ulong s = S[2], r; if (s == 4) return Z_issquareall(x, N); if (s == 3) D = addiu(shifti(x, 3), 1); else D = addiu(mului(8*s - 16, x), (s-4)*(s-4)); if (!Z_issquareall(D, &d)) { avma = av; return 0; } if (s == 3) d = subiu(d, 1); else d = addiu(d, s - 4); n = diviu_rem(d, 2*s - 4, &r); if (r) { avma = av; return 0; } } else { GEN r, S_2 = subiu(S,2), S_4 = subiu(S,4); D = addii(mulii(shifti(S_2,3), x), sqri(S_4)); if (!Z_issquareall(D, &d)) { avma = av; return 0; } d = addii(d, S_4); n = dvmdii(shifti(d,-1), S_2, &r); if (r != gen_0) { avma = av; return 0; } } if (N) *N = gerepileuptoint(av, n); else avma = av; return 1; } /*********************************************************************/ /** **/ /** PERFECT POWER **/ /** **/ /*********************************************************************/ static long polispower(GEN x, GEN K, GEN *pt) { pari_sp av; long v, k = itos(K); GEN y, a, b; 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; a = gel(x,2); b = NULL; if (!ispower(a, K, &b)) { avma = av; return 0; } 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)); if (pt) { if (!gequal1(a)) { if (!b) b = gsqrtn(a, K, NULL, DEFAULTPREC); y = gmul(b,y); } *pt = v? gerepilecopy(av, RgX_shift_shallow(y, v/k)): gerepileupto(av, y); } else avma = av; return 1; } long Z_ispowerall(GEN x, ulong k, GEN *pt) { long s = signe(x); ulong mask; if (!s) { if (pt) *pt = gen_0; return 1; } if (s > 0) { if (k == 2) return Z_issquareall(x, pt); if (k == 3) { mask = 1; return !!is_357_power(x, pt, &mask); } if (k == 5) { mask = 2; return !!is_357_power(x, pt, &mask); } if (k == 7) { mask = 4; return !!is_357_power(x, pt, &mask); } return is_kth_power(x, k, pt); } if (!odd(k)) return 0; if (Z_ispowerall(absi(x), k, pt)) { if (pt) *pt = negi(*pt); return 1; }; return 0; } /* is x a K-th power mod p ? Assume p prime. */ int Fp_ispower(GEN x, GEN K, GEN p) { pari_sp av = avma; GEN p_1; long r; x = modii(x, p); if (!signe(x) || equali1(x)) { avma = av; return 1; } /* implies p > 2 */ p_1 = subiu(p,1); K = gcdii(K, p_1); if (equaliu(K, 2)) { r = kronecker(x,p); avma = av; return (r > 0); } x = Fp_pow(x, diviiexact(p_1,K), p); avma = av; return equali1(x); } /* x unit defined modulo 2^e, e > 0, p prime */ static int U2_issquare(GEN x, long e) { long r = signe(x)>=0?mod8(x):8-mod8(x); if (e==1) return 1; if (e==2) return (r&3L) == 1; return r == 1; } /* x unit defined modulo p^e, e > 0, p prime */ static int Up_issquare(GEN x, GEN p, long e) { return (equaliu(p,2))? U2_issquare(x, e): kronecker(x,p)==1; } long Zn_issquare(GEN d, GEN fn) { long j, np; if (typ(d) != t_INT) pari_err_TYPE("Zn_issquare",d); if (typ(fn) == t_INT) return Zn_ispower(d, fn, gen_2, NULL); /* integer factorization */ np = nbrows(fn); for (j = 1; j <= np; ++j) { GEN r, p = gcoeff(fn, j, 1); long e = itos(gcoeff(fn, j, 2)); long v = Z_pvalrem(d,p,&r); if (v < e && (odd(v) || !Up_issquare(r, p, e-v))) return 0; } return 1; } long ispower(GEN x, GEN K, GEN *pt) { GEN z; if (!K) return gisanypower(x, pt); if (typ(K) != t_INT) pari_err_TYPE("ispower",K); if (signe(K) <= 0) pari_err_DOMAIN("ispower","exponent","<=",gen_0,K); if (equali1(K)) { if (pt) *pt = gcopy(x); return 1; } switch(typ(x)) { case t_INT: return Z_ispowerall(x, itou(K), pt); case t_FRAC: { GEN a = gel(x,1), b = gel(x,2); ulong k = itou(K); if (pt) { z = cgetg(3, t_FRAC); if (Z_ispowerall(a, k, &a) && Z_ispowerall(b, k, &b)) { *pt = z; gel(z,1) = a; gel(z,2) = b; return 1; } avma = (pari_sp)(z + 3); return 0; } return Z_ispower(a, k) && Z_ispower(b, k); } case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), K, pt); case t_FFELT: return FF_ispower(x, K, pt); case t_PADIC: z = Qp_sqrtn(x, K, NULL); if (!z) return 0; if (pt) *pt = z; return 1; case t_POL: return polispower(x, K, pt); case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); if (pt) { z = cgetg(3, t_RFRAC); if (ispower(a, K, &a) && polispower(b, K, &b)) { *pt = z; gel(z,1) = a; gel(z,2) = b; return 1; } avma = (pari_sp)(z + 3); return 0; } return (ispower(a, K, NULL) && polispower(b, K, NULL)); } case t_REAL: if (signe(x) < 0 && !mpodd(K)) return 0; case t_COMPLEX: if (pt) *pt = gsqrtn(x, K, NULL, DEFAULTPREC); return 1; case t_SER: if (signe(x) && (!dvdsi(valp(x), K) || !ispower(gel(x,2), K, NULL))) return 0; if (pt) *pt = gsqrtn(x, K, NULL, DEFAULTPREC); return 1; default: pari_err_TYPE("ispower",x); return 0; /* not reached */ } } long gisanypower(GEN x, GEN *pty) { long tx = typ(x); ulong k, h; if (tx == t_INT) return Z_isanypower(x, pty); if (tx == t_FRAC) { pari_sp av = avma; GEN fa, P, E, a = gel(x,1), b = gel(x,2); long i, j, p, e; int sw = (absi_cmp(a, b) > 0); if (sw) swap(a, b); k = Z_isanypower(a, pty? &a: NULL); if (!k) { /* a = -1,1 or not a pure power */ if (!is_pm1(a)) { avma = av; return 0; } if (signe(a) < 0) b = negi(b); k = Z_isanypower(b, pty? &b: NULL); if (!k || !pty) { avma = av; return k; } *pty = gerepileupto(av, ginv(b)); return k; } fa = factoru(k); P = gel(fa,1); E = gel(fa,2); h = k; for (i = lg(P) - 1; i > 0; i--) { p = P[i]; e = E[i]; for (j = 0; j < e; j++) if (!is_kth_power(b, p, &b)) break; if (j < e) k /= upowuu(p, e - j); } if (k == 1) { avma = av; return 0; } if (!pty) { avma = av; return k; } if (k != h) a = powiu(a, h/k); *pty = gerepilecopy(av, mkfrac(a, b)); return k; } pari_err_TYPE("gisanypower", x); return 0; /* not reached */ } /* v_p(x) = e != 0 for some p; return ispower(x,,&x), updating x. * No need to optimize for 2,3,5,7 powers (done before) */ static long split_exponent(ulong e, GEN *x) { GEN fa, P, E; long i, j, l, k = 1; if (e == 1) return 1; fa = factoru(e); P = gel(fa,1); E = gel(fa,2); l = lg(P); for (i = 1; i < l; i++) { ulong p = P[i]; for (j = 0; j < E[i]; j++) { GEN y; if (!is_kth_power(*x, p, &y)) break; k *= p; *x = y; } } return k; } static long Z_isanypower_nosmalldiv(GEN *px) { /* any prime divisor of x is > 102 */ const double LOG2_103 = 6.6865; /* lower bound for log_2(103) */ const double LOG103 = 4.6347; /* lower bound for log(103) */ forprime_t T; ulong mask = 7, e2; long k, ex; GEN y, x = *px; k = 1; while (Z_issquareall(x, &y)) { k <<= 1; x = y; } while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } e2 = (ulong)((expi(x) + 1) / LOG2_103); /* >= log_103 (x) */ if (u_forprime_init(&T, 11, e2)) { GEN logx = NULL; const ulong Q = 30011; /* prime */ ulong p, xmodQ; double dlogx = 0; /* cut off at x^(1/p) ~ 2^30 bits which seems to be about optimum; * for large p the modular checks are no longer competitively fast */ while ( (ex = is_pth_power(x, &y, &T, 30)) ) { k *= ex; x = y; e2 = (ulong)((expi(x) + 1) / LOG2_103); u_forprime_restrict(&T, e2); } if (DEBUGLEVEL>4) err_printf("Z_isanypower: now k=%ld, x=%ld-bit\n", k, expi(x)); xmodQ = umodiu(x, Q); /* test Q | x, just in case */ if (!xmodQ) return k * split_exponent(Z_lval(x,Q), px); /* x^(1/p) < 2^31 */ p = T.p; if (p <= e2) { logx = logr_abs( itor(x, DEFAULTPREC) ); dlogx = rtodbl(logx); e2 = (ulong)(dlogx / LOG103); /* >= log_103(x) */ } while (p && p <= e2) { /* is x a p-th power ? By computing y = round(x^(1/p)). * Check whether y^p = x, first mod Q, then exactly. */ pari_sp av = avma; long e; GEN logy = divru(logx, p), y = grndtoi(mpexp(logy), &e); ulong ymodQ = umodiu(y,Q); if (e >= -10 || Fl_powu(ymodQ, p % (Q-1), Q) != xmodQ || !equalii(powiu(y, p), x)) avma = av; else { k *= p; x = y; xmodQ = ymodQ; logx = logy; dlogx /= p; e2 = (ulong)(dlogx / LOG103); /* >= log_103(x) */ u_forprime_restrict(&T, e2); continue; /* if success, retry same p */ } p = u_forprime_next(&T); } } *px = x; return k; } static ulong tinyprimes[] = { 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 }; /* disregard the sign of x, caller will take care of x < 0 */ static long Z_isanypower_aux(GEN x, GEN *pty) { long ex, v, i, l, k; GEN y, P, E; ulong mask, e = 0; if (absi_cmp(x, gen_2) < 0) return 0; /* -1,0,1 */ if (signe(x) < 0) x = negi(x); k = l = 1; P = cgetg(26 + 1, t_VECSMALL); E = cgetg(26 + 1, t_VECSMALL); /* trial division */ for(i = 0; i < 26; i++) { ulong p = tinyprimes[i]; int stop; v = Z_lvalrem_stop(&x, p, &stop); if (v) { P[l] = p; E[l] = v; l++; e = ugcd(e, v); if (e == 1) goto END; } if (stop) { if (is_pm1(x)) k = e; goto END; } } if (e) { /* Bingo. Result divides e */ long v3, v5, v7; ulong e2 = e; v = u_lvalrem(e2, 2, &e2); if (v) { for (i = 0; i < v; i++) { if (!Z_issquareall(x, &y)) break; k <<= 1; x = y; } } mask = 0; v3 = u_lvalrem(e2, 3, &e2); if (v3) mask = 1; v5 = u_lvalrem(e2, 5, &e2); if (v5) mask |= 2; v7 = u_lvalrem(e2, 7, &e2); if (v7) mask |= 4; while ( (ex = is_357_power(x, &y, &mask)) ) { x = y; switch(ex) { case 3: k *= 3; if (--v3 == 0) mask &= ~1; break; case 5: k *= 5; if (--v5 == 0) mask &= ~2; break; case 7: k *= 7; if (--v7 == 0) mask &= ~4; break; } } k *= split_exponent(e2, &x); } else k = Z_isanypower_nosmalldiv(&x); END: if (pty && k != 1) { if (e) { /* add missing small factors */ y = powuu(P[1], E[1] / k); for (i = 2; i < l; i++) y = mulii(y, powuu(P[i], E[i] / k)); x = equali1(x)? y: mulii(x,y); } *pty = x; } return k == 1? 0: k; } long Z_isanypower(GEN x, GEN *pty) { pari_sp av = avma; long k = Z_isanypower_aux(x, pty); if (!k) { avma = av; return 0; } if (signe(x) < 0) { long v = vals(k); if (v) { GEN y; k >>= v; if (k == 1) { avma = av; return 0; } if (!pty) { avma = av; return k; } y = *pty; y = powiu(y, 1< p >= 103 */ v = Z_isanypower_nosmalldiv(&n); /* expensive */ if (!isprime(n)) { avma = av; return 0; } if (pt) *pt = gerepilecopy(av, n); else avma = av; return v; } long uisprimepower(ulong n, ulong *pp) { /* We must have CUTOFF^11 >= ULONG_MAX and CUTOFF^3 < ULONG_MAX. * Tests suggest that 200-300 is the best range for 64-bit platforms. */ const ulong CUTOFF = 200UL; const long TINYCUTOFF = 46; /* tinyprimes[45] = 199 */ const ulong CUTOFF3 = CUTOFF*CUTOFF*CUTOFF; #ifdef LONG_IS_64BIT /* primes preceeding the appropriate root of ULONG_MAX. */ const ulong ROOT9 = 137; const ulong ROOT8 = 251; const ulong ROOT7 = 563; const ulong ROOT5 = 7129; const ulong ROOT4 = 65521; #else const ulong ROOT9 = 11; const ulong ROOT8 = 13; const ulong ROOT7 = 23; const ulong ROOT5 = 83; const ulong ROOT4 = 251; #endif ulong mask; long v, i; int e; if (n < 2) return 0; if (!odd(n)) { if (n & (n-1)) return 0; *pp = 2; return vals(n); } if (n < 8) { *pp = n; return 1; } /* 3,5,7 */ for (i = 1/*skip p=2*/; i < TINYCUTOFF; i++) { ulong p = tinyprimes[i]; if (n % p == 0) { v = u_lvalrem(n, p, &n); if (n == 1) { *pp = p; return v; } return 0; } } /* p | n => p >= CUTOFF */ if (n < CUTOFF3) { if (n < CUTOFF*CUTOFF || uisprime_101(n)) { *pp = n; return 1; } if (uissquareall(n, &n)) { *pp = n; return 2; } return 0; } /* Check for squares, fourth powers, and eighth powers as appropriate. */ v = 1; if (uissquareall(n, &n)) { v <<= 1; if (CUTOFF <= ROOT4 && uissquareall(n, &n)) { v <<= 1; if (CUTOFF <= ROOT8 && uissquareall(n, &n)) v <<= 1; } } if (CUTOFF > ROOT5) mask = 1; else { const ulong CUTOFF5 = CUTOFF3*CUTOFF*CUTOFF; if (n < CUTOFF5) mask = 1; else mask = 3; if (CUTOFF <= ROOT7) { const ulong CUTOFF7 = CUTOFF5*CUTOFF*CUTOFF; if (n >= CUTOFF7) mask = 7; } } if (CUTOFF <= ROOT9 && (e = uis_357_power(n, &n, &mask))) { v *= e; mask=1; } if ((e = uis_357_power(n, &n, &mask))) v *= e; if (uisprime_101(n)) { *pp = n; return v; } return 0; } /*********************************************************************/ /** **/ /** KRONECKER SYMBOL **/ /** **/ /*********************************************************************/ /* t = 3,5 mod 8 ? (= 2 not a square mod t) */ static int ome(long t) { switch(t & 7) { case 3: case 5: return 1; default: return 0; } } /* t a t_INT, is t = 3,5 mod 8 ? */ static int gome(GEN t) { return signe(t)? ome( mod2BIL(t) ): 0; } /* t a t_INT, return 1 if t = 3 (mod 4), 0 otherwise */ static int eps(GEN t) { switch(signe(t)) { case -1: return mod4(t) == 1; case 1: return mod4(t) == 3; default: return 0; } } /* assume y odd, return kronecker(x,y) * s */ static long krouu_s(ulong x, ulong y, long s) { ulong x1 = x, y1 = y, z; while (x1) { long r = vals(x1); if (r) { if (odd(r) && ome(y1)) s = -s; x1 >>= r; } if (x1 & y1 & 2) s = -s; z = y1 % x1; y1 = x1; x1 = z; } return (y1 == 1)? s: 0; } long kronecker(GEN x, GEN y) { pari_sp av = avma, lim; long s = 1, r; ulong xu, yu; if (typ(x) != t_INT) pari_err_TYPE("kronecker",x); if (typ(y) != t_INT) pari_err_TYPE("kronecker",y); switch (signe(y)) { case -1: y = negi(y); if (signe(x) < 0) s = -1; break; case 0: return is_pm1(x); } r = vali(y); if (r) { if (!mpodd(x)) { avma = av; return 0; } 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 */ { GEN z; r = vali(x); if (r) { if (odd(r) && gome(y)) s = -s; x = shifti(x,-r); } /* 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(DEBUGMEM>1) pari_warn(warnmem,"kronecker"); gerepileall(av, 2, &x, &y); } } xu = itou(x); if (!xu) return is_pm1(y)? s: 0; r = vals(xu); if (r) { if (odd(r) && gome(y)) s = -s; xu >>= r; } /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */ if (xu & mod2BIL(y) & 2) s = -s; yu = umodiu(y, xu); avma = av; return krouu_s(yu, xu, s); } long krois(GEN x, long y) { ulong yu; long s = 1, r; if (y <= 0) { if (y == 0) return is_pm1(x); yu = (ulong)-y; if (signe(x) < 0) s = -1; } else yu = (ulong)y; r = vals(yu); if (r) { if (!mpodd(x)) return 0; if (odd(r) && gome(x)) s = -s; yu >>= r; } return krouu_s(umodiu(x, yu), yu, s); } /* assume y != 0 */ long kroiu(GEN x, ulong y) { long s = 1, r = vals(y); if (r) { if (!mpodd(x)) return 0; if (odd(r) && gome(x)) s = -s; y >>= r; } return krouu_s(umodiu(x, y), y, s); } long 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; case 0: return (x==1 || x==-1); } r = vali(y); if (r) { if (!odd(x)) { avma = av; return 0; } if (odd(r) && ome(x)) s = -s; 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); if (r) { if (odd(r) && gome(y)) s = -s; xu >>= 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); } long kross(long x, long y) { ulong yu; long s = 1, r; if (y <= 0) { if (y == 0) return (labs(x)==1); yu = (ulong)-y; if (x < 0) s = -1; } else yu = (ulong)y; r = vals(yu); if (r) { if (!odd(x)) return 0; if (odd(r) && ome(x)) s = -s; yu >>= r; } x %= (long)yu; if (x < 0) x += yu; return krouu_s((ulong)x, yu, s); } long krouu(ulong x, ulong y) { long r; if (y & 1) 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); } /*********************************************************************/ /** **/ /** HILBERT SYMBOL **/ /** **/ /*********************************************************************/ /* x,y are t_INT or t_REAL */ static long mphilbertoo(GEN x, GEN y) { long sx = signe(x), sy = signe(y); if (!sx || !sy) return 0; return (sx < 0 && sy < 0)? -1: 1; } long hilbertii(GEN x, GEN y, GEN p) { pari_sp av; long oddvx, oddvy, z; if (!p) return mphilbertoo(x,y); if (is_pm1(p) || signe(p) < 0) pari_err_PRIME("hilbertii",p); if (!signe(x) || !signe(y)) return 0; av = avma; oddvx = odd(Z_pvalrem(x,p,&x)); oddvy = odd(Z_pvalrem(y,p,&y)); /* x, y are p-units, compute hilbert(x * p^oddvx, y * p^oddvy, p) */ if (equaliu(p, 2)) { z = (eps(x) && eps(y))? -1: 1; if (oddvx && gome(y)) z = -z; if (oddvy && gome(x)) z = -z; } else { z = (oddvx && oddvy && eps(p))? -1: 1; if (oddvx && kronecker(y,p) < 0) z = -z; if (oddvy && kronecker(x,p) < 0) z = -z; } avma = av; return z; } static void err_prec(void) { pari_err_PREC("hilbert"); } static void err_p(GEN p, GEN q) { pari_err_MODULUS("hilbert", p,q); } static void err_oo(GEN p) { pari_err_MODULUS("hilbert", p, strtoGENstr("oo")); } /* x t_INTMOD, *pp = prime or NULL [ unset, set it to x.mod ]. * Return lift(x) provided it's p-adic accuracy is large enough to decide * hilbert()'s value [ problem at p = 2 ] */ static GEN lift_intmod(GEN x, GEN *pp) { GEN p = *pp, N = gel(x,1); x = gel(x,2); if (!p) { *pp = p = N; switch(itos_or_0(p)) { case 2: case 4: err_prec(); } return x; } if (!signe(p)) err_oo(N); if (equaliu(p,2)) { if (vali(N) <= 2) err_prec(); } else { if (!dvdii(N,p)) err_p(N,p); } if (!signe(x)) err_prec(); return x; } /* x t_PADIC, *pp = prime or NULL [ unset, set it to x.p ]. * Return lift(x)*p^(v(x) mod 2) provided it's p-adic accuracy is large enough * to decide hilbert()'s value [ problem at p = 2 ]*/ static GEN lift_padic(GEN x, GEN *pp) { GEN p = *pp, q = gel(x,2), y = gel(x,4); if (!p) *pp = p = q; else if (!equalii(p,q)) err_p(p, q); if (equaliu(p,2) && precp(x) <= 2) err_prec(); if (!signe(y)) err_prec(); return odd(valp(x))? mulii(p,y): y; } long hilbert(GEN x, GEN y, GEN p) { pari_sp av = avma; long tx = typ(x), ty = typ(y), z; if (p && typ(p) != t_INT) pari_err_TYPE("hilbert",p); if (tx == t_REAL) { if (p && signe(p)) err_oo(p); switch (ty) { case t_INT: case t_REAL: return mphilbertoo(x,y); case t_FRAC: return mphilbertoo(x,gel(y,1)); default: pari_err_TYPE2("hilbert",x,y); } } if (ty == t_REAL) { if (p && signe(p)) err_oo(p); switch (tx) { case t_INT: case t_REAL: return mphilbertoo(x,y); case t_FRAC: return mphilbertoo(gel(x,1),y); default: pari_err_TYPE2("hilbert",x,y); } } if (tx == t_INTMOD) { x = lift_intmod(x, &p); tx = t_INT; } if (ty == t_INTMOD) { y = lift_intmod(y, &p); ty = t_INT; } if (tx == t_PADIC) { x = lift_padic(x, &p); tx = t_INT; } if (ty == t_PADIC) { y = lift_padic(y, &p); ty = t_INT; } if (tx == t_FRAC) { tx = t_INT; x = p? mulii(gel(x,1),gel(x,2)): gel(x,1); } if (ty == t_FRAC) { ty = t_INT; y = p? mulii(gel(y,1),gel(y,2)): gel(y,1); } if (tx != t_INT || ty != t_INT) pari_err_TYPE2("hilbert",x,y); if (p && !signe(p)) p = NULL; z = hilbertii(x,y,p); avma = av; return z; } /*******************************************************************/ /* */ /* SQUARE ROOT MODULO p */ /* */ /*******************************************************************/ /* Tonelli-Shanks. Assume p is prime and (a,p) != -1. */ ulong Fl_sqrt(ulong a, ulong p) { long i, e, k; ulong p1, q, v, y, w, m; if (!a) return 0; p1 = p - 1; e = vals(p1); if (e == 0) /* p = 2 */ { if (p != 2) pari_err_PRIME("Fl_sqrt [modulus]",utoi(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> 1, p); /* a ^ [(q-1)/2] */ if (!p1) return 0; v = Fl_mul(a, p1, p); w = Fl_mul(v, p1, p); 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); 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); } p1 = p - v; if (v > p1) v = p1; return v; } /* 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 * S(n) = (2^n+3)^2-8 with n = 750, 771, 779, 790, 874, 1176, 1728, 2604, etc. * * If X^2 := t^2 - a is not a square in F_p (so X is in F_p^2), then * (t+X)^(p+1) = (t-X)(t+X) = a, hence sqrt(a) = (t+X)^((p+1)/2) in F_p^2. * If (a|p)=1, then sqrt(a) is in F_p. * cf: LNCS 2286, pp 430-434 (2002) [Gonzalo Tornaria] */ /* compute y^2, y = y[1] + y[2] X */ static GEN sqrt_Cipolla_sqr(void *data, GEN y) { GEN u = gel(y,1), v = gel(y,2), p = gel(data,2), n = gel(data,3); GEN u2 = sqri(u), v2 = sqri(v); v = subii(sqri(addii(v,u)), addii(u2,v2)); u = addii(u2, mulii(v2,n)); /* NOT mkvec2: must be gerepileupto-able */ retmkvec2(modii(u,p), modii(v,p)); } /* compute (t+X) y^2 */ static GEN sqrt_Cipolla_msqr(void *data, GEN y) { GEN u = gel(y,1), v = gel(y,2), a = gel(data,1), p = gel(data,2), gt = gel(data,4); ulong t = gt[2]; GEN d = addii(u, mului(t,v)), d2= sqri(d); GEN b = remii(mulii(a,v), p); u = subii(mului(t,d2), mulii(b,addii(u,d))); v = subii(d2, mulii(b,v)); /* NOT mkvec2: must be gerepileupto-able */ retmkvec2(modii(u,p), modii(v,p)); } /* assume a reduced mod p [ otherwise correct but inefficient ] */ static GEN sqrt_Cipolla(GEN a, GEN p) { pari_sp av1; GEN u, v, n, y, pov2; ulong t; if (kronecker(a, p) < 0) return NULL; pov2 = shifti(p,-1); if (cmpii(a,pov2) > 0) a = subii(a,p); /* center: avoid multiplying by huge base*/ av1 = avma; for(t=1; ; t++) { n = subsi((long)(t*t), a); if (kronecker(n, p) < 0) break; avma = av1; } /* compute (t+X)^((p-1)/2) =: u+vX */ u = utoipos(t); y = gen_pow_fold(mkvec2(u, gen_1), pov2, mkvec4(a,p,n,u), sqrt_Cipolla_sqr, sqrt_Cipolla_msqr); /* Now u+vX = (t+X)^((p-1)/2); thus * (u+vX)(t+X) = sqrt(a) + 0 X * Whence, * sqrt(a) = (u+vt)t - v*a * 0 = (u+vt) * Thus a square root is v*a */ v = Fp_mul(gel(y, 2), a, p); if (cmpii(v,pov2) > 0) v = subii(p,v); return v; } #define sqrmod(x,p) (remii(sqri(x),p)) /* Tonelli-Shanks. Assume p is prime and return NULL if (a,p) = -1. */ GEN Fp_sqrt(GEN a, GEN p) { pari_sp av = avma, av1,lim; long i, k, e; GEN p1, q, v, y, w, m; if (typ(a) != t_INT) pari_err_TYPE("Fp_sqrt",a); if (typ(p) != t_INT) pari_err_TYPE("Fp_sqrt",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); if (u == ~0UL) return NULL; return utoi(u); } p1 = addsi(-1,p); e = vali(p1); a = modii(a, p); /* On average, the algorithm of Cipolla is better than the algorithm of * Tonelli and Shanks if and only if e(e-1)>8*log2(n)+20 * see LNCS 2286 pp 430 [GTL] */ if (e*(e-1) > 20 + 8 * expi(p)) { v = sqrt_Cipolla(a,p); if (!v) { avma = av; return NULL; } return gerepileuptoint(av,v); } if (e == 0) /* p = 2 */ { avma = av; if (!equaliu(p,2)) pari_err_PRIME("Fp_sqrt [modulus]",p); if (!signe(a) || !mod2(a)) return gen_0; return gen_1; } q = shifti(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 = krosi(k,p); if (i >= 0) { if (i) continue; pari_err_PRIME("Fp_sqrt [modulus]",p); } av1 = avma; y = m = Fp_pow(utoipos((ulong)k),q,p); for (i=1; i w even power of y, hence w^(2^(e-1)) = 1 */ p1 = sqrmod(w,p); for (k=1; !equali1(p1) && k < e; k++) p1 = sqrmod(p1,p); if (k == e) { avma=av; return NULL; } /* p composite or (a/p) != 1 */ /* w ^ (2^k) = 1 --> w = y ^ (u * 2^(e-k)), u odd */ p1 = y; for (i=1; i < e-k; i++) p1 = sqrmod(p1,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(DEBUGMEM>1) pari_warn(warnmem,"Fp_sqrt"); gerepileall(av,3, &y,&w,&v); } } av1 = avma; p1 = subii(p,v); if (cmpii(v,p1) > 0) v = p1; else avma = av1; return gerepileuptoint(av, v); } /*********************************************************************/ /** **/ /** GCD & BEZOUT **/ /** **/ /*********************************************************************/ GEN lcmii(GEN x, GEN y) { pari_sp av; GEN a, b; if (!signe(x) || !signe(y)) return gen_0; av = avma; a = gcdii(x,y); if (!equali1(a)) y = diviiexact(y,a); b = mulii(x,y); setabssign(b); return gerepileuptoint(av, b); } /*********************************************************************/ /** **/ /** CHINESE REMAINDERS **/ /** **/ /*********************************************************************/ /* P.M. & M.H. * * Chinese Remainder Theorem. x and y must have the same type (integermod, * polymod, or polynomial/vector/matrix recursively constructed with these * as coefficients). Creates (with the same type) a z in the same residue * class as x and the same residue class as y, if it is possible. * * We also allow (during recursion) two identical objects even if they are * not integermod or polymod. For example, if * * x = [1. mod(5, 11), mod(X + mod(2, 7), X^2 + 1)] * y = [1, mod(7, 17), mod(X + mod(0, 3), X^2 + 1)], * * then chinese(x, y) returns * * [1, mod(16, 187), mod(X + mod(9, 21), X^2 + 1)] * * Someone else may want to allow power series, complex numbers, and * quadratic numbers. */ GEN chinese1(GEN x) { return gassoc_proto(chinese,x,NULL); } GEN chinese(GEN x, GEN y) { pari_sp av,tetpil; long tx = typ(x); GEN z,p1,p2,d,u,v; if (!y) return chinese1(x); if (gequal(x,y)) return gcopy(x); if (tx == typ(y)) switch(tx) { case t_POLMOD: { GEN A = gel(x,1), B = gel(y,1); GEN a = gel(x,2), b = gel(y,2); z = cgetg(3, t_POLMOD); if (varn(A)!=varn(B)) pari_err_VAR("chinese",A,B); if (RgX_equal(A,B)) /* same modulus */ { gel(z,1) = gcopy(A); gel(z,2) = chinese(a,b); return z; } av = avma; d = RgX_extgcd(A,B,&u,&v); p2 = gsub(b, a); if (!gequal0(gmod(p2, d))) break; p1 = gdiv(A,d); p2 = gadd(a, gmul(gmul(u,p1), p2)); tetpil = avma; gel(z,1) = gmul(p1,B); gel(z,2) = gmod(p2,gel(z,1)); gerepilecoeffssp(av,tetpil,z+1,2); return z; } case t_INTMOD: { GEN A = gel(x,1), B = gel(y,1); GEN a = gel(x,2), b = gel(y,2), c, d, C, U; z = cgetg(3,t_INTMOD); Z_chinese_pre(A, B, &C, &U, &d); c = Z_chinese_post(a, b, C, U, d); if (!c) pari_err_OP("chinese", x,y); gel(z,1) = icopy_avma(C, (pari_sp)z); gel(z,2) = icopy_avma(c, (pari_sp)gel(z,1)); avma = (pari_sp)gel(z,2); return z; } case t_POL: { long i, lx = lg(x), ly = lg(y); if (varn(x) != varn(y)) break; if (lx < ly) { swap(x,y); lswap(lx,ly); } z = cgetg(lx, t_POL); z[1] = x[1]; for (i=2; i=0 ? sr:r); } /* Montgomery reduction */ INLINE ulong init_montdata(GEN N) { return (ulong) -invmod2BIL(mod2BIL(N)); } typedef struct muldata { GEN N; GEN iM; ulong inv, s; GEN (*res)(struct muldata *,GEN); GEN (*mul2)(struct muldata *,GEN); } muldata; /* Montgomery reduction */ static GEN _montred(muldata *D, GEN x) { return red_montgomery(x, D->N, D->inv); } 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); } /* 2x mod N */ static GEN _muli2red(muldata *D, GEN x) { GEN z = shifti(x,1); return (cmpii(z,D->N) >= 0)? subii(z,D->N): z; } static GEN _muli2montred(muldata *D, GEN x) { GEN z = _muli2red(D,x); long l = lgefint(D->N); while (lgefint(z) > l) z = subii(z,D->N); return z; } static GEN _mul(void *data, GEN x, GEN y) { muldata *D = (muldata *)data; return D->res(D, mulii(x,y)); } static GEN _sqr(void *data, GEN x) { muldata *D = (muldata *)data; return D->res(D, sqri(x)); } static GEN _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) { D->N = N; if (lN >= Fp_POW_BARRETT_LIMIT && (k==0 || ((double)k)*expi(*y) > 2 + expi(N))) { D->mul2 = &_muli2red; D->res = &_remiibar; D->s = 1+(expi(N)>>1); D->iM = Fp_invmBarrett(N, D->s); return 0; } else if (mod2(N) && lN < Fp_POW_REDC_LIMIT) { *y = remii(shifti(*y, bit_accuracy(lN)), N); D->mul2 = &_muli2montred; D->res = &_montred; D->inv = init_montdata(N); return 1; } else { D->mul2 = &_muli2red; D->res = &_remii; return 0; } } GEN Fp_powu(GEN A, ulong k, GEN N) { long lN = lgefint(N), sA; int base_is_2, use_montgomery; muldata D; pari_sp av; if (lN == 3) { ulong n = (ulong)N[2]; return utoi( Fl_powu(umodiu(A, n), k, n) ); } if (k <= 2) { /* frequent special cases */ if (k == 2) return Fp_sqr(A,N); if (k == 1) return A; if (k == 0) return gen_1; } sA = signe(A)==-1 && odd(k); base_is_2 = 0; if (lgefint(A) == 3) switch(A[2]) { case 1: return sA ? gen_m1 : gen_1; case 2: base_is_2 = 1; break; } /* TODO: Move this out of here and use for general modular computations */ av = avma; use_montgomery = Fp_select_red(&A, k, N, lN, &D); if (base_is_2) A = gen_powu_fold_i(A, k, (void*)&D, &_sqr, &_m2sqr); else A = gen_powu_i(A, k, (void*)&D, &_sqr, &_mul); if (use_montgomery) { A = _montred(&D, A); if (cmpii(A,N) >= 0) A = subii(A,N); if (sA) A = subii(N, A); } return gerepileuptoint(av, A); } GEN Fp_pows(GEN A, long k, GEN N) { if (lgefint(N) == 3) { ulong n = N[2]; ulong a = umodiu(A, n); if (k < 0) { a = Fl_inv(a, n); k = -k; } return utoi( Fl_powu(a, (ulong)k, n) ); } if (k < 0) { A = Fp_inv(A, N); k = -k; }; return Fp_powu(A, (ulong)k, N); } /* A^K mod N */ GEN Fp_pow(GEN A, GEN K, GEN N) { pari_sp av = avma; long t,s, lN = lgefint(N), sA; int base_is_2, use_montgomery; GEN y; muldata D; s = signe(K); if (!s) { t = signe(remii(A,N)); avma = av; return t? gen_1: gen_0; } if (lN == 3) { ulong k, n = N[2], a = umodiu(A, n); if (s < 0) a = Fl_inv(a, n); if (a <= 1) return utoi(a); /* 0 or 1 */ if (lgefint(K) > 3) { /* silly case : huge exponent, small modulus */ pari_warn(warner, "Mod(a,b)^n with n >> b : wasteful"); if (s > 0) { ulong d = ugcd(a, n); if (d != 1) { /* write n = n1 n2, with n2 maximal such that (n1,a) = 1 */ ulong n1 = ucoprime_part(n, d), n2 = n/n1; k = umodiu(K, eulerphiu(n1)); /* CRT: = a^K (mod n1), = 0 (mod n2)*/ return utoi( Fl_mul(Fl_powu(a, k, n1), n2 * Fl_inv(n2,n1), n) ); } /* gcd(a,n) = 1 */ k = umodiu(K, eulerphiu(n)); } else k = umodiu(negi(K), eulerphiu(n)); } else k = (ulong)K[2]; return utoi(Fl_powu(a, k, n)); } if (s < 0) y = Fp_inv(A,N); else { y = modii(A,N); if (!signe(y)) { avma = av; return gen_0; } } if (lgefint(K) == 3) return gerepileuptoint(av, Fp_powu(y, K[2], N)); base_is_2 = 0; sA = signe(y)==-1 && mod2(K); if (lgefint(y) == 3) switch(y[2]) { case 1: return sA ? gen_m1 : gen_1; case 2: base_is_2 = 1; break; } /* TODO: Move this out of here and use for general modular computations */ use_montgomery = Fp_select_red(&y, 0UL, N, lN, &D); if (base_is_2) y = gen_pow_fold_i(y, K, (void*)&D, &_sqr, &_m2sqr); else y = gen_pow_i(y, K, (void*)&D, &_sqr, &_mul); if (use_montgomery) { y = _montred(&D,y); if (cmpii(y,N) >= 0) y = subii(y,N); if (sA) y = subii(N, y); } return gerepileuptoint(av,y); } static GEN _Fp_mul(void *E, GEN x, GEN y) { return Fp_mul(x,y,(GEN)E); } static GEN _Fp_pow(void *E, GEN x, GEN n) { return Fp_pow(x,n,(GEN)E); } static GEN _Fp_rand(void *E) { return addis(randomi(subis((GEN)E,1)),1); } static GEN Fp_easylog(void *E, GEN a, GEN g, GEN ord); static const struct bb_group Fp_star={_Fp_mul,_Fp_pow,_Fp_rand,hash_GEN, equalii,equali1,Fp_easylog}; static GEN _Fp_red(void *E, GEN x) { return Fp_red(x, (GEN)E); } static GEN _Fp_add(void *E, GEN x, GEN y) { (void) E; return addii(x,y); } static GEN _Fp_neg(void *E, GEN x) { (void) E; return negi(x); } static GEN _Fp_rmul(void *E, GEN x, GEN y) { (void) E; return mulii(x,y); } static GEN _Fp_inv(void *E, GEN x) { return Fp_inv(x,(GEN)E); } static int _Fp_equal0(GEN x) { return signe(x)==0; } static GEN _Fp_s(void *E, long x) { (void) E; return stoi(x); } static const struct bb_field Fp_field={_Fp_red,_Fp_add,_Fp_rmul,_Fp_neg, _Fp_inv,_Fp_equal0,_Fp_s}; const struct bb_field *get_Fp_field(void **E, GEN p) { *E = (void*)p; return &Fp_field; } /*********************************************************************/ /** **/ /** ORDER of INTEGERMOD x in (Z/nZ)* **/ /** **/ /*********************************************************************/ ulong Fl_order(ulong a, ulong o, ulong p) { pari_sp av = avma; GEN m, P, E; long i; if (!o) o = p-1; m = factoru(o); P = gel(m,1); E = gel(m,2); for (i = lg(P)-1; i; i--) { ulong j, l=P[i], e=E[i], t = o / upowuu(l,e), y = Fl_powu(a, t, p); if (y == 1) o = t; else { for (j = 1; j < e; j++) { y = Fl_powu(y, l, p); if (y == 1) break; } o = t * upowuu(l, j); } } avma = av; return o; } /*Find the exact order of a assuming a^o==1*/ GEN Fp_order(GEN a, GEN o, GEN p) { if (lgefint(p) == 3 && typ(o) == t_INT && lgefint(o)==3) { ulong pp = p[2], oo = o[2]; return utoi( Fl_order(umodiu(a, pp), oo, pp) ); } return gen_order(a, o, (void*)p, &Fp_star); } GEN Fp_factored_order(GEN a, GEN o, GEN p) { return gen_factored_order(a, o, (void*)p, &Fp_star); } /* return order of a mod p^e, e > 0, pe = p^e */ static GEN Zp_order(GEN a, GEN p, long e, GEN pe) { GEN ap, op; if (equaliu(p, 2)) { if (e == 1) return gen_1; if (e == 2) return mod4(a) == 1? gen_1: gen_2; if (mod4(a) == 1) op = gen_1; else { op = gen_2; a = Fp_sqr(a, pe); } } else { ap = (e == 1)? a: remii(a,p); op = Fp_order(ap, subis(p,1), p); if (e == 1) return op; a = Fp_pow(a, op, pe); /* 1 mod p */ } if (equali1(a)) return op; return mulii(op, powiu(p, e - Z_pval(subis(a,1), p))); } GEN znorder(GEN x, GEN o) { pari_sp av = avma; GEN b, a; if (typ(x) != t_INTMOD) pari_err_TYPE("znorder [t_INTMOD expected]",x); b = gel(x,1); a = gel(x,2); if (!equali1(gcdii(a,b))) pari_err_COPRIME("znorder", a,b); if (!o) { GEN fa = Z_factor(b), P = gel(fa,1), E = gel(fa,2); long i, l = lg(P); o = gen_1; for (i = 1; i < l; i++) { GEN p = gel(P,i); long e = itos(gel(E,i)); if (l == 2) o = Zp_order(a, p, e, b); else { GEN pe = powiu(p,e); o = lcmii(o, Zp_order(remii(a,pe), p, e, pe)); } } return gerepileuptoint(av, o); } return Fp_order(a, o, b); } GEN order(GEN x) { return znorder(x, NULL); } /*********************************************************************/ /** **/ /** DISCRETE LOGARITHM in (Z/nZ)* **/ /** **/ /*********************************************************************/ static GEN Fp_log_halfgcd(ulong bnd, GEN C, GEN g, GEN p) { pari_sp av = avma; GEN h1, h2, F, G; if (!Fp_ratlift(g,p,C,shifti(C,-1),&h1,&h2)) return NULL; if ((F = Z_issmooth_fact(h1, bnd)) && (G = Z_issmooth_fact(h2, bnd))) { GEN M = cgetg(3, t_MAT); gel(M,1) = vecsmall_concat(gel(F, 1),gel(G, 1)); gel(M,2) = vecsmall_concat(gel(F, 2),zv_neg_inplace(gel(G, 2))); return gerepileupto(av, M); } avma = av; return NULL; } static GEN Fp_log_find_rel(GEN b, ulong bnd, GEN C, GEN p, GEN *g, long *e) { GEN rel; do { (*e)++; *g = Fp_mul(*g, b, p); rel = Fp_log_halfgcd(bnd, C, *g, p); } while (!rel); return rel; } struct Fp_log_rel { GEN rel; long *sieve; ulong prmax; long nbrel, nbmax; }; /* add u^e */ static long addifsmooth1(struct Fp_log_rel *r, GEN h, long u, long e) { pari_sp av = avma; GEN z; if ((z = Z_issmooth_fact(h, r->prmax))) { long off = r->prmax+1; GEN F = cgetg(3, t_MAT); gel(F,1) = vecsmall_append(gel(z,1), off+u); gel(F,2) = vecsmall_append(gel(z,2), e); gel(r->rel,++r->nbrel) = gerepileupto(av, F); } return r->nbrel==r->nbmax; } /* add u^-1 v^-1 */ static long addifsmooth2(struct Fp_log_rel *r, GEN h, long u, long v) { pari_sp av = avma; GEN z; if ((z = Z_issmooth_fact(h, r->prmax))) { long off = r->prmax+1; GEN P = mkvecsmall2(off+u,off+v), E = mkvecsmall2(-1,-1); GEN F = cgetg(3, t_MAT); gel(F,1) = vecsmall_concat(gel(z,1), P); gel(F,2) = vecsmall_concat(gel(z,2), E); gel(r->rel,++r->nbrel) = gerepileupto(av, F); } return r->nbrel==r->nbmax; } /* Let p=C^2+c Solve h = (C+x)*(C+a)-p = 0 [mod l] h= -c+x*(C+a)+C*a = 0 [mod l] x = (c-C*a)/(C+a) [mod l] h = -c+C*(x+a)+a*x */ static void Fp_log_sieve_h(struct Fp_log_rel *r, GEN C, GEN c, GEN Ci, GEN ci, long a, GEN pr, GEN sz) { long th = expi(C), n = lg(pr)-1; long i,j; if (addifsmooth1(r, addis(C,a), a, -1)) return; for(j=0; j<=a; j++) r->sieve[j]=0; for(i=1; i<=n; i++) { ulong li = pr[i], s = sz[i], al = a % li; ulong u, iv = Fl_invsafe(Fl_add(Ci[i],al,li),li); if (!iv) continue; u = Fl_mul(Fl_sub(ci[i],Fl_mul(Ci[i],al,li),li), iv ,li); for(j = u; j<=a; j+=li) r->sieve[j] += s; } th = th - expu(th)-1; for(j=0; jsieve[j]>=th) { GEN h = addiu(subii(muliu(C,a+j),c), a*j); if (addifsmooth2(r, h, a, j)) return; } /* j = a */ if (r->sieve[a]>=th) { GEN h = addiu(subii(muliu(C,2*a),c), a*a); if (addifsmooth1(r, h, a, -2)) return; } } static GEN _psi(void*E, GEN y) { GEN lx = (GEN) E; long prec = lg(lx); GEN ly = glog(y, prec); GEN u = gdiv(lx, ly); return gsub(gdiv(y ,ly), gpow(u, u, prec)); } static GEN opt_param(GEN x, long prec) { return zbrent((void*)glog(x,prec), _psi, gen_2, x, prec); } static GEN check_kernel(long N, long prmax, GEN C, GEN M, GEN p, GEN m) { pari_sp av = avma; GEN K = FpMs_leftkernel_elt(M, N, m); long i, f=0; long l = lg(K), lm = lgefint(m); GEN idx = diviiexact(subis(p,1),m), g; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); for(i=1; i=0) return NULL; p_1 = subiu(p,1); if (!is_pm1(gcdii(m,diviiexact(p_1,m)))) m = diviiexact(p_1, coprime_part(p_1, m)); pr = primes_upto_zv(bnd); nbi = lg(pr)-1; if (DEBUGLEVEL) { err_printf("bnd=%lu Size FB=%ld\n", bnd, nbi); timer_start(&ti); } C = sqrtremi(p, &c); av2 = avma; Ci = cgetg(nbi+1,t_VECSMALL); ci = cgetg(nbi+1,t_VECSMALL); sz = cgetg(nbi+1,t_VECSMALL); for (i = 1; i <= nbi; ++i) { ulong lp = pr[i]; Ci[i] = umodiu(C, lp); ci[i] = umodiu(c, lp); sz[i] = expu(lp); } r.nbrel = 0; r.nbmax = 8*nbi; r.rel = cgetg(r.nbmax+1,t_VEC); r.sieve = cgetg(r.nbmax+2,t_VECSMALL)+1; r.prmax = pr[nbi]; for(i=0; r.nbrel < r.nbmax; i++) { Fp_log_sieve_h(&r, C, c, Ci, ci, i, pr, sz); if (DEBUGLEVEL && (i&127)==0) err_printf("%ld%% ",100*r.nbrel/(r.nbmax)); } nbrow = r.prmax+i; if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&ti," %ld relations, %ld generators", r.nbrel, nbi+i); } setlg(r.rel,r.nbrel+1); r.rel = gerepileupto(av2, r.rel); K = check_kernel(nbrow, r.prmax, C, r.rel, p, m); if (DEBUGLEVEL) timer_start(&ti); Ao = Fp_log_find_ind(a, K, r.prmax, C, p, m); if (DEBUGLEVEL) timer_printf(&ti," log element"); Bo = Fp_log_find_ind(b, K, r.prmax, C, p, m); if (DEBUGLEVEL) timer_printf(&ti," log generator"); d = gcdii(Ao,Bo); l = Fp_div(diviiexact(Ao, d) ,diviiexact(Bo, d), m); if (!equalii(a,Fp_pow(b,l,p))) pari_err_BUG("Fp_log_index"); return gerepileuptoint(av, l); } /* 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) { pari_sp av = avma; GEN p = (GEN)E; /* assume a reduced mod p, p not necessarily prime */ if (equali1(a)) return gen_0; /* p > 2 */ if (equalii(subis(p,1), a)) /* -1 */ { pari_sp av2; GEN t; ord = dlog_get_ord(ord); if (mpodd(ord)) { avma = av; return cgetg(1, t_VEC); } /* no solution */ t = shifti(ord,-1); /* only possible solution */ av2 = avma; 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)) return Fp_log_index(a, g, ord, p); avma = av; return NULL; /* not easy */ } 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); } /* find x such that h = g^x mod N > 1, N = prod_{i <= l} P[i]^E[i], P[i] prime. * PHI[l] = eulerphi(N / P[l]^E[l]). Destroys P/E */ static GEN znlog_rec(GEN h, GEN g, GEN N, GEN P, GEN E, GEN PHI) { long l = lg(P) - 1, e = E[l]; GEN p = gel(P, l), phi = gel(PHI,l), pe = e == 1? p: powiu(p, e); GEN a,b, hp,gp, hpe,gpe, ogpe; /* = order(g mod p^e) | p^(e-1)(p-1) */ if (l == 1) { hpe = h; gpe = g; } else { hpe = modii(h, pe); gpe = modii(g, pe); } if (e == 1) { hp = hpe; gp = gpe; } else { hp = remii(hpe, p); gp = remii(gpe, p); } 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); if (typ(a) != t_INT) return NULL; } else { /* Avoid black box groups: (Z/p^2)^* / (Z/p)^* ~ (Z/pZ, +), where DL is trivial */ /* [order(gp), factor(order(gp))] */ GEN v = Fp_factored_order(gp, subis(p,1), p); GEN ogp = gel(v,1); if (!equali1(Fp_pow(hp, ogp, p))) return NULL; a = Fp_log(hp, gp, v, p); if (typ(a) != t_INT) return NULL; if (e == 1) ogpe = ogp; else { /* find a s.t. g^a = h (mod p^e), p odd prime, e > 0, (h,p) = 1 */ /* use p-adic log: O(log p + e) mul*/ long vpogpe, vpohpe; hpe = Fp_mul(hpe, Fp_pow(gpe, negi(a), pe), pe); gpe = Fp_pow(gpe, ogp, pe); /* g,h = 1 mod p; compute b s.t. h = g^b */ /* v_p(order g mod pe) */ vpogpe = equali1(gpe)? 0: e - Z_pval(subis(gpe,1), p); /* v_p(order h mod pe) */ vpohpe = equali1(gpe)? 0: e - Z_pval(subis(hpe,1), p); if (vpohpe > vpogpe) return NULL; ogpe = mulii(ogp, powiu(p, vpogpe)); /* order g mod p^e */ if (is_pm1(gpe)) return is_pm1(hpe)? a: NULL; b = gdiv(Qp_log(cvtop(hpe, p, e)), Qp_log(cvtop(gpe, p, e))); a = addii(a, mulii(ogp, gtrunc(b))); } } /* gp^a = hp => x = a mod ogpe => generalized Pohlig-Hellman strategy */ if (l == 1) return a; N = diviiexact(N, pe); /* make N coprime to p */ h = Fp_mul(h, Fp_pow(g, modii(negi(a), phi), N), N); g = Fp_pow(g, modii(ogpe, phi), N); setlg(P, l); /* remove last element */ setlg(E, l); b = znlog_rec(h, g, N, P, E, PHI); if (!b) return NULL; return addmulii(a, b, ogpe); } static GEN get_PHI(GEN P, GEN E) { long i, l = lg(P); GEN PHI = cgetg(l, t_VEC); gel(PHI,1) = gen_1; for (i=1; i 1) t = mulii(t, gel(PHI,i)); gel(PHI,i+1) = t; } return PHI; } GEN znlog(GEN h, GEN g, GEN o) { pari_sp av = avma; GEN N, fa, P, E, x; switch (typ(g)) { case t_PADIC: { GEN p = gel(g,2); long v = valp(g); if (v < 0) pari_err_DIM("znlog"); if (v > 0) { long k = gvaluation(h, p); if (k % v) return cgetg(1,t_VEC); k /= v; if (!gequal(h, gpowgs(g,k))) { avma = av; return cgetg(1,t_VEC); } avma = av; return stoi(k); } N = gel(g,3); g = Rg_to_Fp(g, N); break; } case t_INTMOD: N = gel(g,1); g = gel(g,2); break; default: pari_err_TYPE("znlog", g); return NULL; /* not reached */ } if (equali1(N)) { avma = av; return gen_0; } h = Rg_to_Fp(h, N); if (o) return gerepileupto(av, Fp_log(h, g, o, N)); fa = Z_factor(N); P = gel(fa,1); E = vec_to_vecsmall(gel(fa,2)); x = znlog_rec(h, g, N, P, E, get_PHI(P,E)); if (!x) { avma = av; return cgetg(1,t_VEC); } return gerepileuptoint(av, x); } GEN Fp_sqrtn(GEN a, GEN n, GEN p, GEN *zeta) { a = modii(a,p); if (!signe(a)) { if (zeta) *zeta = gen_1; if (signe(n) < 0) pari_err_INV("Fp_sqrtn", mkintmod(gen_0,p)); return gen_0; } if (equaliu(n,2)) { if (zeta) *zeta = addis(p,-1); return Fp_sqrt(a,p); } return gen_Shanks_sqrtn(a,n,addis(p,-1),zeta,(void*)p,&Fp_star); } /*********************************************************************/ /** **/ /** FUNDAMENTAL DISCRIMINANTS **/ /** **/ /*********************************************************************/ long isfundamental(GEN x) { if (typ(x) != t_INT) pari_err_TYPE("isfundamental",x); return Z_isfundamental(x); } /* x fundamental ? */ long uposisfundamental(ulong x) { ulong r = x & 15; /* x mod 16 */ if (!r) return 0; switch(r & 3) { /* x mod 4 */ case 0: return (r == 4)? 0: uissquarefree(x >> 2); case 1: return uissquarefree(x); default: return 0; } } /* -x fundamental ? */ long unegisfundamental(ulong x) { ulong r = x & 15; /* x mod 16 */ if (!r) return 0; switch(r & 3) { /* x mod 4 */ case 0: return (r == 12)? 0: uissquarefree(x >> 2); case 3: return uissquarefree(x); default: return 0; } } long Z_isfundamental(GEN x) { long r; switch(lgefint(x)) { case 2: return 0; case 3: return signe(x) < 0? unegisfundamental(x[2]) : uposisfundamental(x[2]); } r = mod16(x); if (!r) return 0; if ((r & 3) == 0) { pari_sp av; r >>= 2; /* |x|/4 mod 4 */ if (signe(x) < 0) r = 4-r; if (r == 1) return 0; av = avma; r = Z_issquarefree( shifti(x,-2) ); avma = av; return r; } r &= 3; /* |x| mod 4 */ if (signe(x) < 0) r = 4-r; return (r==1) ? Z_issquarefree(x) : 0; } GEN quaddisc(GEN x) { const pari_sp av = avma; long i,r,tx=typ(x); GEN P,E,f,s; if (!is_rational_t(tx)) pari_err_TYPE("quaddisc",x); f = factor(x); P = gel(f,1); E = gel(f,2); s = gen_1; for (i=1; i1) s = shifti(s,2); return gerepileuptoint(av, s); } /*********************************************************************/ /** **/ /** FACTORIAL **/ /** **/ /*********************************************************************/ /* return a * (a+1) * ... * b. Assume a <= b [ note: factoring out powers of 2 * first is slower ... ] */ GEN mulu_interval(ulong a, ulong b) { pari_sp av = avma; ulong k, l, N, n = b - a + 1; long lx; GEN x; if (n < 61) { x = utoi(a); for (k=a+1; k<=b; k++) x = mului(k,x); return gerepileuptoint(av, x); } lx = 1; x = cgetg(2 + n/2, t_VEC); N = b + a; for (k = a;; k++) { l = N - k; if (l <= k) break; gel(x,lx++) = muluu(k,l); } if (l == k) gel(x,lx++) = utoipos(k); setlg(x, lx); return gerepileuptoint(av, divide_conquer_prod(x, mulii)); } GEN mpfact(long n) { if (n < 2) { if (n < 0) pari_err_DOMAIN("factorial", "argument","<",gen_0,stoi(n)); return gen_1; } return mulu_interval(2UL, (ulong)n); } /*******************************************************************/ /** **/ /** LUCAS & FIBONACCI **/ /** **/ /*******************************************************************/ static void lucas(ulong n, GEN *a, GEN *b) { GEN z, t, zt; if (!n) { *a = gen_2; *b = gen_1; return; } lucas(n >> 1, &z, &t); zt = mulii(z, t); switch(n & 3) { case 0: *a = addsi(-2,sqri(z)); *b = addsi(-1,zt); break; case 1: *a = addsi(-1,zt); *b = addsi(2,sqri(t)); break; case 2: *a = addsi(2,sqri(z)); *b = addsi(1,zt); break; case 3: *a = addsi(1,zt); *b = addsi(-2,sqri(t)); } } GEN fibo(long n) { pari_sp av = avma; GEN a, b; if (!n) return gen_0; lucas((ulong)(labs(n)-1), &a, &b); a = diviuexact(addii(shifti(a,1),b), 5); if (n < 0 && !odd(n)) setsigne(a, -1); return gerepileuptoint(av, a); } /*******************************************************************/ /* */ /* CONTINUED FRACTIONS */ /* */ /*******************************************************************/ static GEN icopy_lg(GEN x, long l) { long lx = lgefint(x); GEN y; if (lx >= l) return icopy(x); y = cgeti(l); affii(x, y); return y; } /* continued fraction of a/b. If y != NULL, stop when partial quotients * differ from y */ static GEN 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 ) */ 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; z = cgetg(l,t_VEC); l--; if (y) { pari_sp av = avma; if (l >= (ulong)lg(y)) l = lg(y)-1; for (i = 1; i <= l; i++) { GEN q = gel(y,i); gel(z,i) = q; c = b; if (!gequal1(q)) c = mulii(q, b); c = subii(a, c); if (signe(c) < 0) { /* partial quotient too large */ c = addii(c, b); if (signe(c) >= 0) i++; /* by 1 */ break; } if (cmpii(c, b) >= 0) { /* partial quotient too small */ c = subii(c, b); if (cmpii(c, b) < 0) { /* by 1. If next quotient is 1 in y, add 1 */ if (i < l && equali1(gel(y,i+1))) gel(z,i) = addis(q,1); i++; } break; } if ((i & 0xff) == 0) gerepileall(av, 2, &b, &c); a = b; b = c; } } else { a = icopy_lg(a, ly); b = icopy(b); for (i = 1; i <= l; i++) { gel(z,i) = truedvmdii(a,b,&c); if (c == gen_0) { i++; break; } affii(c, a); cgiv(c); c = a; a = b; b = c; } } i--; if (i > 1 && gequal1(gel(z,i))) { cgiv(gel(z,i)); --i; gel(z,i) = addsi(1, gel(z,i)); /* unclean: leave old z[i] on stack */ } setlg(z,i+1); return z; } static GEN sersfcont(GEN a, GEN b, long k) { long i, l = typ(a) == t_POL? lg(a): 3; GEN y, c; if (lg(b) > l) l = lg(b); if (k > 0 && l > k+1) l = k+1; y = cgetg(l,t_VEC); for (i=1; i= lb) pari_err_DIM("contfrac [too few denominators]"); lb = k+1; } y = cgetg(lb,t_VEC); if (lb==1) return y; if (is_scalar_t(tx)) { if (!is_intreal_t(tx) && tx != t_FRAC) pari_err_TYPE("sfcont2",x); } else if (tx == t_SER) x = ser2rfrac_i(x); if (!gequal1(gel(b,1))) x = gmul(gel(b,1),x); for (i = 1;;) { if (tx == t_REAL) { long e = expo(x); if (e > 0 && nbits2prec(e+1) > realprec(x)) break; gel(y,i) = floorr(x); p1 = subri(x, gel(y,i)); } else { gel(y,i) = gfloor(x); p1 = gsub(x, gel(y,i)); } if (++i >= lb) break; if (gequal0(p1)) break; x = gdiv(gel(b,i),p1); } setlg(y,i); return gerepilecopy(av,y); } GEN gcf(GEN x) { return gboundcf(x,0); } GEN gcf2(GEN b, GEN x) { return contfrac0(x,b,0); } GEN contfrac0(GEN x, GEN b, long nmax) { long tb; if (!b) return gboundcf(x,nmax); tb = typ(b); if (tb == t_INT) return gboundcf(x,itos(b)); if (! is_vec_t(tb)) pari_err_TYPE("contfrac0",b); if (nmax < 0) pari_err_DOMAIN("contfrac","nmax","<",gen_0,stoi(nmax)); return sfcont2(b,x,nmax); } GEN contfracpnqn(GEN x, long n) { pari_sp av = avma; long i, lx = lg(x); GEN M,A,B, p0,p1, q0,q1; if (lx == 1) { if (! is_matvec_t(typ(x))) pari_err_TYPE("pnqn",x); if (n >= 0) return cgetg(1,t_MAT); return matid(2); } switch(typ(x)) { case t_VEC: case t_COL: A = x; B = NULL; break; case t_MAT: switch(lgcols(x)) { case 2: A = row(x,1); B = NULL; break; case 3: A = row(x,2); B = row(x,1); break; default: pari_err_DIM("pnqn [ nbrows != 1,2 ]"); return NULL; /*not reached*/ } break; default: pari_err_TYPE("pnqn",x); return NULL; /*not reached*/ } p1 = gel(A,1); q1 = B? gel(B,1): gen_1; /* p[0], q[0] */ if (n >= 0) { lx = minss(lx, n+2); if (lx == 2) return gerepilecopy(av, mkmat(mkcol2(p1,q1))); } else if (lx == 2) return gerepilecopy(av, mkmat2(mkcol2(p1,q1), mkcol2(gen_1,gen_0))); /* lx >= 3 */ p0 = gen_1; q0 = gen_0; /* p[-1], q[-1] */ M = cgetg(lx, t_MAT); gel(M,1) = mkcol2(p1,q1); for (i=2; i= 0) { A = d-1 - B; /* denominator bound useless, don't use it */ if (A < B) B = -1; } if (B < 0) { B = d >> 1; A = odd(d)? B : B-1; } if (varn(N) != varn(x)) x = scalarpol(x, varn(N)); if (! RgXQ_ratlift(x, N, A, B, &a,&b)) return NULL; if (degpol(RgX_gcd(a,b)) > 0) return NULL; return gdiv(a,b); } /* k > 0 t_INT, x a t_FRAC, returns the convergent a/b * of the continued fraction of x with b <= k maximal */ static GEN bestappr_frac(GEN x, GEN k) { pari_sp av; GEN p0, p1, p, q0, q1, q, a, y; if (cmpii(gel(x,2),k) <= 0) return gcopy(x); av = avma; y = x; p1 = gen_1; p0 = truedvmdii(gel(x,1), gel(x,2), &a); /* = floor(x) */ q1 = gen_0; q0 = gen_1; x = mkfrac(a, gel(x,2)); /* = frac(x); now 0<= x < 1 */ for(;;) { x = ginv(x); /* > 1 */ a = typ(x)==t_INT? x: divii(gel(x,1), gel(x,2)); if (cmpii(a,k) > 0) { /* next partial quotient will overflow limits */ GEN n, d; a = divii(subii(k, q1), q0); p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; /* compare |y-p0/q0|, |y-p1/q1| */ n = gel(y,1); d = gel(y,2); if (absi_cmp(mulii(q1, subii(mulii(q0,n), mulii(d,p0))), mulii(q0, subii(mulii(q1,n), mulii(d,p1)))) < 0) { p1 = p0; q1 = q0; } break; } p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; if (cmpii(q0,k) > 0) break; x = gsub(x,a); /* 0 <= x < 1 */ if (typ(x) == t_INT) { p1 = p0; q1 = q0; break; } /* x = 0 */ } return gerepileupto(av, gdiv(p1,q1)); } /* bestappr(t_REAL != 0), to maximal accuracy */ static GEN bestappr_real_max(GEN x) { pari_sp av = avma; GEN p0, p1, p, q0, q1, q, a; long e; p1 = gen_1; a = p0 = floorr(x); q1 = gen_0; q0 = gen_1; x = subri(x,a); /* 0 <= x < 1 */ e = bit_prec(x) - expo(x); for(;;) { long d; if (!signe(x) || expi(q0) > e) { p1 = p0; q1 = q0; break; } x = invr(x); /* > 1 */ d = nbits2prec(expo(x) + 1); if (d > lg(x)) { p1 = p0; q1 = q0; break; } /* original x was ~ 0 */ a = truncr(x); /* truncr(x) will NOT raise e_PREC */ p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; x = subri(x,a); /* 0 <= x < 1 */ } return gerepileupto(av, gdiv(p1,q1)); } /* k > 0 t_INT, x != 0 a t_REAL, returns the convergent a/b * of the continued fraction of x with b <= k maximal */ static GEN bestappr_real(GEN x, GEN k) { pari_sp av = avma; GEN kr, p0, p1, p, q0, q1, q, a, y; y = x; p1 = gen_1; a = p0 = floorr(x); q1 = gen_0; q0 = gen_1; x = subri(x,a); /* 0 <= x < 1 */ if (!signe(x)) { cgiv(x); return a; } kr = itor(k, realprec(x)); for(;;) { long d; x = invr(x); /* > 1 */ if (cmprr(x,kr) > 0) { /* next partial quotient will overflow limits */ a = divii(subii(k, q1), q0); p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; /* compare |y-p0/q0|, |y-p1/q1| */ if (absr_cmp(mulir(q1, subri(mulir(q0,y), p0)), mulir(q0, subri(mulir(q1,y), p1))) < 0) { p1 = p0; q1 = q0; } break; } d = nbits2prec(expo(x) + 1); if (d > lg(x)) { p1 = p0; q1 = q0; break; } /* original x was ~ 0 */ a = truncr(x); /* truncr(x) will NOT raise e_PREC */ p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; if (cmpii(q0,k) > 0) break; x = subri(x,a); /* 0 <= x < 1 */ if (!signe(x)) { p1 = p0; q1 = q0; break; } } return gerepileupto(av, gdiv(p1,q1)); } /* k t_INT or NULL */ static GEN bestappr_Q(GEN x, GEN k) { long lx, tx = typ(x), i; GEN a, y; switch(tx) { case t_INT: return icopy(x); case t_FRAC: return k? bestappr_frac(x, k): gcopy(x); case t_REAL: if (!signe(x)) return gen_0; return k? bestappr_real(x, k): bestappr_real_max(x); case t_INTMOD: { pari_sp av = avma; a = mod_to_frac(gel(x,2), gel(x,1), k); if (!a) return NULL; return gerepilecopy(av, a); } case t_PADIC: { pari_sp av = avma; long v = valp(x); a = mod_to_frac(gel(x,4), gel(x,3), k); if (!a) return NULL; if (v) a = gmul(a, powis(gel(x,2), v)); return gerepilecopy(av, a); } case t_COMPLEX: case t_POLMOD: case t_POL: case t_SER: 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; } for (; i 0) { if (typ(a) != t_POL || varn(a) != vx) a = scalarpol_shallow(a, vx); a = RgX_shift(a, v); } t = mkrfraccopy(a, b); } return t; } static GEN bestappr_RgX(GEN x, long B); /* x t_POLMOD, B >= 0 or < 0 [omit condition on B]. * Look for coprime t_POL a,b, deg(b)<=B, such that a/b = x */ static GEN bestappr_RgX(GEN x, long B) { long i, lx, tx = typ(x); GEN y, t; switch(tx) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_COMPLEX: case t_PADIC: case t_QUAD: case t_POL: return gcopy(x); case t_RFRAC: { pari_sp av = avma; if (B < 0 || degpol(gel(x,2)) <= B) return gcopy(x); x = rfractoser(x, varn(gel(x,2)), 2*B+1); t = bestappr_ser(x, B); if (!t) return NULL; return gerepileupto(av, t); } case t_POLMOD: { pari_sp av = avma; t = mod_to_rfrac(gel(x,2), gel(x,1), B); if (!t) return NULL; return gerepileupto(av, t); } case t_SER: { pari_sp av = avma; t = bestappr_ser(x, B); if (!t) return NULL; return gerepileupto(av, t); } 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; } for (; i1) pari_warn(warnmem,"quadunit"); gerepileall(av2,4, &a,&f,&u,&v); } } if (signe(gel(y,3)) < 0) y = gneg(y); return gerepileupto(av, y); } GEN quadregulator(GEN x, long prec) { pari_sp av = avma, av2, lim; GEN R, rsqd, u, v, sqd; long r, Rexpo; check_quaddisc_real(x, &r, "quadregulator"); sqd = sqrti(x); rsqd = gsqrt(x,prec); Rexpo = 0; R = real2n(1, prec); /* = 2 */ av2 = avma; lim = stack_lim(av2,2); u = stoi(r); v = gen_2; for(;;) { GEN u1 = subii(mulii(divii(addii(u,sqd),v), v), u); GEN v1 = divii(subii(x,sqri(u1)),v); if (equalii(v,v1)) { R = sqrr(R); shiftr_inplace(R, -1); R = mulrr(R, divri(addir(u1,rsqd),v)); break; } if (equalii(u,u1)) { R = sqrr(R); shiftr_inplace(R, -1); break; } R = mulrr(R, divri(addir(u1,rsqd),v)); 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(DEBUGMEM>1) pari_warn(warnmem,"quadregulator"); gerepileall(av2,3, &R,&u,&v); } } R = logr_abs(divri(R,v)); if (Rexpo) { GEN t = mulsr(Rexpo, mplog2(prec)); shiftr_inplace(t, 1); R = addrr(R,t); } return gerepileuptoleaf(av, R); } /*************************************************************************/ /** **/ /** CLASS NUMBER **/ /** **/ /*************************************************************************/ 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}; GEN qfbclassno0(GEN x,long flag) { switch(flag) { case 0: return map_proto_G(classno,x); case 1: return map_proto_G(classno2,x); default: pari_err_FLAG("qfbclassno"); } return NULL; /* not reached */ } /* f^h = 1, return order(f) */ static GEN find_order(GEN f, GEN h) { return gen_order(f, h, NULL, &qfb_group); } static GEN end_classno(GEN h, GEN hin, GEN forms) { GEN a, b, p1, q, fh, fg, f = gel(forms,1); long i, com, l = lg(forms); h = find_order(f,h); /* H = */ q = diviiround(hin, h); /* approximate order of G/H */ for (i=2; 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))); } q = gerepileuptoint(av, q); } return mulii(q,h); } /* Write x = Df^2, where D = fundamental discriminant, * P^E = factorisation of conductor f, with E[i] >= 0 */ static void corediscfact(GEN x, long xmod4, GEN *ptD, GEN *ptP, GEN *ptE) { long s = signe(x), l, i; GEN fa = absi_factor(x); GEN d, P = gel(fa,1), E = gtovecsmall(gel(fa,2)); l = lg(P); d = gen_1; for (i=1; i>= 1; } if (!xmod4 && mod4(d) != ((s < 0)? 3: 1)) { d = shifti(d,2); E[1]--; } *ptD = (s < 0)? negi(d): d; *ptP = P; *ptE = E; } static GEN conductor_part(GEN x, long xmod4, GEN *ptD, GEN *ptreg) { long l, i, s = signe(x); GEN E, H, D, P, reg; corediscfact(x, xmod4, &D, &P, &E); H = gen_1; l = lg(P); /* f \prod_{p|f} [ 1 - (D/p) p^-1 ] = \prod_{p^e||f} p^(e-1) [ p - (D/p) ] */ for (i=1; i= 2) H = mulii(H, powiu(p,e-1)); } } /* divide by [ O_K^* : O^* ] */ if (s < 0) { reg = NULL; switch(itou_or_0(D)) { case 4: H = shifti(H,-1); break; case 3: H = divis(H,3); break; } } else { reg = quadregulator(D,DEFAULTPREC); if (!equalii(x,D)) H = divii(H, roundr(divrr(quadregulator(x,DEFAULTPREC), reg))); } if (ptreg) *ptreg = reg; *ptD = D; return H; } static long two_rank(GEN x) { GEN p = gel(absi_factor(x),1); long l = lg(p)-1; #if 0 /* positive disc not needed */ if (signe(x) > 0) { long i; for (i=1; i<=l; i++) if (mod4(gel(p,i)) == 3) { l--; break; } } #endif return l-1; } static GEN sqr_primeform(GEN x, ulong p) { return redimag(qfisqr(primeform_u(x, p))); } static ulong _low(GEN x) { return signe(x)? mod2BIL(x): 0; } /* h(x) for x<0 using Baby Step/Giant Step. * Assumes G is not too far from being cyclic. * * Compute G^2 instead of G so as to kill most of the non-cyclicity */ 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; if (signe(x) >= 0) return classno2(x); check_quaddisc(x, &s, &k, "classno"); if (cmpiu(x,12) <= 0) return gen_1; 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)) ) { long d, k = kroiu(D,p); pari_sp av3; if (!k) continue; if (k > 0) { if (++nforms < MAXFORM) vectrunc_append(forms, sqr_primeform(D,p)); d = p - 1; } else d = p + 1; av3 = avma; affrr(divru(mulur(p,p1),d), p1); avma = av3; } 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 0) { GEN invlogd = invr(logd); p2 = subsr(1, shiftr(mulrr(logr_abs(reg),invlogd),1)); if (cmprr(sqrr(p2), shiftr(invlogd,1)) >= 0) p1 = mulrr(p2,p1); } n = itos_or_0( mptrunc(p1) ); if (!n) pari_err_OVERFLOW("classno [discriminant too large]"); p4 = divri(Pi,d); p7 = invr(sqrtr_abs(Pi)); half = real2n(-1, prec); if (s > 0) { /* i = 1, shortcut */ p1 = sqrtr_abs(dr); p5 = subsr(1, mulrr(p7,incgamc(half,p4,prec))); S = addrr(mulrr(p1,p5), eint1(p4,prec)); for (i=2; i<=n; i++) { long k = kroiu(D,i); if (!k) continue; p2 = mulir(sqru(i), p4); p5 = subsr(1, mulrr(p7,incgamc(half,p2,prec))); p5 = addrr(divru(mulrr(p1,p5),i), eint1(p2,prec)); S = (k>0)? addrr(S,p5): subrr(S,p5); } S = shiftr(divrr(S,reg),-1); } else { /* i = 1, shortcut */ p1 = gdiv(sqrtr_abs(dr), Pi); p5 = subsr(1, mulrr(p7,incgamc(half,p4,prec))); S = addrr(p5, divrr(p1, mpexp(p4))); for (i=2; i<=n; i++) { long k = kroiu(D,i); if (!k) continue; p2 = mulir(sqru(i), p4); p5 = subsr(1, mulrr(p7,incgamc(half,p2,prec))); p5 = addrr(p5, divrr(p1, mulur(i, mpexp(p2)))); S = (k>0)? addrr(S,p5): subrr(S,p5); } } return gerepileuptoint(av, mulii(Hf, roundr(S))); } static GEN hclassno2(GEN x) { long i, l, s, xmod4; GEN Q, H, D, P, E; x = negi(x); check_quaddisc(x, &s, &xmod4, "hclassno"); corediscfact(x, xmod4, &D, &P, &E); Q = quadclassunit0(D, 0, NULL, 0); H = gel(Q,1); l = lg(P); /* H \prod_{p^e||f} (1 + (p^e-1)/(p-1))[ p - (D/p) ] */ for (i=1; i 1) t = mulii(t, diviiexact(subis(powiu(p,e), 1), subis(p,1))); H = mulii(H, addsi(1, t)); } } switch( itou_or_0(D) ) { case 3: H = gdivgs(H, 3); break; case 4: H = gdivgs(H, 2); break; } return H; } GEN hclassno(GEN x) { ulong a, b, b2, d, h; long s; int f; if (typ(x) != t_INT) pari_err_TYPE("hclassno",x); s = signe(x); if (s < 0) return gen_0; if (!s) return gdivgs(gen_1, -12); a = mod4(x); if (a == 1 || a == 2) return gen_0; d = itou_or_0(x); if (!d || d > 500000) return hclassno2(x); h = 0; b = d&1; b2 = (1+d)>>2; f=0; if (!b) { for (a=1; a*a>2; } while (b2*3 < d) { if (b2%b == 0) h++; for (a=b+1; a*a < b2; a++) if (b2%a == 0) h += 2; if (a*a == b2) h++; b += 2; b2 = (b*b+d)>>2; } if (b2*3 == d) { GEN y = cgetg(3,t_FRAC); gel(y,1) = utoipos(3*h+1); gel(y,2) = utoipos(3); return y; } if (f) { GEN y = cgetg(3,t_FRAC); gel(y,1) = utoipos(2*h+1); gel(y,2) = gen_2; return y; } return utoipos(h); } pari-2.7.5/src/basemath/trans1.c0000644000175000017500000024533012571634536015060 0ustar billbill/* 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. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #ifdef LONG_IS_64BIT static const long SQRTVERYBIGINT = 3037000500L; /* ceil(sqrt(LONG_MAX)) */ #else static const long SQRTVERYBIGINT = 46341L; #endif static THREAD GEN gcatalan, geuler, glog2, gpi; void pari_init_floats(void) { gcatalan = geuler = gpi = bernzone = glog2 = NULL; } void pari_close_floats(void) { if (gcatalan) gunclone(gcatalan); if (geuler) gunclone(geuler); if (gpi) gunclone(gpi); if (bernzone) gunclone(bernzone); if (glog2) gunclone(glog2); } /********************************************************************/ /** GENERIC BINARY SPLITTING **/ /** (Haible, Papanikolaou) **/ /********************************************************************/ void abpq_init(struct abpq *A, long n) { A->a = (GEN*)new_chunk(n+1); A->b = (GEN*)new_chunk(n+1); A->p = (GEN*)new_chunk(n+1); A->q = (GEN*)new_chunk(n+1); } static GEN mulii3(GEN a, GEN b, GEN c) { return mulii(mulii(a,b),c); } static GEN mulii4(GEN a, GEN b, GEN c, GEN d) { return mulii(mulii(a,b),mulii(c,d)); } /* T_{n1,n1+1}, given P = p[n1]p[n1+1] */ static GEN T2(struct abpq *A, long n1, GEN P) { GEN u1 = mulii4(A->a[n1], A->p[n1], A->b[n1+1], A->q[n1+1]); GEN u2 = mulii3(A->b[n1],A->a[n1+1], P); return addii(u1, u2); } /* assume n2 > n1. Compute sum_{n1 <= n < n2} a/b(n) p/q(n1)... p/q(n) */ void abpq_sum(struct abpq_res *r, long n1, long n2, struct abpq *A) { struct abpq_res L, R; GEN u1, u2; pari_sp av; long n; switch(n2 - n1) { GEN b, p, q; case 1: r->P = A->p[n1]; r->Q = A->q[n1]; r->B = A->b[n1]; r->T = mulii(A->a[n1], A->p[n1]); return; case 2: r->P = mulii(A->p[n1], A->p[n1+1]); r->Q = mulii(A->q[n1], A->q[n1+1]); r->B = mulii(A->b[n1], A->b[n1+1]); av = avma; r->T = gerepileuptoint(av, T2(A, n1, r->P)); return; case 3: p = mulii(A->p[n1+1], A->p[n1+2]); q = mulii(A->q[n1+1], A->q[n1+2]); b = mulii(A->b[n1+1], A->b[n1+2]); r->P = mulii(A->p[n1], p); r->Q = mulii(A->q[n1], q); r->B = mulii(A->b[n1], b); av = avma; u1 = mulii3(b, q, A->a[n1]); u2 = mulii(A->b[n1], T2(A, n1+1, p)); r->T = gerepileuptoint(av, mulii(A->p[n1], addii(u1, u2))); return; } av = avma; n = (n1 + n2) >> 1; abpq_sum(&L, n1, n, A); abpq_sum(&R, n, n2, A); r->P = mulii(L.P, R.P); r->Q = mulii(L.Q, R.Q); r->B = mulii(L.B, R.B); u1 = mulii3(R.B,R.Q,L.T); u2 = mulii3(L.B,L.P,R.T); r->T = addii(u1,u2); avma = av; r->P = icopy(r->P); r->Q = icopy(r->Q); r->B = icopy(r->B); r->T = icopy(r->T); } /********************************************************************/ /** **/ /** PI **/ /** **/ /********************************************************************/ /* replace *old clone by c. Protect against SIGINT */ static void swap_clone(GEN *old, GEN c) { GEN tmp = *old; *old = c; if (tmp) gunclone(tmp); } /* ---- * 53360 (640320)^(1/2) \ (6n)! (545140134 n + 13591409) * -------------------- = / ------------------------------ * Pi ---- (n!)^3 (3n)! (-640320)^(3n) * n>=0 * * Ramanujan's formula + binary splitting */ static GEN pi_ramanujan(long prec) { const ulong B = 545140134, A = 13591409, C = 640320; const double alpha2 = 47.11041314; /* 3log(C/12) / log(2) */ long n, nmax, prec2; struct abpq_res R; struct abpq S; GEN D, u; nmax = (long)(1 + prec2nbits(prec)/alpha2); #ifdef LONG_IS_64BIT D = utoipos(10939058860032000); /* C^3/24 */ #else D = uutoi(2546948,495419392); #endif abpq_init(&S, nmax); S.a[0] = utoipos(A); S.b[0] = S.p[0] = S.q[0] = gen_1; for (n = 1; n <= nmax; n++) { S.a[n] = addiu(muluu(B, n), A); S.b[n] = gen_1; S.p[n] = mulis(muluu(6*n-5, 2*n-1), 1-6*n); S.q[n] = mulii(sqru(n), muliu(D,n)); } abpq_sum(&R, 0, nmax, &S); prec2 = prec+EXTRAPRECWORD; u = itor(muliu(R.Q,C/12), prec2); return rtor(mulrr(divri(u, R.T), sqrtr_abs(utor(C,prec2))), prec); } #if 0 /* Much slower than binary splitting at least up to prec = 10^8 */ /* Gauss - Brent-Salamin AGM iteration */ static GEN pi_brent_salamin(long prec) { GEN A, B, C; pari_sp av2; long i, G; G = - prec2nbits(prec); incrprec(prec); A = real2n(-1, prec); B = sqrtr_abs(A); /* = 1/sqrt(2) */ setexpo(A, 0); C = real2n(-2, prec); av2 = avma; for (i = 0;; i++) { GEN y, a, b, B_A = subrr(B, A); pari_sp av3 = avma; if (expo(B_A) < G) break; a = addrr(A,B); shiftr_inplace(a, -1); b = mulrr(A,B); affrr(a, A); affrr(sqrtr_abs(b), B); avma = av3; y = sqrr(B_A); shiftr_inplace(y, i - 2); affrr(subrr(C, y), C); avma = av2; } shiftr_inplace(C, 2); return divrr(sqrr(addrr(A,B)), C); } GEN constpi(long prec) { pari_sp av; GEN tmp; if (gpi && realprec(gpi) >= prec) return gpi; tmp = cgetr_block(prec); av = avma; affrr(pi_brent_salamin(prec), tmp); swap_clone(&gpi, tmp); avma = av; return gpi; } #endif GEN constpi(long prec) { pari_sp av; GEN tmp; if (gpi && realprec(gpi) >= prec) return gpi; av = avma; tmp = gclone(pi_ramanujan(prec)); swap_clone(&gpi,tmp); avma = av; return gpi; } GEN mppi(long prec) { return rtor(constpi(prec), prec); } /* Pi * 2^n */ GEN Pi2n(long n, long prec) { GEN x = mppi(prec); shiftr_inplace(x, n); return x; } /* I * Pi * 2^n */ GEN PiI2n(long n, long prec) { retmkcomplex(gen_0, Pi2n(n, prec)); } /* 2I * Pi */ GEN PiI2(long prec) { return PiI2n(1, prec); } /********************************************************************/ /** **/ /** EULER CONSTANT **/ /** **/ /********************************************************************/ GEN consteuler(long prec) { GEN u,v,a,b,tmpeuler; long l, n1, n, k, x; pari_sp av1, av2; if (geuler && realprec(geuler) >= prec) return geuler; av1 = avma; tmpeuler = cgetr_block(prec); incrprec(prec); l = prec+EXTRAPRECWORD; x = (long) (1 + prec2nbits_mul(l, LOG2/4)); a = utor(x,l); u=logr_abs(a); setsigne(u,-1); affrr(u,a); b = real_1(l); v = real_1(l); n = (long)(1+3.591*x); /* z=3.591: z*[ ln(z)-1 ]=1 */ n1 = minss(n, SQRTVERYBIGINT); if (x < SQRTVERYBIGINT) { ulong xx = x*x; av2 = avma; for (k=1; k=0} 1/(binomial(2n,n)(2n+1)^2) + Pi log(2+sqrt(3)) */ static GEN catalan(long prec) { long i, nmax = bit_accuracy(prec) >> 1; struct abpq_res R; struct abpq A; GEN u, v; abpq_init(&A, nmax); A.a[0] = A.b[0] = A.p[0] = A.q[0] = gen_1; for (i = 1; i <= nmax; i++) { A.a[i] = gen_1; A.b[i] = utoipos((i<<1)+1); A.p[i] = utoipos(i); A.q[i] = utoipos((i<<2)+2); } abpq_sum(&R, 0, nmax, &A); u = mulur(3, rdivii(R.T, mulii(R.B,R.Q),prec)); v = mulrr(mppi(prec), logr_abs(addrs(sqrtr_abs(utor(3,prec)), 2))); u = addrr(u, v); shiftr_inplace(u, -3); return u; } GEN constcatalan(long prec) { pari_sp av = avma; GEN tmp; if (gcatalan && realprec(gcatalan) >= prec) return gcatalan; tmp = gclone(catalan(prec)); swap_clone(&gcatalan,tmp); avma = av; return gcatalan; } GEN mpcatalan(long prec) { return rtor(constcatalan(prec), prec); } /********************************************************************/ /** **/ /** TYPE CONVERSION FOR TRANSCENDENTAL FUNCTIONS **/ /** **/ /********************************************************************/ static GEN transvec(GEN (*f)(GEN,long), GEN x, long prec) { long i, l; GEN y = cgetg_copy(x, &l); for (i=1; i= 0? real_0_bit(e): real_1(nbits2prec(-e)); } static GEN powr0(GEN x) { return signe(x)? real_1(realprec(x)): mpexp0(x); } /* x t_POL or t_SER, return scalarpol(RgX_get_1(x)) */ static GEN scalarpol_get_1(GEN x) { GEN y = cgetg(3,t_POL); y[1] = evalvarn(varn(x)) | evalsigne(1); gel(y,2) = RgX_get_1(x); return y; } /* to be called by the generic function gpowgs(x,s) when s = 0 */ static GEN gpowg0(GEN x) { long lx, i; GEN y; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_PADIC: return gen_1; case t_QUAD: x++; /*fall through*/ case t_COMPLEX: { pari_sp av = avma; GEN a = gpowg0(gel(x,1)); GEN b = gpowg0(gel(x,2)); if (a == gen_1) return b; if (b == gen_1) return a; return gerepileupto(av, gmul(a,b)); } case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = gen_1; return y; case t_FFELT: return FF_1(x); case t_POLMOD: y = cgetg(3,t_POLMOD); gel(y,1) = gcopy(gel(x,1)); gel(y,2) = scalarpol_get_1(gel(x,1)); return y; case t_RFRAC: return scalarpol_get_1(gel(x,2)); case t_POL: case t_SER: return scalarpol_get_1(x); case t_MAT: lx=lg(x); if (lx==1) return cgetg(1,t_MAT); if (lx != lgcols(x)) pari_err_DIM("gpow"); y = matid(lx-1); for (i=1; i 0) * * Use left shift binary algorithm (RS is wasteful: multiplies big numbers, * with LS one of them is the base, hence small). Sign of result is set * to s (= 1,-1). Makes life easier for caller, which otherwise might do a * setsigne(gen_1 / gen_m1) */ static GEN powiu_sign(GEN a, ulong N, long s) { pari_sp av; GEN y; if (lgefint(a) == 3) { /* easy if |a| < 3 */ ulong q = a[2]; if (q == 1) return (s>0)? gen_1: gen_m1; if (q == 2) { a = int2u(N); setsigne(a,s); return a; } q = upowuu(q, N); if (q) return s>0? utoipos(q): utoineg(q); } if (N <= 2) { if (N == 2) return sqri(a); a = icopy(a); setsigne(a,s); return a; } av = avma; y = gen_powu_i(a, N, NULL, &_sqri, &_muli); setsigne(y,s); return gerepileuptoint(av, y); } /* a^n */ GEN powiu(GEN a, ulong n) { long s; if (!n) return gen_1; s = signe(a); if (!s) return gen_0; return powiu_sign(a, n, (s < 0 && odd(n))? -1: 1); } GEN powis(GEN a, long n) { long s; GEN t, y; if (n >= 0) return powiu(a, n); s = signe(a); if (!s) pari_err_INV("powis",gen_0); t = (s < 0 && odd(n))? gen_m1: gen_1; if (is_pm1(a)) return t; /* n < 0, |a| > 1 */ y = cgetg(3,t_FRAC); gel(y,1) = t; gel(y,2) = powiu_sign(a, -n, 1); /* force denominator > 0 */ return y; } GEN powuu(ulong p, ulong N) { pari_sp av = avma; long P[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; ulong pN; GEN y; if (N <= 2) { if (N == 2) return sqru(p); if (N == 1) return utoipos(p); return gen_1; } if (!p) return gen_0; pN = upowuu(p, N); if (pN) return utoipos(pN); if (p == 2) return int2u(N); P[2] = p; av = avma; y = gen_powu_i(P, N, NULL, &_sqri, &_muli); return gerepileuptoint(av, y); } /* return 0 if overflow */ static ulong usqru(ulong p) { return p & HIGHMASK? 0: p*p; } ulong upowuu(ulong p, ulong k) { #ifdef LONG_IS_64BIT const ulong CUTOFF3 = 2642245; const ulong CUTOFF4 = 65535; const ulong CUTOFF5 = 7131; const ulong CUTOFF6 = 1625; const ulong CUTOFF7 = 565; const ulong CUTOFF8 = 255; const ulong CUTOFF9 = 138; const ulong CUTOFF10 = 84; const ulong CUTOFF11 = 56; const ulong CUTOFF12 = 40; const ulong CUTOFF13 = 30; const ulong CUTOFF14 = 23; const ulong CUTOFF15 = 19; const ulong CUTOFF16 = 15; const ulong CUTOFF17 = 13; const ulong CUTOFF18 = 11; const ulong CUTOFF19 = 10; const ulong CUTOFF20 = 9; #else const ulong CUTOFF3 = 1625; const ulong CUTOFF4 = 255; const ulong CUTOFF5 = 84; const ulong CUTOFF6 = 40; const ulong CUTOFF7 = 23; const ulong CUTOFF8 = 15; const ulong CUTOFF9 = 11; const ulong CUTOFF10 = 9; const ulong CUTOFF11 = 7; const ulong CUTOFF12 = 6; const ulong CUTOFF13 = 5; const ulong CUTOFF14 = 4; const ulong CUTOFF15 = 4; const ulong CUTOFF16 = 3; const ulong CUTOFF17 = 3; const ulong CUTOFF18 = 3; const ulong CUTOFF19 = 3; const ulong CUTOFF20 = 3; #endif if (p <= 2) { if (p < 2) return p; return k < BITS_IN_LONG? 1UL< CUTOFF3) return 0; return p*p*p; case 4: if (p > CUTOFF4) return 0; p2=p*p; return p2*p2; case 5: if (p > CUTOFF5) return 0; p2=p*p; return p2*p2*p; case 6: if (p > CUTOFF6) return 0; p2=p*p; return p2*p2*p2; case 7: if (p > CUTOFF7) return 0; p2=p*p; return p2*p2*p2*p; case 8: if (p > CUTOFF8) return 0; p2=p*p; p4=p2*p2; return p4*p4; case 9: if (p > CUTOFF9) return 0; p2=p*p; p4=p2*p2; return p4*p4*p; case 10: if (p > CUTOFF10)return 0; p2=p*p; p4=p2*p2; return p4*p4*p2; case 11: if (p > CUTOFF11)return 0; p2=p*p; p4=p2*p2; return p4*p4*p2*p; case 12: if (p > CUTOFF12)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4; case 13: if (p > CUTOFF13)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4*p; case 14: if (p > CUTOFF14)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4*p2; case 15: if (p > CUTOFF15)return 0; p2=p*p; p3=p2*p; p5=p3*p2; return p5*p5*p5; case 16: if (p > CUTOFF16)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p8*p8; case 17: if (p > CUTOFF17)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p*p8*p8; case 18: if (p > CUTOFF18)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p2*p8*p8; case 19: if (p > CUTOFF19)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p*p2*p8*p8; case 20: if (p > CUTOFF20)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p4*p8*p8; } #ifdef LONG_IS_64BIT switch(p) { case 3: if (k > 40) return 0; break; case 4: if (k > 31) return 0; return 1UL<<(2*k); case 5: if (k > 27) return 0; break; case 6: if (k > 24) return 0; break; case 7: if (k > 22) return 0; break; default: return 0; } /* no overflow */ { ulong q = upowuu(p, k >> 1); q *= q ; return odd(k)? q*p: q; } #endif return 0; } typedef struct { long prec, a; GEN (*sqr)(GEN); GEN (*mulug)(ulong,GEN); } sr_muldata; static GEN _rpowuu_sqr(void *data, GEN x) { sr_muldata *D = (sr_muldata *)data; if (typ(x) == t_INT && lgefint(x) >= D->prec) { /* switch to t_REAL */ D->sqr = &sqrr; D->mulug = &mulur; x = itor(x, D->prec); } return D->sqr(x); } static GEN _rpowuu_msqr(void *data, GEN x) { GEN x2 = _rpowuu_sqr(data, x); sr_muldata *D = (sr_muldata *)data; return D->mulug(D->a, x2); } /* return a^n as a t_REAL of precision prec. Assume a > 0, n > 0 */ GEN rpowuu(ulong a, ulong n, long prec) { pari_sp av; GEN y, z; sr_muldata D; if (a == 1) return real_1(prec); if (a == 2) return real2n(n, prec); if (n == 1) return utor(a, prec); z = cgetr(prec); av = avma; D.sqr = &sqri; D.mulug = &mului; D.prec = prec; D.a = (long)a; y = gen_powu_fold_i(utoipos(a), n, (void*)&D, &_rpowuu_sqr, &_rpowuu_msqr); mpaff(y, z); avma = av; return z; } GEN powrs(GEN x, long n) { pari_sp av = avma; GEN y; if (!n) return powr0(x); y = gen_powu_i(x, (ulong)labs(n), NULL, &_sqrr, &_mulr); if (n < 0) y = invr(y); return gerepileuptoleaf(av,y); } GEN powru(GEN x, ulong n) { pari_sp av = avma; GEN y; if (!n) return powr0(x); y = gen_powu_i(x, n, NULL, &_sqrr, &_mulr); return gerepileuptoleaf(av,y); } /* x^(s/2), assume x t_REAL */ GEN powrshalf(GEN x, long s) { if (s & 1) return sqrtr(powrs(x, s)); return powrs(x, s>>1); } /* x^(s/2), assume x t_REAL */ GEN powruhalf(GEN x, ulong s) { if (s & 1) return sqrtr(powru(x, s)); return powru(x, s>>1); } /* x^(n/d), assume x t_REAL, return t_REAL */ GEN powrfrac(GEN x, long n, long d) { long z; if (!n) return powr0(x); z = cgcd(n, d); if (z > 1) { n /= z; d /= z; } if (d == 1) return powrs(x, n); x = powrs(x, n); if (d == 2) return sqrtr(x); return sqrtnr(x, d); } /* assume x != 0 */ static GEN pow_monome(GEN x, long n) { long i, d, dx = degpol(x); GEN A, b, y; if (n < 0) { n = -n; y = cgetg(3, t_RFRAC); } else y = NULL; if (HIGHWORD(dx) || HIGHWORD(n)) { LOCAL_HIREMAINDER; d = (long)mulll((ulong)dx, (ulong)n); if (hiremainder || (d &~ LGBITS)) d = LGBITS; /* overflow */ d += 2; } else d = dx*n + 2; if ((d + 1) & ~LGBITS) pari_err(e_OVERFLOW,"pow_monome [degree]"); A = cgetg(d+1, t_POL); A[1] = x[1]; for (i=2; i < d; i++) gel(A,i) = gen_0; b = gpowgs(gel(x,dx+2), n); /* not memory clean if (n < 0) */ if (!y) y = A; else { GEN c = denom(b); gel(y,1) = c; if (c != gen_1) b = gmul(b,c); gel(y,2) = A; } gel(A,d) = b; return y; } /* x t_PADIC */ static GEN powps(GEN x, long n) { long e = n*valp(x), v; GEN t, y, mod, p = gel(x,2); pari_sp av; if (!signe(gel(x,4))) { if (n < 0) pari_err_INV("powps",x); return zeropadic(p, e); } v = z_pval(n, p); y = cgetg(5,t_PADIC); mod = gel(x,3); if (v == 0) mod = icopy(mod); else { if (precp(x) == 1 && equaliu(p, 2)) v++; mod = mulii(mod, powiu(p,v)); mod = gerepileuptoint((pari_sp)y, mod); } y[1] = evalprecp(precp(x) + v) | evalvalp(e); gel(y,2) = icopy(p); gel(y,3) = mod; av = avma; t = gel(x,4); if (n < 0) { t = Fp_inv(t, mod); n = -n; } t = Fp_powu(t, n, mod); gel(y,4) = gerepileuptoint(av, t); return y; } /* x t_PADIC */ static GEN powp(GEN x, GEN n) { long v; GEN y, mod, p = gel(x,2); if (valp(x)) pari_err_OVERFLOW("valp()"); if (!signe(gel(x,4))) { if (signe(n) < 0) pari_err_INV("powp",x); return zeropadic(p, 0); } v = Z_pval(n, p); y = cgetg(5,t_PADIC); mod = gel(x,3); if (v == 0) mod = icopy(mod); else { mod = mulii(mod, powiu(p,v)); mod = gerepileuptoint((pari_sp)y, mod); } y[1] = evalprecp(precp(x) + v) | _evalvalp(0); gel(y,2) = icopy(p); gel(y,3) = mod; gel(y,4) = Fp_pow(gel(x,4), n, mod); return y; } static GEN pow_polmod(GEN x, GEN n) { GEN z = cgetg(3, t_POLMOD), a = gel(x,2), T = gel(x,1); gel(z,1) = gcopy(T); if (typ(a) != t_POL || varn(a) != varn(T) || lg(a) <= 3) a = powgi(a, n); else { pari_sp av = avma; GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(a, &p) && p) { T = RgX_to_FpX(T, p); a = RgX_to_FpX(a, p); if (lgefint(p) == 3) { ulong pp = p[2]; a = Flxq_pow(ZX_to_Flx(a, pp), n, ZX_to_Flx(T, pp), pp); a = Flx_to_ZX(a); } else a = FpXQ_pow(a, n, T, p); a = FpX_to_mod(a, p); a = gerepileupto(av, a); } else { avma = av; a = RgXQ_pow(a, n, gel(z,1)); } } gel(z,2) = a; return z; } GEN gpowgs(GEN x, long n) { long m; pari_sp av; GEN y; if (n == 0) return gpowg0(x); if (n == 1) switch (typ(x)) { case t_QFI: return redimag(x); case t_QFR: return redreal(x); default: return gcopy(x); } if (n ==-1) return ginv(x); switch(typ(x)) { case t_INT: return powis(x,n); case t_REAL: return powrs(x,n); case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = Fp_pows(gel(x,2), n, gel(x,1)); return y; case t_FRAC: { GEN a = gel(x,1), b = gel(x,2); long s = (signe(a) < 0 && odd(n))? -1: 1; if (n < 0) { n = -n; if (is_pm1(a)) return powiu_sign(b, n, s); /* +-1/x[2] inverts to t_INT */ swap(a, b); } y = cgetg(3, t_FRAC); gel(y,1) = powiu_sign(a, n, s); gel(y,2) = powiu_sign(b, n, 1); return y; } case t_PADIC: return powps(x, n); case t_RFRAC: { av = avma; y = cgetg(3, t_RFRAC); m = labs(n); gel(y,1) = gpowgs(gel(x,1),m); gel(y,2) = gpowgs(gel(x,2),m); if (n < 0) y = ginv(y); return gerepileupto(av,y); } case t_POLMOD: { long N[] = {evaltyp(t_INT) | _evallg(3),0,0}; affsi(n,N); return pow_polmod(x, N); } case t_POL: if (RgX_is_monomial(x)) return pow_monome(x, n); default: { pari_sp av = avma; y = gen_powu_i(x, (ulong)labs(n), NULL, &_sqr, &_mul); if (n < 0) y = ginv(y); return gerepileupto(av,y); } } } /* n a t_INT */ GEN powgi(GEN x, GEN n) { GEN y; if (!is_bigint(n)) return gpowgs(x, itos(n)); /* probable overflow for non-modular types (typical exception: (X^0)^N) */ switch(typ(x)) { case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = Fp_pow(gel(x,2), n, gel(x,1)); return y; case t_FFELT: return FF_pow(x,n); case t_PADIC: return powp(x, n); case t_INT: if (is_pm1(x)) return (signe(x) < 0 && mpodd(n))? gen_m1: gen_1; if (signe(x)) pari_err_OVERFLOW("lg()"); if (signe(n) < 0) pari_err_INV("powgi",gen_0); return gen_0; case t_FRAC: pari_err_OVERFLOW("lg()"); case t_QFR: return qfrpow(x, n); case t_POLMOD: return pow_polmod(x, n); default: { pari_sp av = avma; y = gen_pow(x, n, NULL, &_sqr, &_mul); if (signe(n) < 0) y = ginv(y); return gerepileupto(av,y); } } } /* Assume x = 1 + O(t), n a scalar. Return x^n */ static GEN ser_pow_1(GEN x, GEN n) { long lx, mi, i, j, d; GEN y = cgetg_copy(x, &lx), X = x+2, Y = y + 2; y[1] = evalsigne(1) | _evalvalp(0) | evalvarn(varn(x)); d = mi = lx-3; while (mi>=1 && isrationalzero(gel(X,mi))) mi--; gel(Y,0) = gen_1; for (i=1; i<=d; i++) { pari_sp av = avma; GEN s = gen_0; for (j=1; j<=minss(i,mi); j++) { GEN t = gsubgs(gmulgs(n,j),i-j); s = gadd(s, gmul(gmul(t, gel(X,j)), gel(Y,i-j))); } gel(Y,i) = gerepileupto(av, gdivgs(s,i)); } return y; } /* we suppose n != 0, valp(x) = 0 and leading-term(x) != 0. Not stack clean */ static GEN ser_pow(GEN x, GEN n, long prec) { GEN y, c, lead; if (varncmp(gvar(n), varn(x)) <= 0) return gexp(gmul(n, glog(x,prec)), prec); lead = gel(x,2); if (gequal1(lead)) return ser_pow_1(x, n); x = ser_normalize(x); if (typ(n) == t_FRAC && !isinexact(lead) && ispower(lead, gel(n,2), &c)) c = powgi(c, gel(n,1)); else c = gpow(lead,n, prec); y = gmul(c, ser_pow_1(x, n)); /* gpow(t_POLMOD,n) can be a t_COL [conjvec] */ if (typ(y) != t_SER) pari_err_TYPE("gpow", y); return y; } static long val_from_i(GEN E) { if (is_bigint(E)) pari_err_OVERFLOW("sqrtn [valuation]"); return itos(E); } /* return x^q, assume typ(x) = t_SER, typ(q) = t_INT/t_FRAC and q != 0 */ static GEN ser_powfrac(GEN x, GEN q, long prec) { GEN y, E = gmulsg(valp(x), q); long e; if (!signe(x)) { if (gsigne(q) < 0) pari_err_INV("gpow", x); return zeroser(varn(x), val_from_i(gfloor(E))); } if (typ(E) != t_INT) pari_err_DOMAIN("sqrtn", "valuation", "!=", mkintmod(gen_0, gel(q,2)), x); e = val_from_i(E); y = leafcopy(x); setvalp(y, 0); y = ser_pow(y, q, prec); setvalp(y, e); return y; } static GEN gpow0(GEN x, GEN n, long prec) { pari_sp av = avma; long i, lx; GEN y; switch(typ(n)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: break; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(n, &lx); for (i=1; i 3 */ static GEN 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; if (pp == 4) return z; zp = 3; /* number of correct bits in z (compared to sqrt(x)) */ av = avma; lim = stack_lim(av,2); for(;;) { GEN mod; zp = (zp<<1) - 1; if (zp > pp) zp = pp; mod = int2n(zp); z = addii(z, remi2n(mulii(x, Fp_inv(z,mod)), zp)); z = shifti(z, -1); /* (z + x/z) / 2 */ if (pp == zp) return z; if (zp < pp) zp--; if (low_stack(lim,stack_lim(av,2))) { if (DEBUGMEM > 1) pari_warn(warnmem,"Qp_sqrt"); z = gerepileuptoint(av,z); } } } /* x unit defined modulo p^e, e > 0 */ static GEN Up_sqrt(GEN x, GEN p, long e) { pari_sp av = avma; if (equaliu(p,2)) { long r = signe(x)>=0?mod8(x):8-mod8(x); if (e <= 3) { switch(e) { case 1: break; case 2: if ((r&3) == 1) break; return NULL; case 3: if (r == 1) break; return NULL; } return gen_1; } else { if (r != 1) return NULL; return gerepileuptoint(av, sqrt_2adic(x, 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)); } } GEN Qp_sqrt(GEN x) { long pp, e = valp(x); GEN z,y,mod, p = gel(x,2); if (gequal0(x)) return zeropadic(p, (e+1) >> 1); if (e & 1) return NULL; y = cgetg(5,t_PADIC); pp = precp(x); mod = gel(x,3); z = gel(x,4); /* lift to t_INT */ e >>= 1; z = Up_sqrt(z, p, pp); if (!z) return NULL; if (equaliu(p,2)) { pp = (pp <= 3) ? 1 : pp-1; mod = int2n(pp); } else mod = icopy(mod); y[1] = evalprecp(pp) | evalvalp(e); gel(y,2) = icopy(p); gel(y,3) = mod; gel(y,4) = z; return y; } GEN Zn_sqrt(GEN d, GEN fn) { pari_sp ltop = avma, btop, st_lim; GEN b = gen_0, m = gen_1; long j, np; if (typ(d) != t_INT) pari_err_TYPE("Zn_sqrt",d); if (typ(fn) == t_INT) fn = absi_factor(fn); else if (!is_Z_factorpos(fn)) pari_err_TYPE("Zn_sqrt",fn); np = nbrows(fn); btop = avma; st_lim = stack_lim(btop, 1); for (j = 1; j <= np; ++j) { GEN bp, mp, pr, r; GEN p = gcoeff(fn, j, 1); long e = itos(gcoeff(fn, j, 2)); long v = Z_pvalrem(d,p,&r); if (v >= e) bp =gen_0; else { if (odd(v)) return NULL; bp = Up_sqrt(r, p, e-v); if (!bp) return NULL; if (v) bp = mulii(bp, powiu(p, v>>1L)); } mp = powiu(p, e); pr = mulii(m, mp); b = Z_chinese_coprime(b, bp, m, mp, pr); m = pr; if (low_stack(st_lim, stack_lim(btop, 1))) gerepileall(btop, 2, &b, &m); } return gerepileupto(ltop, b); } static GEN sqrt_ser(GEN b, long prec) { long e = valp(b), vx = varn(b), lx, lold, j; ulong mask; GEN a, x, lta, ltx; if (!signe(b)) return zeroser(vx, e>>1); a = leafcopy(b); x = cgetg_copy(b, &lx); if (e & 1) pari_err_DOMAIN("sqrtn", "valuation", "!=", mkintmod(gen_0, gen_2), x); a[1] = x[1] = evalsigne(1) | evalvarn(0) | _evalvalp(0); lta = gel(a,2); if (gequal1(lta)) ltx = lta; else if (!issquareall(lta,<x)) ltx = gsqrt(lta,prec); gel(x,2) = ltx; for (j = 3; j < lx; j++) gel(x,j) = gen_0; setlg(x,3); mask = quadratic_prec_mask(lx - 2); lold = 1; while (mask > 1) { GEN y, x2 = gmul2n(x,1); long l = lold << 1; if (mask & 1) l--; mask >>= 1; setlg(a, l + 2); setlg(x, l + 2); 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); */ for (j = lold+2; j < l+2; j++) gel(x,j) = gel(y,j); lold = l; } x[1] = evalsigne(1) | evalvarn(vx) | _evalvalp(e >> 1); return x; } GEN gsqrt(GEN x, long prec) { pari_sp av; GEN y; switch(typ(x)) { case t_REAL: return sqrtr(x); case t_INTMOD: { GEN p = gel(x,1), a; y = cgetg(3,t_INTMOD); gel(y,1) = icopy(p); a = Fp_sqrt(gel(x,2),p); if (!a) { if (!BPSW_psp(p)) pari_err_PRIME("sqrt [modulus]",p); pari_err_SQRTN("gsqrt",x); } gel(y,2) = a; return y; } case t_COMPLEX: { /* (u+iv)^2 = a+ib <=> u^2+v^2 = sqrt(a^2+b^2), u^2-v^2=a, 2uv=b */ GEN a = gel(x,1), b = gel(x,2), r, u, v; if (isrationalzero(b)) return gsqrt(a, prec); y = cgetg(3,t_COMPLEX); av = avma; r = cxnorm(x); if (typ(r) == t_INTMOD) pari_err_IMPL("sqrt(complex of t_INTMODs)"); r = gsqrt(r, prec); /* t_REAL, |a+Ib| */ if (!signe(r)) u = v = gerepileuptoleaf(av, sqrtr(r)); else if (gsigne(a) < 0) { /* v > 0 since r > 0, a < 0, rounding errors can't make the sum of two * positive numbers = 0 */ v = sqrtr( gmul2n(gsub(r,a), -1) ); if (gsigne(b) < 0) togglesign(v); v = gerepileuptoleaf(av, v); av = avma; /* v = 0 is impossible */ u = gerepileuptoleaf(av, gdiv(b, shiftr(v,1))); } else { u = sqrtr( gmul2n(gadd(r,a), -1) ); u = gerepileuptoleaf(av, u); av = avma; if (!signe(u)) /* possible if a = 0.0, e.g. sqrt(0.e-10+1e-10*I) */ v = u; else v = gerepileuptoleaf(av, gdiv(b, shiftr(u,1))); } gel(y,1) = u; gel(y,2) = v; return y; } case t_PADIC: y = Qp_sqrt(x); if (!y) pari_err_SQRTN("Qp_sqrt",x); return y; case t_FFELT: return FF_sqrt(x); default: av = avma; if (!(y = toser_i(x))) break; return gerepilecopy(av, sqrt_ser(y, prec)); } return trans_eval("sqrt",gsqrt,x,prec); } /********************************************************************/ /** **/ /** N-th ROOT **/ /** **/ /********************************************************************/ /* exp(2Ipi/n), assume n positive t_INT */ GEN rootsof1complex(GEN n, long prec) { pari_sp av = avma; if (is_pm1(n)) return real_1(prec); if (equaliu(n, 2)) return stor(-1, prec); return gerepileupto(av, expIr( divri(Pi2n(1, prec), n) )); } /*Only the O() of y is used*/ GEN rootsof1padic(GEN n, GEN y) { GEN z, r = cgetp(y), p = gel(y,2); pari_sp av = avma; z = rootsof1_Fp(n, p); z = Zp_sqrtnlift(gen_1, n, z, p, precp(y)); affii(z, gel(r,4)); avma = av; return r; } /* Let x = 1 mod p and y := (x-1)/(x+1) = 0 (p). Then * log(x) = log(1+y) - log(1-y) = 2 \sum_{k odd} y^k / k. * palogaux(x) returns the last sum (not multiplied by 2) */ static GEN palogaux(GEN x) { long k,e,pp; GEN y,s,y2, p = gel(x,2); if (equalii(gen_1, gel(x,4))) { long v = valp(x)+precp(x); if (equaliu(p,2)) v--; return zeropadic(p, v); } y = gdiv(gaddgs(x,-1), gaddgs(x,1)); e = valp(y); /* > 0 */ if (e <= 0) { if (!BPSW_psp(p)) pari_err_PRIME("p-adic log",p); pari_err_BUG("log_p"); } pp = e+precp(y); if (equaliu(p,2)) pp--; else { GEN p1; for (p1=utoipos(e); cmpui(pp,p1) > 0; pp++) p1 = mulii(p1, p); pp -= 2; } k = pp/e; if (!odd(k)) k--; y2 = gsqr(y); s = gdivgs(gen_1,k); while (k > 2) { k -= 2; s = gadd(gmul(y2,s), gdivgs(gen_1,k)); } return gmul(s,y); } GEN Qp_log(GEN x) { pari_sp av = avma; GEN y, p = gel(x,2), a = gel(x,4); if (!signe(a)) pari_err_DOMAIN("Qp_log", "argument", "=", gen_0, x); y = leafcopy(x); setvalp(y,0); if (equaliu(p,2)) y = palogaux(gsqr(y)); else if (gequal1(modii(a, p))) y = gmul2n(palogaux(y), 1); else { /* compute log(x^(p-1)) / (p-1) */ GEN mod = gel(y,3), p1 = subis(p,1); gel(y,4) = Fp_pow(a, p1, mod); p1 = diviiexact(subsi(1,mod), p1); /* 1/(p-1) */ y = gmul(palogaux(y), shifti(p1,1)); } return gerepileupto(av,y); } static GEN Qp_exp_safe(GEN x); /*compute the p^e th root of x p-adic, assume x != 0 */ static GEN Qp_sqrtn_ram(GEN x, long e) { pari_sp ltop=avma; GEN a, p = gel(x,2), n = powiu(p,e); long v = valp(x), va; if (v) { long z; v = sdivsi_rem(v, n, &z); if (z) return NULL; x = leafcopy(x); setvalp(x,0); } /*If p = 2, -1 is a root of 1 in U1: need extra check*/ if (equaliu(p, 2) && mod8(gel(x,4)) != 1) return NULL; a = Qp_log(x); va = valp(a) - e; if (va <= 0) { if (signe(gel(a,4))) return NULL; /* all accuracy lost */ a = cvtop(remii(gel(x,4),p), p, 1); } else { setvalp(a, va); /* divide by p^e */ a = Qp_exp_safe(a); if (!a) return NULL; /* n=p^e and a^n=z*x where z is a (p-1)th-root of 1. * Since z^n=z, we have (a/z)^n = x. */ a = gdiv(x, powgi(a,addis(n,-1))); /* = a/z = x/a^(n-1)*/ if (v) setvalp(a,v); } return gerepileupto(ltop,a); } /*compute the nth root of x p-adic p prime with n*/ static GEN Qp_sqrtn_unram(GEN x, GEN n, GEN *zetan) { pari_sp av; GEN Z, a, r, p = gel(x,2); long v = valp(x); if (v) { long z; v = sdivsi_rem(v,n,&z); if (z) return NULL; } r = cgetp(x); setvalp(r,v); Z = NULL; /* -Wall */ if (zetan) Z = cgetp(x); av = avma; a = Fp_sqrtn(gel(x,4), n, p, zetan); if (!a) return NULL; affii(Zp_sqrtnlift(gel(x,4), n, a, p, precp(x)), gel(r,4)); if (zetan) { affii(Zp_sqrtnlift(gen_1, n, *zetan, p, precp(x)), gel(Z,4)); *zetan = Z; } avma = av; return r; } GEN Qp_sqrtn(GEN x, GEN n, GEN *zetan) { pari_sp av, tetpil; GEN q, p; long e; if (equaliu(n, 2)) { if (zetan) *zetan = gen_m1; if (signe(n) < 0) x = ginv(x); return Qp_sqrt(x); } av = avma; p = gel(x,2); if (!signe(gel(x,4))) { if (signe(n) < 0) pari_err_INV("Qp_sqrtn", x); q = divii(addis(n, valp(x)-1), n); if (zetan) *zetan = gen_1; avma = av; return zeropadic(p, itos(q)); } /* treat the ramified part using logarithms */ e = Z_pvalrem(n, p, &q); if (e) { x = Qp_sqrtn_ram(x,e); if (!x) return NULL; } if (is_pm1(q)) { /* finished */ if (signe(q) < 0) x = ginv(x); x = gerepileupto(av, x); if (zetan) *zetan = (e && equaliu(p, 2))? gen_m1 /*-1 in Q_2*/ : gen_1; return x; } tetpil = avma; /* use hensel lift for unramified case */ x = Qp_sqrtn_unram(x, q, zetan); if (!x) return NULL; if (zetan) { GEN *gptr[2]; if (e && equaliu(p, 2))/*-1 in Q_2*/ { tetpil = avma; x = gcopy(x); *zetan = gneg(*zetan); } gptr[0] = &x; gptr[1] = zetan; gerepilemanysp(av,tetpil,gptr,2); return x; } return gerepile(av,tetpil,x); } GEN sqrtnint(GEN a, long n) { pari_sp ltop = avma; GEN x, b, q; long s, k, e; const ulong nm1 = n - 1; if (typ(a) != t_INT) pari_err_TYPE("sqrtnint",a); if (n <= 0) pari_err_DOMAIN("sqrtnint", "n", "<=", gen_0, stoi(n)); if (n == 1) return icopy(a); s = signe(a); if (s < 0) pari_err_DOMAIN("sqrtnint", "x", "<", gen_0, a); if (!s) return gen_0; if (lgefint(a) == 3) return utoi(usqrtn(itou(a), n)); e = expi(a); k = e/(2*n); if (k == 0) { long flag; if (n > e) {avma = ltop; return gen_1;} flag = cmpii(a, powuu(3, n)); avma = ltop; return (flag < 0) ? gen_2: stoi(3); } if (e < n*(BITS_IN_LONG - 1)) { ulong s, xs, qs; s = 1 + e/n; xs = 1UL << s; qs = itou(shifti(a, -nm1*s)); while (qs < xs) { xs -= (xs - qs + nm1)/n; q = divii(a, powuu(xs, nm1)); if (lgefint(q) > 3) break; qs = itou(q); } return utoi(xs); } b = addsi(1, shifti(a, -n*k)); x = shifti(addsi(1, sqrtnint(b, n)), k); q = divii(a, powiu(x, nm1)); while (cmpii(q, x) < 0) /* a priori one iteration, no GC necessary */ { x = subii(x, divis(addsi(nm1, subii(x, q)), n)); q = divii(a, powiu(x, nm1)); } return gerepileuptoleaf(ltop, x); } ulong usqrtn(ulong a, ulong n) { ulong x, s, q; const ulong nm1 = n - 1; if (!n) pari_err_DOMAIN("sqrtnint", "n", "=", gen_0, utoi(n)); if (n == 1 || a == 0) return a; s = 1 + expu(a)/n; x = 1UL << s; q = (nm1*s >= BITS_IN_LONG)? 0: a >> (nm1*s); while (q < x) { ulong X; x -= (x - q + nm1)/n; X = upowuu(x, nm1); q = X? a/X: 0; } return x; } GEN gsqrtn(GEN x, GEN n, GEN *zetan, long prec) { long i, lx, tx; pari_sp av; GEN y, z; if (typ(n)!=t_INT) pari_err_TYPE("sqrtn",n); if (!signe(n)) pari_err_DOMAIN("sqrtn", "n", "=", gen_0, n); if (is_pm1(n)) { if (zetan) *zetan = gen_1; return (signe(n) > 0)? gcopy(x): ginv(x); } if (zetan) *zetan = gen_0; tx = typ(x); if (is_matvec_t(tx)) { y = cgetg_copy(x, &lx); for (i=1; i= 0 */ if (m < (-a) * 0.1) m = 0; /* not worth it */ L = l + nbits2extraprec(m); /* Multiplication is quadratic in this range (l is small, otherwise we * use logAGM + Newton). Set Y = 2^(-e-a) x, compute truncated series * sum x^k/k!: this costs roughly * m b^2 + sum_{k <= n} (k e + BITS_IN_LONG)^2 * bit operations with |x| < 2^(1+a), |Y| < 2^(1-e) , m = e+a and b bits of * accuracy needed, so * B := (b / 3 + BITS_IN_LONG + BITS_IN_LONG^2 / b) ~ m(m-a) * we want b ~ 3 m (m-a) or m~b+a hence * m = min( a/2 + sqrt(a^2/4 + B), b + a ) * NB: e ~ (b/3)^(1/2) as b -> oo * * Truncate the sum at k = n (>= 1), the remainder is * sum_{k >= n+1} Y^k / k! < Y^(n+1) / (n+1)! (1-Y) < Y^(n+1) / n! * We want Y^(n+1) / n! <= Y 2^-b, hence -n log_2 |Y| + log_2 n! >= b * log n! ~ (n + 1/2) log(n+1) - (n+1) + log(2Pi)/2, * error bounded by 1/6(n+1) <= 1/12. Finally, we want * n (-1/log(2) -log_2 |Y| + log_2(n+1)) >= b */ b += m; d = m-dbllog2(x)-1/LOG2; /* ~ -log_2 Y - 1/log(2) */ n = (long)(b / d); if (n > 1) n = (long)(b / (d + log2((double)n+1))); /* log~constant in small ranges */ while (n*(d+log2((double)n+1)) < b) n++; /* expect few corrections */ X = rtor(x,L); shiftr_inplace(X, -m); setsigne(X, 1); if (n == 1) p2 = X; else { long s = 0, l1 = nbits2prec((long)(d + n + 16)); GEN unr = real_1(L); pari_sp av2; p2 = cgetr(L); av2 = avma; for (i=n; i>=2; i--, avma = av2) { /* compute X^(n-1)/n! + ... + X/2 + 1 */ GEN p1, p3; setprec(X,l1); p3 = divru(X,i); l1 += dvmdsBIL(s - expo(p3), &s); if (l1>L) l1=L; setprec(unr,l1); p1 = addrr_sign(unr,1, i == n? p3: mulrr(p3,p2),1); setprec(p2,l1); affrr(p1,p2); /* p2 <- 1 + (X/i)*p2 */ } setprec(X,L); p2 = mulrr(X,p2); } for (i=1; i<=m; i++) { if (realprec(p2) > L) setprec(p2,L); p2 = mulrr(p2, addsr(2,p2)); } affrr_fixlg(p2,y); avma = av; return y; } GEN mpexpm1(GEN x) { long sx = signe(x); GEN y, z; pari_sp av; if (!sx) return real_0_bit(expo(x)); if (sx > 0) return exp1r_abs(x); /* compute exp(x) * (1 - exp(-x)) */ av = avma; y = exp1r_abs(x); z = addsr(1, y); setsigne(z, -1); return gerepileupto(av, divrr(y, z)); } GEN gexpm1(GEN x, long prec) { switch(typ(x)) { case t_REAL: return mpexpm1(x); case t_COMPLEX: return cxexpm1(x,prec); } return trans_eval("expm1",gexpm1,x,prec); } /********************************************************************/ /** **/ /** EXP(X) **/ /** **/ /********************************************************************/ /* centermod(x, log(2)), set *sh to the quotient */ static GEN modlog2(GEN x, long *sh) { double d = rtodbl(x); long q = (long) ((fabs(d) + (LOG2/2))/LOG2); if (d > LOG2 * LONG_MAX) pari_err_OVERFLOW("expo()"); /* avoid overflow in q */ if (d < 0) q = -q; *sh = q; if (q) { long l = realprec(x) + 1; x = subrr(rtor(x,l), mulsr(q, mplog2(l))); if (!signe(x)) return NULL; } return x; } static GEN mpexp_basecase(GEN x) { pari_sp av = avma; long sh, l = realprec(x); GEN y, z; y = modlog2(x, &sh); if (!y) { avma = av; return real2n(sh, l); } z = addsr(1, exp1r_abs(y)); if (signe(y) < 0) z = invr(z); if (sh) { shiftr_inplace(z, sh); if (realprec(z) > l) z = rtor(z, l); /* spurious precision increase */ } #ifdef DEBUG { GEN t = mplog(z), u = divrr(subrr(x, t),x); if (signe(u) && expo(u) > 5-prec2nbits(minss(l,realprec(t)))) pari_err_BUG("exp"); } #endif return gerepileuptoleaf(av, z); /* NOT affrr, precision often increases */ } GEN mpexp(GEN x) { const long s = 6; /*Initial steps using basecase*/ long i, p, l = realprec(x), sh; GEN a, t, z; ulong mask; if (l <= maxss(EXPNEWTON_LIMIT, (1L<>= 1; } a = mpexp_basecase(rtor(x, nbits2prec(p))); x = addrs(x,1); if (realprec(x) < l+EXTRAPRECWORD) x = rtor(x, l+EXTRAPRECWORD); a = rtor(a, l+EXTRAPRECWORD); /*append 0s */ t = NULL; for(;;) { p <<= 1; if (mask & 1) p--; mask >>= 1; setprec(x, nbits2prec(p)); setprec(a, nbits2prec(p)); t = mulrr(a, subrr(x, logr_abs(a))); /* a (x - log(a)) */ if (mask == 1) break; affrr(t, a); avma = (pari_sp)a; } affrr(t,z); if (sh) shiftr_inplace(z, sh); avma = (pari_sp)z; return z; } static long Qp_exp_prec(GEN x) { long k, e = valp(x), n = e + precp(x); GEN p = gel(x,2); int is2 = equaliu(p,2); if (e < 1 || (e == 1 && is2)) return -1; if (is2) { n--; e--; k = n/e; if (n%e == 0) k--; } else { /* e > 0, n > 0 */ GEN r, t = subis(p, 1); k = itos(dvmdii(subis(muliu(t,n), 1), subis(muliu(t,e), 1), &r)); if (!signe(r)) k--; } return k; } static GEN Qp_exp_safe(GEN x) { long k; pari_sp av; GEN y; if (gequal0(x)) return gaddgs(x,1); k = Qp_exp_prec(x); if (k < 0) return NULL; av = avma; for (y=gen_1; k; k--) y = gaddsg(1, gdivgs(gmul(y,x), k)); return gerepileupto(av, y); } GEN Qp_exp(GEN x) { GEN y = Qp_exp_safe(x); if (!y) pari_err_DOMAIN("gexp(t_PADIC)","argument","",gen_0,x); return y; } static GEN cos_p(GEN x) { long k; pari_sp av; GEN x2, y; if (gequal0(x)) return gaddgs(x,1); k = Qp_exp_prec(x); if (k < 0) return NULL; av = avma; x2 = gsqr(x); if (k & 1) k--; for (y=gen_1; k; k-=2) { GEN t = gdiv(gmul(y,x2), muluu(k, k-1)); y = gsubsg(1, t); } return gerepileupto(av, y); } static GEN sin_p(GEN x) { long k; pari_sp av; GEN x2, y; if (gequal0(x)) return gcopy(x); k = Qp_exp_prec(x); if (k < 0) return NULL; av = avma; x2 = gsqr(x); if (k & 1) k--; for (y=gen_1; k; k-=2) { GEN t = gdiv(gmul(y,x2), muluu(k, k+1)); y = gsubsg(1, t); } return gerepileupto(av, gmul(y, x)); } static GEN cxexp(GEN x, long prec) { GEN r,p1,p2, y = cgetg(3,t_COMPLEX); pari_sp av = avma, tetpil; r = gexp(gel(x,1),prec); if (gequal0(r)) { gel(y,1) = r; gel(y,2) = r; return y; } gsincos(gel(x,2),&p2,&p1,prec); tetpil = avma; gel(y,1) = gmul(r,p1); gel(y,2) = gmul(r,p2); gerepilecoeffssp(av,tetpil,y+1,2); return y; } /* given a t_SER x^v s(x), with s(0) != 0, return x^v(s - s(0)), shallow */ GEN serchop0(GEN s) { long i, l = lg(s); GEN y; if (l == 2) return s; y = cgetg(l, t_SER); y[1] = s[1]; gel(y,2) = gen_0; for (i=3; i =3 && isrationalzero(gel(x,mi))) mi--; mi += ex-2; y[1] = evalsigne(1) | _evalvalp(0) | evalvarn(varn(x)); /* zd[i] = coefficient of X^i in z */ xd = x+2-ex; yd = y+2; ly -= 2; gel(yd,0) = gen_1; for (i=1; i= L); } /* assume x > 0 */ static GEN agm1r_abs(GEN x) { long l = realprec(x), L = 5-prec2nbits(l); GEN a1, b1, y = cgetr(l); pari_sp av = avma; a1 = addrr(real_1(l), x); shiftr_inplace(a1, -1); b1 = sqrtr_abs(x); while (agmr_gap(a1,b1,L)) { GEN a = a1; a1 = addrr(a,b1); shiftr_inplace(a1, -1); b1 = sqrtr_abs(mulrr(a,b1)); } affrr_fixlg(a1,y); avma = av; return y; } struct agmcx_gap_t { long L, ex, cnt; }; static void agmcx_init(GEN x, long *prec, struct agmcx_gap_t *S) { long l = precision(x); if (l) *prec = l; S->L = 1-prec2nbits(*prec); S->cnt = 0; S->ex = LONG_MAX; } static long agmcx_a_b(GEN x, GEN *a1, GEN *b1, long prec) { long rotate = 0; if (gsigne(real_i(x))<0) { /* Rotate by +/-Pi/2, so that the choice of the principal square * root gives the optimal AGM. So a1 = +/-I*a1, b1=sqrt(-x). */ if (gsigne(imag_i(x))<0) { *a1=mulcxI(*a1); rotate=-1; } else { *a1=mulcxmI(*a1); rotate=1; } x = gneg(x); } *b1 = gsqrt(x, prec); return rotate; } /* return 0 if we must stop the AGM loop (a=b or a ~ b), 1 otherwise */ static int agmcx_gap(GEN a, GEN b, struct agmcx_gap_t *S) { GEN d = gsub(b, a); long ex = S->ex; S->ex = gexpo(d); if (gequal0(d) || S->ex - gexpo(b) < S->L) return 0; /* if (S->ex >= ex) we're no longer making progress; twice in a row */ if (S->ex < ex) S->cnt = 0; else if (S->cnt++) return 0; return 1; } static GEN agm1cx(GEN x, long prec) { struct agmcx_gap_t S; GEN a1, b1; pari_sp av = avma; long rotate; agmcx_init(x, &prec, &S); a1 = gtofp(gmul2n(gadd(real_1(prec), x), -1), prec); rotate = agmcx_a_b(x, &a1, &b1, prec); while (agmcx_gap(a1,b1,&S)) { GEN a = a1; a1 = gmul2n(gadd(a,b1),-1); b1 = gsqrt(gmul(a,b1), prec); } if (rotate) a1 = rotate>0 ? mulcxI(a1):mulcxmI(a1); return gerepilecopy(av,a1); } GEN zellagmcx(GEN a0, GEN b0, GEN r, GEN t, long prec) { struct agmcx_gap_t S; pari_sp av = avma; GEN x = gdiv(a0, b0), a1, b1; long rotate; agmcx_init(x, &prec, &S); a1 = gtofp(gmul2n(gadd(real_1(prec), x), -1), prec); r = gsqrt(gdiv(gmul(a1,gaddgs(r, 1)),gadd(r, x)), prec); t = gmul(r, t); rotate = agmcx_a_b(x, &a1, &b1, prec); while (agmcx_gap(a1,b1,&S)) { GEN a = a1, b = b1; a1 = gmul2n(gadd(a,b),-1); b1 = gsqrt(gmul(a,b), prec); r = gsqrt(gdiv(gmul(a1,gaddgs(r, 1)),gadd(gmul(b, r), a )), prec); t = gmul(r, t); } if (rotate) a1 = rotate>0 ? mulcxI(a1):mulcxmI(a1); a1 = gmul(a1, b0); t = gatan(gdiv(a1,t), prec); /* send t to the fundamental domain if necessary */ if (gsigne(real_i(t))<0) t = gadd(t, mppi(prec)); return gerepileupto(av,gdiv(t,a1)); } /* agm(1,x) */ static GEN agm1(GEN x, long prec) { GEN p1, a1, b1, y; long l, l2, ep; pari_sp av; if (gequal0(x)) return gcopy(x); switch(typ(x)) { case t_INT: if (!is_pm1(x)) break; return (signe(x) > 0)? real_1(prec): real_0(prec); case t_REAL: return signe(x) > 0? agm1r_abs(x): agm1cx(x, prec); case t_COMPLEX: if (gequal0(gel(x,2))) return agm1(gel(x,1), prec); return agm1cx(x, prec); case t_PADIC: av = avma; a1 = x; b1 = gen_1; l = precp(x); do { GEN a = a1; a1 = gmul2n(gadd(a,b1),-1); 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); } } while (ep= l2)); return gerepilecopy(av,a1); } return trans_eval("agm",agm1,x,prec); } GEN agm(GEN x, GEN y, long prec) { pari_sp av; if (is_matvec_t(typ(y))) { if (is_matvec_t(typ(x))) pari_err_TYPE2("agm",x,y); swap(x, y); } if (gequal0(y)) return gcopy(y); av = avma; return gerepileupto(av, gmul(y, agm1(gdiv(x,y), prec))); } /********************************************************************/ /** **/ /** LOG(X) **/ /** **/ /********************************************************************/ /* atanh(u/v) using binary splitting */ static GEN atanhQ_split(ulong u, ulong v, long prec) { long i, nmax; GEN u2 = sqru(u), v2 = sqru(v); double d = ((double)v) / u; struct abpq_res R; struct abpq A; /* satisfies (2n+1) (v/u)^2n > 2^bitprec */ nmax = bit_accuracy(prec) / (2*log2(d)); abpq_init(&A, nmax); A.a[0] = A.b[0] = gen_1; A.p[0] = utoipos(u); A.q[0] = utoipos(v); for (i = 1; i <= nmax; i++) { A.a[i] = gen_1; A.b[i] = utoipos((i<<1)+1); A.p[i] = u2; A.q[i] = v2; } abpq_sum(&R, 0, nmax, &A); return rdivii(R.T, mulii(R.B,R.Q),prec); } /* log(2) = 10*atanh(1/17)+4*atanh(13/499) */ static GEN log2_split(long prec) { GEN u = atanhQ_split(1, 17, prec); GEN v = atanhQ_split(13, 499, prec); shiftr_inplace(v, 2); return addrr(mulur(10, u), v); } #if 0 /* slower ! */ /* cf logagmr_abs(). Compute Pi/2agm(1, 4/2^n) ~ log(2^n) = n log(2) */ static GEN log2_agm(long prec) { long n = prec2nbits(prec) >> 1; GEN y = divrr(Pi2n(-1, prec), agm1r_abs( real2n(2 - n, prec) )); return divru(y, n); } #endif GEN constlog2(long prec) { pari_sp av; GEN tmp; if (glog2 && realprec(glog2) >= prec) return glog2; tmp = cgetr_block(prec); av = avma; affrr(log2_split(prec+EXTRAPRECWORD), tmp); swap_clone(&glog2,tmp); avma = av; return glog2; } GEN mplog2(long prec) { return rtor(constlog2(prec), prec); } static GEN logagmr_abs(GEN q) { long prec = realprec(q), lim, e = expo(q); GEN z, y, Q, _4ovQ; pari_sp av; if (absrnz_equal2n(q)) return e? mulsr(e, mplog2(prec)): real_0(prec); z = cgetr(prec); av = avma; incrprec(prec); lim = prec2nbits(prec) >> 1; Q = rtor(q,prec); shiftr_inplace(Q,lim-e); setsigne(Q,1); _4ovQ = invr(Q); shiftr_inplace(_4ovQ, 2); /* 4/Q */ /* Pi / 2agm(1, 4/Q) ~ log(Q), q = Q * 2^(e-lim) */ y = divrr(Pi2n(-1, prec), agm1r_abs(_4ovQ)); y = addrr(y, mulsr(e - lim, mplog2(prec))); affrr_fixlg(y, z); avma = av; return z; } /*return log(|x|), assuming x != 0 */ GEN logr_abs(GEN X) { pari_sp ltop; long EX, L, m, k, a, b, l = realprec(X); GEN z, x, y; ulong u; double d; if (l > LOGAGM_LIMIT) return logagmr_abs(X); /* Assuming 1 < x < 2, we want delta = x-1, 1-x/2, 1-1/x, or 2/x-1 small. * We have 2/x-1 > 1-x/2, 1-1/x < x-1. So one should be choosing between * 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]; k = 2; if (u > (~0UL / 3) * 2) { /* choose 1-x/2 */ EX++; u = ~u; while (!u && ++k < l) { u = (ulong)X[k]; u = ~u; } } else { /* choose x - 1 */ u &= ~HIGHBIT; /* u - HIGHBIT, assuming HIGHBIT set */ while (!u && ++k < l) u = (ulong)X[k]; } if (k == l) return EX? mulsr(EX, mplog2(l)): real_0(l); z = cgetr(EX? l: l - (k-2)); ltop = avma; a = prec2nbits(k) + bfffo(u); /* ~ -log2 |1-x| */ /* Multiplication is quadratic in this range (l is small, otherwise we * use AGM). Set Y = x^(1/2^m), y = (Y - 1) / (Y + 1) and compute truncated * series sum y^(2k+1)/(2k+1): the costs is less than * m b^2 + sum_{k <= n} ((2k+1) e + BITS_IN_LONG)^2 * bit operations with |x-1| < 2^(1-a), |Y| < 2^(1-e) , m = e-a and b bits of * accuracy needed (+ BITS_IN_LONG since bit accuracies increase by * increments of BITS_IN_LONG), so * 4n^3/3 e^2 + n^2 2e BITS_IN_LONG+ n BITS_IN_LONG ~ m b^2, with n ~ b/2e * or b/6e + BITS_IN_LONG/2e + BITS_IN_LONG/2be ~ m * B := (b / 6 + BITS_IN_LONG/2 + BITS_IN_LONG^2 / 2b) ~ m(m+a) * m = min( -a/2 + sqrt(a^2/4 + B), b - a ) * NB: e ~ (b/6)^(1/2) as b -> oo */ L = l+1; b = prec2nbits(L - (k-2)); /* take loss of accuracy into account */ /* instead of the above pessimistic estimate for the cost of the sum, use * optimistic estimate (BITS_IN_LONG -> 0) */ d = -a/2.; m = (long)(d + sqrt(d*d + b/6)); /* >= 0 */ if (m > b-a) m = b-a; if (m < 0.2*a) m = 0; else L += nbits2extraprec(m); x = rtor(X,L); setsigne(x,1); shiftr_inplace(x,-EX); /* 2/3 < x < 4/3 */ for (k=1; k<=m; k++) x = sqrtr_abs(x); y = divrr(subrs(x,1), addrs(x,1)); /* = (x-1) / (x+1), close to 0 */ L = realprec(y); /* should be ~ l+1 - (k-2) */ /* log(x) = log(1+y) - log(1-y) = 2 sum_{k odd} y^k / k * Truncate the sum at k = 2n+1, the remainder is * 2 sum_{k >= 2n+3} y^k / k < 2y^(2n+3) / (2n+3)(1-y) < y^(2n+3) * We want y^(2n+3) < y 2^(-prec2nbits(L)), hence * n+1 > -prec2nbits(L) /-log_2(y^2) */ d = -2*dbllog2r(y); /* ~ -log_2(y^2) */ k = (long)(2*(prec2nbits(L) / d)); k |= 1; if (k >= 3) { GEN S, T, y2 = sqrr(y), unr = real_1(L); pari_sp av = avma; long s = 0, incs = (long)d, l1 = nbits2prec((long)d); S = x; setprec(S, l1); setprec(unr,l1); affrr(divru(unr,k), S); /* destroy x, not needed anymore */ for (k -= 2;; k -= 2) /* k = 2n+1, ..., 1 */ { /* S = y^(2n+1-k)/(2n+1) + ... + 1 / k */ setprec(y2, l1); T = mulrr(S,y2); if (k == 1) break; l1 += dvmdsBIL(s + incs, &s); if (l1>L) l1=L; setprec(S, l1); setprec(unr,l1); affrr(addrr(divru(unr, k), T), S); avma = av; } /* k = 1 special-cased for eficiency */ y = mulrr(y, addsr(1,T)); /* = log(X)/2 */ } shiftr_inplace(y, m + 1); if (EX) y = addrr(y, mulsr(EX, mplog2(l+1))); affrr_fixlg(y, z); avma = ltop; return z; } /* assume Im(q) != 0 and precision(q) >= prec. Compute log(q) with accuracy * prec [disregard input accuracy] */ GEN logagmcx(GEN q, long prec) { GEN z = cgetc(prec), y, Q, a, b; long lim, e, ea, eb; pari_sp av = avma; int neg = 0; incrprec(prec); if (gsigne(gel(q,1)) < 0) { q = gneg(q); neg = 1; } lim = prec2nbits(prec) >> 1; Q = gtofp(q, prec); a = gel(Q,1); b = gel(Q,2); if (gequal0(a)) { affrr_fixlg(logr_abs(b), gel(z,1)); y = Pi2n(-1, prec); if (signe(b) < 0) setsigne(y, -1); affrr_fixlg(y, gel(z,2)); avma = av; return z; } ea = expo(a); eb = expo(b); e = ea <= eb ? lim - eb : lim - ea; shiftr_inplace(a, e); shiftr_inplace(b, e); /* Pi / 2agm(1, 4/Q) ~ log(Q), q = Q * 2^e */ y = gdiv(Pi2n(-1, prec), agm1cx( gdivsg(4, Q), prec )); a = gel(y,1); b = gel(y,2); a = addrr(a, mulsr(-e, mplog2(prec))); if (realprec(a) <= LOWDEFAULTPREC) a = real_0_bit(expo(a)); if (neg) b = gsigne(b) <= 0? gadd(b, mppi(prec)) : gsub(b, mppi(prec)); affrr_fixlg(a, gel(z,1)); affrr_fixlg(b, gel(z,2)); avma = av; return z; } GEN mplog(GEN x) { if (signe(x)<=0) pari_err_DOMAIN("mplog", "argument", "<=", gen_0, x); return logr_abs(x); } /* pe = p^e, p prime, 0 < x < pe a t_INT coprime to p. Return the (p-1)-th * root of 1 in (Z/pe)^* congruent to x mod p, resp x mod 4 if p = 2. * Simplified form of Zp_sqrtnlift: 1/(p-1) is trivial to compute */ GEN Zp_teichmuller(GEN x, GEN p, long e, GEN pe) { GEN q, z, p1; pari_sp av; ulong mask; if (equaliu(p,2)) return (mod4(x) & 2)? subiu(pe,1): gen_1; if (e == 1) return icopy(x); av = avma; p1 = subiu(p, 1); mask = quadratic_prec_mask(e); q = p; z = remii(x, p); while (mask > 1) { /* Newton iteration solving z^{1 - p} = 1, z = x (mod p) */ GEN w, t, qold = q; if (mask <= 3) /* last iteration */ q = pe; else { q = sqri(q); if (mask & 1) q = diviiexact(q, p); } mask >>= 1; /* q <= qold^2 */ if (lgefint(q) == 3) { ulong Z = (ulong)z[2], Q = (ulong)q[2], P1 = (ulong)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); z = utoi(Z); } else { w = diviiexact(addsi(-1,qold),p1); /* -1/(p-1) + O(qold) */ t = Fp_mul(w, subis(Fp_pow(z,p1,q), 1), q); z = Fp_mul(z, addsi(1,t), q); } } return gerepileuptoint(av, z); } GEN teich(GEN x) { GEN p, q, y, z; long n; if (typ(x)!=t_PADIC) pari_err_TYPE("teichmuller",x); z = gel(x,4); if (!signe(z)) return gcopy(x); p = gel(x,2); q = gel(x,3); n = precp(x); y = cgetg(5,t_PADIC); y[1] = evalprecp(n) | _evalvalp(0); gel(y,2) = icopy(p); gel(y,3) = icopy(q); gel(y,4) = Zp_teichmuller(z, p, n, q); return y; } GEN glog(GEN x, long prec) { pari_sp av, tetpil; GEN y, p1; long l; switch(typ(x)) { case t_REAL: if (signe(x) >= 0) { if (!signe(x)) pari_err_DOMAIN("log", "argument", "=", gen_0, x); return logr_abs(x); } retmkcomplex(logr_abs(x), mppi(realprec(x))); case t_FRAC: { GEN a, b; long e1, e2; av = avma; a = gel(x,1); b = gel(x,2); e1 = expi(subii(a,b)); e2 = expi(b); if (e2 > e1) prec += nbits2nlong(e2 - e1); x = fractor(x, prec); return gerepileupto(av, glog(x, prec)); } case t_COMPLEX: if (ismpzero(gel(x,2))) return glog(gel(x,1), prec); l = precision(x); if (l > prec) prec = l; if (prec >= LOGAGMCX_LIMIT) return logagmcx(x, prec); y = cgetg(3,t_COMPLEX); gel(y,2) = garg(x,prec); av = avma; p1 = glog(cxnorm(x),prec); tetpil = avma; gel(y,1) = gerepile(av,tetpil,gmul2n(p1,-1)); return y; case t_PADIC: return Qp_log(x); default: av = avma; if (!(y = toser_i(x))) break; if (!signe(y)) pari_err_DOMAIN("log", "argument", "=", gen_0, x); if (valp(y)) pari_err_DOMAIN("log", "series valuation", "!=", gen_0, x); p1 = integser(gdiv(derivser(y), y)); /* log(y)' = y'/y */ if (!gequal1(gel(y,2))) p1 = gadd(p1, glog(gel(y,2),prec)); return gerepileupto(av, p1); } return trans_eval("log",glog,x,prec); } /********************************************************************/ /** **/ /** SINE, COSINE **/ /** **/ /********************************************************************/ /* Reduce x0 mod Pi/2 to x in [-Pi/4, Pi/4]. Return cos(x)-1 */ static GEN mpcosm1(GEN x, long *ptmod8) { long a = expo(x), l = realprec(x), b, L, i, n, m, B; GEN y, p2, x2; double d; n = 0; if (a >= 0) { long p; GEN q; if (a > 30) { GEN z, pitemp = Pi2n(-2, nbits2prec(a + 32)); z = addrr(x,pitemp); /* = x + Pi/4 */ if (expo(z) >= bit_prec(z) + 3) pari_err_PREC("mpcosm1"); shiftr_inplace(pitemp, 1); 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)); p = l; } if (signe(q)) { x = subrr(x, mulir(q, Pi2n(-1,p))); /* x mod Pi/2 */ a = expo(x); if (!signe(x) && a >= 0) pari_err_PREC("mpcosm1"); n = mod4(q); if (n && signe(q) < 0) n = 4 - n; } } /* a < 0 */ b = signe(x); *ptmod8 = (b < 0)? 4 + n: n; if (!b) return real_0_bit((expo(x)<<1) - 1); b = prec2nbits(l); if (b + (a<<1) <= 0) { y = sqrr(x); shiftr_inplace(y, -1); setsigne(y, -1); return y; } y = cgetr(l); B = b/6 + BITS_IN_LONG + (BITS_IN_LONG*BITS_IN_LONG/2)/ b; d = a/2.; m = (long)(d + sqrt(d*d + B)); /* >= 0 ,*/ if (m < (-a) * 0.1) m = 0; /* not worth it */ L = l + nbits2extraprec(m); b += m; d = 2.0 * (m-dbllog2r(x)-1/LOG2); /* ~ 2( - log_2 Y - 1/log(2) ) */ n = (long)(b / d); if (n > 1) n = (long)(b / (d + log2((double)n+1))); /* log~constant in small ranges */ while (n*(d+log2((double)n+1)) < b) n++; /* expect few corrections */ /* Multiplication is quadratic in this range (l is small, otherwise we * use logAGM + Newton). Set Y = 2^(-e-a) x, compute truncated series * sum Y^2k/(2k)!: this costs roughly * m b^2 + sum_{k <= n} (2k e + BITS_IN_LONG)^2 * ~ floor(b/2e) b^2 / 3 + m b^2 * bit operations with |x| < 2^(1+a), |Y| < 2^(1-e) , m = e+a and b bits of * accuracy needed, so * B := ( b / 6 + BITS_IN_LONG + BITS_IN_LONG^2 / 2b) ~ m(m-a) * we want b ~ 6 m (m-a) or m~b+a hence * m = min( a/2 + sqrt(a^2/4 + b/6), b/2 + a ) * NB1: e ~ (b/6)^(1/2) or b/2. * NB2: We use b/4 instead of b/6 in the formula above: hand-optimized... * * Truncate the sum at k = n (>= 1), the remainder is * < sum_{k >= n+1} Y^2k / 2k! < Y^(2n+2) / (2n+2)!(1-Y^2) < Y^(2n+2)/(2n+1)! * We want ... <= Y^2 2^-b, hence -2n log_2 |Y| + log_2 (2n+1)! >= b * log n! ~ (n + 1/2) log(n+1) - (n+1) + log(2Pi)/2, * error bounded by 1/6(n+1) <= 1/12. Finally, we want * 2n (-1/log(2) - log_2 |Y| + log_2(2n+2)) >= b */ x = rtor(x, L); shiftr_inplace(x, -m); setsigne(x, 1); x2 = sqrr(x); if (n == 1) { p2 = x2; shiftr_inplace(p2, -1); setsigne(p2, -1); } /*-Y^2/2*/ else { GEN unr = real_1(L); pari_sp av; long s = 0, l1 = nbits2prec((long)(d + n + 16)); p2 = cgetr(L); av = avma; for (i=n; i>=2; i--) { GEN p1; setprec(x2,l1); p1 = divrunu(x2, 2*i-1); l1 += dvmdsBIL(s - expo(p1), &s); if (l1>L) l1=L; if (i != n) p1 = mulrr(p1,p2); setprec(unr,l1); p1 = addrr_sign(unr,1, p1,-signe(p1)); setprec(p2,l1); affrr(p1,p2); avma = av; } shiftr_inplace(p2, -1); togglesign(p2); /* p2 := -p2/2 */ setprec(x2,L); p2 = mulrr(x2,p2); } /* Now p2 = sum {1<= i <=n} (-1)^i x^(2i) / (2i)! ~ cos(x) - 1 */ for (i=1; i<=m; i++) { /* p2 = cos(x)-1 --> cos(2x)-1 */ p2 = mulrr(p2, addsr(2,p2)); shiftr_inplace(p2, 1); if ((i & 31) == 0) p2 = gerepileuptoleaf((pari_sp)y, p2); } affrr_fixlg(p2,y); return y; } /* sqrt (|1 - (1+x)^2|) = sqrt(|x*(x+2)|). Sends cos(x)-1 to |sin(x)| */ static GEN mpaut(GEN x) { pari_sp av = avma; GEN t = mulrr(x, addsr(2,x)); /* != 0 */ if (!signe(t)) return real_0_bit(expo(t) >> 1); return gerepileuptoleaf(av, sqrtr_abs(t)); } /********************************************************************/ /** COSINE **/ /********************************************************************/ GEN mpcos(GEN x) { long mod8; pari_sp av; GEN y,p1; if (!signe(x)) { long l = nbits2prec(-expo(x)); if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC; return real_1(l); } av = avma; p1 = mpcosm1(x,&mod8); switch(mod8) { case 0: case 4: y = addsr(1,p1); break; case 1: case 7: y = mpaut(p1); togglesign(y); break; case 2: case 6: y = subsr(-1,p1); break; default: y = mpaut(p1); break; /* case 3: case 5: */ } return gerepileuptoleaf(av, y); } /* convert INT or FRAC to REAL, which is later reduced mod 2Pi : avoid * cancellation */ static GEN tofp_safe(GEN x, long prec) { return (typ(x) == t_INT || gexpo(x) > 0)? gadd(x, real_0(prec)) : fractor(x, prec); } GEN gcos(GEN x, long prec) { pari_sp av; GEN r, u, v, y, u1, v1; long i; switch(typ(x)) { case t_REAL: return mpcos(x); case t_COMPLEX: if (isintzero(gel(x,1))) return gcosh(gel(x,2), prec); i = precision(x); if (!i) i = prec; y = cgetc(i); av = avma; r = gexp(gel(x,2),prec); v1 = gmul2n(addrr(invr(r),r), -1); /* = cos(I*Im(x)) */ u1 = subrr(v1, r); /* = - I*sin(I*Im(x)) */ gsincos(gel(x,1),&u,&v,prec); affrr_fixlg(gmul(v1,v), gel(y,1)); affrr_fixlg(gmul(u1,u), gel(y,2)); avma = av; return y; case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mpcos(tofp_safe(x,prec)), y); avma = av; return y; case t_PADIC: y = cos_p(x); if (!y) pari_err_DOMAIN("gcos(t_PADIC)","argument","",gen_0,x); return y; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepileupto(av, gaddsg(1,y)); if (valp(y) < 0) pari_err_DOMAIN("cos","valuation", "<", gen_0, x); gsincos(y,&u,&v,prec); return gerepilecopy(av,v); } return trans_eval("cos",gcos,x,prec); } /********************************************************************/ /** SINE **/ /********************************************************************/ GEN mpsin(GEN x) { long mod8; pari_sp av; GEN y,p1; if (!signe(x)) return real_0_bit(expo(x)); av = avma; p1 = mpcosm1(x,&mod8); switch(mod8) { case 0: case 6: y=mpaut(p1); break; case 1: case 5: y=addsr(1,p1); break; case 2: case 4: y=mpaut(p1); togglesign(y); break; default: y=subsr(-1,p1); break; /* case 3: case 7: */ } return gerepileuptoleaf(av, y); } GEN gsin(GEN x, long prec) { pari_sp av; GEN r, u, v, y, v1, u1; long i; switch(typ(x)) { case t_REAL: return mpsin(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0,gsinh(gel(x,2),prec)); i = precision(x); if (!i) i = prec; y = cgetc(i); av = avma; r = gexp(gel(x,2),prec); v1 = gmul2n(addrr(invr(r),r), -1); /* = cos(I*Im(x)) */ u1 = subrr(r, v1); /* = I*sin(I*Im(x)) */ gsincos(gel(x,1),&u,&v,prec); affrr_fixlg(gmul(v1,u), gel(y,1)); affrr_fixlg(gmul(u1,v), gel(y,2)); avma = av; return y; case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mpsin(tofp_safe(x,prec)), y); avma = av; return y; case t_PADIC: y = sin_p(x); if (!y) pari_err_DOMAIN("gsin(t_PADIC)","argument","",gen_0,x); return y; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valp(y) < 0) pari_err_DOMAIN("sin","valuation", "<", gen_0, x); gsincos(y,&u,&v,prec); return gerepilecopy(av,u); } return trans_eval("sin",gsin,x,prec); } /********************************************************************/ /** SINE, COSINE together **/ /********************************************************************/ void mpsincos(GEN x, GEN *s, GEN *c) { long mod8; pari_sp av, tetpil; GEN p1, *gptr[2]; if (!signe(x)) { long e = expo(x); *s = real_0_bit(e); *c = e >= 0? real_0_bit(e): real_1(nbits2prec(-e)); return; } av=avma; p1=mpcosm1(x,&mod8); tetpil=avma; switch(mod8) { case 0: *c=addsr( 1,p1); *s=mpaut(p1); break; case 1: *s=addsr( 1,p1); *c=mpaut(p1); togglesign(*c); break; case 2: *c=subsr(-1,p1); *s=mpaut(p1); togglesign(*s); break; case 3: *s=subsr(-1,p1); *c=mpaut(p1); break; case 4: *c=addsr( 1,p1); *s=mpaut(p1); togglesign(*s); break; case 5: *s=addsr( 1,p1); *c=mpaut(p1); break; case 6: *c=subsr(-1,p1); *s=mpaut(p1); break; case 7: *s=subsr(-1,p1); *c=mpaut(p1); togglesign(*c); break; } gptr[0]=s; gptr[1]=c; gerepilemanysp(av,tetpil,gptr,2); } /* SINE and COSINE - 1 */ void mpsincosm1(GEN x, GEN *s, GEN *c) { long mod8; pari_sp av, tetpil; GEN p1, *gptr[2]; if (!signe(x)) { long e = expo(x); *s = real_0_bit(e); *c = real_0_bit(2*e-1); return; } av=avma; p1=mpcosm1(x,&mod8); tetpil=avma; switch(mod8) { case 0: *c=rcopy(p1); *s=mpaut(p1); break; case 1: *s=addsr(1,p1); *c=addrs(mpaut(p1),1); togglesign(*c); break; case 2: *c=subsr(-2,p1); *s=mpaut(p1); togglesign(*s); break; case 3: *s=subsr(-1,p1); *c=subrs(mpaut(p1),1); break; case 4: *c=rcopy(p1); *s=mpaut(p1); togglesign(*s); break; case 5: *s=addsr( 1,p1); *c=subrs(mpaut(p1),1); break; case 6: *c=subsr(-2,p1); *s=mpaut(p1); break; case 7: *s=subsr(-1,p1); *c=subsr(-1,mpaut(p1)); break; } gptr[0]=s; gptr[1]=c; gerepilemanysp(av,tetpil,gptr,2); } /* return exp(ix), x a t_REAL */ GEN expIr(GEN x) { pari_sp av = avma; GEN v = cgetg(3,t_COMPLEX); mpsincos(x, (GEN*)(v+2), (GEN*)(v+1)); if (!signe(gel(v,2))) return gerepilecopy(av, gel(v,1)); return v; } /* return exp(ix)-1, x a t_REAL */ static GEN expm1_Ir(GEN x) { pari_sp av = avma; GEN v = cgetg(3,t_COMPLEX); mpsincosm1(x, (GEN*)(v+2), (GEN*)(v+1)); if (!signe(gel(v,2))) return gerepilecopy(av, gel(v,1)); return v; } /* return exp(z)-1, z complex */ GEN cxexpm1(GEN z, long prec) { pari_sp av = avma; GEN X, Y, x = real_i(z), y = imag_i(z); if (typ(x) != t_REAL) x = gtofp(x, prec); if (typ(y) != t_REAL) y = gtofp(y, prec); if (gequal0(y)) return mpexpm1(x); if (gequal0(x)) return expm1_Ir(y); X = mpexpm1(x); /* t_REAL */ Y = expm1_Ir(y); /* exp(x+iy) - 1 = (exp(x)-1)(exp(iy)-1) + exp(x)-1 + exp(iy)-1 */ return gerepileupto(av, gadd(gadd(X,Y), gmul(X,Y))); } void gsincos(GEN x, GEN *s, GEN *c, long prec) { long i, j, ex, ex2, lx, ly, mi; pari_sp av, tetpil; GEN y, r, u, v, u1, v1, p1, p2, p3, p4, ps, pc; GEN *gptr[4]; switch(typ(x)) { case t_INT: case t_FRAC: *s = cgetr(prec); *c = cgetr(prec); av = avma; mpsincos(tofp_safe(x, prec), &ps, &pc); affrr_fixlg(ps,*s); affrr_fixlg(pc,*c); avma = av; return; case t_REAL: mpsincos(x,s,c); return; case t_COMPLEX: i = precision(x); if (!i) i = prec; ps = cgetc(i); *s = ps; pc = cgetc(i); *c = pc; av = avma; r = gexp(gel(x,2),prec); v1 = gmul2n(addrr(invr(r),r), -1); /* = cos(I*Im(x)) */ u1 = subrr(r, v1); /* = I*sin(I*Im(x)) */ gsincos(gel(x,1), &u,&v, prec); affrr_fixlg(mulrr(v1,u), gel(ps,1)); affrr_fixlg(mulrr(u1,v), gel(ps,2)); affrr_fixlg(mulrr(v1,v), gel(pc,1)); affrr_fixlg(mulrr(u1,u), gel(pc,2)); togglesign(gel(pc,2)); avma = av; return; case t_QUAD: av = avma; gsincos(quadtofp(x, prec), s, c, prec); gerepileall(av, 2, s, c); return; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) { *s = gerepilecopy(av,y); *c = gaddsg(1,*s); return; } ex = valp(y); lx = lg(y); ex2 = 2*ex+2; if (ex < 0) pari_err_DOMAIN("gsincos","valuation", "<", gen_0, x); if (ex2 > lx) { *s = x == y? gcopy(y): gerepilecopy(av, y); av = avma; *c = gerepileupto(av, gsubsg(1, gdivgs(gsqr(y),2))); return; } if (!ex) { gsincos(serchop0(y),&u,&v,prec); gsincos(gel(y,2),&u1,&v1,prec); p1 = gmul(v1,v); p2 = gmul(u1,u); p3 = gmul(v1,u); p4 = gmul(u1,v); tetpil = avma; *c = gsub(p1,p2); *s = gadd(p3,p4); gptr[0]=s; gptr[1]=c; gerepilemanysp(av,tetpil,gptr,2); return; } ly = lx+2*ex; mi = lx-1; while (mi>=3 && isrationalzero(gel(y,mi))) mi--; mi += ex-2; pc = cgetg(ly,t_SER); *c = pc; ps = cgetg(lx,t_SER); *s = ps; pc[1] = evalsigne(1) | _evalvalp(0) | evalvarn(varn(y)); gel(pc,2) = gen_1; ps[1] = y[1]; for (i=2; i 1 and 0 < i < lgcols(x) */ static GEN ZMrow_ZC_mul_i(GEN x, GEN y, long lx, long i) { GEN c = mulii(gcoeff(x,i,1), gel(y,1)); long k; for (k = 2; k < lx; k++) { GEN t = mulii(gcoeff(x,i,k), gel(y,k)); if (signe(t)) c = addii(c, t); } return c; } static long zmrow_zc_mul(GEN x, GEN y, long lx, long i) { long k; long c = coeff(x,i,1) * y[1]; for (k = 2; k < lx; k++) c += coeff(x,i,k) * y[k]; return c; } GEN zm_zc_mul(GEN x, GEN y) { long lx = lg(x), l, i; GEN z; if (lx == 1) return cgetg(1, t_VECSMALL); l = lg(gel(x,1)); z = cgetg(l,t_VECSMALL); for (i=1; i> 32; #endif c ^= c >> 16; c ^= c >> 8; c ^= c >> 4; c ^= c >> 2; c ^= c >> 1; return c & 1; } GEN FpM_FpC_mul(GEN x, GEN y, GEN p) { long lx = lg(x); return lx==1? cgetg(1,t_COL): FpM_FpC_mul_i(x, y, lx, lgcols(x), p); } GEN Flm_Flc_mul(GEN x, GEN y, ulong p) { long l, lx = lg(x); if (lx==1) return cgetg(1,t_VECSMALL); l = lgcols(x); if (p==2) return Flm_Flc_mul_i_2(x, y, lx, l); 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); } GEN F2m_F2c_mul(GEN x, GEN y) { long l, lx = lg(x); if (lx==1) return cgetg(1,t_VECSMALL); l = coeff(x,1,1); return F2m_F2c_mul_i(x, y, lx, l); } /* RgV_to_RgX(FpM_FpC_mul(x,y,p), v), p != NULL, memory clean */ GEN FpM_FpC_mul_FpX(GEN x, GEN y, GEN p, long v) { long i, l, lx = lg(x); GEN z; if (lx==1) return pol_0(v); l = lgcols(x); z = new_chunk(l+1); for (i=l-1; i; i--) { pari_sp av = avma; GEN p1 = ZMrow_ZC_mul_i(x,y,lx,i); p1 = modii(p1, p); if (signe(p1)) { if (i != l-1) stackdummy((pari_sp)(z + l+1), (pari_sp)(z + i+2)); gel(z,i+1) = gerepileuptoint(av, p1); break; } avma = av; } if (!i) { avma = (pari_sp)(z + l+1); return pol_0(v); } z[0] = evaltyp(t_POL) | evallg(i+2); z[1] = evalsigne(1) | evalvarn(v); for (; i; i--) { pari_sp av = avma; GEN p1 = ZMrow_ZC_mul_i(x,y,lx,i); gel(z,i+1) = gerepileuptoint(av, modii(p1,p)); } return z; } /********************************************************************/ /** **/ /** TRANSPOSITION **/ /** **/ /********************************************************************/ /* == zm_transpose */ GEN Flm_transpose(GEN x) { long i, dx, lx = lg(x); GEN y; if (lx == 1) return cgetg(1,t_MAT); dx = lgcols(x); y = cgetg(dx,t_MAT); for (i=1; is(E,0); _1 = S->s(E,1); for (i=1; i<=n; i++) { GEN z = const_col(n, _0); gel(z,i) = _1; gel(y, i) = z; } return y; } GEN matid_F2m(long n) { GEN y = cgetg(n+1,t_MAT); long i; if (n < 0) pari_err_DOMAIN("matid_F2m", "dimension","<",gen_0,stoi(n)); for (i=1; i<=n; i++) { gel(y,i) = zero_F2v(n); F2v_set(gel(y,i),i); } return y; } GEN matid_F2xqM(long n, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_matid(n, E, S); } GEN matid_FlxqM(long n, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_matid(n, E, S); } GEN matid_Flm(long n) { GEN y = cgetg(n+1,t_MAT); long i; if (n < 0) pari_err_DOMAIN("matid_Flm", "dimension","<",gen_0,stoi(n)); for (i=1; i<=n; i++) { gel(y,i) = zero_zv(n); ucoeff(y, i,i) = 1; } return y; } GEN scalar_Flm(long s, long n) { long i; GEN y = cgetg(n+1,t_MAT); for (i=1; i<=n; i++) { gel(y,i) = zero_Flv(n); coeff(y, i,i) = s; } return y; } /********************************************************************/ /** **/ /** CONVERSIONS **/ /** **/ /********************************************************************/ GEN ZV_to_Flv(GEN x, ulong p) { long i, n = lg(x); GEN y = cgetg(n,t_VECSMALL); for (i=1; i2) p = icopy(p); for (i=2; i1) pari_warn(warnmem,"Wiedemann: first loop, %ld",i); W = gerepileupto(av, W); } } b = FpX_renormalize(b, m+2); if (lgpol(b)==0) {avma = btop; continue; } M = FpX_halfgcd(b, monomial(gen_1, m, 0), p); Q = FpX_neg(FpX_normalize(gcoeff(M, 2, 1),p),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); 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 (DEBUGMEM>1) pari_warn(warnmem,"Wiedemann: second loop, %ld",i); gerepileall(av, 2, &V, &W); } } V = FpC_red(V, p); W = FpC_sub(f(E,V), B, p); if (ZV_equal0(W)) return gerepilecopy(ltop, V); av = avma; for (i = 1; i <= n; ++i) { V = W; W = f(E, V); if (ZV_equal0(W)) return gerepilecopy(ltop, shallowtrans(V)); gerepileall(av, 2, &V, &W); } avma = btop; } return NULL; } GEN zMs_ZC_mul(GEN M, GEN B) { long i, j; long n = lg(B)-1; GEN V = zerocol(n); for (i = 1; i <= n; ++i) if (signe(gel(B, i))) { GEN R = gel(M, i), C = gel(R, 1), E = gel(R, 2); long l = lg(C); for (j = 1; j < l; ++j) { long k = C[j]; switch(E[j]) { case 1: gel(V, k) = gel(V,k)==gen_0 ? gel(B,i) : addii(gel(V, k), gel(B,i)); break; case -1: gel(V, k) = gel(V,k)==gen_0 ? negi(gel(B,i)) : subii(gel(V, k), gel(B,i)); break; default: gel(V, k) = gel(V,k)==gen_0 ? mulis(gel(B, i), E[j]) : addii(gel(V, k), mulis(gel(B, i), E[j])); break; } } } return V; } GEN FpMs_FpC_mul(GEN M, GEN B, GEN p) { return FpC_red(zMs_ZC_mul(M, B), p); } GEN ZV_zMs_mul(GEN B, GEN M) { long i, j; long m = lg(M)-1; GEN V = cgetg(m+1,t_VEC); for (i = 1; i <= m; ++i) { GEN R = gel(M, i), C = gel(R, 1), E = gel(R, 2); long l = lg(C); GEN z = mulis(gel(B, C[1]), E[1]); for (j = 2; j < l; ++j) { long k = C[j]; switch(E[j]) { case 1: z = addii(z, gel(B,k)); break; case -1: z = subii(z, gel(B,k)); break; default: z = addii(z, mulis(gel(B,k), E[j])); break; } } gel(V,i) = z; } return V; } GEN 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; GEN xi, xb, pi = gen_1, P; long i; if (!C) { C = Flm_inv(ZM_to_Flm(a, p), p); if (!C) pari_err_INV("ZlM_gauss", a); } P = utoipos(p); av2 = avma; xi = Flm_mul(C, ZM_to_Flm(b, p), p); xb = Flm_to_ZM(xi); for (i = 2; i <= e; i++) { 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(DEBUGMEM>1) pari_warn(warnmem,"ZlM_gauss. i=%ld",i); gerepileall(av2,3, &pi,&b,&xb); } xi = Flm_mul(C, ZM_to_Flm(b, p), p); xb = ZM_add(xb, nm_Z_mul(xi, pi)); } return gerepileupto(av, xb); } struct wrapper_modp_s { GEN (*f)(void*, GEN); void *E; GEN p; }; /* compute f(x) mod p */ static GEN wrap_relcomb_modp(void *E, GEN x) { struct wrapper_modp_s *W = (struct wrapper_modp_s*)E; return FpC_red(W->f(W->E, x), W->p); } static GEN wrap_relcomb(void*E, GEN x) { return zMs_ZC_mul((GEN)E, x); } static GEN wrap_relker(void*E, GEN x) { return ZV_zMs_mul(x, (GEN)E); } /* Solve f(X) = B (mod p^e); blackbox version of ZlM_gauss */ 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); GEN xb, xi, pi = gen_1; long i; W.E = E; W.f = f; W.p = p; xi = gen_FpM_Wiedemann((void*)&W, wrap_relcomb_modp, FpC_red(B, p), p); /* f^(-1) B */ if (!xi || e == 1 || typ(xi) == t_VEC) return xi; xb = xi; for (i = 2; i <= e; i++) { 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(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpM_Dixon. i=%ld",i); gerepileall(av,3, &pi,&B,&xb); } xi = gen_FpM_Wiedemann((void*)&W, wrap_relcomb_modp, FpC_red(B, p), p); if (!xi) return NULL; if (typ(xi) == t_VEC) return gerepileupto(av, xi); xb = ZC_add(xb, ZC_Z_mul(xi, pi)); } return gerepileupto(av, xb); } static GEN vecprow(GEN A, GEN prow) { return mkvec2(vecpermute(prow,gel(A,1)), gel(A,2)); } /* Solve the equation MX = A. Return either a solution as a t_COL, * or the index of a column which is linearly dependent from the others as a * t_VECSMALL with a single component. */ GEN ZpMs_ZpCs_solve(GEN M, GEN A, long nbrow, GEN p, long e) { pari_sp av = avma; GEN pcol, prow; long nbi=lg(M)-1, lR; long i, n; GEN Mp, Ap, Rp; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); RgMs_structelim(M, nbrow, gel(A, 1), &pcol, &prow); if (!pcol) { avma = av; return NULL; } if (DEBUGLEVEL) timer_printf(&ti,"structured elimination (%ld -> %ld)",nbi,lg(pcol)-1); n = lg(pcol)-1; Mp = cgetg(n+1, t_MAT); for(i=1; i<=n; i++) gel(Mp, i) = vecprow(gel(M,pcol[i]), prow); Ap = zCs_to_ZC(vecprow(A, prow), n); if (DEBUGLEVEL) timer_start(&ti); Rp = gen_ZpM_Dixon((void*)Mp,wrap_relcomb, Ap, p, e); if (DEBUGLEVEL) timer_printf(&ti,"linear algebra"); if (!Rp) { avma = av; return NULL; } lR = lg(Rp)-1; if (typ(Rp) == t_COL) { GEN R = zerocol(nbi+1); for (i=1; i<=lR; i++) gel(R,pcol[i]) = gel(Rp,i); return gerepilecopy(av, R); } for (i = 1; i <= lR; ++i) if (signe(gel(Rp, i))) return gerepileuptoleaf(av, mkvecsmall(pcol[i])); return NULL; /* NOT REACHED */ } GEN FpMs_FpCs_solve(GEN M, GEN A, long nbrow, GEN p) { return ZpMs_ZpCs_solve(M, A, nbrow, p, 1); } GEN FpMs_FpCs_solve_safe(GEN M, GEN A, long nbrow, GEN p) { GEN res; pari_CATCH(e_INV) { GEN E = pari_err_last(); GEN x = err_get_compo(E,2); if (typ(x) != t_INTMOD) pari_err(0,E); if (DEBUGLEVEL) pari_warn(warner,"FpMs_FpCs_solve_safe, impossible inverse %Ps", x); res = NULL; } pari_TRY { res = ZpMs_ZpCs_solve(M, A, nbrow, p, 1); } pari_ENDCATCH return res; } static GEN FpMs_structelim_back(GEN M, GEN V, GEN prow, GEN p) { long i, j, oldf = 0, f = 0; long lrow = lg(prow), lM = lg(M); GEN W = const_vecsmall(lM-1,1); GEN R = cgetg(lrow, t_VEC); for (i=1; i=2) continue; if (c==1) { pari_sp av = avma; GEN s = gen_0; for(j=1; j %ld)",nbi,lg(pcol)-1); n = lg(pcol)-1; Mp = cgetg(n+1, t_MAT); for(i=1; i<=n; i++) gel(Mp, i) = vecprow(gel(M,pcol[i]), prow); W.E = (void*) Mp; W.f = wrap_relker; W.p = p; av2 = avma; for(;;) { avma = av2; B = cgetg(n+1,t_VEC); for(i=1; i<=n; i++) gel(B,i) = randomi(p); MB = FpV_FpMs_mul(B, Mp, p); if (DEBUGLEVEL) timer_start(&ti); pari_CATCH(e_INV) { GEN E = pari_err_last(); GEN x = err_get_compo(E,2); if (typ(x) != t_INTMOD) pari_err(0,E); if (DEBUGLEVEL) pari_warn(warner,"FpMs_leftkernel_elt, impossible inverse %Ps", x); Rp = NULL; } pari_TRY { Rp = gen_FpM_Wiedemann((void*)&W, wrap_relcomb_modp, MB, p); } pari_ENDCATCH if (!Rp) continue; if (typ(Rp)==t_COL) { Rp = FpC_sub(Rp,B,p); if (ZV_equal0(Rp)) continue; } R = FpMs_structelim_back(M, Rp, prow, p); if (DEBUGLEVEL) timer_printf(&ti,"Wiedemann left kernel"); return gerepilecopy(av, R); } } pari-2.7.5/src/mt/0000755000175000017500000000000012613365633012325 5ustar billbillpari-2.7.5/src/mt/single.h0000644000175000017500000000122412366172547013763 0ustar billbill/* Copyright (C) 2013 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. */ #define MT_IS_THREAD 0 #define MT_SIGINT_BLOCK(block) #define MT_SIGINT_UNBLOCK(block) pari-2.7.5/src/mt/mpi.h0000644000175000017500000000124312366172547013270 0ustar billbill/* Copyright (C) 2013 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. */ #define MT_IS_THREAD mt_is_thread() #define MT_SIGINT_BLOCK(block) #define MT_SIGINT_UNBLOCK(block) pari-2.7.5/src/mt/single.c0000644000175000017500000000210412435453044013743 0ustar billbill/* Copyright (C) 2013 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 "mt.h" void mt_sigint_block(void) { } void mt_sigint_unblock(void) { } void mt_err_recover(long er) { (void)er; } void pari_mt_close(void) { } void mt_queue_reset(void) { } void mt_broadcast(GEN code) {(void) code;} void mt_sigint(void) {} int mt_is_parallel(void) { return 0; } int mt_is_thread(void) { return 0; } void pari_mt_init(void) { pari_mt_nbthreads = 1; } void mt_queue_start(struct pari_mt *pt, GEN worker) { mtsingle_queue_start(pt, worker); } pari-2.7.5/src/mt/pthread.h0000644000175000017500000000141612366172547014134 0ustar billbill/* Copyright (C) 2013 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. */ #define MT_IS_THREAD mt_is_thread() #define MT_SIGINT_BLOCK(block) do {if (!block) mt_sigint_block();} while(0) #define MT_SIGINT_UNBLOCK(block) do {if (!block) mt_sigint_unblock();} while(0) pari-2.7.5/src/mt/pthread.c0000644000175000017500000001577012435453044014126 0ustar billbill/* Copyright (C) 2013 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 "mt.h" #include struct mt_queue { long no; GEN input, output; GEN worker; long workid; pthread_cond_t cond, cond1, cond2; pthread_mutex_t mut, mut1, mut2; pthread_cond_t *pcond; pthread_mutex_t *pmut; }; struct mt_pstate { pthread_t *th; struct pari_thread *pth; struct mt_queue *mq; long n, nbint, last; long pending; pthread_cond_t pcond; pthread_mutex_t pmut; }; static THREAD long mt_thread_no = -1; static struct mt_pstate *pari_mt; #define LOCK(x) pthread_mutex_lock(x); do #define UNLOCK(x) while(0); pthread_mutex_unlock(x) void mt_sigint_block(void) { if (mt_thread_no>=0) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); } void mt_sigint_unblock(void) { if (mt_thread_no>=0) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); } void mt_err_recover(long er) { (void) er; if (mt_thread_no>=0) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq = mt->mq+mt_thread_no; LOCK(mq->pmut) { mq->output = pari_err_last(); pthread_cond_signal(mq->pcond); } UNLOCK(mq->pmut); pthread_exit((void*)1); } } void mt_sigint(void) { if (pari_mt) pthread_cond_broadcast(&pari_mt->pcond); } int mt_is_parallel(void) { return !!pari_mt; } int mt_is_thread(void) { return mt_thread_no>=0; } void mt_broadcast(GEN code) {(void) code;} void pari_mt_init(void) { pari_mt = NULL; #ifdef _SC_NPROCESSORS_CONF pari_mt_nbthreads = sysconf(_SC_NPROCESSORS_CONF); #else pari_mt_nbthreads = 1; #endif } void pari_mt_close(void) { } static void* mt_queue_run(void *arg) { GEN args = pari_thread_start((struct pari_thread*) arg); pari_sp av = avma; struct mt_queue *mq = (struct mt_queue *) args; mt_thread_no = mq->no; for(;;) { GEN work, done; LOCK(&mq->mut) { 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); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); done = closure_callgenvec(mq->worker,work); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); LOCK(mq->pmut) { 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 mt_queue_check(struct mt_pstate *mt) { long i; for(i=0; in; i++) { struct mt_queue *mq = mt->mq+i; if (mq->output) return i; } return -1; } static GEN mtpthread_queue_get(struct mt_state *junk, long *workid, long *pending) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq; GEN done = NULL; long last; (void) junk; if (mt->nbintn) { mt->last = mt->nbint; *pending = mt->pending; return NULL; } BLOCK_SIGINT_START LOCK(&mt->pmut) { while ((last = mt_queue_check(mt)) < 0) { 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 mq = mt->mq+last; if (mq->output==err_e_STACK) pari_err(e_STACK); done = gcopy(mq->output); 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; } static void mtpthread_queue_submit(struct mt_state *junk, long workid, GEN work) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq = mt->mq+mt->last; (void) junk; if (!work) { mt->nbint=mt->n; return; } BLOCK_SIGINT_START if (mt->nbintn) mt->nbint++; LOCK(&mq->mut) { mq->input = work; mq->workid = workid; 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 } void mt_queue_reset(void) { struct mt_pstate *mt = pari_mt; long i; for (i=0; in; i++) pthread_cancel(mt->th[i]); for (i=0; in; i++) pthread_join(mt->th[i],NULL); if (DEBUGLEVEL) pari_warn(warner,"stop threads"); pari_mt = NULL; for (i=0;in;i++) { 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); pari_free(mt->pth); pari_free(mt->th); pari_free(mt); } void mt_queue_start(struct pari_mt *pt, GEN worker) { if (pari_mt) 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 i; mt->mq = (struct mt_queue *) pari_malloc(sizeof(*mt->mq)*NBT); mt->th = (pthread_t *) pari_malloc(sizeof(*mt->th)*NBT); mt->pth = (struct pari_thread *) pari_malloc(sizeof(*mt->pth)*NBT); mt->pending = 0; mt->n = NBT; mt->nbint = 0; mt->last = 0; pari_mt = mt; pthread_cond_init(&mt->pcond,NULL); pthread_mutex_init(&mt->pmut,NULL); for (i=0;imq+i; mq->no = i; 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 (DEBUGLEVEL) pari_warn(warner,"start threads"); for (i=0;ith[i],NULL, &mt_queue_run, (void*)&mt->pth[i]); pt->get=&mtpthread_queue_get; pt->submit=&mtpthread_queue_submit; pt->end=&mt_queue_reset; } } pari-2.7.5/src/mt/mt.c0000644000175000017500000000336112366172547013121 0ustar billbill/* $Id$ Copyright (C) 2013 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" #include "mt.h" static GEN mtsingle_queue_get(struct mt_state *mt, long *workid, long *pending) { GEN done = mt->pending; if (workid) *workid = mt->workid; mt->pending = NULL; *pending = 0; return done; } static void mtsingle_queue_submit(struct mt_state *mt, long workid, GEN work) { mt->pending = work? closure_callgenvec(mt->worker, work): NULL; mt->workid = workid; } static void mtsingle_queue_end(void) { } void mtsingle_queue_start(struct pari_mt *pt, GEN worker) { pt->get = mtsingle_queue_get; pt->submit = mtsingle_queue_submit; pt->end = mtsingle_queue_end; pt->mt.worker = worker; pt->mt.pending = NULL; } void mt_queue_end(struct pari_mt *pt) { pt->end(); } void mt_queue_submit(struct pari_mt *pt, long workid, GEN work) { pt->submit(&pt->mt, workid, work); } GEN mt_queue_get(struct pari_mt *pt, long *workid, long *pending) { return pt->get(&pt->mt, workid, pending); } void mtstate_save(long *pending) { *pending = mt_is_parallel(); } void mtstate_restore(long *pending) { if (!*pending && mt_is_parallel()) mt_queue_reset(); } void mtstate_reset(void) { if (mt_is_parallel()) mt_queue_reset(); } pari-2.7.5/src/mt/mt.h0000644000175000017500000000130612366172547013123 0ustar billbill/* Copyright (C) 2013 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. */ BEGINEXTERN void mtsingle_queue_start(struct pari_mt *pt, GEN worker); void mt_queue_reset(void); int mt_is_parallel(void); ENDEXTERN pari-2.7.5/src/mt/mpi.c0000644000175000017500000001527412435453044013263 0ustar billbill/* Copyright (C) 2013 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 "mt.h" #include 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 }; struct mt_mstate { long n; int source; long nbint; long *workid; }; static struct mt_mstate pari_mt_data; static struct mt_mstate *pari_mt; static void send_long(long a, long dest) { MPI_Send(&a, 1, MPI_LONG, dest, 0, MPI_COMM_WORLD); } static void send_request(enum PMPI_cmd ecmd, long dest) { send_long((long)ecmd, dest); } static void send_GEN(GEN elt, int dest) { pari_sp av = avma; int size; GEN reloc = copybin_unlink(elt); GENbin *buf = copy_bin(mkvec2(elt,reloc)); size = sizeof(GENbin) + buf->len*sizeof(ulong); MPI_Send(buf, size, MPI_CHAR, dest, 0, MPI_COMM_WORLD); pari_free(buf); avma = av; } static void send_request_GEN(enum PMPI_cmd ecmd, GEN elt, int dest) { send_request(ecmd, dest); send_GEN(elt, dest); } static void send_request_long(enum PMPI_cmd ecmd, long elt, int dest) { send_request(ecmd, dest); send_long(elt, dest); } static long recvfrom_long(int src) { long a; MPI_Recv(&a, 1, MPI_LONG, src, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); return a; } static enum PMPI_cmd recvfrom_request(int src) { return (enum PMPI_cmd) recvfrom_long(src); } static GENbin * recvstatus_buf(int source, MPI_Status *status) { int size; GENbin *buf; MPI_Get_count(status, MPI_CHAR, &size); buf = (GENbin *)pari_malloc(size); MPI_Recv(buf, size, MPI_CHAR, source, 0/* tag */, MPI_COMM_WORLD, MPI_STATUS_IGNORE); return buf; } static GEN recvstatus_GEN(int source, MPI_Status *status) { GENbin *buf = recvstatus_buf(source, status); GEN res = bin_copy(buf); bincopy_relink(gel(res,1),gel(res,2)); return gel(res,1); } static void recvstatus_void(int source, MPI_Status *status) { GENbin *buf = recvstatus_buf(source, status); free(buf); } static GEN recvfrom_GEN(int src) { MPI_Status status; MPI_Probe(src, 0, MPI_COMM_WORLD, &status); return recvstatus_GEN(src, &status); } static GEN recvany_GEN(int *source) { MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, 0 /* tag */, MPI_COMM_WORLD, &status); *source = status.MPI_SOURCE; return recvstatus_GEN(*source, &status); } static void recvany_void(int *source) { MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, 0 /* tag */, MPI_COMM_WORLD, &status); *source = status.MPI_SOURCE; recvstatus_void(*source, &status); } static jmp_buf child_env; static void pari_MPI_child(void) { pari_sp av = avma; long size; GEN worker = NULL, work, done; struct gp_context rec; if (!diffptr) initprimetable(500000); gp_context_save(&rec); if (setjmp(child_env)) { send_GEN(pari_err_last(), 0); gp_context_restore(&rec); } while (1) switch (recvfrom_request(0)) { case PMPI_worker: avma = top; worker = recvfrom_GEN(0); av = avma; break; case PMPI_work: work = recvfrom_GEN(0); done = closure_callgenvec(worker, work); send_GEN(done, 0); avma = av; break; case PMPI_parisize: size = recvfrom_long(0); pari_init_stack(size,top-bot); gp_context_save(&rec); break; case PMPI_precreal: precreal = recvfrom_long(0); break; case PMPI_eval: (void) closure_evalgen(recvfrom_GEN(0)); avma = av; break; case PMPI_close: MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(0); break; } } void mt_err_recover(long er) { if (pari_MPI_rank) longjmp(child_env,er); } void mt_sigint_block(void) { } void mt_sigint_unblock(void) { } void mt_sigint(void) {} int mt_is_parallel(void) { return !!pari_mt; } int mt_is_thread(void) { return pari_MPI_rank; } void mt_broadcast(GEN code) { long i; if (!pari_MPI_rank && !pari_mt) for (i=1;inbint<=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); return done; } static void mtmpi_queue_submit(struct mt_state *junk, long workid, GEN work) { struct mt_mstate *mt = pari_mt; if (!work) { mt->nbint=mt->n+1; return; } if (mt->nbint<=mt->n) mt->nbint++; nbreq++; mt->workid[mt->source] = workid; send_request_GEN(PMPI_work, work, mt->source); } void mt_queue_reset(void) { struct mt_mstate *mt = pari_mt; if (DEBUGLEVEL>0 && nbreq) pari_warn(warner,"%ld discarded threads (MPI)",nbreq); for( ;nbreq>0; nbreq--) recvany_void(&mt->source); pari_free(mt->workid); pari_mt = NULL; } void mt_queue_start(struct pari_mt *pt, GEN worker) { if (pari_mt || pari_MPI_size <= 2 || pari_mt_nbthreads <= 1) 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; 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_GEN(PMPI_worker, worker, i); } mt->n = n; mt->nbint = 1; mt->source = 1; pt->get=&mtmpi_queue_get; pt->submit=&mtmpi_queue_submit; pt->end=&mt_queue_reset; } } pari-2.7.5/src/test/0000755000175000017500000000000012613365633012664 5ustar billbillpari-2.7.5/src/test/tune.c0000644000175000017500000004463512366172547014024 0ustar billbill/* Copyright (C) 2001 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. */ /* This file is a quick hack adapted from gmp-4.0 tuning utilities * (T. Granlund et al.) * * (GMU MP Library is Copyright Free Software Foundation, Inc.) */ #define PARI_TUNE #include #include #define numberof(x) (sizeof(x) / sizeof((x)[0])) int option_trace = 0; double Step_Factor = .01; /* small steps by default */ ulong DFLT_mod1, DFLT_hmod, DFLT_mod2; GEN LARGE_mod; #ifdef LONG_IS_64BIT # define DFLT_mod DFLT_mod1 # define Fmod_MUL_MULII_LIMIT Flx_MUL_MULII_LIMIT # define Fmod_SQR_SQRI_LIMIT Flx_SQR_SQRI_LIMIT # else # define DFLT_mod DFLT_mod2 # define Fmod_MUL_MULII_LIMIT Flx_MUL_MULII2_LIMIT # define Fmod_SQR_SQRI_LIMIT Flx_SQR_SQRI2_LIMIT #endif typedef struct { ulong reps, type; long *var, *var_disable, size, enabled; GEN x, y; ulong l; GEN p; } speed_param; typedef double (*speed_function_t)(speed_param *s); typedef struct { int kernel; const char *name; long *var; int type; /* t_INT or t_REAL */ long min_size; long max_size; speed_function_t fun; double step_factor; /* how much to step sizes (rounded down) */ double stop_factor; long *var_disable; } tune_param; /* ========================================================== */ /* To use GMP cycle counting functions, look for GMP in Oxxx/Makefile */ #ifdef GMP_TIMER /* needed to link with gmp-4.0/tune/{time,freq}.o */ int speed_option_verbose = 0; extern double speed_unittime; extern int speed_precision; void speed_starttime(void); double speed_endtime(void); #else static pari_timer __T; static double speed_unittime = 1e-4; static int speed_precision= 1000; static void speed_starttime() { timer_start(&__T); } static double speed_endtime() { return (double)timer_delay(&__T)/1000.; } #endif /* ========================================================== */ /* int, n words, odd */ static GEN rand_INT(long n) { pari_sp av = avma; GEN x, N = int2n(n*BITS_IN_LONG); do x = randomi(N); while (lgefint(x) != n+2); if (!mpodd(x)) x = addis(x,1); /*For Barrett REDC */ return gerepileuptoint(av, x); } /* real, n words */ static GEN rand_REAL(long n) { return gmul2n(itor(rand_INT(n), n+2),-BITS_IN_LONG*n); } static GEN rand_FpX(long n) { GEN x; do x = random_FpX(n+1, 0, LARGE_mod); while (degpol(x) < n); return x; } /* Flx, degree n */ static GEN rand_Flx(long n, ulong l) { GEN x; do x = random_Flx(n+1, 0, l); while (degpol(x) < n); return x; } /* normalized Fpx, degree n */ static GEN rand_NFpX(long n) { pari_sp av = avma; GEN x = gadd(monomial(gen_1,n,0), random_FpX(n, 0, LARGE_mod)); return gerepileupto(av, x); } /* normalized Flx, degree n */ static GEN rand_NFlx(long n, ulong l) { pari_sp av = avma; GEN x = Flx_add(Flx_shift(pol1_Flx(0),n), random_Flx(n, 0, l), 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 static GEN rand_g(long n, long type) { switch (type) { case t_INT: return rand_INT(n); case t_REAL: return rand_REAL(n); case t_Fhx: return rand_Flx(n,DFLT_hmod); 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_NFlx: return rand_NFlx(n,DFLT_mod); case t_FpX: return rand_FpX(n); case t_NFpX: return rand_NFpX(n); } return NULL; } static void dftmod(speed_param *s) { switch (s->type) { case t_Fhx: s->l=DFLT_hmod; return; 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_NFlx: s->l=DFLT_mod; return; case t_FpX: s->p=LARGE_mod; return; case t_NFpX: s->p=LARGE_mod; return; } } /* ========================================================== */ #define TIME_FUN(call) {\ { \ pari_sp av = avma; \ int i; \ speed_starttime(); \ i = (s)->reps; \ do { call; avma = av; } while (--i); \ } \ return speed_endtime(); \ } #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 */ static void enable(speed_param *s) { m_enable(s,var); s->enabled = 1; if (s->var_disable) m_disable(s,var_disable); } static void disable(speed_param *s) { m_disable(s,var); s->enabled = 0; if (s->var_disable) m_disable(s,var_disable); } static double speed_mulrr(speed_param *s) { TIME_FUN(mulrr(s->x, s->y)); } static double speed_mulii(speed_param *s) { TIME_FUN(mulii(s->x, s->y)); } static double speed_exp(speed_param *s) { TIME_FUN(mpexp(s->x)); } static double speed_inv(speed_param *s) { TIME_FUN(invr(s->x)); } static double speed_log(speed_param *s) { TIME_FUN(mplog(s->x)); } static double speed_logcx(speed_param *s) { GEN z; setexpo(s->x,0); z = mkcomplex(gen_1, s->x); glog(z,s->size); TIME_FUN(glog(z,s->size)); } static double speed_atan(speed_param *s) { setexpo(s->x, 0); gatan(s->x, 0); TIME_FUN(gatan(s->x, 0)); } static double speed_sqri (speed_param *s) { TIME_FUN(sqri(s->x)); } static double speed_Fp_pow(speed_param *s) { TIME_FUN( Fp_pow(s->x, subis(s->y,1), s->y)); } static double speed_divrr(speed_param *s) { TIME_FUN(divrr(s->x, s->y)); } static double speed_invmod(speed_param *s) { GEN T; TIME_FUN(invmod(s->x, s->y, &T)); } static double speed_Flx_sqr(speed_param *s) { TIME_FUN(Flx_sqr(s->x, s->l)); } static double speed_Flx_inv(speed_param *s) { TIME_FUN(Flx_invBarrett(s->x, s->l)); } static double speed_Flx_mul(speed_param *s) { TIME_FUN(Flx_mul(s->x, s->y, s->l)); } static double speed_Flx_divrem(speed_param *s) { GEN r, x = rand_NFlx((degpol(s->x)-1)*2, s->l); TIME_FUN(Flx_divrem(x, s->x, s->l, &r)); } static double speed_Flx_rem(speed_param *s) { GEN x = rand_NFlx((degpol(s->x)-1)*2, s->l); TIME_FUN(Flx_rem(x, s->x, s->l)); } 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); TIME_FUN(Flx_rem(x, q, s->l)); } static double speed_Flx_halfgcd(speed_param *s) { TIME_FUN(Flx_halfgcd(s->x, s->y, s->l)); } static double speed_Flx_gcd(speed_param *s) { TIME_FUN(Flx_gcd(s->x, s->y, s->l)); } static double speed_Flx_extgcd(speed_param *s) { GEN u,v; TIME_FUN(Flx_extgcd(s->x, s->y, s->l, &u, &v)); } static double speed_FpX_inv(speed_param *s) { TIME_FUN(FpX_invBarrett(s->x, s->p)); } static double speed_FpX_divrem(speed_param *s) { GEN r, x = rand_NFpX((degpol(s->x)-1)*2); TIME_FUN(FpX_divrem(x, s->x, s->p, &r)); } static double speed_FpX_rem(speed_param *s) { GEN x = rand_NFpX((degpol(s->x)-1)*2); TIME_FUN(FpX_rem(x, s->x, s->p)); } static double speed_FpXQ_red(speed_param *s) { GEN x = rand_NFpX((degpol(s->x)-1)*2); GEN q = FpX_get_red(s->x, s->p); TIME_FUN(FpX_rem(x, q, s->p)); } static double speed_FpX_halfgcd(speed_param *s) { TIME_FUN(FpX_halfgcd(s->x, s->y, s->p)); } static double speed_FpX_gcd(speed_param *s) { TIME_FUN(FpX_gcd(s->x, s->y, s->p)); } static double speed_FpX_extgcd(speed_param *s) { GEN u,v; TIME_FUN(FpX_extgcd(s->x, s->y, s->p, &u, &v)); } /* small coeffs: earlier thresholds for more complicated rings */ static double speed_RgX_sqr(speed_param *s) { TIME_FUN(RgX_sqr(s->x)); } static double speed_RgX_mul(speed_param *s) { TIME_FUN(RgX_mul(s->x, s->y)); } enum { PARI = 1, GMP = 2 }; #ifdef PARI_KERNEL_GMP # define AVOID PARI #else # define AVOID GMP #endif /* Thresholds are set in this order. If f() depends on g(), g() should * occur first */ #define var(a) # a, &a static tune_param param[] = { {PARI,var(MULII_KARATSUBA_LIMIT), t_INT, 4,0, speed_mulii,0,0,&MULII_FFT_LIMIT}, {PARI,var(SQRI_KARATSUBA_LIMIT), t_INT, 4,0, speed_sqri,0,0,&SQRI_FFT_LIMIT}, {PARI,var(MULII_FFT_LIMIT), t_INT, 500,0, speed_mulii,0.02}, {PARI,var(SQRI_FFT_LIMIT), t_INT, 500,0, speed_sqri,0.02}, {0, var(MULRR_MULII_LIMIT), t_REAL,4,0, speed_mulrr}, {0, var(Fp_POW_REDC_LIMIT), t_INT, 3,100, speed_Fp_pow,0,0,&Fp_POW_BARRETT_LIMIT}, {0, var(Fp_POW_BARRETT_LIMIT), t_INT, 3,0, speed_Fp_pow}, {0, var(INVNEWTON_LIMIT), t_REAL,66,0, speed_inv,0.03}, {GMP, var(DIVRR_GMP_LIMIT), t_REAL,4,0, speed_divrr}, {0, var(EXPNEWTON_LIMIT), t_REAL,66,0, speed_exp}, {0, var(LOGAGM_LIMIT), t_REAL,4,0, speed_log}, {0, var(LOGAGMCX_LIMIT), t_REAL,3,0, speed_logcx,0.05}, {0, var(AGM_ATAN_LIMIT), t_REAL,20,0, speed_atan,0.05}, {GMP, var(INVMOD_GMP_LIMIT), t_INT, 3,0, speed_invmod}, {0, var(Flx_MUL_KARATSUBA_LIMIT),t_Flx,5,0, speed_Flx_mul,0,0,&Fmod_MUL_MULII_LIMIT}, {0, var(Flx_SQR_KARATSUBA_LIMIT),t_Flx,5,0, speed_Flx_sqr,0,0,&Fmod_SQR_SQRI_LIMIT}, {0, var(Flx_MUL_HALFMULII_LIMIT),t_Fhx,3,0, speed_Flx_mul}, {0, var(Flx_SQR_HALFSQRI_LIMIT), t_Fhx,3,0, speed_Flx_sqr}, {0, var(Flx_MUL_MULII_LIMIT), t_Fl1x,5,0, speed_Flx_mul}, {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_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_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}, {0, var(FpX_INVBARRETT_LIMIT), t_NFpX,10,0, speed_FpX_inv,0.05}, {0, var(FpX_DIVREM_BARRETT_LIMIT),t_NFpX,10,0, speed_FpX_divrem,0.05}, {0, var(FpX_REM_BARRETT_LIMIT), t_NFpX,10,0, speed_FpX_rem,0.05}, {0, var(FpX_BARRETT_LIMIT), t_NFpX,10,0, speed_FpXQ_red}, {0, var(FpX_HALFGCD_LIMIT), t_FpX,10,0, speed_FpX_halfgcd}, {0, var(FpX_GCD_LIMIT), t_FpX,10,0, speed_FpX_gcd,0.1}, {0, var(FpX_EXTGCD_LIMIT), t_FpX,10,0, speed_FpX_extgcd}, {0, var(RgX_MUL_LIMIT), t_FpX, 4,0, speed_RgX_mul}, {0, var(RgX_SQR_LIMIT), t_FpX, 4,0, speed_RgX_sqr}, }; /* ========================================================== */ int ndat = 0, allocdat = 0; struct dat_t { long size; double d; } *dat = NULL; int double_cmp_ptr(double *x, double *y) { return (int)(*x - *y); } double time_fun(speed_function_t fun, speed_param *s, long enabled) { const double TOLERANCE = 1.005; /* 0.5% */ pari_sp av = avma; double t[30]; ulong i, j, e; s->reps = 1; if (enabled) enable(s); else disable(s); for (i = 0; i < numberof(t); i++) { for (;;) { double reps_d; t[i] = fun(s); if (!t[i]) { s->reps *= 10; continue; } if (t[i] >= speed_unittime * speed_precision) break; /* go to a value of reps to make t[i] >= precision */ reps_d = ceil (1.1 * s->reps * speed_unittime * speed_precision / maxdd(t[i], speed_unittime)); if (reps_d > 2e9 || reps_d < 1.0) pari_err(e_MISC, "Fatal error: new reps bad: %.2f", reps_d); s->reps = (ulong)reps_d; } t[i] /= s->reps; /* require 3 values within TOLERANCE when >= 2 secs, 4 when below */ e = (t[0] >= 2.0)? 3: 4; /* Look for e many t[]'s within TOLERANCE of each other to consider a valid measurement. Return smallest among them. */ if (i >= e) { qsort (t, i+1, sizeof(t[0]), (QSCOMP)double_cmp_ptr); for (j = e-1; j < i; j++) if (t[j] <= t[j-e+1] * TOLERANCE) { avma = av; return t[j-e+1]; } } } pari_err(e_MISC,"couldn't measure time"); return -1.0; /* not reached */ } void add_dat(long size, double d) { if (ndat == allocdat) { allocdat += maxss(allocdat, 100); dat = (struct dat_t*) pari_realloc((void*)dat, allocdat * sizeof(dat[0])); } dat[ndat].size = size; dat[ndat].d = d; ndat++; } void diag(const char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); } void print_define(const char *name, long value) { printf("#define __%-25s %5ld\n", name, value); } long analyze_dat(int final) { double x, min_x; int j, min_j; /* If the threshold is set at dat[0].size, any positive values are bad. */ x = 0.0; for (j = 0; j < ndat; j++) if (dat[j].d > 0.0) x += dat[j].d; if (final && option_trace >= 3) { diag("\n"); diag("x is the sum of the badness from setting thresh at given size\n"); diag(" (minimum x is sought)\n"); diag("size=%ld first x=%.4f\n", dat[j].size, x); } min_x = x; min_j = 0; /* When stepping to the next dat[j].size, positive values are no longer bad (so subtracted), negative values become bad (so add the absolute value, meaning subtract). */ for (j = 0; j < ndat; j++) { if (final && option_trace >= 3) diag ("size=%ld x=%.4f\n", dat[j].size, x); if (x < min_x) { min_x = x; min_j = j; } x -= dat[j].d; } return min_j; } void Test(tune_param *param) { int since_positive, since_change, thresh, new_thresh; speed_param s; long save_var_disable = -1; pari_timer T; if (param->kernel == AVOID) { print_define(param->name, -1); return; } #define DEFAULT(x,n) if (! (param->x)) param->x = (n); DEFAULT(step_factor, Step_Factor); DEFAULT(stop_factor, 1.2); DEFAULT(max_size, 10000); if (param->var_disable) save_var_disable = *(param->var_disable); s.type = param->type; s.size = param->min_size; s.var = param->var; s.var_disable = param->var_disable; dftmod(&s); ndat = since_positive = since_change = thresh = 0; if (option_trace >= 1) { timer_start(&T); diag("\nSetting %s... (default %ld)\n", param->name, *(param->var)); } if (option_trace >= 2) { diag(" algorithm-A algorithm-B ratio possible\n"); diag(" (seconds) (seconds) diff thresh\n"); } for(;;) { pari_sp av=avma; double t1, t2, d; s.x = rand_g(s.size, s.type); s.y = rand_g(s.size, s.type); t1 = time_fun(param->fun, &s, 0); t2 = time_fun(param->fun, &s, 1); avma = av; if (t2 >= t1) d = (t2 - t1) / t2; else d = (t2 - t1) / t1; add_dat(s.size, d); new_thresh = analyze_dat(0); if (option_trace >= 2) diag ("size =%4ld %.8f %.8f % .4f %c %ld\n", s.size, t1,t2, d, d < 0? '#': ' ', dat[new_thresh].size); #define SINCE_POSITIVE 20 #define SINCE_CHANGE 50 /* Stop if method B has been consistently faster for a while */ if (d >= 0) since_positive = 0; else if (++since_positive > SINCE_POSITIVE) { if (option_trace >= 1) diag("Stop: since_positive (%d)\n", SINCE_POSITIVE); break; } /* Stop if method A has become slower by a certain factor */ if (t1 >= t2 * param->stop_factor) { if (option_trace >= 1) diag("Stop: t1 >= t2 * factor (%.1f)\n", param->stop_factor); break; } /* Stop if threshold implied hasn't changed for a while */ if (thresh != new_thresh) since_change = 0, thresh = new_thresh; else if (++since_change > SINCE_CHANGE) { if (option_trace >= 1) diag("Stop: since_change (%d)\n", SINCE_CHANGE); break; } s.size += maxss((long)floor(s.size * param->step_factor), 1); if (s.size >= param->max_size) { if (option_trace >= 1) diag("Stop: max_size (%ld). Disable Algorithm B?\n",param->max_size); break; } } thresh = dat[analyze_dat(1)].size; if (option_trace >= 1) diag("Total time: %gs\n", (double)timer_delay(&T)/1000.); 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; } void error(char **argv) { long i; diag("This is the PARI/GP tuning utility. Usage: tune [OPTION] var1 var2...\n"); diag("Options:\n"); diag(" -t: verbose output\n"); diag(" -tt: very verbose output\n"); diag(" -ttt: output everything\n"); diag(" -s xxx: set step factor between successive sizes to xxx (default 0.01)\n"); diag(" -p xxx: set Flx modulus to xxx (default 27449)\n"); diag(" -u xxx: set speed_unittime to xxx (default 1e-4s)\n"); diag("Tunable variables (omitting variable indices tunes everybody):\n"); for (i = 0; i < (long)numberof(param); i++) diag(" %2ld: %-25s (default %4ld)\n", i, param[i].name, *(param[i].var)); exit(1); } int main(int argc, char **argv) { int i, r, n = 0; GEN v; pari_init(8000000, 2); DFLT_mod = 27449; LARGE_mod=subis(powuu(3,128),62); #ifdef LONG_IS_64BIT DFLT_hmod = 257; DFLT_mod2 = 281474976710677UL; #else DFLT_hmod = 17; DFLT_mod1 = 1031UL; #endif v = new_chunk(argc); for (i = 1; i < argc; i++) { char *s = argv[i]; if (*s == '-') { switch(*++s) { case 't': option_trace++; while (*++s == 't') option_trace++; break; case 'p': if (!*++s) { if (++i == argc) error(argv); s = argv[i]; } DFLT_mod = itou(gp_read_str(s)); break; case 's': if (!*++s) { if (++i == argc) error(argv); s = argv[i]; } Step_Factor = atof(s); break; case 'u': s++; if (!*++s) { if (++i == argc) error(argv); s = argv[i]; } speed_unittime = atof(s); break; default: error(argv); } } else { if (!isdigit((int)*s)) error(argv); r = atol(s); if (r >= (long)numberof(param) || r < 0) error(argv); v[n++] = r; } } if (n) { for (i = 0; i < n; i++) Test(¶m[ v[i] ]); return 0; } n = numberof(param); for (i = 0; i < n; i++) Test(¶m[i]); return 0; } pari-2.7.5/src/test/64/0000755000175000017500000000000012613365633013115 5ustar billbillpari-2.7.5/src/test/64/ff0000644000175000017500000002740212405547147013441 0ustar billbill? 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 pari-2.7.5/src/test/64/bnr0000644000175000017500000000317512573550143013624 0ustar billbill[] [[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 1 1 [4, [2, 2], [[3, 1; 0, 1], [114, 1; 0, 1]]] [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0]] Total time spent: 20 pari-2.7.5/src/test/64/member0000644000175000017500000002633112405547147014315 0ustar billbill.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 pari-2.7.5/src/test/64/real0000644000175000017500000000014612405547147013765 0ustar billbill5.85492786017126177 E347063955532709820 1.707962973895205473 E-347063955532709821 Total time spent: 0 pari-2.7.5/src/test/64/ellanal0000644000175000017500000000102112405547147014443 0ustar billbill[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 pari-2.7.5/src/test/64/ell0000644000175000017500000003674012434214345013620 0ustar billbill-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 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: 580 pari-2.7.5/src/test/64/kernel0000644000175000017500000000265012405547147014324 0ustar billbillINT: 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 pari-2.7.5/src/test/64/bnrL10000644000175000017500000000715112612420700014004 0ustar billbill[[1, 0.38224508584003564132935849918485739404 + 0.E-38*I], [1, 0.38224508584 003564132935849918485739404 + 0.E-38*I], [0, -3/2]] [[[1], 0.69082574035845153597174938200391860974 - 0.141771150359113754753792 96778414429232*I], [[2], 0.45862410662771988186069579649547270634], [[3], 0. 69082574035845153597174938200391860974 + 0.141771150359113754753792967784144 29232*I]] [[[1], 0.74706478772303241588174336102451164905 - 0.396016528061576517014024 73588976342836*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 6*I]] [[[1, 0], 0.86715515057683562588616895054751987123 + 0.645139937243558470804 54579289618230200*I], [[2, 0], 0.69082574035845153597174938200391860974 + 0. 14177115035911375475379296778414429232*I], [[3, 0], 0.7470647877230324158817 4336102451164905 + 0.39601652806157651701402473588976342837*I], [[4, 0], 0.4 5862410662771988186069579649547270634], [[5, 0], 0.7470647877230324158817433 6102451164905 - 0.39601652806157651701402473588976342837*I], [[6, 0], 0.6908 2574035845153597174938200391860974 - 0.1417711503591137547537929677841442923 2*I], [[7, 0], 0.86715515057683562588616895054751987123 - 0.6451399372435584 7080454579289618230200*I], [[0, 1], 2.2792875031056225486323963801897796381] , [[1, 1], 0.86715515057683562588616895054751987123 + 0.64513993724355847080 454579289618230200*I], [[2, 1], 1.0193283594419870077704818539447783577 - 2. 6651386327279746491 E-39*I], [[3, 1], 0.747064787723032415881743361024511649 05 + 0.39601652806157651701402473588976342836*I], [[4, 1], 0.474851563147004 69763174924587287075804], [[5, 1], 0.74706478772303241588174336102451164905 - 0.39601652806157651701402473588976342836*I], [[6, 1], 1.019328359441987007 7704818539447783577 + 2.6651386327279746491 E-39*I], [[7, 1], 0.867155150576 83562588616895054751987123 - 0.64513993724355847080454579289618230200*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]] [0.90088685686467725961014440212013594076, 0.4063580640155376797096153264205 1751587, 0.40635806401553767970961532642051751587, 0.90088685686467725961014 440212013594076] Total time spent: 180 pari-2.7.5/src/test/64/compat0000644000175000017500000025557112413013143014322 0ustar billbill 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<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). [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] Total time spent: 1300 pari-2.7.5/src/test/64/incgam0000644000175000017500000000537212413013143014265 0ustar billbill 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 pari-2.7.5/src/test/64/nfields0000644000175000017500000007571312413013143014461 0ustar billbill 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 pari-2.7.5/src/test/32/0000755000175000017500000000000012613365633013110 5ustar billbillpari-2.7.5/src/test/32/nffactor0000644000175000017500000014206012413013143014620 0ustar billbill *** Warning: new stack size = 16000000 (15.259 Mbytes). [x^72 - 291*x^70 + 168*x^69 + 40380*x^68 - 48588*x^67 - 3528919*x^66 + 66721 20*x^65 + 215657160*x^64 - 575538144*x^63 - 9642387423*x^62 + 34735086786*x^ 61 + 318475831783*x^60 - 1543992152304*x^59 - 7526047084203*x^58 + 517099213 23996*x^57 + 110268119466273*x^56 - 1306863903654948*x^55 - 197687339387338* x^54 + 24340617020480994*x^53 - 37674206381844006*x^52 - 309388136734870296* x^51 + 1097175021601270233*x^50 + 1965430743178095924*x^49 - 170577413076819 44498*x^48 + 12695705864721864408*x^47 + 149941210123858078557*x^46 - 449449 010694960248724*x^45 - 360137445013361079753*x^44 + 4743771886303072354536*x ^43 - 7957480107528139931362*x^42 - 20006312987061736459890*x^41 + 103127662 005251951018025*x^40 - 57922725775374790826892*x^39 - 5753749773364770608784 06*x^38 + 1141042155363070337681952*x^37 + 2107623272811930164219492*x^36 - 8555883275792119671168984*x^35 - 6622038332271478648217502*x^34 + 6778849907 3804904961005264*x^33 - 62194621346216574281355513*x^32 - 298503076979390816 950994616*x^31 + 935868776923024509133161567*x^30 - 602191893688026944562387 144*x^29 - 2378403718028116295265005703*x^28 + 7144715267789671188060423636* x^27 - 8264313767410946129053876314*x^26 - 2988303993119955116599622124*x^25 + 36320303706133493815706370331*x^24 - 93405543373036036850518472592*x^23 + 137892731303549623166716872621*x^22 - 73374564495372153466268524626*x^21 - 180690507689854149951443988039*x^20 + 506199649638427572646328975856*x^19 - 511453665473658325356669209047*x^18 - 183193264910244539106552118338*x^17 + 1423840911419731272911578335897*x^16 - 2367314022969857609246689985844*x^15 + 2236677523353346112926136338695*x^14 - 1548489683091587051973217338168*x^1 3 + 2105049137205776145162583648404*x^12 - 4754348311294629767834593856064*x ^11 + 7567806891220394207855512254933*x^10 - 7605431066578089163623568649610 *x^9 + 3882625664788999249342771140339*x^8 + 1356469287400668040516453202076 *x^7 - 3841355512345259545848813224621*x^6 + 2330504083587501732658867007532 *x^5 - 169172628407290891217225606775*x^4 - 398965703199322569698936377044*x ^3 + 198978398979453484569202793808*x^2 - 60597282938946837445378411698*x + 12280639561039083425818958713]~ [x^48 + 12*x^46 + 948*x^44 + 7200*x^42 + 152361*x^40 + 815832*x^38 + 9475380 *x^36 + 44654004*x^34 + 299137536*x^32 + 1335241260*x^30 + 5029216452*x^28 + 15282825984*x^26 + 37737671337*x^24 + 79579803672*x^22 + 143658877428*x^20 + 222699104460*x^18 + 303698198961*x^16 + 348787956312*x^14 + 312863646960*x ^12 + 212893847424*x^10 + 111407984496*x^8 + 43762394880*x^6 + 11836253952*x ^4 + 1904684544*x^2 + 136048896]~ [x^48 - 104*x^46 + 4664*x^44 - 122476*x^42 + 2137838*x^40 - 26567700*x^38 + 245144964*x^36 - 1725955872*x^34 + 9441692003*x^32 - 40611588644*x^30 + 1383 56971048*x^28 - 374714866240*x^26 + 807289826646*x^24 - 1380693858220*x^22 + 1866021172640*x^20 - 1978766780068*x^18 + 1630151673857*x^16 - 102950530102 4*x^14 + 489498952012*x^12 - 170832297056*x^10 + 42133382284*x^8 - 690450713 6*x^6 + 669868016*x^4 - 28899680*x^2 + 16]~ [x^64 - 6384*x^62 + 18261761*x^60 - 31231019568*x^58 + 35925400902280*x^56 - 29635423138225800*x^54 + 18244443900381139917*x^52 - 8609789775431197305288 *x^50 + 3173715440318358526295493*x^48 - 926253189958924421506713024*x^46 + 216130107574547887816493973792*x^44 - 40600173780591579547211667354912*x^42 + 6168621134132051706341715912515370*x^40 - 76013943427734813586799139295141 5744*x^38 + 76052955647065900426700689494084391434*x^36 - 617531184355441677 2593815034596603661344*x^34 + 406137362468726923132369140307868626461744*x^3 2 - 21559959594011538596615817038079394912524336*x^30 + 91912201022866770299 8458013093798368177514170*x^28 - 3125139901367629320825272825691018301064633 1888*x^26 + 840017792466500823059432352741453680599704357258*x^24 - 17651171 087877975905738341268934550365403253370816*x^22 + 28594069425611136664663397 3109729677687028435758880*x^20 - 3510138236669349338216717168753743720690200 440965920*x^18 + 31970659328447652254136627725804141367170891626180389*x^16 - 210577501276259853380917767547980363666145460503950096*x^14 + 972633665701 140285445722173171004563157651576027463941*x^12 - 30387893683293821798844628 51269146550248145196800679728*x^10 + 615892792889658839667059092889638564907 5890120481042824*x^8 - 76951350792700777906576936340585240393085356418600329 04*x^6 + 5510293734552561962521574495431679567021222445632508873*x^4 - 19987 78331104544904932086470347413669495129560426038280*x^2 + 2738927449953408337 77347939263771534786080723599733441]~ [x^8 + (-1531349/22619785297920*y^14 + 559416343/10977248747520*y^12 - 25247 684591/1995863408640*y^10 + 103982297321/80715064320*y^8 - 76714376249/12229 55520*y^6 + 111774992009/74186640*y^4 - 26292202739/1686060*y^2 + 1564021312 /54549)*x^6 + (19000645309/37322645741568*y^14 - 96552535399/249482926080*y^ 12 + 536960987254321/5488624373760*y^10 - 4194944378809/407651840*y^8 + 5247 721708074653/10089383040*y^6 - 10860233882239/843030*y^4 + 630194805031381/4 636665*y^2 - 796961577488/2755)*x^4 + (-29172555558095/18661322870784*y^14 + 5062445860141/4248161280*y^12 - 92318704732060083/304923576320*y^10 + 64819 3176741591037/20178766080*y^8 - 8268979844194150111/5044691520*y^6 + 1896413 90835405983/4636665*y^4 - 223283186783900366/515185*y^2 + 8946625664367872/9 405)*x^2 + (41018074761203773/23326653588480*y^14 - 409009053454624763/30492 3576320*y^12 + 117044119382956746521/343039023360*y^10 - 2927890424340695147 291/80715064320*y^8 + 4678762405288733527739/2522345760*y^6 - 38206315875334 762391/824296*y^4 + 2278645136881067296952/4636665*y^2 - 2967400235256172868 48/272745), x^8 + (-16146091/248817638277120*y^14 + 48843457/997931704320*y^ 12 - 267727721489/21954497495040*y^10 + 9174250019/7337733120*y^8 - 82557283 8631/13452510720*y^6 + 10012035071/6744240*y^4 - 286258292621/18546660*y^2 + 140187040/4959)*x^6 + (1723176289/3392967794688*y^14 - 1059662276341/274431 2186880*y^12 + 48715274000629/498965852160*y^10 - 69104247053959/6726255360* y^8 + 476508837255737/917216640*y^6 - 238731150890387/18546660*y^4 + 5725141 8840649/421515*y^2 - 26269467866896/90915)*x^4 + (-29113232197835/1866132287 0784*y^14 + 1631934517436717/1372156093440*y^12 - 92145545361015407/30492357 6320*y^10 + 323550303468175019/10089383040*y^8 - 8257197132303274099/5044691 520*y^6 + 378862459377191059/9273330*y^4 - 223115572203411654/515185*y^2 + 2 59332507639972352/272745)*x^2 + (40511288842122127/23326653588480*y^14 - 454 626079701495571/343039023360*y^12 + 231451885839430725263/686078046720*y^10 - 60389017554715183063/1681563840*y^8 + 2319938341838169992923/1261172880*y^ 6 - 42704610621363386060/927333*y^4 + 2268063476824046324248/4636665*y^2 - 9 8528590048656718144/90915), x^8 + (181633/186613228707840*y^14 - 6489/138601 62560*y^12 - 45386471/5488624373760*y^10 + 178250659/7337733120*y^8 - 259150 32257/10089383040*y^6 + 126060163/1498720*y^4 - 4457231129/4636665*y^2 + 945 4484/4959)*x^6 + (-11712673/1169988894720*y^14 + 2040142733/274431218688*y^1 2 - 93021416071/52522721280*y^10 + 1688263641205/10762008576*y^8 - 890698149 9371/1834433280*y^6 + 14859994827859/296746560*y^4 - 27539242721/421515*y^2 - 10412804654/90915)*x^4 + (-65739851389/2915831698560*y^14 + 8080067384671/ 548862437376*y^12 - 615919067582923/228692682240*y^10 + 7139625968047/558581 76*y^8 - 12035658240536459/5044691520*y^6 + 2909281718459207/148373280*y^4 - 114027481266257/1545555*y^2 + 26994839222348/272745)*x^2 + (351875661187594 13/746452914831360*y^14 - 175794408000830383/5488624373760*y^12 + 2827285081 9680893321/4390899499008*y^10 - 44274526240947916361/107620085760*y^8 + 4488 83263777097920391/40357532160*y^6 - 2698220779200958903/20465280*y^4 + 28100 59487221296958/4636665*y^2 - 81508587175798061/90915), x^8 + (3074279/248817 638277120*y^14 - 127157047/10977248747520*y^12 + 86499746437/21954497495040* y^10 - 2843672497/4747944960*y^8 + 109487803351/2690502144*y^6 - 89990421617 /74186640*y^4 + 52396810109/3709332*y^2 - 13670576288/272745)*x^6 + (-361812 87281/186613228707840*y^14 + 446988241097/2744312186880*y^12 - 2791944232079 /57774993408*y^10 + 85916604196211/13452510720*y^8 - 3999057670537517/100893 83040*y^6 + 3070998321176/272745*y^4 - 593787426492949/4636665*y^2 + 3730615 4735728/90915)*x^4 + (64206977604683/93306614353920*y^14 - 781339956430123/1 372156093440*y^12 + 151234315443075961/914770728960*y^10 - 42955239518225908 7/20178766080*y^8 + 1307386034599317571/1008938304*y^6 - 168786176615470804/ 4636665*y^4 + 127255299187877218/309111*y^2 - 351207138657683456/272745)*x^2 + (-18530706211095341/23326653588480*y^14 + 1798847927551103773/27443121868 80*y^12 - 16252626552763832987/85759755840*y^10 + 653145277562478020663/2690 5021440*y^8 - 742591759365166575365/504469152*y^6 + 1530656313511014482581/3 7093320*y^4 - 432314981823305760184/927333*y^2 + 131680859590220167616/90915 ), x^8 + (3692011/248817638277120*y^14 - 8644699/645720514560*y^12 + 9566281 9793/21954497495040*y^10 - 51309940321/80715064320*y^8 + 113348313275/269050 2144*y^6 - 91885783933/74186640*y^4 + 53072545513/3709332*y^2 - 13761686272/ 272745)*x^6 + (-1260198851/6434938920960*y^14 + 450923192773/2744312186880*y ^12 - 53418556138459/1097724874752*y^10 + 43167277559347/6726255360*y^8 - 40 11960654104563/10089383040*y^6 + 209270128922867/18546660*y^4 - 594571618949 411/4636665*y^2 + 37329116221552/90915)*x^4 + (3385038072653/4910874439680*y ^14 - 782493705352717/1372156093440*y^12 + 151409707529271949/914770728960*y ^10 - 214941552982993939/10089383040*y^8 + 1308011461994334679/1008938304*y^ 6 - 337682297591934347/9273330*y^4 + 127297072825004458/309111*y^2 - 3513766 27887928064/272745)*x^2 + (-18884591927033039/23326653588480*y^14 + 76223129 967189533/114346341120*y^12 - 131815203944675271599/686078046720*y^10 + 1236 67566697208858791/5044691520*y^8 - 373763922533488473487/252234576*y^6 + 116 278861122276976/2805*y^4 - 433850608352102566712/927333*y^2 + 39636262539108 2293312/272745), x^8 + (1192483/67859355893760*y^14 - 46386469/3659082915840 *y^12 + 5757671539/1995863408640*y^10 - 9816397597/40357532160*y^8 + 3150430 0903/3668866560*y^6 - 6499115329/49457760*y^4 + 1346529151/1686060*y^2 - 127 928104/54549)*x^6 + (-377107043/23326653588480*y^14 + 1193294195/99793170432 *y^12 - 3898646479517/1372156093440*y^10 + 83324546651/326121472*y^8 - 90270 807160297/10089383040*y^6 + 203979621263/1586880*y^4 - 6453521496733/9273330 *y^2 + 3740713928/2755)*x^4 + (-55838547409/2455437219840*y^14 + 81535888034 65/548862437376*y^12 - 1244323126435859/457385364480*y^10 + 2090484253417429 /16143012864*y^8 - 12134063030016491/5044691520*y^6 + 165453933807769/872784 0*y^4 - 93498888636323/1545555*y^2 + 14213849400992/272745)*x^2 + (118472423 79734429/248817638277120*y^14 - 177668994581955997/5488624373760*y^12 + 2861 1858755746067827/4390899499008*y^10 - 134874618655070911657/322860257280*y^8 + 152404618518667558583/13452510720*y^6 - 4203829397104185047/31236480*y^4 + 2871462472553380217/4636665*y^2 - 250004160368295232/272745), x^8 + (64582 73/186613228707840*y^14 - 3719191/152461788160*y^12 + 29024100473/5488624373 760*y^10 - 32135840999/80715064320*y^8 + 23297956603/2017876608*y^6 - 211350 0871/16485920*y^4 + 408266029/927333*y^2 - 316594868/272745)*x^6 + (-1110768 17459/373226457415680*y^14 + 18106275053/85759755840*y^12 - 509560146214411/ 10977248747520*y^10 + 195109797344857/53810042880*y^8 - 2298235154532701/201 78766080*y^6 + 87655160117623/59349312*y^4 - 32564739888281/4636665*y^2 + 96 8008850258/90915)*x^4 + (83518124920963/93306614353920*y^14 - 91728776500189 /144437483520*y^12 + 42591591062192407/304923576320*y^10 - 88154696029372417 3/80715064320*y^8 + 86773202255301785/252234576*y^6 - 665429827885409833/148 373280*y^4 + 2218979482348247/103037*y^2 - 8878201815711796/272745)*x^2 + (- 246642305436057809/248817638277120*y^14 + 3860028638255806541/5488624373760* y^12 - 3395672666468176433467/21954497495040*y^10 + 3904062052800146734661/3 22860257280*y^8 - 1024736920815948655471/2690502144*y^6 + 294713641271965414 9381/593493120*y^4 - 22118315020431326588/927333*y^2 + 9833627869746746873/2 72745), x^8 + (38996983/746452914831360*y^14 - 45610777/1219694305280*y^12 + 184040442823/21954497495040*y^10 - 6929849477/10089383040*y^8 + 19138097395 1/8071506432*y^6 - 6002605199/16485920*y^4 + 8595505583/3709332*y^2 - 144096 9832/272745)*x^6 + (-56627432063/186613228707840*y^14 + 1182421824943/548862 4373760*y^12 - 260406121516747/5488624373760*y^10 + 200262331426543/53810042 880*y^8 - 297480952643123/2522345760*y^6 + 92330503999361/59349312*y^4 - 710 13869059163/9273330*y^2 + 1098811062152/90915)*x^4 + (83613652919587/9330661 4353920*y^14 - 1744863264395929/2744312186880*y^12 + 42642092214501583/30492 3576320*y^10 - 882655350615967327/80715064320*y^8 + 173789516969368021/50446 9152*y^6 - 666541614309814567/148373280*y^4 + 2223816735480437/103037*y^2 - 306949426473056/9405)*x^2 + (-742452471836109913/746452914831360*y^14 + 3873 208908206849579/5488624373760*y^12 - 3407275945042823422193/21954497495040*y ^10 + 1305807204358253484253/107620085760*y^8 - 3084740075192713038863/80715 06432*y^6 + 173955024027274456667/34911360*y^4 - 22194121937138006191/927333 *y^2 + 3289110492164463424/90915)]~ [x^2 + (-872560111/1750783970525184*y^18 - 103213549/291797328420864*y^16 - 4176139757/7204872306688*y^14 - 4416978655/10807308460032*y^12 - 13066402491 575/72949332105216*y^10 - 215588492387/1736888859648*y^8 - 892238763206647/1 09423998157824*y^6 - 89512294102405/18237333026304*y^4 - 18290521472141/2532 96292032*y^2 - 284080544581/14072016224), x^2 + (872560111/1750783970525184* y^18 - 103213549/291797328420864*y^16 + 4176139757/7204872306688*y^14 - 4416 978655/10807308460032*y^12 + 13066402491575/72949332105216*y^10 - 2155884923 87/1736888859648*y^8 + 892238763206647/109423998157824*y^6 - 89512294102405/ 18237333026304*y^4 + 18290521472141/253296292032*y^2 - 284080544581/14072016 224), x^2 + (-10955729699/63028222938906624*y^19 + 1635275/72949332105216*y^ 17 - 471200483153/2334378627366912*y^15 + 68074817/2701827115008*y^13 - 1631 44665311371/2626175955787776*y^11 + 10788711995/1519777752192*y^9 - 10805585 507756651/3939263933681664*y^7 + 476476835441/4559333256576*y^5 - 6980744239 9435/3039555504384*y^3 - 4848316573/3518004056*y)*x + (-240314803/1313087977 893888*y^18 + 2177899/20842666315776*y^16 - 10352388961/48632888070144*y^14 + 650809375/5403654230016*y^12 - 3599460371687/54711999078912*y^10 + 2204400 27581/6079111008768*y^8 - 35061053609941/11723999802624*y^6 + 11692976745493 /9118666513152*y^4 - 1447968833323/63324073008*y^2 - 24126350651/7036008112) , x^2 + (-4768637809/63028222938906624*y^19 - 116295749/1750783970525184*y^1 7 - 205045552843/2334378627366912*y^15 - 4961577191/64843850760192*y^13 - 10 134809023919/375167993683968*y^11 - 1681738838629/72949332105216*y^9 - 46714 70958726025/3939263933681664*y^7 - 93324108785933/109423998157824*y^5 - 2896 7498100409/3039555504384*y^3 - 245294011997/84432097344*y)*x + (-496188853/1 750783970525184*y^18 + 8017631/48632888070144*y^16 - 338265737/1029267472384 *y^14 + 338938437/1801218076672*y^12 - 7349975872277/72949332105216*y^10 + 1 12959067435/2026370336256*y^8 - 471966038240125/109423998157824*y^6 + 558940 2408335/3039555504384*y^4 - 8241706316231/253296292032*y^2 + 1651761915/1005 144016), x^2 + (-550587305/9004031848415232*y^19 - 8520109/250111995789312*y ^17 - 165341932517/2334378627366912*y^15 - 2570761369/64843850760192*y^13 - 56851147336519/2626175955787776*y^11 - 895619999627/72949332105216*y^9 - 356 0831957116295/3939263933681664*y^7 - 62314525927891/109423998157824*y^5 - 18 560457963575/3039555504384*y^3 - 371119778467/84432097344*y)*x + (496188853/ 1750783970525184*y^18 + 8017631/48632888070144*y^16 + 338265737/102926747238 4*y^14 + 338938437/1801218076672*y^12 + 7349975872277/72949332105216*y^10 + 112959067435/2026370336256*y^8 + 471966038240125/109423998157824*y^6 + 55894 02408335/3039555504384*y^4 + 8241706316231/253296292032*y^2 + 1651761915/100 5144016), x^2 + (-21512837/1313087977893888*y^19 - 102134281/175078397052518 4*y^17 - 932348591/48632888070144*y^15 - 4407863827/64843850760192*y^13 - 16 4654686001/27355999539456*y^11 - 1540975821641/72949332105216*y^9 - 25030796 719091/82067998618368*y^7 - 110013175606897/109423998157824*y^5 - 7018393859 /2261574036*y^3 - 296247471259/28144032448*y)*x + (240314803/131308797789388 8*y^18 + 2177899/20842666315776*y^16 + 10352388961/48632888070144*y^14 + 650 809375/5403654230016*y^12 + 3599460371687/54711999078912*y^10 + 220440027581 /6079111008768*y^8 + 35061053609941/11723999802624*y^6 + 11692976745493/9118 666513152*y^4 + 1447968833323/63324073008*y^2 - 24126350651/7036008112), x^2 + (21512837/1313087977893888*y^19 + 102134281/1750783970525184*y^17 + 93234 8591/48632888070144*y^15 + 4407863827/64843850760192*y^13 + 164654686001/273 55999539456*y^11 + 1540975821641/72949332105216*y^9 + 25030796719091/8206799 8618368*y^7 + 110013175606897/109423998157824*y^5 + 7018393859/2261574036*y^ 3 + 296247471259/28144032448*y)*x + (240314803/1313087977893888*y^18 + 21778 99/20842666315776*y^16 + 10352388961/48632888070144*y^14 + 650809375/5403654 230016*y^12 + 3599460371687/54711999078912*y^10 + 220440027581/6079111008768 *y^8 + 35061053609941/11723999802624*y^6 + 11692976745493/9118666513152*y^4 + 1447968833323/63324073008*y^2 - 24126350651/7036008112), x^2 + (550587305/ 9004031848415232*y^19 + 8520109/250111995789312*y^17 + 165341932517/23343786 27366912*y^15 + 2570761369/64843850760192*y^13 + 56851147336519/262617595578 7776*y^11 + 895619999627/72949332105216*y^9 + 3560831957116295/3939263933681 664*y^7 + 62314525927891/109423998157824*y^5 + 18560457963575/3039555504384* y^3 + 371119778467/84432097344*y)*x + (496188853/1750783970525184*y^18 + 801 7631/48632888070144*y^16 + 338265737/1029267472384*y^14 + 338938437/18012180 76672*y^12 + 7349975872277/72949332105216*y^10 + 112959067435/2026370336256* y^8 + 471966038240125/109423998157824*y^6 + 5589402408335/3039555504384*y^4 + 8241706316231/253296292032*y^2 + 1651761915/1005144016), x^2 + (4768637809 /63028222938906624*y^19 + 116295749/1750783970525184*y^17 + 205045552843/233 4378627366912*y^15 + 4961577191/64843850760192*y^13 + 10134809023919/3751679 93683968*y^11 + 1681738838629/72949332105216*y^9 + 4671470958726025/39392639 33681664*y^7 + 93324108785933/109423998157824*y^5 + 28967498100409/303955550 4384*y^3 + 245294011997/84432097344*y)*x + (-496188853/1750783970525184*y^18 + 8017631/48632888070144*y^16 - 338265737/1029267472384*y^14 + 338938437/18 01218076672*y^12 - 7349975872277/72949332105216*y^10 + 112959067435/20263703 36256*y^8 - 471966038240125/109423998157824*y^6 + 5589402408335/303955550438 4*y^4 - 8241706316231/253296292032*y^2 + 1651761915/1005144016), x^2 + (1095 5729699/63028222938906624*y^19 - 1635275/72949332105216*y^17 + 471200483153/ 2334378627366912*y^15 - 68074817/2701827115008*y^13 + 163144665311371/262617 5955787776*y^11 - 10788711995/1519777752192*y^9 + 10805585507756651/39392639 33681664*y^7 - 476476835441/4559333256576*y^5 + 69807442399435/3039555504384 *y^3 + 4848316573/3518004056*y)*x + (-240314803/1313087977893888*y^18 + 2177 899/20842666315776*y^16 - 10352388961/48632888070144*y^14 + 650809375/540365 4230016*y^12 - 3599460371687/54711999078912*y^10 + 220440027581/607911100876 8*y^8 - 35061053609941/11723999802624*y^6 + 11692976745493/9118666513152*y^4 - 1447968833323/63324073008*y^2 - 24126350651/7036008112)]~ [x^24 + 69]~ [x^7 - 2*y*x^6 + y^2*x^5 - 28*x^3 + 4*y^2*x + 16/7*y^3, x^7 + 2*y*x^6 + y^2* x^5 - 28*x^3 + 4*y^2*x - 16/7*y^3, x^7 - 2/7*y^3*x^6 - y^2*x^5 - 28*x^3 - 4* y^2*x + 16*y, x^7 + 2/7*y^3*x^6 - y^2*x^5 - 28*x^3 - 4*y^2*x - 16*y]~ [x^2 + (-12035/386*y^15 + 8337/386*y^14 + 566267/772*y^13 - 392327/772*y^12 - 4449119/772*y^11 + 3083327/772*y^10 + 7320431/386*y^9 - 2537889/193*y^8 - 9975849/386*y^7 + 3461954/193*y^6 + 10712085/772*y^5 - 7445851/772*y^4 - 190 5321/772*y^3 + 1322419/772*y^2 + 25961/386*y - 17735/386), x^2 + (-7909/772* y^15 - 1879/772*y^14 + 93535/386*y^13 + 44921/772*y^12 - 371330/193*y^11 - 9 0974/193*y^10 + 4991389/772*y^9 + 317305/193*y^8 - 7127131/772*y^7 - 1947859 /772*y^6 + 2110371/386*y^5 + 1295397/772*y^4 - 224091/193*y^3 - 160649/386*y ^2 + 19739/772*y + 4029/386), x^2 + (7909/772*y^15 - 1879/772*y^14 - 93535/3 86*y^13 + 44921/772*y^12 + 371330/193*y^11 - 90974/193*y^10 - 4991389/772*y^ 9 + 317305/193*y^8 + 7127131/772*y^7 - 1947859/772*y^6 - 2110371/386*y^5 + 1 295397/772*y^4 + 224091/193*y^3 - 160649/386*y^2 - 19739/772*y + 4029/386), x^2 + (12035/386*y^15 + 8337/386*y^14 - 566267/772*y^13 - 392327/772*y^12 + 4449119/772*y^11 + 3083327/772*y^10 - 7320431/386*y^9 - 2537889/193*y^8 + 99 75849/386*y^7 + 3461954/193*y^6 - 10712085/772*y^5 - 7445851/772*y^4 + 19053 21/772*y^3 + 1322419/772*y^2 - 25961/386*y - 17735/386), x^4 + (541/386*y^14 - 12373/386*y^12 + 46089/193*y^10 - 137477/193*y^8 + 311469/386*y^6 - 14604 9/386*y^4 + 12308/193*y^2 - 686/193)*x^2 + (-765/772*y^14 + 8659/386*y^12 - 126401/772*y^10 + 90322/193*y^8 - 369401/772*y^6 + 38430/193*y^4 - 23865/772 *y^2 + 553/386), x^4 + (2052/193*y^14 - 96741/386*y^12 + 763031/386*y^10 - 1 265475/193*y^8 + 1759047/193*y^6 - 2000657/386*y^4 + 430823/386*y^2 - 13920/ 193)*x^2 + (-28293/772*y^14 + 166359/193*y^12 - 5225705/772*y^10 + 4295689/1 93*y^8 - 23400329/772*y^6 + 6320077/386*y^4 - 2369321/772*y^2 + 45727/386), x^4 + (-5155/193*y^15 - 15405/772*y^14 + 241769/386*y^13 + 180325/386*y^12 - 944044/193*y^11 - 2807115/772*y^10 + 3072303/193*y^9 + 2267740/193*y^8 - 41 02400/193*y^7 - 11896515/772*y^6 + 4334901/386*y^5 + 2988835/386*y^4 - 43236 3/193*y^3 - 1014845/772*y^2 + 23130/193*y + 3602/193)*x^2 + (14406/193*y^15 + 38997/772*y^14 - 338423/193*y^13 - 455769/386*y^12 + 2652454/193*y^11 + 70 72893/772*y^10 - 8698762/193*y^9 - 11354279/386*y^8 + 23683093/386*y^7 + 293 19183/772*y^6 - 13169735/386*y^5 - 7082173/386*y^4 + 3014249/386*y^3 + 21677 71/772*y^2 - 244333/386*y + 2027/386), x^4 + (-4705/193*y^15 - 4035/772*y^14 + 220691/386*y^13 + 47935/386*y^12 - 1722817/386*y^11 - 767525/772*y^10 + 5 588151/386*y^9 + 654320/193*y^8 - 3658160/193*y^7 - 3833005/772*y^6 + 341354 7/386*y^5 + 1159745/386*y^4 - 194425/386*y^3 - 441715/772*y^2 - 129025/386*y - 9518/193)*x^2 + (69045/772*y^15 + 17477/772*y^14 - 1634153/772*y^13 - 208 093/386*y^12 + 12990539/772*y^11 + 3347413/772*y^10 - 43749763/772*y^9 - 576 5109/386*y^8 + 62724993/772*y^7 + 17320883/772*y^6 - 37352513/772*y^5 - 5621 249/386*y^4 + 7969659/772*y^3 + 2742727/772*y^2 - 182407/772*y - 34007/386), x^4 + (4705/193*y^15 - 4035/772*y^14 - 220691/386*y^13 + 47935/386*y^12 + 1 722817/386*y^11 - 767525/772*y^10 - 5588151/386*y^9 + 654320/193*y^8 + 36581 60/193*y^7 - 3833005/772*y^6 - 3413547/386*y^5 + 1159745/386*y^4 + 194425/38 6*y^3 - 441715/772*y^2 + 129025/386*y - 9518/193)*x^2 + (-69045/772*y^15 + 1 7477/772*y^14 + 1634153/772*y^13 - 208093/386*y^12 - 12990539/772*y^11 + 334 7413/772*y^10 + 43749763/772*y^9 - 5765109/386*y^8 - 62724993/772*y^7 + 1732 0883/772*y^6 + 37352513/772*y^5 - 5621249/386*y^4 - 7969659/772*y^3 + 274272 7/772*y^2 + 182407/772*y - 34007/386), x^4 + (5155/193*y^15 - 15405/772*y^14 - 241769/386*y^13 + 180325/386*y^12 + 944044/193*y^11 - 2807115/772*y^10 - 3072303/193*y^9 + 2267740/193*y^8 + 4102400/193*y^7 - 11896515/772*y^6 - 433 4901/386*y^5 + 2988835/386*y^4 + 432363/193*y^3 - 1014845/772*y^2 - 23130/19 3*y + 3602/193)*x^2 + (-14406/193*y^15 + 38997/772*y^14 + 338423/193*y^13 - 455769/386*y^12 - 2652454/193*y^11 + 7072893/772*y^10 + 8698762/193*y^9 - 11 354279/386*y^8 - 23683093/386*y^7 + 29319183/772*y^6 + 13169735/386*y^5 - 70 82173/386*y^4 - 3014249/386*y^3 + 2167771/772*y^2 + 244333/386*y + 2027/386) ]~ [x^4 - 4*y*x^3 + (-1/2*y^14 + 1/2*y^10 - 7/2*y^6 + 15/2*y^2)*x^2 + (y^15 - y ^11 + 7*y^7 - 7*y^3)*x + (1/2*y^12 - y^8 + 5/2*y^4 - 2), x^4 + 4*y*x^3 + (-1 /2*y^14 + 1/2*y^10 - 7/2*y^6 + 15/2*y^2)*x^2 + (-y^15 + y^11 - 7*y^7 + 7*y^3 )*x + (1/2*y^12 - y^8 + 5/2*y^4 - 2), x^4 + (-2*y^11 - 10*y^3)*x^3 + (9/2*y^ 14 - 1/2*y^10 + 55/2*y^6 - 7/2*y^2)*x^2 + (3*y^13 + y^9 + 17*y^5 + 3*y)*x + (1/2*y^12 + y^8 + 5/2*y^4 + 4), x^4 + (2*y^11 + 10*y^3)*x^3 + (9/2*y^14 - 1/ 2*y^10 + 55/2*y^6 - 7/2*y^2)*x^2 + (-3*y^13 - y^9 - 17*y^5 - 3*y)*x + (1/2*y ^12 + y^8 + 5/2*y^4 + 4), x^4 + (-2*y^13 - 10*y^5)*x^3 + (1/2*y^14 - 1/2*y^1 0 + 7/2*y^6 - 15/2*y^2)*x^2 + (3*y^15 + y^11 + 17*y^7 + 3*y^3)*x + (1/2*y^12 - y^8 + 5/2*y^4 - 2), x^4 + (-y^13 - y^9 - 7*y^5 - 3*y)*x^3 + (7/2*y^14 - 1 /2*y^10 + 37/2*y^6 - 3/2*y^2)*x^2 + (-y^15 + y^11 - 7*y^7 + 7*y^3)*x + (-1/2 *y^12 - y^8 - 5/2*y^4 - 2), x^4 + (-y^13 + y^9 - 7*y^5 + 3*y)*x^3 + (-7/2*y^ 14 + 1/2*y^10 - 37/2*y^6 + 3/2*y^2)*x^2 + (-3*y^15 - y^11 - 17*y^7 - 3*y^3)* x + (-1/2*y^12 - y^8 - 5/2*y^4 - 2), x^4 + (y^13 - y^9 + 7*y^5 - 3*y)*x^3 + (-7/2*y^14 + 1/2*y^10 - 37/2*y^6 + 3/2*y^2)*x^2 + (3*y^15 + y^11 + 17*y^7 + 3*y^3)*x + (-1/2*y^12 - y^8 - 5/2*y^4 - 2), x^4 + (y^13 + y^9 + 7*y^5 + 3*y) *x^3 + (7/2*y^14 - 1/2*y^10 + 37/2*y^6 - 3/2*y^2)*x^2 + (y^15 - y^11 + 7*y^7 - 7*y^3)*x + (-1/2*y^12 - y^8 - 5/2*y^4 - 2), x^4 + (2*y^13 + 10*y^5)*x^3 + (1/2*y^14 - 1/2*y^10 + 7/2*y^6 - 15/2*y^2)*x^2 + (-3*y^15 - y^11 - 17*y^7 - 3*y^3)*x + (1/2*y^12 - y^8 + 5/2*y^4 - 2), x^4 + (-4*y^15 - 24*y^7)*x^3 + ( -9/2*y^14 + 1/2*y^10 - 55/2*y^6 + 7/2*y^2)*x^2 + (-y^13 + y^9 - 7*y^5 + 7*y) *x + (1/2*y^12 + y^8 + 5/2*y^4 + 4), x^4 + (-3*y^15 - y^11 - 17*y^7 - 7*y^3) *x^3 + (3/2*y^14 - 5/2*y^10 + 17/2*y^6 - 23/2*y^2)*x^2 + (3*y^13 + y^9 + 17* y^5 + 3*y)*x + (-1/2*y^12 + y^8 - 5/2*y^4 + 4), x^4 + (-3*y^15 + y^11 - 17*y ^7 + 7*y^3)*x^3 + (-3/2*y^14 + 5/2*y^10 - 17/2*y^6 + 23/2*y^2)*x^2 + (-y^13 + y^9 - 7*y^5 + 7*y)*x + (-1/2*y^12 + y^8 - 5/2*y^4 + 4), x^4 + (3*y^15 - y^ 11 + 17*y^7 - 7*y^3)*x^3 + (-3/2*y^14 + 5/2*y^10 - 17/2*y^6 + 23/2*y^2)*x^2 + (y^13 - y^9 + 7*y^5 - 7*y)*x + (-1/2*y^12 + y^8 - 5/2*y^4 + 4), x^4 + (3*y ^15 + y^11 + 17*y^7 + 7*y^3)*x^3 + (3/2*y^14 - 5/2*y^10 + 17/2*y^6 - 23/2*y^ 2)*x^2 + (-3*y^13 - y^9 - 17*y^5 - 3*y)*x + (-1/2*y^12 + y^8 - 5/2*y^4 + 4), x^4 + (4*y^15 + 24*y^7)*x^3 + (-9/2*y^14 + 1/2*y^10 - 55/2*y^6 + 7/2*y^2)*x ^2 + (y^13 - y^9 + 7*y^5 - 7*y)*x + (1/2*y^12 + y^8 + 5/2*y^4 + 4)]~ [x^64 + 192*x^62 + 17568*x^60 + 1019520*x^58 + 42131676*x^56 + 1319651424*x^ 54 + 32559096528*x^52 + 649228312512*x^50 + 10651553826426*x^48 + 1456394385 52224*x^46 + 1674922821206832*x^44 + 16307859539653056*x^42 + 13502367773216 7696*x^40 + 953248899971965824*x^38 + 5745239175305568960*x^36 + 29556064271 185194240*x^34 + 129595725382952883843*x^32 + 483002100692576612640*x^30 + 1 523870714370199019760*x^28 + 4047489983524093705152*x^26 + 89858128286488620 19536*x^24 + 16525310345394167002752*x^22 + 24893927149975603242048*x^20 + 3 0294355815129821928192*x^18 + 29274561574319887883226*x^16 + 219878017711043 40121824*x^14 + 12494344840480632094992*x^12 + 5187763623118143696192*x^10 + 1502211081063677383836*x^8 + 283567347515314680480*x^6 + 311461554388845258 72*x^4 + 1543354925530003776*x^2 + 8057044481403681]~ [x + (-7/16*y^29 - 5/32*y^25 - 97/8*y^21 - 139/32*y^17 - 435/16*y^13 - 323/3 2*y^9 - 21/4*y^5 - 77/32*y), x + (-11/32*y^29 - 1/8*y^25 - 309/32*y^21 - 55/ 16*y^17 - 797/32*y^13 - 7*y^9 - 355/32*y^5 + 9/16*y), x + (11/32*y^29 + 1/8* y^25 + 309/32*y^21 + 55/16*y^17 + 797/32*y^13 + 7*y^9 + 355/32*y^5 - 9/16*y) , x + (7/16*y^29 + 5/32*y^25 + 97/8*y^21 + 139/32*y^17 + 435/16*y^13 + 323/3 2*y^9 + 21/4*y^5 + 77/32*y), x + (-21/32*y^31 - 587/32*y^23 + 1/16*y^19 - 14 43/32*y^15 + 13/8*y^11 - 541/32*y^7 + 21/16*y^3), x + (-5/16*y^31 - 5/32*y^2 7 - 35/4*y^23 - 139/32*y^19 - 349/16*y^15 - 323/32*y^11 - 57/8*y^7 - 109/32* y^3), x + (5/16*y^31 + 5/32*y^27 + 35/4*y^23 + 139/32*y^19 + 349/16*y^15 + 3 23/32*y^11 + 57/8*y^7 + 109/32*y^3), x + (21/32*y^31 + 587/32*y^23 - 1/16*y^ 19 + 1443/32*y^15 - 13/8*y^11 + 541/32*y^7 - 21/16*y^3), x^4 + (-13/4*y^24 - 91*y^16 - 909/4*y^8 - 169/2), x^4 + (-1/4*y^24 - 7*y^16 - 57/4*y^8 - 1/2)]~ [8711099/70204123*y^14 - 3396450/70204123*y^13 - 230089978/70204123*y^12 + 7 1459644/70204123*y^11 + 2039293754/70204123*y^10 - 522502724/70204123*y^9 - 7578045032/70204123*y^8 + 136410216/6382193*y^7 + 11598831422/70204123*y^6 - 1582740050/70204123*y^5 - 6466526698/70204123*y^4 + 712163508/70204123*y^3 + 865017354/70204123*y^2 - 11706800/70204123*y + 7921687/70204123] [y, -123209112482/559553426209*y^11 - 236161397417/559553426209*y^10 + 52225 05497467/559553426209*y^9 + 7627164004768/559553426209*y^8 - 68684785347690/ 559553426209*y^7 - 98327585435469/559553426209*y^6 + 334508906676131/5595534 26209*y^5 + 508054669424553/559553426209*y^4 - 499853398148011/559553426209* y^3 - 780815391953932/559553426209*y^2 + 222263541657120/559553426209*y + 69 71304961116/11905392047, -176690268281/1119106852418*y^11 - 641210922141/223 8213704836*y^10 + 3748626002639/559553426209*y^9 + 20339566453621/2238213704 836*y^8 - 49228932581896/559553426209*y^7 - 262748733927015/2238213704836*y^ 6 + 958463738831775/2238213704836*y^5 + 1369627950576313/2238213704836*y^4 - 1439017147702531/2238213704836*y^3 - 2121737405539667/2238213704836*y^2 + 6 35967216650047/2238213704836*y + 19194169373855/47621568188, -68393259315/11 19106852418*y^11 - 143769468519/1119106852418*y^10 + 2890095068571/111910685 2418*y^9 + 4773072512403/1119106852418*y^8 - 38008182942981/1119106852418*y^ 7 - 30714902181882/559553426209*y^6 + 92097658832451/559553426209*y^5 + 1570 24332093039/559553426209*y^4 - 134021586074273/559553426209*y^3 - 2404025913 19962/559553426209*y^2 + 58771325675463/559553426209*y + 4293056883813/23810 784094, -26071422312/559553426209*y^11 - 45431912634/559553426209*y^10 + 110 4266993455/559553426209*y^9 + 1416464504385/559553426209*y^8 - 1440773326506 3/559553426209*y^7 - 18255285107310/559553426209*y^6 + 69227537719650/559553 426209*y^5 + 94877281869432/559553426209*y^4 - 100252280561328/559553426209* y^3 - 143113043669604/559553426209*y^2 + 41073387952215/559553426209*y + 128 0223975324/11905392047, -16163557893/1119106852418*y^11 - 64908872441/223821 3704836*y^10 + 685522417391/1119106852418*y^9 + 2130089587017/2238213704836* y^8 - 4531221497592/559553426209*y^7 - 27490869176393/2238213704836*y^6 + 89 319951302323/2238213704836*y^5 + 141812611520979/2238213704836*y^4 - 1390748 45426265/2238213704836*y^3 - 220351698213059/2238213704836*y^2 + 72725691407 453/2238213704836*y + 2005246545505/47621568188, 9609209575/2238213704836*y^ 11 + 25387385845/559553426209*y^10 - 383645617715/2238213704836*y^9 - 208031 3216715/1119106852418*y^8 + 6033944605985/2238213704836*y^7 + 53081257123225 /2238213704836*y^6 - 33975296862719/2238213704836*y^5 - 255089221619815/2238 213704836*y^4 + 47525895430055/2238213704836*y^3 + 398412597852115/223821370 4836*y^2 - 30904572571305/2238213704836*y - 890343326655/11905392047, 522817 60559/2238213704836*y^11 + 14008471016/559553426209*y^10 - 2227004686929/223 8213704836*y^9 - 336992949231/559553426209*y^8 + 28726688292139/223821370483 6*y^7 + 17917872421753/2238213704836*y^6 - 137376604832131/2238213704836*y^5 - 105226511459813/2238213704836*y^4 + 207364021022899/2238213704836*y^3 + 1 70780696189363/2238213704836*y^2 - 84647799904795/2238213704836*y - 44402858 6648/11905392047, 106577461171/2238213704836*y^11 + 236835106673/22382137048 36*y^10 - 4499294217001/2238213704836*y^9 - 8003166405117/2238213704836*y^8 + 59306288158573/2238213704836*y^7 + 25836461923340/559553426209*y^6 - 72093 028502701/559553426209*y^5 - 264172433170095/1119106852418*y^4 + 21076054618 3675/1119106852418*y^3 + 203797855675948/559553426209*y^2 - 94758333876515/1 119106852418*y - 7259569285101/47621568188, 175225361355/2238213704836*y^11 + 367043962553/2238213704836*y^10 - 7404910374729/2238213704836*y^9 - 121761 49738023/2238213704836*y^8 + 97370244941211/2238213704836*y^7 + 784051152149 35/1119106852418*y^6 - 117954333048705/559553426209*y^5 - 401317015113399/11 19106852418*y^4 + 171430955359538/559553426209*y^3 + 307321505664217/5595534 26209*y^2 - 148696095658675/1119106852418*y - 10923889360787/47621568188, 18 4746017659/1119106852418*y^11 + 182236626649/559553426209*y^10 - 78287971960 99/1119106852418*y^9 - 5941166792275/559553426209*y^8 + 103098612489213/1119 106852418*y^7 + 153130332934513/1119106852418*y^6 - 502641225832273/11191068 52418*y^5 - 789225051651289/1119106852418*y^4 + 749848149414089/111910685241 8*y^3 + 1216440499421323/1119106852418*y^2 - 334431034048089/1119106852418*y - 5475399545957/11905392047, 421608384/2321798449*y^11 + 1306271719/4643596 898*y^10 - 17925705039/2321798449*y^9 - 38874965891/4643596898*y^8 + 2342247 56928/2321798449*y^7 + 502105436649/4643596898*y^6 - 2270324281083/464359689 8*y^5 - 2658757184017/4643596898*y^4 + 3428983243105/4643596898*y^3 + 405157 9820087/4643596898*y^2 - 1510458181035/4643596898*y - 36134279083/98799934] [x + (-y + 1) 1] [x^2 + (y + 2)*x + (y^2 + y + 1) 1] [x^2 + (y + 2)*x + (1/25*y^8 - 3/5*y^5 - 87/25*y^2 + y + 1) 1] [x^2 + (-2/15*y^7 + 7/3*y^4 + 79/15*y + 2)*x + (1/25*y^8 - 2/15*y^7 - 3/5*y^ 5 + 7/3*y^4 - 87/25*y^2 + 79/15*y + 1) 1] [x^2 + (2/15*y^7 - 7/3*y^4 - 94/15*y + 2)*x + (1/25*y^8 + 2/15*y^7 - 3/5*y^5 - 7/3*y^4 - 87/25*y^2 - 94/15*y + 1) 1] [ x - y 3] [ x^2 + y 4] [x^3 - y*x + y 5] [x - y 1] [x + y 1] [x - y 1] [x + y 1] [ x + 1 3] [2*x + 1 2] 9 [x - y, x + y, x + (-373/2372*y^15 - 69/2372*y^13 + 2205/593*y^11 - 56641/47 44*y^9 + 30823/1186*y^7 - 16782/593*y^5 + 11109/593*y^3 - 15285/2372*y), x + (373/2372*y^15 + 69/2372*y^13 - 2205/593*y^11 + 56641/4744*y^9 - 30823/1186 *y^7 + 16782/593*y^5 - 11109/593*y^3 + 15285/2372*y), x^4 + (-231/1186*y^14 - 313/1186*y^12 + 10535/2372*y^10 - 5568/593*y^8 + 10658/593*y^6 - 4133/593* y^4 + 1731/1186*y^2 - 648/593)*x^2 + (81/1186*y^14 + 181/2372*y^12 - 937/593 *y^10 + 4313/1186*y^8 - 4207/593*y^6 + 5463/1186*y^4 - 1270/593*y^2 + 1883/5 93), x^4 + (-93/1186*y^14 - 49/1186*y^12 + 4457/2372*y^10 - 3058/593*y^8 + 6 170/593*y^6 - 6793/593*y^4 + 8429/1186*y^2 - 2140/593)*x^2 + (81/1186*y^14 + 181/2372*y^12 - 937/593*y^10 + 4313/1186*y^8 - 4207/593*y^6 + 5463/1186*y^4 - 1270/593*y^2 + 1883/593), x^4 + (159/2372*y^14 + 281/1186*y^12 - 3437/237 2*y^10 - 217/593*y^8 + 4085/1186*y^6 - 8339/593*y^4 + 12947/1186*y^2 + 146/5 93)*x^2 + (-81/1186*y^14 - 181/2372*y^12 + 937/593*y^10 - 4313/1186*y^8 + 42 07/593*y^6 - 5463/1186*y^4 + 1270/593*y^2 + 489/593)]~ 36 9 x^6 - x^5 - 76*x^4 + 60*x^3 + 1140*x^2 + 1155*x - 695 a^36 - 140*a^34 + 8402*a^32 - 288950*a^30 + 6406703*a^28 - 97539585*a^26 + 1 059042259*a^24 - 8396309325*a^22 + 49297808195*a^20 - 215811263825*a^18 + 70 4643601819*a^16 - 1705347924285*a^14 + 3017070472643*a^12 - 3809285900925*a^ 10 + 3299709349267*a^8 - 1836758642090*a^6 + 585303753211*a^4 - 85409835875* a^2 + 3969153125 [28870969412445129304/150333898582544875079637735*a^34 - 2391040639738112524 6214047/902003391495269250477826410000*a^32 + 1408280580925577743188914959/9 02003391495269250477826410000*a^30 - 47270903738475878949122441507/902003391 495269250477826410000*a^28 + 1016201980774469757442024408441/902003391495269 250477826410000*a^26 - 1653232481585973809555097282799/100222599055029916719 758490000*a^24 + 30766570387863948626786349252629/18040067829905385009556528 2000*a^22 - 25494617146287004973995153489163/20044519811005983343951698000*a ^20 + 54269387427573548559506499935047/7843507752132776091111534000*a^18 - 4 967271194565117464292207548275283/180400678299053850095565282000*a^16 + 1439 0821273796469411671423134660909/180400678299053850095565282000*a^14 - 166375 51485416921371399599192940627/100222599055029916719758490000*a^12 + 21844296 4149682251745527062058729581/902003391495269250477826410000*a^10 - 715047828 08114491609686387087461101/300667797165089750159275470000*a^8 + 132463576654 385501140215626560461749/902003391495269250477826410000*a^6 - 45521136780059 303695022254815264059/902003391495269250477826410000*a^4 + 48834547745749769 48426917348117/644288136782335178912733150*a^2 - 31947174916220852422727719/ 91469478158982811558152, 3251350527072966578858963/4510016957476346252389132 050000*a^34 - 224934549971331898950636911/2255008478738173126194566025000*a^ 32 + 8860674919294055555049660713/1503338985825448750796377350000*a^30 - 995 57773024274624590944467659/501112995275149583598792450000*a^28 + 19366458770 607880120052179046813/4510016957476346252389132050000*a^26 - 285516842858115 285212427862265807/4510016957476346252389132050000*a^24 + 595519111738991674 011764093345989/902003391495269250477826410000*a^22 - 4489547975447934229698 580858261951/902003391495269250477826410000*a^20 + 1076139228842461035371382 151402807/39217538760663880455557670000*a^18 - 11124367147850754939979966580 304871/100222599055029916719758490000*a^16 + 1479061897966350800416026745438 951477/4510016957476346252389132050000*a^14 - 315025857271480248157232912303 3742463/4510016957476346252389132050000*a^12 + 47206506294320482873673946762 98685961/4510016957476346252389132050000*a^10 - 4777649748033279268548939533 863439719/4510016957476346252389132050000*a^8 + 3048859768911341351494073063 483963897/4510016957476346252389132050000*a^6 - 5426099614227091504278277319 81252029/2255008478738173126194566025000*a^4 + 64587456786717997350050100662 819/1718101698086227143767288400*a^2 - 165798995832125073281674123/914694781 58982811558152, -704379081794904012990253/9020033914952692504778264100000*a^ 35 - 185571858472598531261171/501112995275149583598792450000*a^34 + 48715152 518881440798956651/4510016957476346252389132050000*a^33 + 462092978647254762 515957747/9020033914952692504778264100000*a^32 - 143866499279758588432618534 1/2255008478738173126194566025000*a^31 - 13648984531486738963024628227/45100 16957476346252389132050000*a^30 + 96938310360867353475048806483/451001695747 6346252389132050000*a^29 + 919883530735586552464580524411/902003391495269250 4778264100000*a^28 - 232651976540261816658545907611/501112995275149583598792 450000*a^27 - 19875071662837802701492211372933/90200339149526925047782641000 00*a^26 + 30845327236112782336432658557121/4510016957476346252389132050000*a ^25 + 97629122086975105817272227332809/3006677971650897501592754700000*a^24 - 21424985574841499437846887948389/300667797165089750159275470000*a^23 - 610 575128275733935942680874074229/1804006782990538500955652820000*a^22 + 484017 286454879828969736789559843/902003391495269250477826410000*a^21 + 1533419100 031007894056656543524977/601335594330179500318550940000*a^20 - 1158671856773 61369373967739807791/39217538760663880455557670000*a^19 - 110190466434352089 3720157677667127/78435077521327760911115340000*a^18 + 1537709883158934201041 232269889911/128857627356467035782546630000*a^17 + 1024351631773365912595517 71572103159/1804006782990538500955652820000*a^16 - 5292233983819996489701399 1241504027/1503338985825448750796377350000*a^15 - 15119400756767591614096930 48855920037/9020033914952692504778264100000*a^14 + 4823557309278799269424083 0453221347/644288136782335178912733150000*a^13 + 107239762638007600223629533 3324062521/3006677971650897501592754700000*a^12 - 16846944747925094111730588 2802587131/1503338985825448750796377350000*a^11 - 48160226697757002253310017 91553165721/9020033914952692504778264100000*a^10 + 1491287229390570953499395 745247369/13148737485353779161484350000*a^9 + 162299919830912395515658180697 4277013/3006677971650897501592754700000*a^8 - 327237997164237860693483056003 293031/4510016957476346252389132050000*a^7 - 3103794645076791741342476648584 879777/9020033914952692504778264100000*a^6 + 2348322029477720044136044070025 03923/9020033914952692504778264100000*a^5 + 11035578261555912186076185579856 11613/9020033914952692504778264100000*a^4 - 37526865321657483383315681982802 9/90200339149526925047782641000*a^3 - 49201004178902125753179356208497/25771 52547129340715650932600*a^2 + 455861078300944766857933289/213428782370959893 6356880*a + 336438999245457567382406693/365877912635931246232608, -457997268 286495201285601/9020033914952692504778264100000*a^35 - 155437231387909379055 577/1804006782990538500955652820000*a^34 + 63219462123808708551299959/902003 3914952692504778264100000*a^33 + 10732815328231466161638631/9020033914952692 50477826410000*a^32 - 1241268191638711501136747401/3006677971650897501592754 700000*a^31 - 162691836407833782279946/231996757071828510925366875*a^30 + 41 671559320168530327971893369/3006677971650897501592754700000*a^29 + 472202100 3894765857767375379/200445198110059833439516980000*a^28 - 268827453299542151 9377197948701/9020033914952692504778264100000*a^27 - 91447940232848524115401 7943217/1804006782990538500955652820000*a^26 + 39380597302365530060214378192 779/9020033914952692504778264100000*a^25 + 13404987653711757838118111598667/ 1804006782990538500955652820000*a^24 - 81492696927754851227554074520033/1804 006782990538500955652820000*a^23 - 27755367080515496240602993106981/36080135 6598107700191130564000*a^22 + 608451862766595678082876478420347/180400678299 0538500955652820000*a^21 + 207309689387565154271678626939871/360801356598107 700191130564000*a^20 - 144141144819342089103549365967439/7843507752132776091 1115340000*a^19 - 49116300327361576889751394682183/1568701550426555218222306 8000*a^18 + 163228993853205803064485212811743/22271688678895537048835220000* a^17 + 1501366475076386034781931026134473/120267118866035900063710188000*a^1 6 - 192040496313746347169675964373314529/9020033914952692504778264100000*a^1 5 - 65378470826900674859623854989910833/1804006782990538500955652820000*a^14 + 400908998300724067746255602794046311/9020033914952692504778264100000*a^13 + 136351102083667187315285017348776623/1804006782990538500955652820000*a^12 - 586838332855949729229685411031808997/9020033914952692504778264100000*a^11 - 199368556080951864152805639007833629/1804006782990538500955652820000*a^10 + 578030985689012831826453965281320943/9020033914952692504778264100000*a^9 + 196244779045524955444897983850505039/1804006782990538500955652820000*a^8 - 357480334490463612280117630223936969/9020033914952692504778264100000*a^7 - 121476601421295423170534909540278573/1804006782990538500955652820000*a^6 + 3 0624370220614590128641706307930719/2255008478738173126194566025000*a^5 + 104 63389029506180036157409002660637/451001695747634625238913205000*a^4 - 861866 1493592985666542036187341/4295254245215567859418221000*a^3 - 266859198823298 552776653451403/76360075470498984167435040*a^2 + 591232823580313844716106279 /6402863471128796809070640*a + 59236281207552249649513295/365877912635931246 232608, 457997268286495201285601/9020033914952692504778264100000*a^35 - 1554 37231387909379055577/1804006782990538500955652820000*a^34 - 6321946212380870 8551299959/9020033914952692504778264100000*a^33 + 10732815328231466161638631 /902003391495269250477826410000*a^32 + 1241268191638711501136747401/30066779 71650897501592754700000*a^31 - 162691836407833782279946/23199675707182851092 5366875*a^30 - 41671559320168530327971893369/3006677971650897501592754700000 *a^29 + 4722021003894765857767375379/200445198110059833439516980000*a^28 + 2 688274532995421519377197948701/9020033914952692504778264100000*a^27 - 914479 402328485241154017943217/1804006782990538500955652820000*a^26 - 393805973023 65530060214378192779/9020033914952692504778264100000*a^25 + 1340498765371175 7838118111598667/1804006782990538500955652820000*a^24 + 81492696927754851227 554074520033/1804006782990538500955652820000*a^23 - 277553670805154962406029 93106981/360801356598107700191130564000*a^22 - 60845186276659567808287647842 0347/1804006782990538500955652820000*a^21 + 20730968938756515427167862693987 1/360801356598107700191130564000*a^20 + 144141144819342089103549365967439/78 435077521327760911115340000*a^19 - 49116300327361576889751394682183/15687015 504265552182223068000*a^18 - 163228993853205803064485212811743/2227168867889 5537048835220000*a^17 + 1501366475076386034781931026134473/12026711886603590 0063710188000*a^16 + 192040496313746347169675964373314529/902003391495269250 4778264100000*a^15 - 65378470826900674859623854989910833/1804006782990538500 955652820000*a^14 - 400908998300724067746255602794046311/9020033914952692504 778264100000*a^13 + 136351102083667187315285017348776623/1804006782990538500 955652820000*a^12 + 586838332855949729229685411031808997/9020033914952692504 778264100000*a^11 - 199368556080951864152805639007833629/1804006782990538500 955652820000*a^10 - 578030985689012831826453965281320943/9020033914952692504 778264100000*a^9 + 196244779045524955444897983850505039/18040067829905385009 55652820000*a^8 + 357480334490463612280117630223936969/902003391495269250477 8264100000*a^7 - 121476601421295423170534909540278573/1804006782990538500955 652820000*a^6 - 30624370220614590128641706307930719/225500847873817312619456 6025000*a^5 + 10463389029506180036157409002660637/45100169574763462523891320 5000*a^4 + 8618661493592985666542036187341/4295254245215567859418221000*a^3 - 266859198823298552776653451403/76360075470498984167435040*a^2 - 5912328235 80313844716106279/6402863471128796809070640*a + 59236281207552249649513295/3 65877912635931246232608, 704379081794904012990253/90200339149526925047782641 00000*a^35 - 185571858472598531261171/501112995275149583598792450000*a^34 - 48715152518881440798956651/4510016957476346252389132050000*a^33 + 4620929786 47254762515957747/9020033914952692504778264100000*a^32 + 1438664992797585884 326185341/2255008478738173126194566025000*a^31 - 136489845314867389630246282 27/4510016957476346252389132050000*a^30 - 96938310360867353475048806483/4510 016957476346252389132050000*a^29 + 919883530735586552464580524411/9020033914 952692504778264100000*a^28 + 232651976540261816658545907611/5011129952751495 83598792450000*a^27 - 19875071662837802701492211372933/902003391495269250477 8264100000*a^26 - 30845327236112782336432658557121/4510016957476346252389132 050000*a^25 + 97629122086975105817272227332809/30066779716508975015927547000 00*a^24 + 21424985574841499437846887948389/300667797165089750159275470000*a^ 23 - 610575128275733935942680874074229/1804006782990538500955652820000*a^22 - 484017286454879828969736789559843/902003391495269250477826410000*a^21 + 15 33419100031007894056656543524977/601335594330179500318550940000*a^20 + 11586 7185677361369373967739807791/39217538760663880455557670000*a^19 - 1101904664 343520893720157677667127/78435077521327760911115340000*a^18 - 15377098831589 34201041232269889911/128857627356467035782546630000*a^17 + 10243516317733659 1259551771572103159/1804006782990538500955652820000*a^16 + 52922339838199964 897013991241504027/1503338985825448750796377350000*a^15 - 151194007567675916 1409693048855920037/9020033914952692504778264100000*a^14 - 48235573092787992 694240830453221347/644288136782335178912733150000*a^13 + 1072397626380076002 236295333324062521/3006677971650897501592754700000*a^12 + 168469447479250941 117305882802587131/1503338985825448750796377350000*a^11 - 481602266977570022 5331001791553165721/9020033914952692504778264100000*a^10 - 14912872293905709 53499395745247369/13148737485353779161484350000*a^9 + 1622999198309123955156 581806974277013/3006677971650897501592754700000*a^8 + 3272379971642378606934 83056003293031/4510016957476346252389132050000*a^7 - 31037946450767917413424 76648584879777/9020033914952692504778264100000*a^6 - 23483220294777200441360 4407002503923/9020033914952692504778264100000*a^5 + 110355782615559121860761 8557985611613/9020033914952692504778264100000*a^4 + 375268653216574833833156 819828029/90200339149526925047782641000*a^3 - 492010041789021257531793562084 97/2577152547129340715650932600*a^2 - 455861078300944766857933289/2134287823 709598936356880*a + 336438999245457567382406693/365877912635931246232608] [x^12 - x^11 + 7/13*x^10 - 3/13*x^9 + 15/169*x^8 - 5/169*x^7 + 19/2197*x^6 - 5/2197*x^5 + 15/28561*x^4 - 3/28561*x^3 + 7/371293*x^2 - 1/371293*x + 1/482 6809, x^12 + x^11 + 7/13*x^10 + 3/13*x^9 + 15/169*x^8 + 5/169*x^7 + 19/2197* x^6 + 5/2197*x^5 + 15/28561*x^4 + 3/28561*x^3 + 7/371293*x^2 + 1/371293*x + 1/4826809]~ [x - 3, x + (-1/2*y + 1/2), x + (1/2*y + 1/2)]~ [x + (-y^7 - 1) 1] [ x + (y^7 + 1) 1] [x + (-2*y^3 + y), x + (-4/3*y^3 + 2/3*y), x + (-2/3*y^3 + 1/3*y)]~ [x + (-1/3*y - 1/3), x + (2/3*y + 2/3)]~ *** nffactor: Warning: non-monic polynomial. Result of the form [nf,c]. [x + (-2/3*y + 1/3) 1] [ x + (2/3*y - 1/3) 1] *** nfroots: Warning: non-monic polynomial. Result of the form [nf,c]. [-2/3*y + 1/3, 2/3*y - 1/3] [x + (-26388279066648/85070591730466729623209871765718171955*t^5 + 131941395 333267/85070591730466729623209871765718171955*t^4 + 967140655690823730462717 32/85070591730466729623209871765718171955*t^3 - 290142196708032170441048136/ 85070591730466729623209871765718171955*t^2 - 7443676776386824622360021639744 6118676/85070591730466729623209871765718171955*t + 7443676776373163760598366 6543681076444/85070591730466729623209871765718171955) 1] [x^2 + (26388279066648/85070591730466729623209871765718171955*t^5 - 13194139 5333267/85070591730466729623209871765718171955*t^4 - 96714065569082373046271 732/85070591730466729623209871765718171955*t^3 + 290142196708032170441048136 /85070591730466729623209871765718171955*t^2 + 744367677638682462236002163974 46118676/85070591730466729623209871765718171955*t - 744367677637316376059836 66543681076444/85070591730466729623209871765718171955)*x + (54/8507059173046 6729623209871765718171955*t^5 + 19342813113869251167387394/85070591730466729 623209871765718171955*t^4 - 77371252455674916762549976/850705917304667296232 09871765718171955*t^3 - 42535295865117307932921126639575760427/8507059173046 6729623209871765718171955*t^2 + 85070591730773796781391952391721450758/85070 591730466729623209871765718171955*t + 23384026197336981987123709535795926763 206176932728/85070591730466729623209871765718171955) 1] x^6 + 10/7*x^5 - 867/49*x^4 - 76/245*x^3 + 3148/35*x^2 - 25944/245*x + 48771 /1225 [ x - 1 1] [ x + 1 1] [x^2 - 5 1] [x^2 - 2 1] [ x + 1 1] [ x^2 + 1 1] [ x^4 - x^3 + x^2 - x + 1 1] [ x^4 + 1 1] [ x^4 + x^3 + x^2 + x + 1 1] [ x^8 - x^6 + x^4 - x^2 + 1 1] [ x^8 + 1 1] [ x^16 - x^12 + x^8 - x^4 + 1 1] [x^32 - x^24 + x^16 - x^8 + 1 1] 10 10 [0] [x + (-314226370217524044*y + 1473852319020386314), x + (314226370217524044* y - 1473852319020386314)]~ Total time spent: 8061 pari-2.7.5/src/test/32/quad0000644000175000017500000000047712366172547014002 0ustar billbill1 2.6180339887498948482045868343656381177 1.6180339887498948482045868343656381177 + I 1.6180339887498948482045868343656381177 0.E-38 + 1.6180339887498948482045868343656381177*I -1 *** at top-level: norml2(w) *** ^--------- *** norml2: incorrect type in gnorml2 (t_QUAD). 1 2 Total time spent: 4 pari-2.7.5/src/test/32/round0000644000175000017500000000315212366172547014170 0ustar billbill1 1 2 -1 error("incorrect type in gceil (t_INTMOD).") error("incorrect type in gceil (t_QUAD).") error("incorrect type in gceil (t_POLMOD).") x error("incorrect type in gceil (t_SER).") 0 [2, 2] [1, 0; 0, 1] error("incorrect type in gceil (t_STR).") 1 1 -2 error("incorrect type in gfloor (t_INTMOD).") error("incorrect type in gfloor (t_QUAD).") error("incorrect type in gfloor (t_POLMOD).") x error("incorrect type in gfloor (t_SER).") 0 [1, 2] [0, 0; 0, 0] error("incorrect type in gfloor (t_STR).") 0 0.60000000000000000000000000000000000000 2/3 error("incorrect type in gfloor (t_INTMOD).") error("incorrect type in gfloor (t_QUAD).") error("incorrect type in gfloor (t_POLMOD).") 0 error("incorrect type in gfloor (t_SER).") 1/x [1/3, 0] [1/3, 0; 0, 1/3] error("incorrect type in gfloor (t_STR).") 1 2 -1 Mod(1, 3) w Mod(x + 1, x^2 + 1/2) x 1 + O(x^2) 1/x [1, 2] [0, 0; 0, 0] error("incorrect type in ground (t_STR).") [1, -oo] [2, -2] [-1, -oo] [Mod(1, 3), -oo] [w, -oo] [Mod(x + 1, x^2 + 1/2), -oo] [x, -oo] [1 + O(x^2), -oo] [1/x, -oo] [[1, 2], -oo] [[0, 0; 0, 0], -oo] error("incorrect type in grndtoi (t_STR).") 1 1 -1 error("incorrect type in gtrunc (t_INTMOD).") error("incorrect type in gtrunc (t_QUAD).") error("incorrect type in gtrunc (t_POLMOD).") x 1/3*x + 4/3 0 [1, 2] [0, 0; 0, 0] error("incorrect type in gtrunc (t_STR).") [1, -oo] [1, -1] [-1, -oo] error("incorrect type in gtrunc (t_INTMOD).") error("incorrect type in gtrunc (t_QUAD).") error("incorrect type in gtrunc (t_POLMOD).") [x, -oo] [1/3*x + 4/3, -oo] [0, -oo] [[1, 2], -oo] [[0, 0; 0, 0], -oo] error("incorrect type in gtrunc (t_STR).") Total time spent: 4 pari-2.7.5/src/test/32/program0000644000175000017500000000455712366172547014522 0ustar billbill1 echo = 1 (on) ? alias(ln,log) ? ln(2) 0.69314718055994530941723212145817656807 ? 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,2.9,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 ? 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] ? if(3<2,print("bof"),print("ok")); ok ? kill(y);print(x+y); x + y ? f(u)=u+1; ? print(f(5));kill(f); 6 ? f=12 12 ? g(u)=if(u,,return(17));u+2 (u)->if(u,,return(17));u+2 ? g(2) 4 ? g(0) 17 ? 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 ? 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 ? default(seriesprecision,12) ? print((x-12*y)/(y+13*x)); (x - 12*y)/(13*x + y) ? print([1,2;3,4]) [1, 2; 3, 4] ? print1(x+y);print(x+y); x + yx + y ? print((x-12*y)/(y+13*x)); (x - 12*y)/(13*x + y) ? print([1,2;3,4]) [1, 2; 3, 4] ? print1(x+y);print1(" equals ");print(x+y); 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 + y^3}{x^2 - 2 y x + y^2} 1 ? for(i=1,100,for(j=1,25,if(i+j==32,break(2)));print(i)) 1 2 3 4 5 6 ? u=v=p=q=1;for(k=1,400,w=u+v;u=v;v=w;p*=w;q=lcm(q,w);if(k%50==0,print(k" "log(p)/log(q)))); 50 1.5612291269030992792061717254933840846 100 1.6013353755908753487111410311704818784 150 1.6069155486736591275233947740278385687 200 1.6186599989915284815081751756012014738 250 1.6262847062047467650860809884971000430 300 1.6278227768451030011920245320536334380 350 1.6321059051729866681896522731053701088 400 1.6324242855329314481714056192369470068 ? install(addii,GG) ? addii(1,2) 3 ? kill(addii) ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 20 pari-2.7.5/src/test/32/variable0000644000175000017500000000006512366172547014626 0ustar billbill0 3 x x y y y z 0 y [x, y, z, v] Total time spent: 4 pari-2.7.5/src/test/32/ff0000644000175000017500000002672012413013143013415 0ustar billbill? 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^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]~] ? 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([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]~] ? 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([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]~] ? 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 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 ? 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: 2356 pari-2.7.5/src/test/32/lindep0000644000175000017500000000044312366172547014314 0ustar billbill[-1, -1, 1]~ [1, -2]~ [1, -2, 1]~ [y, y, -1, -y^2]~ x^2 + (-y^3 - y^2 - 5*y - 1) 0 (-y + 1)*x - 1 -x + (5*y + 1) []~ [1]~ []~ []~ 1 *** at top-level: algdep(1,-1) *** ^------------ *** algdep: domain error in algdep: degree < 0 x^2 - 2 [0, 0, 0]~ Total time spent: 0 pari-2.7.5/src/test/32/bnr0000644000175000017500000000317512573550041013614 0ustar billbill[] [[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, 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]] [[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.99197791640852265169404803750682485962 - 0.1264112865127400184730959576238 0269676*I 1 1 [4, [2, 2], [[3, 1; 0, 1], [114, 1; 0, 1]]] [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0]] Total time spent: 20 pari-2.7.5/src/test/32/bestappr0000644000175000017500000000025012314242551014637 0ustar billbill-1/7 -1/6 -1/7 [] -1/7 -1/7 [] (x^3 + 1)/(x^10 + 2) 1/2*x^3 + 1/2 1/(x + 1) 1/(x + 1) [] 1/(x^6 + 1) (x - 2)/(-x^2 + x) x^2/(-x + 1) 1/(-x^5 + x^4) Total time spent: 4 pari-2.7.5/src/test/32/interpol0000644000175000017500000000026512366172547014677 0ustar billbillx + 1 Mod(1, 7)*x + Mod(1, 7) Mod(1, 7) -1/6*x^2 + 3/2*x + 2/3 Mod(3, 7) 2.5416666666666666666666666666666666667 0.041666666666666666666666666666666666667 0 0 2 Total time spent: 0 pari-2.7.5/src/test/32/ellsea0000644000175000017500000000061612414216316014273 0ustar billbill[x^6 + 30*x^5 + 315*x^4 + 1300*x^3 + 1575*x^2 + (-y + 750)*x + 125, 0] 1: -18627161351017007203 2: 18827282990304904850 3: -311256626765211726406998 4: -1156815323986765479761266 5: 8021839135157401454666601928 6: 69384671472347162238655401774 7: -28652256072001057705168347198 8: 1271547588042840381566950172346 9: 1854715558584444 10: 20420247695 11: -4742075250 -40969318 Total time spent: 4788 pari-2.7.5/src/test/32/sqrtn0000644000175000017500000000365312366172547014216 0ustar billbill0.E-12 0.E-12 + 0.E-12*I 0.79370052598409973737585281963615413020 1.1739849967053285099666839718862667420 2 + O(17^100) *** at top-level: sqrtn(Mod(0,3),-2) *** ^------------------ *** sqrtn: impossible inverse in Fp_sqrtn: Mod(0, 3). *** at top-level: sqrtn(O(3),-2) *** ^-------------- *** sqrtn: impossible inverse in ginv: O(3). *** at top-level: sqrtn(0*ffgen((2^64+ *** ^-------------------- *** sqrtn: impossible inverse in FpXQ_sqrtn: 0. *** at top-level: sqrtn(0*ffgen(3^2),- *** ^-------------------- *** sqrtn: impossible inverse in Flxq_sqrtn: Vecsmall([0]). *** at top-level: sqrtn(0*ffgen(2^2),- *** ^-------------------- *** sqrtn: impossible inverse in F2xq_sqrtn: Vecsmall([0]). 9 1.0717734625362931642130063250233420229 0.80901699437494742410229341718281905886 + 0.5877852522924731291687059546390 7276860*I 1 + 3^2 + 2*3^4 + 2*3^5 + 3^6 + O(3^8) 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^8) 1 + O(3^2) 1 1 1 *** at top-level: sqrtn(Mod(2,4),3) *** ^----------------- *** sqrtn: impossible inverse in Fl_inv: Mod(2, 4). *** at top-level: sqrtn(Mod(2,4),3,&z) *** ^-------------------- *** sqrtn: impossible inverse in Fl_inv: Mod(2, 4). 1.0000000000000000000000000000000000000 0 error("not an n-th power residue in Qp_sqrt: 1 + 2 + O(2^2).") error("not an n-th power residue in Qp_sqrt: 1 + 2 + O(2^3).") error("not an n-th power residue in gsqrt: Mod(2, 11).") error("not a prime number in Fl_sqrt [modulus]: 33.") 0.E-5 + 0.E-5*I [1 + O(3), 1] [1 + O(2), -1] [2 + O(2^3), 1 + 2 + O(2^2)] [2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000] error("not an n-th power residue in gsqrtn: Mod(2, 7).") [0, 0] Mod(2, 21) error("not a prime number in sqrtn [modulus]: 35.") [Mod(99, 101), Mod(100, 101)] 0.E-38 Total time spent: 0 pari-2.7.5/src/test/32/minmax0000644000175000017500000000014412314242551014312 0ustar billbill1: [1, 1, 0, 0] 2: [11, -3, 1, 4] 3: [11, -3, 1, 4] 4: [11, -3, [1, 1], [2, 2]] Total time spent: 0 pari-2.7.5/src/test/32/addprimes0000644000175000017500000000243612366172547015015 0ustar billbill[[0, 1, 210, 4, 4, 48, 16, 576, 65000, 10922688], [0, -1, 210000630, 5, 5, 4 8000096, 32, 576002304, 65000390000650000, 10922786304486912881835264], [0, 1, 210007560020790, 6, 6, 48001632003072, 64, 576021888078336, 6500468009724 0468000708500000, 10923867696016192486063520726766954883717632], [0, 0, 2100 06930, 6, 7, 48001776007968009216, 96, 576023616144576254592, 65005070125906 093564391733467296447350000, 10923966011120401354532760288014407980573122245 052972159937408], [0, -1, -210000630, 5, 5, 48000096, 32, 576002304, 6500039 0000650000, 10922786304486912881835264]] Testing 210, addprimes = [1000003] Testing 210000630, addprimes = [1000003] Testing 210007560020790, addprimes = [1000003] Testing 210008190043470062370, addprimes = [1000003] Testing -210000630, addprimes = [1000003] Testing 210, addprimes = [1000003, 1000033] Testing 210000630, addprimes = [1000003, 1000033] Testing 210007560020790, addprimes = [1000003, 1000033] Testing 210008190043470062370, addprimes = [1000003, 1000033] Testing -210000630, addprimes = [1000003, 1000033] Testing 210, addprimes = [1000033] Testing 210000630, addprimes = [1000033] Testing 210007560020790, addprimes = [1000033] Testing 210008190043470062370, addprimes = [1000033] Testing -210000630, addprimes = [1000033] [] [1009] Total time spent: 12 pari-2.7.5/src/test/32/sort0000644000175000017500000000133512366172547014031 0ustar billbill[[1, 3/2], [1, 2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 2 0 [[1, 2], [1, 3/2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 1 0 [[4, 1], [5/2, 1.0000000000000000000000000000000000000], [1, 3/2], [1, 2], [ 3, 4]] 4 4 error("incorrect type in lexicographic vecsort, index too large (t_INT).") [[5/2, 1.0000000000000000000000000000000000000], [4, 1], [1, 3/2], [1, 2], [ 3, 4]] 4 0 error("incorrect type in lexicographic vecsort, index too large (t_INT).") [[1, 2], [1, 3/2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 1 0 Vecsmall([1, 2, 3, 4]) List([1, 2, 3, 4]) [1, 2, 3, 4] Vecsmall([4, 6, 2, 1]) [4, 3, 2, 1] Vecsmall([1, 2, 6, 4]) List([]) Total time spent: 8 pari-2.7.5/src/test/32/qfbsolve0000644000175000017500000000000011636712103014632 0ustar billbillpari-2.7.5/src/test/32/gamma0000644000175000017500000001310712532352705014113 0ustar billbill(0.65296549642016672783864624794608469715 + 0.343065839816545357588735986978 31148676*I) + (0.19044897540645184469078131473790885364 + 0.5805524673194769 2349794265298068695525*I)*x + (0.090862784286733058570355592072096462602 + 0 .21088392899265350361451872767550590408*I)*x^2 + (0.034253752000523576920016 074597694397590 + 0.15168994440796279268955277197772465641*I)*x^3 + (-0.0093 139210540785894159197859484392067433 + 0.03306465179643991397682862055127742 8299*I)*x^4 + (0.0066762623841895560506752315759505427095 + 0.01516404667566 6586697065188398143396917*I)*x^5 + O(x^6) 1 - 0.57721566490153286060651209008240243104*x + 0.9890559953279725553953956 5150063470794*x^2 - 0.90747907608088628901656016735627511493*x^3 + 0.9817280 8683440018733638029402185085036*x^4 - 0.981995068903145202104701413791374675 51*x^5 + O(x^6) 0.50000000000000000000000000000000000000*x^-1 + 0.46139216754923356969674395 495879878448 + 0.93661624898783663224281375818851553069*x + 0.72048875166669 501900756857612523634633*x^2 + 1.1032890464233243060581361321045221793*x^3 + O(x^4) (-0.30434960902188368417660077077485938103 + 0.48375784292991511172812918802 297918039*I) + (0.59465032062247697727187848272191072247 + 0.576674047468581 17413405079475000049045*I)*x + (0.23150004831138189314916325909209289721 - 0 .14711677137965943279150680857845149795*I)*x^2 + (-0.02190784473534413804389 4242836567535805 + 0.044442141724177702067115896271895013565*I)*x^3 + (-0.00 095310203972899907556180572534221362410 - 0.01322027411091502743411636095975 8682565*I)*x^4 + (0.0023292347420337443292606199295988510753 + 0.00349489957 19835964464884744063791902941*I)*x^5 + O(x^6) -0.57721566490153286060651209008240243104*x + 0.8224670334241132182362075833 2301259461*x^2 - 0.40068563438653142846657938717048333025*x^3 + 0.2705808084 2778454787900092413529197569*x^4 - 0.20738555102867398526627309729140683361* x^5 + O(x^6) *** lngamma: Warning: normalizing a series with 0 leading term. *** at top-level: lngamma(-2+x) *** ^------------- *** lngamma: domain error in intformal: residue(series, pole) != 0 (0.59465032062247697727187848272191072247 + 0.576674047468581174134050794750 00049045*I) + (0.46300009662276378629832651818418579441 - 0.2942335427593188 6558301361715690299591*I)*x + (-0.065723534206032414131682728509702607416 + 0.13332642517253310620134768881568504070*I)*x^2 + (-0.0038124081589159963022 472229013688544964 - 0.052881096443660109736465443839034730260*I)*x^3 + (0.0 11646173710168721646303099647994255377 + 0.017474497859917982232442372031895 951470*I)*x^4 + (-0.0077757069690405743408170730434310459472 - 0.00403456423 41327827815714280332882428196*I)*x^5 + O(x^6) -0.57721566490153286060651209008240243104 + 1.644934066848226436472415166646 0251892*x - 1.2020569031595942853997381615114499908*x^2 + 1.0823232337111381 915160036965411679028*x^3 - 1.0369277551433699263313654864570341681*x^4 + 1. 0173430619844491397145179297909205279*x^5 + O(x^6) *** psi: Warning: normalizing a series with 0 leading term. -1.0000000000000000000000000000000000000*x^-1 + 0.92278433509846713939348790 991759756896 + 2.8949340668482264364724151666460251892*x - 0.077056903159594 285399738161511449990765*x^2 + 2.1448232337111381915160036965411679028*x^3 + O(x^4) (-3.5449077018110320545963349666822903656 + 0.E-37*I) + (-0.1293535897955400 5531547953707588123112 + 0.E-39*I)*x + (-15.83888462199733289130549035917458 6834 + 0.E-37*I)*x^2 + (-0.088235140923071374511750322744686276244 + 0.E-39* I)*x^3 + (-63.934119924167817737375290277713885431 + 0.E-36*I)*x^4 + (-0.042 848354492868684268292005312709223076 + 0.E-39*I)*x^5 + O(x^6) 1 - 0.57721566490153286060651209008240243104*a*x + O(x^2) -1.0000000000000000000000000000000000000*x^-1 - 0.57721566490153286060651209 008240243104 + 1.6449340668482264364724151666460251892*x - 1.202056903159594 2853997381615114499908*x^2 + 1.0823232337111381915160036965411679028*x^3 - 1 .0369277551433699263313654864570341681*x^4 + O(x^5) x^-1 - 0.57721566490153286060651209008240243104 + 0.989055995327972555395395 65150063470794*x - 0.90747907608088628901656016735627511493*x^2 + 0.98172808 683440018733638029402185085036*x^3 - 0.9819950689031452021047014137913746755 1*x^4 + O(x^5) 4.0238726007709377354370243392300398572 E2564 277.25887222397812376689284858327062723 0.70315664064524318722569033366791109947 170141183460469231740910675752738881536 1001.0000000000000000000000000000000000 8.4592930575197658134779513864578051837 E92 8.4592930575197658134779513864578051837 E92 + 417.27460269708707626917373711 782229398*I 799877009219260410589.21059353880333769 + 88.7228391116729996053515014380223 25492*I -864.73828787067971564321683481711497423 - 631.46012337154844093099132003918 007972*I 3.2007257594901922498857741835634344245 E867 3.0616681090421088936612867355651954590 E867 - 9.193770672812704213454512890 0883765323 E866*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778 + 417.27460269708707626917373711782 2293981451080884873662980649365715022960425756218794729722851598595227020005 2467288*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778 + 41727.460269708707626917373711782 2293981451080884873662980649365715022960425756218794729722851598595227020005 2467288*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778407117373385742831330551204346169684 432 + 417274.602697087076269173737117822293981451080884873662980649365715022 9604257562187947297228515985952270200052467287642139293693997776338197086953 142287383*I Total time spent: 16 pari-2.7.5/src/test/32/bit0000644000175000017500000001675212366172547013631 0ustar billbill4 3 2 3 100 *** at top-level: hammingweight(I) *** ^---------------- *** hammingweight: incorrect type in hammingweight (t_COMPLEX). [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0] #bitand [0, 0, 0] [0, 3, 0] [0, -3, 0] [0, 36893488147419103231, 0] [0, 340282366920938463481821351505477763073, 0] [0, -340282366920938463481821351505477763073, 0] [0, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [3, 3, 3] [3, -3, 1] [3, 36893488147419103231, 3] [3, 340282366920938463481821351505477763073, 1] [3, -340282366920938463481821351505477763073, 3] [3, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [-3, -3, -3] [-3, 36893488147419103231, 36893488147419103229] [-3, 340282366920938463481821351505477763073, 340282366920938463481821351505 477763073] [-3, -340282366920938463481821351505477763073, -3402823669209384634818213515 05477763075] [-3, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 36893488147419103231] [36893488147419103231, 340282366920938463481821351505477763073, 184467440737 09551617] [36893488147419103231, -340282366920938463481821351505477763073, 18446744073 709551615] [36893488147419103231, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 340282366920938463481821351505477763073] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, 1] [340282366920938463481821351505477763073, I, error("forbidden bitwise and t_ INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, -340282366920938463481821351505477763073] [-340282366920938463481821351505477763073, I, error("forbidden bitwise and t _INT , t_COMPLEX.")] [I, I, error("forbidden bitwise and t_COMPLEX , t_COMPLEX.")] #bitnegimply [0, 0, 0] [0, 3, 0] [0, -3, 0] [0, 36893488147419103231, 0] [0, 340282366920938463481821351505477763073, 0] [0, -340282366920938463481821351505477763073, 0] [0, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [3, 3, 0] [3, -3, 2] [3, 36893488147419103231, 0] [3, 340282366920938463481821351505477763073, 2] [3, -340282366920938463481821351505477763073, 0] [3, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [-3, -3, 0] [-3, 36893488147419103231, -36893488147419103232] [-3, 340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [-3, -340282366920938463481821351505477763073, 34028236692093846348182135150 5477763072] [-3, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 0] [36893488147419103231, 340282366920938463481821351505477763073, 184467440737 09551614] [36893488147419103231, -340282366920938463481821351505477763073, 18446744073 709551616] [36893488147419103231, I, error("forbidden bitwise negated imply t_INT , t_C OMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 0] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, 340282366920938463481821351505477763072] [340282366920938463481821351505477763073, I, error("forbidden bitwise negate d imply t_INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, 0] [-340282366920938463481821351505477763073, I, error("forbidden bitwise negat ed imply t_INT , t_COMPLEX.")] [I, I, error("forbidden bitwise negated imply t_COMPLEX , t_COMPLEX.")] #bitor [0, 0, 0] [0, 3, 3] [0, -3, -3] [0, 36893488147419103231, 36893488147419103231] [0, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763073] [0, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [0, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [3, 3, 3] [3, -3, -1] [3, 36893488147419103231, 36893488147419103231] [3, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763075] [3, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [3, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [-3, -3, -3] [-3, 36893488147419103231, -1] [-3, 340282366920938463481821351505477763073, -3] [-3, -340282366920938463481821351505477763073, -1] [-3, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 36893488147419103231] [36893488147419103231, 340282366920938463481821351505477763073, 340282366920 938463500268095579187314687] [36893488147419103231, -340282366920938463481821351505477763073, -3402823669 20938463463374607431768211457] [36893488147419103231, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 340282366920938463481821351505477763073] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, -1] [340282366920938463481821351505477763073, I, error("forbidden bitwise or t_I NT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, -340282366920938463481821351505477763073] [-340282366920938463481821351505477763073, I, error("forbidden bitwise or t_ INT , t_COMPLEX.")] [I, I, error("forbidden bitwise or t_COMPLEX , t_COMPLEX.")] #bitxor [0, 0, 0] [0, 3, 3] [0, -3, -3] [0, 36893488147419103231, 36893488147419103231] [0, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763073] [0, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [0, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [3, 3, 0] [3, -3, -2] [3, 36893488147419103231, 36893488147419103228] [3, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763074] [3, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [3, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [-3, -3, 0] [-3, 36893488147419103231, -36893488147419103230] [-3, 340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [-3, -340282366920938463481821351505477763073, 34028236692093846348182135150 5477763074] [-3, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 0] [36893488147419103231, 340282366920938463481821351505477763073, 340282366920 938463481821351505477763070] [36893488147419103231, -340282366920938463481821351505477763073, -3402823669 20938463481821351505477763072] [36893488147419103231, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 0] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, -2] [340282366920938463481821351505477763073, I, error("forbidden bitwise xor t_ INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, 0] [-340282366920938463481821351505477763073, I, error("forbidden bitwise xor t _INT , t_COMPLEX.")] [I, I, error("forbidden bitwise xor t_COMPLEX , t_COMPLEX.")] #bitneg [0, 36893488147419103231, -1] [3, 36893488147419103228, -4] [-3, 2, 2] [36893488147419103231, 0, -36893488147419103232] [340282366920938463481821351505477763073, 18446744073709551614, -34028236692 0938463481821351505477763074] [-340282366920938463481821351505477763073, 18446744073709551616, 34028236692 0938463481821351505477763072] error("incorrect type in bitwise negation (t_COMPLEX).") 1 1 *** at top-level: bitneg(1,-2) *** ^------------ *** bitneg: domain error in bitwise negation: exponent < -1 340282366920938463463374607431768211454 Total time spent: 0 pari-2.7.5/src/test/32/div0000644000175000017500000006056012366172547013631 0ustar billbill* [1, 1] 1 1 0 1 [1, 0]~ * [1, 2] 3/4 0 3 1 [0, 3]~ * [1, 3] 0.96774193548387096774193548387096774194 0 3 0 [0, 3]~ * [1, 4] 6 6 0 6 [6, 0]~ * [1, 5] 3/(x^2 + 1) 0 3 0 [0, 3]~ * [1, 6] Mod(-3*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [1, 7] 0 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [1, 8] -3 + 3*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [1, 9] 2*3 + 3^2 + 3^3 + O(3^4) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [1, 10] Mod(0, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [1, 11] 3/18446744073709551617 0 3 0 [0, 3]~ * [2, 1] 4/3 1 1 1 [1, 1]~ * [2, 2] 1 1 0 1 [1, 0]~ * [2, 3] 1.2903225806451612903225806451612903226 1 0.90000000000000000000000000000000000000 1 [1, 0.90000000000000000000000000000000000000]~ * [2, 4] 8 8 0 8 [8, 0]~ * [2, 5] 4/(x^2 + 1) 0 4 0 [0, 4]~ * [2, 6] Mod(-4*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [2, 7] 2*t^4 + 2*t^3 + t^2 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [2, 8] -4 + 4*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [2, 9] 2 + O(3^3) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [2, 10] Mod(2, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [2, 11] 4/18446744073709551617 0 4 0 [0, 4]~ * [3, 1] 1.0333333333333333333333333333333333333 1 0.099999999999999999999999999999999999995 1 [1, 0.099999999999999999999999999999999999995]~ * [3, 2] 0.77500000000000000000000000000000000000 0 3.1000000000000000000000000000000000000 0 [0, 3.1000000000000000000000000000000000000]~ * [3, 3] 1.0000000000000000000000000000000000000 1 0.E-37 1 [1, 0.E-37]~ * [3, 4] 6.2000000000000000000000000000000000000 6 0.099999999999999999999999999999999999995 6 [6, 0.099999999999999999999999999999999999995]~ * [3, 5] 3.1000000000000000000000000000000000000/(x^2 + 1) 0 3.1000000000000000000000000000000000000 0 [0, 3.1000000000000000000000000000000000000]~ * [3, 6] Mod(-3.1000000000000000000000000000000000000*x, x^2 + 1) error("forbidden division t_REAL \\ t_POLMOD.") error("forbidden division t_REAL % t_POLMOD.") error("forbidden division t_REAL \\ t_POLMOD.") error("forbidden division t_REAL \\ t_POLMOD.") * [3, 7] error("forbidden division t_REAL / t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") error("forbidden division t_REAL % t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") * [3, 8] 1.9159053651246740294342191865334781649 error("forbidden division t_REAL \\ t_QUAD.") error("forbidden division t_REAL % t_QUAD.") error("forbidden division t_REAL \\ t_QUAD.") error("forbidden division t_REAL \\ t_QUAD.") * [3, 9] error("forbidden division t_REAL / t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") error("forbidden division t_REAL % t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") * [3, 10] error("forbidden division t_REAL / t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") error("forbidden division t_REAL % t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") * [3, 11] 1.6805133673525318726204510291596823708 E-19 0 3.1000000000000000000000000000000000000 0 [0, 3.1000000000000000000000000000000000000]~ * [4, 1] 1/6 0 2 0 [0, 1/2]~ * [4, 2] 1/8 0 error("impossible inverse in Fl_inv: Mod(2, 4).") 0 [0, 1/2]~ * [4, 3] 0.16129032258064516129032258064516129032 0 1/2 0 [0, 1/2]~ * [4, 4] 1 1 0 1 [1, 0]~ * [4, 5] 1/(2*x^2 + 2) 0 1/2 0 [0, 1/2]~ * [4, 6] Mod(-1/2*x, x^2 + 1) error("forbidden division t_FRAC \\ t_POLMOD.") error("forbidden division t_FRAC % t_POLMOD.") error("forbidden division t_FRAC \\ t_POLMOD.") error("forbidden division t_FRAC \\ t_POLMOD.") * [4, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_FRAC \\ t_FFELT.") error("forbidden division t_FRAC % t_FFELT.") error("forbidden division t_FRAC \\ t_FFELT.") error("forbidden division t_FRAC \\ t_FFELT.") * [4, 8] -1/2 + 1/2*w error("forbidden division t_FRAC \\ t_QUAD.") error("forbidden division t_FRAC % t_QUAD.") error("forbidden division t_FRAC \\ t_QUAD.") error("forbidden division t_FRAC \\ t_QUAD.") * [4, 9] 1 + 2*3 + O(3^3) error("forbidden division t_FRAC \\ t_PADIC.") error("forbidden division t_FRAC % t_PADIC.") error("forbidden division t_FRAC \\ t_PADIC.") error("forbidden division t_FRAC \\ t_PADIC.") * [4, 10] Mod(1, 3) error("forbidden division t_FRAC \\ t_INTMOD.") error("forbidden division t_FRAC % t_INTMOD.") error("forbidden division t_FRAC \\ t_INTMOD.") error("forbidden division t_FRAC \\ t_INTMOD.") * [4, 11] 1/36893488147419103234 0 9223372036854775809 0 [0, 1/2]~ * [5, 1] 1/3*x^2 + 1/3 1/3*x^2 + 1/3 0 1/3*x^2 + 1/3 [1/3*x^2 + 1/3, 0]~ * [5, 2] 1/4*x^2 + 1/4 1/4*x^2 + 1/4 0 1/4*x^2 + 1/4 [1/4*x^2 + 1/4, 0]~ * [5, 3] 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 0 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 [0.32258064516129032258064516129032258065*x^2 + 0.32258064516129032258064516 129032258065, 0]~ * [5, 4] 2*x^2 + 2 2*x^2 + 2 0 2*x^2 + 2 [2*x^2 + 2, 0]~ * [5, 5] 1 1 0 1 [1, 0]~ * [5, 6] 0 error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") * [5, 7] (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) 0 (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) [(2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2), 0]~ * [5, 8] (-1 + w)*x^2 + (-1 + w) (-1 + w)*x^2 + (-1 + w) 0 (-1 + w)*x^2 + (-1 + w) [(-1 + w)*x^2 + (-1 + w), 0]~ * [5, 9] (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) 0 (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) [(2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)), 0]~ * [5, 10] Mod(2, 3)*x^2 + Mod(2, 3) Mod(2, 3)*x^2 + Mod(2, 3) Mod(0, 3) Mod(2, 3)*x^2 + Mod(2, 3) [Mod(2, 3)*x^2 + Mod(2, 3), Mod(0, 3)]~ * [5, 11] 1/18446744073709551617*x^2 + 1/18446744073709551617 1/18446744073709551617*x^2 + 1/18446744073709551617 0 1/18446744073709551617*x^2 + 1/18446744073709551617 [1/18446744073709551617*x^2 + 1/18446744073709551617, 0]~ * [6, 1] Mod(1/3*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") 0 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 error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD \\ t_INT.") * [6, 3] Mod(0.32258064516129032258064516129032258065*x, x^2 + 1) error("incorrect type in gfloor (t_POLMOD).") error("forbidden division t_POLMOD % t_REAL.") error("incorrect type in gfloor (t_POLMOD).") error("incorrect type in gfloor (t_POLMOD).") * [6, 4] Mod(2*x, x^2 + 1) error("incorrect type in gfloor (t_POLMOD).") 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("forbidden euclidean division t_POLMOD , t_POL.") Mod(x, x^2 + 1) error("forbidden euclidean division t_POLMOD , t_POL.") error("forbidden euclidean division t_POLMOD , t_POL.") * [6, 6] Mod(1, x^2 + 1) error("forbidden division t_POLMOD \\ t_POLMOD.") error("forbidden division t_POLMOD % t_POLMOD.") error("forbidden division t_POLMOD \\ t_POLMOD.") error("forbidden division t_POLMOD \\ t_POLMOD.") * [6, 7] Mod((2*t^4 + 2*t^3 + t^2)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_FFELT.") error("forbidden division t_POLMOD % t_FFELT.") error("forbidden division t_POLMOD \\ t_FFELT.") error("forbidden division t_POLMOD \\ t_FFELT.") * [6, 8] Mod((-1 + w)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD % t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") * [6, 9] Mod((2 + 3 + 3^2 + O(3^3))*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_PADIC.") error("forbidden division t_POLMOD % t_PADIC.") error("forbidden division t_POLMOD \\ t_PADIC.") error("forbidden division t_POLMOD \\ t_PADIC.") * [6, 10] Mod(Mod(2, 3)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INTMOD.") error("forbidden division t_POLMOD % t_INTMOD.") error("forbidden division t_POLMOD \\ t_INTMOD.") error("forbidden division t_POLMOD \\ t_INTMOD.") * [6, 11] Mod(1/18446744073709551617*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD % t_INT.") error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD \\ t_INT.") * [7, 1] error("impossible inverse in Fl_inv: Mod(0, 3).") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [7, 2] t error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [7, 3] error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT % t_REAL.") error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT / t_REAL.") * [7, 4] 2*t error("incorrect type in gfloor (t_FFELT).") error("forbidden division t_FFELT % t_FRAC.") error("incorrect type in gfloor (t_FFELT).") error("incorrect type in gfloor (t_FFELT).") * [7, 5] t/(x^2 + 1) 0 t 0 [0, t]~ * [7, 6] Mod(2*t*x, x^2 + 1) error("forbidden division t_FFELT \\ t_POLMOD.") error("forbidden division t_FFELT % t_POLMOD.") error("forbidden division t_FFELT \\ t_POLMOD.") error("forbidden division t_FFELT \\ t_POLMOD.") * [7, 7] 1 error("forbidden division t_FFELT \\ t_FFELT.") error("forbidden division t_FFELT % t_FFELT.") error("forbidden division t_FFELT \\ t_FFELT.") error("forbidden division t_FFELT \\ t_FFELT.") * [7, 8] error("forbidden division t_FFELT / t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT % t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") * [7, 9] error("forbidden division t_FFELT / t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") error("forbidden division t_FFELT % t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") * [7, 10] 2*t error("forbidden division t_FFELT \\ t_INTMOD.") error("forbidden division t_FFELT % t_INTMOD.") error("forbidden division t_FFELT \\ t_INTMOD.") error("forbidden division t_FFELT \\ t_INTMOD.") * [7, 11] 2*t error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [8, 1] 1/3*w error("forbidden division t_QUAD \\ t_INT.") w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [8, 2] 1/4*w error("forbidden division t_QUAD \\ t_INT.") w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [8, 3] 0.52194644798383704780793123689214132830 0 error("forbidden division t_QUAD % t_REAL.") 0 [0, w]~ * [8, 4] 2*w error("incorrect type in gfloor (t_QUAD).") error("forbidden division t_QUAD % t_FRAC.") error("incorrect type in gfloor (t_QUAD).") error("incorrect type in gfloor (t_QUAD).") * [8, 5] w/(x^2 + 1) 0 w 0 [0, w]~ * [8, 6] Mod(-w*x, x^2 + 1) error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD % t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") * [8, 7] error("forbidden division t_QUAD / t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD % t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") * [8, 8] 1 error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD % t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") * [8, 9] error("not an n-th power residue in Qp_sqrt: 5.") error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD % t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") * [8, 10] Mod(0, 3) + Mod(2, 3)*w error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD % t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") * [8, 11] 1/18446744073709551617*w error("forbidden division t_QUAD \\ t_INT.") w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [9, 1] 2*3^-1 + O(3^2) error("forbidden division t_PADIC \\ t_INT.") 2 error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [9, 2] 2 + 3 + 3^2 + O(3^3) error("forbidden division t_PADIC \\ t_INT.") error("inconsistent t_PADIC , t_INTMOD.") error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [9, 3] error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC % t_REAL.") error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC / t_REAL.") * [9, 4] 1 + 3 + O(3^3) error("incorrect type in gfloor (t_PADIC).") error("forbidden division t_PADIC % t_FRAC.") error("incorrect type in gfloor (t_PADIC).") error("incorrect type in gfloor (t_PADIC).") * [9, 5] (2 + O(3^3))/(x^2 + 1) 0 2 + O(3^3) 0 [0, 2 + O(3^3)]~ * [9, 6] Mod((1 + 2*3 + 2*3^2 + O(3^3))*x, x^2 + 1) error("forbidden division t_PADIC \\ t_POLMOD.") error("forbidden division t_PADIC % t_POLMOD.") error("forbidden division t_PADIC \\ t_POLMOD.") error("forbidden division t_PADIC \\ t_POLMOD.") * [9, 7] error("forbidden division t_PADIC / t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") error("forbidden division t_PADIC % t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") * [9, 8] 1 + 2*3 + 2*3^2 + O(3^3) + (2 + O(3^3))*w error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC % t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") * [9, 9] 1 + O(3^3) error("forbidden division t_PADIC \\ t_PADIC.") error("forbidden division t_PADIC % t_PADIC.") error("forbidden division t_PADIC \\ t_PADIC.") error("forbidden division t_PADIC \\ t_PADIC.") * [9, 10] Mod(1, 3) error("forbidden division t_PADIC \\ t_INTMOD.") error("forbidden division t_PADIC % t_INTMOD.") error("forbidden division t_PADIC \\ t_INTMOD.") error("forbidden division t_PADIC \\ t_INTMOD.") * [9, 11] 1 + 2*3 + 2*3^2 + O(3^3) error("forbidden division t_PADIC \\ t_INT.") error("inconsistent t_PADIC , t_INTMOD.") error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [10, 1] error("impossible inverse in Fl_inv: Mod(0, 3).") error("forbidden division t_INTMOD \\ t_INT.") Mod(2, 3) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [10, 2] Mod(2, 3) error("forbidden division t_INTMOD \\ t_INT.") Mod(0, 1) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [10, 3] error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD % t_REAL.") error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD / t_REAL.") * [10, 4] Mod(1, 3) error("incorrect type in gfloor (t_INTMOD).") error("forbidden division t_INTMOD % t_FRAC.") error("incorrect type in gfloor (t_INTMOD).") error("incorrect type in gfloor (t_INTMOD).") * [10, 5] Mod(2, 3)/(x^2 + 1) 0 Mod(2, 3) 0 [0, Mod(2, 3)]~ * [10, 6] Mod(Mod(1, 3)*x, x^2 + 1) error("forbidden division t_INTMOD \\ t_POLMOD.") error("forbidden division t_INTMOD % t_POLMOD.") error("forbidden division t_INTMOD \\ t_POLMOD.") error("forbidden division t_INTMOD \\ t_POLMOD.") * [10, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_INTMOD \\ t_FFELT.") error("forbidden division t_INTMOD % t_FFELT.") error("forbidden division t_INTMOD \\ t_FFELT.") error("forbidden division t_INTMOD \\ t_FFELT.") * [10, 8] Mod(1, 3) + Mod(2, 3)*w error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD % t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") * [10, 9] Mod(1, 3) error("forbidden division t_INTMOD \\ t_PADIC.") error("forbidden division t_INTMOD % t_PADIC.") error("forbidden division t_INTMOD \\ t_PADIC.") error("forbidden division t_INTMOD \\ t_PADIC.") * [10, 10] Mod(1, 3) error("forbidden division t_INTMOD \\ t_INTMOD.") error("forbidden division t_INTMOD % t_INTMOD.") error("forbidden division t_INTMOD \\ t_INTMOD.") error("forbidden division t_INTMOD \\ t_INTMOD.") * [10, 11] Mod(1, 3) error("forbidden division t_INTMOD \\ t_INT.") Mod(0, 1) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [11, 1] 18446744073709551617/3 6148914691236517205 2 6148914691236517206 [6148914691236517205, 2]~ * [11, 2] 18446744073709551617/4 4611686018427387904 1 4611686018427387904 [4611686018427387904, 1]~ * [11, 3] 5950562604422436005.4838709677419354839 5950562604422436005 1.5000000000000000001 5950562604422436005 [5950562604422436005, 1.5000000000000000001]~ * [11, 4] 36893488147419103234 36893488147419103234 0 36893488147419103234 [36893488147419103234, 0]~ * [11, 5] 18446744073709551617/(x^2 + 1) 0 18446744073709551617 0 [0, 18446744073709551617]~ * [11, 6] Mod(-18446744073709551617*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [11, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [11, 8] -18446744073709551617 + 18446744073709551617*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [11, 9] 1 + 3 + 3^2 + O(3^3) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [11, 10] Mod(1, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [11, 11] 1 1 0 1 [1, 0]~ * [1, 1] 1/3*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [1, 2] 1/4*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [1, 3] 0.32258064516129032258064516129032258065*x + O(x^2) error("incorrect type in gfloor (t_SER).") error("forbidden division t_SER % t_REAL.") error("incorrect type in gfloor (t_SER).") * [1, 4] 2*x + O(x^2) error("incorrect type in gfloor (t_SER).") error("forbidden division t_SER % t_FRAC.") error("incorrect type in gfloor (t_SER).") * [1, 5] x + O(x^2) error("forbidden euclidean division t_SER , t_POL.") error("forbidden division t_SER % t_POL.") error("forbidden euclidean division t_SER , t_POL.") * [1, 6] error("forbidden division t_SER % t_POL.") error("forbidden division t_SER \\ t_POLMOD.") error("forbidden division t_SER % t_POLMOD.") error("forbidden division t_SER \\ t_POLMOD.") * [1, 7] (2*t^4 + 2*t^3 + t^2)*x + O(x^2) error("forbidden division t_SER \\ t_FFELT.") error("forbidden division t_SER % t_FFELT.") error("forbidden division t_SER \\ t_FFELT.") * [1, 8] (-1 + w)*x + O(x^2) error("forbidden division t_SER \\ t_QUAD.") error("forbidden division t_SER % t_QUAD.") error("forbidden division t_SER \\ t_QUAD.") * [1, 9] (2 + 3 + 3^2 + O(3^3))*x + O(x^2) error("forbidden division t_SER \\ t_PADIC.") error("forbidden division t_SER % t_PADIC.") error("forbidden division t_SER \\ t_PADIC.") * [1, 10] Mod(2, 3)*x + O(x^2) error("forbidden division t_SER \\ t_INTMOD.") error("forbidden division t_SER % t_INTMOD.") error("forbidden division t_SER \\ t_INTMOD.") * [1, 11] 1/18446744073709551617*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [2, 1] [2/3, 1] [0, 1] [2, 0] [1, 1] * [2, 2] [1/2, 3/4] [0, 0] [2, 3] [1, 1] * [2, 3] [0.64516129032258064516129032258064516129, 0.9677419354838709677419354838709 6774194] [0, 0] [2, 3] [0, 0] * [2, 4] [4, 6] [4, 6] [0, 0] [4, 6] * [2, 5] [2/(x^2 + 1), 3/(x^2 + 1)] [0, 0] [2, 3] [0, 0] * [2, 6] [Mod(-2*x, x^2 + 1), Mod(-3*x, x^2 + 1)] error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [2, 7] [t^4 + t^3 + 2*t^2, 0] error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [2, 8] [-2 + 2*w, -3 + 3*w] error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [2, 9] [1 + O(3^3), 2*3 + 3^2 + 3^3 + O(3^4)] error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [2, 10] [Mod(1, 3), Mod(0, 3)] error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [2, 11] [2/18446744073709551617, 3/18446744073709551617] [0, 0] [2, 3] [0, 0] * [3, 1] Mat(2/3) Mat(0) Mat(2) Mat(1) * [3, 2] Mat(1/2) Mat(0) Mat(2) Mat(1) * [3, 3] Mat(0.64516129032258064516129032258064516129) Mat(0) Mat(2) Mat(0) * [3, 4] Mat(4) Mat(4) Mat(0) Mat(4) * [3, 5] Mat(2/(x^2 + 1)) Mat(0) Mat(2) Mat(0) * [3, 6] Mat(Mod(-2*x, x^2 + 1)) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [3, 7] Mat(t^4 + t^3 + 2*t^2) error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [3, 8] Mat(-2 + 2*w) error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [3, 9] Mat(1 + O(3^3)) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [3, 10] Mat(Mod(1, 3)) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [3, 11] Mat(2/18446744073709551617) Mat(0) Mat(2) Mat(0) [0, 1] Mat(0) [1, 1] Mat(1) [-x + y, x^2 + x]~ [[1, 1]~, [2, 1]~] [0, 1]~ [1, 0]~ *** at top-level: divrem(1,"a") *** ^------------- *** divrem: forbidden division t_INT \ t_STR. 2 x Total time spent: 0 pari-2.7.5/src/test/32/galois0000644000175000017500000001454312366172547014325 0ustar billbill[2, -1, 1, "S2"]1 [3, 1, 1, "A3"]1 [6, -1, 2, "S3"]1 [4, -1, 1, "C(4) = 4"]1 [4, 1, 2, "E(4) = 2[x]2"]1 [8, -1, 3, "D(4)"]1 [12, 1, 4, "A4"]1 [24, -1, 5, "S4"]1 [5, 1, 1, "C(5) = 5"]1 [10, 1, 2, "D(5) = 5:2"]1 [20, -1, 3, "F(5) = 5:4"]1 [60, 1, 4, "A5"]1 [120, -1, 5, "S5"]1 [6, -1, 1, "C(6) = 6 = 3[x]2"]1 [6, -1, 2, "D_6(6) = [3]2"]1 [12, -1, 3, "D(6) = S(3)[x]2"]1 [12, 1, 4, "A_4(6) = [2^2]3"]1 [18, -1, 5, "F_18(6) = [3^2]2 = 3 wr 2"]1 [24, -1, 6, "2A_4(6) = [2^3]3 = 2 wr 3"]1 [24, 1, 7, "S_4(6d) = [2^2]S(3)"]1 [24, -1, 8, "S_4(6c) = 1/2[2^3]S(3)"]1 [36, -1, 9, "F_18(6):2 = [1/2.S(3)^2]2"]1 [36, 1, 10, "F_36(6) = 1/2[S(3)^2]2"]1 [48, -1, 11, "2S_4(6) = [2^3]S(3) = 2 wr S(3)"]1 [60, 1, 12, "L(6) = PSL(2,5) = A_5(6)"]1 [72, -1, 13, "F_36(6):2 = [S(3)^2]2 = S(3) wr 2"]1 [120, -1, 14, "L(6):2 = PGL(2,5) = S_5(6)"]1 [360, 1, 15, "A6"]1 [720, -1, 16, "S6"]1 [7, 1, 1, "C(7) = 7"]1 [14, -1, 2, "D(7) = 7:2"]1 [21, 1, 3, "F_21(7) = 7:3"]1 [42, -1, 4, "F_42(7) = 7:6"]1 [168, 1, 5, "L(7) = L(3,2)"]1 [2520, 1, 6, "A7"]1 [5040, -1, 7, "S7"]1 [8, -1, 1, "C(8)=8"]1 [8, 1, 2, "4[x]2"]1 [8, 1, 3, "E(8)=2[x]2[x]2"]1 [8, 1, 4, "D_8(8)=[4]2"]1 [8, 1, 5, "Q_8(8)"]1 [16, -1, 6, "D(8)"]1 [16, -1, 7, "1/2[2^3]4"]1 [16, -1, 8, "2D_8(8)=[D(4)]2"]1 [16, 1, 9, "E(8):2=D(4)[x]2"]1 [16, 1, 10, "[2^2]4"]1 [16, 1, 11, "1/2[2^3]E(4)=Q_8:2"]1 [24, 1, 12, "2A_4(8)=[2]A(4)=SL(2,3)"]1 [24, 1, 13, "E(8):3=A(4)[x]2"]1 [24, 1, 14, "S(4)[1/2]2=1/2(S_4[x]2)"]1 [32, -1, 15, "[1/4.cD(4)^2]2"]1 [32, -1, 16, "1/2[2^4]4"]1 [32, -1, 17, "[4^2]2"]1 [32, 1, 18, "E(8):E_4=[2^2]D(4)"]1 [32, 1, 19, "E(8):4=[1/4.eD(4)^2]2"]1 [32, 1, 20, "[2^3]4"]1 [32, -1, 21, "1/2[2^4]E(4)=[1/4.dD(4)^2]2"]1 [32, 1, 22, "E(8):D_4=[2^3]2^2"]1 [48, -1, 23, "2S_4(8)=GL(2,3)"]1 [48, 1, 24, "E(8):D_6=S(4)[x]2"]1 [56, 1, 25, "E(8):7=F_56(8)"]1 [64, -1, 26, "1/2[2^4]eD(4)"]1 [64, -1, 27, "[2^4]4"]1 [64, -1, 28, "1/2[2^4]dD(4)"]1 [64, 1, 29, "E(8):D_8=[2^3]D(4)"]1 [64, -1, 30, "1/2[2^4]cD(4)"]1 [64, -1, 31, "[2^4]E(4)"]1 [96, 1, 32, "[2^3]A(4)"]1 [96, 1, 33, "E(8):A_4=[1/3.A(4)^2]2=E(4):6"]1 [96, 1, 34, "1/2[E(4)^2:S_3]2=E(4)^2:D_6"]1 [128, -1, 35, "[2^4]D(4)"]1 [168, 1, 36, "E(8):F_21"]1 [168, 1, 37, "L(8)=PSL(2,7)"]1 [192, -1, 38, "[2^4]A(4)"]1 [192, 1, 39, "[2^3]S(4)"]1 [192, -1, 40, "1/2[2^4]S(4)"]1 [192, 1, 41, "E(8):S_4=[E(4)^2:S_3]2=E(4)^2:D_12"]1 [288, 1, 42, "[A(4)^2]2"]1 [336, -1, 43, "L(8):2=PGL(2,7)"]1 [384, -1, 44, "[2^4]S(4)"]1 [576, 1, 45, "[1/2.S(4)^2]2"]1 [576, -1, 46, "1/2[S(4)^2]2"]1 [1152, -1, 47, "[S(4)^2]2"]1 [1344, 1, 48, "E(8):L_7=AL(8)"]1 [20160, 1, 49, "A8"]1 [40320, -1, 50, "S8"]1 [9, 1, 1, "C(9)=9"]1 [9, 1, 2, "E(9)=3[x]3"]1 [18, 1, 3, "D(9)=9:2"]1 [18, -1, 4, "S(3)[x]3"]1 [18, 1, 5, "S(3)[1/2]S(3)=3^2:2"]1 [27, 1, 6, "1/3[3^3]3"]1 [27, 1, 7, "E(9):3=[3^2]3"]1 [36, -1, 8, "S(3)[x]S(3)=E(9):D_4"]1 [36, 1, 9, "E(9):4"]1 [54, 1, 10, "[3^2]S(3)_6"]1 [54, 1, 11, "E(9):6=1/2[3^2:2]S(3)"]1 [54, -1, 12, "[3^2]S(3)"]1 [54, -1, 13, "E(9):D_6=[3^2:2]3=[1/2.S(3)^2]3"]1 [72, 1, 14, "M(9)=E(9):Q_8"]1 [72, -1, 15, "E(9):8"]1 [72, -1, 16, "E(9):D_8"]1 [81, 1, 17, "[3^3]3=3wr3"]1 [108, -1, 18, "E(9):D_12=[3^2:2]S(3)=[1/2.S(3)^2]S(3)"]1 [144, -1, 19, "E(9):2D_8"]1 [162, -1, 20, "[3^3]S(3)=3wrS(3)"]1 [162, 1, 21, "1/2.[3^3:2]S(3)"]1 [162, -1, 22, "[3^3:2]3"]1 [216, 1, 23, "E(9):2A_4"]1 [324, -1, 24, "[3^3:2]S(3)"]1 [324, 1, 25, "[1/2.S(3)^3]3"]1 [432, -1, 26, "E(9):2S_4"]1 [504, 1, 27, "L(9)=PSL(2,8)"]1 [648, -1, 28, "[S(3)^3]3=S(3)wr3"]1 [648, -1, 29, "[1/2.S(3)^3]S(3)"]1 [648, 1, 30, "1/2[S(3)^3]S(3)"]1 [1296, -1, 31, "[S(3)^3]S(3)=S(3)wrS(3)"]1 [1512, 1, 32, "L(9):3=P|L(2,8)"]1 [181440, 1, 33, "A9"]1 [362880, -1, 34, "S9"]1 [10, -1, 1, "C(10)=5[x]2"]1 [10, -1, 2, "D(10)=5:2"]1 [20, -1, 3, "D_10(10)=[D(5)]2"]1 [20, -1, 4, "1/2[F(5)]2"]1 [40, -1, 5, "F(5)[x]2"]1 [50, -1, 6, "[5^2]2"]1 [60, 1, 7, "A_5(10)"]1 [80, 1, 8, "[2^4]5"]1 [100, -1, 9, "[1/2.D(5)^2]2"]1 [100, -1, 10, "1/2[D(5)^2]2"]1 [120, -1, 11, "A(5)[x]2"]1 [120, -1, 12, "1/2[S(5)]2=S_5(10a)"]1 [120, -1, 13, "S_5(10d)"]1 [160, -1, 14, "[2^5]5"]1 [160, 1, 15, "[2^4]D(5)"]1 [160, -1, 16, "1/2[2^5]D(5)"]1 [200, -1, 17, "[5^2:4]2"]1 [200, 1, 18, "[5^2:4]2_2"]1 [200, -1, 19, "[5^2:4_2]2"]1 [200, -1, 20, "[5^2:4_2]2_2"]1 [200, -1, 21, "[D(5)^2]2"]1 [240, -1, 22, "S(5)[x]2"]1 [320, -1, 23, "[2^5]D(5)"]1 [320, 1, 24, "[2^4]F(5)"]1 [320, -1, 25, "1/2[2^5]F(5)"]1 [360, 1, 26, "L(10)=PSL(2,9)"]1 [400, -1, 27, "[1/2.F(5)^2]2"]1 [400, 1, 28, "1/2[F(5)^2]2"]1 [640, -1, 29, "[2^5]F(5)"]1 [720, -1, 30, "L(10):2=PGL(2,9)"]1 [720, 1, 31, "M(10)=L(10)'2"]1 [720, -1, 32, "S_6(10)=L(10):2"]1 [800, -1, 33, "[F(5)^2]2"]1 [960, 1, 34, "[2^4]A(5)"]1 [1440, -1, 35, "L(10).2^2=P|L(2,9)"]1 [1920, -1, 36, "[2^5]A(5)"]1 [1920, 1, 37, "[2^4]S(5)"]1 [1920, -1, 38, "1/2[2^5]S(5)"]1 [3840, -1, 39, "[2^5]S(5)"]1 [7200, -1, 40, "[A(5)^2]2"]1 [14400, -1, 41, "[1/2.S(5)^2]2=[A(5):2]2"]1 [14400, 1, 42, "1/2[S(5)^2]2"]1 [28800, -1, 43, "[S(5)^2]2"]1 [1814400, 1, 44, "A10"]1 [3628800, -1, 45, "S10"]1 [11, 1, 1, "C(11)=11"]1 [22, -1, 2, "D(11)=11:2"]1 [55, 1, 3, "F_55(11)=11:5"]1 [110, -1, 4, "F_110(11)=11:10"]1 [660, 1, 5, "L(11)=PSL(2,11)(11)"]1 [7920, 1, 6, "M(11)"]1 [19958400, 1, 7, "A11"]1 [39916800, -1, 8, "S11"]1 [2, -1, 1, "S2"]1 [3, 1, 1, "A3"]1 [6, -1, 1, "S3"]1 [4, -1, 1, "C(4) = 4"]1 [4, 1, 1, "E(4) = 2[x]2"]1 [8, -1, 1, "D(4)"]1 [12, 1, 1, "A4"]1 [24, -1, 1, "S4"]1 [5, 1, 1, "C(5) = 5"]1 [10, 1, 1, "D(5) = 5:2"]1 [20, -1, 1, "F(5) = 5:4"]1 [60, 1, 1, "A5"]1 [120, -1, 1, "S5"]1 [6, -1, 1, "C(6) = 6 = 3[x]2"]1 [6, -1, 2, "D_6(6) = [3]2"]1 [12, -1, 1, "D(6) = S(3)[x]2"]1 [12, 1, 1, "A_4(6) = [2^2]3"]1 [18, -1, 1, "F_18(6) = [3^2]2 = 3 wr 2"]1 [24, -1, 2, "2A_4(6) = [2^3]3 = 2 wr 3"]1 [24, 1, 1, "S_4(6d) = [2^2]S(3)"]1 [24, -1, 1, "S_4(6c) = 1/2[2^3]S(3)"]1 [36, -1, 1, "F_18(6):2 = [1/2.S(3)^2]2"]1 [36, 1, 1, "F_36(6) = 1/2[S(3)^2]2"]1 [48, -1, 1, "2S_4(6) = [2^3]S(3) = 2 wr S(3)"]1 [60, 1, 1, "L(6) = PSL(2,5) = A_5(6)"]1 [72, -1, 1, "F_36(6):2 = [S(3)^2]2 = S(3) wr 2"]1 [120, -1, 1, "L(6):2 = PGL(2,5) = S_5(6)"]1 [360, 1, 1, "A6"]1 [720, -1, 1, "S6"]1 [7, 1, 1, "C(7) = 7"]1 [14, -1, 1, "D(7) = 7:2"]1 [21, 1, 1, "F_21(7) = 7:3"]1 [42, -1, 1, "F_42(7) = 7:6"]1 [168, 1, 1, "L(7) = L(3,2)"]1 [2520, 1, 1, "A7"]1 [5040, -1, 1, "S7"]1 [16, -1, 7, "1/2[2^3]4"] [10, -1, 1, "C(10)=5[x]2"] [32, -1, 21, "1/2[2^4]E(4)=[1/4.dD(4)^2]2"] [32, -1, 15, "[1/4.cD(4)^2]2"] [8, 1, 2, "4[x]2"] [16, -1, 7, "1/2[2^3]4"] [16, -1, 7, "1/2[2^3]4"] [16, -1, 8, "2D_8(8)=[D(4)]2"] [8, 1, 2, "4[x]2"] [39916800, -1, 8, "S11"] Total time spent: 7552 pari-2.7.5/src/test/32/pow0000644000175000017500000000322112571635623013640 0ustar billbillMod(1, 3) Mod(1, 3) 1 [;] [1] Qfb(1, 2, -1, 0.E-38) Qfb(-1, 2, 1, 0.E-38) Vecsmall([1, 2, 3]) O(2) *** at top-level: O(2)^-2 *** ^--- *** _^_: impossible inverse in powps: O(2). 4 9/4 1 1 -1 *** at top-level: 2^n *** ^-- *** _^_: overflow in lg(). *** at top-level: (1/2)^n *** ^-- *** _^_: overflow in lg(). Qfb(2, 0, -1, 0.E-38) Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) O(x^0) x + O(x^4) [8.0000000000000000000000000000000000000, 27.0000000000000000000000000000000 00000] [8.0000000000000000000000000000000000000, 27.0000000000000000000000000000000 00000]~ [8.0000000000000000000000000000000000000] O(x^0) 0.E-19 *** at top-level: Mod(2,3)^(1/2) *** ^------ *** _^_: not an n-th power residue in gpow: Mod(2, 3). Mod(2, 3) *** at top-level: Mod(1,4)^(1/2) *** ^------ *** _^_: not a prime number in gpow: 4. 3 + 7 + 2*7^2 + 6*7^3 + 7^4 + O(7^5) *** at top-level: (3+O(7^5))^(1/2) *** ^------ *** _^_: not an n-th power residue in gpow: 3 + O(7^5). 1 + O(2) 1 + O(2) *** at top-level: sqrt(Mod(2,4)) *** ^-------------- *** sqrt: not a prime number in Fl_sqrt [modulus]: 4. [[0, 0], [1.0000000000000000000000000000000000000, 1.00000000000000000000000 00000000000000]] [[0, 0]~, [1.0000000000000000000000000000000000000, 1.0000000000000000000000 000000000000000]~] [[0, 0; 0, 0], [1.0000000000000000000000000000000000000, 1.00000000000000000 00000000000000000000; 1.0000000000000000000000000000000000000, 1.00000000000 00000000000000000000000000]] Total time spent: 4 pari-2.7.5/src/test/32/diffop0000644000175000017500000000076012366172547014312 0ustar billbill(X^11 + 55*X^9 + 990*X^7 + 6930*X^5 + 17325*X^3 + 10395*X)*E Mod(((512*C^8 - 130560*C^6 + 1693440*C^4 - 4838400*C^2 + 3628800)/C^11)*S, S ^2 + (C^2 - 1)) 240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + 362880*q^6 + 577920* 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(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 pari-2.7.5/src/test/32/member0000644000175000017500000002622612456454707014320 0ustar billbill.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.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]] .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.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])]]] .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-48), Qfb(3, 29, -22, 0.E-48)]] .cyc: [2, 2] .gen: [Qfb(2, 31, -18, 0.E-48), Qfb(3, 29, -22, 0.E-48)] .no: 4 .reg: 10.950385405825605330267750825017937393 GAL .gen: [Vecsmall([2, 1])] .group: [Vecsmall([1, 2]), Vecsmall([2, 1])] .mod: 96889010407 .orders: Vecsmall([2]) .p: 7 .pol: x^2 - 2 .roots: [19757775943, 77131234464]~ 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(12, 13), Mod(3, 13)]] .group: [13, [13], [[Mod(12, 13), Mod(3, 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: [[9*x + 8, 4*x + 2]] .group: [195, [195], [[9*x + 8, 4*x + 2]]] .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 pari-2.7.5/src/test/32/valuation0000644000175000017500000000121512405547147015035 0ustar billbilloo oo oo oo 0 0 0 0 0 -1 0 0 ERROR ERROR 0 0 0 ERROR 0 0 ERROR 0 0 0 ERROR ERROR 0 0 1 0 0 0 ERROR 1 0 0 0 0 ERROR 0 1 0 0 0 0 1 1 ERROR *** at top-level: valuation(0,1) *** ^-------------- *** valuation: domain error in gvaluation: p = 1 *** at top-level: valuation(0,-1) *** ^--------------- *** valuation: domain error in gvaluation: p = -1 *** at top-level: valuation(0,0) *** ^-------------- *** valuation: domain error in gvaluation: p = 0 2 1.0000000000000000000000000000000000000 - 1.00000000000000000000000000000000 00000*x + O(x^2) 1 O(x) Total time spent: 8 pari-2.7.5/src/test/32/dirmul0000644000175000017500000000016112366172547014332 0ustar billbill[0, 0, 0, 1] [0, 1] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] [1, 4, 6, 12] [1, 0, 0, 0] [1/2, 0, 0, 0] Total time spent: 8 pari-2.7.5/src/test/32/deriv0000644000175000017500000000161312366172547014152 0ustar billbill-0.65364362086361191463916818309775038142 -0.65364362086361191463916818309775038142 1 + O(t^2) 0 Mod(x, x^2 + 1) Mod(x, x^2 + 1) error("incorrect priority in intformal: variable x = x") Mod(1/2*y^2*x + y, x^2 + 1) Mod(0, 3) Mod(0, 3) Mod(0, 3) Mod(1, 3)*x Mod(1, 3)*y 0 0 0 t*x t*y y + O(x^2) y + O(x^2) x + O(x^3) x + 1/2*y*x^2 + O(x^4) y + 1/2*y^2*x + O(x^3) y/(x^2 + 2*y*x + y^2) y/(x^2 + 2*y*x + y^2) -x/(x^2 + 2*y*x + y^2) error("domain error in intformal: residue(series, pole) != 0") error("domain error in intformal: residue(series, pole) != 0") (-x^4 - 6*x^2 - 12*x + 3)/(3*x^6 + 9*x^4 + 9*x^2 + 3) (-x^4 - 6*x^2 - 12*x + 3)/(3*x^6 + 9*x^4 + 9*x^2 + 3) 0 error("domain error in intformal: residue(series, pole) != 0") (y*x^3 + 3*y*x + 3*y)/(3*x^4 + 6*x^2 + 3) [y] [y] [x] [1/2*y*x^2] [1/2*y^2*x] Mat(y) Mat(y) Mat(x) Mat(1/2*y*x^2) Mat(1/2*y^2*x) -Y*A + Y 0 0 x x O(x) O(x) x x Total time spent: 0 pari-2.7.5/src/test/32/pol0000644000175000017500000000220412516207611013614 0ustar billbillMod(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) y x x y + O(y^17) y + O(x^16) y + O(x^5) 0 0 0 y^-1 + O(y^15) 1/y + O(x^16) 1/y + O(x^5) y x x y^-1 + y + O(y^15) ((y^2 + 1)/y) + O(x^16) ((y^2 + 1)/y) + O(x^5) y^2 + 2*y + 3 x^2 + 2*x + 3 3*x^2 + 2*x + 1 1 + 2*y + 3*y^2 + O(y^3) 1 + 2*x + 3*x^2 + O(x^3) 1 + 2*x + 3*x^2 + O(x^3) y^2 + 2*y x^2 + 2*x 2*x + 1 1 + 2*y + O(y^3) 1 + 2*x + O(x^3) 1 + 2*x + O(x^3) y^2 + 2*y + 4 x^2 + 2*x + 4 4*x^2 + 2*x + 1 1 + 2*y + 4*y^2 + O(y^3) 1 + 2*x + 4*x^2 + O(x^3) 1 + 2*x + 4*x^2 + O(x^3) y^2 + 2*y - 4 x^2 + 2*x - 4 -4*x^2 + 2*x + 1 1 + 2*y - 4*y^2 + O(y^3) 1 + 2*x - 4*x^2 + O(x^3) 1 + 2*x - 4*x^2 + O(x^3) 2*y^2 + y 2*x^2 + x 2*x^2 + x 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) 1 1 x + 2 x^2 + x + 1 -x^3 - 2*x^2 - x + 1 [4, 0, 0, 0, -2]~ x^2 + 1 2 [0 -1/2] [1 0] *** at top-level: Pol("") *** ^------- *** Pol: incorrect type in gtopoly (t_STR). "t_INT" *** polroots: Warning: normalizing a polynomial with 0 leading term. [0.E-38 + 0.E-38*I]~ Total time spent: 0 pari-2.7.5/src/test/32/bnfisintnorm0000644000175000017500000001165112314242551015536 0ustar billbill echo = 1 (on) ? setrand(1);bnf=bnfinit(x^2+105); ? for(i=1,1000,do(i)) 1:1 4:1 9:1 16:1 25:1 36:1 49:1 64:1 81:1 100:1 105:1 106:2 109:2 114:2 121:3 130:2 141:2 144:1 154:2 169:3 186:2 196:1 205:2 225:1 226:2 249:2 256:1 274:2 289:1 301:2 324:1 330:2 361:3 394:2 400:1 420:1 421:2 424:2 429:4 436:2 441:1 445:2 456:2 466:2 469:2 484:3 501:2 505:2 520:2 529:1 541:2 546:2 564:2 576:1 589:4 616:2 625:1 634:2 645:2 676:3 681:2 709:2 729:1 730:2 744:2 781:4 784:1 820:2 834:2 841:1 861:2 889:2 900:1 904:2 945:1 946:4 949:4 954:2 961:3 970:2 981:2 994:2 996:2 ? setrand(1);bnf=bnfinit(x^2-65); ? for(i=1,1000,do(i-500)) -491:2 -490:6 -485:2 -484:3 -481:2 -469:4 -464:10 -454:4 -446:4 -441:3 -439:2 -419:2 -416:6 -415:2 -406:8 -404:6 -400:5 -394:4 -389:2 -386:4 -376:8 -365:2 -364:6 -361:1 -360:4 -350:4 -335:2 -334:4 -329:4 -326:4 -324:3 -316:6 -315:2 -311:2 -296:8 -290:4 -289:1 -274:4 -269:2 -261:2 -260:3 -259:4 -256:9 -251:2 -250:2 -244:6 -235:2 -234:2 -225:1 -224:12 -211:2 -199:2 -196:9 -194:4 -191:2 -185:2 -181:2 -179:2 -169:1 -166:4 -160:6 -146:4 -144:5 -140:6 -139:2 -134:4 -131:2 -126:4 -121:1 -116:6 -104:4 -101:2 -100:3 -94:4 -91:2 -90:2 -81:1 -79:2 -74:4 -65:1 -64:7 -61:2 -56:8 -49:3 -40:4 -36:3 -35:2 -29:2 -26:2 -25:1 -16:5 -14:4 -10:2 -9:1 -4:3 -1:1 0:1 1:1 4:3 9:1 10:2 14:4 16:5 25:1 26:2 29:2 35:2 36:3 40:4 49:3 56:8 61:2 64:7 65:1 74:4 79:2 81:1 90:2 91:2 94:4 100:3 101:2 104:4 116:6 121:1 126:4 131:2 134:4 139:2 140:6 144:5 146:4 160:6 166:4 169:1 179:2 181:2 185:2 191:2 194:4 196:9 199:2 211:2 224:12 225:1 234:2 235:2 244:6 250:2 251:2 256:9 259:4 260:3 261:2 269:2 274:4 289:1 290:4 296:8 311:2 315:2 316:6 324:3 326:4 329:4 334:4 335:2 350:4 360:4 361:1 364:6 365:2 376:8 386:4 389:2 394:4 400:5 404:6 406:8 415:2 416:6 419:2 439:2 441:3 446:4 454:4 464:10 469:4 481:2 484:3 485:2 490:6 491:2 ? setrand(1);bnf=bnfinit(x^5-37); ? for(i=1,1000,do(i-500)) -499:1 -497:3 -496:2 -494:1 -491:3 -490:1 -487:1 -486:1 -483:1 -481:1 -478:1 -477:1 -476:1 -475:1 -474:1 -468:1 -466:1 -465:4 -463:1 -461:1 -457:1 -455:1 -454:1 -452:1 -450:1 -448:2 -447:1 -446:1 -443:1 -442:1 -441:1 -439:1 -435:1 -434:1 -426:2 -425:1 -424:1 -419:1 -417:1 -416:2 -415:1 -412:1 -405:1 -403:1 -402:1 -400:2 -398:1 -394:1 -392:1 -386:1 -382:3 -381:1 -380:1 -373:1 -372:4 -371:1 -370:1 -365:1 -364:1 -361:1 -360:1 -359:1 -358:1 -355:3 -354:1 -350:1 -349:1 -348:1 -347:1 -345:1 -343:1 -342:1 -340:1 -338:1 -337:1 -333:1 -332:1 -327:1 -326:1 -325:1 -324:1 -323:1 -321:1 -320:2 -317:1 -315:1 -314:1 -313:1 -310:1 -306:1 -304:2 -296:1 -293:1 -292:1 -291:1 -289:1 -288:2 -284:3 -282:1 -281:3 -280:1 -279:1 -276:1 -274:1 -272:2 -269:1 -267:1 -266:1 -265:1 -260:1 -259:1 -258:1 -256:3 -252:1 -250:1 -248:1 -247:1 -245:1 -243:1 -239:1 -238:1 -237:1 -234:1 -233:1 -227:1 -226:1 -225:1 -224:2 -223:1 -221:1 -217:1 -213:2 -212:1 -208:2 -206:1 -201:1 -200:1 -199:1 -197:1 -196:1 -193:1 -191:3 -190:1 -186:4 -185:1 -182:1 -180:1 -179:1 -177:1 -175:1 -174:1 -171:1 -170:1 -169:1 -166:1 -163:1 -162:1 -160:2 -157:1 -155:1 -153:1 -152:1 -148:1 -146:1 -144:2 -142:3 -141:1 -140:1 -138:1 -137:1 -136:1 -133:1 -130:1 -129:1 -128:2 -126:1 -125:1 -124:1 -119:1 -117:1 -113:1 -112:2 -106:1 -104:1 -103:1 -100:1 -98:1 -95:1 -93:4 -91:1 -90:1 -87:1 -85:1 -83:1 -81:1 -80:2 -76:1 -74:1 -73:1 -72:1 -71:3 -70:1 -69:1 -68:1 -65:1 -64:2 -63:1 -62:1 -56:1 -53:1 -52:1 -50:1 -49:1 -45:1 -40:1 -38:1 -37:1 -36:1 -35:1 -34:1 -32:2 -31:1 -28:1 -26:1 -25:1 -20:1 -19:1 -18:1 -17:1 -16:2 -14:1 -13:1 -10:1 -9:1 -8:1 -7:1 -5:1 -4:1 -2:1 -1:1 0:1 1:1 2:1 4:1 5:1 7:1 8:1 9:1 10:1 13:1 14:1 16:2 17:1 18:1 19:1 20:1 25:1 26:1 28:1 31:1 32:2 34:1 35:1 36:1 37:1 38:1 40:1 45:1 49:1 50:1 52:1 53:1 56:1 62:1 63:1 64:2 65:1 68:1 69:1 70:1 71:3 72:1 73:1 74:1 76:1 80:2 81:1 83:1 85:1 87:1 90:1 91:1 93:4 95:1 98:1 100:1 103:1 104:1 106:1 112:2 113:1 117:1 119:1 124:1 125:1 126:1 128:2 129:1 130:1 133:1 136:1 137:1 138:1 140:1 141:1 142:3 144:2 146:1 148:1 152:1 153:1 155:1 157:1 160:2 162:1 163:1 166:1 169:1 170:1 171:1 174:1 175:1 177:1 179:1 180:1 182:1 185:1 186:4 190:1 191:3 193:1 196:1 197:1 199:1 200:1 201:1 206:1 208:2 212:1 213:2 217:1 221:1 223:1 224:2 225:1 226:1 227:1 233:1 234:1 237:1 238:1 239:1 243:1 245:1 247:1 248:1 250:1 252:1 256:3 258:1 259:1 260:1 265:1 266:1 267:1 269:1 272:2 274:1 276:1 279:1 280:1 281:3 282:1 284:3 288:2 289:1 291:1 292:1 293:1 296:1 304:2 306:1 310:1 313:1 314:1 315:1 317:1 320:2 321:1 323:1 324:1 325:1 326:1 327:1 332:1 333:1 337:1 338:1 340:1 342:1 343:1 345:1 347:1 348:1 349:1 350:1 354:1 355:3 358:1 359:1 360:1 361:1 364:1 365:1 370:1 371:1 372:4 373:1 380:1 381:1 382:3 386:1 392:1 394:1 398:1 400:2 402:1 403:1 405:1 412:1 415:1 416:2 417:1 419:1 424:1 425:1 426:2 434:1 435:1 439:1 441:1 442:1 443:1 446:1 447:1 448:2 450:1 452:1 454:1 455:1 457:1 461:1 463:1 465:4 466:1 468:1 474:1 475:1 476:1 477:1 478:1 481:1 483:1 486:1 487:1 490:1 491:3 494:1 496:2 497:3 499:1 500:1 ? bnfisintnorm(bnfinit(x^3+5),5) [-x] ? bnfisintnorm(bnfinit('y^2+93),54647) [] ? print("Total time spent: ",gettime); Total time spent: 512 pari-2.7.5/src/test/32/multivar-mul0000644000175000017500000000000011636712103015447 0ustar billbillpari-2.7.5/src/test/32/cyclo0000644000175000017500000000343512366172547014156 0ustar billbill *** Warning: new stack size = 8000000 (7.629 Mbytes). *** at top-level: poliscyclo(1) *** ^------------- *** poliscyclo: incorrect type in poliscyclo (t_INT). 0 0 100000 12345 [x - 1, x + 1] [x - 1, x^2 + x + 1] [x - 1, x^2 + 1] [x - 1, x^4 + x^3 + x^2 + x + 1] [x - 1, x^2 - x + 1] [x - 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x - 1, x^4 + 1] [x - 1, x^6 + x^3 + 1] [x - 1, x^4 - x^3 + x^2 - x + 1] [x + 1, x^2 + x + 1] [x + 1, x^2 + 1] [x + 1, x^4 + x^3 + x^2 + x + 1] [x + 1, x^2 - x + 1] [x + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x + 1, x^4 + 1] [x + 1, x^6 + x^3 + 1] [x + 1, x^4 - x^3 + x^2 - x + 1] [x^2 + 1, x^2 + x + 1] [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] [x^4 + x^2 + 1] [x^8 + 2*x^7 + 3*x^6 + 3*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] [x^4 + 1, x^2 + x + 1] [x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] [x^2 + 1, x^4 + x^3 + x^2 + x + 1] [x^2 + 1, x^2 - x + 1] [x^2 + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^2 + 1, x^4 + 1] [x^2 + 1, x^6 + x^3 + 1] [x^2 + 1, x^4 - x^3 + x^2 - x + 1] [x^4 + x^3 + x^2 + x + 1, x^2 - x + 1] [x^10 + 2*x^9 + 3*x^8 + 4*x^7 + 5*x^6 + 5*x^5 + 5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1] [x^4 + 1, x^4 + x^3 + x^2 + x + 1] [x^10 + x^9 + x^8 + 2*x^7 + 2*x^6 + x^5 + 2*x^4 + 2*x^3 + x^2 + x + 1] [x^8 + x^6 + x^4 + x^2 + 1] [x^6 + x^5 + x^4 + x^3 + x^2 + x + 1, x^2 - x + 1] [x^4 + 1, x^2 - x + 1] [x^6 + x^3 + 1, x^2 - x + 1] [x^6 - 2*x^5 + 3*x^4 - 3*x^3 + 3*x^2 - 2*x + 1] [x^4 + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^12 + x^11 + x^10 + 2*x^9 + 2*x^8 + 2*x^7 + 3*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + x^2 + x + 1] [x^6 + x^5 + x^4 + x^3 + x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] [x^4 + 1, x^6 + x^3 + 1] [x^4 + 1, x^4 - x^3 + x^2 - x + 1] [x^6 + x^3 + 1, x^4 - x^3 + x^2 - x + 1] 1 1 Total time spent: 532 pari-2.7.5/src/test/32/contfrac0000644000175000017500000000075612421727115014634 0ustar billbill *** at top-level: contfrac(1,[],-1) *** ^----------------- *** contfrac: domain error in contfrac: nmax < 0 *** at top-level: contfracpnqn(Vecsmal *** ^-------------------- *** contfracpnqn: incorrect type in pnqn (t_VECSMALL). [1 0] [0 1] [;] [;] [2 1] [1 0] [2] [1] [2] [1] [10 3] [ 7 2] [1] [1] [1 3] [1 2] [1 3 10] [1 2 7] [144 22] [ 33 5] [4] [1] [4 22] [1 5] [4 22 144] [1 5 33] Total time spent: 0 pari-2.7.5/src/test/32/real0000644000175000017500000000035412405547147013761 0ustar billbill *** at top-level: 1.<<2^60 *** ^---- *** overflow in t_INT-->long assignment. *** at top-level: 1.>>2^60 *** ^---- *** overflow in t_INT-->long assignment. Total time spent: 0 pari-2.7.5/src/test/32/galpol0000644000175000017500000000154512366172547014323 0ustar billbill5 [x^8 - x^7 - 7*x^6 + 6*x^5 + 15*x^4 - 10*x^3 - 10*x^2 + 4*x + 1, 1] [x^8 - 7*x^6 + 14*x^4 - 8*x^2 + 1, 1] [x^8 - 4*x^7 - 8*x^6 + 24*x^5 + 30*x^4 - 16*x^3 - 20*x^2 + 2, 3] [x^8 - 12*x^6 + 36*x^4 - 36*x^2 + 9, 3] [x^8 - 12*x^6 + 23*x^4 - 12*x^2 + 1, 7] [x^8 + 8*x^6 + 20*x^4 + 16*x^2 + 2, 1] [x^8 - x^7 + x^5 - x^4 + x^3 - x + 1, 1] [x^8 + 3*x^4 + 1, 1] [x^8 + 12*x^6 + 36*x^4 + 36*x^2 + 9, 3] [x^8 - x^4 + 1, 1] *** at top-level: galoisgetpol(8,6) *** ^----------------- *** galoisgetpol: domain error in galoisgetpol: group index > 5 *** at top-level: galoisgetpol(3,1,3) *** ^------------------- *** galoisgetpol: invalid flag in galoisgetpol. *** at top-level: galoisgetpol(3,1,2) *** ^------------------- *** galoisgetpol: domain error in galoisgetpol: s > 1 [96, 161] Total time spent: 3624 pari-2.7.5/src/test/32/ellanal0000644000175000017500000000102112515251402014422 0ustar billbill[0, 0.25384186085591068433775892335090946105] [1, 0.30599977383405230182048368332167647444] [2, 1.5186330005768535404603852157894440392] [3, 10.391099400715804138751850510360917049] [5, 9997.0334671722554999496820788093288504] [-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 pari-2.7.5/src/test/32/modfun0000644000175000017500000000071612415474356014332 0ustar billbill1 + 2 + 2^3 + 2^4 + 2^7 + 2^12 + 2^13 + 2^14 + 2^16 + 2^17 + 2^18 + 2^19 + O (2^20) 1 - x - 2*x^2 - 3*x^3 - 4*x^4 + O(x^5) 0.99812906992595851327996232224527387813 2^-1 + 2^5 + 2^7 + 2^8 + 2^10 + 2^12 + 2^16 + O(2^18) x^-1 + 743 + 196884*x + 21690644*x^2 + O(x^3) 0.E-38 - 0.50432357748832834893222560519660217759*I 1.0905077326652576592070106557607079790 1.0811782878393746833655992417658285836 - 0.14233982193131805512395869109512 286588*I Total time spent: 4 pari-2.7.5/src/test/32/log0000644000175000017500000000023612366172547013622 0ustar billbill9.9999999999999999999999999999950000000 E-31 -5.7721566490153286060651209008157996401 E-31 error("not a prime number in p-adic log: 33.") Total time spent: 0 pari-2.7.5/src/test/32/content0000644000175000017500000000060412366172547014512 0ustar billbill1 1 1 3 1 6 1 1 1 1 x error("incorrect type in denom (t_QFI).") error("incorrect type in denom (t_QFR).") 4 2 2 1.0000000000000000000000000000000000000 Mod(1, 3) 2 x 3 + 2*I O(2^-3) w Mod(1/2*x, x^2) 2*x 2 error("incorrect type in numer (t_QFI).") error("incorrect type in numer (t_QFR).") [8, 3] [2, 4; 3, 8] 2 1 Mod(1, 3) 2/3 x 1/2 + 1/3*I 1/8 w 1/2 2 2 1 1 1/4 1/2 Total time spent: 0 pari-2.7.5/src/test/32/for0000644000175000017500000000051312366172547013625 0ustar billbill18446744073709551614 18446744073709551615 18446744073709551616 18446744073709551617 18446744073709551618 -18446744073709551618 -18446744073709551617 -18446744073709551616 -18446744073709551615 -18446744073709551614 4294967279 4294967291 4294967311 18446744073709551557 18446744073709551629 18446744073709551653 Total time spent: 0 pari-2.7.5/src/test/32/iterator0000644000175000017500000000033012314242551014647 0ustar billbill4 6 8 9 10 6 8 9 10 6 8 9 10 12 6 8 9 6 *** at top-level: forcomposite(a=6,12,print(a);a=1) *** ^------------- *** index read-only: was changed to 1. Total time spent: 0 pari-2.7.5/src/test/32/help0000644000175000017500000001372012405547147013767 0ustar billbillx: user defined variable sin(x): sine of x. f = ()->1 echo: default echo: default log: default new is aliased to: sin(x): sine of x. test1 test2 test3 test4 new is aliased to: test2 does_not_exist: unknown identifier Help topics: for a list of relevant subtopics, type ?n for n in 0: user-defined functions (aliases, installed and user functions) 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 12: The PARI community Also: ? functionname (short on-line help) ?\ (keyboard shortcuts) ?. (member functions) Extended help (if available): ?? (opens the full user's manual in a dvi previewer) ?? tutorial / refcard / libpari (tutorial/reference card/libpari manual) ?? keyword (long help text about "keyword" from the user's manual) ??? keyword (a propos: list of related functions). Member functions, followed by relevant objects a1-a6, b2-b8, c4-c6 : coeff. of the curve. ell area : area ell bid : big ideal bid, bnr bnf : big number field bnf,bnr clgp : class group bid, bnf,bnr cyc : cyclic decomposition (SNF) bid, clgp,ell, bnf,bnr diff, codiff: different and codifferent nf,bnf,bnr disc : discriminant ell,nf,bnf,bnr,rnf e, f : inertia/residue degree prid fu : fundamental units bnf,bnr gen : generators bid,prid,clgp,ell, bnf,bnr, gal group: group ell, ,rnf,gal index: index nf,bnf,bnr j : j-invariant ell mod : modulus bid, bnr, gal nf : number field nf,bnf,bnr,rnf no : number of elements bid, clgp,ell, bnf,bnr omega, eta: [w1,w2] and [eta1, eta2] ell orders: relative orders of generators gal p : rational prime prid, ell, rnf,gal pol : defining polynomial nf,bnf,bnr, gal polabs: defining polynomial over Q rnf reg : regulator bnf,bnr roots: roots ell,nf,bnf,bnr, gal sign,r1,r2 : signature nf,bnf,bnr t2 : t2 matrix nf,bnf,bnr tate : Tate's [u^2, u, q, [a,b]] ell tu : torsion unit and its order bnf,bnr zk : integral basis nf,bnf,bnr,rnf zkst : structure of (Z_K/m)* bid, bnr # : enable/disable timer ## : print time for last result \\ : comment up to end of line \a {n} : print result in raw format (readable by PARI) \B {n} : print result in beautified format \c : list all commands (same effect as ?*) \d : print all defaults \e {n} : enable/disable echo (set echo=n) \g {n} : set debugging level \gf{n} : set file debugging level \gm{n} : set memory debugging level \h {m-n}: hashtable information \l {f} : enable/disable logfile (set logfile=f) \m {n} : print result in prettymatrix format \o {n} : set output method (0=raw, 1=prettymatrix, 2=prettyprint, 3=2-dim) \p {n} : change real precision \ps{n} : change series precision \q : quit completely this GP session \r {f} : read in a file \s : print stack information \t : print the list of PARI types \u : print the list of user-defined functions \um : print the list of user-defined member functions \v : print current version of GP \w {nf} : write to a file \x {n} : print complete inner structure of result \y {n} : disable/enable automatic simplification (set simplify=n) {f}=optional filename. {n}=optional integer cmp divrem lex max min shift shiftmul sign vecmax vecmin List of the PARI types: t_INT : long integers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_REAL : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_INTMOD : integermods [ code ] [ mod ] [ integer ] t_FRAC : irred. rationals [ code ] [ num. ] [ den. ] t_FFELT : finite field elt. [ code ] [ cod2 ] [ elt ] [ mod ] [ p ] t_COMPLEX: complex numbers [ code ] [ real ] [ imag ] t_PADIC : p-adic numbers [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ] t_QUAD : quadratic numbers [ cod1 ] [ mod ] [ real ] [ imag ] t_POLMOD : poly mod [ code ] [ mod ] [ polynomial ] ------------------------------------------------------------- t_POL : polynomials [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_SER : power series [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_RFRAC : irred. rat. func. [ code ] [ num. ] [ den. ] t_QFR : real qfb [ code ] [ a ] [ b ] [ c ] [ del ] t_QFI : imaginary qfb [ code ] [ a ] [ b ] [ c ] t_VEC : row vector [ code ] [ x_1 ] ... [ x_k ] t_COL : column vector [ code ] [ x_1 ] ... [ x_k ] t_MAT : matrix [ code ] [ col_1 ] ... [ col_k ] t_LIST : list [ code ] [ n ] [ nmax ][ vec ] t_STR : string [ code ] [ man_1 ] ... [ man_k ] t_VECSMALL: vec. small ints [ code ] [ x_1 ] ... [ x_k ] t_CLOSURE: functions [ code ] [ arity ] [ code ] [ operand ] [ data ] [ te xt ] t_ERROR : error context [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ] Total time spent: 0 pari-2.7.5/src/test/32/bern0000644000175000017500000000233512366172547013771 0ustar billbill-1/2 1/6 0 -1/30 0 1/42 0 -1/30 0 5/66 0 -691/2730 0 7/6 0 -3617/510 0 43867/798 0 -174611/330 1 x - 1/2 x^2 - x + 1/6 x^3 - 3/2*x^2 + 1/2*x x^4 - 2*x^3 + x^2 - 1/30 x^5 - 5/2*x^4 + 5/3*x^3 - 1/6*x *** at top-level: bernfrac(-1) *** ^------------ *** bernfrac: domain error in bernfrac: index < 0 *** at top-level: bernreal(-1) *** ^------------ *** bernreal: domain error in bernreal: index < 0 *** at top-level: bernpol(-1) *** ^----------- *** bernpol: domain error in bernpol: index < 0 [1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730, 7/6, -3617/510, 43867/798, -17 4611/330, 854513/138, -236364091/2730, 8553103/6, -23749461029/870, 86158412 76005/14322, -7709321041217/510, 2577687858367/6, -26315271553053477373/1919 190, 2929993913841559/6, -261082718496449122051/13530, 152009764391807080269 1/1806, -27833269579301024235023/690, 596451111593912163277961/282, -5609403 368997817686249127547/46410, 495057205241079648212477525/66, -80116571813548 9957347924991853/1590, 29149963634884862421418123812691/798, -24793929293132 26753685415739663229/870, 84483613348880041862046775994036021/354, -12152331 40483755572040304994079820246041491/56786730] Total time spent: 0 pari-2.7.5/src/test/32/factor0000644000175000017500000000517612413013143014302 0ustar billbill [x^2 + I 1] [x + 1.0000000000000000000000000000000000000 1] [x - 1.0000000000000000000000000000000000000 1] [x + (0.45508986056222734130435775782246856962 - 1.0986841134678099660398011 952406783785*I) 1] [x + (-0.45508986056222734130435775782246856962 + 1.098684113467809966039801 1952406783785*I) 1] [Mod(1, 5)*x + Mod(2, 5) 1] [Mod(1, 5)*x + Mod(3, 5) 1] [Mod(1, 3)*x^2 + (Mod(1, 3) + Mod(1, 3)*I) 1] *** at top-level: factor(x^2+Mod(1,5)* *** ^-------------------- *** factor: sorry, factor for general polynomials is not yet implemented. [(1 + O(5))*x^2 + O(5)*x + (2 + O(5)) 1] *** at top-level: factor(x^2+(1+O(3))+ *** ^-------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [(1 + O(5))*x + (2 + O(5)) 1] [(1 + O(5))*x + (3 + O(5)) 1] [ x + (1 - w) 1] [x + (-1 + w) 1] *** at top-level: factor(x^2+quadgen(- *** ^-------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [Mod(1, 5)*x + (Mod(4, 5) + Mod(1, 5)*w) 1] [Mod(1, 5)*x + (Mod(1, 5) + Mod(4, 5)*w) 1] *** at top-level: factor(x^2+quadgen(- *** ^-------------------- *** factor: sorry, factor for general polynomial is not yet implemented. *** at top-level: factor(x^2+quadgen(-3)*(1+O(3))) *** ^---------- *** _*_: not an n-th power residue in Qp_sqrt: -3. [x^2 + Mod(y, y^2 + 1) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(1, 3)*y + Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(2, 3)*y + Mod(2, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] *** at top-level: factor(x^2+Mod(y*Mod *** ^-------------------- *** factor: sorry, factor for general polynomial is not yet implemented. *** at top-level: factor(x^2+Mod(y*(1+ *** ^-------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [ I 1] [ 3 -1] [ 1 + I -2] [15 + 2*I 1] [ 1 + I 1] [ 2 + I 4] [1 + 2*I 4] [ -I 1] [ 1 + I 1] [2 + 3*I 1] [ -I 1] [ 3 1] [ 1 + I 1] [2 + 3*I 1] [ -1 1] [1 + I 5] [ -1 1] [1 + 2*I -2] [31271192761826143388782348951 1] [31274945109847936339856761591 -1] [ 500009 1] [ 500029 -1] [ 500041 1] [ 500057 -1] [ 500069 1] [ 500083 -1] [250110012091 1] [250115013209 -1] [ x - 2.0000000000000000000000000000000000000 1] [x^2 + 0.E-38*x + 1.0000000000000000000000000000000000000 1] [x + 1 2] [x - 2 -1] [x + 2 -1] Total time spent: 8 pari-2.7.5/src/test/32/nfhilbert0000644000175000017500000000750712413013143015001 0ustar billbill[-1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1] [-1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1] -1 *** at top-level: nfhilbert(nf,Mod(0,3 *** ^-------------------- *** nfhilbert: domain error in nfhilbert: a = 0 *** at top-level: nfhilbert(nf,3,0.,pr *** ^-------------------- *** nfhilbert: domain error in nfhilbert: b = 0 1 1 -1 [1, 2]: 1 [1, 3]: 1 [1, 4]: error("precision too low in hilbert.") [1, 5]: error("precision too low in hilbert.") [1, 6]: 1 [1, 7]: 1 [1, 8]: 0 [1, 9]: error("precision too low in hilbert.") [1, 10]: 1 [1, 11]: 1 [2, 3]: 1 [2, 4]: error("precision too low in hilbert.") [2, 5]: error("precision too low in hilbert.") [2, 6]: 1 [2, 7]: 1 [2, 8]: 0 [2, 9]: error("precision too low in hilbert.") [2, 10]: 1 [2, 11]: 1 [3, 4]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 5]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 6]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 7]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 8]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 9]: error("forbidden hilbert t_REAL , t_PADIC.") [3, 10]: error("forbidden hilbert t_REAL , t_PADIC.") [3, 11]: error("forbidden hilbert t_REAL , t_PADIC.") [4, 5]: error("precision too low in hilbert.") [4, 6]: error("precision too low in hilbert.") [4, 7]: error("precision too low in hilbert.") [4, 8]: error("precision too low in hilbert.") [4, 9]: error("precision too low in hilbert.") [4, 10]: error("precision too low in hilbert.") [4, 11]: error("precision too low in hilbert.") [5, 6]: error("precision too low in hilbert.") [5, 7]: error("precision too low in hilbert.") [5, 8]: error("precision too low in hilbert.") [5, 9]: error("precision too low in hilbert.") [5, 10]: error("precision too low in hilbert.") [5, 11]: error("precision too low in hilbert.") [6, 7]: error("inconsistent moduli in hilbert: 3 != 8") [6, 8]: error("inconsistent moduli in hilbert: 5 != 8") [6, 9]: error("inconsistent moduli in hilbert: 8 != 2") [6, 10]: error("inconsistent moduli in hilbert: 8 != 2") [6, 11]: error("inconsistent moduli in hilbert: 8 != 5") [7, 8]: error("inconsistent moduli in hilbert: 5 != 3") [7, 9]: error("inconsistent moduli in hilbert: 3 != 2") [7, 10]: error("inconsistent moduli in hilbert: 3 != 2") [7, 11]: error("inconsistent moduli in hilbert: 3 != 5") [8, 9]: error("inconsistent moduli in hilbert: 5 != 2") [8, 10]: error("inconsistent moduli in hilbert: 5 != 2") [8, 11]: 0 [9, 10]: error("precision too low in hilbert.") [9, 11]: error("precision too low in hilbert.") [10, 11]: error("inconsistent moduli in hilbert: 2 != 5") p = 0: 1: 1 2: 1 3: 1 4: error("inconsistent moduli in hilbert: 2 != oo") 5: error("inconsistent moduli in hilbert: 4 != oo") 6: error("inconsistent moduli in hilbert: 8 != oo") 7: error("inconsistent moduli in hilbert: 3 != oo") 8: error("inconsistent moduli in hilbert: 5 != oo") 9: error("inconsistent moduli in hilbert: 0 != 2") 10: error("inconsistent moduli in hilbert: 0 != 2") 11: error("inconsistent moduli in hilbert: 0 != 5") p = 2: 1: 1 2: -1 3: error("inconsistent moduli in hilbert: 2 != oo") 4: error("precision too low in hilbert.") 5: error("precision too low in hilbert.") 6: 1 7: error("precision too low in hilbert.") 8: error("precision too low in hilbert.") 9: error("precision too low in hilbert.") 10: 1 11: error("inconsistent moduli in hilbert: 2 != 5") p = 5: 1: 1 2: 1 3: error("inconsistent moduli in hilbert: 5 != oo") 4: error("inconsistent moduli in hilbert: 2 != 5") 5: error("inconsistent moduli in hilbert: 4 != 5") 6: error("inconsistent moduli in hilbert: 8 != 5") 7: error("inconsistent moduli in hilbert: 3 != 5") 8: error("precision too low in hilbert.") 9: error("inconsistent moduli in hilbert: 5 != 2") 10: error("inconsistent moduli in hilbert: 5 != 2") 11: 1 -1 -1 1 Total time spent: 1084 pari-2.7.5/src/test/32/round40000644000175000017500000003400712573107135014246 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 1 disc = 691051969765063543658256000000000000 2 disc = 31088519960728128454656000000000000 3 disc = 1802370734536 4 disc = 654752768 5 disc = -58773124044 6 disc = 11378694989371408384 7 disc = -48269476692516748870958029675063944413184 8 disc = 1461501637330902918203684832716283019655932542976 9 disc = 1346286087882789617664 10 disc = 193428131138340667952988160000000000000000 11 disc = 11378694989371408384 12 disc = 144 13 disc = 442050625 14 disc = 12008989 15 disc = 16974593 16 disc = 31554496 17 disc = 33076161 18 disc = 11574317056 19 disc = 10368641602001 20 disc = 39213900625 21 disc = 103161709 22 disc = 105823817 23 disc = 65037750625 24 disc = 73116160000 25 disc = 183250432 26 disc = 21292697885552828353 27 disc = 213813760000 28 disc = 225360027841 29 disc = 114655968874330129 30 disc = 393832837 31 disc = 440711081 32 disc = 364488705441 33 disc = 370150560000 34 disc = 234001122366390625 35 disc = 395451064801 36 disc = 364007458703857 37 disc = 497871360000 38 disc = 588865925376 39 disc = 709732288 40 disc = 647395642881 41 disc = 659020863601 42 disc = 446012924483368791310336 43 disc = 670801950625 44 disc = 728933458176 45 disc = 689869781056000000 46 disc = 913308254830140625 47 disc = 979146657 48 disc = 1064726745878753869969 49 disc = 1048772096 50 disc = 1082432160000 51 disc = 1192518600625 52 disc = 1559914552888693 53 disc = 1442919878656 54 disc = 1334633301 55 disc = 1490902050625 56 disc = 2980200459393400813138329769 57 disc = 1718786550625 58 disc = 1810639360000 59 disc = 1835743170816 60 disc = 2222606887281 61 disc = 1856331989 62 disc = 1986121593 63 disc = 2752095195136 64 disc = 2786442301696 65 disc = 2217342464 66 disc = 2972069112961 67 disc = 3035957760000 68 disc = 5920163568466890625 69 disc = 3471607400625 70 disc = 2588282117 71 disc = 7027753833487138816 72 disc = 5245121853990193 73 disc = 5958832035878149 74 disc = 2961169856 75 disc = 4797852160000 76 disc = 3301293169 77 disc = 3436115229 78 disc = 5922408960000 79 disc = 42098158229810084367630336 80 disc = 26961206542479413771201 81 disc = 7233948160000 82 disc = 11899888859544201 83 disc = 7909194404241 84 disc = 24827168863016095744 85 disc = 9082363580416 86 disc = 9272177250625 87 disc = 9421854806016 88 disc = 16696389126347776 89 disc = 52518884338097360421921 90 disc = 30232096024977015625 91 disc = 5564051648 92 disc = 10971993760000 93 disc = 12625407900625 94 disc = 24566124836069257 95 disc = 6869835701 96 disc = 7177888089 97 disc = 13932481925376 98 disc = 52817485810944986209 99 disc = 7495014493 100 disc = 31681277442558976 101 disc = 71415925156555415437890625 102 disc = 9166361760000 103 disc = 103063708057575099687890625 104 disc = 17471883970840462300304775614373553 105 disc = 95468057368868913808408576 106 disc = 17515230173 107 disc = 62523502209 108 disc = 62523502209 109 disc = 74724856128 110 disc = 80174499328 111 disc = 183637853504 112 disc = 326371204125 113 disc = 376367048000 114 disc = 567869252041 115 disc = 567869252041 116 disc = 688231506789 117 disc = 899470488077 118 disc = 941192000000 119 disc = 998800479936 120 disc = 1095593933629 121 disc = 1488181848713 122 disc = 2565164201769 123 disc = 2565164201769 124 disc = 2694903759296 125 disc = 2704209893568 126 disc = 3151307486781 127 disc = 3338010958625 128 disc = 3471072448221 129 disc = 4007556327104 130 disc = 4624076296000 131 disc = 4831094417625 132 disc = 5534900853769 133 disc = 5534900853769 134 disc = 6056434988352 135 disc = 6080389219008 136 disc = 6636193049088 137 disc = 7100029448000 138 disc = 7534146860864 139 disc = 7720128615744 140 disc = 8606302763157 141 disc = 9288810792261 142 disc = 9750967476544 143 disc = 10229618526912 144 disc = 10367362235125 145 disc = 15883285246353 146 disc = 18243373078125 147 disc = 18525482136000 148 disc = 18753251922432 149 disc = 20339710127073 150 disc = 21673299838841 151 disc = 21682629379125 152 disc = 22454408824128 153 disc = 22454408824128 154 disc = 22454408824128 155 disc = 22886952012288 156 disc = 24907321081664 157 disc = 24991851015053 158 disc = 25002110044521 159 disc = 25002110044521 160 disc = 25032903977277 161 disc = 27100023260653 162 disc = 29698839199232 163 disc = 31033149890625 164 disc = 31033149890625 165 disc = 31033149890625 166 disc = 32012033131008 167 disc = 32795655776729 168 disc = 32795655776729 169 disc = 32795655776729 170 disc = 32795655776729 171 disc = 33252674173893 172 disc = 33823616904000 173 disc = 35861911358833 174 disc = 37156053182409 175 disc = 37166075494848 176 disc = 40509102979584 177 disc = 45990453983552 178 disc = 50722851083913 179 disc = 51035911843357 180 disc = 51895117000000 181 disc = 51895117000000 182 disc = 52464835537856 183 disc = 57566111236928 184 disc = 57566111236928 185 disc = 64867893832000 186 disc = 68443024217625 187 disc = 70608870146368 188 disc = 70608870146368 189 disc = 70608870146368 190 disc = 73792042960384 191 disc = 78496212952513 192 disc = 78496212952513 193 disc = 78496212952513 194 disc = 78496212952513 195 disc = 80018416634688 196 disc = 81272764978496 197 disc = 83780436119093 198 disc = 88812049936896 199 disc = 91343875006656 200 disc = 93113668703125 201 disc = 95343780573504 202 disc = 95343780573504 203 disc = 95550545616813 204 disc = 100856310518592 205 disc = 100856310518592 206 disc = 101481612657984 207 disc = 102588675089797 208 disc = 102792615579584 209 disc = 104413920565969 210 disc = 104413920565969 211 disc = 106712258605568 212 disc = 109627139656000 213 disc = 109627139656000 214 disc = 109627139656000 215 disc = 117102420633024 216 disc = 121935391665472 217 disc = 124460777226752 218 disc = 130323843000000 219 disc = 131197182717797 220 disc = 131623667572032 221 disc = 142114065431625 222 disc = 143318415538368 223 disc = 148203857088000 224 disc = 154888759857664 225 disc = 155625375008069 226 disc = 160032253665088 227 disc = 160315392124224 228 disc = 160315392124224 229 disc = 160315392124224 230 disc = 163963718650837 231 disc = 164206490176000 232 disc = 168855627483648 233 disc = 172808693000000 234 disc = 172808693000000 235 disc = 182284263000000 236 disc = 190983561521472 237 disc = 190983561521472 238 disc = 190983561521472 239 disc = 205849293516125 240 disc = 207390588005888 241 disc = 219747465563625 242 disc = 227081481823729 243 disc = 227081481823729 244 disc = 238374130976064 245 disc = 238374130976064 246 disc = 238374130976064 247 disc = 239853467163968 248 disc = 240421391475741 249 disc = 244152343937501 250 disc = 244152343937501 251 disc = 244152343937501 252 disc = 245832015985984 253 disc = 245832015985984 254 disc = 245832015985984 255 disc = 250380544197952 256 disc = 250380544197952 257 disc = 250380544197952 258 disc = 264856663448000 259 disc = 266306899520753 260 disc = 266953144495869 261 disc = 268036698442176 262 disc = 280342627195392 263 disc = 284124652664021 264 disc = 286295419093312 265 disc = 286295419093312 266 disc = 286295419093312 267 disc = 292979858533713 268 disc = 293019561288000 269 disc = 301855146292441 270 disc = 301855146292441 271 disc = 312604448196032 272 disc = 325603874022336 273 disc = 343308792619261 274 disc = 343956387524625 275 disc = 358470842647653 276 disc = 363887297335457 277 disc = 370533009640625 278 disc = 378388023667289 279 disc = 378388023667289 280 disc = 378388023667289 281 disc = 378435108978368 282 disc = 382167204596009 283 disc = 385272136297125 284 disc = 391853565596233 285 disc = 407478805289353 286 disc = 412162994888000 287 disc = 419718684302848 288 disc = 420610640203125 289 disc = 427178948689297 290 disc = 430522800097229 291 disc = 437262761657701 292 disc = 458528043068928 293 disc = 461406087545417 294 disc = 471655843734321 295 disc = 471655843734321 296 disc = 471710378827584 297 disc = 471710378827584 298 disc = 471710378827584 299 disc = 474114086770176 300 disc = 479184750300277 301 disc = 492814358126272 302 disc = 507558505272832 303 disc = 512537788181952 304 disc = 526672365558093 305 disc = 531381953186973 306 disc = 534063139779637 307 disc = 545919434583489 308 disc = 561188988355904 309 disc = 561188988355904 310 disc = 561188988355904 311 disc = 561842388364096 312 disc = 586376253000000 313 disc = 586376253000000 314 disc = 611354775822848 315 disc = 619777755576000 316 disc = 626277261303693 317 disc = 632689381320192 318 disc = 642489904555569 319 disc = 646877982134125 320 disc = 646877982134125 321 disc = 646877982134125 322 disc = 650182119827968 323 disc = 654605112335552 324 disc = 654605112335552 325 disc = 654605112335552 326 disc = 676928662294464 327 disc = 678155219611793 328 disc = 683425351376704 329 disc = 687273151702249 330 disc = 704612615071625 331 disc = 706705122232017 332 disc = 706705122232017 333 disc = 706705122232017 334 disc = 722893530076992 335 disc = 726766684501312 336 disc = 740652641361333 337 disc = 743283484296704 338 disc = 743702041351801 339 disc = 743702041351801 340 disc = 761874028623037 341 disc = 761949106541056 342 disc = 765458231098176 343 disc = 773039298114433 344 disc = 778002617184317 345 disc = 810000647049313 346 disc = 814597322969457 347 disc = 840297038077125 348 disc = 847557413131456 349 disc = 847557413131456 350 disc = 847557413131456 351 disc = 847557413131456 352 disc = 860329562380029 353 disc = 873174569112000 354 disc = 884514834431488 355 disc = 884514834431488 356 disc = 888834215593792 357 disc = 898101431252641 358 disc = 901568676645125 359 disc = 920173609084625 360 disc = 927543993493824 361 disc = 936704478987584 362 disc = 936704478987584 363 disc = 936704478987584 364 disc = 945000308955968 365 disc = 945000308955968 366 disc = 945000308955968 367 disc = 946850453833536 368 disc = 948500270840277 369 disc = 965396977375537 370 disc = 995805877256000 371 disc = 995805877256000 372 disc = 995805877256000 373 disc = 4239150758955121 374 disc = 71583777861999601 375 disc = 154348440599505681 376 disc = 206144025464586496 377 disc = 498311414318121121 378 disc = 988566915013816576 379 disc = 1594861774888100161 380 disc = 1920991678454430481 381 disc = 3203072711854650625 382 disc = 3282543960141600625 383 disc = 3563847743378991201 384 disc = 11629529577315932881 385 disc = 14937144551057330176 386 disc = 15104107144156878961 387 disc = 18107955017924915521 388 disc = 32757037519097735281 389 disc = 34660765693554192481 390 disc = 39891322034514837441 391 disc = 47965803087841295281 392 disc = 54568636296342159616 393 disc = 73911569995951513281 394 disc = 3830987530897003258893 395 disc = 17723470954150385603125 396 disc = 33413112917251096211093 397 disc = 34637703462495298817024 398 disc = 88388569691530342400000 399 disc = 219491114456594107591949 400 disc = 480467194090863436127232 401 disc = 1037662435085339279821824 402 disc = 1173200147537629968564224 403 disc = 1288413852163540951269376 404 disc = 1309219498202517731691949 405 disc = 2589525908257257679485601 406 disc = 3190278955076438566369093 407 disc = 3227335013943818471790557 408 disc = 3713732460841424506170368 409 disc = 4862809470873883357637632 410 disc = 6002643624777941817982976 411 disc = 7126069515444754920275968 412 disc = 12952518753342414842160584761 413 disc = 19889530276837831068388593664 414 disc = 33146763213552556976071497289 415 disc = 134058271322059099333696000000 416 disc = 143177496454836860404568609521 417 disc = 782366492329362629572165894144 418 disc = 885679687572037927988717116729 419 disc = 1932285652221352905364571537408 420 disc = 792696226576452305767009651523584 421 disc = 1120727194291010174129782797578125 422 disc = 1677627312816188946952964414636032 423 disc = 40650250977089753091644821936498677 424 disc = 82968596939468322350524272929144832 425 disc = 86620507852136986313803229728551889 426 disc = -48269476692516748870958029675063944413184 427 disc = 3057647616 428 disc = -61837572703801526878847827968 429 disc = 10953815427820782987807562683135882947045385765546796605368678856 6125676724691632661454253689888403350678050281881600000000000000000000000000 0000000000000000000000 430 disc = -4047658052954461065912911660658154357072747299150021320490491581 6357719261043885533725876268976267090078699982339498617717978285115098117423 5226786109719181996179722769519700738142090773570860994444369576764647340001 6271055386451054047833315739281064060031306134989387012001240366983880112401 0950391140893121715388041767973840048335480267318286333231520541406374861862 1393537964424677884127250669128055090586243928496505152582326687370689187624 8193649132417798542886781065276330907871042811558631554710375998113711429289 8496513938923014831159547568236743150682002399344666964624978609632942422782 6498518955202829946466452792918443649912549887356822674330431196145149803023 4895588458953982456193472068052465591438058958231038395076434692769303458913 1290964204147229157301290925386293126167130333738976824399921085466861118333 7378074137212916065543375824994038692415387212889537750773611240570763116746 580968621149210575140668368291928317296640 3940200619639447921227904010014361380507973927046544666794829340424572177149 7210611414266254884915640806627990306816 63456228123711897600000000 32065375478269160177874763776 44676618219970392643498326834331791020485046219833344 3353338721974729817301054329173240175627277795006862757734308781291047845002 3018568598687979818620835459868306327959658030836737051459691258806591089437 47971479203517856656769812503986176 2 2 [1, 1/4747561509943*x + 1/4747561509943], -2100 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, x], -47332614610453741984512822900 [1, 1/23737807549715*x + 1/23737807549715], -84 1600000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000854400000000000000002528000000000000000000000000000000 0000000000000000000000000000000000000000000114062400000000000001349952000000 0000000009985600000000000000000000000000000000000000000000000000000000000000 0000000001802185920000000000005332310400000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000007118634384 551496736222216254722000000000000000000 827291662110720806941937696976 827291662110720806941937696976 Total time spent: 2611 pari-2.7.5/src/test/32/select0000644000175000017500000000065112573110460014303 0ustar billbill[2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] Vecsmall([2, 3, 5]) List([2, 3, 5]) List([2, 3, 5]) [1 2] [2 0] [0] [0] [] [1, 3] *** at top-level: select(x->x,v,1) *** ^---------------- *** select: incorrect type in select (t_VECSMALL). *** at top-level: select(x->x,v) *** ^-------------- *** select: incorrect type in select (t_VECSMALL). Total time spent: 0 pari-2.7.5/src/test/32/stark0000644000175000017500000001551612366172547014174 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 321: x^3 - x^2 - 4*x + 1 520: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 577: x^7 - x^6 - 10*x^5 + 13*x^4 + 10*x^3 - 7*x^2 - 2*x + 1 840: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 904: x^8 - 3*x^7 - 17*x^6 + 44*x^5 + 112*x^4 - 206*x^3 - 357*x^2 + 315*x + 4 63 1009: x^7 - x^6 - 9*x^5 + 2*x^4 + 21*x^3 + x^2 - 13*x - 1 1129: x^9 - x^8 - 16*x^7 - 6*x^6 + 64*x^5 + 65*x^4 - 48*x^3 - 78*x^2 - 19*x + 1 1229: x^3 - 14*x - 19 1297: x^11 - x^10 - 28*x^9 - 50*x^8 + 63*x^7 + 216*x^6 + 77*x^5 - 173*x^4 - 122*x^3 + 18*x^2 + 17*x - 1 1509: x^3 - x^2 - 7*x + 4 1901: x^3 - x^2 - 9*x - 4 1937: x^6 - 10*x^4 + 25*x^2 - 13 2305: x^16 - 4*x^15 - 27*x^14 + 99*x^13 + 237*x^12 - 752*x^11 - 769*x^10 + 2 006*x^9 + 1063*x^8 - 2006*x^7 - 769*x^6 + 752*x^5 + 237*x^4 - 99*x^3 - 27*x^ 2 + 4*x + 1 2584: x^8 - 3*x^7 - 15*x^6 + 54*x^5 + 16*x^4 - 220*x^3 + 271*x^2 - 119*x + 1 7 2920: x^12 - 4*x^11 - 44*x^10 + 264*x^9 - 66*x^8 - 1880*x^7 + 2558*x^6 + 304 0*x^5 - 6688*x^4 + 2192*x^3 + 446*x^2 - 80*x + 1 3281: x^6 - x^5 - 17*x^4 - 11*x^3 + 17*x^2 - x - 1 32569: x^3 - x^2 - 20*x + 13 [y^2 - 145, 1]: x^4 + Mod(y - 14, y^2 - 145)*x^3 + Mod(-8*y + 95, y^2 - 145) *x^2 + Mod(21*y - 250, y^2 - 145)*x + Mod(-18*y + 217, y^2 - 145) [y^2 - 229, 1]: x^3 + Mod(-y - 14, y^2 - 229)*x^2 + Mod(6*y + 87, y^2 - 229) *x + Mod(-10*y - 156, y^2 - 229) [y^2 - 401, 1]: x^5 + Mod(-11/2*y - 219/2, y^2 - 401)*x^4 + Mod(155/2*y + 30 91/2, y^2 - 401)*x^3 + Mod(-403*y - 8075, y^2 - 401)*x^2 + Mod(1789/2*y + 35 845/2, y^2 - 401)*x + Mod(-1421/2*y - 28437/2, y^2 - 401) [y^2 - 577, 1]: x^7 + Mod(11/2*y - 271/2, y^2 - 577)*x^6 + Mod(-553/2*y + 13 285/2, y^2 - 577)*x^5 + Mod(5730*y - 137633, y^2 - 577)*x^4 + Mod(-118647/2* y + 2849989/2, y^2 - 577)*x^3 + Mod(319416*y - 7672635, y^2 - 577)*x^2 + Mod (-1674997/2*y + 40234809/2, y^2 - 577)*x + Mod(810062*y - 19458357, y^2 - 57 7) [y^2 - 761, 1]: x^3 + Mod(731/2*y - 20167/2, y^2 - 761)*x^2 + Mod(-244695*y + 6750211, y^2 - 761)*x + Mod(21008185/2*y - 579536589/2, y^2 - 761) [y^3 - y^2 - 17*y - 16, 1]: x^4 + Mod(-2*y^2 - 10*y - 11, y^3 - y^2 - 17*y - 16)*x^3 + Mod(21*y^2 + 86*y + 68, y^3 - y^2 - 17*y - 16)*x^2 + Mod(-66*y^2 - 262*y - 204, y^3 - y^2 - 17*y - 16)*x + Mod(65*y^2 + 262*y + 209, y^3 - y^ 2 - 17*y - 16) [y^3 - 14*y - 7, 1]: x^3 + Mod(-5*y^2 - 21*y - 10, y^3 - 14*y - 7)*x^2 + Mod (25*y^2 + 98*y + 42, y^3 - 14*y - 7)*x + Mod(-30*y^2 - 119*y - 52, y^3 - 14* y - 7) [y^3 - y^2 - 16*y + 22, 1]: x^3 + Mod(-10*y^2 - 27*y + 60, y^3 - y^2 - 16*y + 22)*x^2 + Mod(171*y^2 + 464*y - 1016, y^3 - y^2 - 16*y + 22)*x + Mod(-715* y^2 - 1940*y + 4234, y^3 - y^2 - 16*y + 22) [y^3 - 36*y - 45, 1]: x^3 + Mod(-12*y^2 - 78*y - 79, y^3 - 36*y - 45)*x^2 + Mod(1589/3*y^2 + 3469*y + 3642, y^3 - 36*y - 45)*x + Mod(-3038/3*y^2 - 6631* y - 6962, y^3 - 36*y - 45) [y^3 - 21*y - 35, 1]: x^3 + Mod(-4*y^2 + 12*y + 48, y^3 - 21*y - 35)*x^2 + M od(20*y^2 - 64*y - 219, y^3 - 21*y - 35)*x + Mod(-34*y^2 + 106*y + 381, y^3 - 21*y - 35) [y^3 - 12*y - 1, 1]: x^3 + Mod(-3*y^2 - 13*y - 4, y^3 - 12*y - 1)*x^2 + Mod( 16*y^2 + 54*y + 7, y^3 - 12*y - 1)*x + Mod(-18*y^2 - 65*y - 6, y^3 - 12*y - 1) [y^3 - y^2 - 17*y - 16, 1]: x^4 + Mod(-2*y^2 - 10*y - 11, y^3 - y^2 - 17*y - 16)*x^3 + Mod(21*y^2 + 86*y + 68, y^3 - y^2 - 17*y - 16)*x^2 + Mod(-66*y^2 - 262*y - 204, y^3 - y^2 - 17*y - 16)*x + Mod(65*y^2 + 262*y + 209, y^3 - y^ 2 - 17*y - 16) [y^3 - y^2 - 30*y - 27, 1]: x^3 + Mod(-250/3*y^2 - 1343/3*y - 350, y^3 - y^2 - 30*y - 27)*x^2 + Mod(3004/3*y^2 + 16139/3*y + 4244, y^3 - y^2 - 30*y - 27 )*x + Mod(-2729*y^2 - 14662*y - 11564, y^3 - y^2 - 30*y - 27) [y^3 - 14*y - 7, 1]: x^3 + Mod(-5*y^2 - 21*y - 10, y^3 - 14*y - 7)*x^2 + Mod (25*y^2 + 98*y + 42, y^3 - 14*y - 7)*x + Mod(-30*y^2 - 119*y - 52, y^3 - 14* y - 7) [y^3 - y^2 - 16*y + 22, 1]: x^3 + Mod(-10*y^2 - 27*y + 60, y^3 - y^2 - 16*y + 22)*x^2 + Mod(171*y^2 + 464*y - 1016, y^3 - y^2 - 16*y + 22)*x + Mod(-715* y^2 - 1940*y + 4234, y^3 - y^2 - 16*y + 22) [y^3 - y^2 - 30*y + 71, 1]: x^3 + Mod(-35*y^2 - 108*y + 604, y^3 - y^2 - 30* y + 71)*x^2 + Mod(194*y^2 + 599*y - 3364, y^3 - y^2 - 30*y + 71)*x + Mod(-25 9*y^2 - 800*y + 4495, y^3 - y^2 - 30*y + 71) [y^3 - y^2 - 16*y - 6, 1]: x^3 + Mod(-11*y^2 + 47*y + 22, y^3 - y^2 - 16*y - 6)*x^2 + Mod(293*y^2 - 1260*y - 532, y^3 - y^2 - 16*y - 6)*x + Mod(-1325*y^ 2 + 5696*y + 2410, y^3 - y^2 - 16*y - 6) [y^3 - 36*y - 45, 1]: x^3 + Mod(-12*y^2 - 78*y - 79, y^3 - 36*y - 45)*x^2 + Mod(1589/3*y^2 + 3469*y + 3642, y^3 - 36*y - 45)*x + Mod(-3038/3*y^2 - 6631* y - 6962, y^3 - 36*y - 45) [y^3 - 12*y - 1, [5, y + 1]]: x^6 + Mod(-2*y^2 - 7*y - 2, y^3 - 12*y - 1)*x^ 5 + Mod(27*y^2 + 94*y + 1, y^3 - 12*y - 1)*x^4 + Mod(-149*y^2 - 521*y - 32, y^3 - 12*y - 1)*x^3 + Mod(410*y^2 + 1439*y + 127, y^3 - 12*y - 1)*x^2 + Mod( -557*y^2 - 1957*y - 178, y^3 - 12*y - 1)*x + Mod(298*y^2 + 1046*y + 89, y^3 - 12*y - 1) [y^3 - y^2 - 37*y + 64, 1]: x^3 + Mod(-20*y^2 - 91*y + 230, y^3 - y^2 - 37*y + 64)*x^2 + Mod(17039/3*y^2 + 25994*y - 195548/3, y^3 - y^2 - 37*y + 64)*x + Mod(-504718*y^2 - 2309993*y + 5792200, y^3 - y^2 - 37*y + 64) [y^3 - y^2 - 9*y + 8, 1]: x^3 + Mod(-y^2 - 3*y, y^3 - y^2 - 9*y + 8)*x^2 + M od(5*y^2 + 12*y - 11, y^3 - y^2 - 9*y + 8)*x + Mod(-6*y^2 - 13*y + 15, y^3 - y^2 - 9*y + 8) [y^3 - 21*y - 35, 1]: x^3 + Mod(-4*y^2 + 12*y + 48, y^3 - 21*y - 35)*x^2 + M od(20*y^2 - 64*y - 219, y^3 - 21*y - 35)*x + Mod(-34*y^2 + 106*y + 381, y^3 - 21*y - 35) [y^3 - y^2 - 16*y + 8, 1]: x^3 + Mod(-3/2*y^2 - 11/2*y, y^3 - y^2 - 16*y + 8 )*x^2 + Mod(10*y^2 + 34*y - 18, y^3 - y^2 - 16*y + 8)*x + Mod(-16*y^2 - 53*y + 32, y^3 - y^2 - 16*y + 8) [y^3 - y^2 - 4*y - 1, 7]: x^9 + Mod(3803*y^2 - 4845*y - 13885, y^3 - y^2 - 4 *y - 1)*x^8 + Mod(-11843718*y^2 + 15087600*y + 43242511, y^3 - y^2 - 4*y - 1 )*x^7 + Mod(2447928994*y^2 - 3118393621*y - 8937617416, y^3 - y^2 - 4*y - 1) *x^6 + Mod(-122752473137*y^2 + 156373216132*y + 448180745635, y^3 - y^2 - 4* y - 1)*x^5 + Mod(2291810549483*y^2 - 2919515812766*y - 8367614391752, y^3 - y^2 - 4*y - 1)*x^4 + Mod(-20378966548367*y^2 + 25960573005885*y + 7440551044 5644, y^3 - y^2 - 4*y - 1)*x^3 + Mod(92972141705228*y^2 - 118436333193067*y - 339449973794721, y^3 - y^2 - 4*y - 1)*x^2 + Mod(-210119040368961*y^2 + 267 668660944174*y + 767164243383345, y^3 - y^2 - 4*y - 1)*x + Mod(1864214244966 95*y^2 - 237480491909325*y - 680642034264572, y^3 - y^2 - 4*y - 1) [y^3 - y^2 - 7*y + 6, [29, y - 13]]: x^7 + Mod(-5*y^2 - 11*y + 7, y^3 - y^2 - 7*y + 6)*x^6 + Mod(143*y^2 + 254*y - 306, y^3 - y^2 - 7*y + 6)*x^5 + Mod(- 1762*y^2 - 3082*y + 3846, y^3 - y^2 - 7*y + 6)*x^4 + Mod(11513*y^2 + 20157*y - 25127, y^3 - y^2 - 7*y + 6)*x^3 + Mod(-39912*y^2 - 69904*y + 87044, y^3 - y^2 - 7*y + 6)*x^2 + Mod(67549*y^2 + 118318*y - 147287, y^3 - y^2 - 7*y + 6 )*x + Mod(-43616*y^2 - 76398*y + 95101, y^3 - y^2 - 7*y + 6) x^4 + Mod(-32520*y - 102840, y^2 - 10)*x^3 + Mod(11599824*y + 36681864, y^2 - 10)*x^2 + Mod(-656457120*y - 2075899680, y^2 - 10)*x + Mod(6706767168*y + 21208659984, y^2 - 10) Total time spent: 25097 pari-2.7.5/src/test/32/subst0000644000175000017500000000112412366172547014176 0ustar billbillY/x x + 1 0 O(x^2) *** at top-level: subst(x+O(x^2),x,Mod *** ^-------------------- *** subst: forbidden substitution t_SER , t_INTMOD. Mod(0, 3) *** at top-level: subst(1/x+O(x^2),x,M *** ^-------------------- *** subst: impossible inverse in gsubst: Mod(0, 3). Mod(2, 3) -1/-y Mod(y*x, y^2*x^2 + 1) y*x/(y^2*x^2 + 1) List([]) List([y*x^2]) x^2 + y^2*x^3 + O(x^4) [;] *** at top-level: subst(1,x,Mat([1,2]) *** ^-------------------- *** subst: forbidden substitution t_INT , t_MAT (1x2). 4*y^2 + O(y^3) Total time spent: 0 pari-2.7.5/src/test/32/zn0000644000175000017500000000230412515252551013454 0ustar billbillMod(1, 2) Mod(3, 4) *** at top-level: znprimroot(8) *** ^------------- *** znprimroot: domain error in znprimroot: argument = 8 Mod(5, 9223372036854775837) Mod(5, 85070591730234616400799229995519050569) Mod(5, 170141183460469232801598459991038101138) Mod(5, 170141183460469232801598459991038101138) Mod(5, 170141183460469232801598459991038101138) [2, [2], [-1]] [1, [], []] [4, [4], [Mod(7, 10)]] [6, [6], [Mod(3, 14)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [2, [2], [-1]] *** _^_: Warning: Mod(a,b)^n with n >> b : wasteful. Mod(84, 148) [599, 599, 599, 599] [1000000003700000003419, 1000000003700000003419, 1000000003700000003419, 100 0000003700000003419] [] [] [] [] 1 48 [] [] [] 194 Mod(1, 2) 945843084768538962295343 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 generic discrete logarithm (order factorization) (t _MAT).") error("incorrect type in generic discrete logarithm (order factorization) (t _MAT).") [] Total time spent: 1392 pari-2.7.5/src/test/32/characteristic0000644000175000017500000000005412366172547016027 0ustar billbill0 0 6 0 3 0 3 0 3 2 0 0 Total time spent: 0 pari-2.7.5/src/test/32/history0000644000175000017500000000032012405547147014530 0ustar billbill2 3 4 5 *** 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) 1 Total time spent: 4 pari-2.7.5/src/test/32/debugger0000644000175000017500000000562012366172547014627 0ustar billbill echo = 1 (on) ? default(breakloop,1) ? my(bound=100,step=20,halt=41);check(B)=my(bi=[B^2]);for(i=1,bound,my(p=i+step,N=p^2);if(i==halt,error("check:",N))) (B)->my(bound=100,step=20,halt=41);my(bi=[B^2]);for(i=1,bound,my(p=i+step,N= p^2);if(i==halt,error("check:",N))) ? check(1000); *** at top-level: check(1000) *** ^----------- *** in function check: ...i+step,N=p^2);if(i==halt,error("check:",N))) *** ^------------------- *** user error: check:3721 *** Break loop: type 'break' to go back to GP prompt break> [bound,step,halt,i,p,N,bi,B] [100, 20, 41, 41, 61, 3721, [1000000], 1000] break> break ? [bound,step,halt,i,p,N,bi,B] [bound, step, halt, i, p, N, bi, B] ? my(p=120);for(i=1,100,1/0) *** at top-level: my(p=120);for(i=1,100,1/0) *** ^--- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> [p,i] [120, 1] break> dbg_err() error("impossible inverse in gdiv: 0.") break> break ? fun(N)=check(N^2+1); ? fun(20); *** at top-level: fun(20) *** ^------- *** in function fun: check(N^2+1) *** ^------------ *** in function check: ...i+step,N=p^2);if(i==halt,error("check:",N))) *** ^------------------- *** user error: check:3721 *** Break loop: type 'break' to go back to GP prompt break> N 3721 break> dbg_up(4) *** at top-level: fun(20) *** ^------- *** in function fun: check(N^2+1) *** ^------------ break> N 20 break> break ? f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); ? f(221,3) *** at top-level: f(221,3) *** ^-------- *** in function f: my(z=x^2+1);breakpoint();gcd(N,z *** ^-------------------- *** Break loop: to continue; 'break' to go back to GP prompt break> z 10 13 ? z z ? iferrname("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) *** at top-level: ...("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) *** ^------------------- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> i 100 break> break ? f()=1/0 ()->1/0 ? f(); *** at top-level: f() *** ^--- *** in function f: 1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> allocatemem(10^7) *** Warning: new stack size = 10000000 (9.537 Mbytes). ? for(i=1,10,if(i==2,1/0)); *** at top-level: for(i=1,10,if(i==2,1/0)) *** ^---- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> i 2 break> break ? print("Total time spent: ",gettime); Total time spent: 0 pari-2.7.5/src/test/32/chinese0000644000175000017500000000016312366172547014456 0ustar billbillMod(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 pari-2.7.5/src/test/32/ellweilpairing0000644000175000017500000001471312405547147016051 0ustar billbill[56, 46, [39, 3]] [63, 1, [18, 6]] [118, 118, [57, 3]] [144, 12, [12, 12]] [104, 1, [63, 3]] [108, 84, [57, 3]] [92, 1, [63, 3]] [98, 1, [16, 8]] [37, 136, [40, 4]] [148, 1, [72, 2]] [156, 28, [12, 12]] [4, 1, [5, 5]] [64, 108, [18, 6]] [107, 126, [18, 6]] [12, 12, [12, 12]] [178, 36, [14, 14]] [95, 98, [16, 8]] [148, 0, [72, 2]] [107, 37, [18, 6]] [104, 53, [63, 3]] [11, 7, [9, 3]] [92, 58, [63, 3]] [136, 0, [40, 4]] [156, 0, [30, 6]] [161, 36, [14, 14]] [144, 0, [30, 6]] [1, 0, [128]] [1, 0, [192]] [1, 1, [114]] [1, 1, [18, 6]] [156, 1, [12, 12]] [1, 1, [180]] [1, 1, [192]] [1, 3, [6]] t^5 + t^3 + t^2 t^5 + t^4 + 1 [0, 0, 0, 2, 0]:[2, 2] [0, 0, 1, 2, 2]:[2, 2] [0, 0, 2, 2, 2]:[2, 2] [1, 2, 0, 2, 0]:[2, 2] [1, 2, 1, 0, 2]:[2, 2] [1, 2, 2, 1, 2]:[2, 2] [2, 2, 0, 2, 0]:[2, 2] [2, 2, 1, 1, 2]:[2, 2] [2, 2, 2, 0, 2]:[2, 2] [0, 0, 0, 1, 0]:[2, 2] [0, 0, 0, 4, 0]:[4, 2] [0, 0, 1, 1, 1]:[2, 2] [0, 0, 1, 4, 1]:[4, 2] [0, 0, 2, 1, 4]:[2, 2] [0, 0, 2, 4, 4]:[4, 2] [0, 0, 3, 1, 4]:[2, 2] [0, 0, 3, 4, 4]:[4, 2] [0, 0, 4, 1, 1]:[2, 2] [0, 0, 4, 4, 1]:[4, 2] [0, 1, 0, 1, 1]:[4, 2] [0, 1, 0, 3, 0]:[2, 2] [0, 1, 1, 1, 2]:[4, 2] [0, 1, 1, 3, 1]:[2, 2] [0, 1, 2, 1, 0]:[4, 2] [0, 1, 2, 3, 4]:[2, 2] [0, 1, 3, 1, 0]:[4, 2] [0, 1, 3, 3, 4]:[2, 2] [0, 1, 4, 1, 2]:[4, 2] [0, 1, 4, 3, 1]:[2, 2] [0, 2, 0, 2, 0]:[4, 2] [0, 2, 0, 4, 3]:[2, 2] [0, 2, 1, 2, 1]:[4, 2] [0, 2, 1, 4, 4]:[2, 2] [0, 2, 2, 2, 4]:[4, 2] [0, 2, 2, 4, 2]:[2, 2] [0, 2, 3, 2, 4]:[4, 2] [0, 2, 3, 4, 2]:[2, 2] [0, 2, 4, 2, 1]:[4, 2] [0, 2, 4, 4, 4]:[2, 2] [0, 3, 0, 2, 0]:[4, 2] [0, 3, 0, 4, 2]:[2, 2] [0, 3, 1, 2, 1]:[4, 2] [0, 3, 1, 4, 3]:[2, 2] [0, 3, 2, 2, 4]:[4, 2] [0, 3, 2, 4, 1]:[2, 2] [0, 3, 3, 2, 4]:[4, 2] [0, 3, 3, 4, 1]:[2, 2] [0, 3, 4, 2, 1]:[4, 2] [0, 3, 4, 4, 3]:[2, 2] [0, 4, 0, 1, 4]:[4, 2] [0, 4, 0, 3, 0]:[2, 2] [0, 4, 1, 1, 0]:[4, 2] [0, 4, 1, 3, 1]:[2, 2] [0, 4, 2, 1, 3]:[4, 2] [0, 4, 2, 3, 4]:[2, 2] [0, 4, 3, 1, 3]:[4, 2] [0, 4, 3, 3, 4]:[2, 2] [0, 4, 4, 1, 0]:[4, 2] [0, 4, 4, 3, 1]:[2, 2] [1, 0, 0, 1, 4]:[4, 2] [1, 0, 0, 3, 0]:[2, 2] [1, 0, 1, 0, 1]:[2, 2] [1, 0, 1, 3, 0]:[4, 2] [1, 0, 2, 0, 3]:[4, 2] [1, 0, 2, 2, 4]:[2, 2] [1, 0, 3, 2, 3]:[4, 2] [1, 0, 3, 4, 4]:[2, 2] [1, 0, 4, 1, 1]:[2, 2] [1, 0, 4, 4, 0]:[4, 2] [1, 1, 0, 1, 0]:[2, 2] [1, 1, 0, 4, 0]:[4, 2] [1, 1, 1, 1, 1]:[4, 2] [1, 1, 1, 3, 1]:[2, 2] [1, 1, 2, 0, 4]:[2, 2] [1, 1, 2, 3, 4]:[4, 2] [1, 1, 3, 0, 4]:[4, 2] [1, 1, 3, 2, 4]:[2, 2] [1, 1, 4, 2, 1]:[4, 2] [1, 1, 4, 4, 1]:[2, 2] [1, 2, 0, 1, 1]:[4, 2] [1, 2, 0, 3, 0]:[2, 2] [1, 2, 1, 0, 1]:[2, 2] [1, 2, 1, 3, 2]:[4, 2] [1, 2, 2, 0, 0]:[4, 2] [1, 2, 2, 2, 4]:[2, 2] [1, 2, 3, 2, 0]:[4, 2] [1, 2, 3, 4, 4]:[2, 2] [1, 2, 4, 1, 1]:[2, 2] [1, 2, 4, 4, 2]:[4, 2] [1, 3, 0, 2, 0]:[4, 2] [1, 3, 0, 4, 3]:[2, 2] [1, 3, 1, 1, 4]:[2, 2] [1, 3, 1, 4, 1]:[4, 2] [1, 3, 2, 1, 4]:[4, 2] [1, 3, 2, 3, 2]:[2, 2] [1, 3, 3, 0, 2]:[2, 2] [1, 3, 3, 3, 4]:[4, 2] [1, 3, 4, 0, 1]:[4, 2] [1, 3, 4, 2, 4]:[2, 2] [1, 4, 0, 2, 0]:[4, 2] [1, 4, 0, 4, 2]:[2, 2] [1, 4, 1, 1, 3]:[2, 2] [1, 4, 1, 4, 1]:[4, 2] [1, 4, 2, 1, 4]:[4, 2] [1, 4, 2, 3, 1]:[2, 2] [1, 4, 3, 0, 1]:[2, 2] [1, 4, 3, 3, 4]:[4, 2] [1, 4, 4, 0, 1]:[4, 2] [1, 4, 4, 2, 3]:[2, 2] [2, 0, 0, 1, 1]:[4, 2] [2, 0, 0, 3, 0]:[2, 2] [2, 0, 1, 0, 2]:[4, 2] [2, 0, 1, 2, 1]:[2, 2] [2, 0, 2, 1, 4]:[2, 2] [2, 0, 2, 4, 0]:[4, 2] [2, 0, 3, 0, 4]:[2, 2] [2, 0, 3, 3, 0]:[4, 2] [2, 0, 4, 2, 2]:[4, 2] [2, 0, 4, 4, 1]:[2, 2] [2, 1, 0, 2, 0]:[4, 2] [2, 1, 0, 4, 3]:[2, 2] [2, 1, 1, 1, 1]:[4, 2] [2, 1, 1, 3, 4]:[2, 2] [2, 1, 2, 0, 4]:[4, 2] [2, 1, 2, 2, 2]:[2, 2] [2, 1, 3, 1, 2]:[2, 2] [2, 1, 3, 4, 4]:[4, 2] [2, 1, 4, 0, 4]:[2, 2] [2, 1, 4, 3, 1]:[4, 2] [2, 2, 0, 2, 0]:[4, 2] [2, 2, 0, 4, 2]:[2, 2] [2, 2, 1, 1, 1]:[4, 2] [2, 2, 1, 3, 3]:[2, 2] [2, 2, 2, 0, 4]:[4, 2] [2, 2, 2, 2, 1]:[2, 2] [2, 2, 3, 1, 1]:[2, 2] [2, 2, 3, 4, 4]:[4, 2] [2, 2, 4, 0, 3]:[2, 2] [2, 2, 4, 3, 1]:[4, 2] [2, 3, 0, 1, 4]:[4, 2] [2, 3, 0, 3, 0]:[2, 2] [2, 3, 1, 0, 0]:[4, 2] [2, 3, 1, 2, 1]:[2, 2] [2, 3, 2, 1, 4]:[2, 2] [2, 3, 2, 4, 3]:[4, 2] [2, 3, 3, 0, 4]:[2, 2] [2, 3, 3, 3, 3]:[4, 2] [2, 3, 4, 2, 0]:[4, 2] [2, 3, 4, 4, 1]:[2, 2] [2, 4, 0, 1, 0]:[2, 2] [2, 4, 0, 4, 0]:[4, 2] [2, 4, 1, 0, 1]:[2, 2] [2, 4, 1, 3, 1]:[4, 2] [2, 4, 2, 2, 4]:[4, 2] [2, 4, 2, 4, 4]:[2, 2] [2, 4, 3, 1, 4]:[4, 2] [2, 4, 3, 3, 4]:[2, 2] [2, 4, 4, 0, 1]:[4, 2] [2, 4, 4, 2, 1]:[2, 2] [3, 0, 0, 1, 1]:[4, 2] [3, 0, 0, 3, 0]:[2, 2] [3, 0, 1, 2, 2]:[4, 2] [3, 0, 1, 4, 1]:[2, 2] [3, 0, 2, 0, 4]:[2, 2] [3, 0, 2, 3, 0]:[4, 2] [3, 0, 3, 1, 4]:[2, 2] [3, 0, 3, 4, 0]:[4, 2] [3, 0, 4, 0, 2]:[4, 2] [3, 0, 4, 2, 1]:[2, 2] [3, 1, 0, 2, 0]:[4, 2] [3, 1, 0, 4, 3]:[2, 2] [3, 1, 1, 0, 4]:[2, 2] [3, 1, 1, 3, 1]:[4, 2] [3, 1, 2, 1, 2]:[2, 2] [3, 1, 2, 4, 4]:[4, 2] [3, 1, 3, 0, 4]:[4, 2] [3, 1, 3, 2, 2]:[2, 2] [3, 1, 4, 1, 1]:[4, 2] [3, 1, 4, 3, 4]:[2, 2] [3, 2, 0, 2, 0]:[4, 2] [3, 2, 0, 4, 2]:[2, 2] [3, 2, 1, 0, 3]:[2, 2] [3, 2, 1, 3, 1]:[4, 2] [3, 2, 2, 1, 1]:[2, 2] [3, 2, 2, 4, 4]:[4, 2] [3, 2, 3, 0, 4]:[4, 2] [3, 2, 3, 2, 1]:[2, 2] [3, 2, 4, 1, 1]:[4, 2] [3, 2, 4, 3, 3]:[2, 2] [3, 3, 0, 1, 4]:[4, 2] [3, 3, 0, 3, 0]:[2, 2] [3, 3, 1, 2, 0]:[4, 2] [3, 3, 1, 4, 1]:[2, 2] [3, 3, 2, 0, 4]:[2, 2] [3, 3, 2, 3, 3]:[4, 2] [3, 3, 3, 1, 4]:[2, 2] [3, 3, 3, 4, 3]:[4, 2] [3, 3, 4, 0, 0]:[4, 2] [3, 3, 4, 2, 1]:[2, 2] [3, 4, 0, 1, 0]:[2, 2] [3, 4, 0, 4, 0]:[4, 2] [3, 4, 1, 0, 1]:[4, 2] [3, 4, 1, 2, 1]:[2, 2] [3, 4, 2, 1, 4]:[4, 2] [3, 4, 2, 3, 4]:[2, 2] [3, 4, 3, 2, 4]:[4, 2] [3, 4, 3, 4, 4]:[2, 2] [3, 4, 4, 0, 1]:[2, 2] [3, 4, 4, 3, 1]:[4, 2] [4, 0, 0, 1, 4]:[4, 2] [4, 0, 0, 3, 0]:[2, 2] [4, 0, 1, 1, 1]:[2, 2] [4, 0, 1, 4, 0]:[4, 2] [4, 0, 2, 2, 3]:[4, 2] [4, 0, 2, 4, 4]:[2, 2] [4, 0, 3, 0, 3]:[4, 2] [4, 0, 3, 2, 4]:[2, 2] [4, 0, 4, 0, 1]:[2, 2] [4, 0, 4, 3, 0]:[4, 2] [4, 1, 0, 1, 0]:[2, 2] [4, 1, 0, 4, 0]:[4, 2] [4, 1, 1, 2, 1]:[4, 2] [4, 1, 1, 4, 1]:[2, 2] [4, 1, 2, 0, 4]:[4, 2] [4, 1, 2, 2, 4]:[2, 2] [4, 1, 3, 0, 4]:[2, 2] [4, 1, 3, 3, 4]:[4, 2] [4, 1, 4, 1, 1]:[4, 2] [4, 1, 4, 3, 1]:[2, 2] [4, 2, 0, 1, 1]:[4, 2] [4, 2, 0, 3, 0]:[2, 2] [4, 2, 1, 1, 1]:[2, 2] [4, 2, 1, 4, 2]:[4, 2] [4, 2, 2, 2, 0]:[4, 2] [4, 2, 2, 4, 4]:[2, 2] [4, 2, 3, 0, 0]:[4, 2] [4, 2, 3, 2, 4]:[2, 2] [4, 2, 4, 0, 1]:[2, 2] [4, 2, 4, 3, 2]:[4, 2] [4, 3, 0, 2, 0]:[4, 2] [4, 3, 0, 4, 3]:[2, 2] [4, 3, 1, 0, 1]:[4, 2] [4, 3, 1, 2, 4]:[2, 2] [4, 3, 2, 0, 2]:[2, 2] [4, 3, 2, 3, 4]:[4, 2] [4, 3, 3, 1, 4]:[4, 2] [4, 3, 3, 3, 2]:[2, 2] [4, 3, 4, 1, 4]:[2, 2] [4, 3, 4, 4, 1]:[4, 2] [4, 4, 0, 2, 0]:[4, 2] [4, 4, 0, 4, 2]:[2, 2] [4, 4, 1, 0, 1]:[4, 2] [4, 4, 1, 2, 3]:[2, 2] [4, 4, 2, 0, 1]:[2, 2] [4, 4, 2, 3, 4]:[4, 2] [4, 4, 3, 1, 4]:[4, 2] [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 pari-2.7.5/src/test/32/ideal0000644000175000017500000000435112405547147014115 0ustar billbill[;] [[1]~, [0]~] *** at top-level: idealaddtoone(Q,2,[; *** ^-------------------- *** idealaddtoone: elements not coprime in idealaddtoone: Mat(2) [;] *** at top-level: idealaddtoone(Q,[;], *** ^-------------------- *** idealaddtoone: elements not coprime in idealaddtoone: [;] [;] [[1]~, [0]~] [[1]~, [0]~] *** at top-level: idealaddtoone(Q,[1,[ *** ^-------------------- *** idealaddtoone: incorrect type in idealaddmultoone [integer matrix] (t_MAT). *** at top-level: ideallog(Q,2,idealst *** ^-------------------- *** ideallog: elements not coprime in zlog_pk: 2 [2, [2]~, 1, 1, 1] *** at top-level: idealstar(Qi,matdiag *** ^-------------------- *** idealstar: elements not coprime in idealaddtoone: [6, 0; 0, 3] [2, 0; 0, 2] [512, [16, 8, 4], [[-1, -2]~, 29, [0, -1]~]] [1/2 0] [ 0 1/2] [1]~ [2 1] [0 1] [2 0 0] [0 1 0] [0 0 1] [1/12 0 0] [ 0 1/12 0] [ 0 0 1/12] [2 0 0] [0 2 0] [0 0 2] [1/6 0 0] [ 0 1/6 0] [ 0 0 1/6] [1/3 0 0] [ 0 1/6 0] [ 0 0 1/6] [1 0 0] [0 1 0] [0 0 1/2] 0 0 1 1 [1725 35 1704] [ 0 5 4] [ 0 0 1] 5 [1 0 0] [0 1 0] [0 0 1/2] [1 0 0] [0 1/2 0] [0 0 1/2] 7 8 9 10 11 [1 0 0] [0 1 0] [0 0 1] [[1, 0, 0; 0, 1, 0; 0, 0, 1], Mat([2, 1])] [[67452192952521724999, [-16711321285323715217, 1]~, 1, 1, [1671132128532371 5218, -1; 1, 16711321285323715217]] 1] [[762234946175168528650011228121, [-63146078120386376378131819641, 1]~, 1, 1 , [63146078120386376378131819642, -1; 1, 63146078120386376378131819641]] -1] [67452192952521724999 19368419142280277485321497629511555041951889852345/762 234946175168528650011228121] [0 1/762234946175168528650011228121] [[67452192952521724999, 50740871667198009782; 0, 1], [7622349461751685286500 11228121, 699088868054782152271879408480; 0, 1]] [[67452192952521724999, 50740871667198009782; 0, 1], 1] [1, 1] [1, 2] [[1, 0; 0, 1], [2, 0; 0, 2]] [18, 9]~ [-85124952/2401, 33204681/2401]~ [249/2401, 1644/2401]~ [-7, -14]~ [14, 0]~ *** nfinit: Warning: non-monic polynomial. Result of the form [nf,c]. [[2, [0, 1]~, 2, 1, [0, -2; 1, 0]]] Total time spent: 8 pari-2.7.5/src/test/32/extract0000644000175000017500000002033612405547147014512 0ustar billbill[36][37][38][39][40][41][42][43][44][45][46][47][48][49][50][51][52][53][54] [55][56][57][58][59][60][61][62][63][64][65][66][67][68][69][70][71][72][73] [74][75][76][77][78][79][80][81][82][83][84][85][86][87][88][89][90][91][92] [93][94][95][96][97][98][99][100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4] [99, 98, 97] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [1, 100] [100, 1] [3, 5] [0 1 0] [0 0 1] [0] [1] [0, 2] [0, 2] [0, 0] [0, 0] [0, 0] [0, 0] [1] [1, 0] [1/x] [5, 4, 3, 2, 1] [1, 2] [1, 2] [1, 2] [1, 2, 3] [1, 2, 3, 4, 5] ["a", "b"] [[1, 3]~, [2, 4]~, [3, 5]~] ["e_INV", "gdiv", 0] [1, 0, 0, 0] [1, 0, 0, 0] [1/x, 0, 0, 0] [5, 4, 3, 2] [1, 2, 0, 0] [1, 2, 0, 0] [1, 2, 0, 0] [1, 2, 3, 0] [1, 2, 3, 4] error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [0, 0, 0, 1] [0, 0, 1, 0] [0, 0, 0, 1/x] [5, 4, 3, 2] [0, 0, 1, 2] [0, 0, 1, 2] [0, 0, 1, 2] [0, 1, 2, 3] [1, 2, 3, 4] error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [1] [0, 1] [1/x] [1, 2, 3, 4, 5] [2, 1] [2, 1] [2, 1] [3, 2, 1] [5, 4, 3, 2, 1] ["b", "a"] [[3, 5]~, [2, 4]~, [1, 3]~] [0, "gdiv", "e_INV"] [0, 0, 0, 1] [0, 0, 0, 1] [0, 0, 0, 1/x] [2, 3, 4, 5] [0, 0, 2, 1] [0, 0, 2, 1] [0, 0, 2, 1] [0, 3, 2, 1] [4, 3, 2, 1] error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [1, 0, 0, 0] [0, 1, 0, 0] [1/x, 0, 0, 0] [2, 3, 4, 5] [2, 1, 0, 0] [2, 1, 0, 0] [2, 1, 0, 0] [3, 2, 1, 0] [4, 3, 2, 1] error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [1]~ [1, 0]~ [1/x]~ [5, 4, 3, 2, 1]~ [1, 2]~ [1, 2]~ [1, 2]~ [1, 2, 3]~ [1, 2, 3, 4, 5]~ ["a", "b"]~ [[1, 2, 3], [3, 4, 5]]~ ["e_INV", "gdiv", 0]~ [1, 0, 0, 0]~ [1, 0, 0, 0]~ [1/x, 0, 0, 0]~ [5, 4, 3, 2]~ [1, 2, 0, 0]~ [1, 2, 0, 0]~ [1, 2, 0, 0]~ [1, 2, 3, 0]~ [1, 2, 3, 4]~ error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [0, 0, 0, 1]~ [0, 0, 1, 0]~ [0, 0, 0, 1/x]~ [5, 4, 3, 2]~ [0, 0, 1, 2]~ [0, 0, 1, 2]~ [0, 0, 1, 2]~ [0, 1, 2, 3]~ [1, 2, 3, 4]~ error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [1]~ [0, 1]~ [1/x]~ [1, 2, 3, 4, 5]~ [2, 1]~ [2, 1]~ [2, 1]~ [3, 2, 1]~ [5, 4, 3, 2, 1]~ ["b", "a"]~ [[3, 4, 5], [1, 2, 3]]~ [0, "gdiv", "e_INV"]~ [0, 0, 0, 1]~ [0, 0, 0, 1]~ [0, 0, 0, 1/x]~ [2, 3, 4, 5]~ [0, 0, 2, 1]~ [0, 0, 2, 1]~ [0, 0, 2, 1]~ [0, 3, 2, 1]~ [4, 3, 2, 1]~ error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") [1, 0, 0, 0]~ [0, 1, 0, 0]~ [1/x, 0, 0, 0]~ [2, 3, 4, 5]~ [2, 1, 0, 0]~ [2, 1, 0, 0]~ [2, 1, 0, 0]~ [3, 2, 1, 0]~ [4, 3, 2, 1]~ error("incorrect type in gtovec (t_STR).") error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") Vecsmall([1]) Vecsmall([1, 0]) error("incorrect type in vectosmall (t_RFRAC).") Vecsmall([5, 4, 3, 2, 1]) Vecsmall([1, 2]) Vecsmall([1, 2]) Vecsmall([1, 2]) Vecsmall([1, 2, 3]) Vecsmall([1, 2, 3, 4, 5]) Vecsmall([97, 98]) error("incorrect type in vectosmall (t_MAT).") error("incorrect type in vectosmall (t_ERROR).") Vecsmall([1, 0, 0, 0]) Vecsmall([1, 0, 0, 0]) error("incorrect type in gtovecsmall (t_RFRAC).") Vecsmall([5, 4, 3, 2]) Vecsmall([1, 2, 0, 0]) Vecsmall([1, 2, 0, 0]) Vecsmall([1, 2, 0, 0]) Vecsmall([1, 2, 3, 0]) Vecsmall([1, 2, 3, 4]) error("incorrect type in gtovecsmall (t_STR).") error("incorrect type in gtovecsmall (t_MAT).") error("incorrect type in gtovecsmall (t_ERROR).") Vecsmall([0, 0, 0, 1]) Vecsmall([0, 0, 1, 0]) error("incorrect type in gtovecsmall (t_RFRAC).") Vecsmall([5, 4, 3, 2]) Vecsmall([0, 0, 1, 2]) Vecsmall([0, 0, 1, 2]) Vecsmall([0, 0, 1, 2]) Vecsmall([0, 1, 2, 3]) Vecsmall([1, 2, 3, 4]) error("incorrect type in gtovecsmall (t_STR).") error("incorrect type in gtovecsmall (t_MAT).") error("incorrect type in gtovecsmall (t_ERROR).") error("incorrect type in component [leaf] (t_INT).") 1 x 2 2 2 2 2 2 error("incorrect type in component [leaf] (t_STR).") [2, 4]~ 0 error("incorrect type in component [leaf] (t_INT).") 0 error("non-existent component: index > 2") 0 error("non-existent component: index > 3") error("non-existent component: index > 2") error("non-existent component: index > 2") error("non-existent component: index > 3") error("non-existent component: index > 5") error("incorrect type in component [leaf] (t_STR).") error("non-existent component: index > 3") error("non-existent component: index > 3") 0 0 1 0 0 error("non-existent component in polcoeff: index < 1") error("incorrect type in polcoeff (t_VECSMALL).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_STR).") error("non-existent component in polcoeff: index < 1") error("incorrect type in polcoeff (t_ERROR).") 0 0 0 3 2 2 error("incorrect type in polcoeff (t_VECSMALL).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_STR).") [2, 4]~ error("incorrect type in polcoeff (t_ERROR).") 0 0 0 0 error("domain error in polcoeff: degree > 2") error("non-existent component in polcoeff: index > 2") error("incorrect type in polcoeff (t_VECSMALL).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_LIST).") error("incorrect type in polcoeff (t_STR).") error("non-existent component in polcoeff: index > 3") error("incorrect type in polcoeff (t_ERROR).") 0 0 x + 1 0 y + O(y^2) Vecsmall([4, 5, 3]) Total time spent: 0 pari-2.7.5/src/test/32/matsnf0000644000175000017500000005563212405547147014337 0ustar billbillx^2 + 10*x + 27 x^2 + 10/3*x + 3 x^2 + 10/a*x + 27/a^2 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]] [0, x, x] [0, x^2 + x, 1] [0, 0] [[1, 0, 0; 0, -2, 1], [;], [;]] [] [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 pari-2.7.5/src/test/32/krasner0000644000175000017500000001460612405547147014510 0ustar billbill *** 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]] [[0, 1, 9, 0], [6, 3, 3, 6], [8, 9, 1, 8]] [[0, 1, 11, 0], [10, 11, 1, 10]] [[0, 1, 13, 0], [12, 13, 1, 12]] [[0, 1, 15, 0], [10, 3, 5, 10], [12, 5, 3, 12], [14, 15, 1, 14]] [[0, 1, 17, 0], [16, 17, 1, 16]] [[0, 1, 19, 0], [18, 19, 1, 18]] [[0, 1, 21, 0], [14, 3, 7, 14], [18, 7, 3, 18], [18, 7, 3, 18], [18, 7, 3, 1 8], [20, 21, 1, 20]] [[0, 1, 23, 0], [22, 23, 1, 22]] [[0, 1, 25, 0], [20, 5, 5, 20], [24, 25, 1, 24]] [[0, 1, 27, 0], [18, 3, 9, 18], [24, 9, 3, 24], [26, 27, 1, 26]] [[0, 1, 29, 0], [28, 29, 1, 28]] [[0, 1, 31, 0], [30, 31, 1, 30]] [[0, 1, 33, 0], [22, 3, 11, 22], [30, 11, 3, 30], [32, 33, 1, 32]] [[0, 1, 35, 0], [28, 5, 7, 28], [30, 7, 5, 30], [34, 35, 1, 34]] [[0, 1, 37, 0], [36, 37, 1, 36]] [[0, 1, 39, 0], [26, 3, 13, 26], [36, 13, 3, 36], [38, 39, 1, 38]] [[0, 1, 41, 0], [40, 41, 1, 40]] [[0, 1, 43, 0], [42, 43, 1, 42]] [[0, 1, 45, 0], [30, 3, 15, 30], [36, 5, 9, 36], [40, 9, 5, 40], [42, 15, 3, 42], [44, 45, 1, 44]] [[0, 1, 47, 0], [46, 47, 1, 46]] [[0, 1, 49, 0], [42, 7, 7, 42], [48, 49, 1, 48]] [[0, 1, 2, 0], [1, 2, 1, 1], [1, 2, 1, 1]] [[0, 1, 4, 0], [2, 2, 2, 2], [2, 2, 2, 2], [3, 4, 1, 3], [3, 4, 1, 3]] [[0, 1, 5, 0], [4, 5, 1, 4]] [[0, 1, 7, 0], [6, 7, 1, 6]] [[0, 1, 8, 0], [4, 2, 4, 4], [4, 2, 4, 4], [6, 4, 2, 6], [6, 4, 2, 6], [6, 4 , 2, 6], [7, 8, 1, 7], [7, 8, 1, 7]] [[0, 1, 10, 0], [5, 2, 5, 5], [5, 2, 5, 5], [8, 5, 2, 8], [9, 10, 1, 9], [9, 10, 1, 9]] [[0, 1, 11, 0], [10, 11, 1, 10]] [[0, 1, 13, 0], [12, 13, 1, 12]] [[0, 1, 14, 0], [7, 2, 7, 7], [7, 2, 7, 7], [12, 7, 2, 12], [13, 14, 1, 13], [13, 14, 1, 13]] [[0, 1, 16, 0], [8, 2, 8, 8], [8, 2, 8, 8], [12, 4, 4, 12], [12, 4, 4, 12], [12, 4, 4, 12], [14, 8, 2, 14], [14, 8, 2, 14], [14, 8, 2, 14], [14, 8, 2, 1 4], [14, 8, 2, 14], [15, 16, 1, 15], [15, 16, 1, 15]] [[0, 1, 17, 0], [16, 17, 1, 16]] [[0, 1, 19, 0], [18, 19, 1, 18]] [[0, 1, 20, 0], [10, 2, 10, 10], [10, 2, 10, 10], [15, 4, 5, 15], [15, 4, 5, 15], [16, 5, 4, 16], [16, 5, 4, 16], [18, 10, 2, 18], [18, 10, 2, 18], [19, 20, 1, 19], [19, 20, 1, 19]] [[0, 1, 22, 0], [11, 2, 11, 11], [11, 2, 11, 11], [20, 11, 2, 20], [21, 22, 1, 21], [21, 22, 1, 21]] [[0, 1, 23, 0], [22, 23, 1, 22]] [[0, 1, 25, 0], [20, 5, 5, 20], [24, 25, 1, 24]] [[0, 1, 26, 0], [13, 2, 13, 13], [13, 2, 13, 13], [24, 13, 2, 24], [25, 26, 1, 25], [25, 26, 1, 25]] [[0, 1, 28, 0], [14, 2, 14, 14], [14, 2, 14, 14], [21, 4, 7, 21], [21, 4, 7, 21], [24, 7, 4, 24], [26, 14, 2, 26], [26, 14, 2, 26], [27, 28, 1, 27], [27 , 28, 1, 27]] [[0, 1, 29, 0], [28, 29, 1, 28]] [[0, 1, 31, 0], [30, 31, 1, 30]] [[0, 1, 32, 0], [16, 2, 16, 16], [16, 2, 16, 16], [24, 4, 8, 24], [24, 4, 8, 24], [24, 4, 8, 24], [28, 8, 4, 28], [28, 8, 4, 28], [28, 8, 4, 28], [28, 8 , 4, 28], [28, 8, 4, 28], [30, 16, 2, 30], [30, 16, 2, 30], [30, 16, 2, 30], [30, 16, 2, 30], [30, 16, 2, 30], [31, 32, 1, 31], [31, 32, 1, 31]] [[0, 1, 34, 0], [17, 2, 17, 17], [17, 2, 17, 17], [32, 17, 2, 32], [33, 34, 1, 33], [33, 34, 1, 33]] [[0, 1, 35, 0], [28, 5, 7, 28], [30, 7, 5, 30], [34, 35, 1, 34]] [[0, 1, 37, 0], [36, 37, 1, 36]] [[0, 1, 38, 0], [19, 2, 19, 19], [19, 2, 19, 19], [36, 19, 2, 36], [37, 38, 1, 37], [37, 38, 1, 37]] [[0, 1, 40, 0], [20, 2, 20, 20], [20, 2, 20, 20], [30, 4, 10, 30], [30, 4, 1 0, 30], [30, 4, 10, 30], [32, 5, 8, 32], [32, 5, 8, 32], [35, 8, 5, 35], [35 , 8, 5, 35], [36, 10, 4, 36], [36, 10, 4, 36], [36, 10, 4, 36], [36, 10, 4, 36], [38, 20, 2, 38], [38, 20, 2, 38], [38, 20, 2, 38], [39, 40, 1, 39], [39 , 40, 1, 39]] [[0, 1, 41, 0], [40, 41, 1, 40]] [[0, 1, 43, 0], [42, 43, 1, 42]] [[0, 1, 44, 0], [22, 2, 22, 22], [22, 2, 22, 22], [33, 4, 11, 33], [33, 4, 1 1, 33], [40, 11, 4, 40], [42, 22, 2, 42], [42, 22, 2, 42], [43, 44, 1, 43], [43, 44, 1, 43]] [[0, 1, 46, 0], [23, 2, 23, 23], [23, 2, 23, 23], [44, 23, 2, 44], [45, 46, 1, 45], [45, 46, 1, 45]] [[0, 1, 47, 0], [46, 47, 1, 46]] [[0, 1, 49, 0], [42, 7, 7, 42], [48, 49, 1, 48]] [[0, 1, 50, 0], [25, 2, 25, 25], [25, 2, 25, 25], [40, 5, 10, 40], [45, 10, 5, 45], [45, 10, 5, 45], [48, 25, 2, 48], [49, 50, 1, 49], [49, 50, 1, 49]] [[0, 1, 105, 0], [70, 3, 35, 70], [84, 5, 21, 84], [90, 7, 15, 90], [90, 7, 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]] [[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 , 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 12], [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, 2, 0], [1, 2, 1, 1], [1, 2, 1, 1]] [[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, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [ 9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [ 10, 4, 1, 10], [10, 4, 1, 10], [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], [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 pari-2.7.5/src/test/32/gcdext0000644000175000017500000000402012413013143014265 0ustar billbill[0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1, 2] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [1, 0, 2] [1/2, 0, 1] [1/2, 0, 1] [0, 1, 2] [1/2, 0, 1] [1/2, 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [1, 0, x] [1, 0, x] [1, 0, x] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, -3, 3*x + 5] [0, 1, (10*T^3 + 3*T + 5)*z^6 + (11*T^3 + 15*T^2 + 10*T + 13)*z^4 + (14*T^3 + 13*T^2 + 15)*z^2 + (9 + 13*T + 14*T^2 + 11*T^3 + O(T^20))] Mod(1, 7)*x 1 + I 1 1 2 w w Mod(2, 4) *** at top-level: gcd(1/2,Mod(2,4)) *** ^----------------- *** gcd: inconsistent gcd t_INTMOD , t_FRAC. Mod(1, 4) 2 Mod(1, 5) Mod(1, 5) 1/2 1/2 1 1 1 Mod(1, x^3) Mod(x, x^3) 1 *** at top-level: gcd(t,1/x) *** ^---------- *** gcd: inconsistent gcd t_POLMOD , t_RFRAC. 1 y x 1/x^2 1 1 1 0 1 1 error("forbidden gcd t_REAL , t_FFELT.") error("forbidden gcd t_REAL , t_FFELT.") error("forbidden gcd t_REAL , t_FFELT.") 1 1 error("inconsistent gcd t_INTMOD , t_FFELT.") error("inconsistent gcd t_FRAC , t_FFELT.") error("inconsistent gcd t_FRAC , t_FFELT.") 1 1 1 error("inconsistent gcd t_FRAC , t_FFELT.") 0 1 error("inconsistent gcd t_FRAC , t_FFELT.") error("forbidden gcd t_FFELT , t_COMPLEX.") error("forbidden gcd t_FFELT , t_COMPLEX.") error("forbidden gcd t_FFELT , t_COMPLEX.") error("forbidden gcd t_FFELT , t_QUAD.") error("forbidden gcd t_FFELT , t_QUAD.") error("forbidden gcd t_FFELT , t_QUAD.") 1 1 error("inconsistent gcd t_FFELT , t_PADIC.") 0 1 error("inconsistent gcd t_FFELT , t_PADIC.") error("inconsistent gcd t_FFELT , t_PADIC.") error("inconsistent gcd t_FFELT , t_PADIC.") error("inconsistent gcd t_FFELT , t_PADIC.") 1 1 + I Mod(1, 3) 1 1 (-k + 0.E-38)/k 1/18446744073709551616 Total time spent: 4 pari-2.7.5/src/test/32/ell0000644000175000017500000003625212456454707013625 0ustar billbill-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^2 + 1, a^3 + a^2 + a + 1]]] 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.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 [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 [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.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 [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 [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.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 [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 [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.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 -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] 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 1 [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 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: 1048 pari-2.7.5/src/test/32/linear0000644000175000017500000003775312405547147014325 0ustar billbill echo = 1 (on) ? algdep(2*cos(2*Pi/13),6) x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1 ? algdep(2*cos(2*Pi/13),6,15) x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1 ? charpoly([1,2;3,4],z) z^2 - 5*z - 2 ? charpoly(Mod(x^2+x+1,x^3+5*x+1),z) z^3 + 7*z^2 + 16*z - 19 ? charpoly([1,2;3,4],z,1) z^2 - 5*z - 2 ? charpoly(Mod(1,8191)*[1,2;3,4],z,2) z^2 + Mod(8186, 8191)*z + Mod(8189, 8191) ? lindep(Mod(1,7)*[2,-1;1,3]) [-3, 1]~ ? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)]) [3, 3, -9, 2, -6]~ ? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14) [-3, -3, 9, -2, 6]~ ? matadjoint([1,2;3,4]) [ 4 -2] [-3 1] ? matcompanion(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] ? matdet([1,2,3;1,5,6;9,8,7]) -30 ? matdet([1,2,3;1,5,6;9,8,7],1) -30 ? matdetint([1,2,3;4,5,6]) 3 ? matdiagonal([2,4,6]) [2 0 0] [0 4 0] [0 0 6] ? mateigen([1,2,3;4,5,6;7,8,9]) [1 -1.2833494518006402717978106547571267252 0.283349451800640271797810654757 12672521] [-2 -0.14167472590032013589890532737856336261 0.6416747259003201358989053273 7856336260] [1 1 1] ? mathess(mathilbert(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] ? mathilbert(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] ? amat=1/mathilbert(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] ? mathnf(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] ? mathnf(amat,1) [[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]] ? mathnf(amat,4) [[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]] ? mathnf(amat,5) [[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])] ? mathnfmod(amat,matdetint(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] ? mathnfmodid(amat,123456789*10^100) [60 0 0 0 30 24 35] [ 0 120 0 0 0 0 24] [ 0 0 360 0 0 0 180] [ 0 0 0 360 0 0 240] [ 0 0 0 0 180 0 90] [ 0 0 0 0 0 72 0] [ 0 0 0 0 0 0 12] ? matid(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] ? matimage([1,3,5;2,4,6;3,5,7]) [1 3] [2 4] [3 5] ? matimage([1,3,5;2,4,6;3,5,7],1) [3 5] [4 6] [5 7] ? matimage(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] ? matimagecompl([1,3,5;2,4,6;3,5,7]) Vecsmall([3]) ? matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) Vecsmall([3]) ? matindexrank([1,1,1;1,1,1;1,1,2]) [Vecsmall([1, 3]), Vecsmall([1, 3])] ? matintersect([1,2;3,4;5,6],[2,3;7,8;8,9]) [-1] [-1] [-1] ? matinverseimage([1,1;2,3;5,7],[2,2,6]~) [4, -2]~ ? matisdiagonal([1,0,0;0,5,0;0,0,0]) 1 ? matker(matrix(4,4,x,y,x/y)) [-1/2 -1/3 -1/4] [ 1 0 0] [ 0 1 0] [ 0 0 1] ? matker(matrix(4,4,x,y,sin(x+y))) [1.0000000000000000000000000000000000000 1.080604611736279434801873214885953 2075] [-1.0806046117362794348018732148859532075 -0.1677063269057152260048635409984 7562047] [1 0] [0 1] ? matker(matrix(4,4,x,y,x+y),1) [ 1 2] [-2 -3] [ 1 0] [ 0 1] ? matkerint(matrix(4,4,x,y,x*y)) [-1 -1 -1] [-1 0 1] [ 1 -1 1] [ 0 1 -1] ? matkerint(matrix(4,4,x,y,x*y),1) [-1 -1 -1] [-1 0 1] [ 1 -1 1] [ 0 1 -1] ? matkerint(matrix(4,6,x,y,2520/(x+y))) [ 3 1] [ -30 -15] [ 70 70] [ 0 -140] [-126 126] [ 84 -42] ? matmuldiagonal(amat,[1,2,3,4,5,6,7]) [ 49 -2352 26460 -117600 242550 -232848 84084] [ -1176 75264 -952560 4515840 -9702000 9580032 -3531528] [ 8820 -635040 8573040 -42336000 93555000 -94303440 35315280] [-29400 2257920 -31752000 161280000 -363825000 372556800 -141261120] [ 48510 -3880800 56133000 -291060000 667012500 -691558560 264864600] [-38808 3193344 -47151720 248371200 -576298800 603542016 -233080848] [ 12012 -1009008 15135120 -80720640 189189000 -199783584 77693616] ? matmultodiagonal(amat^-1,%) [1 0 0 0 0 0 0] [0 2 0 0 0 0 0] [0 0 3 0 0 0 0] [0 0 0 4 0 0 0] [0 0 0 0 5 0 0] [0 0 0 0 0 6 0] [0 0 0 0 0 0 7] ? matpascal(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] ? matrank(matrix(5,5,x,y,x+y)) 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] ? matrixqz([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0],-1) [19 12 2] [ 0 1 0] [ 0 0 1] ? matrixqz([1,3;3,5;5,7],-2) [2 -1] [1 0] [0 1] ? matsize([1,2;3,4;5,6]) [3, 2] ? matsnf(1/mathilbert(6)) [27720, 2520, 2520, 840, 210, 6] ? matsnf(x*matid(5)-matrix(5,5,j,k,1),2) [x^2 - 5*x, x, x, x, 1] ? matsolve(mathilbert(10),[1,2,3,4,5,6,7,8,9,0]~) [9236800, -831303990, 18288515520, -170691240720, 832112321040, -23298940665 00, 3883123564320, -3803844432960, 2020775945760, -449057772020]~ ? matsolvemod([2,3;5,4],[7,11]~,[1,4]~) [-5, -1]~ ? matsolvemod([2,3;5,4],[7,11]~,[1,4]~,1) [[-5, -1]~, [4, 9; -5, 8]] ? matsupplement([1,3;2,4;3,6]) [1 3 0] [2 4 0] [3 6 1] ? mattranspose(vector(2,x,x)) [1, 2]~ ? %*%~ [1 2] [2 4] ? norml2(vector(10,x,x)) 385 ? qfgaussred(mathilbert(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] ? qfjacobi(mathilbert(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]] ? m=1/mathilbert(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,matid(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] ? qflll(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] ? qflllgram(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] ? qflllgram(m,1) [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] ? qflllgram(mp~*mp,4) [[-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]] ? qflll(m,1) [-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] ? qflll(m,2) [-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] ? qflll(mp,4) [[-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]] ? qfminim([2,1;1,2],4,6) [6, 2, [0, -1, 1; 1, 1, 0]] ? qfperfection([2,0,1;0,2,1;1,1,2]) 6 ? qfsign(mathilbert(5)-0.11*matid(5)) [2, 3] ? trace(1+I) 2 ? trace(Mod(x+5,x^3+x+1)) 15 ? Vec(sin(x)) [1, 0, -1/6, 0, 1/120, 0, -1/5040, 0, 1/362880, 0, -1/39916800, 0, 1/6227020 800, 0, -1/1307674368000, 0] ? vecmax([-3,7,-2,11]) 11 ? vecmin([-3,7,-2,11]) -3 ? concat([1,2],[3,4]) [1, 2, 3, 4] ? concat(Mat(vector(4,x,x)~),vector(4,x,10+x)~) [1 11] [2 12] [3 13] [4 14] ? vecextract([1,2,3,4,5,6,7,8,9,10],1000) [4, 6, 7, 8, 9, 10] ? vecextract(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] ? round((1.*mathilbert(7))^(-1)<<77)/2^77 [49 -1176 8820 -29400 48510 -38808 12012] [-1176 37632 -317520 1128960 -1940400 1596672 -504504] [8820 -317520 2857680 -10584000 18711000 -15717240 5045040] [-29400 1128960 -10584000 6092986130857731040519127040001/151115727451828646 838272 -10995935908032311487186862080001/151115727451828646838272 9383198641 520905802399455641601/151115727451828646838272 -20180160] [48510 -1940400 18711000 -10995935908032311487186862080001/15111572745182864 6838272 10079607915696285529921290240001/75557863725914323419136 -8708781239 161590697851994767361/75557863725914323419136 37837800] [-38808 1596672 -15717240 9383198641520905802399455641601/151115727451828646 838272 -8708781239161590697851994767361/75557863725914323419136 152007817992 63867399887118139393/151115727451828646838272 -33297264] [12012 -504504 5045040 -20180160 37837800 -33297264 11099088] ? vecsort([8,7,6,5],,1) Vecsmall([4, 3, 2, 1]) ? vecsort([[1,5],[2,4],[1,5,1],[1,4,2]]) [[1, 4, 2], [1, 5], [1, 5, 1], [2, 4]] ? vecsort(vector(17,x,5*x%17)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] ? 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]] ? vector(10,x,1/x) [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 pari-2.7.5/src/test/32/logint0000644000175000017500000000022212366172547014330 0ustar billbill99 100 1267650600228229401496703205376 232 6901746346790563787434755862277025452451108972170386555162524223799296 146 116 100 Total time spent: 0 pari-2.7.5/src/test/32/kernel0000644000175000017500000000250212405547147014313 0ustar billbillINT: 187654321 conv:40000003 0b2f60b1 +:40000003 0a72ff63 -:40000003 0bebc1ff *:c0000004 00083b0b 5e0e86ee /:c0000003 0000000f rem:40000003 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 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 pari-2.7.5/src/test/32/graph0000644000175000017500000000565712366172547014156 0ustar billbill echo = 1 (on) ? plotinit(0,500,500) ? plotmove(0,0,0);plotbox(0,500,500) ? plotmove(0,200,150) ? plotcursor(0) [200, 150] ? psdraw([0,0,0]) ? plotinit(1,700,700) ? plotkill(1) ? 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) [243, 583] ? plot(x=-5,5,sin(x),-1,1) 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 ? plotpoints(0,225,334) ? plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) ? psdraw([0,20,20]) ? psploth(x=-5,5,sin(x)) [-5.000000000000000000, 5.000000000000000000, -0.9999964107564721649, 0.9999 964107564721649] ? psploth(t=0,2*Pi,[sin(5*t),sin(7*t)],1,100) [-0.9998741276738750683, 0.9998741276738750683, -0.9998741276738750683, 0.99 98741276738750683] ? psplothraw(vector(100,k,k),vector(100,k,k*k/100)) [1.0000000000000000000, 100.00000000000000000, 0.010000000000000000208, 100. 00000000000000000] ? plotmove(0,50,50);plotrbox(0,50,50) ? plotrline(0,200,150) ? plotcursor(0) [250, 200] ? plotrmove(0,5,5);plotcursor(0) [255, 205] ? plotrpoint(0,20,20) ? plotinit(3,600,600);plotscale(3,-7,7,-2,2);plotcursor(3) [-7, 2] ? plotmove(0,100,100);plotstring(0,Pi) ? plotmove(0,200,200);plotstring(0,"(0,0)") ? psdraw([0,10,10]) ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 16 pari-2.7.5/src/test/32/prec0000644000175000017500000000047312366172547013775 0ustar billbillI 1 + O(3^3) + I O(2^3) 1 + O(2^3) x + (1 + O(3^3)) (1 + O(3^3))/((1 + O(5^3))*x) Mod(1 + O(3^3), (1 + O(3^3))*x) [1 + O(3^3), 2] 77 38 1 1 2 *** at top-level: padicprec(O(2^2),3) *** ^------------------- *** padicprec: inconsistent moduli in padicprec: 2 != 3 2 3 3 3 4 Total time spent: 8 pari-2.7.5/src/test/32/charpoly0000644000175000017500000000273012366172547014663 0ustar billbill(-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) x^4 - 16*x^2 x^4 - 16*x^2 x^2 - 4*x [1 14/39] [0 1] [1 0.35897435897435897435897435897435897438] [0 1] [[5/3, 21/10], [1, 14/39; 0, 1]] -x^2 + (-y - w)*x + (-y + (w^2 - w)) x - 1 x - 1.0000000000000000000000000000000000000 x + Mod(2, 3) x - 1/2 x + (2 + O(3)) x^2 + 1 x^2 - x - 1 Mod(1, 3)*x^2 + Mod(1, 3)*x + Mod(1, 3) Mod(1, 18446744073709551629)*x^2 + Mod(18446744073709551627, 184467440737095 51629)*x + Mod(1, 18446744073709551629) x^4 - 4*x^3 + 6*x^2 - 4*x + 1 x^4 - 4*x^3 + 6*x^2 - 4*x + 1 x^4 - 73786976294838206516*x^3 + 2041694201525630783657939720089299321846*x^ 2 - 25108406941546723108427206932497066002105857518694949724756*x + 11579208 9237316195749980275248795307917777354730270819790751905975615430356881 Mod(1, 3)*x^4 + Mod(1, 3)*x^3 + Mod(1, 3)*x^2 + Mod(1, 3)*x Mod(1, 18446744073709551629)*x^4 + Mod(18446744073709551600, 184467440737095 51629)*x^3 + Mod(46, 18446744073709551629)*x^2 + Mod(16, 1844674407370955162 9)*x [1 0] [0 1] [;] [1] [0 0 0] [0 0 0] [0 0 0] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] *** at top-level: charpoly(x*matid(3)) *** ^-------------------- *** charpoly: incorrect priority in charpoly: variable x = x x^4 - 4*x^3 + 6*x^2 - 4*x + 2 x^2 [] [[], [;]] [1] [[1], Mat(1)] Total time spent: 4 pari-2.7.5/src/test/32/sumdedekind0000644000175000017500000000015412366172547015334 0ustar billbill-1/18 0 1145846923/57826382 56713727820156410558782357164918483627/73786976294838206464 Total time spent: 4 pari-2.7.5/src/test/32/parallel0000644000175000017500000000225212366172547014635 0ustar billbill[[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] [[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] [[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] 188 Vecsmall([188, 722, 752]) [414951556888099295851240786369116115101244623224243689999565732969065281141 2908146399707048947103794288197886611300789182395151075411775307886874834113 963687061181803401509523685563, 41495155688809929585124078636911611510124462 3224243689999565732969065281141290814639970704894710379428819788661130078918 2395151075411775307886874834113963687061181803401509523686097, 4149515568880 9929585124078636911611510124462322424368999956573296906528114129081463997070 4894710379428819788661130078918239515107541177530788687483411396368706118180 3401509523686127] 7432339208719 7432339208719 [75, 85070591730234615858594180193637120807] Total time spent: 23517 pari-2.7.5/src/test/32/bnrL10000644000175000017500000000710112612420444013777 0ustar billbill[[1, 0.38224508584003564132935849918485739404 + 0.E-38*I], [1, 0.38224508584 003564132935849918485739404 + 0.E-38*I], [0, -3/2]] [[[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 402473588976342837*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 06157651701402473588976342837*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]] [0.90088685686467725961014440212013594076, 0.4063580640155376797096153264205 1751587, 0.40635806401553767970961532642051751587, 0.90088685686467725961014 440212013594076] Total time spent: 232 pari-2.7.5/src/test/32/sumdiv0000644000175000017500000000323312526652003014334 0ustar billbill3628800 20993420690550 3628800 20993420690550 3628800 20993420690550 3628800 20993420690550 0 0 7 [7, 720] 4 15 829440 270 15334088 20993420690550 57335533287534038504 1 error("domain error in moebius: argument = 0") 0 [0, 1] error("domain error in omega: argument = 0") error("domain error in bigomega: argument = 0") 2 error("domain error in numdiv: argument = 0") error("domain error in sumdiv: argument = 0") error("domain error in sumdivk: argument = 0") error("domain error in sumdivk: argument = 0") 1 error("incorrect type in moebius (t_MAT).") 0 [0, 1] error("incorrect type in omega (t_MAT).") error("incorrect type in bigomega (t_MAT).") 2 error("incorrect type in numdiv (t_MAT).") error("incorrect type in sumdiv (t_MAT).") error("incorrect type in sumdivk (t_MAT).") error("incorrect type in sumdivk (t_MAT).") 0 -1 -2 [-2, 1] 1 1 1 2 3 5 9 0 -1 -2 [-2, 1] 1 1 1 2 3 5 9 1 1 1 [1, 1] 0 0 1 1 1 1 1 [1] 1 0 [0, 1] *** at top-level: divisors(fa) *** ^------------ *** divisors: domain error in divisors: argument = 0 [30, 2] [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120] 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 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). 0 Total time spent: 0 pari-2.7.5/src/test/32/nfrootsof10000644000175000017500000000014311636712103015121 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 46 46 18 2 2 2 Total time spent: 58691 pari-2.7.5/src/test/32/lift0000644000175000017500000000076012366172547014001 0ustar billbilllift 1 2 x 3 8/3 x x + 2 (a)->lift(a,'x) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) x Mod(1, 3)*x + Mod(2, 3) (a)->lift(a,'y) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) Mod(x, x^2) Mod(1, 3)*x + Mod(2, 3) (a)->lift(a,'z) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) Mod(x, x^2) Mod(1, 3)*x + Mod(2, 3) centerlift 1 -1 x 3 -1/3 x x - 1 liftall 1 2 x 3 8/3 x x + 2 liftint 1 2 x 3 8/3 Mod(x, x^2) x + 2 liftpol 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) x Mod(1, 3)*x + Mod(2, 3) Total time spent: 4 pari-2.7.5/src/test/32/mathnf0000644000175000017500000000231112366172547014312 0ustar billbill echo = 1 (on) ? mathnf([0,2]) [2] ? mathnf([0,2],1) [Mat(2), [1, 0; 0, 1]] ? mathnf([0,x]) [x] ? mathnf([0,x],1) [Mat(x), [1, 0; 0, 1]] ? mathnf([x,x^2+1;x^3+x+1,x+2]*Mod(1,5)) [Mod(1, 5)*x^5 + Mod(2, 5)*x^3 + Mod(4, 5)*x + Mod(1, 5) Mod(4, 5)*x^4 + Mod (2, 5)*x^3 + Mod(4, 5)*x^2 + Mod(3, 5)*x] [0 1] ? v=[116085838,181081878,314252913,10346840]; ? [H,U]=mathnf(v,1);[v*U,norml2(U)] [[0, 0, 0, 1], 2833319] ? [H,U]=mathnf(v,5);[v*U,norml2(U)] [[0, 0, 0, 1], 765585180708864230567243002686057927228240493] ? mathnf([]) [;] ? mathnf([],1) [[;], [;]] ? mathnf([;]) [;] ? mathnf([;],1) [[;], [;]] ? mathnfmodid(matrix(0,2),[]) [;] ? mathnfmodid([0,7;-1,0;-1,-1],[6,2,2]) [2 1 1] [0 1 0] [0 0 1] ? matsolvemod([;],[]~,[]~,1) 0 ? matsolvemod([;],[],[]~,1) *** at top-level: matsolvemod([;],[],[ *** ^-------------------- *** matsolvemod: incorrect type in gaussmodulo (t_VEC). ? matsolvemod([;],[]~,[],1) *** at top-level: matsolvemod([;],[]~, *** ^-------------------- *** matsolvemod: incorrect type in gaussmodulo (t_VEC). ? matsolvemod([;],1,1,1) 0 ? matsolvemod([1,2;3,4],1,2,1) [[0, 0]~, [-1, 0; 0, 1]] ? print("Total time spent: ",gettime); Total time spent: 0 pari-2.7.5/src/test/32/env0000644000175000017500000000006612366172547013632 0ustar billbill"/root" 1 "XXX, YYY, XXX" "XXX" 0 Total time spent: 0 pari-2.7.5/src/test/32/thue0000644000175000017500000000133712434213504013772 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). [] [[0, -1]] [[-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]] [] [[5, 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]] [[0, 3], [3, -276], [3, 0]] [[0, 3], [3, 0], [19, 2], [27, 3]] [[-1, 1], [1, 1], [-1, -1], [1, -1]] [] [[0, 0]] [[0, 0]] [[-1, -1], [1, -1], [-1, 1], [1, 1]] [] [[0, 1], [1, -537825], [1, 1], [537824, 1], [1, 0]] [[44, -131]] [[4181, 6765], [10946, 17711], [-17711, -28657], [2584, 4181]] [] [] [[0, 1]] [] Total time spent: 2512 pari-2.7.5/src/test/32/genus2red0000644000175000017500000011667212413013143014726 0ustar billbillType: [I{0-0-0}], p. 155 [1, Mat([7, 0]), x^5 + x^3 - 2*x^2 + 3*x + 1, [7, [1, []], ["(tame) [I{0-0-0 }] page 155", []]]] Type: [I*{0-0-0}], p. 155 [2401, Mat([7, 4]), 7*x^5 + 7*x^3 - 14*x^2 + 21*x + 7, [7, [1, []], ["(tame) [I*{0-0-0}] page 155", [2, 2, 2, 2]]]] Type: [II], p. 155 [49, Mat([7, 2]), x^6 + 28*x^4 - 49*x^2 + 343, [7, [1, []], ["(tame) [II] pa ge 155", []]]] [9, Mat([3, 2]), x^6 + 12*x^4 - 9*x^2 + 27, [3, [1, []], ["[II] page 155", [ ]]]] Type: [III], p. 155 [2401, Mat([7, 4]), x^6 + 28*x^3 + 49, [7, [1, []], ["[III] page 155", [3, 3 ]]]] Type: [IV], p. 155 [2401, Mat([7, 4]), 7*x^6 + 245*x^3 + 343, [7, [4, []], ["[III*{3}] page 184 ", []]]] Type: [V], p. 156 [2401, Mat([7, 4]), x^6 + 7, [7, [1, []], ["[V] page 156", [3]]]] Type: [V*], p. 156 [2401, Mat([7, 4]), 7*x^6 + 49, [7, [1, []], ["[V*] page 156", [3]]]] Type: [VI], p. 156 [2401, Mat([7, 4]), x^5 + 21*x^3 + 49*x, [7, [1, []], ["(tame) [VI] page 156 ", [2, 2]]]] Type: [VII], p. 156 [2401, Mat([7, 4]), x^5 + 7*x, [7, [1, []], ["[VII] page 156", [2]]]] Type: [VII*], p. 156 [2401, Mat([7, 4]), 7*x^5 + 49*x, [7, [1, []], ["[VII*] page 156", [2]]]] Type: [VIII-1], p. 156 [2401, Mat([7, 4]), x^5 + 7, [7, [1, []], ["[VIII-1] page 156", []]]] Type: [VIII-2], p. 157 [2401, Mat([7, 4]), x^5 + 343, [7, [1, []], ["[VIII-2] page 157", []]]] Type: [VIII-3], p. 157 [2401, Mat([7, 4]), 7*x^5 + 343, [7, [1, []], ["[VIII-3] page 157", []]]] Type: [VIII-4], p. 157 [2401, Mat([7, 4]), 7*x^6 + 49*x, [7, [1, []], ["[VIII-4] page 157", []]]] Type: [IX-1], p. 157 [2401, Mat([7, 4]), x^5 + 49, [7, [1, []], ["[IX-1] page 157", [5]]]] Type: [IX-2], p. 157 [2401, Mat([7, 4]), x^6 + 7*x, [7, [1, []], ["[IX-2] page 157", [5]]]] Type: [IX-3], p. 157 [2401, Mat([7, 4]), 7*x^5 + 49, [7, [1, []], ["[IX-3] page 157", [5]]]] Type: [IX-4], p. 158 [2401, Mat([7, 4]), x^6 + 49*x, [7, [1, []], ["[IX-4] page 158", [5]]]] Type: [I{0}-I{0}-10], p. 158 [1, Mat([7, 0]), 508021860739623365322188197652216501772434524836001*x^6 + 5 080218607396233653221881976522165257101144141196013*x^4 + 508021860739623365 322188197652216501772434524836002*x^3 + 2393767988928360030*x^2 + 2393767988 92836013*x + 1, [7, [5, [Mod(2, 7), Mod(5, 7)]], ["(tame) [I{0}-I{0}-10] pag e 158", []]]] [1, Mat([3, 0]), 42391158275216203514294433201*x^6 + 42391158275216203510807 648800*x^4 + 42391158275216203514294433202*x^3 - 3486784401*x^2 - 3486784400 *x + 1, [3, [5, [Mod(0, 3), Mod(1, 3)]], ["[I{0}-I{0}-10] page 158", []]]] Type: [I{0}*-I{0}*-10], p. 158 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 24893071176241544900787221684958 6097837332861811440640*x^4 + 17425149823369080494630608325843912106803538735 9467068*x^3 - 6551443127975383932596363883779423529*x^2 + 410531210101213754 7000*x + 66885, [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [I*{0}-I*{0}-10] p age 158", [2, 2, 2, 2]]]] [81, Mat([3, 4]), 42391158275216203514294433201*x^6 - 36472996377170786403*x ^5 + 381520424476945831607729192403*x^4 + 1144561273102580527491412618835*x^ 3 - 984770902371897590535*x^2 - 564859072647*x + 945, [3, [5, [Mod(0, 3), Mo d(0, 3)]], ["[I*{0}-I*{0}-10] page 158", [2, 2, 2, 2]]]] Type: [I{0}-I{0}*-10], p. 159 [49, Mat([7, 2]), 508021860739623365322188197652216501772434524836001*x^6 + 248930711762415449007872216849586086107869716062476493*x^4 + 174251498233690 814305510551794710260107945042018748344*x^3 + 117294631457489641470*x^2 + 82 106242020242749519*x + 343, [7, [5, [Mod(2, 7), Mod(5, 7)]], ["(tame) [I{0}- I*{0}-10] page 159", [2, 2]]]] [9, Mat([3, 2]), 42391158275216203514294433201*x^6 + 38152042447694583162516 3114408*x^4 + 1144561273430837494885949696428*x^3 - 31381059609*x^2 - 941431 78818*x + 27, [3, [5, [Mod(0, 3), Mod(1, 3)]], ["[I*{0}-I{0}-10] page 159", [2, 2]]]] Type: [2I{0}-11], p. 159 [49, Mat([7, 2]), x^6 - 21*x^4 + 574743694141699243350*x^2 + 265173084183644 7612787128678837, [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [2I{0}-11] page 159", []]]] [9, Mat([3, 2]), x^6 - 9*x^4 - 282429536454*x^2 + 150095482585608537, [3, [5 , [Mod(0, 3), Mod(0, 3)]], ["[2I{0}-11] page 159", []]]] Type: [2I{0}*-10], p. 159 [2401, Mat([7, 4]), x^6 - 21*x^4 + 82106242020242749176*x^2 + 54116956037952 111668959660849*x - 574743694141699243546, [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [2I*{0}-10] page 159", [2, 2]]]] Type: [2I{0}*-10], p. 159 [2401, Mat([7, 4]), x^6 - 21*x^4 + 82106242020242749176*x^2 + 54116956037952 111668959660849*x - 574743694141699243546, [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [2I*{0}-10] page 159", [2, 2]]]] Type: [I{0}-II-10], p. 159 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + x^3 + 44567640326363195900190045974568007*x^2 + 1675637592249852021* x + 7, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-II-10] page 159", []] ]] Type: [I{0}-II*-10], p. 160 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + x^3 + 107006904423598033356356300384937784807*x^2 + 4023205858991894 702421*x + 16807, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-II*-10] pa ge 160", []]]] [243, Mat([3, 5]), 12157665459056928801*x^5 + 10460353203*x^4 + x^3 + 295431 2706550833698643*x^2 + 2541865828329*x + 243, [3, [5, [Mod(0, 3), Mod(0, 3)] ], ["[II*-I{0}-10] pages 159-177", []]]] Type: [I{0}-IV-10], p. 160 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + x^3 + 311973482284542371301330321821976049*x^2 + 1172946314574896414 7*x + 49, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-IV-10] page 160", [3]]]] [243, Mat([3, 5]), 12157665459056928801*x^5 + 10460353203*x^4 + x^3 + 109418 989131512359209*x^2 + 94143178827*x + 9, [3, [5, [Mod(0, 3), Mod(0, 3)]], [" [IV-I{0}-10] pages 159-177", [3]]]] Type: [I{0}-IV*-10], p. 160 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + x^3 + 15286700631942576193765185769276826401*x^2 + 57474369414169924 3203*x + 2401, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-IV*-10] page 160", [3]]]] [243, Mat([3, 5]), 12157665459056928801*x^5 + 10460353203*x^4 + x^3 + 984770 902183611232881*x^2 + 847288609443*x + 81, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[IV*-I{0}-10] pages 159-177", [3]]]] Type: [I{0}*-II-10], p. 160 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + x^3 + 2183814375991796599109312252753832343*x^2 + 1172946314574 8964147*x + 7, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-II-10] page 160", [2, 2]]]] [2187, Mat([3, 7]), 109418989131512359209*x^5 + 31381059609*x^4 + x^3 + 3282 56967394537077627*x^2 + 94143178827*x + 3, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[II-I*{0}-10] pages 159-177", [2, 2]]]] Type: [I{0}*-II*-10], p. 160-161 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + x^3 + 5243338316756303634461458718861951455543*x^2 + 2816244101 2943262916947*x + 16807, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-II *-10] page 160", [2, 2]]]] [2187, Mat([3, 7]), 109418989131512359209*x^5 + 31381059609*x^4 + x^3 + 2658 8814358957503287787*x^2 + 7625597484987*x + 243, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[II*-I*{0}-10] pages 159-177", [2, 2]]]] Type: [I{0}*-IV-10], p. 161 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + x^3 + 15286700631942576193765185769276826401*x^2 + 821062420202 42749029*x + 49, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-IV-10] pag e 161", [6, 2]]]] Type: [I{0}*-IV*-10], p. 161 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + x^3 + 749048330965186233494494102694564493649*x^2 + 40232058589 91894702421*x + 2401, [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-IV*-1 0] page 161", [6, 2]]]] Type: [I{0}-III-10], p. 161 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + 44567640326363195900190045974568008*x^3 + 1675637592249852021*x^2 + 7*x, [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I{0}-III-10] page 161", [2]] ]] Type: [I{0}-III*-10], p. 162 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 23937679889283600 3*x^4 + 2183814375991796599109312252753832344*x^3 + 82106242020242749029*x^2 + 343*x, [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I{0}-III*-10] page 162" , [2]]]] Type: [I{0}*-III-10], p. 162 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + 2183814375991796599109312252753832344*x^3 + 1172946314574896414 7*x^2 + 7*x, [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I*{0}-III-10] page 1 62", [2, 2, 2]]]] Type: [I{0}*-III*-10], p. 162 [2401, Mat([7, 4]), 311973482284542371301330321821976049*x^5 + 1675637592249 852021*x^4 + 107006904423598033356356300384937784808*x^3 + 57474369414169924 3203*x^2 + 343*x, [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I*{0}-III*-10] page 162", [2, 2, 2]]]] Type: [2II-10], p. 162 [2401, Mat([7, 4]), x^6 - 21*x^4 + 147*x^2 + 7730993719707444524137094407*x - 343, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2II-10] page 162", []]]] [59049, Mat([3, 10]), x^6 - 9*x^4 + 27*x^2 + 5559060566555523*x - 27, [3, [5 , [Mod(0, 3), Mod(0, 3)]], ["[2II-10] page 162", []]]] Type: [2II*-10], p. 163 [2401, Mat([7, 4]), x^6 - 21*x^4 + 147*x^2 + 378818692265664781682717625943* x - 343, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2II*-10] page 163", []]] ] [59049, Mat([3, 10]), x^6 - 9*x^4 + 27*x^2 + 50031545098999707*x - 27, [3, [ 5, [Mod(0, 3), Mod(0, 3)]], ["[2II*-10] page 163", []]]] Type: [II-II-10], p. 163 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 3556153 025177363557255317383565515512407041673852013*x^3 - 133702920979089587700570 137923704021*x^2 + 1675637592249852021*x + 42, [7, [5, [Mod(0, 7), Mod(0, 7) ]], ["(tame) [II-II-10] page 163", []]]] Type: [II-II*-10], p. 163 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 3556153 025177363557255317383565515512407041673868813*x^3 - 133702920979089587700570 137923704021*x^2 + 1675637592249852021*x + 117642, [7, [5, [Mod(0, 7), Mod(0 , 7)]], ["(tame) [II-II*-10] page 163", []]]] Type: [II*-II*-10], p. 163 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 8538323 413450849900970017037940802745289307058918685613*x^3 - 321020713270794100069 068901154813354421*x^2 + 4023205858991894702421*x + 282458442, [7, [5, [Mod( 0, 7), Mod(0, 7)]], ["(tame) [II*-II*-10] page 163", []]]] Type: [II*-II*-(-1)], p. 163 [2401, Mat([7, 4]), 7*x^6 - 21*x^5 + 21*x^4 + 679*x^3 - 1029*x^2 + 1029*x + 16464, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-II*--1] page 163", []] ]] Type: [II-IV-10], p. 164 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 3556153 025177363557255317383565515512407041673852055*x^3 - 133702920979089587700570 137923704021*x^2 + 1675637592249852021*x + 336, [7, [5, [Mod(0, 7), Mod(0, 7 )]], ["(tame) [II-IV-10] page 164", [3]]]] Type: [II-IV*-10], p. 164 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 3556153 025177363557255317383565515512407041673854407*x^3 - 133702920979089587700570 137923704021*x^2 + 1675637592249852021*x + 16800, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II-IV*-10] page 164", [3]]]] Type: [II*-IV-10], p. 164 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 8538323 413450849900970017037940802745289307058918668855*x^3 - 321020713270794100069 068901154813354421*x^2 + 4023205858991894702421*x + 806736, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-IV-10] page 164", [3]]]] Type: [II*-IV-(-1)], p. 164 [2401, Mat([7, 4]), x^6 + 56*x^3 + 343, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["[ II*-IV-(-1)] page 164", [3]]]] Type: [II*-IV*-10], p. 164-165 [2401, Mat([7, 4]), 174251498233690814305510551794710260107945042018748343*x ^6 - 935920446853627113903990965465928147*x^5 + 1675637592249852021*x^4 + 41 8377847259091645147530834859099334519176045887014771591*x^3 - 22471449928955 58700483482308083693480947*x^2 + 4023205858991894702421*x + 115248, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-IV*-10] page 164", [3]]]] Type: [2IV-10], p. 165 [2401, Mat([7, 4]), x^6 - 21*x^4 + 147*x^2 + 54116956037952111668959660506, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2IV-10] page 165", [3]]]] [59049, Mat([3, 10]), x^6 - 9*x^4 + 27*x^2 + 16677181699666542, [3, [5, [Mod (0, 3), Mod(0, 3)]], ["[2IV-10] page 165", [3]]]] Type: [2IV*-10], p. 165 [2401, Mat([7, 4]), x^6 - 21*x^4 + 147*x^2 + 378818692265664781682717625600, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2IV*-10] page 165", [3]]]] [59049, Mat([3, 10]), x^6 - 9*x^4 + 27*x^2 + 50031545098999680, [3, [5, [Mod (0, 3), Mod(0, 3)]], ["[2IV*-10] page 165", [3]]]] Type: [IV-IV-10], p. 165 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 2489307 1176241544900787221684958608586849291716964097*x^3 - 93592044685362711390399 0965465928147*x^2 + 11729463145748964147*x + 2352, [7, [5, [Mod(0, 7), Mod(0 , 7)]], ["(tame) [IV-IV-10] page 165", [3, 3]]]] Type: [IV-IV*-10], p. 165 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 239376798892836003*x^4 + 2489307 1176241544900787221684958608586849291716966449*x^3 - 93592044685362711390399 0965465928147*x^2 + 11729463145748964147*x + 117600, [7, [5, [Mod(0, 7), Mod (0, 7)]], ["(tame) [IV-IV*-10] page 165", [3, 3]]]] Type: [IV*-IV*-10], p. 166 [2401, Mat([7, 4]), 174251498233690814305510551794710260107945042018748343*x ^6 - 935920446853627113903990965465928147*x^5 + 1675637592249852021*x^4 + 41 8377847259091645147530834859099334519176045887014771549*x^3 - 22471449928955 58700483482308083693480947*x^2 + 4023205858991894702421*x + 14406, [7, [5, [ Mod(0, 7), Mod(0, 7)]], ["(tame) [IV*-IV*-10] page 166", [3, 3]]]] Type: [II-III-10], p. 166 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 15751783840566688010*x^4 - 133702920979089587700570137923704015*x^3 + 167563 7592249852021*x^2 + 42*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [II-III- 10] page 166", [2]]]] Type: [II-III*-10], p. 166 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 17425149823369081430551055179471 0260347321840911584346*x^4 - 6551443127975389797327936758261497023*x^3 + 821 06242020242749029*x^2 + 2058*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [I I-III*-10] page 166", [2]]]] Type: [II*-III-10], p. 166 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 15751783840566688010*x^4 - 133702920979089587700570137923687215*x^3 + 167563 7592249852021*x^2 + 117642*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [II* -III-10] page 166", [2]]]] Type: [II*-III-(-1)], p. 167 [2401, Mat([7, 4]), x^5 + 7*x^3 + 49*x^2 + 343, [7, [5, [Mod(0, 7), Mod(6, 7 )]], ["[II*-III-(-1)] page 167", [2]]]] Type: [II*-III*-10], p. 167 [2401, Mat([7, 4]), 174251498233690814305510551794710260107945042018748343*x ^6 - 935920446853627113903990965465928147*x^5 + 5976826389415594930679011926 5585619218700787004680533670*x^4 - 321020713270794100069068901154813354373*x ^3 + 574743694141699243203*x^2 + 16464*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], [ "(tame) [II*-III*-10] page 167", [2]]]] Type: [IV-III-10], p. 167 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 15751783840566688010*x^4 - 133702920979089587700570137923703973*x^3 + 167563 7592249852021*x^2 + 336*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [IV-III -10] page 167", [6]]]] [2187, Mat([3, 7]), 42391158275216203514294433201*x^6 - 36472996377170786403 *x^5 + 127173474825648610553343652806*x^4 - 109418989131512359201*x^3 + 3138 1059609*x^2 + 24*x, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III-IV-10] pages 160 -174", [6]]]] Type: [IV-III*-10], p. 167 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 17425149823369081430551055179471 0260347321840911584346*x^4 - 6551443127975389797327936758261496981*x^3 + 821 06242020242749029*x^2 + 16464*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [ IV-III*-10] page 167", [6]]]] [2187, Mat([3, 7]), 42391158275216203514294433201*x^6 - 36472996377170786403 *x^5 + 1144561273430837494896410049630*x^4 - 984770902183611232873*x^3 + 282 429536481*x^2 + 216*x, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*-IV-10] pages 160-174", [6]]]] Type: [IV-III*-(-1)], p. 167 [2401, Mat([7, 4]), x^6 + 7*x^4 + 7*x^3 + 49*x, [7, [5, [Mod(0, 7), Mod(6, 7 )]], ["[IV-III*-(-1)] page 167", [6]]]] Type: [IV*-III-10], p. 168 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 15751783840566688010*x^4 - 133702920979089587700570137923701621*x^3 + 167563 7592249852021*x^2 + 16800*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [IV*- III-10] page 168", [6]]]] Type: [IV*-III*-10], p. 168 [2401, Mat([7, 4]), 174251498233690814305510551794710260107945042018748343*x ^6 - 935920446853627113903990965465928147*x^5 + 5976826389415594930679011926 5585619218700787004680533670*x^4 - 321020713270794100069068901154813354415*x ^3 + 574743694141699243203*x^2 + 2058*x, [7, [5, [Mod(0, 7), Mod(6, 7)]], [" (tame) [IV*-III*-10] page 168", [6]]]] Type: [2III-10], p. 168 [2401, Mat([7, 4]), x^6 - 21*x^4 + 3909821048582988049*x^3 + 147*x^2 - 27368 747340080916343*x - 343, [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [2III-10] page 168", [2]]]] [81, Mat([3, 4]), x^6 - 9*x^4 + 31381059609*x^3 + 27*x^2 - 94143178827*x - 2 7, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2III-10] page 168", [2]]]] Type: [2III*-10], p. 168 [2401, Mat([7, 4]), x^6 - 21*x^4 + 27368747340080916343*x^3 + 147*x^2 - 1915 81231380566414401*x - 343, [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [2III*- 10] page 168", [2]]]] [81, Mat([3, 4]), x^6 - 9*x^4 + 94143178827*x^3 + 27*x^2 - 282429536481*x - 27, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2III*-10] page 168", [2]]]] Type: [III-III-10], p. 169 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 16310329704649972017*x^4 - 133702920979089587700570137923704029*x^3 + 558545 8640832840070*x^2 - 56*x, [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [III-III -10] page 169", [2, 2]]]] Type: [III-III*-10], p. 169 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 - 19100417282727083957224305417672003*x^5 + 35561530251773635572553173835655 43120531180647604353*x^4 - 133702920979089587700570137923704365*x^3 + 193256 868972816266422*x^2 - 2408*x, [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [III -III*-10] page 169", [2, 2]]]] Type: [III*-III*-{10}], p. 169 [2401, Mat([7, 4]), 174251498233690814305510551794710260107945042018748343*x ^6 - 935920446853627113903990965465928147*x^5 + 5976826389415594930679011926 5585619222610608053263521719*x^4 - 321020713270794100069068901154813354429*x ^3 + 1915812313805664144010*x^2 - 2744*x, [7, [5, [Mod(6, 7), Mod(6, 7)]], [ "(tame) [III*-III*-10] page 169", [2, 2]]]] Type: [I{9-0-0}], p. 170 [7, Mat([7, 1]), x^5 + 40353610*x^3 + x^2 + 121060821*x + 40353607, [7, [2, [Mod(2, 7)]], ["(tame) [I{9-0-0}] page 170", [9]]]] Type: [I{9}-I{0}-10], p. 170 [7, Mat([7, 1]), 6366805760909027985741435139224001*x^5 - 159584532595224002 *x^4 + 19100417282727083957224305458025611*x^3 + 636680576090902750698783735 3551995*x^2 - 159584532474163178*x + 40353608, [7, [6, [Mod(2, 7)]], ["(tame ) [I{9}-I{0}-10] page 170", [9]]]] [3, Mat([3, 1]), 12157665459056928801*x^5 - 6973568802*x^4 - 121576654590569 09117*x^3 + 12157665466030497603*x^2 - 6973588486*x + 19684, [3, [6, [Mod(0, 3)]], ["(tame) [I{9}-I{0}-10] page 170", [9]]]] Type: [I{0}-I*{9}-10], p. 170 [49, Mat([7, 2]), x^6 + 4*x^5 + 19100417282727083957224307394998728*x^4 + 50 8021860739623479924691894014720245118274940175011*x^3 + 35561530629451293191 48051483501814963799504492542834*x^2 + 1004525211269079266605816908070627976 335864597950580018666977*x + 70316764788835530156201894723072969620825817394 84589084102397, [7, [6, [Mod(2, 7)]], ["(tame) [I*{9}-I{0}-10] page 170", [4 ]]]] [9, Mat([3, 2]), x^6 - 12157665459056751660*x^4 + 42391158250900872596180575 607*x^3 + 127171321168158531362286712374*x^2 + 75094665106723368777956004270 53229*x + 22528399551400256301066821173173441, [3, [6, [Mod(0, 3)]], ["[I*{9 }-I{0}-10] page 170", [4]]]] Type: [I{9}-I{0}*-10], p. 171 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 935920446853627113903990965506281755*x^3 + 218381437599179657565038 5961255904049*x^2 - 54737494674229852310*x + 13841287544, [7, [6, [Mod(2, 7) ]], ["(tame) [I*{0}-I{9}-10] page 170", [18, 2]]]] Type: [I*{9-0-0}], p. 171 [2401, Mat([7, 4]), 7*x^5 + 282475270*x^3 + 7*x^2 + 847425747*x + 282475249, [7, [2, [Mod(2, 7)]], ["(tame) [I*{9-0-0}] page 171", [4, 2, 2]]]] Type: [I*{9}-I{0}*-10], p. 171 [2401, Mat([7, 4]), x^6 + 4*x^5 + 935920446853627113903990967443254872*x^4 + 174251498233690819921033232916472943531890842723624217*x^3 + 12197604894864 56222471317833459850493873847680657395212*x^2 + 3445521474652941218234561596 37489836481536621034944927824583035*x + 241186503225705876208378720213726101 0629601295382324365507824195, [7, [6, [Mod(2, 7)]], ["(tame) [I*{0}-I*{9}-10 ] page 171", [4, 2, 2]]]] Type: [II{9-0}], p. 171 [343, Mat([7, 3]), x^6 - 2*x^5 + 5764823*x^4 - 42*x^3 + 121060891*x^2 - 98*x + 282475298, [7, [2, [Mod(0, 7)]], ["(tame) [II{9-0}] page 171", [36]]]] Type: [II*{9-0}], p. 172 [49, Mat([7, 2]), 7*x^6 - 14*x^5 + 40353761*x^4 - 294*x^3 + 847426237*x^2 - 686*x + 1977327086, [7, [2, [Mod(0, 7)]], ["(tame) [II*{9-0}] page 172", []] ]] Type: [II-I{9}-10], p. 172 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 40353608*x^3 + 44567640326363195900190045974568007*x^2 - 1117091728 166568014*x + 282475256, [7, [6, [Mod(0, 7)]], ["(tame) [II-I{9}-10] page 17 2", [9]]]] Type: [II*-I{9}-10], p. 172 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 40353608*x^3 + 107006904423598033356356300384937784807*x^2 - 268213 7239327929801614*x + 678223089656, [7, [6, [Mod(0, 7)]], ["(tame) [II*-I{9}- 10] page 172", [9]]]] Type: [IV-I{9}-10], p. 173 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 40353608*x^3 + 311973482284542371301330321821976049*x^2 - 781964209 7165976098*x + 1977326792, [7, [6, [Mod(0, 7)]], ["(tame) [IV-I{9}-10] page 173", [9, 3]]]] Type: [IV*-I{9}-10], p. 173 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 40353608*x^3 + 15286700631942576193765185769276826401*x^2 - 3831624 62761132828802*x + 96889012808, [7, [6, [Mod(0, 7)]], ["(tame) [IV*-I{9}-10] page 173", [9, 3]]]] Type: [II-I*{9}-10], p. 173 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 + 25467223043636111942965740556896004*x^5 + 157775381157130877341310732*x^4 + 3556153025177363557255317383565515512407053537812471*x^3 + 178270561305452 783600760183898272028*x^2 + 1104427668099916141389175124*x + 83047723248, [7 , [6, [Mod(0, 7)]], ["(tame) [II-I*{9}-10] page 173", [4]]]] Type: [II*-I*{9}-10], p. 174 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 + 25467223043636111942965740556896004*x^5 + 157775381157130877341310732*x^4 + 8538323413450849900970017037940802745289307070782629271*x^3 + 428027617694 392133425425201539751139228*x^2 + 2651730831107898655475409472724*x + 199397 583518448, [7, [6, [Mod(0, 7)]], ["(tame) [II*-I*{9}-10] page 174", [4]]]] Type: [II*-I*{9}-(-1)], p. 174 [2401, Mat([7, 4]), 7*x^5 - 14*x^4 + 282475256*x^3 + 343*x^2 - 686*x + 13841 287544, [7, [6, [Mod(0, 7)]], ["(tame) [II*-I*{9}--1] page 174", [4]]]] Type: [IV-I*{9}-10], p. 174 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 + 25467223043636111942965740556896004*x^5 + 157775381157130877341310732*x^4 + 24893071176241544900787221684958608586849303580924513*x^3 + 12478939291381 69485205321287287904196*x^2 + 7730993676699412989724225868*x + 581334062736, [7, [6, [Mod(0, 7)]], ["(tame) [IV-I*{9}-10] page 174", [12]]]] Type: [IV*-I*{9}-10], p. 174 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 + 25467223043636111942965740556896004*x^5 + 157775381157130877341310732*x^4 + 1219760487635835700138573862562971820755615305995198865*x^3 + 611468025277 70304775060743077107305604*x^2 + 378818690158271236496487067532*x + 28485369 074064, [7, [6, [Mod(0, 7)]], ["(tame) [IV*-I*{9}-10] page 174", [12]]]] Type: [IV*-I*{9}-(-1)], p. 175 [2401, Mat([7, 4]), 7*x^5 - 14*x^4 + 282475256*x^3 + 49*x^2 - 98*x + 1977326 792, [7, [6, [Mod(0, 7)]], ["(tame) [IV*-I*{9}--1] page 174", [12]]]] [2187, Mat([3, 7]), 3*x^5 - 6*x^4 + 59052*x^3 + 9*x^2 - 18*x + 177156, [3, [ 6, [Mod(0, 3)]], ["[IV*-I*{9}--1] pages 159-177", [12]]]] Type: [IV-II{9}], p. 175 [343, Mat([7, 3]), x^6 - 2*x^5 + 40353608*x^4 + 7*x^3 - 14*x^2 + 282475256*x , [7, [2, [Mod(0, 7)]], ["(tame) [IV-II{9}] page 175", [29]]]] [729, Mat([3, 6]), x^6 - 2*x^5 + 19684*x^4 + 3*x^3 - 6*x^2 + 59052*x, [3, [6 , [Mod(0, 3)]], ["[IV-II{9}] page 175", [29]]]] Type: [IV*-II{9}], p. 175 [343, Mat([7, 3]), x^6 - 2*x^5 + 5764802*x^4 + 49*x^3 - 98*x^2 + 282475298*x , [7, [2, [Mod(0, 7)]], ["(tame) [IV*-II{9}] page 175", [28]]]] [729, Mat([3, 6]), x^6 - 2*x^5 + 6562*x^4 + 9*x^3 - 18*x^2 + 59058*x, [3, [6 , [Mod(0, 3)]], ["[IV*-II{9}] page 175", [28]]]] Type: [IV*-II{0}], p. 175 [343, Mat([7, 3]), 7*x^5 + 49*x^3 + 49*x^2 + 343, [7, [2, [Mod(0, 7)]], ["[I V*-II{0}] page 175", []]]] [729, Mat([3, 6]), 3*x^5 + 9*x^3 + 9*x^2 + 27, [3, [6, [Mod(0, 3)]], ["[IV*- II{0}] page 175", []]]] Type: [II-II*{9}], p. 176 [2401, Mat([7, 4]), x^5 + 282475249*x^3 + 7*x^2 + 1977326743, [7, [2, [Mod(0 , 7)]], ["[II-II*{9}] page 176", [2, 2]]]] [2187, Mat([3, 7]), x^5 + 59049*x^3 + 3*x^2 + 177147, [3, [6, [Mod(0, 3)]], ["[II-II*{9}] page 176", [2, 2]]]] Type: [II*-II*{9}], p. 176 [2401, Mat([7, 4]), 7*x^6 - 14*x^5 + 282475256*x^4 + 49*x^3 - 98*x^2 + 19773 26792*x, [7, [2, [Mod(0, 7)]], ["(tame) [II*-II*{9}] page 176", [2, 2]]]] [2187, Mat([3, 7]), 3*x^6 - 6*x^5 + 59052*x^4 + 9*x^3 - 18*x^2 + 177156*x, [ 3, [6, [Mod(0, 3)]], ["[II*-II*{9}] page 176", [2, 2]]]] Type: [III-I{9}-10], p. 176 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 44567640326363195900190046014921615*x^3 - 1117091728166568014*x^2 + 282475256*x, [7, [6, [Mod(6, 7)]], ["(tame) [III-I{9}-10] page 176", [18]]] ] [27, Mat([3, 3]), 12157665459056928801*x^5 - 6973568802*x^4 + 36472996377170 806087*x^3 - 20920706406*x^2 + 59052*x, [3, [6, [Mod(0, 3)]], ["[III-I{9}-10 ] pages 159-177", [18]]]] Type: [III*-I{9}-10], p. 176 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 - 1595845325952240 02*x^4 + 2183814375991796599109312252794185951*x^3 - 54737494680161832686*x^ 2 + 13841287544*x, [7, [6, [Mod(6, 7)]], ["(tame) [III*-I{9}-10] page 176", [18]]]] [27, Mat([3, 3]), 12157665459056928801*x^5 - 6973568802*x^4 + 32825696739453 7097311*x^3 - 188286357654*x^2 + 531468*x, [3, [6, [Mod(0, 3)]], ["[III*-I{9 }-10] pages 159-177", [18]]]] Type: [III-I*{9}-10], p. 177 [2401, Mat([7, 4]), x^6 + 4*x^5 + 44567640326363195900190047951894732*x^4 + 267405841958179175401140283756715034*x^3 + 881247867777497128998513653865824 60699453771*x^2 + 528748722538339171106362420127476948226402066*x - 61687350 9628062366290756156815389740634465608, [7, [6, [Mod(6, 7)]], ["(tame) [III-I *{9}-10] page 177", [4, 2]]]] [81, Mat([3, 4]), x^6 + 36472996377170963544*x^4 + 72945992754341572814*x^3 + 6460972470237541785510147*x^2 + 12922163778453346599281658*x - 19383245667 680019897328164, [3, [6, [Mod(0, 3)]], ["[I*{9}-III-10] pages 161-177", [4, 2]]]] Type: [III*-I*{9}-10], p. 177 [2401, Mat([7, 4]), x^6 + 4*x^5 + 2183814375991796599109312254731159068*x^4 + 13102886255950779594655873524432301050*x^3 + 43181145521097359320927169039 42542282683541067*x^2 + 25908687404378619384211758586246368564860027954*x - 30226801971775055948247051683954096626707029144, [7, [6, [Mod(6, 7)]], ["(ta me) [III*-I*{9}-10] page 177", [4, 2]]]] [81, Mat([3, 4]), x^6 + 328256967394537254768*x^4 + 656513934789074155262*x^ 3 + 58148752232137876078094403*x^2 + 116299474006080119382197514*x - 1744492 11009120179071701948, [3, [6, [Mod(0, 3)]], ["[I*{9}-III*-10] pages 162-177" , [4, 2]]]] Type: [III*-I*{9}-(-1)], p. 177 [2401, Mat([7, 4]), 7*x^5 - 14*x^4 + 282475305*x^3 - 98*x^2 + 1977326792*x, [7, [6, [Mod(6, 7)]], ["(tame) [III*-I*{9}--1] page 177", [4, 2]]]] Type: [III-II{9}], p. 177 [343, Mat([7, 3]), x^6 - 2*x^5 + 40353608*x^4 + 7*x^2 - 14*x + 282475256, [7 , [2, [Mod(6, 7)]], ["(tame) [III-II{9}] page 177", [19]]]] Type: [III*-II{9}], p. 178 [343, Mat([7, 3]), x^6 - 2*x^5 + 5764802*x^4 + 343*x^2 - 686*x + 1977327086, [7, [2, [Mod(6, 7)]], ["(tame) [III*-II{9}] page 178", [19]]]] Type: [III*-II{0}], p. 178 [343, Mat([7, 3]), 7*x^6 + 49*x^4 + 49*x^2 + 343, [7, [2, [Mod(6, 7)]], ["(t ame) [III*-II{0}] page 178", []]]] Type: [III-II*{9}], p. 178 [2401, Mat([7, 4]), x^6 + 282475249*x^4 + 7*x^2 + 1977326743, [7, [2, [Mod(6 , 7)]], ["(tame) [III-II*{9}] page 178", [8]]]] Type: [III*-II*{9}], p. 178 [2401, Mat([7, 4]), 282475249*x^6 + 7*x^4 + 1977326743*x^2 + 49, [7, [2, [Mo d(6, 7)]], ["(tame) [III*-II*{9}] page 178", [8]]]] Type: [I{9-8-0}], p. 179 [49, Mat([7, 2]), x^5 + x^4 + 46118407*x^3 + 34588805*x^2 + 232630473633600* x - 232630554340814, [7, [3, []], ["(tame) [I{8-9-0}] page 179", [72]]]] Type: [I{9}-I{8}-10}], p. 179 [49, Mat([7, 2]), 6366805760909027985741435139224001*x^5 + 63668057609090278 26156902543999999*x^4 + 256923577521058878088611317639703031862407*x^3 + 256 923577521058871648799965597876173411195*x^2 - 6439811511393728899334400*x + 232630554340814, [7, [7, []], ["(tame) [I{8}-I{9}-10] page 179", [72]]]] Type: [I*{9-8-0}], p. 180 [2401, Mat([7, 4]), 7*x^5 + 7*x^4 + 322828849*x^3 + 242121635*x^2 + 16284133 15435200*x - 1628413880385698, [7, [3, []], ["(tame) [I*{8-9-0}] page 180", [4, 2, 2]]]] [81, Mat([3, 4]), 3*x^5 + 3*x^4 + 78729*x^3 + 39363*x^2 + 387361440*x - 3874 79538, [3, [3, []], ["(tame) [I*{8-9-0}] page 180", [4, 2, 2]]]] Type: [I*{9}-I*{8}-10], p. 180 [2401, Mat([7, 4]), 508021860739623365322188197652216501772434524836001*x^6 + 3556153025177363582722540427201627455372782230748011*x^5 + 100452521126907 9039999221712767258830172664699912235178878009*x^4 + 70316764788835533303515 71935604422778407017230014542438128339*x^3 + 3524991484034604193284089402685 37457526303138*x^2 + 311973470135837957969478408827349338*x + 23458926374545 651500, [7, [7, []], ["(tame) [I*{8}-I*{9}-10] page 180", [4, 2, 2]]]] Type: [I{9}-I*{8}-10], p. 180 [343, Mat([7, 3]), 6366805760909027985741435139224001*x^5 + 4456764032636319 5740605513379344005*x^4 + 1798465042647412146620279223477921223036843*x^3 + 12589255298531884981263281802603029551507501*x^2 - 3155507640582927177622370 94*x + 79792268274938744, [7, [7, []], ["(tame) [I*{8}-I{9}-10] page 180", [ 18, 2]]]] [27, Mat([3, 3]), 12157665459056928801*x^5 + 36472996370197217601*x^4 + 7178 97987691831668083527*x^3 + 2153693962663775502180501*x^2 - 1235345630247378* x + 3486961548, [3, [7, []], ["[I*{8}-I{9}-10] page 180", [18, 2]]]] Type: [2I{8}-10], p. 181 [343, Mat([7, 3]), x^6 + 1977326722*x^4 + 9387480337620071731394*x^2 + 18562 115855305211939015772541728, [7, [7, []], ["(tame) [2I{8}-10] page 181", [8] ]]] [27, Mat([3, 3]), x^6 + 177138*x^4 + 2541864765474*x^2 + 450276280295106672, [3, [7, []], ["[2I{8}-10] page 181", [8]]]] Type: [2I{9}-10}], p. 181 [343, Mat([7, 3]), x^6 + 1977326722*x^4 + 9387480337647754305649*x^3 - 27682 574255*x^2 + 18562115855305211938918883531664*x + 96889010064, [7, [7, []], ["(tame) [2I{9}-10] page 181", [9]]]] Type: [2I{8}-0], p. 181 [343, Mat([7, 3]), x^6 - 7*x^4 + 117600*x^2 + 823886, [7, [3, []], ["(tame) [2I{8}-0] page 181", [8]]]] Type: [2I{9}-0], p. 181 [343, Mat([7, 3]), x^6 - 7*x^4 + 117649*x^3 - 49*x^2 + 823543*x + 343, [7, [ 3, []], ["(tame) [2I{9}-0] page 181", [9]]]] Type: [2I*{8}-10}], p. 181 [2401, Mat([7, 4]), x^6 + 1977326743*x^5 - 21*x^4 - 27682574402*x^3 + 657123 62363534280139690*x^2 + 129934811447123020117269034708856*x - 45998653654473 9960977144, [7, [7, []], ["(tame) [2I*{8}-10] page 181", [2, 2]]]] [81, Mat([3, 4]), x^6 + 177147*x^5 - 9*x^4 - 1062882*x^3 + 7625597485014*x^2 + 1350851717674586412*x - 22876792454988, [3, [7, []], ["[2I*{8}-10] pages 159, 181", [2, 2]]]] Type: [2I*{9}-10}], p. 181 [2401, Mat([7, 4]), x^6 + 1977326743*x^5 - 21*x^4 + 65712362363506597565141* x^3 + 129934811447123020117172145698596*x^2 - 459986536544643071966394*x - 3 43, [7, [7, []], ["(tame) [2I*{9}-10] page 181", [4]]]] Type: [II{9-8}], p. 182 [343, Mat([7, 3]), x^6 - 2*x^5 + 46118416*x^4 - 80707228*x^3 + 2326308771696 77*x^2 - 564950498*x + 1628413880385698, [7, [3, []], ["[II{9-8}] page 182", [36]]]] [27, Mat([3, 3]), x^6 - 2*x^5 + 26248*x^4 - 39372*x^3 + 129238581*x^2 - 1180 98*x + 387479538, [3, [3, []], ["[II{9-8}] page 182", [36]]]] Type: [III{8}], p. 182 [2401, Mat([7, 4]), 2402*x^5 - 14*x^3 + 49*x, [7, [3, []], ["(tame) [III{8}] page 182", [2, 2]]]] Type: [III{9}], p. 182 [2401, Mat([7, 4]), x^5 + 16807*x^4 - 14*x^3 + 49*x, [7, [3, []], ["(tame) [ III{9}] page 182", [4]]]] Type: [I{9-8-5}], pp. 182-183 [49, Mat([7, 2]), x^6 - 6*x^5 + 46135228*x^4 - 265214472*x^3 + 2334061737433 69*x^2 - 931878986337810*x + 3910752249023424154, [7, [4, []], ["(tame) [I{5 -8-9}] page 182", [157]]]] Type: [I*{9-8-5}], pp. 183 [2401, Mat([7, 4]), 7*x^6 - 42*x^5 + 322946596*x^4 - 1856501304*x^3 + 163384 3216203583*x^2 - 6523152904364670*x + 27375265743163969078, [7, [4, []], ["( tame) [I*{5-8-9}] page 183", [4, 4]]]] Type: [II{9-8}], p. 183 [343, Mat([7, 3]), x^6 - 2*x^5 + 5764788*x^4 + 28*x^3 - 80589530*x^2 - 23539 6*x + 678505665796, [7, [4, []], ["(tame) [II{9-8}] page 183", [44]]]] [27, Mat([3, 3]), x^6 - 2*x^5 + 6556*x^4 + 12*x^3 - 38634*x^2 - 1476*x + 484 2756, [3, [4, []], ["(tame) [II{9-8}] page 183", [44]]]] Type: [II{9-9}], p. 183 [343, Mat([7, 3]), x^6 - 2*x^5 + 5764788*x^4 + 117677*x^3 - 80942477*x^2 + 6 78223190400*x + 282475298, [7, [4, []], ["(tame) [II{9-9}] page 183", [45]]] ] [27, Mat([3, 3]), x^6 - 2*x^5 + 6556*x^4 + 741*x^3 - 40821*x^2 + 4783680*x + 59058, [3, [4, []], ["(tame) [II{9-9}] page 183", [45]]]] Type: [II*{9-8}], p. 184 [343, Mat([7, 3]), 7*x^6 - 14*x^5 + 40353516*x^4 + 196*x^3 - 564126710*x^2 - 1647772*x + 4749539660572, [7, [4, []], ["(tame) [II*{9-8}] page 184", [8]] ]] Type: [II*{9-9}], p. 184 [343, Mat([7, 3]), 7*x^6 - 14*x^5 + 40353516*x^4 + 823739*x^3 - 566597339*x^ 2 + 4747562332800*x + 1977327086, [7, [4, []], ["(tame) [II*{9-9}] page 184" , [9]]]] Type: [III{12}], p. 184 [2401, Mat([7, 4]), x^6 - 14*x^3 + 117698, [7, [4, []], ["[III{12}] page 184 ", [3, 3]]]] [59049, Mat([3, 10]), x^6 - 6*x^3 + 738, [3, [4, []], ["[III{12}] page 184", [3, 3]]]] Type: [III{13}], p. 184 [2401, Mat([7, 4]), x^6 - 14*x^3 + 117649*x + 49, [7, [4, []], ["[III{13}] p age 184", [9]]]] [59049, Mat([3, 10]), x^6 - 6*x^3 + 729*x + 9, [3, [4, []], ["[III{13}] page 184", [9]]]] Type: [III{14}], p. 184 [2401, Mat([7, 4]), x^6 - 14*x^3 + 117649*x^2 + 49, [7, [4, []], ["[III{14}] page 184", [9]]]] [59049, Mat([3, 10]), x^6 - 6*x^3 + 729*x^2 + 9, [3, [4, []], ["[III{14}] pa ge 184", [9]]]] Type: [III*{6}], p. 184 [2401, Mat([7, 4]), 7*x^6 - 98*x^3 + 17150, [7, [4, []], ["[III*{6}] page 18 4", []]]] [59049, Mat([3, 10]), 3*x^6 - 18*x^3 + 270, [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*{6}] page 184", []]]] Type: [III*{7}], p. 184 [2401, Mat([7, 4]), 7*x^6 - 98*x^3 + 16807*x + 343, [7, [4, []], ["[III*{7}] page 184", []]]] [59049, Mat([3, 10]), 3*x^6 - 18*x^3 + 243*x + 27, [3, [5, [Mod(0, 3), Mod(0 , 3)]], ["[III*{7}] page 184", []]]] Type: [III{8}], p. 184 [2401, Mat([7, 4]), x^6 - 14*x^3 + 2401*x^2 + 49, [7, [4, []], ["[III{8}] pa 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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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) [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 pari-2.7.5/src/test/32/op0000644000175000017500000000006012366172547013452 0ustar billbill2 3 1 10 2 [2, 3, 1, 10, 2] Total time spent: 0 pari-2.7.5/src/test/32/io0000644000175000017500000000017712366172547013454 0ustar billbill["123", "456", "a7b", "\\frac{1}{2}"] [1, 3] 1 setting x setting F setting del ()->system(Str("rm -f ",F)) Total time spent: 4 pari-2.7.5/src/test/32/factorint0000644000175000017500000000025612314242551015016 0ustar billbill [ -1 1] [ 3 5] [ 73 1] [ 181 1] [ 223 1] [ 293 2] [ 4157 2] [112573 1] [281191 1] [ 2 1] [ 397 1] [27031 1] [32203 1] Total time spent: 8 pari-2.7.5/src/test/32/qfisom0000644000175000017500000000103012366172547014330 0ustar billbill[2, [Mat(-1)]] 78382080 78382080 78382080 78382080 339738624 339738624 339738624 339738624 OK OK OK OK "Group([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]], [[0, 0, 0, 1], [0, 1, 1, 0], [0, -1, 0, 0], [1, -1, -1, 0]], [[-1, 0, 0, 0], [0, 0, -1, 1], [-1, 0, 1, 0], [-1, 1, 1, 0]])" "MatrixGroup<4, Integers() |[[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0 , 0, 0, -1]], [[0, 0, 0, 1], [0, 1, 1, 0], [0, -1, 0, 0], [1, -1, -1, 0]], [ [-1, 0, 0, 0], [0, 0, -1, 1], [-1, 0, 1, 0], [-1, 1, 1, 0]]>" Total time spent: 876 pari-2.7.5/src/test/32/trans0000644000175000017500000006641612366172547014204 0ustar billbill realprecision = 2003 significant digits (2000 digits displayed) echo = 1 (on) ? abs(-0.01) 0.01000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000 ? agm(1,2) 1.45679103104690686918643238326508197497386394322130559079417238326792645458 0250900257473712818448444328189401816036799935576243074340124511691213249952 2793768970211976726893728266666782707432902072384564600963133367494416649516 4008269322390862633767383824102548872626451365906604088758851004667281309474 3978935512911720175447186956416035641113070606125170400972745374521370401420 1441576823232389645029091322392292018630204591966775362115295609984320494009 6186133886391108403038148862815907317011423554730230353362620898683561308007 5985703121250813571733533606272496417145565136129415437696905495272776402217 1898328404019382434954163396634111712470749200493994758236553202742331569542 1876892595105619103413471250457295583940482770732998417330233202020190654108 3764475690954512308594220997449412380273230046465841574004772512701790771147 6178286660643441589473410355454995401702603050129297014707762364655074858504 2893120294754259839628734570376126531045680923276419320475962493117272367678 4849010063883831645335627155765372880260543270126668904548807658246837332956 7456063204392060008273159252979241205175727929568980698371820180811180125021 3108997246951100317036787543001787446227930192106015685776149083936743191510 5478717272782446538831715921363968336746689231345994523668360452657260101103 3970534995271323625630073974543738138730451563908543487241207008447748794693 7515044344604858428093017239592603673212918887571985640286492629881099516041 7385214470404976503137921156910217010840121652176385776278443131535045190731 0748437504378670908384466987679450508904899924299954903140622820681590930451 6140452345824869722715061998188837843566441517471116059500690242314345907596 6810454416997061373268370421830924936517791683419258027937814913005585514983 9054216129918366396073532425917284089191304056017436113358867622552811309835 6883812066118653768412057434259281956810028485877428124011968982035483804304 1113162808407169939503577633814675423251711145297625856010709698328986771681 3002707534621244314382491 ? agm(1+O(7^5),8+O(7^5)) 1 + 4*7 + 6*7^2 + 5*7^3 + 2*7^4 + O(7^5) ? 4*arg(3+3*I) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 6237996274956735188575272489122793818301194912983367336244065664308602139494 6395224737190702179860943702770539217176293176752384674818467669405132000568 1271452635608277857713427577896091736371787214684409012249534301465495853710 5079227968925892354201995611212902196086403441815981362977477130996051870721 1349999998372978049951059731732816096318595024459455346908302642522308253344 6850352619311881710100031378387528865875332083814206171776691473035982534904 2875546873115956286388235378759375195778185778053217122680661300192787661119 5909216420198938095257201065485863278865936153381827968230301952035301852968 9957736225994138912497217752834791315155748572424541506959508295331168617278 5588907509838175463746493931925506040092770167113900984882401285836160356370 7660104710181942955596198946767837449448255379774726847104047534646208046684 2590694912933136770289891521047521620569660240580381501935112533824300355876 4024749647326391419927260426992279678235478163600934172164121992458631503028 6182974555706749838505494588586926995690927210797509302955321165344987202755 9602364806654991198818347977535663698074265425278625518184175746728909777727 9380008164706001614524919217321721477235014144197356854816136115735255213347 5741849468438523323907394143334547762416862518983569485562099219222184272550 2542568876717904946016534668049886272327917860857843838279679766814541009538 8378636095068006422512520511739298489608412848862694560424196528502221066118 6306744278622039194945047123713786960956364371917287467764657573962413890865 8326459958133904780275901 ? bernreal(12) -0.2531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 355311355311355311355311355 ? bernvec(6) [1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730] ? eta(q) 1 - q - q^2 + q^5 + q^7 - q^12 - q^15 + O(q^17) ? gammah(10) 1133278.38894878556733457416558889247556029830827515977660872341452948339005 6004153717630538727607290658350271700893237334889580173178076577597995379664 6009714415152490764416630481375706606053932396039541459764525989187023837695 1671610855238044170151137400635358652611835795089229729903867565432085491785 4385740637379886563030379410949122020517030255827739818376409926875136586189 2723863412249690833216320407918186480305202146014474770321625907339955121137 5592642390902407584016964257200480120814533383602757695668466603948271024098 9327940404023866529740516995285324916879158647845355052036653927090566136730 0094575478250332011940143726954935586482054200041299507288301750480889450074 6343904971296912338686722783533463981407672637863409944118391772608796763236 9447079178552767334696553209914181695759970997941993901164691598147347830004 4823839605663115658079374350293361148126253885222073444191541294051101114944 2148757269775793389728426903218921936202601614618932645339512192242743521391 3623655029508006651504215607326378350230912034475135438952688674605137188671 8291478726407002040566684129567384943465438236552781293212272474626739330722 3823357944724162685811265841905467657996783321819427448381523647154314724898 8856361879313902224622692050075011483135711717132961476630033785190129658511 7517708668749218485078393526224163290497667641778463362558549256811856160652 4106684792418747471383982225174086085681964985490608637796815226536639176681 1441751691654768874563756211537865821827254193841183086848150171014212517613 4162649414056791266931385305249721381461657257845049119527820872404022311592 3493153739717855496390762049815239940623016182617392553134094087438136687759 5419535805662758475769269988659439227267578534611414012815013931015921875970 6336658641047462598114625941565529553227923237890531007539153745378752638260 5084066808355122734552729235496172099847732335381840125710668124155748264901 6432532465927671474115401431858884909633728259417038958526362232126251606829 1066841997114282966060548 ? Pi 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 6237996274956735188575272489122793818301194912983367336244065664308602139494 6395224737190702179860943702770539217176293176752384674818467669405132000568 1271452635608277857713427577896091736371787214684409012249534301465495853710 5079227968925892354201995611212902196086403441815981362977477130996051870721 1349999998372978049951059731732816096318595024459455346908302642522308253344 6850352619311881710100031378387528865875332083814206171776691473035982534904 2875546873115956286388235378759375195778185778053217122680661300192787661119 5909216420198938095257201065485863278865936153381827968230301952035301852968 9957736225994138912497217752834791315155748572424541506959508295331168617278 5588907509838175463746493931925506040092770167113900984882401285836160356370 7660104710181942955596198946767837449448255379774726847104047534646208046684 2590694912933136770289891521047521620569660240580381501935112533824300355876 4024749647326391419927260426992279678235478163600934172164121992458631503028 6182974555706749838505494588586926995690927210797509302955321165344987202755 9602364806654991198818347977535663698074265425278625518184175746728909777727 9380008164706001614524919217321721477235014144197356854816136115735255213347 5741849468438523323907394143334547762416862518983569485562099219222184272550 2542568876717904946016534668049886272327917860857843838279679766814541009538 8378636095068006422512520511739298489608412848862694560424196528502221066118 6306744278622039194945047123713786960956364371917287467764657573962413890865 8326459958133904780275901 ? precision(Pi,38) 3.14159265358979323846264338327950288420 ? sqr(1+O(2)) 1 + O(2^3) ? 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) ? teichmuller(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) ? \p500 realprecision = 500 significant digits ? Catalan 0.91596559417721901505460351493238411077414937428167213426649811962176301977 6254769479356512926115106248574422619196199579035898803325859059431594737481 1584069953320287733194605190387274781640878659090247064841521630002287276409 4238825995774150881639747025248201156070764488380787337048990086477511322599 7134340748540755323076856533576809583526021938232395080072068035576104823573 3942319149829836189977069036404180862179411019175327431499782339761055122477 9530324875371878665828082360570225594194818097 ? Euler 0.57721566490153286060651209008240243104215933593992359880576723488486772677 7664670936947063291746749514631447249807082480960504014486542836224173997644 9235362535003337429373377376739427925952582470949160087352039481656708532331 5177661152862119950150798479374508570574002992135478614669402960432542151905 8775535267331399254012967420513754139549111685102807984234877587205038431093 9973613725530608893312676001724795378367592713515772261027349291394079843010 3417771778088154957066107501016191663340152279 ? acos(0.5) 1.04719755119659774615421446109316762806572313312503527365831486410260546876 2069666209344941780705689327382695504427435549031281536516860743908453136042 8270391500947009006461737018532148743163183101273214762703252219778153761585 4941126226105509040063638188285564115344953681810888273779786908674971375790 8195668868771862724960506973654276418030571788122630863453337110176849606822 1737947156506471705364776857567885865306510307287057939775372643683728493581 541266542498557839619175749637426460610039831 ? acosh(3) 1.76274717403908605046521864995958461805632065652327082150659121730675436844 4052175667413783820512085713479632384212984377524145023953183875054510925531 5808184431573607257943924806147148192510979557431265247356130135260657908083 2711638011905460870335948934683023103172356012785221262668194525145789831496 9445764001529311893860982812579887622449034763169345542526389217689105106337 1787365189299048490338319777210134365908031791918295896639410019154526845141 480345838118685682417318463628901744528191443 ? 3*asin(sqrt(3)/2) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 623799627495673518857527248912279381830119491 ? asinh(0.5) 0.48121182505960344749775891342436842313518433438566051966101816884016386760 8221774412009429122723474997231839958293656411272568323726737622753059241864 4097541824170072118371502238239374691872752432791930187970790035617267969445 4575230534543418876528553256490207399693496618755630102123996367930820635997 7988509980156825797852649328666651116241713808272592788479026096533113247227 5149314064985088932176366002566661953210679681757661847307351598603984845754 5412056323413570047800639487224315261789680045 ? 3*atan(sqrt(3)) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 623799627495673518857527248912279381830119491 ? atanh(0.5) 0.54930614433405484569762261846126285232374527891137472586734716681874714660 9304483436807877406866044393985014532978932871184002112965259910526400935383 6387053015813845916906835896868494221804799518712851583979557605727959588753 3567352747008338779011110158512647344878034505326075282143406901815868664928 8891183495827396065909074510015051911815061124326374099112995548726245448229 0267335044229825428742220595094285438237474335398065429147058010830605920007 0491275719597438444683992471511278657676648427 ? besseljh(1,1) 0.24029783912342701089584304474193368045758480608072900860700721913956804181 9821642483230581867706826873304134469286897059613333800107373387969440858132 2409671228346463513063730101700769785661236389472736777787130860593313537501 4950471611773181090861874975058165031596147120593670107339079838226694509538 1174862561382806604491442967609698710345402983618630021989455840750069855186 9089492304665506543890102558566214670131694260158621630986009048855189842820 0103186464147214505293464124112486584095535336 ? cos(1) 0.54030230586813971740093660744297660373231042061792222767009725538110039477 4471764517951856087183089343571731160030089097860633760021663456406512265417 3185847179711644744794942331179245513932543359435177567028925963757361543275 4964175449177511513122273010063135707823223677140151746899593667873067422762 0245077637440675874981617842720216455851115632968890571081242729331698685247 1456894904342375433094423024093596239583182454728173664078071243433621748100 3220271297578822917644683598726994264913443918 ? cosh(1) 1.54308063481524377847790562075706168260152911236586370473740221471076906304 9223698964264726435543035587046858604423527565032194694709586290763493942377 3472069151633480026408029059364105029494057980033657762593319443209506958499 1368981037430548471273929845616039038581747145363600451873630682751434880120 2720574972705524471670706447103271142282939448411677273102139632958667273012 2826261409857215459162042522453939258584439199475134380734969475319971032521 055637731102374474158960765443652715148207669 ? exp(1) 2.71828182845904523536028747135266249775724709369995957496696762772407663035 3547594571382178525166427427466391932003059921817413596629043572900334295260 5956307381323286279434907632338298807531952510190115738341879307021540891499 3488416750924476146066808226480016847741185374234544243710753907774499206955 1702761838606261331384583000752044933826560297606737113200709328709127443747 0472306969772093101416928368190255151086574637721112523897844250569536967707 854499699679468644549059879316368892300987931 ? exp(1.123) 3.07406257154898987680161138009760625104248179708261339399712186197767466996 4935625311477807765382361174054209564400933143178772679923822312458571526893 0949675915002937652898704613739372482459452568993085662295138072557500421797 5971600253639265100975969190654549368799844236165029593059925114588814911583 9185488320031389051117206437605098919216790228388886978184284707042848120462 1182818728513135542290354814654148922271957843494116542832234810156127014491 955053641170027738831683277094167546025000529 ? incgam(4,1,6) 5.88607105874307714552838032258337387913297809650828535212538882715938393191 8396853714356389534714299946037204429503923331951612684642064138026457431905 5805294751098780374098407782238580023298615198035196589516153270359568407982 7992725182985932743696823436032979670756942663882506560584119323653928852565 9814209708876601791309278295271957611829097587465878928057118995331313636440 2883453599077405070514506827481973857316860179666499801153515201126481557348 108412200404484860301786425134984607926838502 ? incgamc(2,1) 0.26424111765711535680895245967707826510837773793646433098432639660507700851 0200393285705451308160712506745349446312009583506048414419741982746692821011 8024338156112652453237699027220177497087673100245600426310480841205053949002 1500909352126758407037897070495877541155382167014686679926985084543258893429 2523223786390424776086340213091005298521362801566765133992860125583585795444 9639568300115324366185686646564753267835392477541687524855810599859189805331 4864484749494393924622766968581269240091451867 ? log(2) 0.69314718055994530941723212145817656807550013436025525412068000949339362196 9694715605863326996418687542001481020570685733685520235758130557032670751635 0759619307275708283714351903070386238916734711233501153644979552391204751726 8157493206515552473413952588295045300709532636664265410423915781495204374043 0385500801944170641671518644712839968171784546957026271631064546150257207402 4816377733896385506952606683411372738737229289564935470257626520988596932019 6505855476470330679365443254763274495125040607 ? sin(Pi/6) 0.50000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000 ? sinh(1) 1.17520119364380145688238185059560081515571798133409587022956541301330756730 4323895607117452089623391840419533327579532356785218901919457282136840352883 2484238229689806253026878572974193778037894530156457975748559863812033933000 2119435713493927674792878380863977809159438228870943791837123225023064326834 8982186865900736859713876553648773791543620849195059840098569695750460170734 7646045559914877642254885845736315892502135438245978143162874775249565935186 798861968577094170390099113872716177152780263 ? sqr(tan(Pi/3)) 3.00000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000 ? tanh(1) 0.76159415595576488811945828260479359041276859725793655159681050012195324457 6638483458947521673676714421902759701554077532368309114762485413297006669611 3211253965101376080877764393409926042066795531174758011305900662577831975245 1237997591796119707757354591410814335043351567518059703276048802963895774140 4110555282743457474128870116732022433666141820426521385314984008017809424940 5971665020197077111278076211510055741702778683601321201082307883017522102475 0850545493659202265152413525903793814306804484 ? thetanullk(0.5,7) -804.63037320243369422783730584965684022502842525603918290428537089203649185 3005202838354617419978916066838351498344792388634514250685494567531066970308 1395985000299687911464724641787835671746030420666636980738176244141521534964 5910468287548147547821547802569972386188420035275376210374637455233928908304 8519707951113024675783203592515011343853492633432924541927657918744234297707 8009339159045897789510058204677594956471190358977738843586880213576194151544 6040652826323066997075899093444932117587282486 ? \p210 realprecision = 211 significant digits (210 digits displayed) ? dilog(0.5) 0.58224052646501250590265632015968010874419847480612642543434704787317104407 1683200816840318587915857185644360650489146599186798136823369642378773825725 010992996274322284433100379999291599248198351965163954430361 ? eint1(2) 0.04890051070806111956723983522804952231449218496302311632732287371169292871 4152191279268961007451641767339733440496339126093474911387068904573480132428 0606565260878276314803271231475388617592828799527149833070515 ? lngamma(10^50*I) -157079632679489661923132169163975144209858469968811.93673753887608474948977 0941153418951907406847934940095420371647821881900698782085734298414871973667 351244826946727013485797329023211606491949054831345082284018 + 1141292546497 0228420089957273421821038005507443143864.09476847610738955343272591658130426 4976155641647932550343141949832879612722439831043441291767982893579577059574 3877177782974245137531522747279687821610884364*I ? polylog(5,0.5) 0.50840057924226870745910884925858994131954112566482164872449779635262539422 8780242619384210049344955062253148566177885373776251290109126927256295587733 653575441097747430180753135597085935261518462072899907112039 ? 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) ? polylog(5,0.5,1) 1.03379274554168906408344764673478841754654188263517803810922886849674521856 8302490767987790059233900087664928281011147504065464055196977752510643903051 08453214093020806938180803753912648028281347292317330014656 ? polylog(5,0.5,2) 1.03445942344901048625461825783418822628308099519811715037388226488478462874 5613316541842884367897989911634714028478465772399056966065341954518002332809 93803867195735501893802985262734041524337126856608372430479 ? polylog(5,0.5,3) 0.94956934899649226018699647701016092398772870595673235481511016276008056001 9780143078976018486726179185715990894178927384257428042889858760164776911430 334108913396327982261675208743365007260765477862866539420350 ? psi(1) -0.5772156649015328606065120900824024310421593359399235988057672348848677267 7766467093694706329174674951463144724980708248096050401448654283622417399764 4923536253500333742937337737673942792595258247094916008735204 ? round(prod(k=1,17,x-exp(2*I*Pi*k/17)),&e) x^17 - 1 ? e -693 ? theta(0.5,3) 0.08080641825189469129987168321046629852436630463736585818145355698789812007 7007090242373481570553349455066987093523256662570622075796055596272586626054 1756288186798491280103427257359418016911094472073083250230198 ? weber(I) 1.18920711500272106671749997056047591529297209246381741301900222471946666822 6917159870781344538137673716037394774769213186063726361789847756785360862538 01777507015151140355709227316234286888992417544607190871050 ? weber(I,1) 1.09050773266525765920701065576070797899270271854006712178566764768330053084 8841840338211140494203119891451619262918090010347769026116087255320275930582 70136445935603377184958072509793552467405409688916300069889 ? weber(I,2) 1.09050773266525765920701065576070797899270271854006712178566764768330053084 8841840338211140494203119891451619262918090010347769026116087255320275930582 70136445935603377184958072509793552467405409688916300069889 ? zeta(3) 1.20205690315959428539973816151144999076498629234049888179227155534183820578 6313090186455873609335258146199157795260719418491995998673283213776396837207 90016145394178294936006671919157552224249424396156390966410 ? \p38 realprecision = 38 significant digits ? besselk(1+I,1) 0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415 2302743*I ? erfc(2) 0.0046777349810472658379307436327470713891 ? gamma(10.5) 1133278.3889487855673345741655888924756 ? hyperu(1,1,1) 0.59634736232319407434107849936927937607 ? incgam(2,1) 0.73575888234288464319104754032292173491 ? zeta(0.5+14.1347251*I) 5.2043097453468479398562848599360610966 E-9 - 3.2690639869786982176409251733 763732423 E-8*I ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 44 pari-2.7.5/src/test/32/idealappr0000644000175000017500000000035012366172547014777 0ustar billbill[3, 0]~ [23/2, [6, 1/2]~] [-23/2, 0]~ [0, 0] *** at top-level: idealtwoelt(K,[;],1) *** ^-------------------- *** idealtwoelt: domain error in idealtwoelt2: element mod ideal != 0 [0, 0]~ Total time spent: 0 pari-2.7.5/src/test/32/zncoppersmith0000644000175000017500000000050612366172547015746 0ustar billbill[100000000000] 1 [1339991002000615200] 1 [-997, -955, -913, -871, -829, -787, -745, -703, -661, -619, -577, -535, -49 3, -451, -409, -367, -325, -283, -241, -199, -157, -115, -73, -31, 11, 53, 9 5, 137, 179, 221, 263, 305, 347, 389, 431, 473, 515, 557, 599, 641, 683, 725 , 767, 809, 851, 893, 935, 977] Total time spent: 284 pari-2.7.5/src/test/32/rfrac0000644000175000017500000000027112366172547014135 0ustar billbilly^2/x (32*b^4 + 128*b^3 + 80*b^2 + 16*b + 1)/(32*b^3 + 40*b^2 + 12*b + 1) (x^408 - x^306 - x^102 + 1)/(x^510 + 1) (-x^994 + x^497)/(x^1491 + 1) [1, 0] 0 0.E-38/x Total time spent: 3004 pari-2.7.5/src/test/32/cmp0000644000175000017500000000042012405547147013607 0ustar billbill(f,g)->[cmp(f,f),cmp(f,g),cmp(g,f)] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [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 pari-2.7.5/src/test/32/list0000644000175000017500000000062612405547147014013 0ustar billbillList([1, 2, 3, 3, 5]) List([1, 1, 2, 3, 3]) List([1, 2, 3, 3, 1, 2, 3, 3]) List([1, 1, 2, 2, 3, 3, 3, 3]) List([1, 2, 3]) List([1, 2]) List([2]) List([[1, 2, 3], 2]) 3 List([[3, 2, 3], 2]) List([Vecsmall([1, 2, 3]), 2]) 3 [List([0])] List([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]) List([10, 9, 8, 7, 6, 5]) List([]) List([1, y + 1]) List([y, x]) List([y, y*x]) 108 1 Mod(1, 3) Mod(22, 30) Total time spent: 28 pari-2.7.5/src/test/32/qf0000644000175000017500000000325512515252602013436 0ustar billbill [7/2 1 8/7 11/7] [ -1 -7/2 -4/7 -5/7] [ 0 0 -24/7 -29/24] [ 0 0 0 -311/168] [12, 1] 266 Vecsmall([0, 0, 0, 0, 0, 0, 0, 133, 0, 165, 0, 638, 0, 396, 0, 4268]) Vecsmall([0, 0, 0, 133, 165, 638, 396, 4268]) [8, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~] [8, [-2, -2, 1, 1, -1, -1, 2, 0, 1, 1, 1, 1]~] [] [] [0, 0, [;]] [0, 0, [;]] [] [0, 0, [;]] *** at top-level: qfminim(L~*L,10^16)[ *** ^-------------------- *** qfminim: precision too low in qfminim. 10000000000000000.000 [0, 1]~ [1, 0]~ [-1, 1]~ [-1, 1]~ 14 23 2 -13 [66 78 90] [78 93 108] [90 108 126] [35 67 99] [67 110 153] [99 153 207] *** at top-level: qfnorm(1) *** ^--------- *** qfnorm: incorrect type in qfnorm (t_INT). *** at top-level: qfnorm(1,1) *** ^----------- *** qfnorm: incorrect type in qfnorm (t_INT). *** at top-level: qfnorm(x,Mat(1)) *** ^---------------- *** qfnorm: inconsistent dimensions in qfeval. *** at top-level: qfnorm(x,Mat(x~)) *** ^----------------- *** qfnorm: inconsistent dimensions in qfeval. *** at top-level: qfbil(1,1) *** ^---------- *** qfbil: incorrect type in qfbil (t_INT). *** at top-level: qfbil([1],[1,2]) *** ^---------------- *** qfbil: inconsistent dimensions in qfbil. *** at top-level: qfbil([1,2],[1,2],q) *** ^-------------------- *** qfbil: inconsistent dimensions in qfevalb. *** at top-level: qfbil([1,2],[1,2],Ma *** ^-------------------- *** qfbil: inconsistent operation 'RgV_RgM_mul' t_VEC (2 elts) , t_MAT (1x2). Total time spent: 12 pari-2.7.5/src/test/32/subgroup0000644000175000017500000000040112366172547014701 0ustar billbill[53835600, 29] [5, 0; 0, 1] [10, 0; 0, 1] [[12, 0; 0, 1]] [] [] *** at top-level: forsubgroup(h=[2,3],2,print(h)) *** ^--------- *** incorrect type in forsubgroup [not a group] (t_VEC). [] Total time spent: 4 pari-2.7.5/src/test/32/subfields0000644000175000017500000040405012611153614015006 0ustar billbill1: [[x, 0], [x^2 + 972, 3*x^3], [x^3 + 54, 1/12*x^4 + 3/2*x], [x^3 + 864, 2* x^2], [x^3 - 54, -1/12*x^4 + 3/2*x], [x^6 + 108, x]] 2: [[x, 0], [x^2 - 30, -8/7*x^7 + 97/7*x^5 - 197/7*x^3 + 139/7*x], [x^2 - 2, -6/7*x^7 + 71/7*x^5 - 125/7*x^3 + 43/7*x], [x^2 - 24*x + 84, -2*x^6 + 24*x^ 4 - 44*x^2 + 24], [x^2 - 6, 2*x^7 - 23*x^5 + 35*x^3 - 11*x], [x^2 - 24*x + 6 4, 32/7*x^6 - 360/7*x^4 + 480/7*x^2 - 24/7], [x^2 - 24*x + 36, -18/7*x^6 + 1 92/7*x^4 - 144/7*x^2 + 24/7], [x^2 - 10, -x^5 + 11*x^3 - 11*x], [x^4 - 16*x^ 2 + 49, -x^7 + 12*x^5 - 23*x^3 + 13*x], [x^4 - 18*x^2 + 36, 3/7*x^7 - 32/7*x ^5 + 24/7*x^3 + 31/7*x], [x^4 - 20*x^2 + 25, -4/7*x^7 + 45/7*x^5 - 60/7*x^3 + 31/7*x], [x^4 - 4*x^2 + 1, 4/7*x^7 - 45/7*x^5 + 60/7*x^3 - 17/7*x], [x^4 - 6*x^2 + 4, -3/7*x^7 + 32/7*x^5 - 24/7*x^3 - 17/7*x], [x^4 - 8*x^2 + 1, x^7 - 12*x^5 + 23*x^3 - 11*x], [x^4 - 24*x^3 + 92*x^2 - 96*x + 16, 2*x^2], [x^8 - 12*x^6 + 23*x^4 - 12*x^2 + 1, x]] 3: [[x, 0], [x^2 - 8, -x^6 + 9*x^2], [x^2 - 4*x - 8, x^6 - 11*x^2 + 2], [x^2 + 8*x - 8, -x^4 + 1], [x^4 - 8*x^3 + 20*x^2 - 16*x - 8, -x^7 + 10*x^3 + x + 2], [x^4 + 4*x^2 - 8, x^7 - 10*x^3 + x], [x^4 - 4*x^3 - 4*x^2 + 16*x - 8, - x^2 + 1], [x^8 - 10*x^4 + 1, x]] 4: [[x, 0], [x^2 - 6*x + 7, -x^4 - 2*x^2], [x^4 - 4*x^3 + 10*x^2 - 12*x + 7, -x^2], [x^8 + 4*x^6 + 10*x^4 + 12*x^2 + 7, x]] 5: [[x, 0], [x^3 - 54*x^2 + 729*x - 4116, 1/64*x^8 - 9/32*x^7 + 117/64*x^6 - 87/16*x^5 + 99/16*x^4 + 9/2*x^3 + 737/16*x^2 + 15*x + 24], [x^3 - 81*x^2 + 1764*x - 4116, -1/70*x^8 + 121/490*x^7 - 207/140*x^6 + 883/245*x^5 - 851/980 *x^4 - 3042/245*x^3 - 9804/245*x^2 - 7936/245*x + 5493/245], [x^3 - 81*x^2 - 1176*x - 4116, 87/2240*x^8 - 5361/7840*x^7 + 9567/2240*x^6 - 46203/3920*x^5 + 20697/1960*x^4 + 30841/1960*x^3 + 483999/3920*x^2 + 35967/490*x + 10937/2 45], [x^3 - 81*x^2 + 3528*x - 4116, 3/448*x^8 - 197/1568*x^7 + 387/448*x^6 - 2111/784*x^5 + 263/98*x^4 + 2619/392*x^3 + 2095/784*x^2 + 97/98*x - 3/49], [x^9 - 18*x^8 + 117*x^7 - 348*x^6 + 396*x^5 + 288*x^4 + 3012*x^3 + 576*x^2 + 576*x - 512, x]] 6: [[x, 0], [x^5 - 45*x^4 + 524*x^3 - 1559*x^2 + 91*x - 1, 3038549959301070/ 193673549326818517*x^9 + 114701029571267416/193673549326818517*x^8 - 3295488 74995714210/193673549326818517*x^7 + 376376940440002096/17606686302438047*x^ 6 - 14032630283051868958/193673549326818517*x^5 + 31750438068174608336/19367 3549326818517*x^4 - 33640776846315210164/193673549326818517*x^3 + 1289404927 8294790719/193673549326818517*x^2 - 592790870239579798/193673549326818517*x + 867925062747780/17606686302438047], [x^10 + 38*x^9 - 99*x^8 + 1334*x^7 - 4 272*x^6 + 9244*x^5 - 8297*x^4 + 1222*x^3 + 1023*x^2 - 74*x + 1, x]] 7: [[x, 0], [x^5 + 120*x^4 + 3990*x^3 + 42160*x^2 + 43385*x + 517448, -17134 556086196609/5068781981585866941336*x^9 + 206152709694981995/506878198158586 6941336*x^8 + 1609240120979582377/5068781981585866941336*x^7 - 6920363323788 920677/1689593993861955647112*x^6 + 81936943990555286701/5068781981585866941 336*x^5 + 152900407806684015487/1689593993861955647112*x^4 - 119401334776012 7291825/5068781981585866941336*x^3 - 3869545478257111110553/5068781981585866 941336*x^2 + 5817710613679700856179/1267195495396466735334*x - 2019572872099 705211315/633597747698233367667], [x^10 - 20*x^9 + 80*x^8 + 200*x^7 - 3770*x ^6 + 872*x^5 + 29080*x^4 + 36280*x^3 - 456615*x^2 + 541260*x - 517448, x]] 8: [[x, 0], [x^2 + 6*x + 16, 1258375/11052559*x^9 - 688130/11052559*x^8 - 11 958010/11052559*x^7 + 31393060/11052559*x^6 + 276559109/11052559*x^5 + 61866 7950/11052559*x^4 + 716993740/11052559*x^3 + 454173360/11052559*x^2 + 196757 250/11052559*x + 9706600/11052559], [x^10 - 10*x^8 + 20*x^7 + 235*x^6 + 606* x^5 + 800*x^4 + 600*x^3 + 270*x^2 + 70*x + 16, x]] 9: [[x, 0], [x^3 - 4*x^2 - 12*x - 8, -5/74*x^11 + 7/37*x^10 - 17/74*x^9 - 6/ 37*x^8 + 29/37*x^7 - 22/37*x^6 + 12/37*x^5 + 43/37*x^4 - 46/37*x^3 + 20/37*x ^2 + 18/37*x - 60/37], [x^4 + 6*x^3 + 12*x^2 + 8*x + 8, -4/37*x^11 + 15/74*x ^10 - 5/74*x^9 - 17/37*x^8 + 41/74*x^7 + 24/37*x^6 - 3/37*x^5 + 54/37*x^4 + 30/37*x^3 - 42/37*x^2 + 14/37*x - 22/37], [x^12 + 6*x^9 + 4*x^8 + 8*x^6 - 4* x^5 - 12*x^4 + 8*x^3 - 8*x + 8, x]] 10: [[x, 0], [x^2 - 23*x + 1, -95/63*x^11 - 760/63*x^10 + 170/21*x^9 + 745/7 *x^8 + 3305/21*x^7 + 205*x^6 + 635/3*x^5 + 870/7*x^4 + 590/7*x^3 + 575/63*x^ 2 - 650/63*x + 454/21], [x^3 + 15*x^2 + 12*x - 1, -16/7*x^11 - 142/7*x^10 - 89/21*x^9 + 3530/21*x^8 + 8051/21*x^7 + 1667/3*x^6 + 1916/3*x^5 + 10919/21*x ^4 + 7034/21*x^3 + 2672/21*x^2 - 436/21*x - 386/21], [x^4 + 18*x^3 - 36*x^2 + 270*x + 1107, 310/63*x^11 + 2644/63*x^10 - 290/63*x^9 - 7426/21*x^8 - 2114 /3*x^7 - 1010*x^6 - 3398/3*x^5 - 6084/7*x^4 - 11806/21*x^3 - 11218/63*x^2 + 2762/63*x + 47/9], [x^6 - 3*x^5 - 33*x^4 + 106*x^3 - 24*x^2 - 75*x + 1, -x^1 1 - 9*x^10 - 3*x^9 + 73*x^8 + 177*x^7 + 267*x^6 + 315*x^5 + 267*x^4 + 177*x^ 3 + 73*x^2 - 2*x - 7], [x^12 + 9*x^11 + 3*x^10 - 73*x^9 - 177*x^8 - 267*x^7 - 315*x^6 - 267*x^5 - 177*x^4 - 73*x^3 + 3*x^2 + 9*x + 1, x]] 11: [[x - 34734, 34734], [x^3 - 404450238*x^2 + 51929707167307884*x - 210694 5843643976551078888, -9342188044422318487729248211775/2214669002270171995835 0965876436984233324505664916550383771692*x^11 + 6033218347374060922967697235 7289403/5536672505675429989587741469109246058331126416229137595942923*x^10 - 755466390810188186936214482171670640445/22146690022701719958350965876436984 233324505664916550383771692*x^9 - 392022912004136123430642855831161297287133 3/3691115003783619993058494312739497372220750944152758397295282*x^8 + 647561 90353632899593058088471324843886641684521/7382230007567239986116988625478994 744441501888305516794590564*x^7 - 183930570642208634667376560703511349411910 07246920/1845557501891809996529247156369748686110375472076379198647641*x^6 - 214051222556933671040122576873060155244550337314553091/36911150037836199930 58494312739497372220750944152758397295282*x^5 + 3742979005268450240872002688 31763757380697898774819087471/3691115003783619993058494312739497372220750944 152758397295282*x^4 + 732738748406097211695426095371309517410358207767354112 603431/7382230007567239986116988625478994744441501888305516794590564*x^3 - 1 029490244100838046829406711792226497002817428265903324830579547/553667250567 5429989587741469109246058331126416229137595942923*x^2 - 45096911671329708869 307328748124201519401653093836882262901185897/553667250567542998958774146910 9246058331126416229137595942923*x + 1035452998465952296944708318989954617972 835353405495945537529058226202/553667250567542998958774146910924605833112641 6229137595942923], [x^4 - 34734*x^3 + 300462696*x^2 + 41450199048*x - 379221 762052224, 14110573821076695554388896014506463760825/18532084403873711703780 61701288375914871619333547574940815535866672304656*x^11 - 481485463029074233 335782172117101303661014341/185320844038737117037806170128837591487161933354 7574940815535866672304656*x^10 + 5367285004556060607251380985659601467584643 783775/185320844038737117037806170128837591487161933354757494081553586667230 4656*x^9 - 724957691551120605058587600103565855371815194249245/7721701834947 3798765752570887015663119650805564482289200647327778012694*x^8 - 14926423613 827844109215358159995271639520843231424596277/617736146795790390126020567096 125304957206444515858313605178622224101552*x^7 + 763836288194432943202980786 97519097254809895356403449363049/6177361467957903901260205670961253049572064 44515858313605178622224101552*x^6 + 2751911640084126226673791312812683285355 833117563952352468743/386085091747368993828762854435078315598254027822411446 00323663889006347*x^5 - 2797395403590994034737713919789472364603094039317098 91862395749053/6177361467957903901260205670961253049572064445158583136051786 22224101552*x^4 - 7504160249443571670530091644599868598849760894682531424393 6087235753/61773614679579039012602056709612530495720644451585831360517862222 4101552*x^3 + 19286065393511873013020896030775996158242421244256300897032679 4213732861/46330211009684279259451542532209397871790483338689373520388396666 8076164*x^2 - 16191548463390010827165201305543186319057665739249267235602841 186782411209/463302110096842792594515425322093978717904833386893735203883966 668076164*x - 13056495504690505502174926686295024785326634173334466106080828 4353649867306/11582552752421069814862885633052349467947620834672343380097099 1667019041], [x^4 - 34734*x^3 + 300462696*x^2 + 719593875864*x - 12048455417 833440, -912978933965428702677328421946337977275/427009469302505073852676592 5050936313158231730603136168953156155639990654*x^11 + 8407246036776236034735 3536967653431092912031/17080378772100202954107063700203745252632926922412544 675812624622559962616*x^10 - 11398417297495892544563044210311176625029955575 /17080378772100202954107063700203745252632926922412544675812624622559962616* x^9 - 893347789433470245763794191918075393707137337220545/142336489767501691 2842255308350312104386077243534378722984385385213330218*x^8 + 24686014963885 51544725562985100449173297162272410181126/7116824488375084564211276541751560 52193038621767189361492192692606665109*x^7 + 2619172679537435761406478400285 9409319675692967171797755667/56934595907000676513690212334012484175443089741 37514891937541540853320872*x^6 - 5444505759822050986091257169800106052333185 45168647774612861/1358820904701686790302869029451371937361410256357402122180 7975037836088*x^5 - 84089850641580864583404121851546268588343862717124795869 654550967/569345959070006765136902123340124841754430897413751489193754154085 3320872*x^4 + 82269200238740742666178668103656946863466970188385987011592278 2319399/56934595907000676513690212334012484175443089741375148919375415408533 20872*x^3 + 3503428352603249699300472760879525632722446036723176866748006043 47982411/8540189386050101477053531850101872626316463461206272337906312311279 981308*x^2 - 253000270288016296385150329441426641791370700418697463186888852 550572865528/213504734651252536926338296252546815657911586530156808447657807 7819995327*x + 1912911454523555330264483772745854808577616715831981650539735 0720058392018650/21350473465125253692633829625254681565791158653015680844765 78077819995327], [x^4 - 34734*x^3 + 300462696*x^2 - 667378778688*x + 4288123 52307072, 6273160180385208072676253797115270236775/5940858424916371597850579 454643268649594120257767824314298295930250745714*x^11 - 91833464035386409580 0706379445833929537385123/23763433699665486391402317818573074598376481031071 297257193183721002982856*x^10 + 11620993006244117573583895395392195759302448 890375/237634336996654863914023178185730745983764810310712972571931837210029 82856*x^9 - 2209724345743573539834795881875030751631879652688650/99014307081 9395266308429909107211441599020042961304052383049321708457619*x^8 - 90490574 1980509693458118408199924159677196678384605051/99014307081939526630842990910 7211441599020042961304052383049321708457619*x^7 + 22877305893848271839343308 7107542783081076855760562416305945/79211445665551621304674392728576915327921 60343690432419064394573667660952*x^6 - 2571247739128689359677893264165877823 48593980664060018882482409/7921144566555162130467439272857691532792160343690 432419064394573667660952*x^5 - 902915509977437374550740055247922997304160711 198583657340540293029/792114456655516213046743927285769153279216034369043241 9064394573667660952*x^4 + 12647371976768847217149269686446726878798796344873 47056588849959499529/7921144566555162130467439272857691532792160343690432419 064394573667660952*x^3 + 184108522696301150772261875173517105531726706993092 1240026759849694558005/11881716849832743195701158909286537299188240515535648 628596591860501491428*x^2 - 105226430872673292657652274117946531461625581409 6099354896910163038066989639/59408584249163715978505794546432686495941202577 67824314298295930250745714*x + 351897368084118382955192810963102536960435507 9690659359039411864812112186299/29704292124581857989252897273216343247970601 28883912157149147965125372857], [x^4 - 34734*x^3 + 300462696*x^2 - 944224434 00*x - 618844230971136, -6244226996057952777880113480351379337675/7384147894 07247856391164124670071766158949771633107927816709692427223344*x^11 + 216750 230651841816989537133589460109029889307/738414789407247856391164124670071766 158949771633107927816709692427223344*x^10 - 24992189654493621869938874441777 63611038902109425/7384147894072478563911641246700717661589497716331079278167 09692427223344*x^9 + 188417720221548167848861074692067065579959656279560/153 83641445984330341482585930626495128311453575689748496181451925567153*x^8 + 5 318638181429905968700041964805475458478670091210794943/246138263135749285463 721374890023922052983257211035975938903230809074448*x^7 - 386763277860758627 19262052122652322648153233487743293439359/2461382631357492854637213748900239 22052983257211035975938903230809074448*x^6 + 7698539809990361287561871527957 3605511131289962139790144515/61534565783937321365930343722505980513245814302 758993984725807702268612*x^5 + 143154969427923778251503253915653423528426333 300467148693599297771/246138263135749285463721374890023922052983257211035975 938903230809074448*x^4 - 449658405954593992823654430001517440485681802597131 26203807118706065/2461382631357492854637213748900239220529832572110359759389 03230809074448*x^3 - 1130232482228186252206081607706505141404728370672174259 61760024891067261/1846036973518119640977910311675179415397374429082769819541 77423106805836*x^2 + 6176287549251876371093517320579733410772043422707238431 4053857007019156725/18460369735181196409779103116751794153973744290827698195 4177423106805836*x + 6525285229664225652346515846620963724288153967638848197 61741487186945039935/4615092433795299102444775779187948538493436072706924548 8544355776701459], [x^6 - 34734*x^5 + 401383590*x^4 - 1534279047280*x^3 - 62 3086166484273*x^2 + 6024207776080451370*x - 3395544494886430834931, 65048283 4595988426289875584925611839809050403841510975/93879859694709658900023423073 908800229122926824806536083213101085431514021400845370272*x^11 - 28280356132 03818848595391814308127055615711578492704854205/1173498246183870736250292788 4238600028640365853100817010401637635678939252675105671284*x^10 + 2617776421 07582168054428278943612510410442805195866384609962775/9387985969470965890002 3423073908800229122926824806536083213101085431514021400845370272*x^9 - 15927 1141747715886165104807305964751229171393962459611440912934045/15646643282451 609816670570512318133371520487804134422680535516847571919003566807561712*x^8 - 549955490462771080691539799763589822375411867004836057005174839265373/312 9328656490321963334114102463626674304097560826884536107103369514383800713361 5123424*x^7 + 25864145666173083796718616503459506022050622985470132525739709 5009034637/19558304103064512270838213140397666714400609755168028350669396059 46489875445850945214*x^6 - 6592918174156851318520777070014249645801977031244 2956213117809125335509633/78233216412258049083352852561590666857602439020672 11340267758423785959501783403780856*x^5 - 7800898227382363725189039065112986 079820471591287196576278549997100182092831745/156466432824516098166705705123 18133371520487804134422680535516847571919003566807561712*x^4 + 6122142268116 939512060932346170056883900854266430077469732839637712189084833407767/312932 8656490321963334114102463626674304097560826884536107103369514383800713361512 3424*x^3 + 32022508461623431276902286210776146200887958099783536289531117346 37868539334724284127/5867491230919353681251463942119300014320182926550408505 200818817839469626337552835642*x^2 - 800638255584388658971089596935817625981 9365543316588290509462947927580787314394474893213/23469964923677414725005855 768477200057280731706201634020803275271357878505350211342568*x - 58990558701 8760848758798275065010731791241332701940631740790132610723674961763135480882 7/29337456154596768406257319710596500071600914632752042526004094089197348131 68776417821], [x^6 - 404450238*x^5 + 54100188079371078*x^4 - 271097787243506 0813524384*x^3 + 42285567950111504527423881770355*x^2 - 20529948264855793448 2118273363967086790*x + 308274255189281477531677588408355830798086937, -4120 869126500964373994569574506880767182320713762311294475/938798596947096589000 23423073908800229122926824806536083213101085431514021400845370272*x^11 + 146 940653700070562235241304852946310481730440354337413521273481/938798596947096 58900023423073908800229122926824806536083213101085431514021400845370272*x^10 - 222703401706905275932607625400403116755352990786094605748551642925/117349 8246183870736250292788423860002864036585310081701040163763567893925267510567 1284*x^9 + 12377075137704495001629425332319301954065542889699939222464837777 94171/1564664328245160981667057051231813337152048780413442268053551684757191 9003566807561712*x^8 + 20066085476142621805212784221307018563054220745603711 26880840186645292325/3129328656490321963334114102463626674304097560826884536 1071033695143838007133615123424*x^7 - 30041249679723991746278208886194545785 402295380444679832412631893124807114363/312932865649032196333411410246362667 43040975608268845361071033695143838007133615123424*x^6 + 2087488959839192259 0201106347226773398572860027042902334147818870582912283491027/31293286564903 219633341141024636266743040975608268845361071033695143838007133615123424*x^5 + 1113444893903474697082861783171804271560046490863740226525751251144715711 09171287261/3129328656490321963334114102463626674304097560826884536107103369 5143838007133615123424*x^4 - 54037078291258541773319971842404517193840416945 659451213116511317761079476637043173135/156466432824516098166705705123181333 71520487804134422680535516847571919003566807561712*x^3 - 2033717931912934290 80383788937903691340509781131977766772274019850437153377772215101960661/4693 9929847354829450011711536954400114561463412403268041606550542715757010700422 685136*x^2 + 119226908672022683411723814050468113357593231142438856317381065 29862168277632359183454929030/2933745615459676840625731971059650007160091463 275204252600409408919734813168776417821*x + 21641809528558234322621587024281 82538403098495413532025934764817277543505392932163117127075065/1173498246183 8707362502927884238600028640365853100817010401637635678939252675105671284], [x^6 - 34734*x^5 + 401383590*x^4 - 1534279047280*x^3 - 169315682156985*x^2 + 770453108539110906*x + 33220916743396911661, -36288992724566042787812747887 4582939883814569944534675/93879859694709658900023423073908800229122926824806 536083213101085431514021400845370272*x^11 + 12238241238442727065545358658257 447978393534633897082817625/938798596947096589000234230739088002291229268248 06536083213101085431514021400845370272*x^10 - 664894587801976961863497775860 01819171185673071207046291100875/4693992984735482945001171153695440011456146 3412403268041606550542715757010700422685136*x^9 + 64656603467569138793589545 104078793625221358249253851685597622935/156466432824516098166705705123181333 71520487804134422680535516847571919003566807561712*x^8 + 4623655015680620106 51546371322987178103039625985593620591030386511105/3129328656490321963334114 1024636266743040975608268845361071033695143838007133615123424*x^7 - 19015914 06040779221754637364862552563516461322719907608688999134986276895/3129328656 4903219633341141024636266743040975608268845361071033695143838007133615123424 *x^6 - 187253813263959519095029930199330041649555034596928840729682216077533 1374615/31293286564903219633341141024636266743040975608268845361071033695143 838007133615123424*x^5 + 737173668594558261406590356021435552666740739108865 6090600761557159558228783105/31293286564903219633341141024636266743040975608 268845361071033695143838007133615123424*x^4 + 241072810751756404394252967643 452651428825132481432156536773360547515144225208245/195583041030645122708382 1314039766671440060975516802835066939605946489875445850945214*x^3 - 10065153 5951548846430086524306167014187845178960442135338090501538082420220528382937 25/4693992984735482945001171153695440011456146341240326804160655054271575701 0700422685136*x^2 - 11030678695913727302525949875303187188235190350092781841 5833782064611237363146362782355/11734982461838707362502927884238600028640365 853100817010401637635678939252675105671284*x - 53243921404282058396885384791 2984676758353132269792636297543816246239642774824102925179/11734982461838707 362502927884238600028640365853100817010401637635678939252675105671284], [x^1 2 - 34734*x^11 + 401000259*x^10 - 1456627492885*x^9 - 2537142937228035*x^8 + 18762072755679375516*x^7 - 812368636358864062944*x^6 - 70132863629758257512 231931*x^5 + 25834472514893102332821062085*x^4 + 766232806103524502472479395 84745*x^3 - 45080885015422662132515763499758450*x^2 - 2070499552240812214288 316981071818900*x - 550505759097778545485364826246753544, x]] 12: [[x, 0], [x^3 + 3*x^2 + 4*x + 1, 14932268423886825/134040977335195199*x^ 14 + 3314773739694150/134040977335195199*x^13 - 458667248689990/134040977335 195199*x^12 + 299660784416742155/134040977335195199*x^11 + 19314189677750535 00/134040977335195199*x^10 + 7916949557683234500/134040977335195199*x^9 + 26 268194382756835965/134040977335195199*x^8 + 56555578533556092735/13404097733 5195199*x^7 + 80995665441611911535/134040977335195199*x^6 + 7977029541497422 1849/134040977335195199*x^5 + 57127754838291495800/134040977335195199*x^4 + 29731892661369048315/134040977335195199*x^3 + 10792405938344532550/134040977 335195199*x^2 + 2538888140467665125/134040977335195199*x + 15389316999785695 0/134040977335195199], [x^15 + 20*x^12 + 125*x^11 + 503*x^10 + 1650*x^9 + 34 30*x^8 + 4690*x^7 + 4335*x^6 + 2904*x^5 + 1400*x^4 + 485*x^3 + 100*x^2 + 15* x + 1, x]] 13: [[x, 0], [x^2 - 2, -x^16], [x^4 - 2, -x^8], [x^8 - 2, -x^4], [x^16 - 2, -x^2], [x^32 - 2, x]] 14: [[x, 0], [x^3 - 2256*x^2 + 6096*x + 64, -1941708934505961434012429883125 0860157099952726892251/770574202417890161481916508657135480583189210820336*x ^26 + 465261347703887731979726777504133076469790749716419/700522002198081964 98356046241557770962108110074576*x^25 + 145546216272635060505776677527078053 207287212099723363/48160887651118135092619781791070967536449325676271*x^24 + 609511312566045052425738403987685164063245222472298727/77057420241789016148 1916508657135480583189210820336*x^23 - 1103182803837756393768615747557123337 78850601164726902531/770574202417890161481916508657135480583189210820336*x^2 2 - 35764561073596826122555693587416304111300918329291915265/385287101208945 080740958254328567740291594605410168*x^21 + 26986765568191452078996731186958 97987172753535814855959363/7705742024178901614819165086571354805831892108203 36*x^20 + 2535300787966757653899707912201660658080677991096347496733/7705742 02417890161481916508657135480583189210820336*x^19 - 184500421281399807210404 13663350432313722498669439849137367/3852871012089450807409582543285677402915 94605410168*x^18 - 382738570038762014634870665591100320360686007281960816237 5/70052200219808196498356046241557770962108110074576*x^17 + 1421780866681070 75407847922087024499291038110902822453518015/3852871012089450807409582543285 67740291594605410168*x^16 + 493295798745689513357840097535831176396514500407 9263946901/10853157780533664246224176178269513811030833955216*x^15 - 7580219 3796193664872566402589365181600247079699279904970949/48160887651118135092619 781791070967536449325676271*x^14 - 14189256922643983469056003182354684709402 94544244297103895783/770574202417890161481916508657135480583189210820336*x^1 3 + 2949268306628070636920950136227355126808364474772530622119857/7705742024 17890161481916508657135480583189210820336*x^12 + 166589581259622181167910161 70344564504455183828422917544032/4378262513738012281147252890097360685131756 879661*x^11 - 990545784945921859397562859484696191953405596548533237819111/1 92643550604472540370479127164283870145797302705084*x^10 - 157793499488740516 3427397869387988325500213538839953957172237/38528710120894508074095825432856 7740291594605410168*x^9 + 25167273706310086938584534037448648134472333543354 60822902795/770574202417890161481916508657135480583189210820336*x^8 + 168807 157196505177595021303258144303674164728470637182661851/700522002198081964983 56046241557770962108110074576*x^7 - 5183318657770617066878045436057944671512 46150122922616485461/770574202417890161481916508657135480583189210820336*x^6 - 1776270119139661464090238799174385930766842582827745181371/27132894451334 16061556044044567378452757708488804*x^5 - 3795395413907166661496173345979920 804875647669966430644559/48160887651118135092619781791070967536449325676271* x^4 + 935037583110078417918059907483691589942806970032644103842/481608876511 18135092619781791070967536449325676271*x^3 + 2070294748166925189510266998004 27111617432833336068658906/4816088765111813509261978179107096753644932567627 1*x^2 + 7357964953188324444369967201461211123383988457557368072/481608876511 18135092619781791070967536449325676271*x - 296542410803660849197540276703255 503397498629122175636/48160887651118135092619781791070967536449325676271], [ x^3 - 2796*x^2 - 960*x + 64, -7398467947462967071449081703305414037830363783 21220562733077/1645953101585370740052867362633907861270288820806508923601430 2*x^26 - 2210993295137920400153699721177302123375420702843160712207137/90527 420587195390702907704944864932369865885144357990798078661*x^25 + 77445201700 75936726930825115050660035652030327315379025370168609/1448438729395126251246 523279117838917917854162309727852769258576*x^24 + 82848290601238996733541936 29984574355737519289228087543949666801/1448438729395126251246523279117838917 917854162309727852769258576*x^23 - 35901241029118455354254627498534656545123 1093312484340564713122561/14484387293951262512465232791178389179178541623097 27852769258576*x^22 - 526355214064307610466287041002238084273709423917420752 758848566155/144843872939512625124652327911783891791785416230972785276925857 6*x^21 + 4214074164145018774103330454775088768075402073444754515666988968027 /724219364697563125623261639558919458958927081154863926384629288*x^20 + 6853 33941994204545917666687114508041352829458300155523409117259047/6583812406341 4829602114694505356314450811552832260356944057208*x^19 - 1069113459131628901 45797530748166151719319481766399539290295124370257/1448438729395126251246523 279117838917917854162309727852769258576*x^18 - 22069952916279389685637098419 7801378507797376158324629810580186498873/14484387293951262512465232791178389 17917854162309727852769258576*x^17 + 715081621748863035896257730347336007514 096632125143483060169924296217/144843872939512625124652327911783891791785416 2309727852769258576*x^16 + 2324224568652505655977226792952233162797157561370 9400185272082977721/20400545484438397904880609565039984759406396652249688067 172656*x^15 - 23131236016680905235421808448499402418785791423724641025641151 24139141/1448438729395126251246523279117838917917854162309727852769258576*x^ 14 - 5856573846677695136177029586583045589991747682773104214719002354121491/ 1448438729395126251246523279117838917917854162309727852769258576*x^13 + 3651 180832394425697740451101578157246205689545997506067287443696038813/144843872 9395126251246523279117838917917854162309727852769258576*x^12 + 1004042652056 1184085992260635787732864328665489520074163406248596214953/14484387293951262 51246523279117838917917854162309727852769258576*x^11 - 114188197615994305615 0352420584376105638987469781569823827491087714737/72421936469756312562326163 9558919458958927081154863926384629288*x^10 - 1941840292156985856042966823843 091035965664640434668187482417279631473/362109682348781562811630819779459729 479463540577431963192314644*x^9 - 405860245714839461599072202945428738509236 22637376408267704565530984/9052742058719539070290770494486493236986588514435 7990798078661*x^8 + 10820459067092489285053671440133728060542917460755957359 61248749508317/7242193646975631256232616395589194589589270811548639263846292 88*x^7 + 8861380037025468041187538410135187781855132948807436648032930087691 51/1448438729395126251246523279117838917917854162309727852769258576*x^6 + 12 69141287869800364601057824070219376621096840567842007072173038733/2040054548 4438397904880609565039984759406396652249688067172656*x^5 - 97999252912324104 67649476579009759547499077607129326386012443315269/7242193646975631256232616 39558919458958927081154863926384629288*x^4 - 1658731209293582607061161341066 424240216534357816117719110794086563/362109682348781562811630819779459729479 463540577431963192314644*x^3 - 416959419511533591557215671143180277136599872 17016395377055931636/9052742058719539070290770494486493236986588514435799079 8078661*x^2 - 56581149967573957735857504427621740454460778602059876917654405 1/90527420587195390702907704944864932369865885144357990798078661*x + 4694516 3889986656942312064244366240832320064800593433556330540/90527420587195390702 907704944864932369865885144357990798078661], [x^3 + 2084*x^2 - 960*x + 64, - 561227570831357327261748722300671144714199316788821374765/374668834678013552 26040608060903790085031225603283152269884*x^26 - 467030323146825154773051563 1866750664171046908135280010511/14986753387120542090416243224361516034012490 2413132609079536*x^25 + 2655982187166666534628949444775506592906681662216895 80586573/149867533871205420904162432243615160340124902413132609079536*x^24 + 348189693874250542182197336832501857397062852480476420943493/74933766935602 710452081216121807580170062451206566304539768*x^23 - 11991930611906407551536 445364733429567610668847504070595479995/149867533871205420904162432243615160 340124902413132609079536*x^22 - 37235352814481353508805084287382560420754145 636609578106529157/149867533871205420904162432243615160340124902413132609079 536*x^21 + 66280866039627531860595064079889449185756276577079917533847481/37 466883467801355226040608060903790085031225603283152269884*x^20 + 97025825868 1296916077879398527505905523423187223670658505540191/14986753387120542090416 2432243615160340124902413132609079536*x^19 - 2943834022061190442942620941971 984643359379628448515131816679339/149867533871205420904162432243615160340124 902413132609079536*x^18 - 33453163819081176501607746814474780772199787876567 28390306807373/37466883467801355226040608060903790085031225603283152269884*x ^17 + 13674894571589217805893019967706794800106223373397441220281477961/1498 67533871205420904162432243615160340124902413132609079536*x^16 + 602078892442 5419464207909813876066699842494812053733761289242738/93667208669503388065101 52015225947521257806400820788067471*x^15 + 294353128177567374225243548890428 4513815971474029257246467871633/14986753387120542090416243224361516034012490 2413132609079536*x^14 - 1679924756905466276300271331479047571634361641324411 11855454223073/74933766935602710452081216121807580170062451206566304539768*x ^13 - 169267741415077227249195598342359460523011079667191272211912713953/149 867533871205420904162432243615160340124902413132609079536*x^12 + 58046585984 6163164837994249948641890283751158991278197371683104575/14986753387120542090 4162432243615160340124902413132609079536*x^11 + 2147410176527707658180995922 86832494196454603044510532036771347703/7493376693560271045208121612180758017 0062451206566304539768*x^10 - 2872787266706575737776271249101323331042903273 1768248245371736066/93667208669503388065101520152259475212578064008207880674 71*x^9 - 209256865896977388082011634232583311906433877889134968495769903035/ 74933766935602710452081216121807580170062451206566304539768*x^8 + 9685258147 1927815905027359872825120899862107832279504762470974403/14986753387120542090 4162432243615160340124902413132609079536*x^7 + 14832711113305345708607215075 6136089755982514457246759954599435889/14986753387120542090416243224361516034 0124902413132609079536*x^6 + 33168501411549202886974743354924252564559928858 971918327422562761/149867533871205420904162432243615160340124902413132609079 536*x^5 - 931928278647997781785460776674338081385763852142006458288593669/74 933766935602710452081216121807580170062451206566304539768*x^4 - 884320275796 39909365435795132422861390768710065327799424993805/9366720866950338806510152 015225947521257806400820788067471*x^3 - 936806802023053551712453814839333960 9995787303491086013553107/93667208669503388065101520152259475212578064008207 88067471*x^2 - 208351784599897404047289786553424700159852897511454373845310/ 9366720866950338806510152015225947521257806400820788067471*x + 1193113483585 5584097274884576748218224199275925940999633098/93667208669503388065101520152 25947521257806400820788067471], [x^3 - 51*x^2 + 48*x + 64, -1556489649355473 0802541434445630680122230637785713/69371377009148175174079939980762865583621 192509024*x^26 + 393501446137692897081827553127467296566229415669/8671422126 143521896759992497595358197952649063628*x^25 + 37344182946088564647085401854 93019023991368874788845/138742754018296350348159879961525731167242385018048* x^24 + 602926222827948364981856199181901144185734257180965/69371377009148175 174079939980762865583621192509024*x^23 - 16077924803290367253342138093970327 920188322691620725/12612977638026940940741807269229611924294762274368*x^22 - 3922406994747505217428135835740166290414595225993829/4335711063071760948379 996248797679098976324531814*x^21 + 21610264543463032674757067537962822239076 07275350339129/69371377009148175174079939980762865583621192509024*x^20 + 216 5332906631891276979111265349104518658030209781415135/69371377009148175174079 939980762865583621192509024*x^19 - 58971883561690962814857386897540236894683 583190758222363/138742754018296350348159879961525731167242385018048*x^18 - 8 08645284560840678162955816053077064211321736186290851/1576622204753367617592 725908653701490536845284296*x^17 + 45261307567929335788409099690641349911541 0773495517136907/138742754018296350348159879961525731167242385018048*x^16 + 4155848462327012334970630882373126743426565772330513255/97706164801617148132 5069577193843177234101302944*x^15 - 1916906407594845094913715796739119007763 588347723982336701/138742754018296350348159879961525731167242385018048*x^14 - 299986634866134590855571167455249119719959097988270586497/1734284425228704 3793519984995190716395905298127256*x^13 + 4619793814928435228565196907730980 082353574691727216335189/138742754018296350348159879961525731167242385018048 *x^12 + 78349128423247148069316494006284281559905812973178274922/21678555315 35880474189998124398839549488162265907*x^11 - 153594553777708340787226033909 9202940420314394485957829651/34685688504574087587039969990381432791810596254 512*x^10 - 1374248730618644771669596326725122660339183152162363418743/346856 88504574087587039969990381432791810596254512*x^9 + 1919162854225643871387126 081073397590088114675963996148559/693713770091481751740799399807628655836211 92509024*x^8 + 1636581600518698341122592802132989754567255132253863579141/69 371377009148175174079939980762865583621192509024*x^7 - 727051399465472071466 584875687608034262747495330744101465/138742754018296350348159879961525731167 242385018048*x^6 - 3129326368290877748444147730987503938931452439481078643/4 88530824008085740662534788596921588617050651472*x^5 - 7853272245711394369054 234379510390729335994591529342187/867142212614352189675999249759535819795264 9063628*x^4 + 418784664422249354368655241667072778856572355632199668/2167855 531535880474189998124398839549488162265907*x^3 + 397946744104206949165008228 423407476436082933606062359/867142212614352189675999249759535819795264906362 8*x^2 + 251390094927160964464702475829596929962821546628958/1970777755941709 52199090738581712686317105660537*x - 120287049627746942543990932319832935260 559012851341/2167855531535880474189998124398839549488162265907], [x^9 - 48*x ^8 + 174*x^7 + 14126*x^6 - 161823*x^5 + 385746*x^4 - 6675*x^3 - 36000*x^2 - 2448*x + 64, 178178188655743046634447029929429775436905591698460680780932100 496865/205964516518161148365604356303023392123365913321634271403375289329924 48*x^26 - 585564521969460077357680976548963715611696576170565261427516488163 5/2574556456477014354570054453787792401542073916520428392542191116624056*x^2 5 - 10687142837936058552014304459469637843322787822700061498629424693789001/ 10298225825908057418280217815151169606168295666081713570168764466496224*x^24 - 1402835507304473951065987980845947097369430580835560692715331310893721/51 49112912954028709140108907575584803084147833040856785084382233248112*x^23 + 1012900128203402102473485745427750041226576306008764551073032446477869925/20 596451651816114836560435630302339212336591332163427140337528932992448*x^22 + 328919581448673536238320354914122819802889778663415605005969834124974355/10 298225825908057418280217815151169606168295666081713570168764466496224*x^21 - 24790579215115629643252807365825638835640678700733064482849780918179925523/ 20596451651816114836560435630302339212336591332163427140337528932992448*x^20 - 5832173386907353146877015446206257884156389895865445571205228489686060047 /5149112912954028709140108907575584803084147833040856785084382233248112*x^19 + 1696111600359040840909273306891850706643173999758616474941310792478712626 35/10298225825908057418280217815151169606168295666081713570168764466496224*x ^18 + 9697080497106399861191897725886740668361334064940381998717473365130732 1643/5149112912954028709140108907575584803084147833040856785084382233248112* x^17 - 327120630399511077813977748140132153294726625367687415565755220838576 526321/257455645647701435457005445378779240154207391652042839254219111662405 6*x^16 - 1138999673083302844914685818871872035600808950711579060183082860884 5047711/72522717083859559283663505740501194409635884972406433592737777933072 *x^15 + 13972754134719749413326585357917408124657913013131895961405820974299 46258661/2574556456477014354570054453787792401542073916520428392542191116624 056*x^14 + 65851885655711698415709986878635451394614593495829489112190966898 67146999399/1029822582590805741828021781515116960616829566608171357016876446 6496224*x^13 - 2720653637087195067556980889397993529153592086209825470898788 5001814753969751/20596451651816114836560435630302339212336591332163427140337 528932992448*x^12 - 34293755135701575804420198501418430750514382699868104822 77918479570182936201/2574556456477014354570054453787792401542073916520428392 542191116624056*x^11 + 22835826439820082051418422065018962048491089627612609 78426528451857752896183/1287278228238507177285027226893896200771036958260214 196271095558312028*x^10 + 14947887342855499886534738267886765943220050885236 006331762672201405988749873/102982258259080574182802178151511696061682956660 81713570168764466496224*x^9 - 2312626178466862669742148746078905849305846413 1200007005664027600126057045919/20596451651816114836560435630302339212336591 332163427140337528932992448*x^8 - 445576096474071332751690815863648261275689 0661907234201680058799794426791471/51491129129540287091401089075755848030841 47833040856785084382233248112*x^7 + 4624705944018551774607971268900030697728 951454822215623885390104059701776587/205964516518161148365604356303023392123 36591332163427140337528932992448*x^6 + 8599900915430274139150759565472944105 816722893187288625260353285457226639/362613585419297796418317528702505972048 17942486203216796368888966536*x^5 + 8034752231162982963190541106207649014904 4362450082543846760021463982037425/25745564564770143545700544537877924015420 73916520428392542191116624056*x^4 - 8922522963571710266599529622404778968906 989375240265231503487119143065023/128727822823850717728502722689389620077103 6958260214196271095558312028*x^3 - 21144874691331414081453526729989154088688 08374418990056015683781028655257/1287278228238507177285027226893896200771036 958260214196271095558312028*x^2 - 192483049971516500402391596044759086577617 18632176246503489249504631097/3218195570596267943212568067234740501927592395 65053549067773889578007*x + 772370447994581394351475349432365497130635003149 339294507791334368751/321819557059626794321256806723474050192759239565053549 067773889578007], [x^9 + 99*x^8 + 1440*x^7 - 31531*x^6 + 21918*x^5 + 657516* x^4 - 412728*x^3 - 101232*x^2 - 4704*x + 64, -116775785290993381144377305824 508342289373090070606232293294852385637399/129654663148182442896147942292753 22534165884243596877384842474463318746016*x^26 + 552166192249122841691117037 564558605113925565497001189328618239765847369/285240258926001374371525473044 057095751649453359131302466534438193012412352*x^25 + 30797646004445989526038 9354175175129155748185908023135837408937764111256765/28524025892600137437152 5473044057095751649453359131302466534438193012412352*x^24 + 9548937104748672 2067604217301278561093619276908698815411389806740649145115/28524025892600137 4371525473044057095751649453359131302466534438193012412352*x^23 - 1457190262 1536833762306452679243678193359782225230874835173123442581019901013/28524025 8926001374371525473044057095751649453359131302466534438193012412352*x^22 - 5 073118360294215627279555750716078075739573108615793775479122727454113175915/ 142620129463000687185762736522028547875824726679565651233267219096506206176* x^21 + 222288182831921152527413812511774822190998494079156377266028775168506 19754407/1782751618287508589822034206525356848447809083494570640415840238706 3275772*x^20 + 3192268104418169501707726526426130696821166172727519861651402 5007215961315745/25930932629636488579229588458550645068331768487193754769684 948926637492032*x^19 - 48440665919063213836160970027368071803912510753947878 69169605809477979881385121/2852402589260013743715254730440570957516494533591 31302466534438193012412352*x^18 - 576157032248853180780745828304852594090428 3898322254036932624541470676168884155/28524025892600137437152547304405709575 1649453359131302466534438193012412352*x^17 + 3708017260965446785241454380744 9789527054845951753559142553988351117586485322367/28524025892600137437152547 3044057095751649453359131302466534438193012412352*x^16 + 6690532737232158463 06739724709248108090991883324363234427195339752480326510401/4017468435577484 146077823564000804165516189483931426795303301946380456512*x^15 - 15647336223 3854132825610078371890840094526749287076481504357502173381907576765179/28524 0258926001374371525473044057095751649453359131302466534438193012412352*x^14 - 19058607474696748298021760840723277900858668670358109594140791035299241669 8366147/28524025892600137437152547304405709575164945335913130246653443819301 2412352*x^13 + 3760501130250599632842150837484828093032120941847886194504246 34750660671639395111/2852402589260013743715254730440570957516494533591313024 66534438193012412352*x^12 + 194618130808416391775814659595407495648049868134 830027990122903410205676919898881/142620129463000687185762736522028547875824 726679565651233267219096506206176*x^11 - 12487466875264921887021926610814574 6988791012998543786000090321197456260187496439/71310064731500343592881368261 014273937912363339782825616633609548253103088*x^10 - 10302912988461472796984 0085996371342275695248315537711218283616740029260681078825/71310064731500343 592881368261014273937912363339782825616633609548253103088*x^9 + 391226077488 60089947316569637897236944176473734384191179581404758131894035826045/3565503 2365750171796440684130507136968956181669891412808316804774126551544*x^8 + 23 6791436304921675278668511641876113141565152478740335854961221227114230880915 635/285240258926001374371525473044057095751649453359131302466534438193012412 352*x^7 - 630310047255703733187591942383343386185406018610210158245704121817 78622927671947/2852402589260013743715254730440570957516494533591313024665344 38193012412352*x^6 - 4414056259818143328633827998833799596044572702988049946 80425955472862036771007/2008734217788742073038911782000402082758094741965713 397651650973190228256*x^5 - 944276862193647191236572777447563272665598810128 681991559924394348134257090533/356550323657501717964406841305071369689561816 69891412808316804774126551544*x^4 + 1152931981696616284615891384450236658814 02268276620622776231400099174946122829/1782751618287508589822034206525356848 4478090834945706404158402387063275772*x^3 + 63911647394393256923010357440864 74495628949058051998012436427850094434819152/4456879045718771474555085516313 392121119522708736426601039600596765818943*x^2 + 463132299442654665686412246 504660574754698118158865041528435016000535480469/891375809143754294911017103 2626784242239045417472853202079201193531637886*x - 9208473384290981762320762 179065375898275268983750393346913361377172631986/445687904571877147455508551 6313392121119522708736426601039600596765818943], [x^9 - 36*x^8 - 1581*x^7 - 2929*x^6 + 6342*x^5 + 13140*x^4 - 5496*x^3 - 14256*x^2 - 1632*x + 64, -91264 312653239983701677339387771012871773982715072549763565121697/313893413349304 9088141512594511220295539662206569996472570775568064*x^26 + 2745582646439785 84477295461966060388344340650830038564070601043341/3452827546842353996955663 8539623423250936284272269961198278531248704*x^25 + 1203965815809614488879224 74044847036629177847017731084385042343270615/3452827546842353996955663853962 3423250936284272269961198278531248704*x^24 + 3031925519530116108814534260803 9392794060378706535173405700888801025/34528275468423539969556638539623423250 936284272269961198278531248704*x^23 - 28518954338528671683342728763611931534 10321035165476507650507925792737/1726413773421176998477831926981171162546814 2136134980599139265624352*x^22 - 1820763297285515713967265577848039056258664 187729519639125160621742915/172641377342117699847783192698117116254681421361 34980599139265624352*x^21 + 139553735144038802830612649236255728367390088187 505648928779037635668371/345282754684235399695566385396234232509362842722699 61198278531248704*x^20 + 129686606522264455422841162767307824993100156224193 240593913110845200739/345282754684235399695566385396234232509362842722699611 98278531248704*x^19 - 173532953655053765496231468194247392183807099820540136 027251907055479893/313893413349304908814151259451122029553966220656999647257 0775568064*x^18 - 2157477331235938546809646641030311758841162089998282663463 720014029046761/345282754684235399695566385396234232509362842722699611982785 31248704*x^17 + 147200639187815395903446627577382567028901847339250410912658 02436213941351/3452827546842353996955663853962342325093628427226996119827853 1248704*x^16 + 1795722965295458382045568195813715108170495250683439616774057 6446505837301/34528275468423539969556638539623423250936284272269961198278531 248704*x^15 - 62861305847846745699518468082664906156499345022513346882708829 186805129423/345282754684235399695566385396234232509362842722699611982785312 48704*x^14 - 726990034788507410471959465283929848133294060418304485664994122 69535053991/3452827546842353996955663853962342325093628427226996119827853124 8704*x^13 + 7655821445485614815740348581605904625416871871803841414070808687 6767165807/17264137734211769984778319269811711625468142136134980599139265624 352*x^12 + 18740280729290702376768166717427932090712009519308402067176639829 485666773/431603443355294249619457981745292790636703553403374514978481640608 8*x^11 - 5153830538944909309488705674760851910658376375732381992123114243343 1877201/8632068867105884992389159634905855812734071068067490299569632812176* x^10 - 804182804496969247263648152816681379666915719606620345867191595892304 41945/17264137734211769984778319269811711625468142136134980599139265624352*x ^9 + 13150072800085550850048805482319300205089752530910115876141449706340982 3483/34528275468423539969556638539623423250936284272269961198278531248704*x^ 8 + 944269737518033467982150142657319754481410403815125791153115299566510871 95/34528275468423539969556638539623423250936284272269961198278531248704*x^7 - 13813955213489775578706620836640970336210852546815268784537605184487441961 /17264137734211769984778319269811711625468142136134980599139265624352*x^6 - 802271934030959556263962373968189966415033784342954215470502046665383015/107 9008608388235624048644954363231976591758883508436287446204101522*x^5 - 72451 7100962773427156670692738379583851925682226419513627174684155584211/86320688 67105884992389159634905855812734071068067490299569632812176*x^4 + 2418167612 5968096635225561790528764696326074242511085050335949381946643/10790086083882 35624048644954363231976591758883508436287446204101522*x^3 + 1004157410376915 7648641064714562586079600589195151968367072242288370801/21580172167764712480 97289908726463953183517767016872574892408203044*x^2 + 1711141209765523604984 48866349636866704202518064544969032341737623527/1079008608388235624048644954 363231976591758883508436287446204101522*x - 35031118434103246442769646163584 06962357832888273571276711411976738/5395043041941178120243224771816159882958 79441754218143723102050761], [x^9 - 96*x^8 + 2913*x^7 - 28705*x^6 + 12234*x^ 5 + 175548*x^4 - 110904*x^3 + 24528*x^2 - 2208*x + 64, 150464597533827861737 42015461484622984451943452088362123746955056657/3117448019913018583701561488 164299719684030835200018606598334807241824*x^26 - 65898798875673847752724420 76936563048347586086638330235490276563089/6234896039826037167403122976328599 439368061670400037213196669614483648*x^25 - 49596040460286201565423234730781 11384044599111339788219400805892643411/8572982054760801105179294092451824229 131084796800051168145420719915016*x^24 - 12141603218369585496713463730946078 783160573119585354378652218197968741/685838564380864088414343527396145938330 48678374400409345163365759320128*x^23 + 469246396711786900856367874322991480 727862807000605790905003330530467621/171459641095216022103585881849036484582 62169593600102336290841439830032*x^22 + 812026684590436831198902813308877329 84388462768190024292819119726682403/4286491027380400552589647046225912114565 542398400025584072710359957508*x^21 - 57252485621224171053610790079053074884 01540735497592584645496979991612211/8572982054760801105179294092451824229131 084796800051168145420719915016*x^20 - 45025655528787062067308044620887856565 260162652822461630327103538277392663/685838564380864088414343527396145938330 48678374400409345163365759320128*x^19 + 311812245399480577380344713687445211 651446733012893871452158592110284838411/342919282190432044207171763698072969 16524339187200204672581682879660064*x^18 + 738824930056479941811559746967838 338282351986280105053378936482919932569623/685838564380864088414343527396145 93833048678374400409345163365759320128*x^17 - 119286613136994729940998894984 4922438769660844714680847900869826335559755609/17145964109521602210358588184 903648458262169593600102336290841439830032*x^16 - 85718291300597573998646682 684253312757490588288040002137889973360241979299/965969808987132518893441587 881895687789418005273245202044554447314368*x^15 + 10060227424829357358617480 425423345222601099453443979677539887162221414563995/342919282190432044207171 76369807296916524339187200204672581682879660064*x^14 + 221440083349784089012 7701050423892962534315935571623448333454890318596338405/62348960398260371674 03122976328599439368061670400037213196669614483648*x^13 - 150971208159657906 9851149965333271398896932073879377746980651656779266372275/21432455136902002 76294823523112956057282771199200012792036355179978754*x^12 - 123841349445716 65906902737053577847916500272875472139962375420035554510095353/1714596410952 1602210358588184903648458262169593600102336290841439830032*x^11 + 1601727606 4226742567044256659232798000673939983517328094316742223158236359997/17145964 109521602210358588184903648458262169593600102336290841439830032*x^10 + 13027 667371741636275282946942427179589667888073059834172920586922129479988811/171 45964109521602210358588184903648458262169593600102336290841439830032*x^9 - 1 249795050842533952607898011139041343931767458160962146201655054789209199919/ 2143245513690200276294823523112956057282771199200012792036355179978754*x^8 - 270605827030395561198470270920088587032771851486899902221598365663845253040 9/6234896039826037167403122976328599439368061670400037213196669614483648*x^7 + 4986554526140487336384634300870192208642389731097457866557480606164182349 89/4286491027380400552589647046225912114565542398400025584072710359957508*x^ 6 + 691102780126791419969141024144208861749974585808631098263191971324745142 9/60373113061695782430840099242618480486838625329577825127784652957148*x^5 + 244477829204093556057635888982776362030706875207811209894915898021554766473 /17145964109521602210358588184903648458262169593600102336290841439830032*x^4 - 7089009901061870418772873999715539202969615640615901178397832665649979865 /2143245513690200276294823523112956057282771199200012792036355179978754*x^3 - 300413556215192122321647509858218440648415571439716751070265850713055549/3 89681002489127322962695186020537464960503854400002325824791850905228*x^2 - 6 2607373637686066421772012245577706993957689823422569362072179275009919/21432 45513690200276294823523112956057282771199200012792036355179978754*x + 139033 8607723961974464380565605508734659040794131017136124182385578780/10716227568 45100138147411761556478028641385599600006396018177589989377], [x^27 - 120*x^ 25 - 63*x^24 + 5673*x^23 + 5181*x^22 - 138003*x^21 - 167184*x^20 + 1865730*x ^19 + 2668613*x^18 - 14070078*x^17 - 21889917*x^16 + 57688596*x^15 + 8948208 9*x^14 - 132575217*x^13 - 190829625*x^12 + 164200812*x^11 + 215956974*x^10 - 86796519*x^9 - 129504396*x^8 + 1575183*x^7 + 32931993*x^6 + 9928740*x^5 + 4 9968*x^4 - 372144*x^3 - 50736*x^2 - 1344*x + 64, x]] 15: [[x, 0], [x^2 - 9*x + 26, 1/4*x^8 - 1/4*x^6 + 5/4*x^4 - 7/4*x^2 + 13/2], [x^4 + 9*x^2 + 26, -1/8*x^11 + 1/4*x^9 - 3/4*x^7 + x^5 - 13/8*x^3 + 1/4*x], [x^6 + 3*x^5 + 8*x^4 + 14*x^3 + 21*x^2 + 23*x + 26, -x^2], [x^6 - 6*x^5 + 1 8*x^4 - 36*x^3 + 53*x^2 - 52*x + 26, -1/16*x^10 - 1/8*x^9 + 1/8*x^8 + 3/8*x^ 7 - 3/8*x^6 - 5/8*x^5 + 1/2*x^4 + 5/8*x^3 - 13/16*x^2 - 3/4*x + 13/8], [x^6 - 6*x^5 + 18*x^4 - 36*x^3 + 53*x^2 - 52*x + 26, -1/16*x^10 + 1/8*x^9 + 1/8*x ^8 - 3/8*x^7 - 3/8*x^6 + 5/8*x^5 + 1/2*x^4 - 5/8*x^3 - 13/16*x^2 + 3/4*x + 1 3/8], [x^12 - 3*x^10 + 8*x^8 - 14*x^6 + 21*x^4 - 23*x^2 + 26, x]] 16: [[x + 8, -8], [x^2 - 128*x + 432, -63853319923935875733112922371/1966774 45849124016855404926596330*x^23 - 347020193457008939020832368879/13111829723 2749344570269951064220*x^22 + 1982575716076299992923868753999/19667744584912 4016855404926596330*x^21 + 19493268324409893257675589592367/1966774458491240 16855404926596330*x^20 - 14932100440413369856941006855715/786709783396496067 42161970638532*x^19 - 67744878698721403584811614689019/437060990775831148567 56650354740*x^18 + 174898430108209143532696301394817/65559148616374672285134 975532110*x^17 + 1091659012660063950399753242337676/983387229245620084277024 63298165*x^16 - 31871852329624596113344375061168/134710579348715080037948579 8605*x^15 - 244046691963636257474551069780003/855119329778800073284369246071 0*x^14 + 16914117747207052855867936091832763/1966774458491240168554049265963 30*x^13 + 352042453850719240333222491668827/39335489169824803371080985319266 *x^12 - 13741518852590675208071626279654969/98338722924562008427702463298165 *x^11 + 1241568198829120261307917362777269/13563961782698208058993443213540* x^10 + 9654446830505254415463413843706103/196677445849124016855404926596330* x^9 - 11415227965484593081409990734676318/98338722924562008427702463298165*x ^8 + 32598724049685323796271849547813467/393354891698248033710809853192660*x ^7 - 528773939007352577000940657428188/19667744584912401685540492659633*x^6 - 30013863579657220176453366895779967/196677445849124016855404926596330*x^5 + 8395004490545366622815116016736529/196677445849124016855404926596330*x^4 - 4005311266907432823376705250987299/43706099077583114856756650354740*x^3 - 1 0434735356465814055105764148854887/393354891698248033710809853192660*x^2 + 3 443184498214169462961749332429279/65559148616374672285134975532110*x + 15116 602831050450769752445128065041/196677445849124016855404926596330], [x^3 + 8* x^2 - 224*x + 832, -25167798587599067474576627480079175785311/12391180178858 71369570044909938690767230139380*x^23 - 629381005050427357633379262860193288 59863/371735405365761410871013472981607230169041814*x^22 + 73063468282620141 6701968149575006679565931/1239118017885871369570044909938690767230139380*x^2 1 + 10326356023409929244005814719241662887497083/165215735718116182609339321 3251587689640185840*x^20 - 9527595290655738777730304003808686117484103/92933 8513414403527177533682454018075422604535*x^19 - 7182269062008195914677380953 9929284189557075/743470810731522821742026945963214460338083628*x^18 + 203704 8120273075143767701314314087192010861299/14869416214630456434840538919264289 206761672560*x^17 + 2047597832114659016884010941347229611101357321/297388324 2926091286968107783852857841352334512*x^16 - 5970672241502210208992454142441 947745762049/5092265826928238505082376342213797673548518*x^15 - 612073735395 038122826306433768432119908872467/323248178578922965974794324331832374060036 360*x^14 + 1121147049647191018123239530328482820809271433/309779504471467842 392511227484672691807534845*x^13 + 19202612990354992415990096137657665767199 83457/826078678590580913046696606625793844820092920*x^12 - 31836941441515018 097310599095971704502960344507/743470810731522821742026945963214460338083628 0*x^11 - 429923037654339845298230104518334151252052071/256369245079835455773 112739987315331151063320*x^10 - 66066567140940412290718921432354966580277235 1/2478236035771742739140089819877381534460278760*x^9 + 845107242349572808223 8958177949283169510746053/1652157357181161826093393213251587689640185840*x^8 + 571456667518488282535990065275685445420915711/743470810731522821742026945 963214460338083628*x^7 - 40987718259023987123110871072594114727149233283/743 4708107315228217420269459632144603380836280*x^6 - 12442975498817761454150693 158095724275856679829/1652157357181161826093393213251587689640185840*x^5 - 5 787931825323004141890817142718039502657962799/123911801788587136957004490993 8690767230139380*x^4 + 6336476749528282806129322474762881455933674451/743470 8107315228217420269459632144603380836280*x^3 - 36998997560438657374619789272 480718742278003/495647207154348547828017963975476306892055752*x^2 - 19368530 540770431766052137116415061665505291693/148694162146304564348405389192642892 06761672560*x + 22661897566194450311787210499625704062202984207/495647207154 3485478280179639754763068920557520], [x^3 + 8*x^2 - 288*x + 832, 68364404746 903530024663065757008379579955/581171881309459312442391330267291824333509443 63*x^23 + 407018094398282215126229404324184695928621/11623437626189186248847 8266053458364866701888726*x^22 - 1846342647374143836526239251659707362713159 1/232468752523783724976956532106916729733403777452*x^21 - 104319145852502097 726417979402988924882380925/929875010095134899907826128427666918933615109808 *x^20 + 544645884665062890915770180576266315439973353/2324687525237837249769 56532106916729733403777452*x^19 - 571087973351048776307830735034211879963335 57/232468752523783724976956532106916729733403777452*x^18 - 32634449384411587 311921727417502938376980295137/929875010095134899907826128427666918933615109 808*x^17 + 5109984413175970220050697757257255410691829557/103319445566126099 989758458714185213214846123312*x^16 + 63834497382931344472264386071524333891 257697/265375288269159503398352205601503116134022577*x^15 - 3180032649381151 67955428829968481196292272256965/4649375050475674499539130642138334594668075 54904*x^14 - 32758026171964994776099258362315044592758611151/116234376261891 862488478266053458364866701888726*x^13 + 13950580052378885880698431611713106 31447183684601/464937505047567449953913064213833459466807554904*x^12 - 36713 8669921305627112153919132682656188637214155/15497916834918914998463768807127 7819822269184968*x^11 - 9344350691334055924155794611473267518951813359/17813 69751140105172237214805416986434738726264*x^10 + 445418222695092774567764884 0473205808434425052699/464937505047567449953913064213833459466807554904*x^9 + 532735991282814263758070069339436465634811057629/9298750100951348999078261 28427666918933615109808*x^8 - 3097041132005892702978963412137429379401585681 943/232468752523783724976956532106916729733403777452*x^7 + 47107732208383237 91495995968582774999138838194793/4649375050475674499539130642138334594668075 54904*x^6 + 4680094261142940356595699040461088668345290745295/92987501009513 4899907826128427666918933615109808*x^5 - 31772068877699035216127743260740332 40872898935249/232468752523783724976956532106916729733403777452*x^4 + 267602 3300754930565238673841878460022598929454265/46493750504756744995391306421383 3459466807554904*x^3 + 1973867445762173054028454079380253917823814402527/464 937505047567449953913064213833459466807554904*x^2 - 452745708031015599250534 7554656042387453269590969/929875010095134899907826128427666918933615109808*x + 4513082178431793136859575419012685513290234695549/92987501009513489990782 6128427666918933615109808], [x^3 + 8*x^2 - 176*x + 256, -1291795034206608863 62191055636986486401/5348195879528384571737930341960898650842570*x^23 - 1017 388578405808067580350543227199930467/534819587952838457173793034196089865084 2570*x^22 + 17293020253475804663513339324112592886509/2139278351811353828695 1721367843594603370280*x^21 + 153591004975668357616122953689943413579981/213 92783518113538286951721367843594603370280*x^20 - 195257710452618747974251461 30654489573679/1188487973228529904830651187102421922409460*x^19 - 2394000234 493207441559886062250365661371359/213927835181135382869517213678435946033702 80*x^18 + 2548502849189477343363734355824249444564159/1069639175905676914347 5860683921797301685140*x^17 + 16559618779681825783245163882758786645690143/2 1392783518113538286951721367843594603370280*x^16 - 2253812945412770680253754 6686894078901186431/10696391759056769143475860683921797301685140*x^15 - 2386 49100524803675730685640840718761757387/1550201704211125962822588504916202507 49060*x^14 + 83764510804010183344194485774562389670847129/106963917590567691 43475860683921797301685140*x^13 - 724007625467909157262967431788072319623749 8/2674097939764192285868965170980449325421285*x^12 - 65813656109345475127909 062133316902447218653/5348195879528384571737930341960898650842570*x^11 + 429 75845367520331985190157408978391239733028/2674097939764192285868965170980449 325421285*x^10 + 7169267563324905872474977052289419196241397/213927835181135 38286951721367843594603370280*x^9 - 4085299109515478220857392480376490666731 84261/21392783518113538286951721367843594603370280*x^8 + 1605463393210303557 3446511836165145052704493/891365979921397428622988390326816441807095*x^7 - 1 1976704743917628507434028345515781505450429/23769759464570598096613023742048 43844818920*x^6 - 337905522070797040728739459350043422683071433/213927835181 13538286951721367843594603370280*x^5 + 1905156900839662827301096172627475123 96974077/10696391759056769143475860683921797301685140*x^4 - 1679791704686921 31031722771982103131653648097/10696391759056769143475860683921797301685140*x ^3 - 126098373977878421269087002029319424484684681/2139278351811353828695172 1367843594603370280*x^2 + 114130769395071974525095359635352451213259051/1069 6391759056769143475860683921797301685140*x - 1852565384501048222774521568355 2153251778309/4278556703622707657390344273568718920674056], [x^4 + 8*x^3 + 2 4*x^2 + 24*x + 16, 797586616242660780670544616783278840027/93203209582363941 194709877980669191536824720*x^23 + 416930024946098786179648458855064651064/5 825200598897746324669367373791824471051545*x^22 - 76483139002173486712024594 82579537616379/31067736527454647064903292660223063845608240*x^21 - 490116417 570507717782256988318382238102971/186406419164727882389419755961338383073649 440*x^20 + 401479600928580479150821819436198970287551/9320320958236394119470 9877980669191536824720*x^19 + 418723798220495877200291178100828144075573/103 55912175818215688301097553407687948536080*x^18 - 110146073037221150383706821 65405081545163563/186406419164727882389419755961338383073649440*x^17 - 52942 801431544551995159688249513710795991263/186406419164727882389419755961338383 073649440*x^16 + 12242700330402727625801859343924334575476719/23300802395590 985298677469495167297884206180*x^15 + 66165807124282508781305344105235930331 108373/93203209582363941194709877980669191536824720*x^14 - 22950727122632699 79924417185269170856043297/1294489021977276961037637194175960993567010*x^13 - 19146732166941600924433106357183343366881023/93203209582363941194709877980 669191536824720*x^12 + 35890897250549504054728654280046515364193021/15533868 263727323532451646330111531922804120*x^11 - 18615941477917969938728982456122 3869178185397/93203209582363941194709877980669191536824720*x^10 + 4163070985 32453007601505238856238804612211/647244510988638480518818597087980496783505* x^9 + 287757327733184487152262147810851296810166311/186406419164727882389419 755961338383073649440*x^8 - 68358421103456607009255404623620124209598979/233 00802395590985298677469495167297884206180*x^7 + 1018360144986811239148930243 63517723739380599/46601604791181970597354938990334595768412360*x^6 + 6648397 6998090365966441619595197217331832127/20711824351636431376602195106815375897 072160*x^5 + 48087864063875215970746866353480398693077223/932032095823639411 94709877980669191536824720*x^4 + 2336146371036484790434237269814921810505094 7/5825200598897746324669367373791824471051545*x^3 + 319288179836847038859497 79257443509042046649/46601604791181970597354938990334595768412360*x^2 + 3603 65600143693048930795243805489756245941713/1864064191647278823894197559613383 83073649440*x - 13773231328822549892612253248252528613609411/414236487032728 6275320439021363075179414432], [x^4 + 8*x^3 + 24*x^2 + 24*x + 16, -488736511 558300125692146988636796617179/95578380347448095121483086750097588285896736* x^23 - 2051932177967284799581018723934835044459/5309910019302671951193504819 4498660158831520*x^22 + 14517814543943288309153164167882045028759/7964865028 9540079267902572291747990238247280*x^21 + 1392663827938882169506189996340090 27125571/95578380347448095121483086750097588285896736*x^20 - 923937492475388 986204658550803232214661557/238945950868620237803707716875243970714741840*x^ 19 - 10631029772526434455295915370434401838939803/47789190173724047560741543 3750487941429483680*x^18 + 13232150180027486337799985973119575983730111/2389 45950868620237803707716875243970714741840*x^17 + 171179212934529535946568728 17556318499321911/119472975434310118901853858437621985357370920*x^16 - 10970 3774841359229762900118681090656000872273/23894595086862023780370771687524397 0714741840*x^15 - 38171088413014548603260111248314077702032/2164365496998371 71923648294271054321299585*x^14 + 193992073164158769423639985280476876083008 43/13274775048256679877983762048624665039707880*x^13 - 485909976509256122795 4831797349179479998895/5973648771715505945092692921881099267868546*x^12 - 74 7694190985765990865555663083248713479035647/47789190173724047560741543375048 7941429483680*x^11 + 436434976101863543377189366772544232044840017/159297300 579080158535805144583495980476494560*x^10 - 69114826050221450249069274996582 793300440569/39824325144770039633951286145873995119123640*x^9 - 590684763980 745767673635614634720526563044811/477891901737240475607415433750487941429483 680*x^8 + 379779415104260449606302623291513345166050495/95578380347448095121 483086750097588285896736*x^7 - 8819608414588227103160201248693726722042285/2 654955009651335975596752409724933007941576*x^6 - 140521448998820557119363816 656940918131422723/79648650289540079267902572291747990238247280*x^5 + 126216 8829341241906720696926886552986776800959/47789190173724047560741543375048794 1429483680*x^4 - 57844968154351950070234769626930248895643429/15929730057908 015853580514458349598047649456*x^3 + 881301280989954919647791802483929254073 024561/477891901737240475607415433750487941429483680*x^2 + 29243370469732450 440677221435538723375090369/19912162572385019816975643072936997559561820*x - 47011330840295019461394642343977534957826491/265495500965133597559675240972 49330079415760], [x^4 + 8*x^3 + 24*x^2 + 248*x + 1744, 219672788337945683139 27675097089313745104160955047/1014922463372614382177445798597477834284022303 635334456*x^23 + 451687949693457121990886779621285611194341334145487/2537306 158431535955443614496493694585710055759088336140*x^22 - 13382516981582247552 47406174486075310765498060572731/2029844926745228764354891597194955668568044 607270668912*x^21 - 4223856776965630429359975395444009155302560885943337/634 326539607883988860903624123423646427513939772084035*x^20 + 51461276114821276 38912060431639907463590080095940249/4228843597385893259072690827489490976183 42626514722690*x^19 + 105936163610012076872125349335497405382040687559737968 9/10149224633726143821774457985974778342840223036353344560*x^18 - 3452344986 70983358763303874528795477249298778155336817/2029844926745228764354891597194 955668568044607270668912*x^17 - 19182792473542713025398308867987412778610410 19894694197/2537306158431535955443614496493694585710055759088336140*x^16 + 1 05629504409321431307553638640481644623085206126643607/6951523721730235494366 0671136813550293426185180502360*x^15 + 3784770371195205864845116670473718252 6338800845507061/18386276510373448952489960119519525983406201152814030*x^14 - 5667555402115990253347794530780260472114097324564393497/101492246337261438 2177445798597477834284022303635334456*x^13 - 6641638794910391960936620673185 168682231598789447099287/507461231686307191088722899298738917142011151817667 2280*x^12 + 24049764175786070793476825475231470529143359000282678811/2537306 158431535955443614496493694585710055759088336140*x^11 - 16008808436687663096 8087023738250605484861574103897979/34997326323193599385429165468878546009793 872539149464*x^10 - 48963475354535881489960109688076686948554461694434405349 /10149224633726143821774457985974778342840223036353344560*x^9 + 170107818254 2242003068275881477787526790107232819436613/25373061584315359554436144964936 9458571005575908833614*x^8 - 11539471305543338750986400623650399774098712516 10932353/422884359738589325907269082748949097618342626514722690*x^7 + 709764 703822713854140140055431911423015308135885895003/338307487790871460725815266 1991592780946741012117781520*x^6 + 23208255318049227426850418921476949716547 254062896852519/2537306158431535955443614496493694585710055759088336140*x^5 + 267452972565485887755305340342359338986825994184278195/1014922463372614382 177445798597477834284022303635334456*x^4 + 230801947204155727991302777461721 57190069965693854287359/5074612316863071910887228992987389171420111518176672 280*x^3 + 8746785179662579050668569130655251913092563603040368361/1014922463 3726143821774457985974778342840223036353344560*x^2 + 38066887924252694224202 134807737382611963682052887562207/101492246337261438217744579859747783428402 23036353344560*x - 16613935596769377706629903068976014792030072749138987127/ 2537306158431535955443614496493694585710055759088336140], [x^4 + 8*x^3 + 24* x^2 + 24*x + 16, 69447805351768765373607565352615156828747/18417623689593630 845389455585205871067752496480*x^23 + 48640037439929590831569926526232920584 1653/18417623689593630845389455585205871067752496480*x^22 - 4305686882583414 087262398642542662585554199/27626435534390446268084183377808806601628744720* x^21 - 241133464788758001152646064492803285353837/23022029611992038556736819 4815073388346906206*x^20 + 5549107294305918846419681800867339542504913/15348 01974132802570449121298767155922312708040*x^19 + 917486582561884963358107715 313211136054340247/55252871068780892536168366755617613203257489440*x^18 - 29 27354856021208654007261816804903495079660893/5525287106878089253616836675561 7613203257489440*x^17 - 6148011192251326623690910612187753151553441693/55252 871068780892536168366755617613203257489440*x^16 + 16659158095393614901761014 7373263173924359927/378444322388910222850468265449435706871626640*x^15 + 421 6098805893565312642385142134546955723496939/27626435534390446268084183377808 806601628744720*x^14 - 2675983732556069521507138217026200808136829743/172665 2220899402891755261461113050412601796545*x^13 + 1788310169033395499344701721 175832375461702153/3069603948265605140898242597534311844625416080*x^12 + 444 52081743594001532680179309546559943546054917/1841762368959363084538945558520 5871067752496480*x^11 - 4319567159583304716923734589250498326591184061/19052 71416164858363316150577779917696664051360*x^10 - 142504104702325246299495674 47312513258558075343/27626435534390446268084183377808806601628744720*x^9 + 3 69708578125450862509474360053533543924733249/1918502467666003213061401623458 94490289088505*x^8 - 11967368496526327137675654041396737888341317791/6139207 896531210281796485195068623689250832160*x^7 + 333348487477700398549377560262 74482346958723413/27626435534390446268084183377808806601628744720*x^6 + 3868 30470483318083897419896567302981752609111/2412789129641087010313029115965834 63769683360*x^5 - 18842604735018897070130480283341577785106480877/6139207896 531210281796485195068623689250832160*x^4 + 209390199785183771570549524271665 4690321405155/1841762368959363084538945558520587106775249648*x^3 - 123877769 054334108036625667326870432576253219071/552528710687808925361683667556176132 03257489440*x^2 - 7925487180434948895501097569391545353202549677/36835247379 18726169077891117041174213550499296*x - 267455378231931860912020044636251354 79025638959/11050574213756178507233673351123522640651497888], [x^6 + 8*x^5 - 224*x^4 + 3584*x^2 + 2048*x - 4096, -21967278833794568313927675097089313745 104160955047/1522383695058921573266168697896216751426033455453001684*x^23 - 451687949693457121990886779621285611194341334145487/380595923764730393316542 1744740541878565083638632504210*x^22 + 1338251698158224755247406174486075310 765498060572731/3044767390117843146532337395792433502852066910906003368*x^21 + 8447713553931260858719950790888018310605121771886674/19029796188236519665 82710872370270939282541819316252105*x^20 - 514612761148212763891206043163990 7463590080095940249/634326539607883988860903624123423646427513939772084035*x ^19 - 1059361636100120768721253493354974053820406875597379689/15223836950589 215732661686978962167514260334554530016840*x^18 + 34523449867098335876330387 4528795477249298778155336817/30447673901178431465323373957924335028520669109 06003368*x^17 + 1918279247354271302539830886798741277861041019894694197/3805 959237647303933165421744740541878565083638632504210*x^16 - 10562950440932143 1307553638640481644623085206126643607/10427285582595353241549100670522032544 0139277770753540*x^15 - 1261590123731735288281705556824572750877960028183568 7/9193138255186724476244980059759762991703100576407015*x^14 + 56675554021159 90253347794530780260472114097324564393497/1522383695058921573266168697896216 751426033455453001684*x^13 + 66416387949103919609366206731851686822315987894 47099287/7611918475294607866330843489481083757130167277265008420*x^12 - 2404 9764175786070793476825475231470529143359000282678811/38059592376473039331654 21744740541878565083638632504210*x^11 + 160088084366876630968087023738250605 484861574103897979/52495989484790399078143748203317819014690808808724196*x^1 0 + 48963475354535881489960109688076686948554461694434405349/152238369505892 15732661686978962167514260334554530016840*x^9 - 1701078182542242003068275881 477787526790107232819436613/380595923764730393316542174474054187856508363863 250421*x^8 + 1153947130554333875098640062365039977409871251610932353/6343265 39607883988860903624123423646427513939772084035*x^7 - 7097647038227138541401 40055431911423015308135885895003/5074612316863071910887228992987389171420111 518176672280*x^6 - 23208255318049227426850418921476949716547254062896852519/ 3805959237647303933165421744740541878565083638632504210*x^5 - 26745297256548 5887755305340342359338986825994184278195/15223836950589215732661686978962167 51426033455453001684*x^4 - 2308019472041557279913027774617215719006996569385 4287359/7611918475294607866330843489481083757130167277265008420*x^3 - 874678 5179662579050668569130655251913092563603040368361/15223836950589215732661686 978962167514260334554530016840*x^2 + 228284598781041687064446131081112874450 77656165232505153/15223836950589215732661686978962167514260334554530016840*x + 11539323279906305795742674075988625620609961230962314847/3805959237647303 933165421744740541878565083638632504210], [x^6 + 8*x^5 - 96*x^4 - 448*x^3 + 4352*x^2 - 9216*x + 4096, -3500954735160931119014945191286514244723143201268 91/30447673901178431465323373957924335028520669109060033680*x^23 - 368753192 376745612767576249150695148256008996498511/380595923764730393316542174474054 1878565083638632504210*x^22 + 1222625548165299105222761470379044939248540356 671807/3805959237647303933165421744740541878565083638632504210*x^21 + 269066 12703922440457002658814457944899258851853285507/7611918475294607866330843489 481083757130167277265008420*x^20 - 32744711717911473968833608836796502659132 601780070963/6089534780235686293064674791584867005704133821812006736*x^19 - 821215527972063467089717577787130145191745484957891347/152238369505892157326 61686978962167514260334554530016840*x^18 + 719519555995694923374695500139118 398858293255363049029/101492246337261438217744579859747783428402230363533445 60*x^17 + 11456591503899749478776843861204390272634390714911041293/304476739 01178431465323373957924335028520669109060033680*x^16 - 126204248534422370494 879068149453132967995005612845677/208545711651907064830982013410440650880278 555541507080*x^15 - 53531955812109655939472657032353807104275538376490069/55 158829531120346857469880358558577950218603458442090*x^14 + 26202308497279151 618253227373408437905565991764550480251/152238369505892157326616869789621675 14260334554530016840*x^13 + 354501989648103752047502920687867766560793495564 3395919/3805959237647303933165421744740541878565083638632504210*x^12 - 13113 890767927935230296960282562651862223700759508281357/101492246337261438217744 57985974778342840223036353344560*x^11 - 192082355663057123910705211616724893 129593397695446143/524959894847903990781437482033178190146908088087241960*x^ 10 - 9075733795262301087631564506281286680882246660124904363/380595923764730 3933165421744740541878565083638632504210*x^9 + 49456672348902714074007125072 616599461038794256834978203/152238369505892157326616869789621675142603345545 30016840*x^8 + 36666141424661985681937782663463554650862812240098411231/1522 3836950589215732661686978962167514260334554530016840*x^7 - 82408754732311433 70973635583124680417011947954932254389/1691537438954357303629076330995796390 473370506058890760*x^6 - 119558618647824072907167067569787864040350402317013 169449/30447673901178431465323373957924335028520669109060033680*x^5 - 841455 23660896882078649693962881935941270834937407797919/3044767390117843146532337 3957924335028520669109060033680*x^4 - 62972355756385214926235004866384135061 546328061654626117/30447673901178431465323373957924335028520669109060033680* x^3 - 1104223987741025090975428994366940678681301630289615753/25373061584315 35955443614496493694585710055759088336140*x^2 - 4062551484247078790667379350 0102030712257870147945309931/30447673901178431465323373957924335028520669109 060033680*x + 63791074728602678092728158519442947086183797037123189561/30447 673901178431465323373957924335028520669109060033680], [x^6 + 8*x^5 - 128*x^4 - 336*x^3 + 7216*x^2 - 13120*x - 27904, 68395468625287412392477690238745594 48112516050997/529524763498755329831710851442162348322098593201044064*x^23 + 264057752641949424493842106909461112590467967337481/26476238174937766491585 54257210811741610492966005220320*x^22 - 974650745949411817591373952935998638 29212493378033/220635318124481387429879521434234311800874413833768360*x^21 - 4941506074493296333553606068488925730493565848754739/1323811908746888324579 277128605405870805246483002610160*x^20 + 24078898601220202511610606643783446 43832988608729965/264762381749377664915855425721081174161049296600522032*x^1 9 + 16743486854633442145271927295191821763033605591256547/294180424165975183 239839361912312415734499218445024480*x^18 - 34317973686366666262503682270060 8765518234232496961533/26476238174937766491585542572108117416104929660052203 20*x^17 - 981102178436040493756473234328095480400180483728045283/26476238174 93776649158554257210811741610492966005220320*x^16 + 196920256616637674628715 31157832943814657336924119077/1813440970886148389834626203569049138089378743 8391920*x^15 + 689090669649716376532960462282604780676889170615347111/132381 1908746888324579277128605405870805246483002610160*x^14 - 1273683806791508562 85638496849037298953730047095610861/3677255302074689790497992023903905196681 2402305628060*x^13 + 2485351815425058020615521703184464791386487277406174907 /1323811908746888324579277128605405870805246483002610160*x^12 + 312382368194 6147368634637399354195683346858273744081353/88254127249792554971951808573693 7247203497655335073440*x^11 - 6287938069412429299642811500856899956945062877 53952631/91297373017026781005467388179683163503810102276042080*x^10 + 108496 5570278322118820496988195911861039316141818223213/22063531812448138742987952 1434234311800874413833768360*x^9 + 49738705590952448136202078366786630967472 35255881648837/1323811908746888324579277128605405870805246483002610160*x^8 - 30564883782772692313551672403250018729763244239306584093/264762381749377664 9158554257210811741610492966005220320*x^7 + 55983370269919396444243378427028 95394755251639721124809/6619059543734441622896385643027029354026232415013050 80*x^6 + 6468781183225860084941162895575323110987873786198460187/88254127249 7925549719518085736937247203497655335073440*x^5 - 24852977506194092170356774 803279205001209040292120132861/264762381749377664915855425721081174161049296 6005220320*x^4 + 1327972991473283508138105984790596622315886735312127307/165 476488593361040572409641075675733850655810375326270*x^3 + 299632919694526912 082388120687014152052200719486935981/529524763498755329831710851442162348322 098593201044064*x^2 - 702367680592129411469173646967083897138855141470308193 1/2647623817493776649158554257210811741610492966005220320*x + 12028355404631 0749679541443128494550924664806994372701/17650825449958510994390361714738744 9440699531067014688], [x^6 + 8*x^5 - 72*x^4 - 112*x^3 + 1472*x^2 - 4800*x + 12352, -248324288537794230037344308658506264756917300289/2876492574509062963 1859588056612503569693593867794080*x^23 - 1788748620824073658480983802303622 157316650910699/28764925745090629631859588056612503569693593867794080*x^22 + 4893922720628537561273452838882757793231219431109/1438246287254531481592979 4028306251784846796933897040*x^21 + 3477085372182623557557010422509100552156 7114446533/14382462872545314815929794028306251784846796933897040*x^20 - 2329 267418517221917544908110719619940474852418971/299634643178027391998537375589 713578850974936122855*x^19 - 36211036674871834249014731942467873276992413301 1069/9588308581696876543953196018870834523231197955931360*x^18 + 66399259316 0132006401578900951086063888768596769503/57529851490181259263719176113225007 13938718773558816*x^17 + 708474306805082797315250059590332816571738207608904 7/28764925745090629631859588056612503569693593867794080*x^16 - 1419886558510 5681836944633021110852794734453458011539/14382462872545314815929794028306251 784846796933897040*x^15 - 14769419898249128084480146170042786528408477556530 7/625324472719361513736078001230706599341165084082480*x^14 + 323960664350904 9016930803198865984070727960224129333/89890392953408217599561212676914073655 2924808368565*x^13 - 34123747442987175586246571318801027001553844802359467/1 4382462872545314815929794028306251784846796933897040*x^12 - 1555307524104889 57676817582740630777142530887261952459/2876492574509062963185958805661250356 9693593867794080*x^11 + 5611065044029938661851758835069339903558371291080869 /639220572113125102930213067924722301548746530395424*x^10 - 1329990693517910 3545685384332880895809075669624695873/14382462872545314815929794028306251784 846796933897040*x^9 - 132902926244065063289565453777965966565360552060333181 /14382462872545314815929794028306251784846796933897040*x^8 + 321060842687100 19760073062384633292977314710996745003/3196102860565625514651065339623611507 743732651977120*x^7 - 52582446308425500485788625618509529958229776403424113/ 14382462872545314815929794028306251784846796933897040*x^6 - 1855903197408266 50666702624481311839541729106810034121/2876492574509062963185958805661250356 9693593867794080*x^5 + 34698179995887962509230000075311213988219795782233967 3/28764925745090629631859588056612503569693593867794080*x^4 - 10747995470738 3134704504984330387320654093888816006317/14382462872545314815929794028306251 784846796933897040*x^3 - 801447974127260299398566407668416155686883036376243 /1917661716339375308790639203774166904646239591186272*x^2 + 2513150246512834 81146307861918871333436359512535194513/2876492574509062963185958805661250356 9693593867794080*x - 93791254118396714369508841824281931691346215907343683/2 8764925745090629631859588056612503569693593867794080], [x^6 - 128*x^5 + 5872 *x^4 - 110336*x^3 + 795392*x^2 - 2438144*x + 2768896, 5649470056065977450530 82001281171957988403/14869416214630456434840538919264289206761672560*x^23 + 4576532719144485338350431459895444546264559/14869416214630456434840538919264 289206761672560*x^22 - 3519537609094748522281539121681598929028575/297388324 2926091286968107783852857841352334512*x^21 - 8534861125502448321599130492222 7654302765421/7434708107315228217420269459632144603380836280*x^20 + 54858101 671222010860445203162434994118109361/247823603577174273914008981987738153446 0278760*x^19 + 1323404357548547002222338506563276589994897211/74347081073152 28217420269459632144603380836280*x^18 - 563534094015914174167325245459659833 497439479/1858677026828807054355067364908036150845209070*x^17 - 186767130335 43179605037598406725254681267964793/1486941621463045643484053891926428920676 1672560*x^16 + 65240068584557528892049749665489366182509043/2546132913464119 2525411881711068988367742590*x^15 + 6944007180578281149330884958150231801623 2949/21549878571928197731652954955455491604002424*x^14 - 1219174587667121314 5097649705621399806172628349/1486941621463045643484053891926428920676167256* x^13 - 11531509639587328119129820371087061958449864373/371735405365761410871 0134729816072301690418140*x^12 + 3363722933903668618222259839078028556777794 7539/2973883242926091286968107783852857841352334512*x^11 + 57048978793036875 266208398722224476402917621/512738490159670911546225479974630662302126640*x^ 10 - 9931723438897636702730021299455125408949339377/297388324292609128696810 7783852857841352334512*x^9 - 8324380555078678334003224973705739159475574969/ 1486941621463045643484053891926428920676167256*x^8 + 23080865038452497904061 85266061420043751198217/4956472071543485478280179639754763068920557520*x^7 + 13674858885676639879037946066055961216170017553/165215735718116182609339321 3251587689640185840*x^6 + 41735059483006355414229520171038669516050144171/29 73883242926091286968107783852857841352334512*x^5 + 7186190271448691755023431 380567195860042576223/2973883242926091286968107783852857841352334512*x^4 - 1 4405581188606609112904525272472545779340276021/74347081073152282174202694596 32144603380836280*x^3 - 2614630846638350869102700103520575851369849617/18586 77026828807054355067364908036150845209070*x^2 + 1884514305024652071465391873 9958781841298690819/7434708107315228217420269459632144603380836280*x + 58868 217835201339274718911108764026097012470569/148694162146304564348405389192642 89206761672560], [x^6 - 128*x^5 + 5796*x^4 - 112752*x^3 + 974512*x^2 - 23552 64*x - 5548544, 1568657609589000676489632398214484238355739331/4277425046437 6205395760001907672678270946295051168*x^23 + 1310392797443712975720057683918 5412785996084631/42774250464376205395760001907672678270946295051168*x^22 - 7 825752530749745195712621956219300646309315241/712904174406270089929333365127 8779711824382508528*x^21 - 494925130009383521126186614863393761465958337453/ 42774250464376205395760001907672678270946295051168*x^20 + 425517647316621894 914327362265995304687924955347/213871252321881026978800009538363391354731475 25584*x^19 + 2637895609954650813151566780872822762028959587285/1425808348812 5401798586667302557559423648765017056*x^18 - 3012474760399789309765163253180 255286915598006995/10693562616094051348940000476918169567736573762792*x^17 - 30006077141420698676975375468669190716885674983923/213871252321881026978800 00953836339135473147525584*x^16 + 777088102733057353928882078089759179960608 504941/292974318249152091751780834984059440211960925008*x^15 + 2032340189594 403927077993499458301866711231975891/464937505047567449953913064213833459466 807554904*x^14 - 39621258846105079185530791539914545643343648203425/35645208 72031350449646666825639389855912191254264*x^13 - 433727716793143290401944109 47762103910151042829479/10693562616094051348940000476918169567736573762792*x ^12 + 111830217632072514908210550989211871176552309481599/475269449604180059 9528889100852519807882921672352*x^11 - 1471024591196603780353096370192893579 7358917135551/1474974153944007082612413858885264767963665346592*x^10 - 78428 948244601401396523150212212384571885038777261/356452087203135044964666682563 9389855912191254264*x^9 + 10939471959341527147172170510572393445222068105662 57/42774250464376205395760001907672678270946295051168*x^8 + 1196107874490196 95434901722719788534878705734430029/4277425046437620539576000190767267827094 6295051168*x^7 - 85459961331114624499693402127290245760415437599821/53467813 08047025674470000238459084783868286881396*x^6 + 1694407481139199129039479112 0329596090351233276463/891130218007837612411666706409847463978047813566*x^5 + 226932506488249147866358992212134279355199507497449/4277425046437620539576 0001907672678270946295051168*x^4 + 84260644432024255173228501431933921888577 448684655/21387125232188102697880000953836339135473147525584*x^3 + 260049245 774695484902410565325631597167723463363247/427742504643762053957600019076726 78270946295051168*x^2 - 165043255946056640400288944775348142222709154110443/ 21387125232188102697880000953836339135473147525584*x + 173844651349840294286 61539192228026476067275039793/3564520872031350449646666825639389855912191254 264], [x^6 - 128*x^5 + 5692*x^4 - 115568*x^3 + 1201904*x^2 - 6659968*x + 183 62368, 10977377138240491962525269171644277846711683/181154090831385442213907 176542899559101339531040*x^23 + 30389802666938135888599842289638890696282063 /60384696943795147404635725514299853033779843680*x^22 - 20321499860927178090 338758847250601516530803/11322130676961590138369198533931222443833720690*x^2 1 - 1692856094886090358692988590503313309011438707/9057704541569272110695358 8271449779550669765520*x^20 + 146290478798968128247582698562472768048091403/ 4528852270784636055347679413572488977533488276*x^19 + 5856146193472700543165 702003568135214964860663/20128232314598382468211908504766617677926614560*x^1 8 - 27129060630264870753132675422104089414367844657/603846969437951474046357 25514299853033779843680*x^17 - 377547666471355013205262359495866832790774367 189/181154090831385442213907176542899559101339531040*x^16 + 5012845164765129 943475067825204268184119510991/124078144405058522064319983933492848699547624 0*x^15 + 21464029225265033477063259623192271085420396829/3938132409377944395 954503837889120850029120240*x^14 - 66110715131219166560504239575476426535996 3222319/45288522707846360553476794135724889775334882760*x^13 - 1576467094845 86952011928320421438821016639345613/9057704541569272110695358827144977955066 9765520*x^12 + 4061550160739337620996102631219726749347532706413/18115409083 1385442213907176542899559101339531040*x^11 - 1126332939004088227857652608248 98315977612857287/6246692787289153179789902639410329624184121760*x^10 - 1521 8280324567988648111123170812861216900515754/56610653384807950691845992669656 11221916860345*x^9 + 2081840960113587441649887745098530287210809711431/90577 045415692721106953588271449779550669765520*x^8 - 428449047753103620447116130 2184875955387571541621/181154090831385442213907176542899559101339531040*x^7 + 469413210760649906034859986011059047980598506869/4528852270784636055347679 4135724889775334882760*x^6 + 55864720594330294619778660374760514737674836230 07/181154090831385442213907176542899559101339531040*x^5 - 297019991547106006 9699481257358315937125437709863/18115409083138544221390717654289955910133953 1040*x^4 + 842529722841499853191326096902857051186604210531/3019234847189757 3702317862757149926516889921840*x^3 + 25569321234426637982752574535714316934 74517360113/181154090831385442213907176542899559101339531040*x^2 - 209669369 920421622205353858461916799081258776973/201282323145983824682119085047666176 77926614560*x + 2456366117824133783672097608608233023116792401857/1811540908 31385442213907176542899559101339531040], [x^8 - 128*x^7 + 6372*x^6 - 149962* x^5 + 1601908*x^4 - 4447116*x^3 + 4733661*x^2 - 2052988*x + 471147, -4938012 67890851608442652181089455243582594539/6050876637033176880948824891675684806 826043255360*x^23 - 1298238726344360747051216746018180635108945183/201695887 9011058960316274963891894935608681085120*x^22 + 2579616545696938697613415271 48364603575472233/94544947453643388764825388932432575106656925865*x^21 + 492 30559645855923056526779514779792483270605159/2016958879011058960316274963891 894935608681085120*x^20 - 41406178774920134738833334058684869147462081381/75 6359579629147110118603111459460600853255406920*x^19 - 7724381279500877086330 35584053889389281598477369/2016958879011058960316274963891894935608681085120 *x^18 + 2358835879674900051908319304947407423987612057321/302543831851658844 0474412445837842403413021627680*x^17 + 1637069190446776120896121182768056394 247271995105/605087663703317688094882489167568480682604325536*x^16 - 5605399 8810774207794362193302686741493827943811/82888721055248998369161984817475134 34008278432*x^15 - 34462417002712261963651034841051949470083046471/548086651 9051790653033355880141018846762720340*x^14 + 3676725024907929399836864045889 0836235093772131181/1512719159258294220237206222918921201706510813840*x^13 - 629562075627110243900646403074672859663508507181/50423971975276474007906874 0972973733902170271280*x^12 - 2348082477043420454267263243751494053257037524 01263/6050876637033176880948824891675684806826043255360*x^11 + 2047679654093 121992125127730924628727508381812883/695503061727951365626301711686860322623 68313280*x^10 + 35807564174625103131109673128733316150782935929529/302543831 8516588440474412445837842403413021627680*x^9 - 20214740785304719650309013891 4713160359244487448853/6050876637033176880948824891675684806826043255360*x^8 + 152376990429523067481580072754410086697791175220813/605087663703317688094 8824891675684806826043255360*x^7 - 24673250685713016912556818665356369103433 845251369/3025438318516588440474412445837842403413021627680*x^6 - 5775343593 4377162586561553429153825824818245333063/15127191592582942202372062229189212 01706510813840*x^5 + 42754065234985779395416847570915717710996944251749/2016 958879011058960316274963891894935608681085120*x^4 - 260160730027295582317770 18867506925369338347342907/1512719159258294220237206222918921201706510813840 *x^3 + 24823784754233139999500092096084727381834317981813/605087663703317688 0948824891675684806826043255360*x^2 + 37424516202962553865962690734053704131 883836050337/1512719159258294220237206222918921201706510813840*x + 125434138 59531923934973881780920138972969617647929/5042397197527647400790687409729737 33902170271280], [x^8 - 128*x^7 + 6388*x^6 - 152670*x^5 + 1655686*x^4 - 5638 780*x^3 + 17111589*x^2 - 32653422*x + 22826961, -966605961188333904906317903 5652813746394173/101169715597773808686089847324978297200621695056*x^23 - 180 63686216291631172846228154619046616837551/2248215902172751304135329940555073 2711249265568*x^22 + 61693510809720597393420424738361583463991519/2248215902 1727513041353299405550732711249265568*x^21 + 1203367812960522378437532450096 5962065932978375/404678862391095234744359389299913188802486780224*x^20 - 967 6605749301200266256219940917283934262310269/20233943119554761737217969464995 6594401243390112*x^19 - 46888528112293669665288948620537693877008430863/1011 69715597773808686089847324978297200621695056*x^18 + 267312789841489274465803 784558886621328658163937/404678862391095234744359389299913188802486780224*x^ 17 + 1359564533340134004092064702898265422684733547817/404678862391095234744 359389299913188802486780224*x^16 - 83590022585006593865035333730192776993859 49617/1385886515037997379261504757876415030145502672*x^15 - 2750391611645660 9434643445256128704331160281439/29324555245731538749591260094196607884238172 48*x^14 + 375051952370671286475329668213446472221751560887/16861619266295634 781014974554163049533436949176*x^13 + 13195581129082420428768306559304700532 12733591521/202339431195547617372179694649956594401243390112*x^12 - 75022815 74945212347151304734565225931871054191163/2023394311955476173721796946499565 94401243390112*x^11 + 7746284714609786366972622305105065430551843127/3876234 31409095052437125851819840219159470096*x^10 + 175946480642415213047956695459 877666282099456441/11241079510863756520676649702775366355624632784*x^9 - 123 27342703958373998887525590912952250328347837347/4046788623910952347443593892 99913188802486780224*x^8 + 3821374820076942747478969609504803774352274090287 /202339431195547617372179694649956594401243390112*x^7 - 14878164241730448838 9478390912949887670722475325/33723238532591269562029949108326099066873898352 *x^6 - 6222375070248348975219220413600628712546578012523/1348929541303650782 48119796433304396267495593408*x^5 + 3873246544084234995269750537879131829331 507703/25292428899443452171522461831244574300155423764*x^4 - 693424534714447 53187442022222072168598183328869/2107702408286954347626871819270381191679618 647*x^3 - 4237862675350265727076348403540204959319197316185/2023394311955476 17372179694649956594401243390112*x^2 + 2586062114347979593199803148645105082 88250090483/134892954130365078248119796433304396267495593408*x + 21675465644 39918128228998511047191574468859719247/1348929541303650782481197964333043962 67495593408], [x^8 - 128*x^7 + 6252*x^6 - 141414*x^5 + 1382948*x^4 - 3759740 *x^3 + 3800153*x^2 - 7172584*x + 131759955, -1434844500108651823671046245869 357722482048984911441/152238369505892157326616869789621675142603345545300168 40*x^23 - 2360248553857644561153562817136791989825417906952161/3044767390117 843146532337395792433502852066910906003368*x^22 + 87173632580954524367306477 982456636146356714783720619/304476739011784314653233739579243350285206691090 60033680*x^21 + 352303062731989479239858978593368311587664597723593601/12179 069560471372586129349583169734011408267643624013472*x^20 - 40168626462020809 6739159797334958761758634303266933601/76119184752946078663308434894810837571 30167277265008420*x^19 - 275122015140672215400034184034233494706575007613886 2755/6089534780235686293064674791584867005704133821812006736*x^18 + 89774874 47810351332820197929340628153198362023725455255/1217906956047137258612934958 3169734011408267643624013472*x^17 + 6587693705310815697012843197649612107949 0307340464905151/20298449267452287643548915971949556685680446072706689120*x^ 16 - 456653571533095731745200375715087858605012033188666557/6951523721730235 4943660671136813550293426185180502360*x^15 - 1132692441628489144192494927147 2134397548325112949555901/13238119087468883245792771286054058708052464830026 10160*x^14 + 362432174014317480048478971081546342548806144095956168819/15223 836950589215732661686978962167514260334554530016840*x^13 + 12024185697750483 3960932827002163638604768758609545585477/30447673901178431465323373957924335 028520669109060033680*x^12 - 13030176649505436631272788181758072398359598383 1950270699/3383074877908714607258152661991592780946741012117781520*x^11 + 54 2807100222157433854855297232207847718098908270755205/23331550882129066256952 776979252364006529248359432976*x^10 + 10387878742116168717484553665985401170 8147962354618472239/7611918475294607866330843489481083757130167277265008420* x^9 - 1819856552502463405316947768101240474679904916809582226137/60895347802 356862930646747915848670057041338218120067360*x^8 + 810491866103236539189548 37706236850331188041083782957961/3805959237647303933165421744740541878565083 638632504210*x^7 - 32282509767607037064771269938993949421074543959221288349/ 3805959237647303933165421744740541878565083638632504210*x^6 - 25544033303698 20101316215131962008120825983490870537705723/6089534780235686293064674791584 8670057041338218120067360*x^5 + 22901642742154067726943738201768804798288313 4305484684749/30447673901178431465323373957924335028520669109060033680*x^4 - 179898736115995158794701606412394379275299516278483601917/60895347802356862 93064674791584867005704133821812006736*x^3 - 1051213427478377979478022079669 70243591354528534092045953/1522383695058921573266168697896216751426033455453 0016840*x^2 + 625869742638167665148168633053205193372974205328860697139/6089 5347802356862930646747915848670057041338218120067360*x + 1283657458421180203 581590597667101411582298024120277652453/608953478023568629306467479158486700 57041338218120067360], [x^8 - 128*x^7 + 5996*x^6 - 125058*x^5 + 1105242*x^4 - 2195548*x^3 - 4844447*x^2 + 18920794*x + 28602153, -1355993271508975902670 112217525308808448831/34816877659779740502243080421348085032189650880*x^23 - 238007005988586203227673394695931155753199/77370839243954978893873512047440 1889604214464*x^22 + 22666074111129984968367457453509266857588241/1740843882 9889870251121540210674042516094825440*x^21 + 4068898820114725409336462252389 7117519643353/3481687765977974050224308042134808503218965088*x^20 - 45490205 9145483766490823300364278918000444221/17408438829889870251121540210674042516 094825440*x^19 - 1280985844312606564102406755871045658987741551/696337553195 5948100448616084269617006437930176*x^18 + 2598361076913682739962749218813875 832561504377/6963375531955948100448616084269617006437930176*x^17 + 151902257 41390744173144088753581024754155545179/1160562588659324683408102680711602834 4063216960*x^16 - 18900912952568602594825077189605970512897976743/5802812943 296623417040513403558014172031608480*x^15 - 23585711861370635389761750146132 22534552292339/756888644777820445700936530898871413743253280*x^14 + 10366282 1112077760277790972916514232989363620101/87042194149449351255607701053370212 58047412720*x^13 - 8080295846375527232887657273986796427537554367/1740843882 9889870251121540210674042516094825440*x^12 - 6780516421331314972211686552096 96539275384915153/34816877659779740502243080421348085032189650880*x^11 + 349 1339271605870680074644026838395611311794381/24011639765365338277409020980240 0586428894144*x^10 + 114047357549613363278263916996653840364989677259/174084 38829889870251121540210674042516094825440*x^9 - 3014857976230057453614064597 49821573518824578199/17408438829889870251121540210674042516094825440*x^8 + 4 50539268925236609769367081964550664930155288379/3481687765977974050224308042 1348085032189650880*x^7 - 68332281719297567374473816383660612866633967263/17 408438829889870251121540210674042516094825440*x^6 - 675158388668363191013877 911825935432767942973847/34816877659779740502243080421348085032189650880*x^5 + 381362819390927554165294200203702917063933423627/348168776597797405022430 80421348085032189650880*x^4 - 1111569200596416923083307203056275347661212691 /145070323582415585426012835088950354300790212*x^3 + 31042672538291695701501 960271430850425771758889/11605625886593246834081026807116028344063216960*x^2 + 150661304165789605189254514770671138042455188637/116056258865932468340810 26807116028344063216960*x + 384635219444636964842750487491135732871308506247 /34816877659779740502243080421348085032189650880], [x^12 + 8*x^11 - 32*x^10 - 228*x^9 + 1024*x^8 + 3336*x^7 - 13530*x^6 - 16088*x^5 + 122256*x^4 - 10698 8*x^3 + 199232*x^2 - 69080*x + 78121, 65066666656093209286963509220431628228 125609846371/30447673901178431465323373957924335028520669109060033680*x^23 + 28777027886387296107612774093715751039967295566281/169153743895435730362907 6330995796390473370506058890760*x^22 - 2753699887715968424402732053871259784 36259728360997/3805959237647303933165421744740541878565083638632504210*x^21 - 80022006269961814753010340427347685423806044997340627/12179069560471372586 1293495831697340114082676436240134720*x^20 + 2273476822227624723439495830767 039255674203960133177/152238369505892157326616869789621675142603345545300168 4*x^19 + 13500641478661078022453215249761643930343870473494211/1268653079215 767977721807248246847292855027879544168070*x^18 - 91116180070534091147512832 1506610978694307473001131181/40596898534904575287097831943899113371360892145 413378240*x^17 - 9728433400735177582778402652117110626985769366869131837/121 790695604713725861293495831697340114082676436240134720*x^16 + 11124909834319 966382406610794456633338230128467448343/521364279129767662077455033526101627 20069638885376770*x^15 + 563364077300010961430863629176782915709833296596117 827/2647623817493776649158554257210811741610492966005220320*x^14 - 145633345 15922394909146331379895744140552053495796963891/1522383695058921573266168697 8962167514260334554530016840*x^13 + 8822016970556534270059884803005486339208 288670044090491/60895347802356862930646747915848670057041338218120067360*x^1 2 + 127206528408595099249429648017412581216779996600352749267/60895347802356 862930646747915848670057041338218120067360*x^11 - 40821026680563052231204166 76831874684914089777315963893/2099839579391615963125749928132712760587632352 348967840*x^10 - 101985428721339153294698554491524192926257856110159030157/6 0895347802356862930646747915848670057041338218120067360*x^9 + 42791766032533 0146232441040852756514798359805317404516211/12179069560471372586129349583169 7340114082676436240134720*x^8 - 21843954609832577130402129425960435382306446 172595380307/30447673901178431465323373957924335028520669109060033680*x^7 - 79670778033972604290997393827918115436558365746889551131/6089534780235686293 0646747915848670057041338218120067360*x^6 + 14201999281039237169430199865835 9369497010150308053107821/12179069560471372586129349583169734011408267643624 0134720*x^5 - 32880812508889018789944360729178675709347346407241109941/30447 673901178431465323373957924335028520669109060033680*x^4 + 116995332462780805 31093763988581003099401090648148804321/6766149755817429214516305323983185561 893482024235563040*x^3 + 163571436871579920806852364397323814127866296390460 27087/60895347802356862930646747915848670057041338218120067360*x^2 + 1251190 7933455800045847813518474740191270721168689800161/13532299511634858429032610 647966371123786964048471126080*x - 45416834122173675984634751540632770357151 083852279226589/121790695604713725861293495831697340114082676436240134720], [x^12 - 128*x^11 + 7072*x^10 - 222776*x^9 + 4451440*x^8 - 59277312*x^7 + 538 574272*x^6 - 3352440064*x^5 + 14157839104*x^4 - 39002448384*x^3 + 6493475532 8*x^2 - 60655540224*x + 67769520128, 424335399013795484329585864541253623465 77727596679/2537306158431535955443614496493694585710055759088336140*x^23 + 2 331149955329407472011088732357531429051310087608687/152238369505892157326616 86978962167514260334554530016840*x^22 - 117744683119365199164534463210453275 78601169057156303/30447673901178431465323373957924335028520669109060033680*x ^21 - 19203277897513304435875027071404693549163294955615771/3383074877908714 607258152661991592780946741012117781520*x^20 + 17776413035305843790166972269 14277892436745504290040/3805959237647303933165421744740541878565083638632504 21*x^19 + 2783688502078301876560706834153669130185103696349940957/3044767390 1178431465323373957924335028520669109060033680*x^18 - 9368835950076297763911 3187803799778204842493008934437/16915374389543573036290763309957963904733705 06058890760*x^17 - 22494833465693100038623435737441544529042861169363366239/ 30447673901178431465323373957924335028520669109060033680*x^16 + 126985191749 458775559712085056412947213693017549428081/208545711651907064830982013410440 650880278555541507080*x^15 + 19591133792006442315214801942678713499657467010 04151259/661905954373444162289638564302702935402623241501305080*x^14 - 41426 206800008018177054092468893471960443825648821883303/152238369505892157326616 86978962167514260334554530016840*x^13 - 269776341839468553115193902728158799 5060970730880391713/422884359738589325907269082748949097618342626514722690*x ^12 + 46732021768203656922658288059424441444564612668808031887/7611918475294 607866330843489481083757130167277265008420*x^11 + 41457121502089039190792804 3693337502039665952339040431/58328877205322665642381942448130910016323120898 582440*x^10 - 224031270077185123205112847922590353376838562318236338363/3044 7673901178431465323373957924335028520669109060033680*x^9 - 36706572813832147 301604562077501280352523525747845964451/101492246337261438217744579859747783 42840223036353344560*x^8 + 6348692994518079825970323151915463372525713814650 9584497/15223836950589215732661686978962167514260334554530016840*x^7 + 18749 04595986563688607035761097189266972839481139388301/3044767390117843146532337 3957924335028520669109060033680*x^6 + 24322607008365923955576621650706418947 7224297241159265407/30447673901178431465323373957924335028520669109060033680 *x^5 + 2018932968640554810896242722069864549217866087131569398/2114421798692 94662953634541374474548809171313257361345*x^4 - 3229658818789990933359262960 7895158083800617281062974671/76119184752946078663308434894810837571301672772 65008420*x^3 + 44189240178661966971221203380498006729702098568972563783/3044 7673901178431465323373957924335028520669109060033680*x^2 - 32774215919947604 742286419081703350830159707258712991371/152238369505892157326616869789621675 14260334554530016840*x + 918914399905141421157902593003827981001865103376222 20197/30447673901178431465323373957924335028520669109060033680], [x^12 - 128 *x^11 + 7000*x^10 - 215116*x^9 + 4123778*x^8 - 51886068*x^7 + 441305792*x^6 - 2587581388*x^5 + 10632143781*x^4 - 30176341404*x^3 + 57593424368*x^2 - 661 54473176*x + 40390771664, 18463333363928720155975373691072684438923522507053 7/5295247634987553298317108514421623483220985932010440640*x^23 + 14764526048 80626530553846524977325866833188168836537/5295247634987553298317108514421623 483220985932010440640*x^22 - 74563168555786751271456226849761196022885418315 9599/661905954373444162289638564302702935402623241501305080*x^21 - 277034534 2288087595503347842807168999915911160687795/26476238174937766491585542572108 1174161049296600522032*x^20 + 1952462511265135777118054851030325738619954157 2761357/882541272497925549719518085736937247203497655335073440*x^19 + 862775 355008463613598861314059265231988773175429977471/529524763498755329831710851 4421623483220985932010440640*x^18 - 1671698503824514168765610134764272312875 344639274132939/5295247634987553298317108514421623483220985932010440640*x^17 - 6046753989964051670150427547837550905068469974439337417/52952476349875532 98317108514421623483220985932010440640*x^16 + 100801483178391565008385581717 147016529133985704616193/362688194177229677966925240713809827617875748767838 40*x^15 + 459042749345955009876011084734556610501145869459401983/17650825449 9585109943903617147387449440699531067014688*x^14 - 6696071714046912378411037 767491697499530865033768128673/661905954373444162289638564302702935402623241 501305080*x^13 + 2843887739020458188940081476050531170015006076104519289/264 7623817493776649158554257210811741610492966005220320*x^12 + 1749773848262678 2066355810225587881685578115610236771051/10590495269975106596634217028843246 96644197186402088128*x^11 - 262831859305312267071570609341247658975337459598 1226203/182594746034053562010934776359366327007620204552084160*x^10 - 157937 3035852710694285764315809691750557713541998251247/26476238174937766491585542 5721081174161049296600522032*x^9 + 56771438349914697469159750141686154803567 58682133096713/330952977186722081144819282151351467701311620750652540*x^8 - 15119194179787853101127959095680921091042759833521116131/1765082544995851099 439036171473874494406995310670146880*x^7 + 102810823183983243963428197906125 932479203158517964291/441270636248962774859759042868468623601748827667536720 *x^6 + 13125284180768256728812564593605976684173487579326904331/105904952699 7510659663421702884324696644197186402088128*x^5 - 53893267212112384604258881 33373553192823646013149797697/5295247634987553298317108514421623483220985932 010440640*x^4 + 2042730533678441931444059941826970835004691000616458689/1323 81190874688832457927712860540587080524648300261016*x^3 - 1372649475078011559 9211968200080332353637900234726227791/52952476349875532983171085144216234832 20985932010440640*x^2 - 5955933052912600565408319112157485403575846366641862 129/5295247634987553298317108514421623483220985932010440640*x + 276576666305 09651485384460280486609412867864388770353397/5295247634987553298317108514421 623483220985932010440640], [x^12 + 8*x^11 - 48*x^10 - 324*x^9 + 1600*x^8 + 5 656*x^7 - 25178*x^6 - 24856*x^5 + 264128*x^4 - 276364*x^3 + 14400*x^2 - 1096 08*x + 560233, 22862683949356898693145720439385966734937527286017/3044767390 117843146532337395792433502852066910906003368*x^23 + 30556774423730200703910 0439676636870860564868697503/50746123168630719108872289929873891714201115181 76672280*x^22 - 364791094039097263336592619234953294707856932092757/15223836 95058921573266168697896216751426033455453001684*x^21 - 273742642624935610504 146130767021453802539972115720943/121790695604713725861293495831697340114082 676436240134720*x^20 + 14134085765647291289865842805006724827498636217759473 1/30447673901178431465323373957924335028520669109060033680*x^19 + 1762486125 10521942483402656912564193084191824833668099/5074612316863071910887228992987 389171420111518176672280*x^18 - 53155113329191278415304907106997345808113240 9688264449/8119379706980915057419566388779822674272178429082675648*x^17 - 29 186583579369888686985010537793345832291701792552327297/121790695604713725861 293495831697340114082676436240134720*x^16 + 11817062190700924586592156144389 5390547606705964931577/20854571165190706483098201341044065088027855554150708 0*x^15 + 1363966020060875846841749525186906348568750503317401503/26476238174 93776649158554257210811741610492966005220320*x^14 - 294104004144804546814634 2871333931639873341678117947157/15223836950589215732661686978962167514260334 55453001684*x^13 + 19112993959296991832395430252531127320925998625478787687/ 60895347802356862930646747915848670057041338218120067360*x^12 + 156333529316 220483031618920533800052228339474556808477213/608953478023568629306467479158 48670057041338218120067360*x^11 - 119109811646202738658274183044654802333199 7885655797093/419967915878323192625149985626542552117526470469793568*x^10 + 47920057190141968221470677444242599015309498856573549967/6089534780235686293 0646747915848670057041338218120067360*x^9 + 57923265720776925815812973461067 014182029316155657865059/243581391209427451722586991663394680228165352872480 26944*x^8 - 129103734947918182696414547934825944381114830346566447877/304476 73901178431465323373957924335028520669109060033680*x^7 + 1585073692884849190 30160135488531036952019108757315221173/6089534780235686293064674791584867005 7041338218120067360*x^6 + 52457631936009898928081743383414740674142398819731 6146629/121790695604713725861293495831697340114082676436240134720*x^5 - 2027 1881673669276000010912604356149766757839753125231593/60895347802356862930646 74791584867005704133821812006736*x^4 + 5998134809924570435371766096065767126 4785160000836785237/20298449267452287643548915971949556685680446072706689120 *x^3 + 82125560315233201823890923941614440369511665073048407767/608953478023 56862930646747915848670057041338218120067360*x^2 + 4468048988614755837724669 20404288528897644279371535857/1353229951163485842903261064796637112378696404 8471126080*x - 36853554286489699504420429525610772575693627713065347137/1217 90695604713725861293495831697340114082676436240134720], [x^12 - 128*x^11 + 7 028*x^10 - 217804*x^9 + 4201632*x^8 - 52044492*x^7 + 410394530*x^6 - 1951174 544*x^5 + 4906888668*x^4 - 3571058548*x^3 - 7310592704*x^2 + 8305027036*x + 8727249437, 354204903997215358797307281171178249849973081621/639220572113125 1029302130679247223015487465303954240*x^23 + 2487869341017886594476380601135 8224944545334971617/57529851490181259263719176113225007139387187735588160*x^ 22 - 1495198202130256279220517957152874314680896954621/799025715141406378662 766334905902876935933162994280*x^21 - 25966415989986949963577511108089769993 615534412979/1598051430282812757325532669811805753871866325988560*x^20 + 109 9116491805220663815752150310053611201337564429957/28764925745090629631859588 056612503569693593867794080*x^19 + 14420763777731206410046878257265435461644 627644870991/57529851490181259263719176113225007139387187735588160*x^18 - 31 553116547541365721111777958296319698059776971879007/575298514901812592637191 76113225007139387187735588160*x^17 - 972498436345994409047717032282946890576 96145029094833/57529851490181259263719176113225007139387187735588160*x^16 + 135677260380623987418934151831085143839101525665107381/287649257450906296318 59588056612503569693593867794080*x^15 + 377894481706623930704387691847302005 0700623474542391/1250648945438723027472156002461413198682330168164960*x^14 - 19562719073527465023636694631182686094154715049100273/119853857271210956799 4149502358854315403899744491420*x^13 + 1908591369254382006959493273752222755 4397778508717641/3196102860565625514651065339623611507743732651977120*x^12 + 1300107356368521428018560813290773003351388611398957147/5752985149018125926 3719176113225007139387187735588160*x^11 - 1699951639250159298693534919196173 587070390344681333031/57529851490181259263719176113225007139387187735588160* x^10 + 21885214988151134785275765148847535005644172169314179/479415429084843 8271976598009435417261615598977965680*x^9 + 31665344378449207077751274203403 356981738049781701411/1198538572712109567994149502358854315403899744491420*x ^8 - 384048224170228136943335430902244076368661075238273365/1150597029803625 1852743835222645001427877437547117632*x^7 + 24537667159561162056113877288532 3269695201997090034903/14382462872545314815929794028306251784846796933897040 *x^6 + 518211448087437512082635179578312011744395434386465281/19176617163393 753087906392037741669046462395911862720*x^5 - 495935376162218891763871987374 901719755454688995137219/191766171633937530879063920377416690464623959118627 20*x^4 + 430442457721369897191159498019894905104349245911845359/143824628725 45314815929794028306251784846796933897040*x^3 + 3877973790598824428826471770 8230091254542725845133977/63922057211312510293021306792472230154874653039542 40*x^2 - 866270056674413518007230896808600800427673779982469421/575298514901 81259263719176113225007139387187735588160*x + 184897148273759181037362315660 360107875627946870841823/191766171633937530879063920377416690464623959118627 20], [x^12 + 8*x^11 - 20*x^10 - 192*x^9 + 502*x^8 + 2856*x^7 - 3060*x^6 - 13 352*x^5 + 52353*x^4 + 42544*x^3 - 8992*x^2 - 25208*x + 136624, 9948798988126 75791402622578945789183307264767199/8457687194771786518145381654978981952366 85253029445380*x^23 + 59789121796993226628948017663501487213874578749141/507 4612316863071910887228992987389171420111518176672280*x^22 - 3587372968213104 38734338853899660739396012657034911/2029844926745228764354891597194955668568 0446072706689120*x^21 - 2873644538544616442300064820458652204594434885416599 /6766149755817429214516305323983185561893482024235563040*x^20 - 225589532411 7630810209853167935028674275921290261/44319758225878357300325144043557984029 869969591062640*x^19 + 13835692239945575042839142170853097859813764868679991 7/20298449267452287643548915971949556685680446072706689120*x^18 + 1457156005 6883905575916866446065437075872717486135657/50746123168630719108872289929873 89171420111518176672280*x^17 - 395760275355413610621807116292185233854861851 002844533/6766149755817429214516305323983185561893482024235563040*x^16 - 939 112140068214318715010369110990436866535698835453/463434914782015699624404474 24542366862284123453668240*x^15 + 132950761649943569069311808062897979602968 310160498177/441270636248962774859759042868468623601748827667536720*x^14 + 9 78046276355281793667534074922071332286493561828989489/1014922463372614382177 4457985974778342840223036353344560*x^13 - 1129747394988597964467917318244127 095892064667203424565/101492246337261438217744579859747783428402230363533445 6*x^12 + 421426032051438936722778095963751075383403070519243271/507461231686 3071910887228992987389171420111518176672280*x^11 + 4362458932800119355826262 59743091386419019331873167499/1749866316159679969271458273443927300489693626 95747320*x^10 - 10313894948045606599628050224105385214968336425524192873/676 6149755817429214516305323983185561893482024235563040*x^9 - 51545870853179449 095853282767237096546480108369838175731/202984492674522876435489159719495566 85680446072706689120*x^8 + 9117132738149561693605469592970411714722159288430 688623/2537306158431535955443614496493694585710055759088336140*x^7 - 4829913 928007192670126765410781714580554864652496841001/405968985349045752870978319 4389911337136089214541337824*x^6 - 60887880298505501517060765765033323911833 35610880266333/6766149755817429214516305323983185561893482024235563040*x^5 + 46084005155239229035442834618698271542646311695210480277/101492246337261438 21774457985974778342840223036353344560*x^4 - 8153259732874800058123066239009 394363808083426262437247/338307487790871460725815266199159278094674101211778 1520*x^3 - 24080782821134485584190150996460355347673534634324443257/20298449 267452287643548915971949556685680446072706689120*x^2 + 397620832390668218552 0923103263375479437623604945781277/10149224633726143821774457985974778342840 22303635334456*x - 52744010985633614911677082098196802012646172402331852887/ 20298449267452287643548915971949556685680446072706689120], [x^12 + 8*x^11 - 96*x^10 - 500*x^9 + 3496*x^8 + 1896*x^7 - 23646*x^6 + 10088*x^5 - 7632*x^4 + 108804*x^3 - 72120*x^2 + 29080*x + 8669, -160076268942759843491807179189838 226976188513273211/20298449267452287643548915971949556685680446072706689120* x^23 - 996499635730976890503667465144832055871723653093551/15223836950589215 732661686978962167514260334554530016840*x^22 + 17733655257084927901033078811 53296896121059813393801/7611918475294607866330843489481083757130167277265008 420*x^21 + 98424969300447112803010536981003748205958953274541561/40596898534 904575287097831943899113371360892145413378240*x^20 - 50932526295732471756349 575482932816704526233461136379/121790695604713725861293495831697340114082676 43624013472*x^19 - 1145230923459929339628594743781409599519998376321752411/3 0447673901178431465323373957924335028520669109060033680*x^18 + 2350200912696 730758224519321784847776410893983727229239/405968985349045752870978319438991 13371360892145413378240*x^17 + 326416164085346765403320903745258911722545507 96691214423/121790695604713725861293495831697340114082676436240134720*x^16 - 215203527208982101554131954505106199673836033352432421/41709142330381412966 1964026820881301760557111083014160*x^15 - 1848131016790642703978207397953274 286212446217631879483/264762381749377664915855425721081174161049296600522032 0*x^14 + 55328977529123941436545890133199926186670098756144408033/3044767390 1178431465323373957924335028520669109060033680*x^13 + 6512714067097255297913 449617341311661885063658367692287/202984492674522876435489159719495566856804 46072706689120*x^12 - 832741003561894524701602644325502684017255494394387966 69/30447673901178431465323373957924335028520669109060033680*x^11 + 410881995 192243441699889583733158322072766997991674623/233315508821290662569527769792 523640065292483594329760*x^10 + 29379558359240744593646038441273899479199882 829159795253/60895347802356862930646747915848670057041338218120067360*x^9 - 25565663436635476659601393395810012994911625365562733711/1353229951163485842 9032610647966371123786964048471126080*x^8 + 29255048017247281406169956044711 995016584629206346895769/152238369505892157326616869789621675142603345545300 16840*x^7 - 68664980484187976386528046668326132069656697441891027871/6089534 7802356862930646747915848670057041338218120067360*x^6 - 38113723010604051750 8636133797935097577710954942079446719/12179069560471372586129349583169734011 4082676436240134720*x^5 - 20426554047909827220845525005027316136195713469917 30893/6766149755817429214516305323983185561893482024235563040*x^4 - 84134077 486443969853039440381806581478078071947496932503/304476739011784314653233739 57924335028520669109060033680*x^3 - 2960783154005029317239038437213566955696 2249202521416123/60895347802356862930646747915848670057041338218120067360*x^ 2 + 49723190123383675496609082996917957082213122058381448129/121790695604713 725861293495831697340114082676436240134720*x + 17299898357937903217009106857 9518664529518677926525605711/12179069560471372586129349583169734011408267643 6240134720], [x^12 + 8*x^11 - 96*x^10 - 440*x^9 + 3820*x^8 + 2476*x^7 - 2886 6*x^6 - 7944*x^5 + 28592*x^4 - 78536*x^3 + 10884*x^2 + 159444*x - 91071, -28 43543750743793449163008440663651841434705457245/2706459902326971685806522129 593274224757392809694225216*x^23 - 12602975509304114055800420933216793110727 93599978009/121790695604713725861293495831697340114082676436240134720*x^22 + 570731733731003725351372109440675289941476598770863/30447673901178431465323 373957924335028520669109060033680*x^21 + 51592625775826643511866946240589855 77759549230333661/13532299511634858429032610647966371123786964048471126080*x ^20 - 5774381398913496913794879696624862509179034351243487/60895347802356862 930646747915848670057041338218120067360*x^19 - 25468830711446803184345827193 2277843024215812872643049/40596898534904575287097831943899113371360892145413 378240*x^18 + 20033262878589630479972285983900066074399699473462869/30447673 901178431465323373957924335028520669109060033680*x^17 + 55176945627841311088 2177179020595815257295888900607149/10149224633726143821774457985974778342840 223036353344560*x^16 - 2196210823307814646404558793935983828145341622776393/ 92686982956403139924880894849084733724568246907336480*x^15 - 281198062671316 44596199544287679231995494222195918933/1103176590622406937149397607171171559 00437206916884180*x^14 + 304514561389622743033625986558859551531129703238802 3343/15223836950589215732661686978962167514260334554530016840*x^13 + 6341682 965913223773626928153451927146827201459143872529/101492246337261438217744579 85974778342840223036353344560*x^12 - 971232245781567976274478605121606023057 45728225275341069/121790695604713725861293495831697340114082676436240134720* x^11 - 2551276395028313523351048147505389667653665761782939583/4199679158783 231926251499856265425521175264704697935680*x^10 + 10180519150826648417575790 6926793237808116128714341253427/60895347802356862930646747915848670057041338 218120067360*x^9 - 20272760961834455884178435606038856153257919669244492931/ 40596898534904575287097831943899113371360892145413378240*x^8 - 1865773872120 99192426030273535446653260095296117785642631/1217906956047137258612934958316 97340114082676436240134720*x^7 + 3300537798438143487111980175860071706890748 8889952173347/20298449267452287643548915971949556685680446072706689120*x^6 - 39115208858757321709938597019725056041630348474811196863/608953478023568629 30646747915848670057041338218120067360*x^5 - 5539361638969286663932918946276 6239897550377218752807981/40596898534904575287097831943899113371360892145413 378240*x^4 + 64402986133347052436258518319496764711767679294921068777/608953 47802356862930646747915848670057041338218120067360*x^3 - 1297933348655958087 58307214004222253253020247405099177719/1217906956047137258612934958316973401 14082676436240134720*x^2 + 3900779029174220341536242528866339356307493590998 2781157/60895347802356862930646747915848670057041338218120067360*x + 3917569 0216233454071931113702470696322351493063061964491/60895347802356862930646747 915848670057041338218120067360], [x^12 + 8*x^11 - 96*x^10 - 404*x^9 + 3412*x ^8 + 1260*x^7 - 21558*x^6 - 22600*x^5 + 115056*x^4 + 129348*x^3 - 158196*x^2 - 308636*x - 142411, -668965224263535698951035552798251404886640051188469/1 21790695604713725861293495831697340114082676436240134720*x^23 - 522171975341 2401374098995133400803800172339867929167/12179069560471372586129349583169734 0114082676436240134720*x^22 + 5718323145017272666709458110806890233229264753 381243/30447673901178431465323373957924335028520669109060033680*x^21 + 12434 087272000961086772811753580691066313436906507469/761191847529460786633084348 9481083757130167277265008420*x^20 - 3893187297078473294000250738769036174547 2914592223087/10149224633726143821774457985974778342840223036353344560*x^19 - 1043301491205948231908424718639106834470204686958032907/405968985349045752 87097831943899113371360892145413378240*x^18 + 667864415723478355393870787186 1675496441670377137933487/12179069560471372586129349583169734011408267643624 0134720*x^17 + 22122086031461047810356371854786679936211211173131714093/1217 90695604713725861293495831697340114082676436240134720*x^16 - 394863083446836 915534524170968216903183701507703296477/834182846607628259323928053641762603 521114222166028320*x^15 - 11103731891455954559643155427971936684242173308347 43981/2647623817493776649158554257210811741610492966005220320*x^14 + 5193183 9285403408769737480751228092224989253670367415221/30447673901178431465323373 957924335028520669109060033680*x^13 - 44551296374879728480089523872541484087 65609414389517739/60895347802356862930646747915848670057041338218120067360*x ^12 - 339372827622239657883169496965045381019939562026015194207/121790695604 713725861293495831697340114082676436240134720*x^11 + 26541490769726873500666 65846456196103044261908748211563/1399893052927743975417166618755141840391754 901565978560*x^10 + 16167287887659074297609123346059902626725458808559143179 /15223836950589215732661686978962167514260334554530016840*x^9 - 158397352873 93423962056277168280332697428495450276352123/7611918475294607866330843489481 083757130167277265008420*x^8 + 116063234760368696797073011434558912526742361 85087299217/8119379706980915057419566388779822674272178429082675648*x^7 - 19 434164957414447238256519636329478106624733429298116103/304476739011784314653 23373957924335028520669109060033680*x^6 - 2832965223540201167307000776498771 81268540478120997440163/1217906956047137258612934958316973401140826764362401 34720*x^5 + 181552408650077417895085086169959141618857336367367324417/121790 695604713725861293495831697340114082676436240134720*x^4 - 807763889237836951 23221859525260859276171260950761502643/6089534780235686293064674791584867005 7041338218120067360*x^3 + 39678238836131920899246476567750525687401412328606 354359/40596898534904575287097831943899113371360892145413378240*x^2 + 298470 299527392719046809962954040235580423608315993300221/121790695604713725861293 495831697340114082676436240134720*x + 11790798094515584514981227444717596268 5297095338144540411/12179069560471372586129349583169734011408267643624013472 0], [x^24 + 8*x^23 - 32*x^22 - 298*x^21 + 624*x^20 + 4592*x^19 - 8845*x^18 - 31488*x^17 + 76813*x^16 + 65924*x^15 - 265616*x^14 + 48348*x^13 + 385639*x^ 12 - 394984*x^11 - 20946*x^10 + 369102*x^9 - 362877*x^8 + 183396*x^7 + 43450 1*x^6 - 194418*x^5 + 450637*x^4 + 125800*x^3 - 16401*x^2 - 45880*x + 115151, x]] [[x, 0], [x^2 - 976*x + 97344, -222910045/36233685138*x^11 + 300079190/18116 842569*x^10 + 715283545/6038947523*x^9 - 2927995150/18116842569*x^8 - 302927 33825/18116842569*x^7 - 26191831810/6038947523*x^6 - 1653293375/2588120367*x ^5 + 392517147590/18116842569*x^4 + 44195250305/12077895046*x^3 + 5530280884 0/862706789*x^2 + 415469340/147291403*x + 3752257918344/6038947523], [x^2 - 816*x + 190224, -11621/3192644*x^11 + 13011/1596322*x^10 + 93385/1596322*x^9 - 24442/798161*x^8 - 1208211/1596322*x^7 - 2483984/798161*x^6 - 166171/3257 8*x^5 - 1881456/798161*x^4 - 31329625/3192644*x^3 + 8077959/228046*x^2 - 299 67534/798161*x + 36823272/61397], [x^2 - 696*x + 190224, 7265387/877165562*x ^11 - 7779276/438582781*x^10 - 70950769/438582781*x^9 + 52367618/438582781*x ^8 + 991023843/438582781*x^7 + 2976293650/438582781*x^6 + 304715797/62654683 *x^5 - 7333904490/438582781*x^4 + 14554825027/877165562*x^3 + 284983362/8950 669*x^2 + 590708988/10697141*x - 2566049700/33737137], [x^4 + 96*x^3 + 3120* x^2 + 39168*x + 190224, 31299577/538329036336*x^11 - 22574459/89721506056*x^ 10 - 288389093/269164518168*x^9 + 480877091/134582259084*x^8 + 1402144189/89 721506056*x^7 + 2861867893/134582259084*x^6 - 20824219669/269164518168*x^5 - 20819819613/44860753028*x^4 - 259963038355/538329036336*x^3 - 275194979907/ 89721506056*x^2 - 343627653/273541177*x - 2485307679/123243827], [x^6 - 24*x ^5 + 156*x^4 + 464*x^3 - 7623*x^2 + 3120*x + 97344, -37833763/628050542392*x ^11 + 964935605/1884151627176*x^10 + 702697657/1884151627176*x^9 - 184577050 85/1884151627176*x^8 - 3878927261/1884151627176*x^7 + 124228524689/188415162 7176*x^6 + 33661857251/269164518168*x^5 + 501706392647/1884151627176*x^4 - 2 8113142906/235518953397*x^3 + 68497211168/33645564771*x^2 + 52679128/1472914 03*x - 113366240/33737137], [x^6 + 26*x^5 + 249*x^4 - 904*x^3 - 11264*x^2 + 2496*x + 97344, 39092497/628050542392*x^11 - 150408273/314025271196*x^10 - 1 02037993/314025271196*x^9 + 725270613/78506317799*x^8 + 165014715/3140252711 96*x^7 - 10487527333/157012635598*x^6 - 2801595011/44860753028*x^5 + 2560058 803/78506317799*x^4 + 636975566557/628050542392*x^3 - 47019481331/4486075302 8*x^2 + 9584655/147291403*x + 15835357278/6038947523], [x^6 - 30*x^5 + 33*x^ 4 + 1904*x^3 - 4656*x^2 - 33024*x + 97344, 407243497/3768303254352*x^11 - 29 0544097/942075813588*x^10 - 3615375499/1884151627176*x^9 + 890457909/3140252 71196*x^8 + 50759345369/1884151627176*x^7 + 69197550965/942075813588*x^6 + 2 146912181/89721506056*x^5 - 288650751499/942075813588*x^4 + 525158512705/376 8303254352*x^3 - 34296010547/33645564771*x^2 + 63828605/294582806*x - 236593 88402/6038947523], [x^12 - 4*x^11 - 14*x^10 + 44*x^9 + 226*x^8 + 380*x^7 - 5 42*x^6 - 2620*x^5 + 4249*x^4 - 6312*x^3 + 13056*x^2 - 67392*x + 97344, x]] Total time spent: 5336 pari-2.7.5/src/test/32/compat0000644000175000017500000025571012405547147014331 0ustar billbill 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] [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.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] [-38808.00000004559575 1596672.000001717726 -15717240.00001591859 62092800.0 0006016001 -115259760.0001079261 100590336.0000916694 -33297264.00002968058] [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)) [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)) [[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< charpoly(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 ma y 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, whe re n is the dimension of the matrix. This function did not change As far as I can recall, this function never existed New syntax: compimag(x,y) ===> x*y Total time spent: 0 pari-2.7.5/src/test/32/equal0000644000175000017500000000070012573104164014132 0ustar billbill[1, 0, 1, 0] [0, 0] [1, 0] [1, 0] [0, 1] [0, 0, 1] [0, 0, 1] [0, 0, 1] [0, 0, 0, 0, 1] 1 0 [0, 0, 0, 1] 0 [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] [0, 0] [1, 0] [0, 0] [0, 0] [1, 0] [0, 1] [1, 1] [1, 0] [0, 0] [1, 0] [0, 0] [0, 0] [0, 1] 1 Total time spent: 4 pari-2.7.5/src/test/32/orthopol0000644000175000017500000000006612366172547014710 0ustar billbillU T L H 1 1 1 1 0 -1 209 1 1 1 1 Total time spent: 16 pari-2.7.5/src/test/32/polred0000644000175000017500000000656212366172547014336 0ustar billbillx^7 + Mod(7*y, y^2 - y - 1)*x^6 + Mod(21*y + 7, y^2 - y - 1)*x^5 + 35*x^4 + Mod(-35*y - 14, y^2 - y - 1)*x^3 + Mod(-7*y - 77, y^2 - y - 1)*x^2 + Mod(14* y + 7, y^2 - y - 1)*x + Mod(-y + 44, y^2 - y - 1) x^8 + Mod(-5265231366756*y - 11544453645457, y^2 - y - 7)*x^7 + Mod(28411458 5416607426786*y + 622944640581258439174, y^2 - y - 7)*x^6 + Mod(-88698486784 831757442657946*y - 194478741347464554095950854, y^2 - y - 7)*x^5 + Mod(1457 861838374320941446687517087*y + 3196482213651741289611519839129, y^2 - y - 7 )*x^4 + Mod(-3466536016262523445329224834043387*y - 760066587058933027706659 6588522840, y^2 - y - 7)*x^3 + Mod(500059251848756466420835983321373618*y + 1096421116344588264250099626740668170, y^2 - y - 7)*x^2 + Mod(-1916208944621 5341153510282273347908836*y - 42014460135353505823787366140454468112, y^2 - y - 7)*x + Mod(100691810991091652032034511974871062155*y + 22077509296238717 8747302102119022589688, y^2 - y - 7) x^8 + Mod(-8*y + 1, y^2 - y - 7)*x^7 + Mod(21*y + 189, y^2 - y - 7)*x^6 + Mo d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod( -2451*y - 3350, y^2 - y - 7)*x^3 + Mod(2402*y + 6871, y^2 - y - 7)*x^2 + Mod (-2050*y - 3861, y^2 - y - 7)*x + Mod(565*y + 1331, y^2 - y - 7) x^8 + Mod(-8*y + 1, y^2 - y - 7)*x^7 + Mod(21*y + 189, y^2 - y - 7)*x^6 + Mo d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod( -2451*y - 3350, y^2 - y - 7)*x^3 + Mod(2402*y + 6871, y^2 - y - 7)*x^2 + Mod (-2050*y - 3861, y^2 - y - 7)*x + Mod(565*y + 1331, y^2 - y - 7) x^8 + Mod(-8*y + 1, y^2 - y - 7)*x^7 + Mod(21*y + 189, y^2 - y - 7)*x^6 + Mo d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod( -2451*y - 3350, y^2 - y - 7)*x^3 + Mod(2402*y + 6871, y^2 - y - 7)*x^2 + Mod (-2050*y - 3861, y^2 - y - 7)*x + Mod(565*y + 1331, y^2 - y - 7) x^8 + Mod(-8*y + 1, y^2 - y - 7)*x^7 + Mod(21*y + 189, y^2 - y - 7)*x^6 + Mo d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod( -2451*y - 3350, y^2 - y - 7)*x^3 + Mod(2402*y + 6871, y^2 - y - 7)*x^2 + Mod (-2050*y - 3861, y^2 - y - 7)*x + Mod(565*y + 1331, y^2 - y - 7) 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 *** nfinit: Warning: non-monic polynomial. Result of the form [nf,c]. x^2 - 3646554366 304 x^4 + 1000000000000000000000*x^2 + 1 x^4 + 146077*x^2 + 2629386 x^9 - 4*x^7 - 3*x^6 + 9*x^5 + 8*x^4 - 6*x^3 - 9*x^2 - 4*x - 1 x^5 - 13*x^3 - 3*x^2 + 5*x + 1 x^6 + 21471450*x^2 + 71643071500 x^6 - 12*x^4 - 24*x^3 + 21651666*x^2 - 257657256*x + 71814482884 x^4 + 146077*x^2 + 10517544 x [x, Mod(-1/2, x)] *** at top-level: polred([x,[1]]) *** ^--------------- *** polred: domain error in gvaluation: p = 1 [x - 1] [x - 1] [ 1 x - 1] [2*x x^2 + 1] x + 1 [x + 1, Mod(-1/2, x + 1)] [x^2 + 1, Mod(1/2*x, x^2 + 1)] [2*x + 1] [x - 1, x^2 + 1] [x^8 - 4*x^7 + 24*x^6 - 58*x^5 + 126*x^4 - 160*x^3 + 160*x^2 - 89*x + 26, Mo d(-68/135*x^7 + 208/135*x^6 - 1378/135*x^5 + 56/3*x^4 - 194/5*x^3 + 4976/135 *x^2 - 4492/135*x + 1856/135, x^8 - 4*x^7 + 24*x^6 - 58*x^5 + 126*x^4 - 160* 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 pari-2.7.5/src/test/32/ellglobalred0000644000175000017500000000163012366172547015470 0ustar billbill[["496a1", [0, 0, 0, 1, 1], [[0, 1]]], [1, 0, 0, 0]] ["11a1", [0, -1, 1, -10, -20], []] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] ["11a1", [0, -1, 1, -10, -20], []] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] -122023936/161051 error("incorrect type in ellsearch (t_VEC).") error("domain error in ellsearch: conductor <= 0") error("incorrect type in ellsearch (t_STR).") error("incorrect type in ellsearch (t_COMPLEX).") Total time spent: 1240 pari-2.7.5/src/test/32/bessel0000644000175000017500000004016412366172547014322 0ustar billbill1.8572024140248075150290504794684852507 E-10 1 - 1/46*x^2 + 1/4600*x^4 - 1/745200*x^6 + O(x^7) besselh1 [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + (-1/4 - 1/2*I)*x^2 + (1/64 + 3/64*I)*x^4 + (-1/2304 - 11/6912*I) *x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 + 0.08825696421567695798292 6766023515162828*I [2, 3]: 0.93846980724081290422840467359971262557 - 0.44451873350670655714839 847506833191038*I [2, 4]: 0.22744989480229475542017649479538153049 - 0.05105545867308961813450 6215898455430057*I [3, 1]: 4*I*x^-2 + (1 + I) + (-1/8 - 5/16*I)*x^2 + O(x^3) [3, 2]: 0.44005058574493351595968220371891491313 - 0.78121282130028871654715 000004796482055*I [3, 3]: 0.24226845767487388638395457614153164080 - 1.47147239267024306918858 46353232974532*I [3, 4]: -0.015640669069980772062382408481746291203 - 0.292666506764257448350 36876789097604882*I [4, 1]: (1 - I) + (-1/6 + 1/2*I)*x^2 + (1/120 - 1/24*I)*x^4 + (-1/5040 + 1/7 20*I)*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708055 - 0.43109886801837607952052 096729853340009*I [4, 3]: 0.54097378993452809133091313466411641349 - 0.99024588024340488002335 195542348755756*I [4, 4]: 0.14085110084956896263172093887132583804 - 0.20269003235062497321863 218183621826188*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: 0.26938214945091836540555327716757818205 - 1.03976259800634355895849 86807324939546*I [5, 3]: 0.10940542017270712675781308031594165118 - 2.26083223277617932197371 42212172870084*I [5, 4]: -0.19118520534054547001908105095911444129 - 0.3150944893490879685794 3764282485894340*I [6, 1]: 380507258880*I*x^-20 + 10569646080*I*x^-18 + 165150720*I*x^-16 + O(x ^-15) [6, 2]: 2.6306151236874532069978536877905029441 E-10 - 121618014.27868918928 813042666797114529*I [6, 3]: 2.6131773608228030862436154291215029458 E-13 - 121963623349.56963053 464019824934463602*I [6, 4]: -3689851.3824160519844673516400513272729 - 205195.348659968658569759 91788233215816*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: 0.58245577631758767297591196874548910891 - 1.44030896971971272914426 26374028590791*I [7, 3]: 0.38021680508212671683351192801028812479 - 0.98141687216350076398947 866786133576037*I [7, 4]: 0.20154312205360321787812231235059586177 - 0.76783553572168519458542 835586375224028*I besselh2 [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + (-1/4 + 1/2*I)*x^2 + (1/64 - 3/64*I)*x^4 + (-1/2304 + 11/6912*I) *x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 - 0.08825696421567695798292 6766023515162828*I [2, 3]: 0.93846980724081290422840467359971262557 + 0.44451873350670655714839 847506833191038*I [2, 4]: 1.6477670588097637977792999000562559034 - 0.942004436545154646198413 22655202096895*I [3, 1]: -4*I*x^-2 + (1 - I) + (-1/8 + 5/16*I)*x^2 + O(x^3) [3, 2]: 0.44005058574493351595968220371891491313 + 0.78121282130028871654715 000004796482055*I [3, 3]: 0.24226845767487388638395457614153164080 + 1.47147239267024306918858 46353232974532*I [3, 4]: 1.2439613389157879924008217252327509830 + 1.022722564418433025377072 5711483489108*I [4, 1]: (1 + I) + (-1/6 - 1/2*I)*x^2 + (1/120 + 1/24*I)*x^4 + (-1/5040 - 1/7 20*I)*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708055 + 0.43109886801837607952052 096729853340009*I [4, 3]: 0.54097378993452809133091313466411641349 + 0.99024588024340488002335 195542348755756*I [4, 4]: 1.7949514649306922611370433739385788319 + 0.323099244779188375242885 44204680075863*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: 0.26938214945091836540555327716757818205 + 1.03976259800634355895849 86807324939546*I [5, 3]: 0.10940542017270712675781308031594165118 + 2.26083223277617932197371 42212172870084*I [5, 4]: 0.79927619103677503777576265264156481050 + 1.08771932295608823645995 14526225738913*I [6, 1]: -380507258880*I*x^-20 - 10569646080*I*x^-18 - 165150720*I*x^-16 + O( x^-15) [6, 2]: 2.6306151236874532069978536877905029441 E-10 + 121618014.27868918928 813042666797114529*I [6, 3]: 2.6131773608228030862436154291215029458 E-13 + 121963623349.56963053 464019824934463602*I [6, 4]: 3689851.3824160527671366489980962693903 + 205195.3486599858655861754 3080013707678*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: -0.053793008222511491987048146883432543616 + 0.334151434861435901321 42313893855556329*I [7, 3]: -0.56713133425013005304402421178983091608 + 0.3472809452441059847447 3666211692428233*I [7, 4]: 0.56669526894058228371774833075826997077 + 0.56952668509437225367197 037537154780157*I besseli [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + 1/4*x^2 + 1/64*x^4 + 1/2304*x^6 + O(x^7) [2, 2]: 1.2660658777520083355982446252147175376 [2, 3]: 1.0634833707413235192631844154453565293 [2, 4]: 0.93760847680602927659973819742581871695 + 0.49652994760912213216645 972122523819950*I [3, 1]: 1 + 1/8*x^2 + 1/192*x^4 + 1/9216*x^6 + O(x^7) [3, 2]: 0.56515910399248502720769602760986330733 [3, 3]: 0.25789430539089631636247965952320963419 [3, 4]: 0.36502802882708778851335190162868643100 + 0.61416033492290361016921 965837550234589*I [4, 1]: 1 + 1/6*x^2 + 1/120*x^4 + 1/5040*x^6 + O(x^7) [4, 2]: 0.93767488824548764671726288439139336783 [4, 3]: 0.58799308679041632548887344016323449809 [4, 4]: 0.72698064596355457190337225790772836581 + 0.64183847533798587174998 976767935220305*I [5, 1]: 1 + 0.10355339059327376220042218105242451964*x^2 + 0.003791260736238 8304125791589473295974330*x^4 + 7.1572974488511092712416929822558597732 E-5* x^6 + O(x^7) [5, 2]: 0.33140333780825958195735832301263837654 [5, 3]: 0.11521946070729671962775067900799783493 [5, 4]: 0.12322584912763267310364477086934931491 + 0.47591631113525426300712 693607959667758*I [6, 1]: 1 + 1/44*x^2 + 1/4224*x^4 + 1/658944*x^6 + O(x^7) [6, 2]: 2.7529480398368736252357102010027635344 E-10 [6, 3]: 2.6430419258812795384721773266572060848 E-13 [6, 4]: -3.9133464867902247105872448856946075458 E-10 + 8.603508207756458902 4593151718189946275 E-9*I [7, 1]: 1 + (1/10 - 1/20*I)*x^2 + (1/320 - 1/320*I)*x^4 + (1/21760 - 1/13056 *I)*x^6 + O(x^7) [7, 2]: 0.25369454079993178519197028239401935067 - 0.70438419774772610421577 993808361942912*I [7, 3]: -0.10655105565636707643885659348968940182 - 0.3307637608360080173839 7259495461028707*I [7, 4]: 0.47875240945839830415507917927631039129 + 0.07128046026390996971374 9689821284593892*I besselj [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 - 1/4*x^2 + 1/64*x^4 - 1/2304*x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 [2, 3]: 0.93846980724081290422840467359971262557 [2, 4]: 0.93760847680602927659973819742581871695 - 0.49652994760912213216645 972122523819950*I [3, 1]: 1 - 1/8*x^2 + 1/192*x^4 - 1/9216*x^6 + O(x^7) [3, 2]: 0.44005058574493351595968220371891491313 [3, 3]: 0.24226845767487388638395457614153164080 [3, 4]: 0.61416033492290361016921965837550234589 + 0.36502802882708778851335 190162868643100*I [4, 1]: 1 - 1/6*x^2 + 1/120*x^4 - 1/5040*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708055 [4, 3]: 0.54097378993452809133091313466411641349 [4, 4]: 0.96790128289013061188438215640495233496 + 0.06020460621428170101212 6630105291248378*I [5, 1]: 1 - 0.10355339059327376220042218105242451964*x^2 + 0.003791260736238 8304125791589473295974330*x^4 - 7.1572974488511092712416929822558597732 E-5* x^6 + O(x^7) [5, 2]: 0.26938214945091836540555327716757818205 [5, 3]: 0.10940542017270712675781308031594165118 [5, 4]: 0.30404549284811478387834080084122518461 + 0.38631241680350013394025 690489885747395*I [6, 1]: 1 - 1/44*x^2 + 1/4224*x^4 - 1/658944*x^6 + O(x^7) [6, 2]: 2.6306151236874532069978536877905029441 E-10 [6, 3]: 2.6131773608228030862436154291215029458 E-13 [6, 4]: 3.9133464867902247105872448856946075458 E-10 + 8.6035082077564589024 593151718189946275 E-9*I [7, 1]: 1 + (-1/10 + 1/20*I)*x^2 + (1/320 - 1/320*I)*x^4 + (-1/21760 + 1/130 56*I)*x^6 + O(x^7) [7, 2]: 0.26433138404753809049443191093102828265 - 0.55307876742913841391141 974923215175792*I [7, 3]: -0.093457264584001668105256141889771395645 - 0.317067963459697389622 37100287220573902*I [7, 4]: 0.38411919549709275079793532155443291627 - 0.09915442531365647045672 8990246102219357*I besseljh [1, 1]: error("incorrect type in jbesselh (t_POL).") [1, 2]: error("incorrect type in jbesselh (t_POL).") [1, 3]: error("incorrect type in jbesselh (t_POL).") [1, 4]: error("incorrect type in jbesselh (t_POL).") [2, 1]: 1 - 1/6*x^2 + 1/120*x^4 - 1/5040*x^6 + O(x^7) [2, 2]: 0.67139670714180309041636401204046708055 [2, 3]: 0.54097378993452809133091313466411641349 [2, 4]: 0.96790128289013061188438215640495233496 + 0.06020460621428170101212 6630105291248379*I [3, 1]: 1 - 1/10*x^2 + 1/280*x^4 - 1/15120*x^6 + O(x^7) [3, 2]: 0.24029783912342701089584304474193368046 [3, 3]: 0.091701699625651302638474313904745269419 [3, 4]: 0.25115830598729948221749558131361228142 + 0.37320184370263719381653 345438379595363*I [4, 1]: error("incorrect type in jbesselh (t_FRAC).") [4, 2]: error("incorrect type in jbesselh (t_FRAC).") [4, 3]: error("incorrect type in jbesselh (t_FRAC).") [4, 4]: error("incorrect type in jbesselh (t_FRAC).") [5, 1]: error("incorrect type in jbesselh (t_REAL).") [5, 2]: error("incorrect type in jbesselh (t_REAL).") [5, 3]: error("incorrect type in jbesselh (t_REAL).") [5, 4]: error("incorrect type in jbesselh (t_REAL).") [6, 1]: 1 - 1/46*x^2 + 1/4600*x^4 - 1/745200*x^6 + O(x^7) [6, 2]: 5.6781874776346222994224383562334313034 E-11 [6, 3]: 3.9855051571881421614590449651836245138 E-14 [6, 4]: -7.5567733209249243890627329164720828368 E-10 + 2.075203626533608360 9444796696375043842 E-9*I [7, 1]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 2]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 3]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 4]: error("incorrect type in jbesselh (t_COMPLEX).") besselk [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1/2*x^2 + 3/64*x^4 + 11/6912*x^6 + O(x^7) [2, 2]: 0.42102443824070833333562737921260903614 [2, 3]: 0.92441907122766586178192416753021698954 [2, 4]: 0.080197726946517818726968736564279166834 - 0.3572774592853302506059 4569325002398166*I [3, 1]: -4*x^-2 + 1 + 5/16*x^2 + O(x^3) [3, 2]: 0.60190723019723457473754000153561733926 [3, 3]: 1.6564411200033008936964454031740915115 [3, 4]: 0.024568305523740348612477346185201235995 - 0.4597194738011893647760 4300851857199811*I [4, 1]: 1/2*x^-1 - 1 + 1/4*x - 1/6*x^2 + 1/48*x^3 - 1/120*x^4 + O(x^5) [4, 2]: 0.46106850444789455843957587387569458969 [4, 3]: 1.0750476034999202387227558602482085118 [4, 4]: 0.068685783419996419480057426969766668173 - 0.3815782598126830739602 7449697029326916*I [5, 1]: error("domain error in besselk: 2n mod Z != 0") [5, 2]: 0.84808712130706055249297377794312403937 [5, 3]: 2.8356740750874926233948621504947623564 [5, 4]: -0.060833677914566850837201614245364256444 - 0.575727321703454299901 71626792018756559*I [6, 1]: 380507258880*x^-20 - 10569646080*x^-18 + 165150720*x^-16 + O(x^-15) [6, 2]: 180713289.90102945469159786130234001591 [6, 3]: 188937569319.90025964462417816833870273 [6, 4]: -322320.09995047688108832869622332914303 - 5796004.99791820584997486 34606037942199*I [7, 1]: error("domain error in besselk: 2n mod Z != 0") [7, 2]: 0.32545977186584141085464640324923711950 + 0.28942803702599212763456 715924152302743*I [7, 3]: 0.38335176781651847215073123333424046030 + 0.96679218008775594813220 288497987441030*I [7, 4]: 0.31594457269950863123935043154373419884 - 0.40665811731437652111601 397817696670098*I besseln [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: -1/2*x^2 + 3/64*x^4 - 11/6912*x^6 + O(x^7) [2, 2]: 0.088256964215676957982926766023515162828 [2, 3]: -0.44451873350670655714839847506833191038 [2, 4]: 0.44547448893603251403195350532678276945 + 0.71015858200373452117956 170263043718646*I [3, 1]: 4*x^-2 + 1 - 5/16*x^2 + O(x^3) [3, 2]: -0.78121282130028871654715000004796482055 [3, 3]: -1.4714723926702430691885846353232974532 [3, 4]: -0.65769453559134523686372066951966247983 + 0.6298010039928843822316 0206685724863709*I [4, 1]: -1 + 1/2*x^2 - 1/24*x^4 + 1/720*x^6 + O(x^7) [4, 2]: -0.43109886801837607952052096729853340009 [4, 3]: -0.99024588024340488002335195542348755756 [4, 4]: -0.26289463856490667423075881194150951025 + 0.8270501820405616492526 6121753362649691*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: -1.0397625980063435589584986807324939546 [5, 3]: -2.2608322327761793219737142212172870084 [5, 4]: -0.70140690615258810251969454772371641734 + 0.4952306981886602538974 2185180033962590*I [6, 1]: 380507258880*x^-20 + 10569646080*x^-18 + 165150720*x^-16 + O(x^-15) [6, 2]: -121618014.27868918928813042666797114529 [6, 3]: -121963623349.56963053464019824934463602 [6, 4]: -205195.34865997726207796767434123461747 + 3689851.38241605237580200 03190737983316*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: -0.88723020229057431523284288817070732122 - 0.3181243922700495824814 8005781446082626*I [7, 3]: -0.66434890870380337436710766498913002135 - 0.4736740696661283849387 6806990005952043*I [7, 4]: -0.66868111040802872412869936561765002092 + 0.1825760734434895329198 1300920383705450*I [0.38318604387456485808270441031554362199 - 1.130318207984970054415392055219 7266147*I, -0.38318604387456485808270441031554362199 + 0.E-38*I]~ [-0.38318604387456485808270441031554362199 + 0.E-38*I, 0.3831860438745648580 8270441031554362199 + 1.1303182079849700544153920552197266147*I]~ [0.E-39 - 0.44005058574493351595968220371891491313*I, 0.E-39 + 0.44005058574 493351595968220371891491313*I]~ [0.E-38 - 0.56515910399248502720769602760986330733*I, 0.E-38 + 0.56515910399 248502720769602760986330733*I]~ [-0.20755374871029735167013412472066868268 - 0.20755374871029735167013412472 066868268*I, -0.20755374871029735167013412472066868268 + 0.20755374871029735 167013412472066868268*I]~ [-0.69122984369208426288314166384697051872 + 1.22712623014357148924328078170 72674867*I, -0.69122984369208426288314166384697051872 - 1.227126230143571489 2432807817072674867*I]~ [-0.56515910399248502720769602760986330733 - 0.38318604387456485808270441031 554362199*I, -0.56515910399248502720769602760986330733 + 0.38318604387456485 808270441031554362199*I]~ [0.44005058574493351595968220371891491313 - 0.781212821300288716547150000047 96482055*I] [0.44005058574493351595968220371891491313 + 0.781212821300288716547150000047 96482055*I] [0.56515910399248502720769602760986330733] [0.44005058574493351595968220371891491313] [0.24029783912342701089584304474193368046] [0.60190723019723457473754000153561733926] [-0.78121282130028871654715000004796482055] [0.44005058574493351595968220371891491313 - 0.781212821300288716547150000047 96482055*I]~ [0.44005058574493351595968220371891491313 + 0.781212821300288716547150000047 96482055*I]~ [0.56515910399248502720769602760986330733]~ [0.44005058574493351595968220371891491313]~ [0.24029783912342701089584304474193368046]~ [0.60190723019723457473754000153561733926]~ [-0.78121282130028871654715000004796482055]~ Mat(0.44005058574493351595968220371891491313 - 0.781212821300288716547150000 04796482055*I) Mat(0.44005058574493351595968220371891491313 + 0.781212821300288716547150000 04796482055*I) Mat(0.56515910399248502720769602760986330733) Mat(0.44005058574493351595968220371891491313) Mat(0.24029783912342701089584304474193368046) Mat(0.60190723019723457473754000153561733926) Mat(-0.78121282130028871654715000004796482055) 0.E-96 5.3192304053524357058659474657917582463 E-127 2.0125228237125015700004500237283661172 E-436 5.7412378153505365740198971395908944617 E-10 2.0105123109834969409015328783614871604 E-436 + 0.E-475*I 11.628856980944362293418444710423341176 Total time spent: 32 pari-2.7.5/src/test/32/quadray0000644000175000017500000024470712432421614014506 0ustar billbill-15: x^2 - x + 1 -35: x^2 - x - 1 -51: x^2 - x + 1 -91: x^2 - x + 2 -115: x^2 - x - 1 -123: x^2 - x + 1 -187: x^2 - x + 3 -195: x^4 - x^3 + 2*x^2 + x + 1 -235: x^2 - x - 1 -267: x^2 - x + 1 -403: x^2 - x - 3 -427: x^2 - x + 2 -435: x^4 - x^3 + 2*x^2 + x + 1 -483: x^4 - x^3 - x^2 - 2*x + 4 -555: x^4 - x^3 + 2*x^2 + x + 1 -595: x^4 - x^3 + 5*x^2 + 2*x + 4 -627: x^4 - x^3 - 2*x^2 - 3*x + 9 -715: x^4 - x^3 + 8*x^2 + 3*x + 9 -795: x^4 - x^3 + 2*x^2 + x + 1 -1155: x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1 -1435: x^4 - x^3 + 5*x^2 + 2*x + 4 -1995: x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1 -3003: x^8 - 9*x^6 + 80*x^4 - 9*x^2 + 1 -3315: x^8 + 9*x^6 + 77*x^4 + 36*x^2 + 16 -20: x^2 + 1 -24: x^2 - 2 -40: x^2 + 2 -52: x^2 + 1 -84: x^4 - x^2 + 1 -88: x^2 - 2 -120: x^4 + 2*x^2 + 4 -132: x^4 - x^2 + 1 -148: x^2 + 1 -168: x^4 - 2*x^3 + x^2 + 6*x + 3 -228: x^4 - x^2 + 1 -232: x^2 + 2 -280: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 -312: x^4 + 2*x^2 + 4 -340: x^4 + 3*x^2 + 1 -372: x^4 - x^2 + 1 -408: x^4 + 2*x^2 + 4 -420: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -520: x^4 + 6*x^2 + 4 -532: x^4 - 3*x^2 + 4 -660: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -708: x^4 - x^2 + 1 -760: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 -840: x^8 - 4*x^7 - 2*x^6 + 20*x^5 - 3*x^4 - 32*x^3 + 64*x^2 - 44*x + 19 -1012: x^4 - 5*x^2 + 9 -1092: x^8 + 3*x^6 + 5*x^4 + 12*x^2 + 16 -1320: x^8 - 4*x^7 - 2*x^6 + 20*x^5 - 3*x^4 - 32*x^3 + 64*x^2 - 44*x + 19 -1380: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -1428: x^8 + 3*x^6 + 5*x^4 + 12*x^2 + 16 -1540: x^8 - 4*x^7 + 20*x^6 - 46*x^5 + 93*x^4 - 114*x^3 + 92*x^2 - 42*x + 9 -1848: x^8 - 2*x^7 + 3*x^6 - 14*x^5 + 65*x^4 - 64*x^3 + 46*x^2 + 24*x + 4 -5460: x^16 + 9*x^14 + 44*x^12 + 261*x^10 + 1029*x^8 + 1044*x^6 + 704*x^4 + 576*x^2 + 256 x^20 + 27*x^19 + 601*x^18 - 4014*x^17 + 9878*x^16 - 12222*x^15 + 8299*x^14 + 513*x^13 - 12221*x^12 + 18036*x^11 - 17652*x^10 + 18036*x^9 - 12221*x^8 + 5 13*x^7 + 8299*x^6 - 12222*x^5 + 9878*x^4 - 4014*x^3 + 601*x^2 + 27*x + 1 x^88 - 40020669926358941160*x^87 + 24818793423306608856949584839454391158484 *x^86 - 451973748435231895940407803697160552367624*x^85 + 121004331374769746 054948634032289469332999202*x^84 + 10059034519705811655247252004833057160111 397504*x^83 + 351284965440856373689297063590147136894509846260*x^82 + 707678 7287183022340559185242964779073439110772112*x^81 + 7424864222152380159098443 6783829317747047323123243*x^80 + 3016669049298212175376092685252207677089225 7842640*x^79 - 8503049963424563714394067134889147531482230019127096*x^78 - 6 465786499366041070602916523486769538280412443510592*x^77 + 42150640446078238 28889410160434091263108115351306399268*x^76 + 119525498598846149476451596656 291689313170011135603889064*x^75 + 20718604339256925426029633374659465824208 08944831769026648*x^74 + 270442350108592451558861828173327053458397647311211 61439752*x^73 + 285289444253762620585561596576563633155859094294552566693317 *x^72 + 2511360320483460798105377398519192324398612242438706127652544*x^71 + 18767162620094934148004508464072766541604227783326918296860524*x^70 + 12042 3236654140529086575067911655764408706511359484732574173280*x^69 + 6698817371 51097381424117880193907743151768744395737304965311638*x^68 + 326030488372458 1257592451461949148632593587481718123636435123040*x^67 + 1401218174432359703 4445628272252822116949974099153581386829916444*x^66 + 5367567444185487660948 9208131197694348596313231643993076280314304*x^65 + 1849586073448214933624859 71605260396892443743494472396759635803315*x^64 + 578456213592452525292885126 678569328965911834184953238551507495512*x^63 + 16556817033476544452278210145 76515450466671643615335188802513429760*x^62 + 436878840618787239769625306249 7812500894047454768846457782824580152*x^61 + 1068901472860957747029160191079 1767817886254017900185293235705392064*x^60 + 2434351573155431230076300160060 7496079487124511808873652848483412160*x^59 + 5169291351655811457272426459136 7158576380942435990299052219843612304*x^58 + 1022998330750281135258911239455 74251052215437006684583051817380710576*x^57 + 188216797464058241448403558395 102741401235865324690992824034126437157*x^56 + 32060490325705765556225025226 1154391117300969466803557524988405580272*x^55 + 5026257120330186308702396982 13303008551061011852403188260952091908532*x^54 + 719344126023656757735145641 575616692987264009491520118662670217955328*x^53 + 92863816021928333070040902 0325566534550048821651703177989079236808666*x^52 + 1060255920795694954480037 612092276836813066528658822564102146651872808*x^51 + 10301589215685511855337 00012926850740762293883499745887488519869745108*x^50 + 771562428494427189300 153767022260995609490878443644218508155682351496*x^49 + 27346597807333111348 9250648988966144580871198921998690911757680224167*x^48 - 3923005119785941970 23702549831167038133623220261146198494006317061248*x^47 - 107531566077276356 7397744183394797701786847214693166357365831146616968*x^46 - 1589451619928021 606930471659130946568147974811578111348229080651241920*x^45 - 17807285584553 57793403089789263493950243261264268279117584476244784076*x^44 - 158945161992 8021606930471659130946568147974811578111348229080651241920*x^43 - 1075315660 772763567397744183394797701786847214693166357365831146616968*x^42 - 39230051 1978594197023702549831167038133623220261146198494006317061248*x^41 + 2734659 78073331113489250648988966144580871198921998690911757680224167*x^40 + 771562 428494427189300153767022260995609490878443644218508155682351496*x^39 + 10301 58921568551185533700012926850740762293883499745887488519869745108*x^38 + 106 0255920795694954480037612092276836813066528658822564102146651872808*x^37 + 9 28638160219283330700409020325566534550048821651703177989079236808666*x^36 + 719344126023656757735145641575616692987264009491520118662670217955328*x^35 + 502625712033018630870239698213303008551061011852403188260952091908532*x^34 + 320604903257057655562250252261154391117300969466803557524988405580272*x^33 + 188216797464058241448403558395102741401235865324690992824034126437157*x^3 2 + 102299833075028113525891123945574251052215437006684583051817380710576*x^ 31 + 51692913516558114572724264591367158576380942435990299052219843612304*x^ 30 + 24343515731554312300763001600607496079487124511808873652848483412160*x^ 29 + 10689014728609577470291601910791767817886254017900185293235705392064*x^ 28 + 4368788406187872397696253062497812500894047454768846457782824580152*x^2 7 + 1655681703347654445227821014576515450466671643615335188802513429760*x^26 + 578456213592452525292885126678569328965911834184953238551507495512*x^25 + 184958607344821493362485971605260396892443743494472396759635803315*x^24 + 5 3675674441854876609489208131197694348596313231643993076280314304*x^23 + 1401 2181744323597034445628272252822116949974099153581386829916444*x^22 + 3260304 883724581257592451461949148632593587481718123636435123040*x^21 + 66988173715 1097381424117880193907743151768744395737304965311638*x^20 + 1204232366541405 29086575067911655764408706511359484732574173280*x^19 + 187671626200949341480 04508464072766541604227783326918296860524*x^18 + 251136032048346079810537739 8519192324398612242438706127652544*x^17 + 2852894442537626205855615965765636 33155859094294552566693317*x^16 + 270442350108592451558861828173327053458397 64731121161439752*x^15 + 207186043392569254260296333746594658242080894483176 9026648*x^14 + 119525498598846149476451596656291689313170011135603889064*x^1 3 + 4215064044607823828889410160434091263108115351306399268*x^12 - 646578649 9366041070602916523486769538280412443510592*x^11 - 8503049963424563714394067 134889147531482230019127096*x^10 + 30166690492982121753760926852522076770892 257842640*x^9 + 74248642221523801590984436783829317747047323123243*x^8 + 707 6787287183022340559185242964779073439110772112*x^7 + 35128496544085637368929 7063590147136894509846260*x^6 + 10059034519705811655247252004833057160111397 504*x^5 + 121004331374769746054948634032289469332999202*x^4 - 45197374843523 1895940407803697160552367624*x^3 + 24818793423306608856949584839454391158484 *x^2 - 40020669926358941160*x + 1 x^180 - 51943580593235209115083942712389400740668999369044471856895869572767 632154790719027854950985687*x^179 + 2547067915519807589841747083394507454979 0011527047653789753822310509943417124290253283094780925633779566003695241876 25607464220675698078104131248853904115685519116107718359916443145223952387*x ^178 + 856553204115408701571995615320558014258368114267533599476048702248757 8902931990647387774030794984717551258507939754932426394582122894184128382067 3569718022270291080598668993546776793532380154605306*x^177 + 762080502049470 4596056107304576599883142953678664313128034639146864833136453854583485947432 8177873097803164055573630934557797549232895603414584717394309407907786380469 1683834066404398393999145427753183790*x^176 + 308956387636466960153212938167 7324702311668880384172270669030644914696644648416192123216702361395347555520 1495693461977412751821857739072346944409047470651675235147675440424833117756 620892810879743135932320774*x^175 + 4884082662966665508762665969667649569784 5383873744492103182446854649967702283785050616521253612447115822047297077954 9614257317623478309277167745811150568304415956966429217813229788441116863100 4611840186992685967179*x^174 + 124005751296377747143710892598982088036932674 2142684503704154223658839486788375142268292156393058732202380086677633411654 8906703591687073852643697697716348962297583421466683339923965234468615997649 73368284228647193399*x^173 + 77807342164244792507055296791047457009683139076 6947550930281827860194252415153283906741350015821421760488076097868784697023 0684361377176470035198102530788844464458277074023468487612291349831916437723 0037354352780222249*x^172 - 266780829858115272388789250462200876445272313022 9458822467054384295379499065005972497338635889603051515741573734931874924695 7762408306245748926170958653384087543385833522528441856486249210097660034861 41241557823792412532*x^171 + 14828387316468627026106844845255173547861518903 8589804985538974108300682790820861191991101023068971076505863346789787263249 0126030705881134291752595991307720023292738164624564498269365143236280388326 494814603159167594322356*x^170 + 2072714630254694525113015470563866763470442 2896220054319081495621750749375349838158314700070013284414958575563065629489 9298590460673967042987581924280852650108640761845803254699501956119005286958 261737898381117495750422003980*x^169 + 4082791913658668250669500487553396688 5085691856416081922391794020222319071345465620337482939902695391053957179581 6611178564058054521757672875527012214760684410920857152888054853976552319787 6482624865506579220641586389147210551*x^168 + 259189082653047933938409996483 4388754704904320561628999269016762833054641395201768798413743705844841716523 7122469823713043234758088183799986341785098434142194216335145773402440120312 8996614247360365624068492442391061043753826375*x^167 + 187953325502846394560 1845576629993961992277419183089685715578164443785846738744772926323542142109 3239442057010359289122214569790614009609800219235849343052099855997036406115 0923659276590113217049579865275822653265241753456459305677*x^166 - 991521344 5331010597888861249891641758957210552260378821158082129353375249195112911754 5101896722210096101308894624313777264446536224444928929934283573873319884763 96421078624456037269503565600020449431475165029149896378441501395456086*x^16 5 + 870693463207410936114722926699616258456056310070174066271951439226764821 3754498248686363880077592953938815295745097173153881494887680426204688519814 5897926708879854493196612672343274340176910775178567635481360192954408109761 462192666*x^164 + 3291269524452623301119531480681600174871375032940729132937 0111633092058003369070348946123426594086592059620504463833497832222752798945 6786539655327366403796168376108709100410788811433213881703418728731545343808 0442501304279059153710266*x^163 - 484246978651008470853848049302633937841710 0550099032573348884254048698254002568503682165709558099310997622779159632947 3025430835921039731844769840401840637061784295187888579980063280775750740026 326213445261209232925320378956182578938287*x^162 + 2366596557978274147475255 9694980204169227021539516608112189319106501133980328077568567038119905399100 7262473707379165967733688444634721899783534252243520926838729652205328556398 93844358125373580233579396300331967493836532017339326648417*x^161 - 17861170 0215272735065228998593221635895564621730723507909826896490382687997403628306 4372396936244334959016553113715105764010891971421665085465778102274753181053 1359367179288752406620535700142801097476915172283884503644920276078920893715 961*x^160 + 5442886569416213072883949195207003561672975168183342200753916623 1352236561897735153650345477157913505173224695785900066453147636135746522196 8827923591138659172463973059604218652821751160134239388400400287612441644522 959559654240096950196384*x^159 - 1878459194456192332344340381238953837099207 3242518317157665963817987346890603378811086853859511458448823118145390556032 4154260960085054869261002833248663395080605671172589053299559751809388877985 0319337022684143396368259434426190698508218580*x^158 - 184127686942437509991 1682977301117955663562464265148547217904344728959181240974449884065092029207 1219636898969097801966235466592457246648086083637230209961453625153292993135 3654541155851737335657948991190630601809654864812836013412428233332508*x^157 + 6272745337714289642780597731451440214649776184728899306566105704002623998 3846347725688034820317498349655377903497224390190783460776334008364647848917 2185092927745795075828017034702156144511828098427591206009505705409852728295 6922223630676347544*x^156 - 130604497267883349741727434418972048161536102040 0079797720405754446746742329603550983122106752795162131799337624121456619065 4040984420476843424034832196407821304821044910660899700295392042290695059542 0192036616889048813209519926849958791965413764*x^155 + 193926478941415365968 2053039191650223015193274556301436638340272814361000782491228757908126714135 5744831221609082890601733276886531625139761625422579999591146356457708488690 66496229883200724281039999541182828857613242844117034223500903997780849964*x ^154 - 208974081851580435134258388853435474877812078509775426825496895616316 4247844796032344219123951883470813854035626246176679417061266672681500232259 0819881630082047200072248185982748889171705144305698252911851141436968395735 658717414968653352018931248*x^153 + 1672646641882017449123000870294181985430 0761766363953593948968045530794890931499833945021531203099422476121576329491 5115325960697513628674724029981734640823975379662772003784140453861998461512 834247290509716832865395591217427305274661390000337103156*x^152 - 1133671449 3365295420476716878286616778916616227898741966819659317216135015136322466563 9827520548877905001507920274192410200096811676503284991805981968482979122155 1667739765953276248859306767909175625527281202034750975189910458947747942582 531447345892*x^151 + 9686019535728726397130721344019529061590234306774474243 9775684839133142925738217830167297947427381690011105467748624943273307935251 9499655312785116384255798310740712404573339361423884780107379495371631287103 7645627569348897599991117672316256550430096*x^150 - 119041422102704367724958 8670984575013578769595187713509039012506017888268506357273229685836102923546 0042880742312037127040383670254597841508519424535302963725051506007472454825 8974287875801351389617602402488639578930420752407411968308213028222350043652 *x^149 + 1390123122192263005517637294725114792837919558648428420458046731138 9247265920089325134952307005121333495864776226593824308305802270042865765522 1706646232757561716861576911604612712092794424651617086755060497490406116694 4942837594012909743669233042838778*x^148 - 123556176727604048392495454055977 6399401450331126081896858806346942631913417189093648332266104142047071085393 9823740200206373338590719973268754644225041558662153246796876936041537325415 712055287848699094590808089508684909536725801531454334504662219155298*x^147 + 78338857321405672298333791473025282082268588399811517655878927064487660842 9607987213338588537735184368455093544029691810855962878302724567812912958403 0825298526758499964573195767901492416707505928731723979119497738428625056534 2370732550549861221973628014*x^146 - 337429582052616696434247676773381390391 7055420548509812685321889562165936397719575630122778103303140528950818170117 1026255806634894861047352747650017243235019037703269391120793396636598558834 3500355068020592838333693543614719695933939552850201760137124456*x^145 + 126 7022512449095517765635963857489440320956185849532448394191453064873093377283 3265337003928417799194535821386624283453961529673399508105934582815314275613 7678638219426069444953840237686338226443443810754745407998159540925231095791 4375045407870857103723132*x^144 - 153719609646143637199240438779331521362833 0310998022856189520090149655383700607165028197046414621578662674582267335714 8666559983310416796564643262431404031085708670498514131879172395315308884725 086995597751964859239544450069420287019254955379338574827976392*x^143 + 2752 6304730305492309519611803297873567100995379403820014027217572772469997269963 1748009334990330332456740707557146239264293783419594063347012801512753255648 8881765170905842263824483323437412768565907107652500759762684840263032684703 37380600828996170962184046*x^142 - 35523095157828313337139462591351702816577 1657314332343178845563474958542277571903631744992145135630234735095041102708 2345107273636547410151070834277389339249300538652341339871040322822838485719 858336476359261521139254885461283464480406069617193177086233150446*x^141 + 3 4465803554989246489275769454764022910035142135182748059069252044933640478411 7307420416885830806110765171489332421312130211574457885515807957701177125587 6661225789242989640797022695297712572706533434600560766081391785453226598427 1205078552129981020849945722662*x^140 - 268373722516115839581073071008494919 0456447093682830001175926782807962713700083271168738651540876330140533486735 6212670696857859739463338404796759488859624213038265846572508064515479105995 6333436847011768914542767112707721040710586854450242752202162514502517912*x^ 139 + 1742444297891369493991077844263622734267621349666334184372478600323885 9274274057411635646353155281298451648136704209002938845039923935043096379256 4945721786177563429720654144039386133241554831725367065310144005542392522004 1645737733894132094639323829473024157820*x^138 - 963039078892037951990470202 7468142690696595830419680618831266273162745223389393610063433083213953579433 1498149151107810908751113241849208570338521838179678717281819508263987198750 1951924824700995996767534695158748257780864272656666861530432230128739030598 8300028*x^137 + 457447376242160839222865523212081512251204172769554541536513 6010675335568757571514112103791600745366139173664147588418919365588570555754 7201003803879915712080042312095406320055413204732204964260573379515119902554 321889204610298573371864198642424001195728006133182*x^136 - 1868860578136529 9491100566653843653174297026478659238845320831747624530880395790502643308730 5462268585078679776019946603866991516563272428283420299615035631054324035580 7669631492489263529234747091359176119230324423792605912297491073916656362078 32174634098946284598*x^135 + 65093076668803329116252899967129264121954195081 3165825173825622033622982444205859242607493663511833086292972086895883603422 4352287091011138657074487961579204189764700353920301472872505685227133477493 45517047708745645767806883427498415677547239236298519819304443846*x^134 - 18 8737857214948682414768736751123125995536055732425264657481481197221465136381 8263080004881765201151009039934832304971738613022285488660591980899059758561 7366670880266091842937662126151457793355558304191543211766144762254313419741 75714575265820939899419742919508060*x^133 + 42953889394645520155740965583894 8254975167613584775116826651538942451816286881091436166450578237021021126058 7376408754507104013237607018922017023401049094197048725524392809860540776061 0681787413121689140926769612819886834513469809393226136437731088172895759675 25206*x^132 - 63261727328918865906350940397161109868277289808692349026207015 7309911965921420948111081525007085507792610014228611379115265836635218591862 4482685303352489099685390524441351132050179570452776530090912230189731431879 125807895290459527651483474680605068851138729175634*x^131 - 1119917054839792 2751688900486058857057243360132605635779686384574213339264438353376214516815 2207498910643644483743753772520064969246600402986900436948848152659373181329 5043050789946887406470007794027558566892567839570362080341591028664006259784 979214096682612622692*x^130 + 4271314220049466852560738338393246245128105321 7108326600567680720579375803199815405014779522998261575404021302604267102318 9973496984002749534274370752056057799997646445393423249459072172570153388076 90270224780252688493775073451490812831750493851260007482523315136586*x^129 - 148023590100710673141860886464816208028643509093283015533625006596766946972 6741578398020050334876578221252235677233082465182051389340632694789790351225 9115953643872578590861494318898368229141353955324644187699428307147375218229 1248178529493117079561875143739124185634*x^128 + 246175641614565897679653848 5278045743286736401969417596627545851445013857575343959525966011452777041860 1869322995580927692188758796260764328940765798775338277071600497396412898284 6342663264119335560750008714258096212502569271025201095741906534219351860811 124404494196*x^127 + 1990565893680671595442880060323376805411690898242032023 4239133079106312028397798694740007864603898415855926572783576585034622967997 5575446479539827712484639591071048813727255731760017261708300771575388890158 591817638333201062459001177511936169630253047386566741135222*x^126 - 3016573 2341675486865253308430441797191448447887193219597832133129727214089635223501 3420645212244383261917032590855201496548201420356430642227248391186457171733 8876314939133108407277975244227776960656325124355051502725255975073566061339 620994099300340563608380613367050*x^125 + 1257948144362960333134666662231940 3520935251787268873160231319726921665830921964289640164226960267401382195941 0507546787902030963701849030258171787071185516798073095493413189997247441301 2363645824641255038770075189157898962912949013449974648054148641764400320533 8871882*x^124 - 366475271260105058017315536083033948306360270631496526170966 8533370069635382315040133597595175856841519762702237383805014287542574172530 6210807276260801506088986006283626986882464595447299254658758485568943925875 853699462405048328247959368186852953798221740253247284792*x^123 + 8471667404 0018254168541029547267006611224730675524513635334023354380604251758054675593 5413776225446989659313910683079873583112382327573250917778108062870743163021 6965584066720515779759514188951805094972301673794254962048375194153324360075 8727975735045108792516939770864*x^122 - 161146935717428461799784793801173853 4799737191324944707968337975196134044400893575466678041623869973266066574271 1435647219232676062975775017270732119064549881937724549671623652481177104960 6102487507016989267838733791065664530366349655384775511706599600386112512946 557632*x^121 + 2522694849864480951479825412582961761101029175375006299005032 3620295897587695065324670940000207944207812042399077482469097012869133985212 6354595110186421998141347799854111539239085705015451817020704883026517132793 698058647769011690212936405831828960609809154392310067086*x^120 - 3123954350 9500414655822246820581466016766786100370771446195101114970617420873338985187 2315673998753642061765284674623730429562551231647203516276142369010876697525 2061798837483708658347309888670578337964579148520979957165473678360131302986 17785547855899873691057926811306*x^119 + 26093073450128435322247521043157618 8712392067239030279298185926981851613832003883595362112194063431825921469777 7131659026396971729721032938463093179955600695600080670675651357367571081793 3768796854158042814794986008423382503555686761603718155957955520619915926285 1046258*x^118 - 546620888417310306456913297002373587712583541328636451073449 6886209350963457906027266059482196156973048570086277940148682564568467798438 0285254978737341206009503937974698380503149962544290779617099637261387918629 06553536781663415296571417609896418531671323802662549340*x^117 - 50182021729 3272384861232464186597002893681068429473599603378492391207630929901153313074 7556376877685127771266174954090809732508146930392545806488414232849981602588 1335383921214771830072947665323419883309028215410288472590477875403748309525 8171403839074803113722901930619*x^116 + 118406103336876158577917454186709740 5449294198484094378541103762383848536861007244183348157579457933081098099434 7987985778741196393539613217121527222032672240767536916435194526743758819619 0063225181878442213678933572194923238652257406338724947439730929871504295850 1899245*x^115 - 176734272677759520180709847378647130652166835479092271077232 7067981192822476939413912953115815829947318808933249885514336602487836197536 9611127131928890515684844943744748937382837125994011164383657897820620204611 77419977223148716322298719262705865767989172293892727336803*x^114 + 17753024 8530519942716171951800965388948822797211110233322549229100349316200278964800 3343785390491378071036048329384421918922891522117638503012421231548652255160 9599399433846703918342084346728100760000876417162144138571778762943474072695 63098844605653811371200441716482612*x^113 - 68055808039422415389652936779491 5026270001374161671086886435342385993661681436002138177107204224273906832078 4550021770688659201646483026969760576245696112286845508450285259619203332272 0607576466516522822599227539775561873960850804338603845784871088630793662781 4494090172*x^112 - 171345855168993153971261857965957509597335839923271917993 0591415159154748543112880240425751510004701705465610982555391151034624958936 9879115829869566643976034053215829935761929815383663545384160654490729816046 26649741228358475390951398611771434975819632467920927623648602*x^111 + 47552 8035498943149856772358089912005247194452214038396267610512853006205877224336 1926512880782786766025384282981294577511242497413537295024045772317451006411 5818078293866049727834002439604775548744427611299658913382859972919684056285 23953865800092933414124830547621130787*x^110 - 67242845398127603346764378735 8630417913935967603492325560313387832908161625682986070993808856191981689362 7337618874976711707752413017492294772666895660870194024839210050819796389750 1107885069331081963929674153546422780993129544541729439872603263786386221427 59365186532673*x^109 + 55277967193070494108505087891929956655236889687657826 8175977451438771610569912425740087266827286735858716699401268464277514456005 1393232906738794805715412356740750890873873435323228244674952180988795091974 844777831874994317609349719963129292674653332785827444869904448205*x^108 - 4 1613159149582603037007821378021268206873842361757130321500129691291418451571 4472352328413744363607247454062853765212695133675510221970937823367502714872 5264869179155436190999803707918965482858909915679294544758294286168029187155 42674704594105656661109974298786084926216*x^107 - 64968550520798695907403393 0416095844971770756779773877908365468264830766792721054670459397639118998550 4854765543268865886038920660387928909044011453689430024047009170672072811027 5782636138143658008315348604258233043465414839888086317182504579245353574551 48087384017967480*x^106 + 10988704303885892826315283975311210242722783884449 6602821133827001873720461030281740372523131562861261636562127194114761297380 7567084209038324237434507186912029498523360122835533024309739840677831689412 3866277910335992520712968840312446267340837533424627065123680989778324*x^105 - 1037769081322395498728280928797930421673181636784651943232652987200370379 9887100753154281880152957110034253066824316513009332837888828809575782813589 8395431699875068691882278140209738486991188655032931569583339555950811469751 14819216369493334147767991300084429910831005417*x^104 + 69810186616581919293 4087787107108500858284600224749854536503416055380938630777674032345768445107 9032740625501338477163577149719360331436837611189692791831261366092124431433 6123841173727343108316374825964917374812406255193704152752318584125714566685 03155908009579048097943*x^103 - 62618742936856051264116083169826991776205278 5386210430790988069604384137878194361389699073225403863192706786752381073990 4629809810678656127043145873535279223707645117591581849318483810783264428888 878968101286898381392510682070079334990623735577742545874102235967038827767* x^102 + 88547713577136747022744956480711506392268841458610902634308115200722 8001393811863713127092848888453031249274119846056297769374759830206187529701 1903856417069237945552069729259203293736154678785007420066778201855082685563 641521979888163226986534911148352808279115809917358*x^101 - 4630158507380629 2388093315791533391137484806668109034703107450628858742143410102799736933423 6907074978067722826731138207487756769203481925052544349731537665931451375605 6491082785764360244007240454153410730447743408991269401214809728107755411693 172395012634341107448006498*x^100 - 1987106430336286502255096633621975778269 2749388116010785359867801694785712027822174277716791024889732874123796999017 1165326722657523135611227287116367063127157679861619224054599116072941563451 0018552431779605085569288059085092991937490866241369045567079522410549051673 8430*x^99 + 6116111486479868423461963851524196927490094772654137109281820240 9655601335862868609893744275312622546677599324483201519748792880440223783865 4698142956751915407410209991596924924552268184253687896341372281276522326101 46924043615114529192462392320461821295874662972625510705*x^98 - 858543407202 8582480876325305001979394403680268817452625497746550339718414937826890236809 6758090513332370728027354524452052318746523877507900393006790670253886201007 7151654142173689494119764321155798594114038476768325934248961469594904974057 82950778627016658691250674749383*x^97 + 490657445429729269017920968754688301 6620517611911217595219014813015157155188541123765870476789021829481317185682 2346556428383215072814614042291152340886085128841976463982340477579191182175 5499560251631802981685749888173758813318700520169103214089237413133223676806 81136483*x^96 + 588480356039113348615320015128938548650997950279831325677040 1070851758771375890193257175605171144175873327958813862484089151772708967824 5090710382325088735952719657758536202632425695397040762304230638936597396706 141037241892685559313526162149365318736429347633086308123732*x^95 - 17860801 0792691455581088588394658008616948993017279794644452692311940825238452683644 2319855428360563553746309477403369295008059059368147822762461583481089204503 0764049052795948146830428753094428042821800841448746792034840653376273350188 2132907610936220993092559868115464848*x^94 + 2080698898949934438755286742414 6744709766506973468237223938818775848985645787102709849630670421667929387077 1839075966340916755041077369098858794090822988106295163721588178394959186872 9508222800790599280424915420728365948473247641413622178547384599468880111768 92625701864148*x^93 - 855864218009308575944636024731111359775112255204531345 0227262959123310950664276060293965525931786616911167403341188615339530286675 6775269831884121745448799689118137607558616438099756213430487533482486835346 075682903923880766231253716972279618549611306311532332784130069552*x^92 - 13 6808840532983525733371616856915983783270410509211401019532102689258560876086 9527424128221769318567475482882108641281228508725452571176264919548871309015 8567261995935441375507973903437038954795573527871968541716126334097932463611 5855437833626026464694567238228672113384692*x^91 + 3083618181674886298656898 1166117178805224503007958449196073139881830099761716540415100166992970870487 3373126707079788137630463247890473378063608477167239399012803238136948080412 0312330266139820196748423629961267609185986608819581540758534872341667324689 62725982670350394704*x^90 - 289813403115309877208771459417444034084104076525 9424539591515173961928303088393009380304940043691096832523560373895822112785 5808066054703063840814273369617911574459101343616657558236169574623914019563 0152780337575962071156042744164046198739767637262303611768624103749962308*x^ 89 + 72613516630962625965473064217525199676649443527570426575481770740043888 6779646591936295747831851104939101651758342323554432645301127945581635380942 7667424563537772502070799105048465507245059623491244896462413185145901940314 5696053808385861551596378474452839548918080875392*x^88 + 2007137579167957439 0719911721927558340943820520648172319420534796396724837614574044411853430783 6722420021463109835306685189533078441109841798470591234934768692554906817588 1207883501035322616933512472492706367178783380343756988188031103657790713917 44233368892636267232901060*x^87 - 341583527690850438763926482860330447741875 4305316360798807536901393938873869395520682617524619723932218997197449552997 7902796418727196784273654618816384850023400797434252298928612530838816162641 9574193744111685493591811397803624718762999077541037470623557200013418602943 344*x^86 + 26018106816532769824515089189721783374074645569591071162155828403 0232272450337410678138897855399057733160129008028400975157648521806369052132 6598794386401757044711814737218799723053160173284842744313272283592926991658 43454191912138368855662104946473338105764358284022377572*x^85 - 285687497537 0233084322274278589877961032877493803575239781590446839383349838850110790540 3648812210524131836405185194224569727115488819662642038492004860753207681555 8064901322408777764393214575140844637199884061193474482510361153824419358509 00211274244171508240172003554579*x^84 - 185573110599032244389576804101570527 0843481327670529736455724859117579642729259313496498283495085435901054470028 2535196961772216663035884293412871166129440632779930980074617184610893507366 8787347778013694399060652311121162557391893749324368007933315027120013043270 445299679*x^83 + 25050117171467230890654410834087578617559538489554781281579 3157881185513898265592143907721703598168076058572348175071967137401886379765 0888321554412070999395502650926168357968511833244292802087783872357923454661 96695362647033860816591741894381954763538781291764410558313991*x^82 - 156624 0805166486574430551541640026858587070051407347684313586931160679067646271535 7829110559493831623647655992465253608722147473274284815377360979913488645232 4593004096825642014547164807256580851492214151707379016954878586353260655456 252800749153240368998676635038282783458*x^81 - 11012223211385811697215073324 1921762613953353874156837170764058477228457541142548719349032469796569578235 3672680465156231420291792630380279912309212851197963260878119761617542365940 8318430631980819407521411635240395800739279192347581702754335107271855384807 48046492479002*x^80 + 111235651556599161905998900669481587907856029607842384 7058721145611490097096177499329308286485980098377201553695581299300616429252 2896328548114223502627261314995818846022537138353738293647104367494387573394 8393580977308270455034395646105894483336815886915572733813700662098*x^79 - 1 2379020348161516025309044646747619580648761934003227421750700116671436042176 9234916272072233533611217288217765756191391217561297135624913793687875324800 7048123566476086580476470670309837456621193106958657582668447487991539286833 57031134988178799550492266664939630915472321*x^78 + 644986875872857655262996 2870357260072805613051355925273289691398310869281737114462536081840128975833 0126180055099077158183624456453836279081213829170321954905360807167962624432 0834840220201004905145194463702511094693925819892194681047038159942946067231 75356042055357536463*x^77 + 632358398592670498095591997355631111077729590643 2790651615164768723582162467454648690012209970035792209695666782959269273807 2446931808206460612526556054521554052793022216016750971388084812894581490191 87488153428597505906544272968607176655503312813518126744417345713254937*x^76 - 4407859464775144416487947396167367671725803977033500362272840558411894622 4142347820758760948628866949429655387790156661766965605123758771588193309114 1713374027265271324050920162934924792826148476476160753572716996003978356956 83804000368513801138734053137773265487620770740*x^75 + 416372459606780296337 1450264046151575655550849081038974416037216542290125884466463363808042083850 9725418382508403123824265992064946980309513636360132567064198384175231861989 9012223863450049443691606628550828159458118620199310401445249248178059313891 70550354597821348040080*x^74 - 184161864081127040151143217561783123125395859 3984003709177376821791781406937773897678496561663900933927169138471529228790 5120635576312602740572720848588646957621039854850944227105781066695720878550 615756344477554232044466772542846688611602947158650463473157163999798684880* x^73 - 294578669269207164351858864041819495442047310529305439637416055593898 7162766090787137613214756965908109965354836546249973970248312691190106013609 0096047571535265598414402965513205463264379299412109566296535132357163168956 32417972107859793797811490919775354115913639814509*x^72 + 116883470301786694 7940105919928790584076295711500240939987022716541425069544597244574520104343 0843831048650119597248348399831622778255382707463446772861932339155184508820 8691492120804327123688321050527154392082194558601074437356409645501206599517 48548591269958013706855735*x^71 - 962337617562843751668517056379887654984035 3607775335999245012386540197534720757701144759975007037123456361469330484819 1315697282222826434358396253666199318705803758613569124925030815057449171128 4560115497697369485081240160416963318875432658639303154335108578568393415001 1*x^70 + 3726752627853214173014791913150187098796942009506244634835348186874 6218248319652489347706949219918369593434279794434225414007742000717921598981 1967637764507611718683775885631603729498673872931482040372125187697058620137 8729901384977948736920393075869570682078658147246402*x^69 + 6664265109721472 5027167403028506905386766457143598965411785702251914095207487701546804662501 9973661173639310250173508615816977744154467727637322113813424769329746934178 2443037607433520297691194068563933234561377974297855282622664908800977935892 66781529161410379918516384*x^68 - 207155588658254864820236483929333843353850 2314782709935428769719703150188593756759875477634107095955930003335004909963 7806096997987389425073233030518177133541278388985086967790086225554199073757 9183726492903476789901947898423219398782945711055270770359481994540571424130 4*x^67 + 1533378023324702195795907021652744267401738630185227412509325644190 9317029060634416164456507736338956677716876820335111092883359676091733924360 7562229802747370137957394804745995747839571913841959663322372004062970960303 2739266325572053308062722007360886556152476819257995*x^66 - 5448017961352466 8954308761386777114515861425568699050923629567132295720176133619693154821070 6679446412666455188970580511515741859257380970964727783399666659463150181605 5832418778533170218818696428046565610812780388008951253152709903494726503303 47825776795872045310257331*x^65 - 782824212320460720852470872605130544762708 5270844370030560427574258798403117425649643063954946491985881365052474110155 1061361746263419716606571746236356433610334478429319747526941053865615635278 723792660268903548758991779230812111021711115289261014249648789576891768349* x^64 + 241834633150739573689757316859489557852802058328995612290604847372968 8962517428202844726500527178649942306770989823832330134459212595922531552449 0113231117621334324551438466322046602200466264537273693298034252254721421676 4952766269941267448422272698762518675998018630028*x^63 - 1666339352730570520 3639407453322817405171376787484109204948738088424073980877086807482951938601 8865103399869046069476520137316208493195695957902129110473449041403464176591 9862359175005557769808809061623387720644388156956972127266850675533756707525 90808120744985654078946*x^62 + 570449220804489887130193887685456156518623172 5938262332193484731157547462002602737462832660959996983966122744124822282431 6513410409807491982186685917971756931992668327222699312497837591559016609364 497532211515388699725043424503916154248093353508075820460159560673674726*x^6 1 + 379845061301619031112865499569621029871812941926085546779444789597593099 2185392685054292994780700584857914762885227739218300244363323904098764703684 3361325604313463057739669057343485520202139735014463468397975802705055082320 02067235766810391945048746973605012517899250*x^60 - 179994905002158006799826 1581248012266767598208187591516407746996243019260988129520947344375845837479 4375473622136858584586366278763492407789131148115802682216654123834671962143 5349323536462397163996997039950567353507544138641982512459740031444726096910 94329488186488560*x^59 + 119982265165997044452636805135365752758447406488957 0849779495733478576958767846719905517427473004995721810584114866176087023280 6873265056291159390228424704274613300367658551594974395489222878733856100659 323368722107547660243619913236809974787583082322603729616639857984*x^58 - 41 4498343303395026162273181308147077705273369693379285169454980456825999696414 1108191789225342382926105642661506635099783996258510012027273821755928691169 8167108483458843302305307979514403727827680023751217095370719902334212472094 52432417836264144119102122277397817768*x^57 + 151296257711150774319086699562 0621904293538949888063494638380250947255821384926730801679647950967103397199 8232664074317796747475932212744662087954481765782241246318995396862540981468 8990486802544852254612284845621149784604770996714678404380352987098024383778 212981782*x^56 + 77172024931648750131579375330854241317819193485030367789630 0194979153932088946756095579709069441269038355362032598061536345375371499825 7603589364289068081989344439616890875432673156016666549955986167393531518011 67940120441305635456765616769010583292909919688853748166*x^55 - 533362214813 2692571383637474154386631336646003027379100089536309803633081806433335487865 3788348099478071550518684140405592181062300213393211342562869431261195244746 4055597603055279266341016276936298547770626014341819185195774706572228813839 188337921892972222814214310*x^54 + 19809672028428641640899800622402763302466 1074260655961612294389483118237887223011979572958763434751014838641676318160 5147310285574152096915663041869066749730025370705253261451722595574825909044 34743256388662636089294615411424475808328353443007431056186153291193660236*x ^53 - 3298236730725312112107997188999732021783635308764336412988146411506139 7104102160872908196077077455976298299221998872649597890835291998156291479044 1156752915907868097785637632834657415730880385603530195196698224915641474164 13441042710366926553820042101416886262527990*x^52 - 101449365782699643760207 3313704763252338242187697491537141888115893684195480412346735267432884547401 4326674844047109008343871306484926351769633249049418818884494773111342516465 1364847880469035878140408781793697844423605606532175548895998431434178111893 10391299541374*x^51 + 997010027853800903810835659831173696396465410573075578 3905356009776229418935908969084901777161285772610734056245264176199983282362 9243150822898802087782083582569387718010137408195023053062329504663705594403 79207927321560114457596629472924327212630999737789491694628*x^50 - 400136364 1205954524277253466159627211505461211798229164611000835355077955105452940106 5043117114065854192422518937652264386811681003511656062957851230278085993229 0192913573475644905186402717704749806127538925050731511982133457968662243173 0574757902251581738927743514*x^49 + 9180213565693093847510479570029388499565 5962139940688297118935762169143151779122206282849955988804045093690808202777 1911618936765072016334219087961215540705432215522135777876375064000492729289 146413824719753030999530625757538495495631483556564886408485696916274754*x^4 8 - 501301210215460642688466550524464459820491039666763299722186435065388308 0998476722426260605286629208716991084876566352805637002187528368901275570021 1644840502467709341605696416994819511376212841122712589602930316113642419950 349056502832731819476610421210838732740*x^47 - 54944298141158889585149685718 7336779616988953202758365462768772698687661348560047998087075022182507327394 7519184487938281971887003668567460606612213622645012761958365390879314022191 3390146402903001771434654731924912308476740943900732699364805260630537589779 248726*x^46 + 26686242659774581832060629132908634079744101584587342617793147 5307484074819549903437909197788777407246096377950996274109900334593209284669 9285933458439326397108293597155087876694426014357663784876151672816297841341 0567270026180297395204928647366053260719567023642*x^45 - 7052486107172135206 1948720744051909520509772591994862049253916379923010961566356969081325001527 6292596993146766741009335610467932996827331500592308883886627814990767499859 2394117000761761120597925240350755933951486120638079133147944601048042610283 120648681977182*x^44 + 12094887988138431717848391295686703675228636456392942 8682928139939229340261144090919567211768947492261796729623549396284079133495 0340419054279131563933305486551030416968393033147914495046708454093512499973 890279938140031139050906270219603864516933692949758319412*x^43 - 13249348861 2052453833911384927269989662957662727807923412036942065407705141769113172260 4562201840504522929158651370739513572711063413085138434059101868053588204820 3501768317607444088231087593813985100365809682458092656030031376932623184206 7770517384807361785676*x^42 + 1335101451287203762576138569495941477971504274 6021839256417498499034598980956043459656243655749784623012085862698394648682 7521666667680743107938078657228707393173302010891133955653957891206671708545 21488797288438881522832497235465398261203063264934026405622216*x^41 - 499475 9281308667412284807719782367452360187792248198012964464639579785518460647882 3014472001994317756006942461078978073213429085061547197216262635883812900592 1762751571689421659752686372945957018076639346750248956405331139984740983345 9224825604519148808410998*x^40 + 2123055922106609642987166390747900882690095 8265815080171818541132693855937048009649851884749195950160943998565872859377 2466719457136622623105718221481729397353928547971338648745934933818733937555 9722029289477935787063071140468460122494931142480075599166922066*x^39 - 5735 6058097105987281579532842451121455107789722350655401468909089438850594255611 7398406496524366947519084716044767896958134185399473668974877433779111152344 5537408221196487932870899207582741017935334684933397499648658504512170298450 81211351675478818348250014*x^38 + 101323645478522769412770862955451494838700 8662851023057079588279613730397359405727823936580260643332082414004528447161 9032650746240307864113277781931187876839372237162972094621638339957461376513 5960868446031017264818726765755631590746592742117108410287162304*x^37 - 1158 2691707749694320983466811601420819483438159197492729367460974781919497846083 2310429882055944418973561703899132956324878554694827218593251972032733158957 9073374625050919799091874768764116278381338067763168272226788014070435497357 3342854568112725548119716*x^36 + 8305639013155526915236550603371532656184411 8485479725403465416008780582431421160189594698593377625798613038172701584227 4206678281269713323953843252700015484543752538426082787722637328521354532797 854400197712614233087564302182567125978130820395479367756272*x^35 - 72553146 6299857240224175450027827480387792541339702494044488085609115659954701904593 4063182032757400157986647557124710638076669642745888083114891044280939887931 1080380921785649390927188469314188121124356596001115383235298455028416330896 607528890361908254*x^34 + 19860798394812096491425064118869331882474934679022 5013755600349219086403728983462588925205132120800514991648137327905331386108 2705026046100093497647310070721575578185071569257102022328094661667732591461 4871110127674403701118049341045392289086401193314942*x^33 - 4504073630957286 8996977652497679946908816176921415580423759147328165686549644634042466661073 3511461352309328969240076472657648713663010059789108519959246932375899814162 7806075361906437084097330297847347043691634727928126429902493759079959944869 550465866*x^32 + 69070920659658480551690757737221770374761684950145185121047 2484618737300993281417864275556465857656908421568917719365815679023157411215 6057258090256560697376971566576951036121500346489928053597706896717897892051 06698965797835172312757476105925970954316*x^31 - 950505499088700807538705994 4852731534709761992249213459182019380991510107647264892021396558868144681611 0662751219780692605034863184825513108322135455467480199290708985357993844600 052787576017748490330946803622885911462082828385374632295839177766961104*x^3 0 + 146871001034451764467214379577713350818960453105454365246878113141243396 2615951663537883759634270986980824512323040156750516514483187596408739659469 9598984366473798855873087478723052705650039925818705324797901096311128210246 360020474709693712139627212*x^29 - 21967157682673292571077015450821069674087 1544590587052875727692154504672915643984006806321437086319058849365052767208 2180148377519601579902888730828514202452285184145954435822512134773040530752 315307032862652438081839581459737476241460047819927741316*x^28 + 25868119256 5279242165718547565481040416951897690007278140339301372610232089805802058986 0750808024571604981879223368087235334407689838584104951724530561739372122119 8951117323168039502216475583876368959953874029365022369810172602125325497095 6445408416*x^27 - 2428059268010321918244811964086129262156487932219116205050 4070649327791508268466838408282079070232219613570494028527410574628542390142 2207371899314254390315983442044698383945383757774385604939274532392556556337 58840387565176697754574091764000708652*x^26 + 228044964584692160131546765047 2366230486843363280069375103638842382972106217168205477299195570432297721283 4433913421328769323459813505283451769698919188569838637736110033080505201432 29246149018773191614239310593408598408683107352357568527200654044*x^25 - 240 6358660663137122033270184955011680904324977408022614274765749948013776439046 4906763369553397919412224096925386397722165397929814334230617641557808733911 0574280678118160005286224756835902809740658092872319513670690482675603106255 535345368222072*x^24 + 17662623687632442866313848276740533318473562530568602 6085380981148726634500393960831149553262597329458902932994016704916196167706 1802977969263820447192793617562366039417910781021352992596284460784056551089 2584667589514772071439777359014056460388*x^23 - 1017233748361584303945573233 3032677102808866261456706104325822118295706056417248083910297875201722536975 2472365095568346621934137039403008509886158851525905826470428214804919613199 4864749556380390451533567703437432891192535285335888731490497100*x^22 + 6962 4456632649901142038343508876142609309013148113719161965752973745996685396900 6242981394546059022035086880100336674301708003625923297490632324135942177919 6475754925837957964115788320422751182797666627301620661963625816748809270833 0371586416*x^21 - 5935499297476735425457730389595586123363077244239039067258 8757027689826646450579634779345685940054648366379750425264531723684895242726 1296842788479967443307602969542957303586075752713784702233094467073009888400 4709831827016377193151480549079*x^20 - 9924231276887632055264945002835855931 6153619298064184888082607712523327637455849379369518935749807342918090562216 3515240369483362753072379694694969114717331800146736581921176222284191504989 22256734920743781356158658426818610320388361445943*x^19 - 223034910041976985 5872625998444601823522405237422212480311276936526222907234872314934718146257 7999956125097315186127418244514895084164378747477418159356551630505131305135 965903638935951781824035858082445936492127698502477328282539866049529*x^18 - 236643075076678358536974434180237346813030211220576398492261042505158468477 4245106684856714329733460194522211899691204030539339797067532556065266564996 8995125799175143049170891303055998502994776437035748429866958228412329271509 6914727786*x^17 + 2542147127057127485965235153724151047113766830500853009593 4057432271073053439213859505464662101818485064985498169276132525055092922810 7659183430955698520972071635491614118402866501132808889569521209673251362824 76709756655755991836417802*x^16 + 183111149787713493280210397619912322103096 5247871179773154030195420556994309371058325110985700072545919333159157805938 6224014037352998052003315867311050614119923950889255536852768279112155091364 24174340648729576596630358137790527045198*x^15 - 449821041069912943789836264 5632599818971731559621159648780555694409049475593695526598586098851324811318 2519341945707916157927951713037252573987087918917682037480599453640794209186 225479459166338434922942612532823032751347335799704869*x^14 - 22982911151946 0414712287398340054262339910173840391365052883789755652220150460120847132485 5387525455121237089427182900348837425717452397567606502432587339063493335218 99975599619910693111772391894198334123224235975702158966025975889*x^13 + 425 1167449102860417605682557582269062328643891986101063790164447568501066388281 7083671619051397999677516644732430950231634364346445730340715448369087696718 20523719962939869299988336933823914482320626610429276999595557594057384713*x ^12 - 2634769415254884935578685134629261396873246071233388299830258283684407 2876185708249044979665212650744995875688959242932243838420517823860588878429 2448997291893491640954677331782979368685632076417137547307030222199889038379 76940*x^11 - 178196131047104477494733878949091986680056821951080835036094383 8004052330411696017910506157765585633940095861000688753523141138483928490467 4511256960034750139170510478764583267207761340591670181326537548133703111264 9106926204*x^10 + 1825000405670995013845885918902187142186986666482440933839 6462521386957836588377301330171147216240982523247505481312286617417272521511 8638399348219471080155689525455946137646839420547370091703312293991788729921 1491191185252*x^9 - 65201626996640512322761674559318066561117950070675294766 3169824762769899024352909587195016688965354038529484926750838814982572946010 1979637110489360349176312329919783316622660007379629280095704481299477431710 45016069129*x^8 - 1437891149083999662420144342263678250208894256538560561654 8933951961391248431401653150798776891480895285823868174684751112400557598552 7985918610201118598268431458892734242196304467884366814923258790382419891488 25558929*x^7 - 1428280930363758251384969101052572662110879466805595758704451 0527911033933582902662199662263051097627055254401259144549052189981714948608 3243967370749726951525986876271444939969618263711803265644040382245363794511 71*x^6 - 1170826372197459055177820600881979710066693446685651498813175990981 0745762172031150515086932467894419392120220600061432329279936873889655682224 7191725072125442393957901078704198243471395495180025340969870794174*x^5 - 11 8223168675776843350634299306552668061864957826207103017499838634433318705119 3832689526795798631026606743575718322278065328528551578753575871762638217620 241416850427234233281589721441720700844787815627946*x^4 - 953048457007008296 1795451881320794184817199918350969024576327248906812630041977334151670173523 3419849726478663631547211301749427543946011643243124123502481796513891248511 161398944690550172434214114*x^3 - 254706791524256177472181318251041912950779 4390935955929617768730635253624759862293118182940797954335902313821207678848 027543595348285081414397619295455292216447729433614628265514361363667915*x^2 + 7114590568532928191072122754665584122789751912529693393245247725975835948 7615527828928204048113*x - 1 x^240 + (-15*y - 36)*x^239 + (499*y + 430)*x^238 + (-6344*y - 983)*x^237 + ( 35389*y - 20411)*x^236 + (-40904*y + 178707)*x^235 + (-424808*y - 438197)*x^ 234 + (1415485*y - 635208)*x^233 + (1438139*y + 2974605)*x^232 + (-5864817*y + 6566480)*x^231 + (-25462020*y - 12961894)*x^230 + (19238389*y - 79956654) *x^229 + (247313433*y - 30224897)*x^228 + (294927621*y + 801098945)*x^227 + (-2353679384*y + 1069498319)*x^226 + (-3266832488*y - 5793469739)*x^225 + (1 2761071756*y - 10152009124)*x^224 + (28891772141*y + 27706877778)*x^223 + (- 56780498004*y + 70327470888)*x^222 + (-156989267296*y - 100643285180)*x^221 + (163182970660*y - 341901790078)*x^220 + (692925090103*y + 282970748175)*x^ 219 + (-520851483678*y + 1249500770581)*x^218 + (-2100987167651*y - 97780636 3155)*x^217 + (2144907137575*y - 3501192827999)*x^216 + (5741131351957*y + 5 368774573391)*x^215 + (-12949633488740*y + 9667592872104)*x^214 + (-18978818 705192*y - 28988343801763)*x^213 + (61143701295650*y - 42854297857883)*x^212 + (99522339968066*y + 118416217970085)*x^211 + (-203990291010201*y + 226088 796680855)*x^210 + (-487486417978576*y - 306059642167156)*x^209 + (371437987 605861*y - 969565907346414)*x^208 + (1761877237395113*y + 250996844693464)*x ^207 + (347587448455796*y + 2909203449118066)*x^206 + (-4262623171412271*y + 1900082482875272)*x^205 + (-5112561845313059*y - 5258998337190094)*x^204 + (4703077156935772*y - 10817923562329066)*x^203 + (19596724151621886*y + 4579 71706716061)*x^202 + (10779811934500297*y + 31310302362591686)*x^201 + (-444 71188376651271*y + 33091705261026148)*x^200 + (-70367728073948453*y - 553681 43890230595)*x^199 + (58047935399898944*y - 125056052810735004)*x^198 + (196 220179915190037*y + 46078797156864550)*x^197 + (-15612945533449050*y + 27845 2806220656846)*x^196 + (-364966710997667886*y + 30164046307811567)*x^195 + ( -76920393658091100*y - 455669527002677921)*x^194 + (569724473209147360*y - 1 04273935104641941)*x^193 + (107554480539021407*y + 761016430421970356)*x^192 + (-1120756441763956820*y + 138805435659787599)*x^191 + (-36744368496876235 9*y - 1741313178847717412)*x^190 + (2626931562224608194*y - 1142827140366519 672)*x^189 + (3001549496003468616*y + 3542726921147289593)*x^188 + (-3816304 655625513057*y + 6563685064488706687)*x^187 + (-12280102244383760786*y - 216 9956083918876046)*x^186 + (-3280308295039992672*y - 20013773166146345265)*x^ 185 + (28534969871679714183*y - 14758677431499660732)*x^184 + (3420538527727 7312731*y + 35129207175233160758)*x^183 + (-35562575528916824663*y + 6232129 2808100809456)*x^182 + (-97526968113689340266*y - 24577168539715006795)*x^18 1 + (-2924482708853224503*y - 135200656059538396115)*x^180 + (16755988046047 3073606*y - 50231770182088582728)*x^179 + (117217186558944665294*y + 1844313 16627662099968)*x^178 + (-175018700423712057769*y + 199325075624692888658)*x ^177 + (-287672838056258651793*y - 130006789216819808906)*x^176 + (433136887 58928043819*y - 370488386653834436323)*x^175 + (435685264104825475131*y - 87 230951613648934063)*x^174 + (260789110179489506909*y + 473346146286012258862 )*x^173 + (-477453708065915165092*y + 475828532275903297714)*x^172 + (-73312 5023480253537968*y - 445824632107486741239)*x^171 + (377925441616168009977*y - 1037951764481934863694)*x^170 + (1401192440853964064557*y + 2712041812199 21501426)*x^169 + (-116817470274758714683*y + 1837817520966021102844)*x^168 + (-2362860273074857968126*y + 103875680474127044027)*x^167 + (-421763202246 558569481*y - 2985437596461812106201)*x^166 + (3701454711020661872373*y - 87 8419497758685431399)*x^165 + (1521006793930665203185*y + 4486769840934475059 679)*x^164 + (-5292413186031800428648*y + 2393646591871321675898)*x^163 + (- 3527560907713404811933*y - 6046342849737077241029)*x^162 + (6659475347960239 461641*y - 4934471883467342725819)*x^161 + (6606218484397706362957*y + 70346 33694928572084799)*x^160 + (-7071251229918632950519*y + 85221454139378375409 88)*x^159 + (-10654172673396879304988*y - 6660938661086516468010)*x^158 + (5 677741559220425296264*y - 12963319200223537566424)*x^157 + (1537868439480061 5926642*y + 3975042669473795569897)*x^156 + (-1409491575820818236069*y + 177 68498236629148702410)*x^155 + (-19928654122136236656860*y + 2108177954625221 499359)*x^154 + (-6549200784773657451762*y - 21617243705895522615660)*x^153 + (22645379524677683996954*y - 11738628703873244299229)*x^152 + (17408053637 884918322314*y + 22982504260819896781381)*x^151 + (-22809630522578701355929* y + 23340226072231874490562)*x^150 + (-29550558164952915082604*y - 224392369 77615542871417)*x^149 + (22094525765620020809639*y - 36386527353264595233550 )*x^148 + (44442209345887020103552*y + 21630493829993114594971)*x^147 + (-20 362621509381561401708*y + 54254830555411448139989)*x^146 + (-659133869795653 69752671*y - 17161940478911028975987)*x^145 + (10842803083053018739937*y - 7 8798826823995559998884)*x^144 + (91671114659094334230114*y + 699010605156960 463896)*x^143 + (13121977610624125288643*y + 103143317388027280663819)*x^142 + (-112336281183122778011108*y + 29666952173920616332098)*x^141 + (-4771339 6391497944676658*y - 119352040791078382516354)*x^140 + (12522214489937288097 8343*y - 66535424263344578690303)*x^139 + (86443391588395703449231*y + 13128 8792905554584140170)*x^138 + (-138308631379146285689943*y + 1087117764446364 01209940)*x^137 + (-134836856528001466894586*y - 145826834678543169365085)*x ^136 + (152261003156819774060466*y - 165525545074570372890946)*x^135 + (2000 19883617103704090631*y + 155735524429003454571137)*x^134 + (-155214006426713 875482591*y + 236255888142978579163439)*x^133 + (-271843213937284128310312*y - 151199785544397594300869)*x^132 + (145501652264843306972923*y - 305326875 506321100258855)*x^131 + (336932852565943631529246*y + 140097781638111061499 104)*x^130 + (-135773050794564515416176*y + 368242715265481945864410)*x^129 + (-400908655930869378612741*y - 131401561676926670933942)*x^128 + (12442649 3872813948801626*y - 435145712814328666799539)*x^127 + (46899879143136708390 7400*y + 112351662733835870233203)*x^126 + (-94381628626117531492779*y + 498 937937395927788353831)*x^125 + (-521540559152841029573809*y - 72188367562634 255595303)*x^124 + (49231480359271694594387*y - 535280543629519838165745)*x^ 123 + (541321200409785903521904*y + 28961946371400127296768)*x^122 + (-12936 229773088822436824*y + 542775176498979507958864)*x^121 - 5428178716207228568 54615*y*x^120 + (-12936229773088822436824*y - 542775176498979507958864)*x^11 9 + (541321200409785903521904*y - 28961946371400127296768)*x^118 + (49231480 359271694594387*y + 535280543629519838165745)*x^117 + (-52154055915284102957 3809*y + 72188367562634255595303)*x^116 + (-94381628626117531492779*y - 4989 37937395927788353831)*x^115 + (468998791431367083907400*y - 1123516627338358 70233203)*x^114 + (124426493872813948801626*y + 435145712814328666799539)*x^ 113 + (-400908655930869378612741*y + 131401561676926670933942)*x^112 + (-135 773050794564515416176*y - 368242715265481945864410)*x^111 + (336932852565943 631529246*y - 140097781638111061499104)*x^110 + (145501652264843306972923*y + 305326875506321100258855)*x^109 + (-271843213937284128310312*y + 151199785 544397594300869)*x^108 + (-155214006426713875482591*y - 23625588814297857916 3439)*x^107 + (200019883617103704090631*y - 155735524429003454571137)*x^106 + (152261003156819774060466*y + 165525545074570372890946)*x^105 + (-13483685 6528001466894586*y + 145826834678543169365085)*x^104 + (-1383086313791462856 89943*y - 108711776444636401209940)*x^103 + (86443391588395703449231*y - 131 288792905554584140170)*x^102 + (125222144899372880978343*y + 665354242633445 78690303)*x^101 + (-47713396391497944676658*y + 119352040791078382516354)*x^ 100 + (-112336281183122778011108*y - 29666952173920616332098)*x^99 + (131219 77610624125288643*y - 103143317388027280663819)*x^98 + (91671114659094334230 114*y - 699010605156960463896)*x^97 + (10842803083053018739937*y + 787988268 23995559998884)*x^96 + (-65913386979565369752671*y + 17161940478911028975987 )*x^95 + (-20362621509381561401708*y - 54254830555411448139989)*x^94 + (4444 2209345887020103552*y - 21630493829993114594971)*x^93 + (2209452576562002080 9639*y + 36386527353264595233550)*x^92 + (-29550558164952915082604*y + 22439 236977615542871417)*x^91 + (-22809630522578701355929*y - 2334022607223187449 0562)*x^90 + (17408053637884918322314*y - 22982504260819896781381)*x^89 + (2 2645379524677683996954*y + 11738628703873244299229)*x^88 + (-654920078477365 7451762*y + 21617243705895522615660)*x^87 + (-19928654122136236656860*y - 21 08177954625221499359)*x^86 + (-1409491575820818236069*y - 177684982366291487 02410)*x^85 + (15378684394800615926642*y - 3975042669473795569897)*x^84 + (5 677741559220425296264*y + 12963319200223537566424)*x^83 + (-1065417267339687 9304988*y + 6660938661086516468010)*x^82 + (-7071251229918632950519*y - 8522 145413937837540988)*x^81 + (6606218484397706362957*y - 703463369492857208479 9)*x^80 + (6659475347960239461641*y + 4934471883467342725819)*x^79 + (-35275 60907713404811933*y + 6046342849737077241029)*x^78 + (-529241318603180042864 8*y - 2393646591871321675898)*x^77 + (1521006793930665203185*y - 44867698409 34475059679)*x^76 + (3701454711020661872373*y + 878419497758685431399)*x^75 + (-421763202246558569481*y + 2985437596461812106201)*x^74 + (-2362860273074 857968126*y - 103875680474127044027)*x^73 + (-116817470274758714683*y - 1837 817520966021102844)*x^72 + (1401192440853964064557*y - 271204181219921501426 )*x^71 + (377925441616168009977*y + 1037951764481934863694)*x^70 + (-7331250 23480253537968*y + 445824632107486741239)*x^69 + (-477453708065915165092*y - 475828532275903297714)*x^68 + (260789110179489506909*y - 473346146286012258 862)*x^67 + (435685264104825475131*y + 87230951613648934063)*x^66 + (4331368 8758928043819*y + 370488386653834436323)*x^65 + (-287672838056258651793*y + 130006789216819808906)*x^64 + (-175018700423712057769*y - 199325075624692888 658)*x^63 + (117217186558944665294*y - 184431316627662099968)*x^62 + (167559 880460473073606*y + 50231770182088582728)*x^61 + (-2924482708853224503*y + 1 35200656059538396115)*x^60 + (-97526968113689340266*y + 24577168539715006795 )*x^59 + (-35562575528916824663*y - 62321292808100809456)*x^58 + (3420538527 7277312731*y - 35129207175233160758)*x^57 + (28534969871679714183*y + 147586 77431499660732)*x^56 + (-3280308295039992672*y + 20013773166146345265)*x^55 + (-12280102244383760786*y + 2169956083918876046)*x^54 + (-38163046556255130 57*y - 6563685064488706687)*x^53 + (3001549496003468616*y - 3542726921147289 593)*x^52 + (2626931562224608194*y + 1142827140366519672)*x^51 + (-367443684 968762359*y + 1741313178847717412)*x^50 + (-1120756441763956820*y - 13880543 5659787599)*x^49 + (107554480539021407*y - 761016430421970356)*x^48 + (56972 4473209147360*y + 104273935104641941)*x^47 + (-76920393658091100*y + 4556695 27002677921)*x^46 + (-364966710997667886*y - 30164046307811567)*x^45 + (-156 12945533449050*y - 278452806220656846)*x^44 + (196220179915190037*y - 460787 97156864550)*x^43 + (58047935399898944*y + 125056052810735004)*x^42 + (-7036 7728073948453*y + 55368143890230595)*x^41 + (-44471188376651271*y - 33091705 261026148)*x^40 + (10779811934500297*y - 31310302362591686)*x^39 + (19596724 151621886*y - 457971706716061)*x^38 + (4703077156935772*y + 1081792356232906 6)*x^37 + (-5112561845313059*y + 5258998337190094)*x^36 + (-4262623171412271 *y - 1900082482875272)*x^35 + (347587448455796*y - 2909203449118066)*x^34 + (1761877237395113*y - 250996844693464)*x^33 + (371437987605861*y + 969565907 346414)*x^32 + (-487486417978576*y + 306059642167156)*x^31 + (-2039902910102 01*y - 226088796680855)*x^30 + (99522339968066*y - 118416217970085)*x^29 + ( 61143701295650*y + 42854297857883)*x^28 + (-18978818705192*y + 2898834380176 3)*x^27 + (-12949633488740*y - 9667592872104)*x^26 + (5741131351957*y - 5368 774573391)*x^25 + (2144907137575*y + 3501192827999)*x^24 + (-2100987167651*y + 977806363155)*x^23 + (-520851483678*y - 1249500770581)*x^22 + (6929250901 03*y - 282970748175)*x^21 + (163182970660*y + 341901790078)*x^20 + (-1569892 67296*y + 100643285180)*x^19 + (-56780498004*y - 70327470888)*x^18 + (288917 72141*y - 27706877778)*x^17 + (12761071756*y + 10152009124)*x^16 + (-3266832 488*y + 5793469739)*x^15 + (-2353679384*y - 1069498319)*x^14 + (294927621*y - 801098945)*x^13 + (247313433*y + 30224897)*x^12 + (19238389*y + 79956654)* x^11 + (-25462020*y + 12961894)*x^10 + (-5864817*y - 6566480)*x^9 + (1438139 *y - 2974605)*x^8 + (1415485*y + 635208)*x^7 + (-424808*y + 438197)*x^6 + (- 40904*y - 178707)*x^5 + (35389*y + 20411)*x^4 + (-6344*y + 983)*x^3 + (499*y - 430)*x^2 + (-15*y + 36)*x - 1 x^3 + (-y - 1)*x^2 + (y - 2)*x + 1 x^6 + (-y - 1)*x^5 + (y - 2)*x^4 + 5*x^3 + (-y - 1)*x^2 + (y - 2)*x + 1 x^15 + (-13*y - 28)*x^14 + (-35*y + 71)*x^13 + (-96*y + 193)*x^12 + (-5*y - 196)*x^11 + (-239*y - 365)*x^10 + (120*y + 1489)*x^9 + (-261*y - 2084)*x^8 + (-261*y + 2345)*x^7 + (120*y - 1609)*x^6 + (-239*y + 604)*x^5 + (-5*y + 201 )*x^4 + (-96*y - 97)*x^3 + (-35*y - 36)*x^2 + (-13*y + 41)*x - 1 x^64 - 2869316*y*x^63 - 14321320456*x^62 + 157634598028*y*x^61 - 20284120752 9344*x^60 - 187341502817748*y*x^59 + 42513677421330536*x^58 + 89659277585427 48*y*x^57 - 581758105735037800*x^56 - 22856296353162116*y*x^55 - 17452945591 56518504*x^54 - 264489521649865972*y*x^53 + 3806496834205999360*x^52 - 74814 8105793479444*y*x^51 + 34464709754552397448*x^50 - 807085220707689700*y*x^49 + 112558678351798157916*x^48 + 885683152130937644*y*x^47 + 3063853398816684 17048*x^46 + 13203419547826420924*y*x^45 + 419863456051485069824*x^44 + 3434 3465258453402972*y*x^43 + 465608689069031605064*x^42 + 80309592889200941068* y*x^41 - 360175722030581287640*x^40 + 110486596140091600940*y*x^39 - 1490512 424563931678536*x^38 + 143957811491089032572*y*x^37 - 3739364774219046032256 *x^36 + 100323919847689168220*y*x^35 - 4985975135633301110936*x^34 + 5481611 3881156185292*y*x^33 - 6135008383051601995834*x^32 - 54816113881156185292*y* x^31 - 4985975135633301110936*x^30 - 100323919847689168220*y*x^29 - 37393647 74219046032256*x^28 - 143957811491089032572*y*x^27 - 1490512424563931678536* x^26 - 110486596140091600940*y*x^25 - 360175722030581287640*x^24 - 803095928 89200941068*y*x^23 + 465608689069031605064*x^22 - 34343465258453402972*y*x^2 1 + 419863456051485069824*x^20 - 13203419547826420924*y*x^19 + 3063853398816 68417048*x^18 - 885683152130937644*y*x^17 + 112558678351798157916*x^16 + 807 085220707689700*y*x^15 + 34464709754552397448*x^14 + 748148105793479444*y*x^ 13 + 3806496834205999360*x^12 + 264489521649865972*y*x^11 - 1745294559156518 504*x^10 + 22856296353162116*y*x^9 - 581758105735037800*x^8 - 89659277585427 48*y*x^7 + 42513677421330536*x^6 + 187341502817748*y*x^5 - 202841207529344*x ^4 - 157634598028*y*x^3 - 14321320456*x^2 + 2869316*y*x + 1 x^21 + (-13*y - 229)*x^20 + (234*y - 100)*x^19 + (-480*y + 8370)*x^18 + (-17 35*y - 16719)*x^17 + (4913*y - 7834)*x^16 + (-2688*y + 51064)*x^15 + (-3960* y - 34104)*x^14 + (1782*y - 32956)*x^13 + (8448*y + 5262)*x^12 + (-6380*y + 97204)*x^11 + (-6380*y - 90824)*x^10 + (8448*y - 13710)*x^9 + (1782*y + 3117 4)*x^8 + (-3960*y + 38064)*x^7 + (-2688*y - 48376)*x^6 + (4913*y + 2921)*x^5 + (-1735*y + 18454)*x^4 + (-480*y - 7890)*x^3 + (234*y - 134)*x^2 + (-13*y + 242)*x - 1 x^6 - 2*y*x^5 + (-y - 7)*x^4 - 4*x^3 + (y - 8)*x^2 + (2*y - 2)*x + 1 x^240 + (-15*y - 36)*x^239 + (499*y + 430)*x^238 + (-6344*y - 983)*x^237 + ( 35389*y - 20411)*x^236 + (-40904*y + 178707)*x^235 + (-424808*y - 438197)*x^ 234 + (1415485*y - 635208)*x^233 + (1438139*y + 2974605)*x^232 + (-5864817*y + 6566480)*x^231 + (-25462020*y - 12961894)*x^230 + (19238389*y - 79956654) *x^229 + (247313433*y - 30224897)*x^228 + (294927621*y + 801098945)*x^227 + (-2353679384*y + 1069498319)*x^226 + (-3266832488*y - 5793469739)*x^225 + (1 2761071756*y - 10152009124)*x^224 + (28891772141*y + 27706877778)*x^223 + (- 56780498004*y + 70327470888)*x^222 + (-156989267296*y - 100643285180)*x^221 + (163182970660*y - 341901790078)*x^220 + (692925090103*y + 282970748175)*x^ 219 + (-520851483678*y + 1249500770581)*x^218 + (-2100987167651*y - 97780636 3155)*x^217 + (2144907137575*y - 3501192827999)*x^216 + (5741131351957*y + 5 368774573391)*x^215 + (-12949633488740*y + 9667592872104)*x^214 + (-18978818 705192*y - 28988343801763)*x^213 + (61143701295650*y - 42854297857883)*x^212 + (99522339968066*y + 118416217970085)*x^211 + (-203990291010201*y + 226088 796680855)*x^210 + (-487486417978576*y - 306059642167156)*x^209 + (371437987 605861*y - 969565907346414)*x^208 + (1761877237395113*y + 250996844693464)*x ^207 + (347587448455796*y + 2909203449118066)*x^206 + (-4262623171412271*y + 1900082482875272)*x^205 + (-5112561845313059*y - 5258998337190094)*x^204 + (4703077156935772*y - 10817923562329066)*x^203 + (19596724151621886*y + 4579 71706716061)*x^202 + (10779811934500297*y + 31310302362591686)*x^201 + (-444 71188376651271*y + 33091705261026148)*x^200 + (-70367728073948453*y - 553681 43890230595)*x^199 + (58047935399898944*y - 125056052810735004)*x^198 + (196 220179915190037*y + 46078797156864550)*x^197 + (-15612945533449050*y + 27845 2806220656846)*x^196 + (-364966710997667886*y + 30164046307811567)*x^195 + ( -76920393658091100*y - 455669527002677921)*x^194 + (569724473209147360*y - 1 04273935104641941)*x^193 + (107554480539021407*y + 761016430421970356)*x^192 + (-1120756441763956820*y + 138805435659787599)*x^191 + (-36744368496876235 9*y - 1741313178847717412)*x^190 + (2626931562224608194*y - 1142827140366519 672)*x^189 + (3001549496003468616*y + 3542726921147289593)*x^188 + (-3816304 655625513057*y + 6563685064488706687)*x^187 + (-12280102244383760786*y - 216 9956083918876046)*x^186 + (-3280308295039992672*y - 20013773166146345265)*x^ 185 + (28534969871679714183*y - 14758677431499660732)*x^184 + (3420538527727 7312731*y + 35129207175233160758)*x^183 + (-35562575528916824663*y + 6232129 2808100809456)*x^182 + (-97526968113689340266*y - 24577168539715006795)*x^18 1 + (-2924482708853224503*y - 135200656059538396115)*x^180 + (16755988046047 3073606*y - 50231770182088582728)*x^179 + (117217186558944665294*y + 1844313 16627662099968)*x^178 + (-175018700423712057769*y + 199325075624692888658)*x ^177 + (-287672838056258651793*y - 130006789216819808906)*x^176 + (433136887 58928043819*y - 370488386653834436323)*x^175 + (435685264104825475131*y - 87 230951613648934063)*x^174 + (260789110179489506909*y + 473346146286012258862 )*x^173 + (-477453708065915165092*y + 475828532275903297714)*x^172 + (-73312 5023480253537968*y - 445824632107486741239)*x^171 + (377925441616168009977*y - 1037951764481934863694)*x^170 + (1401192440853964064557*y + 2712041812199 21501426)*x^169 + (-116817470274758714683*y + 1837817520966021102844)*x^168 + (-2362860273074857968126*y + 103875680474127044027)*x^167 + (-421763202246 558569481*y - 2985437596461812106201)*x^166 + (3701454711020661872373*y - 87 8419497758685431399)*x^165 + (1521006793930665203185*y + 4486769840934475059 679)*x^164 + (-5292413186031800428648*y + 2393646591871321675898)*x^163 + (- 3527560907713404811933*y - 6046342849737077241029)*x^162 + (6659475347960239 461641*y - 4934471883467342725819)*x^161 + (6606218484397706362957*y + 70346 33694928572084799)*x^160 + (-7071251229918632950519*y + 85221454139378375409 88)*x^159 + (-10654172673396879304988*y - 6660938661086516468010)*x^158 + (5 677741559220425296264*y - 12963319200223537566424)*x^157 + (1537868439480061 5926642*y + 3975042669473795569897)*x^156 + (-1409491575820818236069*y + 177 68498236629148702410)*x^155 + (-19928654122136236656860*y + 2108177954625221 499359)*x^154 + (-6549200784773657451762*y - 21617243705895522615660)*x^153 + (22645379524677683996954*y - 11738628703873244299229)*x^152 + (17408053637 884918322314*y + 22982504260819896781381)*x^151 + (-22809630522578701355929* y + 23340226072231874490562)*x^150 + (-29550558164952915082604*y - 224392369 77615542871417)*x^149 + (22094525765620020809639*y - 36386527353264595233550 )*x^148 + (44442209345887020103552*y + 21630493829993114594971)*x^147 + (-20 362621509381561401708*y + 54254830555411448139989)*x^146 + (-659133869795653 69752671*y - 17161940478911028975987)*x^145 + (10842803083053018739937*y - 7 8798826823995559998884)*x^144 + (91671114659094334230114*y + 699010605156960 463896)*x^143 + (13121977610624125288643*y + 103143317388027280663819)*x^142 + (-112336281183122778011108*y + 29666952173920616332098)*x^141 + (-4771339 6391497944676658*y - 119352040791078382516354)*x^140 + (12522214489937288097 8343*y - 66535424263344578690303)*x^139 + (86443391588395703449231*y + 13128 8792905554584140170)*x^138 + (-138308631379146285689943*y + 1087117764446364 01209940)*x^137 + (-134836856528001466894586*y - 145826834678543169365085)*x ^136 + (152261003156819774060466*y - 165525545074570372890946)*x^135 + (2000 19883617103704090631*y + 155735524429003454571137)*x^134 + (-155214006426713 875482591*y + 236255888142978579163439)*x^133 + (-271843213937284128310312*y - 151199785544397594300869)*x^132 + (145501652264843306972923*y - 305326875 506321100258855)*x^131 + (336932852565943631529246*y + 140097781638111061499 104)*x^130 + (-135773050794564515416176*y + 368242715265481945864410)*x^129 + (-400908655930869378612741*y - 131401561676926670933942)*x^128 + (12442649 3872813948801626*y - 435145712814328666799539)*x^127 + (46899879143136708390 7400*y + 112351662733835870233203)*x^126 + (-94381628626117531492779*y + 498 937937395927788353831)*x^125 + (-521540559152841029573809*y - 72188367562634 255595303)*x^124 + (49231480359271694594387*y - 535280543629519838165745)*x^ 123 + (541321200409785903521904*y + 28961946371400127296768)*x^122 + (-12936 229773088822436824*y + 542775176498979507958864)*x^121 - 5428178716207228568 54615*y*x^120 + (-12936229773088822436824*y - 542775176498979507958864)*x^11 9 + (541321200409785903521904*y - 28961946371400127296768)*x^118 + (49231480 359271694594387*y + 535280543629519838165745)*x^117 + (-52154055915284102957 3809*y + 72188367562634255595303)*x^116 + (-94381628626117531492779*y - 4989 37937395927788353831)*x^115 + (468998791431367083907400*y - 1123516627338358 70233203)*x^114 + (124426493872813948801626*y + 435145712814328666799539)*x^ 113 + (-400908655930869378612741*y + 131401561676926670933942)*x^112 + (-135 773050794564515416176*y - 368242715265481945864410)*x^111 + (336932852565943 631529246*y - 140097781638111061499104)*x^110 + (145501652264843306972923*y + 305326875506321100258855)*x^109 + (-271843213937284128310312*y + 151199785 544397594300869)*x^108 + (-155214006426713875482591*y - 23625588814297857916 3439)*x^107 + (200019883617103704090631*y - 155735524429003454571137)*x^106 + (152261003156819774060466*y + 165525545074570372890946)*x^105 + (-13483685 6528001466894586*y + 145826834678543169365085)*x^104 + (-1383086313791462856 89943*y - 108711776444636401209940)*x^103 + (86443391588395703449231*y - 131 288792905554584140170)*x^102 + (125222144899372880978343*y + 665354242633445 78690303)*x^101 + (-47713396391497944676658*y + 119352040791078382516354)*x^ 100 + (-112336281183122778011108*y - 29666952173920616332098)*x^99 + (131219 77610624125288643*y - 103143317388027280663819)*x^98 + (91671114659094334230 114*y - 699010605156960463896)*x^97 + (10842803083053018739937*y + 787988268 23995559998884)*x^96 + (-65913386979565369752671*y + 17161940478911028975987 )*x^95 + (-20362621509381561401708*y - 54254830555411448139989)*x^94 + (4444 2209345887020103552*y - 21630493829993114594971)*x^93 + (2209452576562002080 9639*y + 36386527353264595233550)*x^92 + (-29550558164952915082604*y + 22439 236977615542871417)*x^91 + (-22809630522578701355929*y - 2334022607223187449 0562)*x^90 + (17408053637884918322314*y - 22982504260819896781381)*x^89 + (2 2645379524677683996954*y + 11738628703873244299229)*x^88 + (-654920078477365 7451762*y + 21617243705895522615660)*x^87 + (-19928654122136236656860*y - 21 08177954625221499359)*x^86 + (-1409491575820818236069*y - 177684982366291487 02410)*x^85 + (15378684394800615926642*y - 3975042669473795569897)*x^84 + (5 677741559220425296264*y + 12963319200223537566424)*x^83 + (-1065417267339687 9304988*y + 6660938661086516468010)*x^82 + (-7071251229918632950519*y - 8522 145413937837540988)*x^81 + (6606218484397706362957*y - 703463369492857208479 9)*x^80 + (6659475347960239461641*y + 4934471883467342725819)*x^79 + (-35275 60907713404811933*y + 6046342849737077241029)*x^78 + (-529241318603180042864 8*y - 2393646591871321675898)*x^77 + (1521006793930665203185*y - 44867698409 34475059679)*x^76 + (3701454711020661872373*y + 878419497758685431399)*x^75 + (-421763202246558569481*y + 2985437596461812106201)*x^74 + (-2362860273074 857968126*y - 103875680474127044027)*x^73 + (-116817470274758714683*y - 1837 817520966021102844)*x^72 + (1401192440853964064557*y - 271204181219921501426 )*x^71 + (377925441616168009977*y + 1037951764481934863694)*x^70 + (-7331250 23480253537968*y + 445824632107486741239)*x^69 + (-477453708065915165092*y - 475828532275903297714)*x^68 + (260789110179489506909*y - 473346146286012258 862)*x^67 + (435685264104825475131*y + 87230951613648934063)*x^66 + (4331368 8758928043819*y + 370488386653834436323)*x^65 + (-287672838056258651793*y + 130006789216819808906)*x^64 + (-175018700423712057769*y - 199325075624692888 658)*x^63 + (117217186558944665294*y - 184431316627662099968)*x^62 + (167559 880460473073606*y + 50231770182088582728)*x^61 + (-2924482708853224503*y + 1 35200656059538396115)*x^60 + (-97526968113689340266*y + 24577168539715006795 )*x^59 + (-35562575528916824663*y - 62321292808100809456)*x^58 + (3420538527 7277312731*y - 35129207175233160758)*x^57 + (28534969871679714183*y + 147586 77431499660732)*x^56 + (-3280308295039992672*y + 20013773166146345265)*x^55 + (-12280102244383760786*y + 2169956083918876046)*x^54 + (-38163046556255130 57*y - 6563685064488706687)*x^53 + (3001549496003468616*y - 3542726921147289 593)*x^52 + (2626931562224608194*y + 1142827140366519672)*x^51 + (-367443684 968762359*y + 1741313178847717412)*x^50 + (-1120756441763956820*y - 13880543 5659787599)*x^49 + (107554480539021407*y - 761016430421970356)*x^48 + (56972 4473209147360*y + 104273935104641941)*x^47 + (-76920393658091100*y + 4556695 27002677921)*x^46 + (-364966710997667886*y - 30164046307811567)*x^45 + (-156 12945533449050*y - 278452806220656846)*x^44 + (196220179915190037*y - 460787 97156864550)*x^43 + (58047935399898944*y + 125056052810735004)*x^42 + (-7036 7728073948453*y + 55368143890230595)*x^41 + (-44471188376651271*y - 33091705 261026148)*x^40 + (10779811934500297*y - 31310302362591686)*x^39 + (19596724 151621886*y - 457971706716061)*x^38 + (4703077156935772*y + 1081792356232906 6)*x^37 + (-5112561845313059*y + 5258998337190094)*x^36 + (-4262623171412271 *y - 1900082482875272)*x^35 + (347587448455796*y - 2909203449118066)*x^34 + (1761877237395113*y - 250996844693464)*x^33 + (371437987605861*y + 969565907 346414)*x^32 + (-487486417978576*y + 306059642167156)*x^31 + (-2039902910102 01*y - 226088796680855)*x^30 + (99522339968066*y - 118416217970085)*x^29 + ( 61143701295650*y + 42854297857883)*x^28 + (-18978818705192*y + 2898834380176 3)*x^27 + (-12949633488740*y - 9667592872104)*x^26 + (5741131351957*y - 5368 774573391)*x^25 + (2144907137575*y + 3501192827999)*x^24 + (-2100987167651*y + 977806363155)*x^23 + (-520851483678*y - 1249500770581)*x^22 + (6929250901 03*y - 282970748175)*x^21 + (163182970660*y + 341901790078)*x^20 + (-1569892 67296*y + 100643285180)*x^19 + (-56780498004*y - 70327470888)*x^18 + (288917 72141*y - 27706877778)*x^17 + (12761071756*y + 10152009124)*x^16 + (-3266832 488*y + 5793469739)*x^15 + (-2353679384*y - 1069498319)*x^14 + (294927621*y - 801098945)*x^13 + (247313433*y + 30224897)*x^12 + (19238389*y + 79956654)* x^11 + (-25462020*y + 12961894)*x^10 + (-5864817*y - 6566480)*x^9 + (1438139 *y - 2974605)*x^8 + (1415485*y + 635208)*x^7 + (-424808*y + 438197)*x^6 + (- 40904*y - 178707)*x^5 + (35389*y + 20411)*x^4 + (-6344*y + 983)*x^3 + (499*y - 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 Total time spent: 296 pari-2.7.5/src/test/32/rnf0000644000175000017500000006306012520212701013605 0ustar billbill[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [6, 6, 6, 6]] [] [[1, 0, 0, 0, 0, [55466/1129, 839/1129]~, [111031/1129, 1480/1129]~, [179046 2/21451, 22844/21451]~, [3584116/21451, 39304/21451]~; 0, 1, 0, 0, 0, [-6071 0/1129, -512/1129]~, [-121528/1129, -808/1129]~, [4210657/21451, -12522/2145 1]~, [8428762/21451, -39940/21451]~; 0, 0, 1, 0, 0, [184604/1129, 1104/1129] ~, [369536/1129, 1552/1129]~, [-2435574/21451, 1771/21451]~, [-4875461/21451 , 12168/21451]~; 0, 0, 0, 1, 0, [96298/1129, 463/1129]~, [192767/1129, 584/1 129]~, [1767005/21451, 5405/21451]~, [3537145/21451, 4540/21451]~; 0, 0, 0, 0, 1, [-216304/1129, -928/1129]~, [-432992/1129, -1088/1129]~, [-4319640/214 51, -5473/21451]~, [-8646937/21451, 4368/21451]~; 0, 0, 0, 0, 0, [-564/1129, -1/1129]~, -1, [9/21451, -18/21451]~, [18/21451, -36/21451]~; 0, 0, 0, 0, 0 , [1/1129, -2/1129]~, [2/1129, -4/1129]~, [7/21451, -14/21451]~, [14/21451, -28/21451]~; 0, 0, 0, 0, 0, 0, 0, [-10723/21451, -5/21451]~, [-21465/21451, 28/21451]~; 0, 0, 0, 0, 0, 0, 0, [1/21451, -2/21451]~, [2/21451, -4/21451]~] , [1, 1, 1, 1, 1, 1, 1, 1, [1, 0; 0, 1]], [1, 0; 0, 1], 1] [[[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], [1, 0, 0; 0, 1, 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, 0, 0, 0, 0, 0, -1, 0, 1; 0, 0, 0, 1, 0, 0, 0, 0, -1, -1, 1; 0, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1; 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -1; 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, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1/3, 1/3, 1/3], [6487513772307278389925284499624661, 0; 0, 6487513772307278389925284499624661], 6487513772307278389925284499624661] [[Mat(861), [1]], [480, [120, 2, 2], [334, 286, [-860]~]], [1, 0, 0; 0, 2, 0 ; 0, 0, 2]] [0, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, [1, 1/2; 0, 1/2]]], 2] [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8] 0 1 0 0 *** at top-level: rnfdedekind(nf,P,pr2 *** ^-------------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. 1 *** at top-level: rnfdedekind(nf,P) *** ^----------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. *** at top-level: rnfdedekind(nf,P,[pr *** ^-------------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. [[8, 2; 0, 1], [2, 0; 0, 1], [1, 0; 0, 1]] 1 1 1 1 *** rnfisabelian: Warning: non-monic polynomial. Result of the form [nf,c]. 0 *** rnfisabelian: Warning: non-monic polynomial. Result of the form [nf,c]. 1 [x, 1] [(-78/43*y^2 - 14/43*y + 173/43)*x^2 + (60/43*y^2 + 24/43*y - 143/43)*x + (- 23/43*y^2 - 35/43*y + 110/43), 1] [(-2*y^2 - 24/25*y + 139/25)*x^2 + (8/5*y^2 + 21/25*y - 4)*x + (-24/25*y^2 - 27/25*y + 61/25), 1] [x, -1] *** rnfisnorm: Warning: useless flag in rnfisnorm: the extension is Galois. [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, -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] [Mod(-1, y^3 - 21), -2] [Mod(-y + 3, y^3 - 21), 1] 1: [2, 0]~ Mod(2, x^2 + Mod(-y, y^3 - 21)) 2 2 2 2 4 4 2: [1/2, 0]~ Mod(1/2, x^2 + Mod(-y, y^3 - 21)) 1/2 1/2 1/2 1/2 1 1/4 3: [Mod(y^2 + y, y^3 - 21), Mod(1, y^3 - 21)]~ Mod(x + Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) error("incorrect type in rnfeltabstorel (t_POL).") Mod(x^2 + x, x^6 - 21) error("inconsistent variables in nf_to_scalar_or_basis, x != y.") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") 4: [1, 0]~ Mod(1, x^2 + Mod(-y, y^3 - 21)) Mod(1, x^2 + Mod(-y, y^3 - 21)) Mod(1, x^6 - 21) 1 1 2 1 5: [1/2, 0]~ Mod(1/2, x^2 + Mod(-y, y^3 - 21)) Mod(1/2, x^2 + Mod(-y, y^3 - 21)) Mod(1/2, x^6 - 21) 1/2 1/2 1 1/4 6: [Mod(y, y^3 - 21), 0]~ Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(x^2, x^6 - 21) Mod(x^2, x^6 - 21) Mod(y, y^3 - 21) Mod(2*y, y^3 - 21) Mod(y^2, y^3 - 21) 7: error("inconsistent moduli in rnfalgtobasis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 1 Mod(1, x^6 - 21) Mod(1, x^6 - 21) 1 2 1 8: error("inconsistent moduli in rnfalgtobasis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 1/2 Mod(1/2, x^6 - 21) Mod(1/2, x^6 - 21) 1/2 1 1/4 9: error("inconsistent moduli in rnfalgtobasis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") Mod(x, x^2 + Mod(-y, y^3 - 21)) Mod(x, x^6 - 21) Mod(x, x^6 - 21) error("domain error in rnfeltdown: element not in the base field") 0 Mod(-y, y^3 - 21) 10: [Mod(y^2 + 1/2*y, y^3 - 21), Mod(1, y^3 - 21)]~ Mod(x + Mod(1/2*y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(x + Mod(1/2*y, y^3 - 21), x^2 - y) Mod(1/2*x^2 + x, x^6 - 21) error("inconsistent moduli in nf_to_scalar_or_basis: x^2 - y != y^3 - 21") error("domain error in rnfeltdown: element not in the base field") Mod(y, y^3 - 21) Mod(1/4*y^2 - y, y^3 - 21) 11: [Mod(y, y^3 - 21), 0]~ Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(x^2, x^6 - 21) Mod(x^2, x^6 - 21) Mod(y, y^3 - 21) Mod(2*y, y^3 - 21) Mod(y^2, y^3 - 21) 12: error("incorrect priority in rnfalgtobasis: variable z >= y") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfeltabstorel, z != x.") error("inconsistent variables in eltreltoabs, z != y.") error("inconsistent variables in nf_to_scalar_or_basis, z != y.") error("inconsistent variables in rnfeltabstorel, z != x.") error("inconsistent variables in rnfeltabstorel, z != x.") error("inconsistent variables in rnfeltabstorel, z != x.") 13: error("inconsistent moduli in rnfalgtobasis: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfeltabstorel: y^2 + 1 != x^6 - 21") error("inconsistent moduli in rnfeltreltoabs: y^2 + 1 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfeltdown: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfeltabstorel: y^2 + 1 != x^6 - 21") error("inconsistent moduli in rnfeltabstorel: y^2 + 1 != x^6 - 21") 14: error("inconsistent dimensions in rnfalgtobasis.") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 15: [1, 2]~ Mod(2*x + Mod(-2*y^2 + 1, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 16: [1, Mod(y, y^3 - 21)]~ Mod(Mod(y, y^3 - 21)*x + Mod(-20, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 17: error("incorrect type in rnfalgtobasis (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 18: error("incorrect type in rnfalgtobasis (t_POL).") error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltup (t_COL).") error("incorrect type in rnfeltup (t_COL).") error("incorrect type in rnfeltdown (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") 19: [y, 0]~ Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) Mod(x^2, x^6 - 21) error("inconsistent variables in nf_to_scalar_or_basis, x != y.") Mod(y, y^3 - 21) Mod(2*y, y^3 - 21) Mod(y^2, y^3 - 21) 1: x^2 - 4*x + 4 2: x^2 - x + 1/4 3: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2 - y, y^3 - 21) 4: x^2 - 2*x + 1 5: x^2 - x + 1/4 6: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) 7: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 8: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 9: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 10: x^2 + Mod(-y, y^3 - 21)*x + Mod(1/4*y^2 - y, y^3 - 21) 11: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) 12: error("incorrect priority in rnfcharpoly: variable z >= y") 13: error("inconsistent moduli in rnfcharpoly: y^2 + 1 != y^3 - 21") 14: error("incorrect type in rnfcharpoly (t_COL).") 15: error("incorrect type in rnfcharpoly (t_COL).") 16: error("incorrect type in rnfcharpoly (t_COL).") 17: error("incorrect type in rnfcharpoly (t_COL).") 18: error("incorrect type in rnfcharpoly (t_POL).") 19: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) 1: [2, 0]~ Mod(2, x^2 + 1) 2 2 2 2 4 4 2: [1/2, 0]~ Mod(1/2, x^2 + 1) 1/2 1/2 1/2 1/2 1 1/4 3: [-1, 1]~ Mod(x - 1, x^2 + 1) error("incorrect type in rnfeltabstorel (t_POL).") Mod(x - 2, x^2 - 2*x + 2) error("inconsistent variables in nf_to_scalar_or_basis, x != y.") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") error("incorrect type in rnfeltabstorel (t_POL).") 4: [1/2, 0]~ Mod(1/2, x^2 + 1) Mod(1/2, x^2 + 1) Mod(1/2, x^2 - 2*x + 2) 1/2 1/2 1 1/4 5: [Mod(y, y + 1), 0]~ Mod(Mod(-1, y + 1), x^2 + 1) Mod(-1, x^2 + 1) -1 -1 -1 -2 1 6: [1, 1/2]~ Mod(1/2*x + 1, x^2 + 1) Mod(1/2*x + 1, x^2 + 1) Mod(1/2*x + 1/2, x^2 - 2*x + 2) error("inconsistent moduli in nf_to_scalar_or_basis: x^2 + 1 != y + 1") error("domain error in rnfeltdown: element not in the base field") 2 5/4 7: [0, 1]~ Mod(x, x^2 + 1) Mod(x, x^2 + 1) Mod(x - 1, x^2 - 2*x + 2) error("inconsistent moduli in nf_to_scalar_or_basis: x^2 + 1 != y + 1") error("domain error in rnfeltdown: element not in the base field") 0 1 8: error("inconsistent moduli in rnfalgtobasis: x^2 - 2*x + 2 != y + 1") error("inconsistent moduli in rnfbasistoalg: x^2 - 2*x + 2 != y + 1") Mod(x + 1, x^2 + 1) Mod(x, x^2 - 2*x + 2) Mod(x, x^2 - 2*x + 2) error("domain error in rnfeltdown: element not in the base field") 2 2 9: error("inconsistent moduli in rnfalgtobasis: x^2 - y != y + 1") error("inconsistent moduli in rnfbasistoalg: x^2 - y != y + 1") error("inconsistent moduli in rnfeltabstorel: x^2 - y != x^2 - 2*x + 2") error("inconsistent moduli in rnfeltreltoabs: x^2 - y != y + 1") error("inconsistent moduli in nf_to_scalar_or_basis: x^2 - y != y + 1") error("inconsistent moduli in rnfeltdown: x^2 - y != y + 1") error("inconsistent moduli in rnfeltabstorel: x^2 - y != x^2 - 2*x + 2") error("inconsistent moduli in rnfeltabstorel: x^2 - y != x^2 - 2*x + 2") 10: [0, 1]~ Mod(x, x^2 + 1) Mod(x + 1, x^2 + 1) Mod(x - 1, x^2 - 2*x + 2) error("inconsistent variables in nf_to_scalar_or_basis, x != y.") error("domain error in rnfeltdown: element not in the base field") 2 2 11: error("inconsistent dimensions in rnfalgtobasis.") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") 1 error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 12: [1, 2]~ Mod(2*x + 1, x^2 + 1) error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 13: error("inconsistent dimensions in rnfalgtobasis.") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltreltoabs (t_COL).") Mod(y, x^2 - 2*x + 2) error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") error("incorrect type in rnfeltabstorel (t_COL).") 1: x^2 - 4*x + 4 2: x^2 - x + 1/4 3: x^2 + 2*x + 2 4: x^2 - x + 1/4 5: x^2 + 2*x + 1 6: x^2 - 2*x + 5/4 7: x^2 + 1 8: error("inconsistent moduli in rnfcharpoly: x^2 - 2*x + 2 != y + 1") 9: error("inconsistent moduli in rnfcharpoly: x^2 - y != y + 1") 10: x^2 + 1 11: error("incorrect type in rnfcharpoly (t_COL).") 12: error("incorrect type in rnfcharpoly (t_COL).") 13: error("incorrect type in rnfcharpoly (t_COL).") Mod(1, x^2 - 2) 0 [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] 1 [18416, x^2 + 6979, x^4 + 3879, -9208*x^4 + 9208*x, -6979/2*x^4 + 1/2*x^3 + 6979/2*x - 21/2, 1/2*x^5 - 3879/2*x^4 - 21/2*x^2 + 3879/2*x] 1 [280970 12259 35869] [ 0 1 0] [ 0 0 1] [280970, x^2 + 12259, x^4 + 35869, -140485*x^4 + 140485*x, -12259/2*x^4 + 1/ 2*x^3 + 12259/2*x - 21/2, 1/2*x^5 - 35869/2*x^4 - 21/2*x^2 + 35869/2*x] 1: [[1, 0; 0, 1], [2, 1]] [2, 2*x^2, 2*x^4, -x^4 + x, x^3 - 21, x^5 - 21*x^2] error("incorrect type in rnfidealabstorel (t_INT).") 2 [2, 2*x^2, 2*x^4, -x^4 + x, x^3 - 21, x^5 - 21*x^2] [4, 0, 0; 0, 4, 0; 0, 0, 4] 64 [2, 0] 2: [[1, 0; 0, 1], [1/2, 1/4]] [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] error("incorrect type in rnfidealabstorel (t_FRAC).") 1/2 [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] [1/4, 0, 0; 0, 1/4, 0; 0, 0, 1/4] 1/64 [1/2, 0] 3: [[1, 42; 0, 1], [[210, 189, 189; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [210, x^2 + 189, x^4 + 189, -x^4 + x + 42, -1/2*x^4 + 1/2*x^3 + 21*x^2 + 1/2 *x + 21/2, 1/2*x^5 + 41/2*x^4 - 21/2*x^2 + 1/2*x + 21] error("incorrect type in rnfidealabstorel (t_POL).") [210, 189, 189; 0, 1, 0; 0, 0, 1] error("inconsistent variables in nf_to_scalar_or_basis, x != y.") [420, 399, 399; 0, 1, 0; 0, 0, 1] 420 [210, Mod(x + Mod(-105*y - 84, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 4: [[1, 0; 0, 1], [1, 1/2]] [1, x^2, x^4, -1/2*x^4 + 1/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") 1 [1, x^2, x^4, -1/2*x^4 + 1/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [1, 0, 0; 0, 1, 0; 0, 0, 1] 1 [1, 0] 5: [[1, 0; 0, 1], [1/2, 1/4]] [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] error("incorrect type in rnfidealabstorel (t_POLMOD).") 1/2 [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] [1/4, 0, 0; 0, 1/4, 0; 0, 0, 1/4] 1/64 [1/2, 0] 6: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") [21, 0, 0; 0, 1, 0; 0, 0, 1] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 7: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 8: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 9: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 10: [[1, -756; 0, 1], [[903/2, 84, 336; 0, 1/2, 0; 0, 0, 1/2], 1/4]] [903/2, 1/2*x^2 + 84, 1/2*x^4 + 336, -1/4*x^4 + 1/4*x - 189, 1/4*x^3 - 189*x ^2 - 21/4, 1/4*x^5 - 189*x^4 - 21/4*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") [903/2, 84, 336; 0, 1/2, 0; 0, 0, 1/2] error("inconsistent moduli in nf_to_scalar_or_basis: x^2 - y != y^3 - 21") [903/4, 42, 168; 0, 1/4, 0; 0, 0, 1/4] 903/64 [903/2, Mod(1/2*x - 42, x^2 + Mod(-y, y^3 - 21))] 11: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POL).") [21, 0, 0; 0, 1, 0; 0, 0, 1] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 12: error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") error("incorrect type in rnfidealabstorel (t_POL).") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in nf_to_scalar_or_basis, z != y.") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") 13: error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") 14: error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in rnfidealabstorel (t_COL).") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") 15: [[1, -5371968; 0, 1], [[10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1], 1/2]] [10743937, x^2 + 8099895, x^4 + 3524829, -1/2*x^4 + 1/2*x - 2685984, 1/2*x^3 - 2685984*x^2 - 21/2, 1/2*x^5 - 2685984*x^4 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_COL).") [10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1] error("incorrect type in nf_to_scalar_or_basis (t_COL).") [10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1] 10743937 [10743937, Mod(x - 1847139, x^2 + Mod(-y, y^3 - 21))] 16: [[1, [0, 0, -18]~; 0, 1], [379, 1/2]] [379, 379*x^2, 379*x^4, -19/2*x^4 + 1/2*x, 1/2*x^3 - 399/2, 1/2*x^5 - 399/2* x^2] error("incorrect type in rnfidealabstorel (t_COL).") 379 error("incorrect type in nf_to_scalar_or_basis (t_COL).") [379, 0, 0; 0, 379, 0; 0, 0, 379] 54439939 [379, Mod(Mod(1/2*y, y^3 - 21)*x + 359/2, x^2 + Mod(-y, y^3 - 21))] 17: error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in rnfidealabstorel (t_COL).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") 18: error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in rnfidealabstorel (t_POL).") error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in idealhnf [integer vector] (t_COL).") error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in rnfbasistoalg (t_POL).") error("incorrect type in rnfbasistoalg (t_POL).") 19: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POL).") [21, 0, 0; 0, 1, 0; 0, 0, 1] error("inconsistent variables in nf_to_scalar_or_basis, x != y.") [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 20: error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealabstorel (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") [] error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") 21: [[;], []] [] [[;], []] [;] error("incorrect type in idealtyp (t_VEC).") [;] 0 [0, 0] 22: [[;], []] [] error("incorrect type in rnfidealabstorel (t_INT).") [;] [] [;] 0 [0, 0] 23: [[;], []] [] error("inconsistent dimensions in rnfidealabstorel.") [;] [] [;] 0 [0, 0] 24: error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") [2, x^2 + 1, x^4 + 1, -x^4 + x, -1/2*x^4 + 1/2*x^3 + 1/2*x - 21/2, 1/2*x^5 - 1/2*x^4 - 21/2*x^2 + 1/2*x] error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") 25: error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealabstorel (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") [18416, x^2 + 6979, x^4 + 3879, -9208*x^4 + 9208*x, -6979/2*x^4 + 1/2*x^3 + 6979/2*x - 21/2, 1/2*x^5 - 3879/2*x^4 - 21/2*x^2 + 3879/2*x] error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") 26: error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealabstorel (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("inconsistent operation 'RgV_RgC_mul' t_VEC (3 elts) , t_COL (6 elts). ") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") error("incorrect type in rnfidealhnf (t_MAT).") 27: [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, 12259, 35869; 0, 1, 0; 0, 0, 1] error("incorrect type in idealtyp (t_VEC).") [561940, 12259, 316839; 0, 1, 0; 0, 0, 1] 561940 [280970, Mod(x + Mod(-140485*y + 110026, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) ] 28: [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] error("inconsistent dimensions in rnfidealabstorel.") [280970, 12259, 35869; 0, 1, 0; 0, 0, 1] error("inconsistent operation 'RgV_RgC_mul' t_VEC (3 elts) , t_COL (2 elts). ") [561940, 12259, 316839; 0, 1, 0; 0, 0, 1] 561940 [280970, Mod(x + Mod(-140485*y + 110026, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) ] [[;], []] [[;], []] [[1, 0; 0, 1], [[21, 0, 0; 0, 21, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [[1, 0; 0, 1], [[21, 0, 0; 0, 21, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [[1, -347298; 0, 1], [[5900370, 2821959, 5374299; 0, 1, 0; 0, 0, 1], [1, 1/2 , 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [[1, -347298; 0, 1], [[5900370, 2821959, 5374299; 0, 1, 0; 0, 0, 1], [1, 1/2 , 1/2; 0, 1/2, 0; 0, 0, 1/2]]] *** at top-level: rnfdet(L,[[;],[]]) *** ^------------------ *** rnfdet: incorrect type in checknf [please apply nfinit()] (t_VEC). [1 0 0] [0 1 0] [0 0 1] [280970 12259/2 316839/2] [ 0 1/2 0] [ 0 0 1/2] [1 -1 [-1/2, -1/2]~] [0 1 [1/2, 1/2]~] 1 *** at top-level: rnfidealtwoelt(L,[[1 *** ^-------------------- *** rnfidealtwoelt: incorrect type in idealtyp [non-square t_MAT] (t_MAT). Total time spent: 380 pari-2.7.5/src/test/32/ploth0000644000175000017500000001001012502252164014140 0ustar billbill echo = 1 (on) ? \p19 realprecision = 19 significant digits ? t=plothsizes(); ? plotinit(0,t[1]-11,t[2]-11) ? plotscale(0,0,1000,0,1000); ? plotbox(0,500,500) ? plotdraw([0,0,0]) ? psdraw([0,0,0]) ? 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) [243, 583] ? plot(x=-5,5,sin(x)) 0.9995545 x""x_''''''''''''''''''''''''''''''''''_x""x'''''''''''''''''''| | x _ "_ | | x _ _ | | x _ | | _ " | | " x | | x _ | | " | | " x _ | | _ | | " x | ````````````x``````````````````_```````````````````````````````` | " | | " x _ | | _ | | " x | | x _ | | _ " | | " x | | " " x | | "_ " x | -0.999555 |...................x__x".................................."x__x -5 5 ? ploth(x=-5,5,sin(x)) [-5.000000000000000000, 5.000000000000000000, -0.9999964107564721649, 0.9999 964107564721649] ? 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) [-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) [-1.000000000000000000, 1.000000000000000000, -1.000000000000000000, 1.00000 0000000000000] ? 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) ? plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) ? psploth(x=-5,5,sin(x)); ? psplothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500),1); ? plotmove(0,50,50);plotrbox(0,50,50) ? plotrline(0,150,100) ? plotcolor(0,4); ? plotcursor(0) [200, 150] ? plotrmove(0,5,5);plotcursor(0) [205, 155] ? plotrpoint(0,20,20) ? 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) *** at top-level: ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)], *** ^-------------------- *** inconsistent dimensions in rectploth. ? ploth(x=0,1,x,,1) *** at top-level: ploth(x=0,1,x,,1) *** ^----------------- *** ploth: domain error in ploth: #points < 2 ? plotinit(1); ? plotcopy(0,1,300,0); ? plotclip(1); ? plotdraw([1,10,10]); ? plotinit(100) *** at top-level: plotinit(100) *** ^------------- *** plotinit: domain error in graphic function: rectwindow > 15 ? print("Total time spent: ",gettime); Total time spent: 44 pari-2.7.5/src/test/32/trans20000644000175000017500000000557512530662432014253 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 5.0431656433600286513118821892854247103 [0.54030230586813971740093660744297660373 - 0.841470984807896506652502321630 29899962*I, 0.54030230586813971740093660744297660373 + 0.8414709848078965066 5250232163029899962*I]~ error("incorrect type in exp (t_STR).") O(2^0) error("impossible inverse in powp: O(2^0).") 0 1 2 + O(x^2) 2.8284271247461900976033774484193961571 + O(x^2) Mod(1, y) + Mod(1/2, y)*x + O(x^2) 2 + 1/4*x + O(x^2) error("domain error in gpow [irrational exponent]: valuation != 0") O(x^0) 1 + 0.50000000000000000000000000000000000000*x + O(x^2) error("overflow in sqrtn [valuation].") error("incorrect type in gpow (t_STR).") error("incorrect type in gpow(0,n) (t_INTMOD).") x^196608 error("overflow in pow_monome [degree].") error("overflow in gpow.") 1.0000000000000000000000000000000000000 0.E-38 1 + 1/2*x - 1/16*x^2 + 1/32*x^3 - 21/1024*x^4 + 31/2048*x^5 - 195/16384*x^6 + 319/32768*x^7 - 34325/4194304*x^8 + 58899/8388608*x^9 + O(x^10) [1.0000000000000000000000000000000000000, 1.45679103104690686918643238326508 19750] 3 + 2*3^2 + 3^3 + O(3^4) error("incorrect type in exp (t_INTMOD).") 1 + O(3^5) 1 + 3 + 3^2 + 2*3^3 + 2*3^4 + O(3^5) 0.54030230586813971740093660744297660373 + 0.8414709848078965066525023216302 9899962*I error("incorrect type in log (t_INTMOD).") error("domain error in Qp_log: argument = 0") O(3^4) 0.E-38 + 1.5707963267948966192313216916397514421*I error("incorrect type in cos (t_INTMOD).") 1 + O(3^5) 1 + 3^2 + 2*3^4 + O(3^6) 1.5430806348152437784779056207570616826 error("incorrect type in sin (t_INTMOD).") O(3^5) 3 + 3^2 + 3^3 + 2*3^4 + O(3^5) 1.1752011936438014568823818505956008152*I error("incorrect type in tan (t_INTMOD).") O(3^5) 3 + 3^2 + 3^4 + O(3^5) 0.76159415595576488811945828260479359041*I error("incorrect type in cotan (t_INTMOD).") error("impossible inverse in divpp: O(3^5).") 3^-1 + 2 + 3^2 + O(3^3) -1.3130352854993313036361612469308478329*I 0.27175258531951171652884372249858892071 + 1.0839233273386945434757520612119 717214*I -0.45765755436028576375027741043204727643 1.5707963267948966192313216916397514421 + O(x) -1.5707963267948966192313216916397514421 + O(x) 1.5707963267948966192313216916397514421*I + O(x) -1.5707963267948966192313216916397514421*I + O(x) O(x) 1.4142135623730950488016887242096980786*x + O(x^2) 1.3169578969248167086250463473079684440 + 0.57735026918962576450914878050195 745565*x - 0.19245008972987525483638292683398581855*x^2 + O(x^3) O(x) 0.84147098480789650665250232163029899962*I 1.6 e-38 4.9 e-39 3.1 e-39 0.e-38 0.e-38 0.e-38 0.e-38 0.e-38 3.4 e-39 3.5 e-39 0.e-38 0.e-38 0.e-38 4.2 e-39 0.e-38 0.e-38 -0.20484755831421800270211268209700671730 - 1.024400881608445881724860454410 8866770*I 2.2048475583142180027021126820970067173 - 1.02440088160844588172486045441088 66770*I 1.1170000166126746685453698198370956101 1.7182818284590452353602874713526624978 0.E-2003 Total time spent: 12 pari-2.7.5/src/test/32/aurifeuille0000644000175000017500000000031311636712103015326 0ustar billbill2818034765526617919871 13851033738067865242961762796990508103341 2818034765526617919871 48975219025052205901 288943522443730350379346314566889 73194743542229 97 13 818201 13 1741 31 Total time spent: 16 pari-2.7.5/src/test/32/padic0000644000175000017500000000375412573015517014122 0ustar billbill[O(2)]~ *** at top-level: padicappr(x^2+1+O(3) *** ^-------------------- *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3 *** at top-level: padicappr(x^2+1+O(3) *** ^-------------------- *** 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] [2, 2, 2] [3, 2, 2] [6, 2, 2] [7, 2, 2] [10, 2, 2] [2, 2, 3] [3, 2, 3] [4, 2, 3] [5, 2, 3] [6, 2, 3] [7, 2, 3] [10, 2, 3] [2, 3, 3] [3, 3, 3] [4, 3, 3] [5, 3, 3] [6, 3, 3] [7, 3, 3] [8, 3, 3] [9, 3, 3] [10, 3, 3] [2, 11, 3] [3, 11, 3] [4, 11, 3] [5, 11, 3] [6, 11, 3] [7, 11, 3] [8, 11, 3] [9, 11, 3] [10, 11, 3] [2, 18446744073709551629, 3] [3, 18446744073709551629, 3] [4, 18446744073709551629, 3] [5, 18446744073709551629, 3] [6, 18446744073709551629, 3] [7, 18446744073709551629, 3] [8, 18446744073709551629, 3] [9, 18446744073709551629, 3] [10, 18446744073709551629, 3] [2^3 + O(2^6), 1 + 2^2 + O(2^6), 1 + 2 + 2^4 + 2^5 + O(2^6)]~ [Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + O(2^10))*y + ( 1 + 2^2 + 2^6 + 2^7 + O(2^10)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + O(2^10))*y + (1 + 2 + 2^4 + 2^5 + 2^8 + O(2^1 0)), y^2 + y + 1)]~ 1/2 3 + 3^2 + O(3^5) 2 + 2^2 + O(2^5) 1 + 2*3^2 + 3^3 + 3^4 + O(3^5) 1 + O(x) 3 + 2*3^3 + 3^4 + O(3^5) O(x) 3 + O(3^5) O(x) 1 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + O(3^5) 1 + 2 + 2^2 + 2^3 + O(2^4) 18446744073709551627 + 18446744073709551628*18446744073709551629 + O(1844674 4073709551629^2) 3074457345618258605 + 15372286728091293024*18446744073709551629 + O(18446744 073709551629^2) 2*3^2 + 2*3^3 + O(3^5) 1 + O(2) 1 + 2^2 + O(2^3) 1 + 2 + 2^2 + 2^3 + 2^5 + 2^6 + O(2^7) 1 + 2 + 2^2 + 2^3 + 2^5 + 2^6 + 2^7 + O(2^8) 1 + 2^2 + 2^4 + O(2^5) 1 + 2^2 + 2^4 + 2^5 + O(2^6) 2 + 5 + 2*5^2 + O(5^3) Total time spent: 4 pari-2.7.5/src/test/32/multiif0000644000175000017500000000014012413013143014457 0ustar billbill1 1 1 1 1 1 default 2 2 2 2 default default 3 3 default default default 1 2 Total time spent: 4 pari-2.7.5/src/test/32/random0000644000175000017500000000236012405547147014315 0ustar billbillMod(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 *** 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 2124902699 5 1267650600228229401496704197543 *** at top-level: random("") *** ^---------- *** random: incorrect type in genrand (t_STR). Total time spent: 0 pari-2.7.5/src/test/32/intnum0000644000175000017500000000655012405547147014354 0ustar billbill? 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]; ? \p96 realprecision = 96 significant digits ? check(intcirc(s=1,0.5,zeta(s)),1) -93 ? check(intlaplaceinv(x=2,1,1/x),1) -53 ? m=intnumstep(); ? check(intlaplaceinv(x=2,1,1/x,m+1),1) -94 ? check(intlaplaceinv(x=5,1,1/x),1) -83 ? check(intlaplaceinv(x=100,1,1/x),1) -52 ? A=intmellininv(s=2,4,gamma(s)^3); ? tab=intfuncinit(t=[-oo,4.5],[oo,4.5],gamma(2+I*t)^3,1); ? check(intmellininvshort(2,4,tab),A) -94 ? f(x)=1/(exp(x)-1)-exp(-x)/x; ? 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" ? check(intnum(x=0,[oo,1],g(x)),Euler) "-oo" ? check(intnum(x=0,1,1/sqrt(x)),2) -59 ? check(intnum(x=[0,-1/2],1,1/sqrt(x)),2) "-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" ? check(intnum(x=0,[oo,-2*I],sin(2*x)/x),Pi/2) "-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 ? check(intnum(x=0,[oo,1],sin(x)^3*exp(-x)),3/10) -96 ? check(intnum(x=0,[oo,-I],sin(x)^3*exp(-x)),3/10) -88 ? tab=intnuminit(0,[oo,-I],m+1); ? 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" ? 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)); ? tab=sumnuminit(2); ? b=sumnum(n=1,2,1/(n^3+n+1),tab); ? check(a,b) -305 ? 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) -305 ? check(sumnum(n=1,2,n^(-4/3),,1),zeta(4/3)) -110 ? tab=sumnuminit([2,-3/2]); ? check(sumnum(n=1,[2,-3/2],1/(n*sqrt(n)),tab,1),zeta(3/2)) -305 ? check(suminf(n=1,2^(-n)),1) -307 ? check(sumpos(n=1,2^(-n)),1) -307 ? check(sumnum(n=1,[2,log(2)],2^(-n),intnumstep()+1,1),1) -304 ? tab=sumnuminit(2,,-1); ? a=sumnumalt(n=1,2,1/(n^3+n+1),tab,1); ? b=sumalt(n=1,(-1)^n/(n^3+n+1)); ? check(a,b) -307 ? \p96 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" ? T=intnuminitgen(t,0,[[1],1],exp(t-exp(-t))); ? check(intnum(x=0,[[1],1],exp(-x),T),1) "-oo" ? intfourierexp(t=0,[[1],1],1/2,exp(-t^2)) 0.07515645001618094506724269142337819200573257288846457257682421833136020654 01315089580450881170413 - 0.408148557374490719018171389392074027664154880556 033855962874575972355801042051564345987971241498*I ? intfouriercos(t=0,[[1],1],1/2,exp(-t^2)) 0.07515645001618094506724269142337819200573257288846457257682421833136020654 01315089580450881170413 ? intfouriersin(t=0,[[1],1],1/2,exp(-t^2)) 0.40814855737449071901817138939207402766415488055603385596287457597235580104 2051564345987971241498 ? \p38 realprecision = 38 significant digits ? intnumromb(x=0,1,sin(x)) 0.45969769413186028259906339255702339518 ? intnumromb(x=0,1,sin(x),1) 0.45969769413186028259906339255702338970 ? intnumromb(x=1,100,exp(-x^2),2) 0.13940279264033098824961630553871957887 ? intnumromb(x=0,1,sin(x)/x,3) 0.94608307036718301494135331382317964743 ? 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 ? print("Total time spent: ",gettime); Total time spent: 20736 pari-2.7.5/src/test/32/idealramgroups0000644000175000017500000000156612611142771016053 0ustar billbill2:[[2, 1], [2, 1], [2, 1], [2, 1]] 3:[[15, 1]] 5:[[2, 1], [2, 1]] 7:[[2, 1]] 11:[[2, 1]] 13:[[15, 1]] 17:[[2, 1]] 19:[[10, 1], [5, 1]] 23:[[2, 1]] 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([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, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], Vecsmall([2, 2])], [[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])]] [[[Vecsmall([7, 1, 5, 3, 6, 4, 8, 2]), Vecsmall([3, 5, 8, 2, 7, 1, 4, 6])], Vecsmall([4, 2])], [[Vecsmall([7, 1, 5, 3, 6, 4, 8, 2])], Vecsmall([4])]] Total time spent: 972 pari-2.7.5/src/test/32/resultant0000644000175000017500000007260712414214040015050 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 1127614608 911045 -23334121 15152875237197769342976 1 4789697380021054650345938381924768779764502171151476021251465336909773783338 1483478046719619493978767437813786102680708004930493639232124484712989030743 77376 5591778626126198515789740127923726924138993122908566507963011388676468961202 4477425313882678703984217553283789132475364222241284814412314235455434422980 7710892411505927222662178875831559611191917768447356156048451344207870859235 3421574869121809933510172523951949560305425573780083942051414584453903225103 9150588607156375894233737091156899560058104991022009737098022791771063870332 4543754376917999871790501326547853054436444495861161564399190140572883960196 4316196975817429852098537493490087741730840438498474174124950599821563462379 4776250318165223172258299094200163699119837367865451816040219464272808536682 6366448478399563694093511562444580982947874089384832363620244514399470126325 1221138634876570856880659380036429623915483515843179086549287327024998004564 7976338198194174093893290033883921204928495263532870000949040615012556044932 1818817854986256664488406380789052297112100244473983193254140610618060591371 899564340082899114785688720906351258905787053899776 7081072488122549108437740087055070486542322805098742006332199056679193928966 4483785295568554162322036400017122263928267064345800987077874888846659771496 6170549511731996859294513678297798592859196096017665960363670523570420377721 2919429331810768214726379757777338665118630273090090442002357392565485086331 5412450577546522243130333620009107379345899855572005517250317530197793851722 3355902478870693674755098498729934799138680215415329581514280083638477701043 9833756129716245879910591555562933614970015160148305939648207485535526079234 0506699237254741161806485754160707356885468112747818240990343439929195771261 5718119731260544392168170080797529909765466194544434766073431138630521097535 7468986434676998993972786577010278592120332643280493735615754118765736720057 2393565271488265393041765173848995399894723709392064991834838703664591278597 3082437298288444379811881610029611376601722270737965832251382983968232233649 8871844617255503719150928022965927019986189521620111495073311653079160054784 6857440559795860180426346941115122603046544514726275045580655957003854337394 2366607422738440023830359041009316801704138433518791880556684554000725519633 6314221737402120724621182545795068118781015520862409165116892715165782201744 7373528760095126876619409888737755809138526698545586130093257520346765161706 3668856674264264360780430404097555123190894892970707035925992771214318693453 9933063048724159581078642517219830228441155730464252333929338601304473477379 9924164123779424453250220315240908440937220701876898151966131532288459419998 7193319301791449277695747801099373571458888429427291702061589949699722004575 4707271425056836723915364693803883154598841808528064617757070166253079521282 9330993749058818913084870487521920089024720415354689556927595116643657782190 7772163668281509363539079928183803467678757273373526894367221203626621799795 0834794280858064768554880652430560684135485447762704940367795197161950331922 1933358870993764673870859837952485667866798702804457244640778314935644379077 1781507677136287186820379853171767323733496951804295617087357625661051104152 1796342712986360278714707030680719176226964227465901389213818171046492873465 0022790780563242373313610025898026386690016904386357791379547299812905227390 1289797056874223293654886944596148419408207352315947914652557188420178927934 2848619416825409009261520189608713137382207964171283558993905022859982486695 9083539842491853405079547629485109169490879476146913423588991526498785270327 3968511118988030085179508566878601698165562240004498473335561372165388144302 5299351926733300122236311522899635357333042443410986368545768414279154922277 9119056516432750446537012271038703954019716627215359282310427886580436806649 1128763133722567880219150198570570334214903477999954881887377115447377529450 4743238205391224700586995860603351466477628176669368096677069674459366626343 1922851858053123966451232560199488110901933493373773342297093283394419388248 4588916794714441254931339361853072424034331084764085081987592855543881808243 1779116507645535321440983529543254866843835344498356598259597110076846725320 6851381772957660420342635656117691678289746109819594274521914714099658185017 8103384766865875768775851148845968289169127685348378811992123602296633104373 2805377772394628665071343459476385073839007177030802143173978958766607853438 1299576637513893400073478172504247752287917016974831919723343256352815430862 2756735538729480299222282240438655236155081637699288961373884981739501718182 2681375497299984831021291189018514228948558064909058423273859290080459595571 1759917019292934458035585962564362223881131293139396977742617328161512636776 1481197065944479079708702464472102740839784622024302517281715139380530650311 1915971888668147117514765329906797514964395684832725088547469451338928840681 2720007091412810257156421902095403437335707368255329889993567282476060201844 5771396723720966942646908853851819209514039160674238448209530171041506333081 6987469227749752421380683026987025045039827341868747252476484201784372446710 3510248767574924856801643658855141372196574234941500177109628589376464368340 2999855256027646684276215612404965044584115542842898614670574653437772506535 4923273222262319450335041587329691932221764773887410781545905870741527518830 0856696173015051150711714497101540120133632210837848926748871140267926449098 1423419401755524300390263874468295460307895598999553133968897373983301216878 2734049667608533709411627027619810284143582046196764517591998490057580029106 3609272592147333011404236522621245214993427142890298259090018689952508140536 9654638037034014821665971679425142385118234439462497731669309557480650496918 1834649980677855020436832515946267480139639823701397028549118270169170519415 6721794171223686532838514733056067604528123664171806646382399462634890916813 6669485840561432308522405899924251087786067664162652793044413599537424129707 5477186898973633516352568883257904332028806586709401569864515982688222129153 1567052855728262995530434353630134178070106956944279797548165372439216825076 8326715576786303582598430095125742864236163720296213905787039885884463657834 4643437508267891744779261877500947228066699509369586576615123985367219743858 6658022062041430002005181878216355419666743135504759692658299056669357259645 1140384349942471935622171122262819380938871819723106690671480887238746092900 8259392457845570085120138974098112147614179833839988811199774487498092129908 2525330985586942998714786716070693999685611141806930181168204974764634546790 2491116660085873519752267226746027234992210672340901561111569016509087980484 7241366934438873990966498559499978863196895478498708930733440029703211754971 3174338633455354574979245770026845320172157118052425714203442756762690452556 2195168177038659757872091439804829007952032160043794866268382905222485457033 4877085046605283955920544774598658688901188561694172099986871239644906361688 0166806589820637842653846370311841209424194808154992103008317976618840646505 3524843776927351496372745683004763216358973783229858596853568141313750965802 6732704253827791291256677915251801050186660146187981397142021248163932831949 1242424936332974106235910726775448936949225963230406509254485317395735192765 9629100658168052496684342007876499412743472614751505477517198117059603151774 0513333347014771131213527388744277817255738469560576073881746517093241538950 8379623995721601203434646863118546318466543153575568871197413866654425349795 9709665081383739157130696886846685180184094150972054886673926466898476160056 9251865200870473249492728358926161261942133179621059876513623829755485965508 1765991185475814355042047437792982556193134305138749561348141122718465434028 5955347577189501961066057321746605591478524411065032570202848093134945388063 1469805925510862902366653958969425851152732736769061502994730346813692391400 2188444260504305088747166891225921799545810287134453936174360046753896543846 4725311018589188158298923975056694464632127746952940324604386896534946901154 0189748233921118167859285574717815593009931414748460169210424421915763646667 2549643791464812661184224613907766599594347549012695657501957708976598982379 6246315465707511680970636654737842632945349283341207033490434420327941078448 1247500527894528017587459786622669024443518026949815548731423263169447248228 5110467004911800020475713052104208484239152280018530719982927713299542152131 6714018358725068038634436774574546773146283899186292132944165251525364117406 2333682077664235142911764750699483904374984050720750763989372219539833457960 7517904946980952462925255681650144231984545917747245637003964519102283728734 7801223416232398530453943213234148790697908440512084299095779197332999945341 4964437542186365784691171021464796820401539232838986619037169900580166453697 8875543972648384797560654661388477062010340611513997845689183412371725641192 7259435812034642758959741241517961837062742047554891249269300463738657711558 2873355887128229794245851803952135238397923971740033612324297035200484275438 9156423664686366531825242597376576860994929676476159165395192353567061116835 0879052026395527993330789894200638408494686144201609307220354927475939107543 4100442246166647741053132902356715119673330523458821912870829882436969397956 9406895726081967239095445456258787542857469923106451553636440562462133562360 2668811067192149078795792377466748973463935910225355341714595027831656267131 7448279182843337911131360717637361214496493274000813932176510723999645466023 2577690480408703033440600514220628547543775356283381461661090490710822064909 4442349542870358299272174730711563333091694493018076280359800542459534086476 1753773084515412810070994263488287449786031849963340685709770929949412357769 8595467102933787819050340231630643521983014085233294591129365647969335691870 1645312144680039661515859963988461311015875682686126364930986339192596055528 5415821644430946059242051021689727062158285718368764970142254220221251016570 1562643814866019675250331401163912499653408827720323147052395354630909040950 2449569343309008357721192162211813923928897216896982491145981783817245900369 5174601436757895126770570726969854492290667489978001725658920553817006873736 9361312619106558444263836067946213531312792247596380264510333469355965494293 8057756424419773526095629957221330300887874765988164844737994868164641605222 2825624132991984850324866986619296607978229622915429194579009932988226000946 2799716898319535999601514182213198784020927602509705335937317436616464565386 2872053875185499951244257832174070631688990682874482631471691339296616648363 3357285120715643816652078133798755984077111980231423933018801082978392585421 0557410505624607436448090236794246925372257552335205668157924552625077577745 1444994285443412758408944565156472565466791294345215703318051430639461056798 9104112885134043465540265984546300434414876490392033240018221222923160975692 3574118451325235191746732118645012230660740739534589705361993281591810042848 1386376501091030428196191317149726249705003607276293632768455631898002411316 8723568666921731614366149245523567264036839088882693159534231662113318927190 2700597763458658138616263432657882123932584966891493766304566230992548511870 1578565808767928420814686276337773212621085152030353396508799832670048785694 9458195423731556131061003012038999565838203945938486770903260446305772890830 7066407095099849010110311279170801482672160151298019450205523688931455046837 2696701818054864809290668621005085842719448633255369262839048473607324076854 3876512651160078271451580705114404951011889183775018819798848974826562003664 6661732798500898437911439686901081863261839430043923237046283466602427871304 8506953093641642163367712127257564040734310940434747428181583577390637815785 0568728380279883244330109231305923546694823757987289677640095975011241184318 9915958392805871916668742980025522360460089258695511886998639786040952838129 9175637805687931816598611425185730113293288911861332695586714572145658115029 9844338849992973326251312720024106411331530108183020506081531934467942310766 5480466436597036298814762723036190616555337378880978653796168575503594499080 4938901966476145425173757988475188344145289435972780305559861056903328353435 7097324796734880384585281130228000670331841246489779777755289555189750148212 2460528569662635491485226214600657466593819032606384448441494814219184451373 2970238465927788712086864971958121372221766814952929308218481647008620534821 4870259320816045694040663489812592473817436697294095899807395498397055191786 4246700427676626086795906762335651942030658186154911718028023640965476401541 6331290138619972853394139193068857312592167829698870990849405149987021278969 3611178142790638697562338466404270499149409798871543973677872220822218818707 9274126492516822409042659368169703465936982972778620219021231830098682652554 0129952966507080659132966853812023584303362666270317227465529934100811015105 8868990725432564987605223395940547374046157871476155638971225706634706527197 2100070728017924350626608177098973079265381463675975950527323756525988663565 2792980895669484248299410038263537660623017805311298685765900580697924240570 4587261148427817001651793337528843665500553095898064074090246369336456936473 4373803950522485651344423864279448523115897237705822685322793258751461529039 8924994348239102187147135789338076432776608620822393601589765157207326701598 4974900600705558869601187220120358321975167707693820494316713534023111843805 9283173364786844421849556149175619273166387467854407493491717116722424505053 1728410586881113103309453413145528185963208374232941772791717539803691080384 2397504701077839217768067902076125594575708755459937027409745203440094884479 5140234505133742864665356178364606835448830939783260650214862842555014663195 6415594335179574317671856504206447373591062916029471992300116963386628460524 2847904416596141934741828146379809581664158905733011925952574996015569831756 9703063616018931599351925057216994635704120606881418401365121636867122399809 2774750147634980569429662641208390283422787696005105225767492395514821395148 2324024851334114743756051875991639774324459647227599873088565986456465788550 2092343371481239343113881272770926693174789149230168249996032172137615301356 4980996965817634459665187513080922525605201604845857286564525064751439629278 3000725290349331142295275597309690835948790615844571089136616960068195339705 6194453861378417806817597789190149182835100252960383932417019745974444767099 0624786637634290275002442959915995647243356991025785049598063354253091991467 2884054539571691939828506354835147188797863438910609128541007455256683557131 0562342964055240007307201315671721394884726343064451522335113780730215996618 7001991699723165212904103307749537867071104955163912366676956060671585948075 8856561990076412149919627753695230757225285324756951063606903236791929080189 3973661505448117852920548942305793298953857044793936910063454602785182803429 6064134170981414962838068243888581694538254933156788556169768331700594145992 0829625229407628504478197743358306906062714062770191995932116159202455454698 1833772637944551971708296532225251958444281762416016999602533345461193450313 0648189438004061438499414165320145166394394137001741494601734265729049916536 8786615510481765352709341172007999297661820452214994434444847483883226297140 1401674898781247484082998956186471711709567755084249521203388115453739850984 8201380092084758372275724538800301564602934678377853362331910728064061151092 9552063475242103758900477732246484302256511528132759160221241392285002767024 3669353741641622336731841455767829054402291230797389101828234070416279585998 4177436328311159747118290973201619007228947454290436250321638835917076230562 5908006734101378403247160809171990515159263712996771840506632764382172811486 1045805889911666828084633587319003655886973250316525236916645981137835447238 4293626020194196895754257039489866614124700604916502009470350933899248574263 2433831333725836823737934116481556444659294843962623404784927612972830908818 7995066167536899612315082598662649426372702024801212726876754386409528327484 0407885195827599897275621697816182411963589270076348733404107791216013908821 3312645242645005779272501822320994675104938946391158040143587955328884418481 8552189233778681399753847414887764033120998535989960058575892967832407772128 1486370558522744063535928001892364461867715745222791284527793212818188214212 5151430384435843528957786512789031489302505302683680671161908878734972360980 0169606010403993591690593687152871349591312158380146505938090653290650464244 2393715616059833231533447758770144994797243194913401125749757861887967071474 0668243840880239975410140487167665497226423304105183321456942712666755366048 4513930715943788103872965224019765145227252865954271143477545308093565624554 2038273819668351030692714185064237433409989989843369326821584267652829971183 1047748516522526723332327680235436145444057502299686617058124219054013357604 2058644381474119584378752212603826077589535634202050954327560432207418222041 2946673374895032454261423042963903275402019846909997207392220695906575618068 1181429287813762522813907938908102094558672580674959851503384043646005266215 3556850616430494449519453861414586052518051253449165323698938124942367235337 0262664752264544375885466166799033815620881800700646346140590254007360813756 6106251312723308725668659882494606260328217635132797924501855990617961457672 1019271798366689077713053020708507055485816592439719097528763798162719234761 5768842729973762210377565701985356010572319029207706749810973378297162497315 2429257893364899813089138087002591377752115806621791689735535324942239281389 7707658659115297091177669024303780469123021110257015997626532926986838094760 0251473914561276418783777747329910981979578981148252984143759266894331122042 9041445345958715283155660279310587345830247860448837525261315766198993992499 5959135476557955828889140898705619068986297758402572687925341338893322191018 4951574210527100911563052359377857775455187162182640677583563839405015418626 6271003135442406476904292013486173064280165102275860877358055961680377018117 9407258058194062595343490331433128277476287025562338780716296607863734421964 6398504753473310937624280680487514461999171822917905958714467444259409540096 5125686461106746954329208107230838711949699315085161624573548764472629924000 9388826927578163869644055897801290539733180405120167542888739695296935787527 2277231024000866999422003496826219681773340717008049883536929150209759419719 2476724495228873880421184843573662693488497521949703654293617023731876188021 8161101036337107718919946052334638989394796774173354409309562498787726965123 8501379728687520420137037318041140155292864410431179358106654346624235823545 3064016217648136175289259908242738578378187682097303323420320267640427880197 0546103037587443506906154893888189366292745693373465818296838130553615764337 2012379056702209339738530032711295715914291111593610024223834654681234489950 2995984070241882647259917195419249566653665169904729139657919194431471824505 6330324626778144078219820414708337050772319628837159448612020902643054481443 7785951186072214743077777545529851432900878096517420251324683967383472320646 7072171826870056133206946006956594590822413225672457103287494913610929672857 2802979513803760415959689167004444098745469704235693893440234078348358992130 2902412804083486203809602146349295979585966691897800454007145734217841442504 2509656059394416722763927807238311390512732351899114617488579954637344893472 6956418040020563753576439361112293250812538205606862069824031389592220753938 3931980444000396952790300025110413488020461314044867096400482555611861766557 8779872633208790282853041828436599000821439615909297936909400476874231409386 1107957033048878824727553773211614689966672780402203443704886999018746632918 4578570059506705179295259119648586493455744160376834283354774861549013613756 8914104974148435789675196156799768181676487349484914162264963803701991647308 7077370046772797817386919223496396655554669074903108105861101273892479122450 4487000094244471654652318170723070150479698387577348165943027364806795695771 1605973865900671088466048319535078791374564546245300366331708247635343933398 1970452195592950156793361600483926819755275149212838754795843185318110832468 1382112309145641859606129754154071672948878109857709847136184953440514957541 3641496697051930106770483801168708463106269498367706651154782577811514002639 5106563888263605829321212608718331459495599039042081814718848457860199057649 5346982843071231821350857965681984563335821957754569468382305016184024887604 8160723684261393716356258451730935748281676054966556038316792751070826540054 2473315712042588604514882868227176108332833877184166366265303737221912013662 4512167901067209682554392111071155499467651327936730515479173229263731514370 3330182513953368428655392818025057917570653783124434362274261551843983160477 7351162406242450929672186628419950329891867814208035883609977838886238833276 5330774679847630559105909002838233097431528046724187446177909715044255520881 8889404837062703651637318360772404220635983462926485432718138685237631857455 0598465166755132919094585655974966874524784130599703711634113352005177406926 9603316645497284293848590370977640427328887687375912505822778917514360380115 5682283488759427844250167972992511302878057532531484502529732162662116955639 7406173957119233848745104829248262313597011029557702426889396863083570940205 7509537898825756241704038780955282562441114537127841752209332467489719207566 1744264901601182958290811929305241680377823312435028072780502748828361181784 5922938685656775729737638617283841787967835602522574138712851435180707114732 7070864077169181369700790505644456673957432875813509347521540262444684384812 1628162757064794714790594967511664494982986431532091869678632267880119090181 3358285913239640118632956526316790292934199787619720599635756782126973040030 8849995749515739684821341699562520787829013184888043096654760631188226253631 8585742707987188915896804232114765200530074024419150347592072019161120869323 4748482955558033228065455570160118248780022998383870238441158071327622059726 4610703982594367716830470741988537826072641367377235148800000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000 6424194875218376701463113579276658235425909119319864401234806441094021127054 1375266956365232048220109345396592726319742460454879981062694340660155949810 0158596374952141691378161159043297105952129759212696862483103011107449914024 0094518530978010978915317583738701606420973822157506086835007914978002982268 5532998094510470979840507359084614024762021412168744501835585051640684574287 1078953105601656693485703971643934048397703383418980257911777900546820380805 4170495763626051350369423653552681147090272505727727116438873040672296148742 3911117072924868470426691405643972081983053358547587471903955838256977365810 7214608397690540588379230455866567931949997177575434025237758134753480761133 28381591924887486184484485922972282971065248302182867907169925597 5666658170985421428568776023708028963706995520080659357168692551584779660342 8845370048005616413297301438788684948250159498753561703887501771998471467047 0572365820592328518742718645259795706159687456606230246406028480921554259928 5340467680010491452771885463865912263236353978700007220144125780098160197203 2031201691364593717086444953556041504587784874247426094277154056141748358043 3092986242590451866923730053842550530645976252654457481607935574398512975433 5958612625992295737052292037154444584538830158625476522119502606425844311713 7568524432625716058524905583126467948164530845151327970412952427667083285696 1654438323710321253566705831201432914714319143016623815060881384835591899090 2471009192031544760372901915755330058532299670144074706793928555485848393159 1828050109715302094839971124460319775966476623121401249450851220197356866122 8030237845317849716956219074680650465917640347731788333583546848508416734340 3898157780073751187903396667377222823979111370825580014201215182931295599914 4605197631998749857550713081687598984457233392295649568376711423487711804910 2828628167987521424766213383686969797280488819530652810103906518166447659272 3960381547488477643959422660036664159679049695106798176262658899212922595345 2454875526563586504128373884988804533889790263675488058966242204666913885135 4761573671014826411947138132267980759790003000518532492673507771928777973799 4462263269300516966805110216380798756683709747323283623552894566069041854716 5029737260856017571432569467896308128832457972079937266842795609362963233465 6327577377986418531570275825779937665992342542699460636407443029919577857433 8281851600006090764198717337191559381124541561638319703069586167725629299517 5076255282960787602293050101970033429356854625906232924704291310702886456251 8632469985653278132588227168080017020040737658591877433454971545485013311503 6561434485127084618089632304423817006708918171546906346335387536183560949225 6036074667890092069337996522372744178148163354405930752765169071704137022745 3128090263426824477803494585851173850223374121732489365069889497237403158227 9840839631127334319988930212402475223960918680308467061859410851679902975904 4661251441881460358726937406012647950645653613408222529039998067223110238643 6584292316840781276633771054531894956472312394322235029051864341558369191090 2082097544642694038762391681516198232954168712855564402707363812139413162515 0480689998678584944350427513554851672228063533753307926177250358938882470874 0552103661088094930068257811242447871657269388113518991542989510629246336165 8479986550036211371919196414464310026701922662394921566955076574453643730934 1341714157231194704091874372904256798372091118444460231449307037375034411885 3676576076869932519269429557331764241054721425368240513547145593868968757079 8413509507002710738565824220172607150332145236704442306962285332528127656564 2590547122402610145691024371453366639652111607302939245318506315359461958010 0338927812940593249471506386124415697212645252323776162585064558232775462345 0951607701158724151244612836110221471968264848258590874666079962640426472074 3487324130608218105825409790022539148520998476124281291687889066415082363438 6377246876252328877677745106379993913801568088315491443230018175530767089172 2280158309314854025846942336224310461844675465480506733085433084145387991886 9163462389952637245366258421425459491140903882880003377713821451634188188884 1270198600409570953154950542534700105045291091093642996156632611959521886490 8877592687889204374862069654416936978853484961795533371115377921813664130820 8894785497117037657605284341185537822982652138954441751771331074319374402086 3465730168436263997343397576043651046145427257983216065136429702161412662944 2533223411458043954241454056372388815682513236663702933669435298342603484167 4852785108888112467902247752587923476008872710917234044426046543641356109789 5876614276812058803783525798121627107430819643445666863755934345575064341943 2421032153639761995700534388812500609556342126624454207517606357454052961253 1916416611193320507596890878455922703579754346646730035078177578839631475550 5154158684730661893835639483595803909842534400000000 -146466598037214168132166946505504582163231930504557323838755829912078704914 7232527937922846836370373882122793776918426462873008206004301364448376259630 0479960292079047337203318689620054594788601914812264756266003542446303110405 9560079971360943834135331209843652685215567853268091899077562013277846536466 1786518361349621668764106591611342239895640346016543607765851182771101386113 1718339502303309148563294578063244261544184459699371894760765768843605074654 7819950060859169704099256831302939154372463310228820624840543133303743930037 6832934573832667131007316074052766767211417435693835817229175698303748426224 8164061481748353716219313553054565951525041510277959943506642274215459240400 3413401913246940636306835336167263971847965958219668263615363229308670003786 1280039502702514466128151473480194115101423711109540716126364366215022998077 3438647003907052554543859418494105956511786638237430891776264628858558346877 0999659442974447178448949336232579513990920556348752372589170183967760081282 1068289815831941416139365959202771157717021073756071068631224445237941841902 1010658333344411773566886865763298166211226814014383373536918777417377201936 0194260907892936117931560105492485208945051722728459321506684015902216398736 1437975998395864293392034350055095596731285567989250747678871045484053969091 7738158228784687166822861537430240167501324801433542590655581872680422750854 3569243672323920014911105847183250923458086240362287243614402774812893620769 8958454584510734797308369548615843411537874069109470839942512266512001813365 1686265685135225872723370661848625082264317185263751868490644013658070593769 5212774412568374551078701167623193603318820391281854674000166562224088265619 7825432639193103479385714210231933101171528480116302844082573381791300062745 3330296747551928284460293572813648085075110582219522739451115791229369187172 3294412418856265068263073465221599276551549319404148769602303854312999142835 4606621084918266578016717978376941310421414846182410260276675218940359642915 0789105727294502216051212140336002972753983918342578254176884786051351324666 191659726146306072405158680 5826600558186537404838856131370471039379659134 58076907875090050502110574307657256807287717388760005394175044663 2615551406650875838181122330253797985104602070241678014791853540448034257062 39419 1177939634036131600533146804222733342399463976109814236899724042387935525345 792616589264996745575 227719861472038658791603995367201962254031696071197510053300364489 1025559083270339613328225485791293069513108821161587766318899893534558082149 559351 4618707505262750497822661744140123902029723820123390596302244701544184757399 151666179549811431957 1973 [2, -2, 4] y^4 + 2*y^3 + 3*y^2 + 2*y + 1 1 1 y^4 [-2*x^2 - y*x, x^2, x^4] [-18*y, 6*y^2 + 4, 4] Mod(0, 3) Mod(1, 3) Mod(0, 2) [-x + 1, 1, 1] x^4 + 2*y*x^2 + y^2 Total time spent: 6416 pari-2.7.5/src/test/32/printf0000644000175000017500000002714412515253455014344 0ustar billbill[1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000 00000] 2.5000000000000000000000000000000000000 "string" 1000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000001 %0.12ld for 1 : 1 %ld for medium : 10000000000000000000100000000000000000001 %ld for big : 12532566399657183181075548323827342061649850750809861714634950 0752097059631738116432448839054351520763198615919551594076685828989467263022 7617908382708545798300151112466612039846243589298325716157180147040963056680 9750761327366302322689525054138592715842608868449408241676861770818959228693 6039922311125683719215046689156738352590137241554510185855964549927575493247 3911325485343784979788060849510858742020118363623157274201095547829887915300 8828971184455050023048563841318994713214224394733419925930073562249293741945 3650061490302105127920314430401636855677549136337481321811349678427076091437 3450453993373486112611680559293554029928231924911903600270361122831809358727 7521451746401317827465710073632156460683825273960115641462844554366314469605 0650160812621814327062666195172701780200286645023823083185928061371310300829 284071141207731280600001 %ld for very big : 955872885674440970277216219337772744771565088008376702328 0974773688280268898473796935187284691567817630339154703241830944055836706177 8809896056537787803996812085304655368999238720837283566913503724303376966199 2663921364613620578078079956465825388253571736411644948206142873619873902998 9324013720616227984952217113628421798278427274142950039049698146988876476074 8939673178886152066176070650100465366222106170273181288184814238180677916113 9684997815338572295836554681424837278459728932615631869144483961065493749103 9440849607597072892720960637713500992934377088954488639521019698524851190029 1396723345810969718342617610081591495344841181777365972361910710227844455871 0596976906677394315185249714607867087670127235754713322083182486995225340569 5472246371195637391184890765488286905297801802857817902007091052166469500735 8517047069777274928903320771601018941992164314045858885325103919749607054488 9716525591702409353851295924370666649874439353143103187877095721819476871104 6039621541420996552337447405835520269309421928095461368238705472240356556168 3129303880551193588007845178971366661918797743038379406063588297944215992646 3691785340362496774349413524560068683544691371721027653642635405810344391477 8552857183108973243687481777037313832906066461962417663222739497894271864945 7391622038713205017081287426068599398078599136506248490477428409273845322293 9485952504181333605883065410971257816284281979689677087852619367458015841421 6117184233630606194460758031603508715854504925822065735415717117642951641517 0445161262958756852411254262131565398676464291882351960512281733196470348829 7690518593597258112492554340486265712974508286368276821774451328996893631934 4348417912106139777376465001699264700607259391929003413720980579337938903285 2410694501172153015867959754936696154432352039610821684585660293442216332255 5070580750071570579340084075728526850951081388750387834675278083942728330312 9711486511315300779788820180840619721223715240178672367496637042272860292245 0067577330084637312473407306058275594314586875447869409332649806214474569067 0799154712883103337029383119878973056652922226725046494001644377943743452783 5338666583328256991155261024818087422713163540831882172167350724012550758316 3850231515419634983097154734421315315036556738503952579851113060316168285064 4412325371035901826210793778328430197276032260968667239887228910011826161802 3097733175960455531908934464156879721834606048691762387934893989942083292678 6114165436117688507634248134379080283752266998295759671652312537861057724541 2889100481703172021091464154836384754183307922685257765508608568562975782300 6971972040325406985944302869772198927623772954412851810428791278029990247190 8061321027142210255474075271028994680673537259392939342492022814681786038589 5053727937460469006290862306302596599241161335993054628084062016336294286371 0165693652750247998589876833218400433596639923643807793537485122586379078832 9952053631976486273900477504002455220369355782732974197522274191043597836052 1374994258036101231726093072258297440735657687656653417040524326319232166510 8439492869411835325894574661493440023985420450317689828201344808075337883055 2236604912047688409349395104864407345150328046921038566652090310866567690216 4572259483873093955981046211889222995200260181463334023494439942826046007589 3236653915339309050400710399118863480174135729126354272327526198931847020456 6728795325066963336117780662108205792489168581971029055585610731736547385276 6380276425506456602527540117971724098601448357463139833373628747458351815403 5433419999067815905003867353801202355724147944135805427332705248973655994186 5041130611413678219355893476567393224303909082190781300190833131836924007165 5654227122516796281838018086974384712482708966565668013921060459766010941761 0550107899541363062705900288745023359281714958359096826397307447904564333619 7694074509803666398360812784827236941956828332814974205954617687782092087303 0997251851490998934287793587314012691376625709193571373268588370102514439184 2763124051970683992048284118502185564135882596329582052566937100416646790947 1498445969988310316737367710893103311537634234857638996253794816827403174591 3409235603550443259621347217893233554496027667610159114124614916154055763095 1198325464161885467428416604670527897561905627890990303514190544175156737750 5869860752456948939764228528356856339078838226722969646304926903904720271260 7550621174274970352102351832642427284726879688473896768703167609747279566439 5578498800392719274981059063029204606278954141664029984815148568896796636434 2663259247454948386361302515198028514970927235946532045204096515486837699846 6925997198878817815883151755772929011530954905662647277529146304631954871875 7981842193591589605589369634076907345944834305812025808883916881139977347406 6104158312454962651296646292425018112638301705729188098557570438397461077275 1107669799661841774127735327529629987980135495274197751725763357367533317639 2595386396318128625002625818616041303229327960689610743787729001226196109507 5078523249740107441649074205707503339857610479405501354002538172669003503829 4356191810667246935208576620655055471197756731578925829743450128512240334555 0857364422106089400098097980710060066914254172300542199332763840179799715395 2104179819732919053768526215633403666084738829519651771281993035539758359068 8781450433887737655547586394649717798423766234759515768872575211201196790591 1773213950669559781858266965876148843986997239366002767913524466843361409330 3498345026183151219733115820351724151015788117079632416971637874342694800810 9209865880902821016061611090832735445696838927030768843853697669522942154966 7227488553970025901787267380707303012994912546555721617521680092662101142028 4912848777979814836521707093537471826821110236198096852733094988389478392581 8255430850346483797946697754305745787159147586676699909367391555177886905439 4354984318116361381459652470477414950669405827757863125230111000328882575478 0655518167212766883031211722120463766886341101457050139738519752913754699466 0984654027027880833056766431641756531642291956384797536599138648642741701263 5420756335784238406846840625370460253690959084071991825552481499175959058377 5949053421792234142884606332226448167839120570370707535455711251191807387373 1274143941499679321050883552677572347377971057431359097681006230800441905433 4051844084001679240936517390705136670076739932448640186313345352369221610604 4837426872832723526396728877036669789154090875467323512305194341580241450118 1685347224120973539459000033751051887902883571810921667754470616753277989433 4539341149484795033723281521701291803170133581206157279751790372163062541903 1411202633562600785638810288281580443225667903452442889326189645233595744838 8704292410919276051488657556172485434602528126371477338338731272695247871214 8531344208588042196247695295308496482430546116548334405206970596956241690495 9592823688304857706697333346755997888475028602837035242143266422559083501581 6744458763490333085563144012365643054194157661033194309985104088529575754028 2534806827228478629743216744688778020961699159280663882846234689310077081736 6024364166838206543521287616625394911441500124016866024811204707786292528961 1603281589332853085867183258825475535891673425352359526353307011017102021845 6229639266689296722655890932615138528947513810895234272775643400016991462766 4682562543427367805737384621907606506084956620139938655220574272932080283397 5080497672363160478194130557651083752225518739812293257597020321852115872321 0423508984903210022531681471604161527283425018665371038789874350824128553133 1838974789640955121321093762374555239210706518217412878830898523103817418183 7246685831115344213967160913112271567741324804620469079393138672209754183205 9576782459769012214555724662882616655925264453429317826369579546710887759595 4276881268091161226599431968684120556631276490437760589000224109022110256760 5022075066636881862874245112440744177946359096747914603998880496920718236536 5846712087804226663296973642180785685584316325681616712576674198500848437376 7270481096010523945334771956720006714196133587212624400370608940242114233954 9257662158399796716927732769103582352343826936693477382089998797977999286844 0635047656175995670212747442387427529440977381337458352545813688850563539619 3029768685508418714596477252230715588593206795794876020845605080470098683651 9496988775827449061579572659785772724941721637757846265570487428940047668565 5266879736209501456715267417789381173273996244782286259433553292793669397502 3309431808302492895087313521101191124546218312241301713223117215210051730192 4058849195801312549213512806000001 31 in base 16 == 1f %X for medium : 1D6329F1C35CA4BFB125BCBF2D63100001 %#X for medium : 0X1D6329F1C35CA4BFB125BCBF2D63100001 %x for 0: 0 %#X for 0: 0X0 %10s for "string" : string %.4s for "string" : stri %*.*s for "string" : st %s for 1 : 1 %s for aa : [1.0000000000000000000000000000000000000, 2.00000000000000000000 00000000000000000] %s for 4/3 : 4/3 %s inter %.2s %4.2f for aa, bb, aa : [1.000000000000000000000000000000000000 0, 2.0000000000000000000000000000000000000] inter 2. [1.00,2.00] "%s inter %.2s %4.2f for aa, bb, aa : [1.00000000000000000000000000000000000 00, 2.0000000000000000000000000000000000000] inter 2. [1.00,2.00]\n" %10.5s for 3.5 : 3.500 %10f for Pi : 3.1415926536| %20.10f for 2.7 : 2.7000000000| %+20.10f for 2.7: +2.7000000000| %-20.10f for 2.7: 2.7000000000 | %-*.*f for 2.7: 2.7000000000 | %20.10e for 2.7 : 2.7000000000 e0| %+20.10E for 2.7: +2.7000000000 E0| %-20.10e for 2.7: 2.7000000000 e0 | %-20.10E for ii : 1.0000000000 E100 | %e for 1+0*I : 1.0000000000000000000000000000000000000 E0 %8.3g for 3.14159: 3.14 %8.3G for ii : 1.00 E100 %8.3g for ii : 1.00 e100 %-20.10g for 4/3 : 1.333333333 | %20.13e for 4/3 : 1.3333333333333 e0| %e for 4/3 : 1.3333333333333333333333333333333333333 e0| *** at top-level: printf("%missing arg *** ^-------------------- *** printf: invalid conversion or specification m in format `%missing argument to format '. *** at top-level: printf("%d missing a *** ^-------------------- *** printf: missing arg 1 for printf format '%d missing argument to format '. %-20.10g for aa : [1.000000000 ,2.000000000 ] 1.0000000000000000000000000000000000000 E38 0.99999999999999999999999999999999999999770976478687585326332384035105970783 05024613172747796087832576 0 0.000050 b b a a [1.00] [2.00] *** at top-level: printf("%c",'x) *** ^--------------- *** printf: incorrect type in gtolong (t_POL). -0.0000000000000000000000000000000000000029387 Total time spent: 4 pari-2.7.5/src/test/32/bnfinit0000644000175000017500000000000011636712103014442 0ustar billbillpari-2.7.5/src/test/32/str0000644000175000017500000000034112366172547013646 0ustar billbillVecsmall([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}" "x" "1/2" "ab1" Total time spent: 4 pari-2.7.5/src/test/32/err0000644000175000017500000006215012405547147013630 0ustar billbill *** at top-level: g(10) *** ^----- *** in function g: for(i=-N,N,f(i)) *** ^----- *** in function f: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. *** at top-level: f(Mat(0),Col(1)) *** ^---------------- *** in function f: matsolve *** ^-------- *** matsolve: impossible inverse in gauss: Mat(0). *** at top-level: (matsolve)(Mat(0),Col *** ^-------------------- *** matsolve: impossible inverse in gauss: Mat(0). *** at top-level: g(I) *** ^---- *** in function g: [x.foo] *** ^---- *** in member function foo: 1/(1+a^2) *** ^-------- *** _/_: impossible inverse in gdiv: 0. *** at top-level: (x->1/x)(0) *** ^---------- *** in anonymous function: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. 274177 274177 *** at top-level: ...=2;A=x^2+1;B=[x+t,x+t];r=polhensellift(A,B,[p *** ^-------------------- *** polhensellift: elements not coprime in BuildTree: x + t x + t *** at top-level: M[,1]=1 *** ^------- *** incorrect type in matrix col assignment (t_INT). *** at top-level: M[,3]=1 *** ^------ *** non-existent component: index > 2 *** at top-level: M[,1]=[1,2] *** ^----------- *** incorrect type in matrix col assignment (t_VEC). *** at top-level: M[,1]=[1,2,3]~ *** ^-------------- *** inconsistent dimensions in matrix col assignment. *** at top-level: M[1,]=1 *** ^------- *** incorrect type in matrix row assignment (t_INT). *** at top-level: M[3,]=1 *** ^------ *** non-existent component: index > 2 *** at top-level: M[1,]=[1,2]~ *** ^------------ *** incorrect type in matrix row assignment (t_COL). *** at top-level: M[1,]=[1,2,3] *** ^------------- *** inconsistent dimensions in matrix row assignment. *** at top-level: [;][1,] *** ^---- *** non-existent component: index > 0 *** at top-level: [;][,1] *** ^---- *** non-existent component: index > 0 *** at top-level: 1[1] *** ^--- *** incorrect type in _[_] OCcompo1 [not a vector] (t_INT). *** at top-level: issquare(1,&v[1]) *** ^---- *** incorrect type in &_[_] OCcompo1ptr [not a vector] (t_POL). *** at top-level: 1[1,1] *** ^----- *** incorrect type in _[_,_] OCcompo2 [not a matrix] (t_INT). *** at top-level: 1[,1] *** ^---- *** incorrect type in _[,_] OCcompoC [not a matrix] (t_INT). *** at top-level: issquare(1,&v[,1]) *** ^----- *** incorrect type in &_[,_] OCcompoCptr [not a matrix] (t_POL). *** at top-level: 1[1,] *** ^---- *** incorrect type in _[_,] OCcompoL [not a matrix] (t_INT). *** at top-level: issquare(1,&v[1,]) *** ^----- *** incorrect type in &_[_,] OCcompoLptr [not a matrix] (t_POL). *** at top-level: v[2]=1 *** ^----- *** non-existent component: index > 1 *** at top-level: v[1]=Pi *** ^------- *** incorrect type in t_VECSMALL assignment (t_REAL). *** at top-level: v[1]=2^64 *** ^--------- *** incorrect type in t_VECSMALL assignment (t_INT). *** at top-level: v[Pi]=1 *** ^----- *** incorrect type in gtos [integer expected] (t_REAL). *** at top-level: M=[1.,0;0,1];qflll(M,1) *** ^---------- *** qflll: incorrect type in qflll [integer matrix] (t_MAT). *** at top-level: addprimes(1.) *** ^------------- *** addprimes: incorrect type in addprimes [integer vector] (t_VEC). *** at top-level: nfalgtobasis(nfinit( *** ^-------------------- *** nfalgtobasis: inconsistent moduli in algtobasis: t^3 - 2 != t^2 + 1 *** at top-level: vector(-1,i,0) *** ^-------------- *** vector: domain error in vector: dimension < 0 *** at top-level: vectorv(-1,i,0) *** ^--------------- *** vectorv: domain error in vector: dimension < 0 *** at top-level: vectorsmall(-1,i,0) *** ^------------------- *** vectorsmall: domain error in vectorsmall: dimension < 0 *** at top-level: matrix(-1,1,i,j,0) *** ^------------------ *** matrix: domain error in matrix: nbrows < 0 *** at top-level: matrix(1,-1,i,j,0) *** ^------------------ *** matrix: domain error in matrix: nbcols < 0 *** at top-level: next(-1) *** ^-------- *** next: domain error in next: n < 1 *** at top-level: break(-1) *** ^--------- *** break: domain error in break: n < 1 *** at top-level: v[-1] *** ^---- *** non-existent component: index < 1 *** at top-level: v[#v+1] *** ^------ *** non-existent component: index > 1 *** variable name expected: subst(x,1,0) *** ^---- *** at top-level: exp(1/x) *** ^-------- *** exp: domain error in exp: valuation < 0 *** at top-level: cos(1/x) *** ^-------- *** cos: domain error in cos: valuation < 0 *** at top-level: sin(1/x) *** ^-------- *** sin: domain error in sin: valuation < 0 *** at top-level: tan(1/x) *** ^-------- *** tan: domain error in tan: valuation < 0 *** at top-level: cotan(1/x) *** ^---------- *** cotan: domain error in cotan: valuation < 0 *** at top-level: atan(1/x) *** ^--------- *** atan: domain error in atan: valuation < 0 *** at top-level: asin(1/x) *** ^--------- *** asin: domain error in asin: valuation < 0 *** at top-level: acos(1/x) *** ^--------- *** acos: domain error in acos: valuation < 0 *** at top-level: asinh(1/x) *** ^---------- *** asinh: domain error in asinh: valuation < 0 *** at top-level: acosh(1/x) *** ^---------- *** acosh: domain error in acosh: valuation < 0 *** at top-level: atanh(1/x) *** ^---------- *** atanh: domain error in atanh: valuation < 0 *** at top-level: lngamma(x) *** ^---------- *** lngamma: domain error in lngamma: valuation != 0 *** at top-level: besselj(2,1/x) *** ^-------------- *** besselj: domain error in besselj: valuation < 0 *** at top-level: besseljh(2,1/x) *** ^--------------- *** besseljh: domain error in besseljh: valuation < 0 *** at top-level: besselk(2,1/x) *** ^-------------- *** besselk: domain error in _kbessel1: valuation < 0 *** at top-level: besselk(1/3,O(x)) *** ^----------------- *** besselk: domain error in besselk: 2n mod Z != 0 *** at top-level: besseln(2,1/x) *** ^-------------- *** besseln: domain error in _kbessel1: valuation < 0 *** at top-level: besseln(1/3,O(x)) *** ^----------------- *** besseln: domain error in besseln: 2n mod Z != 0 *** at top-level: polylog(2,1/x) *** ^-------------- *** polylog: domain error in polylog: valuation < 0 *** at top-level: sqrt(x) *** ^------- *** sqrt: domain error in sqrtn: valuation != Mod(0, 2) *** at top-level: sqrt(2+O(2^2)) *** ^-------------- *** sqrt: not an n-th power residue in Qp_sqrt: 2 + O(2^2). *** at top-level: sqrtn(x,3) *** ^---------- *** sqrtn: domain error in sqrtn: valuation != Mod(0, 3) *** at top-level: sqrtn(2+O(2^2),3) *** ^----------------- *** sqrtn: not an n-th power residue in gsqrtn: 2 + O(2^2). *** at top-level: log(x) *** ^------ *** log: domain error in log: series valuation != 0 *** at top-level: log(0) *** ^------ *** log: domain error in log: argument = 0 *** at top-level: abs(x+O(x^2)) *** ^------------- *** abs: domain error in abs: series valuation != 0 *** at top-level: vecmax([]) *** ^---------- *** vecmax: domain error in vecindexmax: empty argument = [] *** at top-level: vecmax([],&i) *** ^------------- *** vecmax: domain error in vecindexmax: empty argument = [] *** at top-level: vecmin([]) *** ^---------- *** vecmin: domain error in vecindexmin: empty argument = [] *** unexpected character '&': vecmmin([],&i) *** ^--- *** at top-level: vecmax(matrix(0,2)) *** ^------------------- *** vecmax: domain error in vecmax: empty argument = matrix(0,2) *** at top-level: listput(L,x,-1) *** ^--------------- *** listput: non-existent component in listput: index < 0 *** at top-level: listinsert(L,x,-1) *** ^------------------ *** listinsert: non-existent component in listinsert: index <= 0 *** at top-level: listinsert(L,x,10) *** ^------------------ *** listinsert: non-existent component in listinsert: index > 1 *** at top-level: ellj(Mod(1,2)) *** ^-------------- *** ellj: incorrect type in modular function (t_INTMOD). *** at top-level: ellj(Qfb(1,1,1)) *** ^---------------- *** ellj: incorrect type in ellj (t_QFI). *** at top-level: eta(1+O(2)) *** ^----------- *** eta: domain error in eta: v_p(q) <= 0 *** at top-level: eta(1/x) *** ^-------- *** eta: domain error in eta: v_p(q) <= 0 *** at top-level: idealhnf(K,Qfb(1,1,1 *** ^-------------------- *** idealhnf: domain error in idealhnf [Qfb]: disc(q) != -4 *** at top-level: idealfactor(K,[;]) *** ^------------------ *** idealfactor: domain error in idealfactor: ideal = 0 *** at top-level: idealdiv(K,2,0,1) *** ^----------------- *** idealdiv: impossible inverse in idealdivexact: 0. *** at top-level: valuation(Pi,2) *** ^--------------- *** valuation: inconsistent valuation t_REAL , t_INT. *** at top-level: x^Pi *** ^--- *** _^_: domain error in gpow [irrational exponent]: valuation != 0 *** at top-level: x^x *** ^-- *** _^_: domain error in gpow [irrational exponent]: valuation != 0 *** at top-level: 0^0. *** ^--- *** _^_: domain error in gpow(0,n): n <= 0 *** at top-level: agm([],[]) *** ^---------- *** agm: forbidden agm t_VEC (0 elts) , t_VEC (0 elts). *** at top-level: sin(1/2+O(2^1)) *** ^--------------- *** sin: domain error in gsin(t_PADIC): argument out of range *** at top-level: cos(1/9+O(3^1)) *** ^--------------- *** cos: domain error in gcos(t_PADIC): argument out of range *** at top-level: exp(1/9+O(3^1)) *** ^--------------- *** exp: domain error in gexp(t_PADIC): argument out of range *** at top-level: ...],Vecsmall([2,2,2,2,3])];galoissubgroups(G) *** ^------------------ *** galoissubgroups: sorry, group_quotient for a non-WSS group is not yet implemented. *** at top-level: bnrstark(bnrinit(bnf *** ^-------------------- *** bnrstark: domain error in bnrstark: r2 != 0 *** at top-level: bnrstark(bnrinit(bnf *** ^-------------------- *** bnrstark: domain error in bnrstark: r2(class field) != 0 *** at top-level: quadray(-16,1) *** ^-------------- *** quadray: domain error in quadray: isfundamental(D) = 0 *** at top-level: quadray(bnfinit(x^3- *** ^-------------------- *** quadray: domain error in quadray: degree != 2 *** at top-level: galoissubcyclo(-1) *** ^------------------ *** galoissubcyclo: domain error in galoissubcyclo: degree <= 0 *** at top-level: galoissubcyclo(6,Mod *** ^-------------------- *** galoissubcyclo: inconsistent moduli in galoissubcyclo: 6 != 3 *** at top-level: galoissubcyclo(6,[;] *** ^-------------------- *** galoissubcyclo: incorrect type in galoissubcyclo [H not in HNF] (t_MAT). *** at top-level: galoissubcyclo(6,Mat *** ^-------------------- *** galoissubcyclo: incorrect type in galoissubcyclo [N not a bnrinit or znstar] (t_MAT). *** at top-level: galoissubcyclo(znsta *** ^-------------------- *** galoissubcyclo: inconsistent dimensions in galoissubcyclo. *** at top-level: galoissubcyclo(bnrin *** ^-------------------- *** galoissubcyclo: domain error in bnr_to_znstar: bnr != Q *** at top-level: polsubcyclo(-1,2) *** ^----------------- *** polsubcyclo: domain error in polsubcyclo: n <= 0 *** at top-level: polsubcyclo(2,-1) *** ^----------------- *** polsubcyclo: domain error in polsubcyclo: d <= 0 *** at top-level: random(-1) *** ^---------- *** random: domain error in random: N <= 0 *** at top-level: znprimroot(0) *** ^------------- *** znprimroot: domain error in znprimroot: argument = 0 *** at top-level: sqrtint(-1) *** ^----------- *** sqrtint: domain error in sqrtint: argument < 0 *** at top-level: sqrtnint(-1,2) *** ^-------------- *** sqrtnint: domain error in sqrtnint: x < 0 *** at top-level: sqrtnint(2,-2) *** ^-------------- *** sqrtnint: domain error in sqrtnint: n <= 0 *** at top-level: znprimroot(8) *** ^------------- *** znprimroot: domain error in znprimroot: argument = 8 *** at top-level: polroots(x^2+Mod(1,2 *** ^-------------------- *** polroots: incorrect type in roots (t_INTMOD). *** at top-level: prime(-2) *** ^--------- *** prime: domain error in prime: n <= 0 *** at top-level: addprimes(-1) *** ^------------- *** addprimes: domain error in addprimes: p < 2 *** at top-level: padicappr(x^2+1+O(3^ *** ^-------------------- *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3 *** at top-level: factorpadic(x^2+1,2, *** ^-------------------- *** factorpadic: domain error in factorpadic: precision <= 0 *** at top-level: polrootspadic(x^2+1, *** ^-------------------- *** polrootspadic: domain error in rootpadic: precision <= 0 *** at top-level: ellinit([1+O(3),1+O( *** ^-------------------- *** ellinit: inconsistent moduli in ellinit: 3 != 5 *** at top-level: ellwp([1,I],I) *** ^-------------- *** ellwp: domain error in ellwp: argument = 0 *** at top-level: ellsigma([1,I],x,1) *** ^------------------- *** ellsigma: incorrect type in log(ellsigma) (t_SER). *** at top-level: ellsigma([1,I],1,1) *** ^------------------- *** ellsigma: domain error in log(ellsigma): argument = 0 *** at top-level: ellap(E) *** ^-------- *** ellap: incorrect type in ellap [can't determine p] (t_VEC). *** at top-level: ellap(E,1) *** ^---------- *** ellap: domain error in ellap: p < 2 *** at top-level: ellap(E,'x) *** ^----------- *** ellap: incorrect type in ellap (t_POL). *** at top-level: elltaniyama(E,-1) *** ^----------------- *** elltaniyama: domain error in elltaniyama: precision < 0 *** at top-level: ellheight(E,[2,2]) *** ^------------------ *** ellheight: domain error in ellheight: point not on E *** at top-level: Qfb(0,0,0) *** ^---------- *** Qfb: domain error in Qfb: issquare(disc) = 1 *** at top-level: quadpoly(2) *** ^----------- *** quadpoly: domain error in quadpoly: disc % 4 > 1 *** at top-level: qfbprimeform(2,5) *** ^----------------- *** qfbprimeform: domain error in primeform: disc % 4 > 1 *** at top-level: qfbcomp(Qfb(1,1,1),Q *** ^-------------------- *** not a function in function call *** at top-level: galoisinit(x^2) *** ^--------------- *** galoisinit: domain error in galoisinit: issquarefree(pol) = 0 *** at top-level: galoisinit(2*x) *** ^--------------- *** galoisinit: sorry, galoisinit(non-monic) is not yet implemented. *** at top-level: ellL1(1,-1) *** ^----------- *** ellL1: domain error in ellL1: derivative order < 0 *** at top-level: ellheegner(ellinit([ *** ^-------------------- *** ellheegner: domain error in ellheegner: (analytic rank)%2 = 0 *** at top-level: ellheegner(ellinit([ *** ^-------------------- *** ellheegner: domain error in ellheegner: analytic rank > 1 *** at top-level: substpol(x+O(x^2),x^ *** ^-------------------- *** substpol: domain error in gdeflate: valuation(x) % 3 != 0 *** at top-level: intformal(1/(x^2+1)) *** ^-------------------- *** intformal: domain error in intformal: residue(series, pole) != 0 *** at top-level: component(x,-1) *** ^--------------- *** component: non-existent component: index < 1 *** at top-level: component(O(x),2) *** ^----------------- *** component: non-existent component: index > 1 *** at top-level: component(Vecsmall([ *** ^-------------------- *** component: non-existent component: index > 0 *** at top-level: polcoeff(O(x),2) *** ^---------------- *** polcoeff: domain error in polcoeff: t_SER = O(x) *** at top-level: polcoeff(x+O(x^2),2) *** ^-------------------- *** polcoeff: domain error in polcoeff: degree > 1 *** at top-level: polcoeff([],2) *** ^-------------- *** polcoeff: non-existent component in polcoeff: index > 0 *** at top-level: polcoeff([],-1) *** ^--------------- *** polcoeff: non-existent component in polcoeff: index < 1 *** at top-level: polcoeff("",2) *** ^-------------- *** polcoeff: incorrect type in polcoeff (t_STR). *** at top-level: matcompanion(0*x) *** ^----------------- *** matcompanion: domain error in matcompanion: polynomial = 0 *** at top-level: matrixqz(Mat([1,2])) *** ^-------------------- *** matrixqz: domain error in QM_minors_coprime: n > m *** at top-level: matrixqz(Mat(0)) *** ^---------------- *** matrixqz: domain error in QM_minors_coprime: rank(A) < 1 *** at top-level: vecextract([1],[-1]) *** ^-------------------- *** vecextract: non-existent component in vecextract: index <= 0 *** at top-level: vecextract([1],[2]) *** ^------------------- *** vecextract: non-existent component in vecextract: index >= 2 *** at top-level: idealfrobenius(K,gal *** ^-------------------- *** idealfrobenius: domain error in idealfrobenius: pr.e > 1 *** at top-level: nfisincl(x^2,x^2) *** ^----------------- *** nfisincl: not an irreducible polynomial in nfisincl: x^2. *** at top-level: polcompositum(x^2,x) *** ^-------------------- *** polcompositum: domain error in polcompositum: issquarefree(arg) = 0 *** at top-level: rnfdedekind(K,x^2+x- *** ^-------------------- *** rnfdedekind: incorrect type in rnfdedekind [non integral pol] (t_POL). *** at top-level: hilbert(Mod(1,2),1) *** ^------------------- *** hilbert: precision too low in hilbert. *** at top-level: hilbert(Mod(1,3),Mod *** ^-------------------- *** hilbert: inconsistent moduli in hilbert: 5 != 3 *** at top-level: hilbert(Mod(1,3),2,0 *** ^-------------------- *** hilbert: inconsistent moduli in hilbert: 3 != oo *** at top-level: znorder(0) *** ^---------- *** znorder: incorrect type in znorder [t_INTMOD expected] (t_INT). *** at top-level: znorder(Mod(2,4)) *** ^----------------- *** znorder: elements not coprime in znorder: 2 4 *** at top-level: contfrac(1e100) *** ^--------------- *** contfrac: precision too low in gboundcf. *** at top-level: contfrac(1.,[1],10) *** ^------------------- *** contfrac: inconsistent dimensions in contfrac [too few denominators]. *** at top-level: contfrac(1,,-1) *** ^--------------- *** contfrac: domain error in gboundcf: nmax < 0 *** at top-level: contfracpnqn(matrix( *** ^-------------------- *** contfracpnqn: inconsistent dimensions in pnqn [ nbrows != 1,2 ]. *** at top-level: divisors(1/2) *** ^------------- *** divisors: incorrect type in divisors [denominator] (t_FRAC). *** at top-level: idealstar(K,0) *** ^-------------- *** idealstar: domain error in Idealstar: ideal = 0 *** at top-level: idealstar(K,1/2) *** ^---------------- *** idealstar: domain error in Idealstar: denominator(ideal) != 1 *** at top-level: idealaddtoone(K,[[;] *** ^-------------------- *** idealaddtoone: domain error in idealaddmultoone: sum(ideals) != 1 *** at top-level: idealdiv(K,1,2,1) *** ^----------------- *** idealdiv: domain error in idealdivexact: denominator(x/y) != 1 *** at top-level: idealred(K,matid(2), *** ^-------------------- *** idealred: inconsistent dimensions in idealred. *** at top-level: idealtwoelt(K,matid( *** ^-------------------- *** idealtwoelt: domain error in idealtwoelt2: element mod ideal != 0 *** at top-level: rnf=rnfinit(K,x^2-y);rnfeltdown(rnf,x) *** ^----------------- *** rnfeltdown: domain error in rnfeltdown: element not in the base field *** at top-level: matid(-1) *** ^--------- *** matid: domain error in matid: size < 0 *** at top-level: polinterpolate([1,1] *** ^-------------------- *** polinterpolate: domain error in polinterpolate: X[1] = X[2] *** 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). *** at top-level: concat([]) *** ^---------- *** concat: domain error in concat: vector = [] *** at top-level: concat(List()) *** ^-------------- *** concat: domain error in concat: vector = List([]) *** at top-level: mathnfmod([1;2],2) *** ^------------------ *** mathnfmod: domain error in ZM_hnfmod: nb lines > nb columns *** at top-level: polsturm(x^2) *** ^------------- *** polsturm: domain error in polsturm: issquarefree(pol) = 0 *** at top-level: removeprimes(2) *** ^--------------- *** removeprimes: domain error in removeprime: prime not in primetable *** at top-level: forstep(a=1,2,0,) *** ^----------------- *** domain error in forstep: step = 0 *** at top-level: e.omega *** ^----- *** _.omega: incorrect type in omega [not defined over C] (t_VEC). *** at top-level: e.eta *** ^--- *** _.eta: incorrect type in eta [not defined over C] (t_VEC). *** at top-level: e.area *** ^---- *** _.area: incorrect type in area [not defined over C] (t_VEC). *** at top-level: e.tate *** ^---- *** _.tate: incorrect type in tate [not defined over Qp] (t_VEC). *** at top-level: ellorder(e,[0,0]*Mod *** ^-------------------- *** ellorder: sorry, ellorder for curve with singular reduction is not yet implemented. *** at top-level: thue(x*(x^3-2),0) *** ^----------------- *** thue: domain error in thue: #sols = oo *** at top-level: direuler(p=2,10,2/(1-p*X)) *** ^---------- *** domain error in direuler: constant term != 1 *** at top-level: solve(x=0,1,x^2+1) *** ^------ *** domain error in solve: f(a)f(b) > 0 *** user warning: 1 (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 pari-2.7.5/src/test/32/sumiter0000644000175000017500000000232412366172547014531 0ustar billbill realprecision = 19 significant digits echo = 1 (on) ? intnum(x=0,Pi,sin(x)) 2.000000000000000000 ? intnum(x=0,4,exp(-x^2)) 0.8862269117895689458 ? intnum(x=1,[1],1/(1+x^2))-Pi/4 0.E-19 ? intnum(x=-0.5,0.5,1/sqrt(1-x^2))-Pi/3 0.E-18 ? intnum(x=0,[[1],-I],sin(x)/x)-Pi/2 0.E-18 ? \p38 realprecision = 38 significant digits ? prod(k=1,10,1+1/k!) 3335784368058308553334783/905932868585678438400000 ? prod(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 ? prodinf(n=0,-2^-n/(1+2^(-n+1)),1) 0.33333333333333333333333333333333333329 ? solve(x=1,4,sin(x)) 3.1415926535897932384626433832795028842 ? sum(k=1,10,2^-k) 1023/1024 ? sum(k=1,10,2.^-k) 0.99902343750000000000000000000000000000 ? 4*sumalt(n=0,(-1)^n/(2*n+1)) 3.1415926535897932384626433832795028842 ? 4*sumalt(n=0,(-1)^n/(2*n+1),1) 3.1415926535897932384626433832795028842 ? sumdiv(8!,x,x) 159120 ? suminf(n=1,2.^-n) 0.99999999999999999999999999999999999999 ? 6/Pi^2*sumpos(n=1,n^-2) 1.0000000000000000000000000000000000000 ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.7.5/src/test/32/disc0000644000175000017500000000003612314242551013743 0ustar billbillMod(1, 2) Total time spent: 4 pari-2.7.5/src/test/32/ffisom0000644000175000017500000000410612366172547014324 0ustar billbill-------------e=0-------------- [0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -------------e=1-------------- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -------------e=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, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -------------e=3-------------- [0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -------------e>=4-------------- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ----------large p--------------- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ----------huge p--------------- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0] Total time spent: 300 pari-2.7.5/src/test/32/zetak0000644000175000017500000000361412571637201014151 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 0.38333333333333333333333333333333333333 1.1900844397698990786847627856353764894 1.5621990258332796845160673535794981916 0 0.52829297004121867318219948972250171261 - 0.6001012794792921690364554072200 6732485*I 0 1.0626469254716411511118505129747317450 1.2851909554841494029175117986995746040 -1/6 0.27507533904957993693083735106782913088 - 0.3452281589507528653748718471820 1732549*I 19.233333333333333333333333333333333333 1.1534151088973390171523689045164417703 1.4238865750458932917520934583801572803 0 0.75988495679933103986934747406595883227 - 0.2667106768393931037951306887756 2967178*I 0 1.1979816549838251284996760656144424126 1.6026632619004405990075072278650989584 0 0.56325049211603379810700612339514262331 - 0.7431218796586144471407060306283 8684011*I 0 1.1897132625253515180121146266710359469 1.5629865407014105763649713127143672948 0 0.080540708067958142852744201044408963832 - 0.799351155467781709752299811229 26087752*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 1.0000000000000000000000000000000000000 1.0000000000000000000000000000000000000 1.0000000000000000000000000000007888609 1.0000000004656629065033784072989233251 1.0000000000000000000000000000007731864 - 1.56474806799752292404311992386390 49803 E-31*I 1.0000000000000000006672083904260744090 - 5.54210563151691387135805391417775 67374 E-19*I -1.8236338315400224657144248914124703368 E1769 + 6.8223788001755144705322033 655798283436 E1768*I 2^-1 + 1 + 2^2 + 2^3 + 2^5 + 2^6 + 2^7 + O(2^9) 1.0000000000000000000000000000000000000 0.E-38 error("overflow in zeta [large negative argument].") 1.6449340668482264364724151666460251892 - 9.37548254315843753702574094567864 97790 E-102*I 100.57794333849687249028215428579024415 -0.50000000000000000000000000000000918939 Total time spent: 1680 pari-2.7.5/src/test/32/concat0000644000175000017500000000233512366172547014312 0ustar billbill [1 2 5] [3 4 6] [1 2] [3 4] [7 8] [1 2 5] [3 4 6] [7 8 9] [1 2 4] [0 3 5] [0 0 6] [1 0 0] [2 3 0] [4 5 6] [5 0 7 8] [6 0 0 0] [1 2 9 0] [3 4 0 9] [;] "x2" [1] [;] *** at top-level: concat([;],[1]) *** ^--------------- *** concat: inconsistent concatenation t_MAT (0x0) , t_VEC (1 elts). [1] [;] *** at top-level: concat([1],[;]) *** ^--------------- *** concat: inconsistent concatenation t_VEC (1 elts) , t_MAT (0x0). [1, 2] [1, 2] [1 2] *** at top-level: concat(1,A) *** ^----------- *** concat: inconsistent concatenation t_INT , t_MAT (2x2). [2 1] *** at top-level: concat(A,1) *** ^----------- *** concat: inconsistent concatenation t_MAT (2x2) , t_INT. [1, 2] [1, 2, 1] *** at top-level: concat([1,2],[1,2]~) *** ^-------------------- *** concat: inconsistent concatenation t_VEC (2 elts) , t_COL (2 elts). [2 3] [1 0] [0 1] [1, 2] [3, 1, 2] [2, 3]~ [2, 3, 1]~ *** at top-level: concat([2,3]~,[1,2]) *** ^-------------------- *** concat: inconsistent concatenation t_COL (2 elts) , t_VEC (2 elts). [;] [1 2] [3 4] [1 2] [1, 2] [1 2] Total time spent: 0 pari-2.7.5/src/test/32/ser0000644000175000017500000000321212601623017013610 0ustar billbillx + 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) 1 + O(x^2) 1 O(x^0) 2*x + O(x^2) 2*x - 8/3*x^3 + 32/5*x^5 - 128/7*x^7 + 512/9*x^9 - 2048/11*x^11 + 8192/13*x^ 13 - 32768/15*x^15 + O(x^17) y + x + O(x^2) (y + O(y^17)) + (1 + O(y^16))*x + O(x^2) *** at top-level: Ser("") *** ^------- *** Ser: incorrect type in gtoser (t_STR). Total time spent: 0 pari-2.7.5/src/test/32/ellff0000644000175000017500000000011112366172547014121 0ustar billbill93 88 [0] [0] Mod(1, 2)*a1^2*x^2 + Mod(1, 2)*a3^2 Total time spent: 8029 pari-2.7.5/src/test/32/exact00000644000175000017500000000124711636712103014213 0ustar billbill *** at top-level: Mod(0,2)*x*1. *** ^--- *** _*_: forbidden multiplication t_REAL * t_INTMOD. Mod(0, 2) Mod(0, 2) Mod(0, 2)*x^15 + O(x^16) Mod(2, 4) + Mod(0, 4)*I Mod(0, 4) + Mod(0, 4)*I Mod(1, 2) + Mod(0, 2)*I Mod(0, 2) Mod(0, 2) Mod(0, 2) 1 Mod(0, 5) Mod(0, 5) 0 0 O(x^4) 0 0 O(x^4) Mod(0, 2) Mod(0, 2) Mod(0, 2)*x^3 + O(x^4) Mod(0, 2) Mod(0, 2) Mod(0, 2)*x^3 + O(x^4) x^3 1 1 + O(x^4) 1 x^3 x^3 + O(x^4) x^3 + 0.E-38*x 0.E-38*x^2 + 1 1 + 0.E-38*x^2 + O(x^4) 0.E-38*x^2 + 1 x^3 + 0 .E-38*x 0.E-38*x + x^3 + O(x^4) x^3 + 0.E-38 0.E-38*x^3 + 1 1 + 0.E-38*x^3 + O(x^4) 0.E-38*x^3 + 1 x^3 + 0.E -38 0.E-38 + x^3 + O(x^4) Total time spent: 8 pari-2.7.5/src/test/32/sumformal0000644000175000017500000000040512314242551015026 0ustar billbill *** at top-level: sumformal(1/n) *** ^-------------- *** sumformal: incorrect type in sumformal [not a t_POL] (t_RFRAC). 0 x 1/2*n^2 + 1/2*n 1/3*n^3 + 1/2*n^2 + 1/6*n 1/2*y*x^2 + (1/2*y + 1)*x (1/2*y^2 + 1/2*y)*x + y Total time spent: 4 pari-2.7.5/src/test/32/ranges0000644000175000017500000000405412413013143014275 0ustar billbill[1267650600228229401496703205376, 1267650600228229401496703205377, 126765060 0228229401496703205378, 1267650600228229401496703205379] [5, 10, 26, 50, 122, 170, 290, 362, 530, 842, 962, 1370] [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] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] [2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 5, 13, 29, 53, 85, 10, 13, 25, 34, 5 8, 73, 109, 17, 25, 41, 65, 97, 26, 29, 34, 41, 61, 74, 89, 106, 37, 61, 85, 50, 53, 58, 65, 74, 85, 113, 130, 149, 65, 73, 89, 113, 145, 82, 85, 97, 10 6, 130, 145, 181, 101, 109, 149, 181] [13, 29, 53, 13, 34, 58, 29, 34, 74, 53, 58, 74] [[1, 1, 1], [2, 1, 1], [2, 2, 1], [2, 2, 2], [3, 1, 1], [3, 2, 1], [3, 2, 2] , [3, 3, 1], [3, 3, 2], [3, 3, 3], [4, 1, 1], [4, 2, 1], [4, 2, 2], [4, 3, 1 ], [4, 3, 2], [4, 3, 3], [4, 4, 1], [4, 4, 2], [4, 4, 3], [4, 4, 4], [5, 1, 1], [5, 2, 1], [5, 2, 2], [5, 3, 1], [5, 3, 2], [5, 3, 3], [5, 4, 1], [5, 4, 2], [5, 4, 3], [5, 4, 4], [5, 5, 1], [5, 5, 2], [5, 5, 3], [5, 5, 4], [5, 5 , 5]] [7, 11, 13, 17] [2, 3] [1, 2, 3, 4] [3, 4, 5] [1, 2, 4, 5] Vecsmall([2, 3]) Vecsmall([1, 2, 3, 4]) Vecsmall([3, 4, 5]) Vecsmall([1, 2, 4, 5]) [7 12] [8 13] [1, 2]~ [1, 6, 11, 16] [1 6 11 16 21] [2 7 12 17 22] [3 8 13 18 23] [1 6 11] [2 7 12] [3 8 13] [4 9 14] [5 10 15] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [5 10 15 20] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [13 18 23] [14 19 24] [15 20 25] [ 6 11] [ 7 12] [ 9 14] [10 15] [1, 3, 4, 5]~ [1, 6, 11, 21] [1 6 11 16 21] [2 7 12 17 22] [4 9 14 19 24] [5 10 15 20 25] [1 6 16 21] [2 7 17 22] [3 8 18 23] [4 9 19 24] [5 10 20 25] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [1 6 11 21] [2 7 12 22] [3 8 13 23] [4 9 14 24] [13 18 23] [14 19 24] [15 20 25] [1, [2, 2]] [3, [1, 4]] [0, 3, 4, [3, 4], 0, I] [0, 3, 4, [3, 4], 0, I] [] [2, 3, 3, 4, 4, 4, 5, 5, 5, 5] [2, 3, 3, 4, 4, 4, 5, 5, 5, 5] [0, 1, 2, 3, 4, 5] Total time spent: 0 pari-2.7.5/src/test/32/prime0000644000175000017500000000061512413013143014131 0ustar billbill8161 17863 38873 84017 180503 386093 821641 1742537 3681131 7754077 16290047 172 309 564 1028 1900 3512 6542 12251 23000 43390 82025 155611 295947 56416 3 1077871 2063689 3957809 8161 17863 38873 84017 180503 386093 821641 1742537 3681131 7754077 16290047 172 309 564 1028 1900 3512 6542 12251 23000 43390 82025 155611 295947 56416 3 1077871 2063689 3957809 203280221 0 Total time spent: 1204 pari-2.7.5/src/test/32/set0000644000175000017500000000077612366172547013645 0ustar billbill[1, 2, 3] [] [1, 2, 3] List([1, 2, 3]) [1] [-2, 1, 3, 5, 7, x, "1"] [-5, 2, 5, 7, "1"] [5, 7, "1"] 0 1 [-2, 1, 3, x] 3 7 0 3 *** at top-level: setsearch(1,3) *** ^-------------- *** setsearch: incorrect type in setsearch (t_INT). [-5, -2, 1, 2, 3, 5, 7, x, "1"] [3, 4, 5, 6, 7] [2, 3, 4, 5, 6] *** at top-level: setbinop(x->x,X) *** ^---------------- *** setbinop: incorrect type in setbinop [function needs exactly 2 arguments] (t_CLOSURE). Total time spent: 4 pari-2.7.5/src/test/32/polygonal0000644000175000017500000000000012314242551015014 0ustar billbillpari-2.7.5/src/test/32/det0000644000175000017500000000060012366172547013610 0ustar billbill2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 Total time spent: 8 pari-2.7.5/src/test/32/number0000644000175000017500000001302112366172547014325 0ustar billbill echo = 1 (on) ? addprimes([nextprime(10^9),nextprime(10^10)]) [1000000007, 10000000019] ? bestappr(Pi,10000) 355/113 ? gcdext(123456789,987654321) [-8, 1, 9] ? bigomega(12345678987654321) 8 ? binomial(1.1,5) -0.0045457500000000000000000000000000000000 ? chinese(Mod(7,15),Mod(13,21)) Mod(97, 105) ? content([123,456,789,234]) 3 ? contfrac(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] ? contfrac(Pi,5) [3, 7, 15, 1, 292] ? contfrac((exp(1)-1)/(exp(1)+1),[1,3,5,7,9]) [0, 6, 10, 42, 30] ? contfracpnqn([2,6,10,14,18,22,26]) [19318376 741721] [ 8927353 342762] ? contfracpnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1]) [34 21] [21 13] ? core(54713282649239) 5471 ? core(54713282649239,1) [5471, 100003] ? coredisc(54713282649239) 21884 ? coredisc(54713282649239,1) [21884, 100003/2] ? 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] ? eulerphi(257^2) 65792 ? factor(17!+1) [ 661 1] [ 537913 1] [1000357 1] ? factor(100!+1,0) [101 1] [14303 1] [149239 1] [432885273849892962613071800918658949059679308685024481795740765527568493010 727023757461397498800981521440877813288657839195622497225621499427628453 1] ? factor(40!+1,100000) [ 41 1] [ 59 1] [ 277 1] [1217669507565553887239873369513188900554127 1] ? factorback(factor(12354545545)) 12354545545 ? factor(230873846780665851254064061325864374115500032^6) [ 2 120] [ 3 6] [ 7 6] [ 23 6] [ 29 6] [500501 36] ? factorcantor(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(factorff(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] ? 10! 3628800 ? factorial(10) 3628800.0000000000000000000000000000000 ? factormod(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] ? factormod(x^11+1,7,1) [ 1 1] [10 1] ? setrand(1);ffinit(2,11) Mod(1, 2)*x^11 + Mod(1, 2)*x^10 + Mod(1, 2)*x^8 + Mod(1, 2)*x^4 + Mod(1, 2)* x^3 + Mod(1, 2)*x^2 + Mod(1, 2) ? setrand(1);ffinit(7,4) Mod(1, 7)*x^4 + Mod(1, 7)*x^3 + Mod(1, 7)*x^2 + Mod(1, 7)*x + Mod(1, 7) ? fibonacci(100) 354224848179261915075 ? gcd(12345678,87654321) 9 ? gcd(x^10-1,x^15-1) x^5 - 1 ? hilbert(2/3,3/4,5) 1 ? hilbert(Mod(5,7),Mod(6,7)) 1 ? isfundamental(12345) 1 ? isprime(12345678901234567) 0 ? ispseudoprime(73!+1) 1 ? issquare(12345678987654321) 1 ? issquarefree(123456789876543219) 0 ? kronecker(5,7) -1 ? kronecker(3,18) 0 ? lcm(15,-21) 105 ? lift(chinese(Mod(7,15),Mod(4,21))) 67 ? modreverse(Mod(x^2+1,x^3-x-1)) Mod(x^2 - 3*x + 2, x^3 - 5*x^2 + 8*x - 5) ? moebius(3*5*7*11*13) -1 ? nextprime(100000000000000000000000) 100000000000000000000117 ? numdiv(2^99*3^49) 5000 ? omega(100!) 25 ? precprime(100000000000000000000000) 99999999999999999999977 ? prime(100) 541 ? 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] ? qfbclassno(-12391) 63 ? qfbclassno(1345) 6 ? qfbclassno(-12391,1) 63 ? qfbclassno(1345,1) 6 ? Qfb(2,1,3)*Qfb(2,1,3) Qfb(2, -1, 3) ? qfbcompraw(Qfb(5,3,-1,0.),Qfb(7,1,-1,0.)) Qfb(35, 43, 13, 0.E-38) ? qfbhclassno(2000003) 357 ? qfbnucomp(Qfb(2,1,9),Qfb(4,3,5),3) Qfb(2, -1, 9) ? form=Qfb(2,1,9);qfbnucomp(form,form,3) Qfb(4, -3, 5) ? qfbnupow(form,111) Qfb(2, -1, 9) ? qfbpowraw(Qfb(5,3,-1,0.),3) Qfb(125, 23, 1, 0.E-38) ? qfbprimeform(-44,3) Qfb(3, 2, 4) ? qfbred(Qfb(3,10,12),,-1) Qfb(3, -2, 4) ? qfbred(Qfb(3,10,-20,1.5)) Qfb(3, 16, -7, 1.5000000000000000000000000000000000000) ? qfbred(Qfb(3,10,-20,1.5),2,,18) Qfb(3, 16, -7, 1.5000000000000000000000000000000000000) ? qfbred(Qfb(3,10,-20,1.5),1) Qfb(-20, -10, 3, 2.1074451073987839947135880252731470616) ? qfbred(Qfb(3,10,-20,1.5),3,,18) Qfb(-20, -10, 3, 1.5000000000000000000000000000000000000) ? quaddisc(-252) -7 ? quadgen(-11) w ? quadpoly(-11) x^2 - x + 3 ? quadregulator(17) 2.0947125472611012942448228460655286535 ? quadunit(17) 3 + 2*w ? sigma(100) 217 ? sigma(100,2) 13671 ? sigma(100,-3) 1149823/1000000 ? sqrtint(10!^2+1) 3628800 ? znorder(Mod(33,2^16+1)) 2048 ? forprime(p=2,100,print(p," ",lift(znprimroot(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 ? znstar(3120) [768, [12, 4, 4, 2, 2], [Mod(2641, 3120), Mod(2341, 3120), Mod(2497, 3120), Mod(391, 3120), Mod(2081, 3120)]] ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 24 pari-2.7.5/src/test/32/lambert0000644000175000017500000000127612405547147014470 0ustar billbill *** at top-level: do(-1) *** ^------ *** in function do: my(x=lambertw(y));exp(x)* *** ^-------------------- *** lambertw: domain error in Lw: y < 0 *** at top-level: do(I) *** ^----- *** in function do: my(x=lambertw(y));exp(x)* *** ^-------------------- *** lambertw: sorry, lambert(t_COMPLEX) is not yet implemented. 1.0000000000000000000000000000000000000 0.99999999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999 Total time spent: 0 pari-2.7.5/src/test/32/partition0000644000175000017500000001016112366172547015050 0ustar billbill1 8646071025430235692572306890072717030146724518193248646261116875039232350406 4122598473575016156709489555875867462346177817327218448788050480708550298957 4471483457937988438791783450144642834886864800778387328738323763398284354678 2467335026575150468969 1315427338504929671669092893786176891908548434593143202526362264344662102688 7135460507830403502328150530572701695452361942348769947362008712123081217734 3187588697310977671154801113558915889945842493651964099879750098080254447377 4788789260448084624118833910204856780861639068659823549617824714773817253043 9615105518523078574457183315543226124650052897717744601504125318067437912564 426796827005538082281337283642237399241533 *** at top-level: numbpart(10^15+2) *** ^----------------- *** numbpart: overflow in numbpart [n < 10^15]. [Vecsmall([])] [Vecsmall([1])] [Vecsmall([9]), Vecsmall([1, 8]), Vecsmall([2, 7]), Vecsmall([3, 6]), Vecsma ll([4, 5]), Vecsmall([1, 1, 7]), Vecsmall([1, 2, 6]), Vecsmall([1, 3, 5]), V ecsmall([1, 4, 4]), Vecsmall([2, 2, 5]), Vecsmall([2, 3, 4]), Vecsmall([3, 3 , 3]), Vecsmall([1, 1, 1, 6]), Vecsmall([1, 1, 2, 5]), Vecsmall([1, 1, 3, 4] ), Vecsmall([1, 2, 2, 4]), Vecsmall([1, 2, 3, 3]), Vecsmall([2, 2, 2, 3]), V ecsmall([1, 1, 1, 1, 5]), Vecsmall([1, 1, 1, 2, 4]), Vecsmall([1, 1, 1, 3, 3 ]), Vecsmall([1, 1, 2, 2, 3]), Vecsmall([1, 2, 2, 2, 2]), Vecsmall([1, 1, 1, 1, 1, 4]), Vecsmall([1, 1, 1, 1, 2, 3]), Vecsmall([1, 1, 1, 2, 2, 2]), Vecs mall([1, 1, 1, 1, 1, 1, 3]), Vecsmall([1, 1, 1, 1, 1, 2, 2]), Vecsmall([1, 1 , 1, 1, 1, 1, 1, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 1, 1])] [Vecsmall([3, 3, 3]), Vecsmall([1, 2, 3, 3]), Vecsmall([2, 2, 2, 3]), Vecsma ll([1, 1, 1, 3, 3]), Vecsmall([1, 1, 2, 2, 3]), Vecsmall([1, 2, 2, 2, 2]), V ecsmall([1, 1, 1, 1, 2, 3]), Vecsmall([1, 1, 1, 2, 2, 2]), Vecsmall([1, 1, 1 , 1, 1, 1, 3]), Vecsmall([1, 1, 1, 1, 1, 2, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 1, 1])] [] [] [1, 4] [2, 3] [1, 1, 3] [1, 2, 2] [0, 0, 1, 4] [0, 0, 2, 3] [0, 1, 1, 3] [0, 1, 2, 2] [1, 1, 1, 2] 451276 [9] [1, 8] [2, 7] [3, 6] [4, 5] [1, 1, 7] [1, 2, 6] [1, 3, 5] [1, 4, 4] [2, 2, 5] [2, 3, 4] [3, 3, 3] [1, 1, 1, 6] [1, 1, 2, 5] [1, 1, 3, 4] [1, 2, 2, 4] [1, 2, 3, 3] [2, 2, 2, 3] [1, 1, 1, 1, 5] [1, 1, 1, 2, 4] [1, 1, 1, 3, 3] [1, 1, 2, 2, 3] [1, 2, 2, 2, 2] [1, 1, 1, 1, 1, 4] [1, 1, 1, 1, 2, 3] [1, 1, 1, 2, 2, 2] [1, 1, 1, 1, 1, 1, 3] [1, 1, 1, 1, 1, 2, 2] [1, 1, 1, 1, 1, 1, 1, 2] [1, 1, 1, 1, 1, 1, 1, 1, 1] [11] [1, 10] [2, 9] [3, 8] [4, 7] [5, 6] [1, 1, 9] [1, 2, 8] [1, 3, 7] [1, 4, 6] [1, 5, 5] [2, 2, 7] [2, 3, 6] [2, 4, 5] [3, 3, 5] [3, 4, 4] [1, 1, 1, 8] [1, 1, 2, 7] [1, 1, 3, 6] [1, 1, 4, 5] [1, 2, 2, 6] [1, 2, 3, 5] [1, 2, 4, 4] [1, 3, 3, 4] [2, 2, 2, 5] [2, 2, 3, 4] [2, 3, 3, 3] [1, 1, 1, 1, 7] [1, 1, 1, 2, 6] [1, 1, 1, 3, 5] [1, 1, 1, 4, 4] [1, 1, 2, 2, 5] [1, 1, 2, 3, 4] [1, 1, 3, 3, 3] [1, 2, 2, 2, 4] [1, 2, 2, 3, 3] [2, 2, 2, 2, 3] [1, 11] [2, 10] [3, 9] [4, 8] [5, 7] [6, 6] [1, 1, 10] [1, 2, 9] [1, 3, 8] [1, 4, 7] [1, 5, 6] [2, 2, 8] [2, 3, 7] [2, 4, 6] [2, 5, 5] [3, 3, 6] [3, 4, 5] [4, 4, 4] [1, 1, 1, 9] [1, 1, 2, 8] [1, 1, 3, 7] [1, 1, 4, 6] [1, 1, 5, 5] [1, 2, 2, 7] [1, 2, 3, 6] [1, 2, 4, 5] [1, 3, 3, 5] [1, 3, 4, 4] [2, 2, 2, 6] [2, 2, 3, 5] [2, 2, 4, 4] [2, 3, 3, 4] [3, 3, 3, 3] [1, 1, 1, 1, 8] [1, 1, 1, 2, 7] [1, 1, 1, 3, 6] [1, 1, 1, 4, 5] [1, 1, 2, 2, 6] [1, 1, 2, 3, 5] [1, 1, 2, 4, 4] [1, 1, 3, 3, 4] [1, 2, 2, 2, 5] [1, 2, 2, 3, 4] [1, 2, 3, 3, 3] [2, 2, 2, 2, 4] [2, 2, 2, 3, 3] [1, 1, 1, 1, 1, 7] [1, 1, 1, 1, 2, 6] [1, 1, 1, 1, 3, 5] [1, 1, 1, 1, 4, 4] [1, 1, 1, 2, 2, 5] [1, 1, 1, 2, 3, 4] [1, 1, 1, 3, 3, 3] [1, 1, 2, 2, 2, 4] [1, 1, 2, 2, 3, 3] [1, 2, 2, 2, 2, 3] [2, 2, 2, 2, 2, 2] [5, 6, 6, 6] [3, 3, 5, 6, 6] [3, 4, 4, 6, 6] [3, 4, 5, 5, 6] [3, 5, 5, 5, 5] [4, 4, 4, 5, 6] [4, 4, 5, 5, 5] [3, 3, 3, 3, 5, 6] [3, 3, 3, 4, 4, 6] [3, 3, 3, 4, 5, 5] [3, 3, 4, 4, 4, 5] [3, 4, 4, 4, 4, 4] [3, 3, 3, 3, 3, 3, 5] [3, 3, 3, 3, 3, 4, 4] [0, 0, 0, 2, 3] [0, 0, 1, 1, 3] [0, 0, 1, 2, 2] [0, 1, 1, 1, 2] [1, 1, 1, 1, 1] [0, 0, 3, 3, 3, 3, 3] [0, 1, 2, 3, 3, 3, 3] [0, 2, 2, 2, 3, 3, 3] [1, 1, 1, 3, 3, 3, 3] [1, 1, 2, 2, 3, 3, 3] [1, 2, 2, 2, 2, 3, 3] [2, 2, 2, 2, 2, 2, 3] Total time spent: 10984 pari-2.7.5/src/test/32/isprime0000644000175000017500000000026412366172547014512 0ustar billbill1 1 1 [ 2 5 1] [ 3 2 1] [1000003 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: 17128 pari-2.7.5/src/test/32/minim0000644000175000017500000000003611706644717014150 0ustar billbill1 1 78 77 Total time spent: 0 pari-2.7.5/src/test/32/elliptic0000644000175000017500000001234512405547147014646 0ustar billbill echo = 1 (on) ? ellinit([-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]] ? ellinit([-17,0],1) [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]] ? ellsub(%,[-1,4],[-4,2]) [9, -24] ? ellj(I) 1728.0000000000000000000000000000000000 ? acurve=ellinit([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] ? elladd(acurve,apoint,apoint) [21/25, -56/125] ? ellak(acurve,1000000007) 43800 ? ellan(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] ? ellap(acurve,10007) 66 ? deu=direuler(p=2,100,1/(1-ellap(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] ? ellan(acurve,100)==deu 1 ? ellisoncurve(acurve,apoint) 1 ? acurve=ellchangecurve(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]] ? apoint=ellchangepoint(apoint,[-1,1,2,3]) [1, 3] ? ellisoncurve(acurve,apoint) 1 ? ellglobalred(acurve) [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) 0.72491221490962306778878739838332384646 ? ellztopoint(acurve,%) [1.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000] ? ellmul(acurve,apoint,10) [-28919032218753260057646013785951999/292736325329248127651484680640160000, 478051489392386968218136375373985436596569736643531551/158385319626308443937 475969221994173751192384064000000] ? ellwp(acurve,x+O(x^33)) x^-2 + 1/5*x^2 - 1/28*x^4 + 1/75*x^6 - 3/1540*x^8 + 1943/3822000*x^10 - 1/11 550*x^12 + 193/10510500*x^14 - 1269/392392000*x^16 + 21859/34684650000*x^18 - 1087/9669660000*x^20 + 22179331/1060517858400000*x^22 - 463/124093970000*x ^24 + 47495017/70175140035000000*x^26 - 34997918161/291117454720092000000*x^ 28 + O(x^30) ? q*Ser(ellan(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) ? bcurve=ellinit([-3,0]) [0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, Vecsmall([1]), [Vecsmall( [128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? elllocalred(bcurve,2) [6, 2, [1, 1, 1, 0], 1] ? elltaniyama(bcurve) [x^-2 - x^2 + 3*x^6 - 2*x^10 + 7*x^14 + O(x^15), -x^-3 + 3*x - 3*x^5 + 8*x^9 - 9*x^13 + O(x^14)] ? ccurve=ellinit([0,0,-1,-1,0]) [0, 0, -1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vec small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? l=elllseries(ccurve,2) 0.38157540826071121129371040958008663665 ? abs(elllseries(ccurve,2,1.2)-l)<1.4e-38 1 ? tcurve=ellinit([1,0,1,-19,26]); ? ellorder(tcurve,[1,2]) 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]]~ ? mhbi=ellbil(mcurve,mpoints,[9,24]) [-0.72448571035980184146215805860545027441, 1.307328627832055544492943428892 1943056]~ ? ma=ellheightmatrix(mcurve,mpoints) [1.1721830987006970106016415566698834135 0.447697388340895169139483498064433 13906] [0.44769738834089516913948349806443313906 1.75502601617295071363242692695662 74446] ? matsolve(ma,mhbi) [-1.0000000000000000000000000000000000000, 1.0000000000000000000000000000000 000000]~ ? cmcurve=ellinit([0,-3/4,0,-2,-1]) [0, -3/4, 0, -2, -1, -3, -4, -4, -1, 105, 1323, -343, -3375, Vecsmall([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? ellmul(cmcurve,[x,y],quadgen(-7)) [((-2 + 3*w)*x^2 + (6 - w))/((-2 - 5*w)*x + (-4 - 2*w)), ((34 - 11*w)*y*x^2 + (40 - 28*w)*y*x + (22 + 23*w)*y)/((-90 - w)*x^2 + (-136 + 44*w)*x + (-40 + 28*w))] ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 32 pari-2.7.5/src/test/32/qfb0000644000175000017500000000113612366172547013611 0ustar billbill[-1, 6, 6] Qfb(-2, -34, 17, -1.2031810657666797073140254201751247272) Qfb(-2, 34, 17, 3.6095431973000391219420762605253741816) Qfb(1, 34, -34, 0.E-38) Qfb(-2, 34, 17, 1.2031810657666797073140254201751247272) Qfb(17, 34, -2, -2.9945542852277529726974917240067615601) Qfb(17, 34, -2, -22194773194531041164.334277319893643413) Qfb(1, -1, 6) Qfb(8, 13, 6) Qfb(1, 1, 6) Qfb(1009, 60, 99108027750247771) Qfb(1, 0, 100000000000000000039) Qfb(1, 1, 6) Qfb(18446744073709551629, 4741036151112220792, 304625896260305173) Qfb(18446744073709551629, 7562574061564804959, 775103267656920011, 0.E-38) Total time spent: 0 pari-2.7.5/src/test/32/rnfkummer0000644000175000017500000002540712413013143015031 0ustar billbill *** 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 + (-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) 4 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 83633556328 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 - 2673104432455463952284352656647109245231103663592899118247897745294025980581 570350460813923435311458682114748384710825808171997155877533243621/5*y^2 + 1 9372161459591757660716692723884954611407620247350322071070721355639658608496 4322202670927424345172110316287310450443586757567876756951302594424/5*y + 13 7651773558650909762864388498297831958827163349141150095186154867116600261791 580542516653158613689676015829782898702530873665348851222173825666/5) 9 x^3 + (-2138833799099964*y - 77766538091057475)*x + (28996816968231072456572 6*y + 10543044869724218021876124) 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 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 + (-1/2*y^5 - 9/2*y^4 - y^3 - 3/2*y^2 - 3/2*y + 3) 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: 15853 pari-2.7.5/src/test/32/quadclassunit0000644000175000017500000004214712526651220015714 0ustar billbill? test(D)=for(d=D,D+10^3,if(!isfundamental(d),next);print(d," ",quadclassunit(d).cyc)); ? setrand(1);test(10^15);test(-10^15) 1000000000000001 [4, 4, 2, 2, 2] 1000000000000005 [2, 2, 2, 2] 1000000000000009 [2, 2] 1000000000000012 [32, 2] 1000000000000013 [] 1000000000000021 [2] 1000000000000024 [4] 1000000000000028 [2] 1000000000000029 [6, 2] 1000000000000033 [] 1000000000000037 [] 1000000000000040 [8, 2, 2, 2] 1000000000000041 [2, 2, 2, 2] 1000000000000045 [4, 2] 1000000000000049 [2] 1000000000000056 [2, 2, 2] 1000000000000057 [2] 1000000000000060 [6, 2, 2, 2] 1000000000000061 [2] 1000000000000065 [4, 2, 2] 1000000000000069 [] 1000000000000076 [2] 1000000000000077 [6, 2] 1000000000000081 [2, 2] 1000000000000085 [2, 2] 1000000000000088 [13] 1000000000000093 [] 1000000000000097 [4, 4] 1000000000000101 [12, 2, 2] 1000000000000104 [2] 1000000000000105 [2, 2, 2] 1000000000000108 [2] 1000000000000109 [4] 1000000000000113 [2, 2] 1000000000000117 [] 1000000000000120 [12, 2] 1000000000000121 [2] 1000000000000124 [8, 2, 2] 1000000000000129 [6] 1000000000000133 [2, 2, 2] 1000000000000136 [4] 1000000000000137 [4, 2] 1000000000000140 [2, 2, 2, 2] 1000000000000145 [4] 1000000000000149 [2, 2] 1000000000000153 [] 1000000000000156 [2, 2, 2, 2] 1000000000000157 [22, 2, 2] 1000000000000165 [2, 2, 2] 1000000000000168 [334] 1000000000000169 [] 1000000000000172 [3] 1000000000000173 [2, 2] 1000000000000177 [2] 1000000000000181 [2] 1000000000000184 [2, 2, 2, 2] 1000000000000185 [8, 2, 2, 2] 1000000000000189 [22] 1000000000000193 [2] 1000000000000201 [2] 1000000000000204 [4, 2, 2] 1000000000000205 [2] 1000000000000209 [2, 2, 2] 1000000000000216 [2, 2, 2] 1000000000000217 [7] 1000000000000220 [8, 2, 2] 1000000000000221 [2, 2, 2, 2] 1000000000000229 [2] 1000000000000232 [6, 2] 1000000000000236 [8, 4] 1000000000000237 [4] 1000000000000241 [] 1000000000000245 [2, 2, 2] 1000000000000248 [2, 2, 2] 1000000000000249 [] 1000000000000252 [2] 1000000000000253 [76] 1000000000000257 [2, 2] 1000000000000261 [2] 1000000000000264 [2, 2] 1000000000000265 [2, 2, 2] 1000000000000268 [2, 2] 1000000000000273 [] 1000000000000277 [4, 2] 1000000000000280 [2, 2] 1000000000000281 [2, 2, 2] 1000000000000284 [4, 2] 1000000000000285 [2] 1000000000000289 [] 1000000000000293 [] 1000000000000297 [] 1000000000000301 [2] 1000000000000309 [14, 2, 2, 2] 1000000000000312 [2, 2] 1000000000000313 [6, 6] 1000000000000316 [2, 2] 1000000000000317 [2, 2] 1000000000000321 [3] 1000000000000328 [4, 2, 2] 1000000000000329 [2] 1000000000000333 [4] 1000000000000344 [2, 2, 2] 1000000000000345 [8, 2, 2] 1000000000000349 [] 1000000000000353 [8, 2, 2] 1000000000000357 [] 1000000000000360 [2, 2, 2] 1000000000000361 [4] 1000000000000364 [4, 2] 1000000000000365 [6, 2, 2] 1000000000000369 [4, 2] 1000000000000373 [2, 2] 1000000000000376 [26, 2] 1000000000000380 [2, 2] 1000000000000381 [2] 1000000000000385 [2] 1000000000000389 [2, 2] 1000000000000392 [2] 1000000000000393 [3] 1000000000000396 [2, 2] 1000000000000397 [4] 1000000000000401 [3] 1000000000000405 [2, 2, 2] 1000000000000408 [2, 2] 1000000000000409 [6, 2] 1000000000000412 [2, 2] 1000000000000417 [6] 1000000000000421 [2] 1000000000000424 [2, 2] 1000000000000428 [12, 2, 2] 1000000000000429 [] 1000000000000433 [] 1000000000000437 [] 1000000000000444 [] 1000000000000445 [2, 2, 2, 2] 1000000000000453 [2, 2] 1000000000000456 [2, 2] 1000000000000457 [4] 1000000000000460 [6, 2, 2, 2] 1000000000000461 [4] 1000000000000465 [4, 2] 1000000000000469 [158] 1000000000000472 [] 1000000000000473 [] 1000000000000477 [2, 2] 1000000000000481 [2] 1000000000000488 [12, 2, 2] 1000000000000489 [2, 2, 2] 1000000000000492 [24] 1000000000000493 [] 1000000000000497 [] 1000000000000501 [12] 1000000000000504 [24] 1000000000000505 [2, 2, 2] 1000000000000508 [2, 2] 1000000000000509 [2] 1000000000000513 [] 1000000000000517 [2] 1000000000000520 [10, 2] 1000000000000524 [6, 2, 2, 2, 2] 1000000000000529 [2, 2] 1000000000000537 [2, 2, 2] 1000000000000540 [6, 2, 2] 1000000000000541 [27] 1000000000000545 [2, 2, 2] 1000000000000549 [2] 1000000000000552 [2] 1000000000000553 [14] 1000000000000556 [2, 2] 1000000000000561 [6, 2] 1000000000000565 [2, 2] 1000000000000568 [2] 1000000000000569 [] 1000000000000572 [36, 2, 2, 2, 2] 1000000000000577 [4, 2] 1000000000000581 [6, 3] 1000000000000585 [2, 2] 1000000000000588 [2] 1000000000000589 [36, 2] 1000000000000597 [4] 1000000000000601 [54, 2] 1000000000000604 [4, 2] 1000000000000605 [4, 2] 1000000000000609 [16] 1000000000000613 [] 1000000000000616 [2, 2, 2] 1000000000000617 [4, 2, 2, 2] 1000000000000621 [12, 2] 1000000000000632 [2] 1000000000000633 [2] 1000000000000636 [2] 1000000000000637 [2] 1000000000000641 [2] 1000000000000645 [2, 2] 1000000000000648 [10, 2, 2] 1000000000000649 [14] 1000000000000652 [2, 2] 1000000000000653 [8] 1000000000000657 [3] 1000000000000661 [2] 1000000000000664 [4, 2] 1000000000000668 [4, 2, 2] 1000000000000669 [36] 1000000000000673 [2] 1000000000000677 [2, 2, 2] 1000000000000681 [9] 1000000000000684 [12, 2] 1000000000000685 [4, 2, 2] 1000000000000689 [4] 1000000000000693 [] 1000000000000696 [2, 2, 2] 1000000000000697 [] 1000000000000705 [12, 2, 2] 1000000000000709 [36] 1000000000000712 [4, 2, 2] 1000000000000713 [4, 2] 1000000000000716 [2, 2, 2] 1000000000000717 [8, 4] 1000000000000721 [] 1000000000000732 [2, 2] 1000000000000733 [2] 1000000000000741 [] 1000000000000744 [2, 2] 1000000000000745 [6] 1000000000000748 [2] 1000000000000749 [8, 2] 1000000000000753 [2, 2] 1000000000000757 [] 1000000000000760 [2, 2, 2] 1000000000000761 [14] 1000000000000765 [2] 1000000000000769 [] 1000000000000776 [4, 2, 2] 1000000000000777 [] 1000000000000780 [6, 2, 2, 2] 1000000000000781 [2, 2, 2] 1000000000000785 [6, 2] 1000000000000789 [6] 1000000000000792 [10, 2] 1000000000000793 [2, 2] 1000000000000796 [] 1000000000000797 [2] 1000000000000801 [4] 1000000000000805 [4, 2] 1000000000000808 [2, 2] 1000000000000812 [2, 2, 2, 2] 1000000000000813 [8, 2] 1000000000000817 [2, 2] 1000000000000821 [2, 2] 1000000000000824 [4, 2] 1000000000000828 [2, 2] 1000000000000829 [] 1000000000000833 [2, 2, 2] 1000000000000837 [12, 2] 1000000000000840 [2, 2] 1000000000000841 [2] 1000000000000844 [2, 2, 2] 1000000000000849 [2] 1000000000000853 [6] 1000000000000856 [2] 1000000000000857 [3] 1000000000000860 [4, 2, 2, 2] 1000000000000861 [6] 1000000000000865 [32, 2, 2] 1000000000000869 [16, 2, 2, 2] 1000000000000873 [] 1000000000000877 [2] 1000000000000885 [2, 2, 2] 1000000000000888 [13] 1000000000000889 [54, 2] 1000000000000892 [30, 2, 2] 1000000000000893 [2] 1000000000000897 [2, 2, 2] 1000000000000904 [2, 2, 2] 1000000000000905 [2, 2, 2] 1000000000000909 [2, 2, 2] 1000000000000913 [8] 1000000000000920 [2, 2] 1000000000000921 [] 1000000000000924 [2, 2, 2, 2] 1000000000000929 [4] 1000000000000933 [] 1000000000000936 [2, 2] 1000000000000937 [2, 2] 1000000000000941 [6] 1000000000000945 [4] 1000000000000949 [] 1000000000000952 [4] 1000000000000956 [2, 2] 1000000000000957 [2, 2] 1000000000000961 [2, 2, 2, 2] 1000000000000965 [2, 2] 1000000000000968 [2, 2, 2] 1000000000000969 [2] 1000000000000972 [2] 1000000000000973 [6] 1000000000000977 [64, 2] 1000000000000981 [2, 2] 1000000000000984 [2, 2, 2] 1000000000000985 [2, 2] 1000000000000988 [108] 1000000000000993 [] 1000000000000997 [12] -999999999999995 [3872378, 2] -999999999999992 [2471436, 2, 2, 2] -999999999999991 [9144306, 2] -999999999999988 [1124902, 2, 2] -999999999999987 [913748, 2, 2, 2] -999999999999983 [13126428, 2] -999999999999979 [2148058, 2, 2] -999999999999976 [2984712, 2, 2] -999999999999971 [7798614, 2] -999999999999967 [11253252] -999999999999960 [481528, 2, 2, 2, 2] -999999999999959 [25233340, 2] -999999999999956 [9820206, 2] -999999999999955 [2185542, 2] -999999999999951 [11807322, 2] -999999999999947 [7261653] -999999999999944 [7665042, 2] -999999999999943 [17982820] -999999999999940 [1458740, 2, 2] -999999999999939 [1705720, 2, 2] -999999999999935 [3815348, 2, 2, 2] -999999999999931 [377454, 2, 2, 2, 2] -999999999999928 [3090498, 2] -999999999999924 [275778, 2, 2, 2, 2, 2, 2] -999999999999923 [2614376, 2, 2] -999999999999919 [20175156] -999999999999915 [878588, 2, 2, 2] -999999999999912 [3618208, 2] -999999999999911 [31532754] -999999999999908 [12931036] -999999999999907 [3859738] -999999999999903 [448308, 2, 2, 2, 2, 2] -999999999999899 [21701582] -999999999999895 [4135150, 2, 2] -999999999999892 [1620700, 2, 2] -999999999999887 [10190276, 2, 2] -999999999999883 [2498825] -999999999999880 [1139478, 2, 2, 2] -999999999999879 [9394500, 2] -999999999999876 [1305236, 2, 2, 2] -999999999999871 [13406168, 2] -999999999999867 [4308820, 2] -999999999999863 [7643020, 2] -999999999999860 [4852422, 2, 2] -999999999999859 [3024070, 2] -999999999999851 [1199052, 4, 2] -999999999999848 [6290596, 2] -999999999999844 [5296516, 2] -999999999999843 [3731152, 2] -999999999999839 [42706704] -999999999999835 [1378294, 2, 2] -999999999999832 [974764, 2, 2, 2] -999999999999831 [21097546, 2] -999999999999827 [7464103] -999999999999823 [4886300, 2] -999999999999816 [3866004, 2, 2] -999999999999815 [8445968, 2, 2] -999999999999812 [1381066, 2, 2, 2] -999999999999811 [3696512, 2] -999999999999807 [3253596, 2, 2] -999999999999803 [7540922, 2] -999999999999799 [17550154] -999999999999796 [2206538, 2, 2] -999999999999795 [1527752, 2, 2] -999999999999791 [31405878] -999999999999787 [5207448] -999999999999780 [760782, 2, 2, 2, 2] -999999999999779 [11011782] -999999999999771 [3947234, 2] -999999999999768 [1192776, 2, 2, 2] -999999999999767 [1232812, 2, 2, 2, 2] -999999999999764 [7211408, 2] -999999999999763 [1285040, 2, 2] -999999999999759 [3402540, 2, 2, 2] -999999999999755 [3392056, 4] -999999999999752 [3435556, 2, 2] -999999999999751 [2159360, 2, 2, 2] -999999999999748 [3957274, 2] -999999999999743 [11495572, 2] -999999999999739 [4758772] -999999999999736 [4989568, 2] -999999999999735 [2123290, 2, 2, 2] -999999999999732 [2033166, 2, 2] -999999999999731 [15293774] -999999999999727 [9307746] -999999999999723 [499770, 2, 2, 2] -999999999999719 [11514202, 2, 2] -999999999999716 [1035944, 8, 2] -999999999999707 [1111128, 2, 2, 2] -999999999999704 [3465724, 2, 2] -999999999999703 [10063644, 2] -999999999999699 [2335196, 2, 2] -999999999999695 [7306262, 2, 2] -999999999999691 [1922812, 2, 2] -999999999999688 [480138, 6, 2] -999999999999687 [3846148, 2, 2] -999999999999683 [3139616, 2] -999999999999679 [5354308, 2, 2] -999999999999672 [2178978, 2, 2] -999999999999671 [21071960, 2] -999999999999668 [6288672, 2] -999999999999667 [2443850, 2] -999999999999663 [2452980, 2, 2, 2] -999999999999659 [11343307] -999999999999656 [20023842] -999999999999655 [3183568, 4] -999999999999652 [2245500, 2] -999999999999647 [6567154, 2, 2] -999999999999643 [3389457] -999999999999640 [181472, 4, 2, 2, 2, 2] -999999999999636 [3131420, 2, 2] -999999999999635 [4518528, 2] -999999999999631 [889308, 2, 2, 2, 2] -999999999999627 [368676, 2, 2, 2, 2] -999999999999624 [3148536, 2, 2] -999999999999623 [7549890, 2, 2] -999999999999620 [6700476, 2] -999999999999619 [6401220] -999999999999615 [16746558, 2] -999999999999611 [6632280, 2] -999999999999608 [3452468, 4] -999999999999607 [4112552, 2, 2] -999999999999604 [1056580, 2, 2, 2] -999999999999599 [39104546] -999999999999595 [173704, 4, 2, 2, 2] -999999999999592 [1255062, 2, 2] -999999999999591 [16457136, 2] -999999999999588 [1333928, 2, 2, 2] -999999999999587 [7930856] -999999999999583 [8857554] -999999999999579 [2607088, 2, 2] -999999999999572 [1824280, 2, 2, 2] -999999999999571 [7737015] -999999999999563 [5842726, 2] -999999999999560 [787644, 2, 2, 2, 2] -999999999999556 [3220034, 2, 2] -999999999999555 [200052, 4, 2, 2, 2] -999999999999551 [34658682] -999999999999547 [1902240, 2] -999999999999544 [2464376, 4] -999999999999543 [11437680] -999999999999539 [1482104, 2, 2, 2] -999999999999535 [4463256, 2, 2] -999999999999528 [1134018, 2, 2, 2] -999999999999527 [22589484] -999999999999524 [2781866, 2, 2, 2] -999999999999523 [1317604, 4] -999999999999519 [851520, 4, 2, 2, 2] -999999999999515 [6167982] -999999999999512 [676026, 2, 2, 2, 2] -999999999999508 [4069512, 2] -999999999999507 [287934, 2, 2, 2, 2] -999999999999503 [18452280, 2] -999999999999499 [4420082] -999999999999496 [8867516] -999999999999492 [1799496, 2, 2] -999999999999491 [12931961] -999999999999487 [13431888] -999999999999483 [2954944, 2] -999999999999480 [658258, 2, 2, 2, 2] -999999999999479 [42634930] -999999999999476 [530106, 2, 2, 2, 2, 2] -999999999999471 [21070792] -999999999999467 [2013918, 2, 2] -999999999999464 [9339422, 2] -999999999999463 [12087026] -999999999999460 [1021798, 2, 2, 2] -999999999999451 [3551814, 2] -999999999999448 [871296, 2, 2, 2] -999999999999447 [2331996, 4, 2] -999999999999444 [760910, 2, 2, 2, 2] -999999999999443 [4886894, 2] -999999999999439 [7887366, 3] -999999999999435 [3573078, 2] -999999999999431 [36933388] -999999999999428 [5934232, 2] -999999999999427 [946428, 2, 2] -999999999999419 [7505708, 2] -999999999999416 [2201616, 6, 2] -999999999999415 [7505874, 2] -999999999999412 [3733110, 2] -999999999999411 [8423382] -999999999999407 [3056636, 2, 2, 2] -999999999999403 [438314, 2, 2, 2] -999999999999399 [5204266, 2, 2] -999999999999395 [440000, 4, 4, 2] -999999999999391 [14843488, 2] -999999999999384 [2002552, 2, 2, 2] -999999999999383 [19605798] -999999999999380 [2144856, 2, 2, 2] -999999999999379 [5267274] -999999999999371 [6940440, 2] -999999999999368 [1560324, 2, 2, 2] -999999999999367 [15851448] -999999999999364 [984184, 2, 2, 2] -999999999999363 [3479512, 2] -999999999999359 [10558080, 4] -999999999999355 [5188556] -999999999999348 [1472778, 2, 2, 2] -999999999999347 [2888262, 3] -999999999999343 [1765078, 2, 2, 2] -999999999999339 [2666192, 2, 2] -999999999999336 [2780706, 2, 2] -999999999999335 [8120196, 2, 2] -999999999999332 [12013212] -999999999999331 [3435240] -999999999999327 [2825256, 4, 2] -999999999999323 [8120472] -999999999999320 [7587430, 2] -999999999999319 [3528900, 2, 2] -999999999999316 [2926406, 2, 2] -999999999999311 [37355466] -999999999999307 [1562448, 4] -999999999999304 [6246412, 2] -999999999999303 [2311596, 2, 2, 2] -999999999999299 [5152654, 2, 2] -999999999999295 [3017552, 2, 2] -999999999999291 [682078, 2, 2, 2] -999999999999287 [6563352, 2, 2] -999999999999284 [3932520, 2, 2] -999999999999283 [6236089] -999999999999272 [4838350, 2, 2] -999999999999271 [19947218] -999999999999268 [948156, 2, 2] -999999999999267 [813228, 2, 2] -999999999999263 [27501864] -999999999999256 [1905422, 2, 2] -999999999999255 [3073434, 2, 2, 2] -999999999999247 [3166660, 2, 2] -999999999999240 [515266, 2, 2, 2, 2] -999999999999239 [2062240, 8, 2] -999999999999236 [1284828, 4, 2, 2] -999999999999235 [329016, 6, 2] -999999999999227 [11870444] -999999999999224 [2451664, 4, 2] -999999999999223 [4068880, 4] -999999999999219 [1892074, 2, 2] -999999999999215 [11095728, 2, 2] -999999999999211 [3135780, 2] -999999999999208 [982388, 2, 2, 2] -999999999999204 [4434704, 2, 2] -999999999999203 [1940982, 3] -999999999999199 [23272893] -999999999999195 [1021548, 2, 2, 2] -999999999999192 [4345186, 2] -999999999999191 [31434168] -999999999999188 [3242488, 2, 2] -999999999999187 [2881940, 2] -999999999999183 [17566220] -999999999999179 [2219256, 2, 2] -999999999999176 [7857696, 2] -999999999999172 [1647452, 2, 2] -999999999999167 [5533268, 2, 2] -999999999999163 [3285527] -999999999999160 [2366136, 2, 2] -999999999999159 [16819386, 2] -999999999999156 [757280, 2, 2, 2, 2] -999999999999155 [2575746, 2, 2] -999999999999151 [9783152, 2] -999999999999147 [210532, 4, 2, 2, 2] -999999999999143 [3668170, 2, 2, 2] -999999999999140 [2439050, 2, 2, 2] -999999999999139 [4723660, 2] -999999999999131 [2175188, 2, 2, 2] -999999999999128 [4662970, 2] -999999999999127 [11240510] -999999999999124 [313380, 6, 2, 2] -999999999999123 [580976, 2, 2, 2] -999999999999119 [27047100] -999999999999115 [2647620, 2] -999999999999107 [2325772, 2, 2] -999999999999103 [14333463] -999999999999096 [3888906, 2, 2] -999999999999095 [40990872] -999999999999092 [1314992, 4, 2] -999999999999091 [1503646, 2, 2] -999999999999087 [9765916, 2] -999999999999083 [11734392] -999999999999080 [909790, 2, 2, 2, 2] -999999999999079 [18131164] -999999999999076 [5363012, 2] -999999999999071 [30434221] -999999999999067 [2822928] -999999999999064 [4215872, 2] -999999999999060 [929084, 2, 2, 2] -999999999999059 [2815234, 2, 2] -999999999999055 [9636108, 2] -999999999999051 [4857524, 2] -999999999999048 [1242132, 2, 2, 2] -999999999999047 [24219706] -999999999999044 [2202860, 2, 2, 2] -999999999999043 [3834587] -999999999999039 [2550480, 8] -999999999999035 [816218, 2, 2, 2, 2] -999999999999032 [9616060] -999999999999031 [19377240] -999999999999028 [937052, 4, 2] -999999999999023 [24634500] -999999999999019 [8268794] -999999999999016 [2220068, 2, 2] -999999999999015 [1964780, 2, 2, 2] -999999999999012 [2168582, 2, 2] -999999999999011 [10976478] -999999999999007 [2903838, 2, 2] -999999999999003 [4036316, 2] ? setrand(11);quadclassunit(-8419588).cyc [176, 2] ? setrand(2);quadclassunit(-1459008).cyc [16, 4, 2, 2] ? setrand(7);quadclassunit(-3799812).cyc [54, 2, 2, 2] ? setrand(1);quadclassunit(-13163208).cyc [156, 2, 2] ? setrand(38);quadclassunit(-29920).cyc [4, 2, 2, 2] ? quadclassunit(-13163208,,[0.1]).cyc [156, 2, 2] ? setrand(1);quadclassunit((2^70+25)).cyc [17] ? setrand(1);quadclassunit(8*3*5*7).cyc [2, 2] ? setrand(1);quadclassunit(-612556842419).cyc [192199] ? print("Total time spent: ",gettime); Total time spent: 4592 pari-2.7.5/src/test/32/polmod0000644000175000017500000000506612366172547014341 0ustar billbillMod(x + 1/3, 2*x^2 + x + 1) Mod(15/16*x + 21/32, 2*x^2 + x + 1) Mod(1/2*x - 1/4, 2*x^2 + x + 1) Mod(-2*x, 2*x^2 + x + 1) Mod(-1/4*x - 3/8, 2*x^2 + x + 1) Mod(1, 2*x^2 + x + 1) Mod(4/3*x^2 - 1/6, 2*x^3 + x + 1) Mod(-39/103*x^2 + 93/103*x + 183/206, 2*x^3 + x + 1) Mod(3/2*x^2 - 1/2*x - 3/4, 2*x^3 + x + 1) Mod(2*x^2 - 2*x + 2, 2*x^3 + x + 1) Mod(-5/4*x^2 - 9/4*x - 7/8, 2*x^3 + x + 1) Mod(1, 2*x^3 + x + 1) Mod(Mod(6, 17)*x^2 + Mod(7, 17)*x + Mod(4, 17), Mod(2, 17)*x^3 + Mod(1, 17)* x + Mod(1, 17)) Mod(Mod(3, 17)*x^2 + Mod(16, 17)*x + Mod(6, 17), Mod(2, 17)*x^3 + Mod(1, 17) *x + Mod(1, 17)) Mod(Mod(15, 17)*x^2 + Mod(13, 17)*x + Mod(8, 17), Mod(2, 17)*x^3 + Mod(1, 17 )*x + Mod(1, 17)) Mod(Mod(8, 17)*x^2 + Mod(13, 17)*x + Mod(1, 17), Mod(2, 17)*x^3 + Mod(1, 17) *x + Mod(1, 17)) Mod(Mod(16, 17)*x^2 + Mod(10, 17), Mod(2, 17)*x^3 + Mod(1, 17)*x + Mod(1, 17 )) Mod(Mod(1, 17), Mod(2, 17)*x^3 + Mod(1, 17)*x + Mod(1, 17)) Mod(Mod(9223372036854775829, 18446744073709551629)*x^2 + Mod(7, 184467440737 09551629)*x + Mod(9223372036854775827, 18446744073709551629), Mod(2, 1844674 4073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod(1, 184467440737095 51629)) Mod(Mod(9746969576064872258, 18446744073709551629)*x^2 + Mod(103913973166311 44804, 18446744073709551629)*x + Mod(12445510739686138545, 18446744073709551 629), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mo d(1, 18446744073709551629)) Mod(Mod(9223372036854775821, 18446744073709551629)*x^2 + Mod(922337203685477 5819, 18446744073709551629)*x + Mod(8, 18446744073709551629), Mod(2, 1844674 4073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod(1, 184467440737095 51629)) Mod(Mod(11980875016945378893, 18446744073709551629)*x^2 + Mod(95086309658296 65788, 18446744073709551629)*x + Mod(6656041676080766052, 184467440737095516 29), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod (1, 18446744073709551629)) Mod(Mod(4611686018427387936, 18446744073709551629)*x^2 + Mod(461168601842738 7920, 18446744073709551629)*x + Mod(9223372036854775833, 1844674407370955162 9), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod( 1, 18446744073709551629)) 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(y, x) Mod(1/y, x) Mod(O(y), x) Mod(1, y)*x Mod(1, y)/(Mod(1, y)*x) Mod(1, y) *** at top-level: Mod(1+O(y),y+1) *** ^--------------- *** Mod: forbidden division t_SER % t_POL. 0 Mod(-1, x - 1) 36893488147419103232 a Total time spent: 0 pari-2.7.5/src/test/32/nf0000644000175000017500000003036712610200115013423 0ustar billbill realprecision = 38 significant digits [85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]] 12.340047278667903334059769086970462220 4.1894250945222025884896456921310573068 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]]] [1, [], []] *** zetakinit: Warning: non-monic polynomial. Result of the form [nf,c]. *** zetakinit: Warning: non-monic polynomial. Change of variables discarded. [3, 3] 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], [[0, 1, 0, 0, 0]~], [[0, 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], [[-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] )]]] [[[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). [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] Total time spent: 1652 pari-2.7.5/src/test/32/factormod0000644000175000017500000003501212366172547015017 0ustar billbill[x + 7, 1; x + 8, 1; x + 20, 1; x + 21, 1; x + 24, 1; x + 50, 1; x + 60, 1; x + 63, 1; x + 68, 1; x + 72, 1; x + 125, 1; x + 139, 1; x + 146, 1; x + 150 , 1; x + 170, 1; x + 180, 1; x + 189, 1; x + 193, 1; x + 204, 1; x + 212, 1; x + 216, 1; x + 239, 1; x + 293, 1; x + 338, 1; x + 343, 1; x + 346, 1; x + 364, 1; x + 365, 1; x + 375, 1; x + 377, 1; x + 392, 1; x + 406, 1; x + 412 , 1; x + 416, 1; x + 417, 1; x + 425, 1; x + 438, 1; x + 448, 1; x + 450, 1; x + 457, 1; x + 463, 1; x + 464, 1; x + 466, 1; x + 502, 1; x + 506, 1; x + 510, 1; x + 512, 1; x + 530, 1; x + 540, 1; x + 567, 1; x + 578, 1; x + 579 , 1; x + 612, 1; x + 614, 1; x + 622, 1; x + 636, 1; x + 648, 1; x + 682, 1; x + 716, 1; x + 717, 1; x + 751, 1; x + 767, 1; x + 769, 1; x + 778, 1; x + 791, 1; x + 814, 1; x + 826, 1; x + 844, 1; x + 845, 1; x + 865, 1; x + 874 , 1; x + 879, 1; x + 881, 1; x + 904, 1; x + 910, 1; x + 923, 1; x + 944, 1; x + 980, 1; x + 982, 1; x + 994, 1; x + 1014, 1; x + 1015, 1; x + 1029, 1; x + 1030, 1; x + 1038, 1; x + 1040, 1; x + 1057, 1; x + 1092, 1; x + 1095, 1 ; x + 1120, 1; x + 1125, 1; x + 1131, 1; x + 1136, 1; x + 1160, 1; x + 1165, 1; x + 1176, 1; x + 1178, 1; x + 1208, 1; x + 1218, 1; x + 1223, 1; x + 122 6, 1; x + 1236, 1; x + 1241, 1; x + 1248, 1; x + 1251, 1; x + 1255, 1; x + 1 265, 1; x + 1275, 1; x + 1279, 1; x + 1280, 1; x + 1282, 1; x + 1314, 1; x + 1325, 1; x + 1327, 1; x + 1344, 1; x + 1350, 1; x + 1371, 1; x + 1373, 1; x + 1389, 1; x + 1392, 1; x + 1398, 1; x + 1403, 1; x + 1406, 1; x + 1409, 1; x + 1417, 1; x + 1445, 1; x + 1468, 1; x + 1481, 1; x + 1506, 1; x + 1518, 1; x + 1522, 1; x + 1526, 1; x + 1530, 1; x + 1535, 1; x + 1536, 1; x + 1555 , 1; x + 1573, 1; x + 1590, 1; x + 1620, 1; x + 1658, 1; x + 1681, 1; x + 16 87, 1; x + 1694, 1; x + 1701, 1; x + 1705, 1; x + 1706, 1; x + 1721, 1; x + 1734, 1; x + 1737, 1; x + 1744, 1; x + 1756, 1; x + 1763, 1; x + 1783, 1; x + 1790, 1; x + 1802, 1; x + 1804, 1; x + 1826, 1; x + 1836, 1; x + 1842, 1; x + 1849, 1; x + 1866, 1; x + 1868, 1; x + 1882, 1; x + 1891, 1; x + 1892, 1 ; x + 1901, 1; x + 1908, 1; x + 1927, 1; x + 1928, 1; x + 1936, 1; x + 1942, 1; x + 1944, 1; x + 1945, 1; x + 2021, 1; x + 2035, 1; x + 2046, 1; x + 205 4, 1; x + 2065, 1; x + 2068, 1; x + 2110, 1; x + 2148, 1; x + 2151, 1; x + 2 164, 1; x + 2171, 1; x + 2185, 1; x + 2209, 1; x + 2212, 1; x + 2213, 1; x + 2231, 1; x + 2253, 1; x + 2257, 1; x + 2260, 1; x + 2275, 1; x + 2276, 1; x + 2291, 1; x + 2293, 1; x + 2301, 1; x + 2307, 1; x + 2334, 1; x + 2338, 1; x + 2360, 1; x + 2373, 1; x + 2429, 1; x + 2434, 1; x + 2442, 1; x + 2450, 1; x + 2455, 1; x + 2461, 1; x + 2478, 1; x + 2483, 1; x + 2485, 1; x + 2528 , 1; x + 2532, 1; x + 2535, 1; x + 2575, 1; x + 2593, 1; x + 2595, 1; x + 26 00, 1; x + 2602, 1; x + 2622, 1; x + 2626, 1; x + 2633, 1; x + 2637, 1; x + 2643, 1; x + 2672, 1; x + 2674, 1; x + 2689, 1; x + 2712, 1; x + 2717, 1; x + 2730, 1; x + 2769, 1; x + 2776, 1; x + 2800, 1; x + 2827, 1; x + 2828, 1; x + 2832, 1; x + 2840, 1; x + 2873, 1; x + 2894, 1; x + 2900, 1; x + 2926, 1 ; x + 2929, 1; x + 2940, 1; x + 2941, 1; x + 2945, 1; x + 2946, 1; x + 2947, 1; x + 2957, 1; x + 2982, 1; x + 3007, 1; x + 3017, 1; x + 3019, 1; x + 302 0, 1; x + 3028, 1; x + 3042, 1; x + 3045, 1; x + 3056, 1; x + 3065, 1; x + 3 087, 1; x + 3090, 1; x + 3094, 1; x + 3114, 1; x + 3116, 1; x + 3120, 1; x + 3121, 1; x + 3154, 1; x + 3163, 1; x + 3171, 1; x + 3200, 1; x + 3205, 1; x + 3221, 1; x + 3229, 1; x + 3232, 1; x + 3238, 1; x + 3268, 1; x + 3276, 1; x + 3278, 1; x + 3285, 1; x + 3317, 1; x + 3332, 1; x + 3338, 1; x + 3343, 1; x + 3344, 1; x + 3359, 1; x + 3360, 1; x + 3368, 1; x + 3375, 1; x + 3393 , 1; x + 3407, 1; x + 3408, 1; x + 3418, 1; x + 3448, 1; x + 3449, 1; x + 34 51, 1; x + 3454, 1; x + 3466, 1; x + 3469, 1; x + 3480, 1; x + 3495, 1; x + 3502, 1; x + 3511, 1; x + 3515, 1; x + 3528, 1; x + 3534, 1; x + 3536, 1; x + 3572, 1; x + 3578, 1; x + 3589, 1; x + 3607, 1; x + 3624, 1; x + 3654, 1; x + 3669, 1; x + 3670, 1; x + 3678, 1; x + 3708, 1; x + 3723, 1; x + 3744, 1 ; x + 3753, 1; x + 3758, 1; x + 3765, 1; x + 3769, 1; x + 3793, 1; x + 3795, 1; x + 3805, 1; x + 3808, 1; x + 3815, 1; x + 3821, 1; x + 3825, 1; x + 383 7, 1; x + 3840, 1; x + 3846, 1; x + 3869, 1; x + 3889, 1; x + 3929, 1; x + 3 941, 1; x + 3942, 1; x + 3944, 1; x + 3947, 1; x + 3959, 1; x + 3961, 1; x + 3975, 1; x + 3981, 1; x + 3982, 1; x + 4032, 1; x + 4050, 1; x + 4094, 1; x + 4099, 1; x + 4103, 1; x + 4113, 1; x + 4119, 1; x + 4138, 1; x + 4145, 1; x + 4153, 1; x + 4167, 1; x + 4176, 1; x + 4194, 1; x + 4209, 1; x + 4218, 1; x + 4222, 1; x + 4227, 1; x + 4235, 1; x + 4238, 1; x + 4251, 1; x + 4265 , 1; x + 4267, 1; x + 4273, 1; x + 4289, 1; x + 4301, 1; x + 4335, 1; x + 43 52, 1; x + 4360, 1; x + 4378, 1; x + 4390, 1; x + 4404, 1; x + 4411, 1; x + 4423, 1; x + 4443, 1; x + 4475, 1; x + 4483, 1; x + 4489, 1; x + 4499, 1; x + 4504, 1; x + 4505, 1; x + 4510, 1; x + 4518, 1; x + 4523, 1; x + 4538, 1; x + 4554, 1; x + 4564, 1; x + 4565, 1; x + 4566, 1; x + 4578, 1; x + 4590, 1 ; x + 4605, 1; x + 4608, 1; x + 4649, 1; x + 4661, 1; x + 4665, 1; x + 4670, 1; x + 4684, 1; x + 4693, 1; x + 4697, 1; x + 4705, 1; x + 4719, 1; x + 472 7, 1; x + 4730, 1; x + 4739, 1; x + 4770, 1; x + 4781, 1; x + 4820, 1; x + 4 834, 1; x + 4840, 1; x + 4855, 1; x + 4860, 1; x + 4883, 1; x + 4906, 1; x + 4913, 1; x + 4924, 1; x + 4939, 1; x + 4963, 1; x + 4974, 1; x + 4987, 1; x + 5002, 1; x + 5039, 1; x + 5043, 1; x + 5054, 1; x + 5061, 1; x + 5063, 1; x + 5078, 1; x + 5082, 1; x + 5102, 1; x + 5103, 1; x + 5115, 1; x + 5118, 1; x + 5135, 1; x + 5163, 1; x + 5170, 1; x + 5189, 1; x + 5202, 1; x + 5207 , 1; x + 5209, 1; x + 5211, 1; x + 5216, 1; x + 5219, 1; x + 5232, 1; x + 52 46, 1; x + 5268, 1; x + 5275, 1; x + 5287, 1; x + 5289, 1; x + 5349, 1; x + 5368, 1; x + 5370, 1; x + 5386, 1; x + 5406, 1; x + 5410, 1; x + 5411, 1; x + 5412, 1; x + 5416, 1; x + 5461, 1; x + 5464, 1; x + 5478, 1; x + 5508, 1; x + 5509, 1; x + 5518, 1; x + 5526, 1; x + 5530, 1; x + 5547, 1; x + 5588, 1 ; x + 5596, 1; x + 5598, 1; x + 5604, 1; x + 5609, 1; x + 5618, 1; x + 5646, 1; x + 5650, 1; x + 5653, 1; x + 5662, 1; x + 5672, 1; x + 5673, 1; x + 567 6, 1; x + 5690, 1; x + 5703, 1; x + 5724, 1; x + 5734, 1; x + 5776, 1; x + 5 781, 1; x + 5784, 1; x + 5789, 1; x + 5797, 1; x + 5808, 1; x + 5826, 1; x + 5832, 1; x + 5835, 1; x + 5836, 1; x + 5845, 1; x + 5900, 1; x + 5959, 1; x + 5966, 1; x + 5969, 1; x + 5987, 1; x + 5993, 1; x + 6026, 1; x + 6063, 1; x + 6085, 1; x + 6086, 1; x + 6092, 1; x + 6094, 1; x + 6105, 1; x + 6125, 1; x + 6127, 1; x + 6138, 1; x + 6151, 1; x + 6162, 1; x + 6164, 1; x + 6184 , 1; x + 6195, 1; x + 6197, 1; x + 6203, 1; x + 6204, 1; x + 6226, 1; x + 62 63, 1; x + 6296, 1; x + 6302, 1; x + 6320, 1; x + 6323, 1; x + 6330, 1; x + 6389, 1; x + 6444, 1; x + 6453, 1; x + 6454, 1; x + 6457, 1; x + 6463, 1; x + 6481, 1; x + 6492, 1; x + 6500, 1; x + 6505, 1; x + 6508, 1; x + 6513, 1; x + 6555, 1; x + 6565, 1; x + 6586, 1; x + 6599, 1; x + 6613, 1; x + 6616, 1 ; x + 6617, 1; x + 6627, 1; x + 6636, 1; x + 6639, 1; x + 6643, 1; x + 6671, 1; x + 6680, 1; x + 6685, 1; x + 6691, 1; x + 6693, 1; x + 6701, 1; x + 674 2, 1; x + 6759, 1; x + 6763, 1; x + 6771, 1; x + 6780, 1; x + 6781, 1; x + 6 811, 1; x + 6825, 1; x + 6828, 1; x + 6873, 1; x + 6877, 1; x + 6878, 1; x + 6879, 1; x + 6883, 1; x + 6903, 1; x + 6919, 1; x + 6921, 1; x + 6940, 1; x + 7000, 1; x + 7002, 1; x + 7014, 1; x + 7021, 1; x + 7043, 1; x + 7057, 1; x + 7070, 1; x + 7073, 1; x + 7078, 1; x + 7080, 1; x + 7082, 1; x + 7087, 1; x + 7100, 1; x + 7119, 1; x + 7126, 1; x + 7154, 1; x + 7171, 1; x + 7174 , 1; x + 7186, 1; x + 7187, 1; x + 7207, 1; x + 7211, 1; x + 7226, 1; x + 72 28, 1; x + 7235, 1; x + 7246, 1; x + 7250, 1; x + 7287, 1; x + 7302, 1; x + 7315, 1; x + 7326, 1; x + 7350, 1; x + 7365, 1; x + 7376, 1; x + 7383, 1; x + 7406, 1; x + 7429, 1; x + 7434, 1; x + 7449, 1; x + 7455, 1; x + 7469, 1; x + 7508, 1; x + 7519, 1; x + 7550, 1; x + 7559, 1; x + 7562, 1; x + 7570, 1 ; x + 7584, 1; x + 7592, 1; x + 7596, 1; x + 7605, 1; x + 7619, 1; x + 7624, 1; x + 7628, 1; x + 7640, 1; x + 7681, 1; x + 7684, 1; x + 7699, 1; x + 771 1, 1; x + 7723, 1; x + 7724, 1; x + 7725, 1; x + 7735, 1; x + 7751, 1; x + 7 766, 1; x + 7771, 1; x + 7779, 1; x + 7784, 1; x + 7785, 1; x + 7790, 1; x + 7800, 1; x + 7806, 1; x + 7814, 1; x + 7846, 1; x + 7866, 1; x + 7878, 1; x + 7885, 1; x + 7899, 1; x + 7911, 1; x + 7929, 1; x + 7937, 1; x + 7954, 1; x + 7988, 1; x + 8000, 1; x + 8016, 1; x + 8022, 1; x + 8024, 1; x + 8038, 1; x + 8051, 1; x + 8054, 1; x + 8062, 1; x + 8067, 1; x + 8071, 1; x + 8080 , 1; x + 8095, 1; x + 8113, 1; x + 8122, 1; x + 8136, 1; x + 8144, 1; x + 81 51, 1; x + 8170, 1; x + 8176, 1; x + 8186, 1; x + 8190, 1; x + 8195, 1; x + 8239, 1; x + 8257, 1; x + 8307, 1; x + 8308, 1; x + 8314, 1; x + 8328, 1; x + 8330, 1; x + 8342, 1; x + 8345, 1; x + 8347, 1; x + 8348, 1; x + 8360, 1; x + 8400, 1; x + 8420, 1; x + 8443, 1; x + 8449, 1; x + 8452, 1; x + 8464, 1 ; x + 8468, 1; x + 8474, 1; x + 8481, 1; x + 8484, 1; x + 8494, 1; x + 8496, 1; x + 8520, 1; x + 8524, 1; x + 8531, 1; x + 8536, 1; x + 8545, 1; x + 856 6, 1; x + 8581, 1; x + 8611, 1; x + 8619, 1; x + 8620, 1; x + 8635, 1; x + 8 665, 1; x + 8682, 1; x + 8700, 1; x + 8711, 1; x + 8717, 1; x + 8753, 1; x + 8755, 1; x + 8761, 1; x + 8774, 1; x + 8778, 1; x + 8787, 1; x + 8794, 1; x + 8809, 1; x + 8820, 1; x + 8823, 1; x + 8835, 1; x + 8838, 1; x + 8840, 1; x + 8841, 1; x + 8871, 1; x + 8881, 1; x + 8882, 1; x + 8896, 1; x + 8914, 1; x + 8921, 1; x + 8929, 1; x + 8930, 1; x + 8945, 1; x + 8946, 1; x + 8951 , 1; x + 8957, 1; x + 8972, 1; x + 9004, 1; x + 9011, 1; x + 9013, 1; x + 90 21, 1; x + 9051, 1; x + 9057, 1; x + 9060, 1; x + 9068, 1; x + 9084, 1; x + 9089, 1; x + 9118, 1; x + 9126, 1; x + 9135, 1; x + 9168, 1; x + 9169, 1; x + 9173, 1; x + 9175, 1; x + 9195, 1; x + 9199, 1; x + 9202, 1; x + 9224, 1; x + 9233, 1; x + 9244, 1; x + 9247, 1; x + 9261, 1; x + 9269, 1; x + 9270, 1 ; x + 9272, 1; x + 9282, 1; x + 9307, 1; x + 9332, 1; x + 9342, 1; x + 9343, 1; x + 9344, 1; x + 9348, 1; x + 9349, 1; x + 9360, 1; x + 9363, 1; x + 938 9, 1; x + 9395, 1; x + 9416, 1; x + 9449, 1; x + 9457, 1; x + 9461, 1; x + 9 462, 1; x + 9489, 1; x + 9513, 1; x + 9520, 1; x + 9559, 1; x + 9572, 1; x + 9577, 1; x + 9600, 1; x + 9615, 1; x + 9617, 1; x + 9646, 1; x + 9652, 1; x + 9656, 1; x + 9663, 1; x + 9667, 1; x + 9687, 1; x + 9689, 1; x + 9694, 1; x + 9696, 1; x + 9714, 1; x + 9754, 1; x + 9757, 1; x + 9761, 1; x + 9804, 1; x + 9806, 1; x + 9811, 1; x + 9828, 1; x + 9834, 1; x + 9839, 1; x + 9847 , 1; x + 9855, 1; x + 9860, 1; x + 9916, 1; x + 9929, 1; x + 9951, 1; x + 99 55, 1; x + 9982, 1; x + 9988, 1; x + 9996, 1; x + 9998, 1; x + 10013, 1; x + 10014, 1; x + 10029, 1; x + 10032, 1; x + 10036, 1; x + 10058, 1; x + 10076 , 1; x + 10077, 1; x + 10080, 1; x + 10104, 1; x + 10118, 1; x + 10125, 1; x + 10138, 1; x + 10141, 1; x + 10179, 1; x + 10221, 1; x + 10224, 1; x + 102 35, 1; x + 10243, 1; x + 10254, 1; x + 10268, 1; x + 10344, 1; x + 10345, 1; x + 10347, 1; x + 10353, 1; x + 10361, 1; x + 10362, 1; x + 10381, 1; x + 1 0388, 1; x + 10397, 1; x + 10398, 1; x + 10407, 1; x + 10421, 1; x + 10423, 1; x + 10440, 1; x + 10447, 1; x + 10453, 1; x + 10463, 1; x + 10485, 1; x + 10487, 1; x + 10499, 1; x + 10506, 1; x + 10526, 1; x + 10533, 1; x + 10545 , 1; x + 10552, 1; x + 10555, 1; x + 10568, 1; x + 10583, 1; x + 10584, 1; x + 10588, 1; x + 10595, 1; x + 10602, 1; x + 10608, 1; x + 10631, 1; x + 106 69, 1; x + 10699, 1; x + 10716, 1; x + 10734, 1; x + 10753, 1; x + 10754, 1; x + 10759, 1; x + 10763, 1; x + 10767, 1; x + 10771, 1; x + 10783, 1; x + 1 0808, 1; x + 10821, 1; x + 10844, 1; x + 10872, 1; x + 10880, 1; x + 10883, 1; x + 10886, 1; x + 10891, 1; x + 10897, 1; x + 10900, 1; x + 10916, 1; x + 10918, 1; x + 10939, 1; x + 10945, 1; x + 10962, 1; x + 10964, 1; x + 10975 , 1; x + 11007, 1; x + 11009, 1; x + 11010, 1; x + 11014, 1; x + 11024, 1; x + 11034, 1; x + 11038, 1; x + 11041, 1; x + 11048, 1; x + 11053, 1; x + 110 63, 1; x + 11066, 1; x + 11071, 1; x + 11081, 1; x + 11111, 1; x + 11113, 1; x + 11124, 1; x + 11129, 1; x + 11153, 1; x + 11158, 1; x + 11164, 1; x + 1 1169, 1; x + 11194, 1; x + 11197, 1; x + 11232, 1; x + 11249, 1; x + 11251, 1; x + 11259, 1; x + 11260, 1; x + 11274, 1; x + 11275, 1; x + 11295, 1; x + 11307, 1; x + 11309, 1; x + 11345, 1; x + 11366, 1; x + 11379, 1; x + 11385 , 1; x + 11408, 1; x + 11410, 1; x + 11415, 1; x + 11424, 1; x + 11444, 1; x + 11445, 1; x + 11463, 1; x + 11475, 1; x + 11498, 1; x + 11511, 1; x + 115 20, 1; x + 11522, 1; x + 11538, 1; x + 11572, 1; x + 11573, 1; x + 11607, 1; x + 11641, 1; x + 11653, 1; x + 11667, 1; x + 11675, 1; x + 11677, 1; x + 1 1710, 1; x + 11711, 1; x + 11722, 1; x + 11749, 1; x + 11759, 1; x + 11777, 1; x + 11779, 1; x + 11783, 1; x + 11787, 1; x + 11823, 1; x + 11825, 1; x + 11826, 1; x + 11832, 1; x + 11839, 1; x + 11841, 1; x + 11851, 1; x + 11864 , 1; x + 11872, 1; x + 11873, 1; x + 11877, 1; x + 11883, 1; x + 11897, 1; x + 11912, 1; x + 11914, 1; x + 11924, 1; x + 11925, 1; x + 11943, 1; x + 119 46, 1; x + 11951, 1; x + 11996, 1; x + 12050, 1; x + 12073, 1; x + 12077, 1; x + 12085, 1; x + 12096, 1; x + 12100, 1; x + 12109, 1; x + 12119, 1; x + 1 2139, 1; x + 12143, 1; x + 12150, 1; x + 12164, 1; x + 12217, 1; x + 12221, 1; x + 12226, 1; x + 12229, 1; x + 12239, 1; x + 12265, 1; x + 12268, 1; x + 12269, 1; x + 12281, 1; x + 12282, 1] [ y + 697093550 1] [y + 1551133506 1] [y + 2227781066 1] [x 1] [x^3 + x^2 + 1 1] [x^27 + x^25 + x^24 + x^23 + x^22 + x^17 + x^16 + x^15 + x^13 + x^12 + x^9 + x^8 + x^4 + x + 1 1] [Mod(1, 41), Mod(3, 41), Mod(9, 41), Mod(14, 41), Mod(27, 41), Mod(32, 41), Mod(38, 41), Mod(40, 41)]~ [Mod(1, 5), Mod(2, 5)]~ *** at top-level: polrootsmod(Pol(0),2 *** ^-------------------- *** polrootsmod: zero polynomial in rootmod. []~ [ Mod(1, 2)*x 1] [Mod(1, 2)*x + Mod(1, 2) 2] [Mod(0, 2) 1] [;] [1 1] [1 2] [2 1] [Mod(1, 7), Mod(2, 7), Mod(3, 7), Mod(5, 7), Mod(6, 7)]~ *** at top-level: polrootsmod(Pol(0),p *** ^-------------------- *** polrootsmod: zero polynomial in rootmod. []~ [Mod(0, 18446744073709551629)]~ [Mod(9223372036854775814, 18446744073709551629)]~ [Mod(1, 18446744073709551629)*x + Mod(2370518075556110396, 18446744073709551 629) 1] [Mod(1, 18446744073709551629)*x + Mod(16076225998153441233, 1844674407370955 1629) 1] [1 1] [1 1] [2 1] [Mod(1, 18446744073709551629)*x + Mod(2370518075556110396, 18446744073709551 629) 1] [Mod(1, 18446744073709551629)*x + Mod(16076225998153441233, 1844674407370955 1629) 1] [Mod(0, 18446744073709551629) 1] [;] 1 0 Total time spent: 56 pari-2.7.5/src/test/32/subcyclo0000644000175000017500000000014611636712103014647 0ustar billbillx - 1 [x^2 - 2, x^2 - 131, x^2 + 262, x^2 + 1, x^2 - 262, x^2 + 2, x^2 + x + 33] Total time spent: 16 pari-2.7.5/src/test/32/agm0000644000175000017500000000023112453017374013571 0ustar billbill *** 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 pari-2.7.5/src/test/32/lex0000644000175000017500000000047112314242551013614 0ustar billbill[1, 1, 0] [1, 2, -1] [1, 3, -1] [1, 4, -1] [1, 5, -1] [1, 6, -1] [1, 7, -1] [2, 2, 0] [2, 3, 1] [2, 4, 1] [2, 5, 1] [2, 6, 1] [2, 7, 1] [3, 3, 0] [3, 4, -1] [3, 5, 1] [3, 6, -1] [3, 7, -1] [4, 4, 0] [4, 5, 1] [4, 6, 1] [4, 7, -1] [5, 5, 0] [5, 6, -1] [5, 7, -1] [6, 6, 0] [6, 7, -1] [7, 7, 0] Total time spent: 0 pari-2.7.5/src/test/32/combinat0000644000175000017500000000554712366172547014647 0ustar billbill[3628800, -10628640, 12753576, -8409500, 3416930, -902055, 157773, -18150, 1 320, -55] [-39916800, 120543840, -150917976, 105258076, -45995730, 13339535, -2637558, 357423, -32670, 1925, -66] [1, 1023, 28501, 145750, 246730, 179487, 63987, 11880, 1155, 55] [1, 2047, 86526, 611501, 1379400, 1323652, 627396, 159027, 22275, 1705, 66] [[1, 2, 3, 4, 5], [1, 2, 3, 5, 4], [1, 2, 4, 3, 5], [1, 2, 4, 5, 3], [1, 2, 5, 3, 4], [1, 2, 5, 4, 3], [1, 3, 2, 4, 5], [1, 3, 2, 5, 4], [1, 3, 4, 2, 5] , [1, 3, 4, 5, 2], [1, 3, 5, 2, 4], [1, 3, 5, 4, 2], [1, 4, 2, 3, 5], [1, 4, 2, 5, 3], [1, 4, 3, 2, 5], [1, 4, 3, 5, 2], [1, 4, 5, 2, 3], [1, 4, 5, 3, 2 ], [1, 5, 2, 3, 4], [1, 5, 2, 4, 3], [1, 5, 3, 2, 4], [1, 5, 3, 4, 2], [1, 5 , 4, 2, 3], [1, 5, 4, 3, 2], [2, 1, 3, 4, 5], [2, 1, 3, 5, 4], [2, 1, 4, 3, 5], [2, 1, 4, 5, 3], [2, 1, 5, 3, 4], [2, 1, 5, 4, 3], [2, 3, 1, 4, 5], [2, 3, 1, 5, 4], [2, 3, 4, 1, 5], [2, 3, 4, 5, 1], [2, 3, 5, 1, 4], [2, 3, 5, 4, 1], [2, 4, 1, 3, 5], [2, 4, 1, 5, 3], [2, 4, 3, 1, 5], [2, 4, 3, 5, 1], [2, 4, 5, 1, 3], [2, 4, 5, 3, 1], [2, 5, 1, 3, 4], [2, 5, 1, 4, 3], [2, 5, 3, 1 , 4], [2, 5, 3, 4, 1], [2, 5, 4, 1, 3], [2, 5, 4, 3, 1], [3, 1, 2, 4, 5], [3 , 1, 2, 5, 4], [3, 1, 4, 2, 5], [3, 1, 4, 5, 2], [3, 1, 5, 2, 4], [3, 1, 5, 4, 2], [3, 2, 1, 4, 5], [3, 2, 1, 5, 4], [3, 2, 4, 1, 5], [3, 2, 4, 5, 1], [ 3, 2, 5, 1, 4], [3, 2, 5, 4, 1], [3, 4, 1, 2, 5], [3, 4, 1, 5, 2], [3, 4, 2, 1, 5], [3, 4, 2, 5, 1], [3, 4, 5, 1, 2], [3, 4, 5, 2, 1], [3, 5, 1, 2, 4], [3, 5, 1, 4, 2], [3, 5, 2, 1, 4], [3, 5, 2, 4, 1], [3, 5, 4, 1, 2], [3, 5, 4 , 2, 1], [4, 1, 2, 3, 5], [4, 1, 2, 5, 3], [4, 1, 3, 2, 5], [4, 1, 3, 5, 2], [4, 1, 5, 2, 3], [4, 1, 5, 3, 2], [4, 2, 1, 3, 5], [4, 2, 1, 5, 3], [4, 2, 3, 1, 5], [4, 2, 3, 5, 1], [4, 2, 5, 1, 3], [4, 2, 5, 3, 1], [4, 3, 1, 2, 5] , [4, 3, 1, 5, 2], [4, 3, 2, 1, 5], [4, 3, 2, 5, 1], [4, 3, 5, 1, 2], [4, 3, 5, 2, 1], [4, 5, 1, 2, 3], [4, 5, 1, 3, 2], [4, 5, 2, 1, 3], [4, 5, 2, 3, 1 ], [4, 5, 3, 1, 2], [4, 5, 3, 2, 1], [5, 1, 2, 3, 4], [5, 1, 2, 4, 3], [5, 1 , 3, 2, 4], [5, 1, 3, 4, 2], [5, 1, 4, 2, 3], [5, 1, 4, 3, 2], [5, 2, 1, 3, 4], [5, 2, 1, 4, 3], [5, 2, 3, 1, 4], [5, 2, 3, 4, 1], [5, 2, 4, 1, 3], [5, 2, 4, 3, 1], [5, 3, 1, 2, 4], [5, 3, 1, 4, 2], [5, 3, 2, 1, 4], [5, 3, 2, 4, 1], [5, 3, 4, 1, 2], [5, 3, 4, 2, 1], [5, 4, 1, 2, 3], [5, 4, 1, 3, 2], [5, 4, 2, 1, 3], [5, 4, 2, 3, 1], [5, 4, 3, 1, 2], [5, 4, 3, 2, 1]] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2 1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 4 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 5 9, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 7 8, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 9 7, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119] 0 Total time spent: 4 pari-2.7.5/src/test/32/digits0000644000175000017500000000306312405547147014321 0ustar billbill[] [] [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] 0 12 135 1938780 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0] [[0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0 , 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0 , 0, 0, 1, 0, 1, 0, 0, 1, 0, 0]] [[1], [0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 , 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 , 0, 1]] [[], [1]] *** at top-level: binary(I) *** ^--------- *** binary: incorrect type in binary (t_COMPLEX). Total time spent: 112 pari-2.7.5/src/test/32/primes0000644000175000017500000000132712502252164014324 0ustar billbill[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 *** at top-level: primes([1,Pol(2)]) *** ^------------------ *** primes: incorrect type in primes_interval (t_POL). Total time spent: 488 pari-2.7.5/src/test/32/size0000644000175000017500000000025212366172547014011 0ustar billbill1 1 1 0 3 3 [1, 3] [3, 1] [2, 3] *** at top-level: matsize(1) *** ^---------- *** matsize: incorrect type in matsize (t_INT). Total time spent: 4 pari-2.7.5/src/test/32/modpr0000644000175000017500000002432012366172547014162 0ustar billbill *** at top-level: nfeltmulmodpr(nfinit *** ^-------------------- *** nfeltmulmodpr: incorrect type in checkprid (t_INT). (P)->my(f);print(K.pol,": ",P);f=[nfeltdivmodpr,nfeltmulmodpr];for(i=1,#v,fo r(j=i,#v,print("*",[i,j],":");for(k=1,#f,print(iferr(f[k](K,v[i],v[j],P),E,E )))));f=[(K,x,P)->nfeltpowmodpr(K,x,-3,P),nfeltreducemodpr];for(i=1,#v,print ("*",i,":");for(k=1,#f,print(iferr(f[k](K,v[i],P),E,E)))) y^2 + 1: [[1, 0]~, [1, 1], [2, [1, 1]~, 2, 1, [1, -1; 1, 1]]]~ *[1, 1]: error("impossible inverse in dvmdii: 0.") [0, 0]~ *[1, 2]: [0, 0]~ [0, 0]~ *[1, 3]: [0, 0]~ [0, 0]~ *[1, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[1, 5]: [0, 0]~ [0, 0]~ *[1, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[2, 2]: [1, 0]~ [1, 0]~ *[2, 3]: [1, 0]~ [1, 0]~ *[2, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[2, 5]: error("impossible inverse in Rg_to_ff: Mod(0, 2).") [0, 0]~ *[2, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[3, 3]: [1, 0]~ [1, 0]~ *[3, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[3, 5]: error("impossible inverse in Rg_to_ff: Mod(0, 2).") [0, 0]~ *[3, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[4, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 5]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("inconsistent variables in poltobasis, z != y.") *[5, 5]: [1, 0]~ [0, 0]~ *[5, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[6, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *1: error("impossible inverse in Fl_inv: Mod(0, 2).") [0, 0]~ *2: [1, 0]~ [1, 0]~ *3: [1, 0]~ [1, 0]~ *4: error("inconsistent variables in poltobasis, z != y.") error("inconsistent variables in poltobasis, z != y.") *5: error("impossible inverse in Fl_inv: Mod(0, 2).") [0, 0]~ *6: error("incorrect type in Rg_to_ff (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") y^2 + 1: [[1, 0]~, [1, 0; 0, 1], [3, [3, 0]~, 1, 2, 1], y^2 + 1]~ *[1, 1]: error("impossible inverse in dvmdii: 0.") [0, 0]~ *[1, 2]: [0, 0]~ error("impossible inverse in Fl_inv: Mod(0, 3).") *[1, 3]: [0, 0]~ [0, 0]~ *[1, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[1, 5]: [0, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[1, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[2, 2]: [1, 0]~ error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 3]: error("impossible inverse in Rg_to_ff: Mod(0, 3).") error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 5]: [0, 2]~ error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("impossible inverse in Fl_inv: Mod(0, 3).") *[3, 3]: [1, 0]~ [2, 0]~ *[3, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[3, 5]: [0, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[3, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[4, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 5]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("inconsistent variables in poltobasis, z != y.") *[5, 5]: [1, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[5, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[6, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *1: error("impossible inverse in Fl_inv: Mod(0, 3).") [0, 0]~ *2: error("impossible inverse in Fl_inv: Mod(0, 3).") error("impossible inverse in Fl_inv: Mod(0, 3).") *3: [0, 1]~ [0, 1]~ *4: error("inconsistent variables in poltobasis, z != y.") error("inconsistent variables in poltobasis, z != y.") *5: error("impossible inverse in Rg_to_ff: Mod(0, 3).") error("impossible inverse in Rg_to_ff: Mod(0, 3).") *6: error("incorrect type in Rg_to_ff (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") y^3 - 9: [[1, 0, 0]~, [1, 0, 0], [3, [0, 1, 0]~, 3, 1, [0, 3, 0; 0, 0, 3; 1, 0, 0]]]~ *[1, 1]: error("impossible inverse in dvmdii: 0.") [0, 0, 0]~ *[1, 2]: [0, 0, 0]~ error("impossible inverse in Fl_inv: Mod(0, 3).") *[1, 3]: [0, 0, 0]~ [0, 0, 0]~ *[1, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[1, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[1, 6]: [0, 0, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[2, 2]: [1, 0, 0]~ error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 3]: error("impossible inverse in Rg_to_ff: Mod(0, 3).") error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("impossible inverse in Fl_inv: Mod(0, 3).") *[2, 6]: error("impossible inverse in Rg_to_ff: Mod(0, 3).") error("impossible inverse in Fl_inv: Mod(0, 3).") *[3, 3]: [1, 0, 0]~ [0, 0, 0]~ *[3, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[3, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[3, 6]: [0, 0, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *[4, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("inconsistent variables in poltobasis, z != y.") *[4, 6]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[5, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[5, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[6, 6]: [1, 0, 0]~ error("impossible inverse in Rg_to_ff: Mod(0, 3).") *1: error("impossible inverse in Fl_inv: Mod(0, 3).") [0, 0, 0]~ *2: error("impossible inverse in Fl_inv: Mod(0, 3).") error("impossible inverse in Fl_inv: Mod(0, 3).") *3: error("impossible inverse in Fl_inv: Mod(0, 3).") [0, 0, 0]~ *4: error("inconsistent variables in poltobasis, z != y.") error("inconsistent variables in poltobasis, z != y.") *5: error("incorrect type in Rg_to_ff (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *6: error("impossible inverse in Rg_to_ff: Mod(0, 3).") error("impossible inverse in Rg_to_ff: Mod(0, 3).") y^3 - 9: [[2, 1, 1]~, [1, 1, 0; 0, 1, 1], [2, [3, 3, 1]~, 1, 2, [1, 3, 0; 0, 1, 3; 1, 0, 1]], y^2 + y + 1]~ *[1, 1]: error("impossible inverse in dvmdii: 0.") [0, 0, 0]~ *[1, 2]: [0, 0, 0]~ [0, 0, 0]~ *[1, 3]: [0, 0, 0]~ [0, 0, 0]~ *[1, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[1, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[1, 6]: [0, 0, 0]~ [0, 0, 0]~ *[2, 2]: [1, 0, 0]~ [1, 0, 0]~ *[2, 3]: [1, 0, 1]~ [0, 0, 1]~ *[2, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[2, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[2, 6]: error("impossible inverse in Rg_to_ff: Mod(0, 2).") [0, 0, 0]~ *[3, 3]: [1, 0, 0]~ [1, 0, 1]~ *[3, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[3, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[3, 6]: error("impossible inverse in Rg_to_ff: Mod(0, 2).") [0, 0, 0]~ *[4, 4]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[4, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("inconsistent variables in poltobasis, z != y.") *[4, 6]: error("inconsistent variables in nf_to_scalar_or_alg, z != y.") error("inconsistent variables in poltobasis, z != y.") *[5, 5]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[5, 6]: error("incorrect type in nf_to_scalar_or_alg (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *[6, 6]: [1, 0, 0]~ [0, 0, 0]~ *1: error("impossible inverse in Fl_inv: Mod(0, 2).") [0, 0, 0]~ *2: [1, 0, 0]~ [1, 0, 0]~ *3: [1, 0, 0]~ [0, 0, 1]~ *4: error("inconsistent variables in poltobasis, z != y.") error("inconsistent variables in poltobasis, z != y.") *5: error("incorrect type in Rg_to_ff (t_COL).") error("incorrect type in Rg_to_ff (t_COL).") *6: error("impossible inverse in Flxq_inv: 0.") [0, 0, 0]~ [1, 0]~ [x + 1 3] [1, y]~ [;] [0, 1]~ [ y y^2] [y^2 y^3] [1] [1] *** at top-level: nfsolvemodpr(K,m,v,P *** ^-------------------- *** nfsolvemodpr: impossible inverse in nfsolvemodpr: [1, 1; 1, 1]. *** at top-level: nfsolvemodpr(K,m,m,P *** ^-------------------- *** nfsolvemodpr: impossible inverse in nfsolvemodpr: [1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ Total time spent: 244 pari-2.7.5/src/test/32/mat0000644000175000017500000002423112456464240013615 0ustar billbillerror("inconsistent addition t_MAT (1x1) + t_MAT (0x1).") error("impossible inverse in gdiv: [Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2)].") [0, 2] 1 1 [[;], [;]] [[], [;]] *** at top-level: mathouseholder(1,1) *** ^------------------- *** mathouseholder: incorrect type in mathouseholder (t_INT). *** at top-level: mathouseholder(q,1) *** ^------------------- *** mathouseholder: incorrect type in mathouseholder (t_INT). [;] [1] [1 2 3] [2 3 4] [1 1] [1 5] [1 0] [0 1] error("incorrect type in diagonal (t_MAT).") [1 0 0 0 0] [1 1 0 0 0] [1 3/2 1 0 0] [1 7/4 7/4 1 0] [1 15/8 35/16 15/8 1] [ 4 6] [10 12] [0 -2] [2 4] [0 0] [Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2)] [Mod(0, 7) Mod(5, 7)] [Mod(2, 7) Mod(4, 7)] [Mod(0, 7) Mod(0, 7)] [Mod(0, 18446744073709551629) Mod(18446744073709551627, 18446744073709551629 )] [Mod(2, 18446744073709551629) Mod(4, 18446744073709551629 )] [Mod(0, 18446744073709551629) Mod(0, 18446744073709551629 )] [Mod(0, 3037000507) Mod(3037000505, 3037000507)] [Mod(2, 3037000507) Mod(4, 3037000507)] [Mod(0, 3037000507) Mod(0, 3037000507)] [Mod(0, 2), Mod(0, 2), Mod(0, 2)]~ [Mod(0, 7), Mod(2, 7), Mod(0, 7)]~ [Mod(0, 18446744073709551629), Mod(2, 18446744073709551629), Mod(0, 18446744 073709551629)]~ [Mod(0, 3037000507), Mod(2, 3037000507), Mod(0, 3037000507)]~ matdet: Mod(1, 2) Mod(1, 7) Mod(29, 3037000507) Mod(29, 18446744073709551629) 29 + O(101^3) matrank: 3 3 3 3 3 matadjoint: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(0, 7), Mod(1, 7); Mod(6, 7), Mod(3, 7), Mod(1, 7); Mod(1, 7) , Mod(2, 7), Mod(1, 7)] [Mod(69, 3037000507), Mod(14, 3037000507), Mod(3037000473, 3037000507); Mod( 3037000499, 3037000507), Mod(3, 3037000507), Mod(1, 3037000507); Mod(3037000 501, 3037000507), Mod(3037000502, 3037000507), Mod(8, 3037000507)] [Mod(69, 18446744073709551629), Mod(14, 18446744073709551629), Mod(184467440 73709551595, 18446744073709551629); Mod(18446744073709551621, 18446744073709 551629), Mod(3, 18446744073709551629), Mod(1, 18446744073709551629); Mod(184 46744073709551623, 18446744073709551629), Mod(18446744073709551624, 18446744 073709551629), Mod(8, 18446744073709551629)] [69 + O(101^3), 14 + O(101^3), 67 + 100*101 + 100*101^2 + O(101^3); 93 + 100 *101 + 100*101^2 + O(101^3), 3 + O(101^3), 1 + O(101^3); 95 + 100*101 + 100* 101^2 + O(101^3), 96 + 100*101 + 100*101^2 + O(101^3), 8 + O(101^3)] matimage: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(1, 2)] [Mod(1, 7), Mod(2, 7), Mod(4, 7); Mod(2, 7), Mod(5, 7), Mod(0, 7); Mod(2, 7) , Mod(2, 7), Mod(4, 7)] [Mod(1, 3037000507), Mod(2, 3037000507), Mod(4, 3037000507); Mod(2, 30370005 07), Mod(12, 3037000507), Mod(7, 3037000507); Mod(2, 3037000507), Mod(9, 303 7000507), Mod(11, 3037000507)] [Mod(1, 18446744073709551629), Mod(2, 18446744073709551629), Mod(4, 18446744 073709551629); Mod(2, 18446744073709551629), Mod(12, 18446744073709551629), Mod(7, 18446744073709551629); Mod(2, 18446744073709551629), Mod(9, 184467440 73709551629), Mod(11, 18446744073709551629)] [1 + O(101^3), 2 + O(101^3), 4 + O(101^3); 2 + O(101^3), 12 + O(101^3), 7 + O(101^3); 2 + O(101^3), 9 + O(101^3), 11 + O(101^3)] matimagecompl: Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) matindexrank: [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] matker: [;] [;] [;] [;] [;] lindep: []~ []~ []~ []~ []~ (x)->matsolve(x,vectorv(#x,i,i)): [Mod(1, 2), Mod(1, 2), Mod(0, 2)]~ [Mod(2, 7), Mod(1, 7), Mod(1, 7)]~ [Mod(2827552196, 3037000507), Mod(1256689865, 3037000507), Mod(942517399, 30 37000507)]~ [Mod(16538460204015460081, 18446744073709551629), Mod(11449703218164549287, 18446744073709551629), Mod(17810649450478187780, 18446744073709551629)]~ [66 + 69*101 + 62*101^2 + O(101^3), 7 + 87*101 + 27*101^2 + O(101^3), 56 + 9 0*101 + 20*101^2 + O(101^3)]~ (x)->matsolve(x,matrix(#x,#x,i,j,i+j)): [Mod(0, 2), Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(1, 2), Mod(1, 2); Mod(1, 2) , Mod(0, 2), Mod(1, 2)] [Mod(2, 7), Mod(2, 7), Mod(2, 7); Mod(4, 7), Mod(0, 7), Mod(3, 7); Mod(5, 7) , Mod(2, 7), Mod(6, 7)] [Mod(628344934, 3037000507), Mod(1466138179, 3037000507), Mod(2303931424, 30 37000507); Mod(2303931419, 3037000507), Mod(314172466, 3037000507), Mod(1361 414020, 3037000507); Mod(209448311, 3037000507), Mod(2513379730, 3037000507) , Mod(1780310642, 3037000507)] [Mod(5724851609082274645, 18446744073709551629), Mod(13357987087858640838, 1 8446744073709551629), Mod(2544378492925455402, 18446744073709551629); Mod(25 44378492925455397, 18446744073709551629), Mod(12085797841395913136, 18446744 073709551629), Mod(3180473116156819246, 18446744073709551629); Mod(190828386 9694091548, 18446744073709551629), Mod(4452662362619546945, 1844674407370955 1629), Mod(6997040855545002342, 18446744073709551629)] [5 + 94*101 + 13*101^2 + O(101^3), 45 + 17*101 + 66*101^2 + O(101^3), 85 + 4 1*101 + 17*101^2 + O(101^3); 80 + 41*101 + 17*101^2 + O(101^3), 52 + 97*101 + 6*101^2 + O(101^3), 24 + 52*101 + 97*101^2 + O(101^3); 35 + 31*101 + 38*10 1^2 + O(101^3), 14 + 73*101 + 55*101^2 + O(101^3), 94 + 13*101 + 73*101^2 + O(101^3)] (x)->x^(-1): [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(0, 7), Mod(1, 7); Mod(6, 7), Mod(3, 7), Mod(1, 7); Mod(1, 7) , Mod(2, 7), Mod(1, 7)] [Mod(1675586489, 3037000507), Mod(2408655575, 3037000507), Mod(2827552195, 3 037000507); Mod(2094483108, 3037000507), Mod(733069088, 3037000507), Mod(125 6689865, 3037000507); Mod(1570862331, 3037000507), Mod(2827552196, 303700050 7), Mod(942517399, 3037000507)] [Mod(15266270957552732385, 18446744073709551629), Mod(12721892464627276986, 18446744073709551629), Mod(16538460204015460080, 18446744073709551629); Mod( 636094623231363849, 18446744073709551629), Mod(15902365580784096232, 1844674 4073709551629), Mod(11449703218164549287, 18446744073709551629); Mod(5088756 985850910794, 18446744073709551629), Mod(16538460204015460081, 1844674407370 9551629), Mod(17810649450478187780, 18446744073709551629)] [79 + 48*101 + 3*101^2 + O(101^3), 98 + 6*101 + 87*101^2 + O(101^3), 65 + 69 *101 + 62*101^2 + O(101^3); 45 + 10*101 + 80*101^2 + O(101^3), 21 + 59*101 + 83*101^2 + O(101^3), 7 + 87*101 + 27*101^2 + O(101^3); 59 + 83*101 + 34*101 ^2 + O(101^3), 66 + 69*101 + 62*101^2 + O(101^3), 56 + 90*101 + 20*101^2 + O (101^3)] (x)->x^2: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(6, 7), Mod(6, 7); Mod(5, 7), Mod(1, 7), Mod(1, 7); Mod(0, 7) , Mod(1, 7), Mod(3, 7)] [Mod(13, 3037000507), Mod(62, 3037000507), Mod(62, 3037000507); Mod(40, 3037 000507), Mod(211, 3037000507), Mod(169, 3037000507); Mod(42, 3037000507), Mo d(211, 3037000507), Mod(192, 3037000507)] [Mod(13, 18446744073709551629), Mod(62, 18446744073709551629), Mod(62, 18446 744073709551629); Mod(40, 18446744073709551629), Mod(211, 184467440737095516 29), Mod(169, 18446744073709551629); Mod(42, 18446744073709551629), Mod(211, 18446744073709551629), Mod(192, 18446744073709551629)] [13 + O(101^3), 62 + O(101^3), 62 + O(101^3); 40 + O(101^3), 9 + 2*101 + O(1 01^3), 68 + 101 + O(101^3); 42 + O(101^3), 9 + 2*101 + O(101^3), 91 + 101 + O(101^3)] (x)->A*x: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(6, 7), Mod(6, 7); Mod(5, 7), Mod(1, 7), Mod(1, 7); Mod(0, 7) , Mod(1, 7), Mod(3, 7)] [Mod(13, 3037000507), Mod(62, 3037000507), Mod(62, 3037000507); Mod(40, 3037 000507), Mod(211, 3037000507), Mod(169, 3037000507); Mod(42, 3037000507), Mo d(211, 3037000507), Mod(192, 3037000507)] [Mod(13, 18446744073709551629), Mod(62, 18446744073709551629), Mod(62, 18446 744073709551629); Mod(40, 18446744073709551629), Mod(211, 184467440737095516 29), Mod(169, 18446744073709551629); Mod(42, 18446744073709551629), Mod(211, 18446744073709551629), Mod(192, 18446744073709551629)] [13 + O(101^3), 62 + O(101^3), 62 + O(101^3); 40 + O(101^3), 9 + 2*101 + O(1 01^3), 68 + 101 + O(101^3); 42 + O(101^3), 9 + 2*101 + O(101^3), 91 + 101 + O(101^3)] [;] matdet: 1 1 1 1 1 matrank: 0 0 0 0 0 matadjoint: [;] [;] [;] [;] [;] matimage: [;] [;] [;] [;] [;] matimagecompl: Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) matindexrank: [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] matker: [;] [;] [;] [;] [;] lindep: []~ []~ []~ []~ []~ (x)->matsolve(x,vectorv(#x,i,i)): []~ []~ []~ []~ []~ (x)->matsolve(x,matrix(#x,#x,i,j,i+j)): [;] [;] [;] [;] [;] (x)->x^(-1): [;] [;] [;] [;] [;] (x)->x^2: [;] [;] [;] [;] [;] (x)->A*x: [;] [;] [;] [;] [;] Mod(3037000506, 3037000507) Mod(18446744073709551628, 18446744073709551629) [Mod(3, 18446744073709551629), Mod(1, 18446744073709551629), Mod(18446744073 709551628, 18446744073709551629)]~ [-1.0000000000000000000000000000000000000*I] [ 1] 3 0 error("inconsistent dimensions in gtrace.") [1 0] [0 1] [;] lindep: [1, 0, 1]~ [1, -2, 1]~ [1, -2, 1]~ [1, -2, 1]~ [3 + O(101^3), 95 + 100*101 + 100*101^2 + O(101^3), 3 + O(101^3)]~ matsupplement: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(0, 2); Mod(1, 2) , Mod(0, 2), Mod(1, 2)] [Mod(1, 7), Mod(2, 7), Mod(0, 7); Mod(4, 7), Mod(5, 7), Mod(0, 7); Mod(0, 7) , Mod(1, 7), Mod(1, 7)] [Mod(1, 3037000507), Mod(2, 3037000507), Mod(0, 3037000507); Mod(4, 30370005 07), Mod(5, 3037000507), Mod(0, 3037000507); Mod(7, 3037000507), Mod(8, 3037 000507), Mod(1, 3037000507)] [Mod(1, 18446744073709551629), Mod(2, 18446744073709551629), Mod(0, 18446744 073709551629); Mod(4, 18446744073709551629), Mod(5, 18446744073709551629), M od(0, 18446744073709551629); Mod(7, 18446744073709551629), Mod(8, 1844674407 3709551629), Mod(1, 18446744073709551629)] [1 + O(101^3), 2 + O(101^3), 0; 4 + O(101^3), 5 + O(101^3), 0; 7 + O(101^3), 8 + O(101^3), 1] *** Warning: new stack size = 1000000 (0.954 Mbytes). 68 2 68 0 2 17 Total time spent: 72 pari-2.7.5/src/test/32/print0000644000175000017500000000011112531356742014160 0ustar billbill1:2:3:4 0 0 1:2:3:40 0 [1, 0; 0, 1] 0 [1, 0; 0, 1]0 Total time spent: 0 pari-2.7.5/src/test/32/lll0000644000175000017500000000324212366172547013624 0ustar billbill [1 0] [0 1] [ 0 0 -8 5] [ 8 -5 26 -16] [ 13 -8 -5 3] [-21 13 8 -5] [;] [;] [;] [[;], [;]] [[;], [;]] [;] Mat(1) Mat(1) Mat(1) [[;], Mat(1)] [[;], Mat(1)] Mat(1) [;] [;] Mat(1) [Mat(1), [;]] [Mat(1), [;]] [;] [1; 0] [1; 0] error("impossible inverse in dvmdii: 0.") [[-2; 1], [1; 0]] [[-2; 1], [1; 0]] [1; 0] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") [[x + 1; -x], [-1; 1]] [-1; 1] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") [[;], [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 8780356471 55*x^2 + 1; 1, -x^3 - 1053355*x^2]] [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 878035647155*x^2 + 1; 1, -x^3 - 1053355*x^2] [;] [;] [[;], [;]] [[;], [;]] Mat(1) Mat(1) [[;], Mat(1)] [[;], Mat(1)] [;] [;] [Mat(1), [;]] [Mat(1), [;]] [1; 0] [1; 0] [[-2; 1], [1; 0]] [[-2; 1], [1; 0]] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") [[x + 1; -x], [-1; 1]] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") [[;], [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 8780356471 55*x^2 + 1; 1, -x^3 - 1053355*x^2]] Total time spent: 8 pari-2.7.5/src/test/32/norm0000644000175000017500000000152612366172547014017 0ustar billbill1/4 *** at top-level: norml2(quadgen(5)) *** ^------------------ *** norml2: incorrect type in gnorml2 (t_QUAD). 1 1 1/2 1 (x)->normlp(x,1) 6 10 21 2.4142135623730950488016887242096980786 1.6180339887498948482045868343656381177 5 (x)->normlp(x,2) 3.7416573867739413855837487323165493018 5.4772255750516611345696978280080213395 9.5393920141694564915262158602322654026 1.7320508075688772935274463415058723670 1.6180339887498948482045868343656381177 5 (x)->normlp(x,2.5) 3.4585606563304871862271371438840799750 4.9402040006184485884345102892270748966 8.2976320964215261445777796306034959974 1.6273657035458510939647914767411763647 1.6180339887498948482045868343656381177 5 normlp 3 4 6 1.4142135623730950488016887242096980786 1.6180339887498948482045868343656381177 5.0000000000000000000000000000000000000 422481 Total time spent: 4 pari-2.7.5/src/test/32/arith0000644000175000017500000000004412314242551014127 0ustar billbill0 4162330905307 Total time spent: 4 pari-2.7.5/src/test/32/galoisinit0000644000175000017500000001064412366172547015207 0ustar billbill[2, 1] [16, 10] [20, 3] [24, 12] [4, 2] [4, 2] [4, 2] [4, 2] [12, 3] [24, 12] [54, 11] [54, 14] [64, 66] [8, 5] [4, 2] [14, 1] *** at top-level: do(x^48+688253440*x^ *** ^-------------------- *** in function do: galoisidentify(galoi *** ^-------------------- *** galoisidentify: incorrect type in checkgal (t_INT). [x]~ [-x, x]~ [-x, x, -x^3, x^3]~ [11 0 0 10 7 1] [ 0 11 0 6 1 1] [ 0 0 11 7 1 5] [ 0 0 0 1 0 0] [ 0 0 0 0 1 0] [ 0 0 0 0 0 1] [11, [9, 10, 5, 10, 6, 10]~, 1, 3, [10, 0, 0, -1, -4, 1; 4, 10, 0, -1, -5, - 3; 5, 4, 10, -1, -5, -4; 1, 5, 4, 9, -5, -4; 0, 1, 5, 3, 5, -4; 0, 0, 1, 4, -1, 6]] Mod(x^4 + x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) 1/2 [1, 1] [1, 1/2] [1, Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)] [1, Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)] [1, [0, 0, 0, 0, 0, 0]~] [1, [;]] [1, [1, 2; Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1), 3]] "Group((1, 5)(2, 10)(3, 11)(4, 6)(7, 9)(8, 12), (1, 8)(2, 3)(4, 7)(5, 12)(6, 9)(10, 11), (1, 2, 7)(3, 9, 12)(4, 5, 11)(6, 8, 10))" "PermutationGroup<12|[5, 10, 11, 6, 1, 4, 9, 12, 7, 2, 3, 8], [8, 3, 2, 7, 1 2, 9, 4, 1, 6, 11, 10, 5], [2, 7, 9, 5, 11, 8, 1, 10, 12, 6, 4, 3]>" [[[Vecsmall([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9]), Vecsmall([3, 7, 2, 1, 6, 12, 11, 9, 5, 8, 4, 10]), Vecsmall([5, 8, 9, 6, 7, 2, 10, 4, 11, 1, 12, 3 ])], Vecsmall([2, 3, 2])], [[Vecsmall([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9 ]), Vecsmall([3, 7, 2, 1, 6, 12, 11, 9, 5, 8, 4, 10])], Vecsmall([2, 3])], [ [Vecsmall([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9]), Vecsmall([5, 8, 9, 6, 7, 2, 10, 4, 11, 1, 12, 3])], Vecsmall([2, 2])], [[Vecsmall([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9]), Vecsmall([12, 5, 6, 10, 4, 11, 9, 3, 1, 2, 8, 7])], Vecsmall([2, 2])], [[Vecsmall([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9]), Vecs mall([6, 9, 5, 12, 11, 7, 8, 1, 4, 3, 10, 2])], Vecsmall([2, 2])], [[Vecsmal l([7, 4, 11, 2, 10, 8, 1, 6, 12, 5, 3, 9])], Vecsmall([2])], [[Vecsmall([11, 1, 4, 7, 8, 9, 3, 12, 10, 6, 2, 5])], Vecsmall([3])], [[], Vecsmall([])]] [1, 1, 0, 0, 0, 1, 1, 1] [0, [2, 1; 0, 3], [2, 1; 0, 2], [2, 1; 0, 2], [2, 1; 0, 2], Mat(2), Mat(3), [;]] [0, 1, 1, 1, 1, 1, 1, 1] [0, [6], [4], [4], [4], [2], [3], []] [x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80, x^2 - 30*x + 180, x^4 - 30*x^3 + 180*x^2 + 1080*x - 6480, x^6 - 18*x^4 + 20*x^3 + 36*x^2 - 60*x + 20, x^4 - 30*x^3 + 180*x^2 + 1080*x - 6480, x^2 - 30*x + 180, x^3 - 12*x + 14, x^3 - 12*x - 4, x^3 - 30*x + 50, x^3 - 12*x + 14, x^3 - 12*x - 4, x^3 - 30*x + 50] [x^2 - 30*x + 180, Mod(3/4*x^9 - 27/2*x^7 - 9/2*x^6 + 81*x^5 + 54*x^4 - 162* x^3 - 162*x^2 + 30, x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80)] [x^2 - 30*x + 180, Mod(3/4*x^9 - 27/2*x^7 - 9/2*x^6 + 81*x^5 + 54*x^4 - 162* x^3 - 162*x^2 + 30, x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80), [x^6 - 12*x^4 - 1/3* y*x^3 + 36*x^2 + 2*y*x + (4/3*y - 20), x^6 - 12*x^4 + (1/3*y - 10)*x^3 + 36* x^2 + (-2*y + 60)*x + (-4/3*y + 20)]] x^2 + x - 4 [x^8 - x^6 + x^4 - x^2 + 1, [41, 2, 1681], [487, 471, 894, 207, 1194, 1210, 787, 1474], [183, 1676, 1421, 923, 183, 1676, 1421, 923; 1136, 1035, 545, 64 6, 545, 646, 1136, 1035; 1238, 928, 443, 753, 1238, 928, 443, 753; 1007, 121 9, 1108, 28, 674, 462, 573, 1653; 941, 1493, 1426, 1183, 941, 1493, 1426, 11 83; 927, 253, 1472, 899, 754, 1428, 209, 782; 1493, 1426, 1183, 941, 1493, 1 426, 1183, 941; 1653, 674, 462, 573, 28, 1007, 1219, 1108], 1, [Vecsmall([1, 2, 3, 4, 5, 6, 7, 8]), Vecsmall([2, 3, 4, 1, 6, 7, 8, 5]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6]), Vecsmall([4, 1, 2, 3, 8, 5, 6, 7]), Vecsmall([5, 6, 7, 8 , 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 pari-2.7.5/src/test/32/apply0000644000175000017500000000024112366172547014162 0ustar billbill[1, 4, 9, 16] [1 4] [9 16] 16*x^2 + 9*x + 4 4 + 9*x + 16*x^2 + O(x^3) List([1, 4, 9, 16]) List([1, 2]) [0, 1, 2] [0, 1, 2] [2, 3] [2, 3] Total time spent: 0 pari-2.7.5/src/test/32/polyser0000644000175000017500000001466412405547147014544 0ustar billbill echo = 1 (on) ? apol=y^3+5*y+1 y^3 + 5*y + 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 ? 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] ? direuler(s=1,40,1+s*X+s^2*X) [1, 6, 12, 0, 30, 72, 56, 0, 0, 180, 132, 0, 182, 336, 360, 0, 306, 0, 380, 0, 672, 792, 552, 0, 0, 1092, 0, 0, 870, 2160, 992, 0, 1584, 1836, 1680, 0, 1406, 2280, 2184, 0] ? 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] ? zz=yy;yy=xx;eval(zz) xx ? factorpadic(apol,7,8) [(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] ? 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) ? intformal((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2)) (x + a)/(x^2 - 7*x + a) ? newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3) [2, 2/3, 2/3, 2/3] ? padicappr(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)]~ ? padicappr(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) ]~ ? Pol(sin(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 ? Pol([1,2,3,4,5]) x^4 + 2*x^3 + 3*x^2 + 4*x + 5 ? Polrev([1,2,3,4,5]) 5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1 ? polcoeff(sin(x),7) -1/5040 ? polcyclo(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 ? pcy=polcyclo(405) x^216 - x^189 + x^135 - x^108 + x^81 - x^27 + 1 ? pcy*pcy x^432 - 2*x^405 + x^378 + 2*x^351 - 4*x^324 + 4*x^297 - x^270 - 4*x^243 + 7* x^216 - 4*x^189 - x^162 + 4*x^135 - 4*x^108 + 2*x^81 + x^54 - 2*x^27 + 1 ? poldegree(x^3/(x-1)) 2 ? poldisc(x^3+4*x+12) -4144 ? poldiscreduced(x^3+4*x+12) [1036, 4, 1] ? polinterpolate([0,2,3],[0,4,9],5) 25 ? polisirreducible(x^5+3*x^3+5*x^2+15) 0 ? pollegendre(10) 46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x ^2 - 63/256 ? zpol=0.3+pollegendre(10) 46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x ^2 + 0.053906250000000000000000000000000000001 ? polrecip(3*x^7-5*x^3+6*x-9) -9*x^7 + 6*x^6 - 5*x^4 + 3 ? polresultant(x^3-1,x^3+1) 8 ? polresultant(x^3-1.,x^3+1.,,1) 8.0000000000000000000000000000000000000 ? polroots(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]~ ? polroots(x^4-1000000000000000000000) [-177827.94100389228012254211951926848447 + 0.E-38*I, 177827.941003892280122 54211951926848447 + 0.E-38*I, 0.E-38 - 177827.941003892280122542119519268484 47*I, 0.E-38 + 177827.94100389228012254211951926848447*I]~ ? polrootsmod(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)]~ ? polrootspadic(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)]~ ? polsturm(zpol) 4 ? polsturm(zpol,0.91,1) 1 ? polsylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0) [a2 b1 0] [a1 b0 b1] [a0 0 b0] ? polsym(x^17-1,17) [17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]~ ? poltchebi(10) 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 ? polzagier(6,3) 4608*x^6 - 13824*x^5 + 46144/3*x^4 - 23168/3*x^3 + 5032/3*x^2 - 120*x + 1 ? serconvol(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) ? serlaplace(x*exp(x*y)/(exp(x)-1)) 1 + (y - 1/2)*x + (y^2 - y + 1/6)*x^2 + (y^3 - 3/2*y^2 + 1/2*y)*x^3 + (y^4 - 2*y^3 + y^2 - 1/30)*x^4 + (y^5 - 5/2*y^4 + 5/3*y^3 - 1/6*y)*x^5 + (y^6 - 3* y^5 + 5/2*y^4 - 1/2*y^2 + 1/42)*x^6 + (y^7 - 7/2*y^6 + 7/2*y^5 - 7/6*y^3 + 1 /6*y)*x^7 + (y^8 - 4*y^7 + 14/3*y^6 - 7/3*y^4 + 2/3*y^2 - 1/30)*x^8 + (y^9 - 9/2*y^8 + 6*y^7 - 21/5*y^5 + 2*y^3 - 3/10*y)*x^9 + (y^10 - 5*y^9 + 15/2*y^8 - 7*y^6 + 5*y^4 - 3/2*y^2 + 5/66)*x^10 + (y^11 - 11/2*y^10 + 55/6*y^9 - 11* y^7 + 11*y^5 - 11/2*y^3 + 5/6*y)*x^11 + (y^12 - 6*y^11 + 11*y^10 - 33/2*y^8 + 22*y^6 - 33/2*y^4 + 5*y^2 - 691/2730)*x^12 + (y^13 - 13/2*y^12 + 13*y^11 - 143/6*y^9 + 286/7*y^7 - 429/10*y^5 + 65/3*y^3 - 691/210*y)*x^13 + (y^14 - 7 *y^13 + 91/6*y^12 - 1001/30*y^10 + 143/2*y^8 - 1001/10*y^6 + 455/6*y^4 - 691 /30*y^2 + 7/6)*x^14 + (y^15 - 15/2*y^14 + 35/2*y^13 - 91/2*y^11 + 715/6*y^9 - 429/2*y^7 + 455/2*y^5 - 691/6*y^3 + 35/2*y)*x^15 + O(x^16) ? serreverse(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) ? 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 + 1/62 27020800*y^13 - 1/1307674368000*y^15 + O(y^17) ? 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 - 6495059/6227020800*x^13 + 69301/479001600*x^14 + 26537089/1188794880 00*x^15 + 1528727/17435658240*x^16 + O(x^17) ? taylor(y/(x-y),y) (O(y^16)*x^15 + y*x^14 + y^2*x^13 + y^3*x^12 + y^4*x^11 + y^5*x^10 + y^6*x^9 + y^7*x^8 + y^8*x^7 + y^9*x^6 + y^10*x^5 + y^11*x^4 + y^12*x^3 + y^13*x^2 + y^14*x + y^15)/x^15 ? variable(name^4-other) name ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 4 pari-2.7.5/src/test/32/incgam0000644000175000017500000000537312413013143014261 0ustar billbill 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: 4.7 e-43 10 - I, -100: 7.9 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 56983544264467232044835043 E-68 *** at top-level: eint1(0) *** ^-------- *** eint1: domain error in eint1: x = 0 Total time spent: 188 pari-2.7.5/src/test/32/ispower0000644000175000017500000002543012526672057014533 0ustar billbill[101, 6] [5, 2160] [3, 21218] [5, 21218] [5, 84872] [21, 21218] [35, 21218] [105, 21218] [100003, 103] [121, 541] [2, 2] [3, 2] [2, 3] [4, 2] [2, 5] [3, 3] [5, 2] [2, 6] [2, 7] [6, 2] [4, 3] [2, 10] [2, 11] [3, 5] [7, 2] [2, 12] [2, 13] [2, 14] [3, 6] [2, 15] [5, 3] [8, 2] [2, 17] [2, 18] [3, 7] [2, 19] [2, 20] [2, 21] [2, 22] [9, 2] [2, 23] [2, 24] [4, 5] [2, 26] [6, 3] [2, 28] [2, 29] [2, 30] [2, 31] [3, 10] [10, 2] [2, 33] [2, 34] [2, 35] [4, 6] [3, 11] [2, 37] [2, 38] [2, 39] [2, 40] [2, 41] [3, 12] [2, 42] [2, 43] [2, 44] [2, 45] [11, 2] [2, 46] [7, 3] [3, 13] [2, 47] [2, 48] [4, 7] [2, 50] [2, 51] [2, 52] [3, 14] [2, 53] [2, 54] [2, 55] [5, 5] [2, 56] [2, 57] [2, 58] [3, 15] [2, 59] [2, 60] [2, 61] [2, 62] [2, 63] [12, 2] [2, 65] [2, 66] [2, 67] [2, 68] [2, 69] [2, 70] [3, 17] [2, 71] [2, 72] [2, 73] [2, 74] [2, 75] [2, 76] [3, 18] [2, 77] [2, 78] [2, 79] [2, 80] [8, 3] [2, 82] [3, 19] [2, 83] [2, 84] [2, 85] [2, 86] [2, 87] [2, 88] [5, 6] [2, 89] [3, 20] [2, 90] [13, 2] [2, 91] [2, 92] [2, 93] [2, 94] [2, 95] [2, 96] [3, 21] [2, 97] [2, 98] [2, 99] [4, 10] [2, 101] [2, 102] [2, 103] [3, 22] [2, 104] [2, 105] [2, 106] [2, 107] [2, 108] [2, 109] [2, 110] [3, 23] [2, 111] [2, 112] [2, 113] [2, 114] [2, 115] [2, 116] [2, 117] [3, 24] [2, 118] [2, 119] [2, 120] [4, 11] [2, 122] [2, 123] [2, 124] [6, 5] [2, 126] [2, 127] [14, 2] [2, 129] [5, 7] [2, 130] [2, 131] [2, 132] [3, 26] [2, 133] [2, 134] [2, 135] [2, 136] [2, 137] [2, 138] [2, 139] [2, 140] [9, 3] [2, 141] [2, 142] [2, 143] [4, 12] [2, 145] [2, 146] [2, 147] [2, 148] [3, 28] [2, 149] [2, 150] [2, 151] [2, 152] [2, 153] [2, 154] [2, 155] [2, 156] [3, 29] [2, 157] [2, 158] [2, 159] [2, 160] [2, 161] [2, 162] [2, 163] [2, 164] [3, 30] [2, 165] [2, 166] [2, 167] [2, 168] [4, 13] [2, 170] [2, 171] [2, 172] [3, 31] [2, 173] [2, 174] [2, 175] [2, 176] [2, 177] [2, 178] [2, 179] [2, 180] [2, 181] [15, 2] [2, 182] [2, 183] [2, 184] [2, 185] [2, 186] [2, 187] [2, 188] [2, 189] [3, 33] [2, 190] [2, 191] [2, 192] [2, 193] [2, 194] [2, 195] [4, 14] [2, 197] [2, 198] [3, 34] [2, 199] [2, 200] [2, 201] [2, 202] [2, 203] [2, 204] [2, 205] [2, 206] [2, 207] [3, 35] [2, 208] [2, 209] [2, 210] [2, 211] [2, 212] [2, 213] [2, 214] [2, 215] [6, 6] [2, 217] [2, 218] [2, 219] [2, 220] [2, 221] [2, 222] [2, 223] [2, 224] [4, 15] [3, 37] [2, 226] [2, 227] [2, 228] [2, 229] [2, 230] [2, 231] [2, 232] [2, 233] [2, 234] [3, 38] [2, 235] [2, 236] [2, 237] [2, 238] [2, 239] [2, 240] [2, 241] [2, 242] [10, 3] [3, 39] [2, 244] [2, 245] [2, 246] [2, 247] [2, 248] [2, 249] [2, 250] [2, 251] [2, 252] [3, 40] [2, 253] [2, 254] [2, 255] [16, 2] [2, 257] [2, 258] [2, 259] [2, 260] [2, 261] [2, 262] [3, 41] [2, 263] [2, 264] [2, 265] [2, 266] [2, 267] [2, 268] [2, 269] [2, 270] [2, 271] [2, 272] [3, 42] [2, 273] [2, 274] [2, 275] [2, 276] [2, 277] [2, 278] [2, 279] [7, 5] [2, 280] [2, 281] [3, 43] [2, 282] [2, 283] [2, 284] [2, 285] [2, 286] [2, 287] [2, 288] [4, 17] [2, 290] [2, 291] [3, 44] [2, 292] [2, 293] [2, 294] [2, 295] [2, 296] [2, 297] [2, 298] [2, 299] [2, 300] [2, 301] [3, 45] [2, 302] [2, 303] [2, 304] [2, 305] [2, 306] [2, 307] [2, 308] [2, 309] [2, 310] [2, 311] [3, 46] [2, 312] [2, 313] [2, 314] [2, 315] [2, 316] [5, 10] [2, 317] [2, 318] [2, 319] [2, 320] [2, 321] [2, 322] [3, 47] [2, 323] [4, 18] [2, 325] [2, 326] [2, 327] [2, 328] [2, 329] [2, 330] [2, 331] [2, 332] [3, 48] [2, 333] [2, 334] [2, 335] [2, 336] [2, 337] [2, 338] [2, 339] [2, 340] [2, 341] [2, 342] [6, 7] [2, 344] [2, 345] [2, 346] [2, 347] [2, 348] [2, 349] [2, 350] [2, 351] [2, 352] [2, 353] [3, 50] [2, 354] [2, 355] [2, 356] [2, 357] [2, 358] [2, 359] [2, 360] [4, 19] [2, 362] [17, 2] [2, 363] [2, 364] [3, 51] [2, 365] [2, 366] [2, 367] [2, 368] [2, 369] [2, 370] [2, 371] [2, 372] [2, 373] [2, 374] [3, 52] [2, 375] [2, 376] [2, 377] [2, 378] [2, 379] [2, 380] [2, 381] [2, 382] [2, 383] [2, 384] [2, 385] [3, 53] [2, 386] [2, 387] [2, 388] [2, 389] [2, 390] [2, 391] [2, 392] [2, 393] [2, 394] [2, 395] [2, 396] [3, 54] [2, 397] [2, 398] [2, 399] [4, 20] [2, 401] [5, 11] [2, 402] [2, 403] [2, 404] [2, 405] [2, 406] [2, 407] [3, 55] [2, 408] [2, 409] [2, 410] [2, 411] [2, 412] [2, 413] [2, 414] [2, 415] [2, 416] [2, 417] [2, 418] [2, 419] [3, 56] [2, 420] [11, 3] [2, 421] [2, 422] [2, 423] [2, 424] [2, 425] [2, 426] [2, 427] [2, 428] [2, 429] [2, 430] [3, 57] [2, 431] [2, 432] [2, 433] [2, 434] [2, 435] [2, 436] [2, 437] [2, 438] [2, 439] [2, 440] [4, 21] [3, 58] [2, 442] [2, 443] [2, 444] [2, 445] [2, 446] [2, 447] [2, 448] [2, 449] [2, 450] [2, 451] [2, 452] [2, 453] [3, 59] [2, 454] [2, 455] [2, 456] [2, 457] [2, 458] [2, 459] [2, 460] [2, 461] [2, 462] [2, 463] [2, 464] [3, 60] [2, 465] [2, 466] [2, 467] [2, 468] [2, 469] [2, 470] [2, 471] [2, 472] [2, 473] [2, 474] [2, 475] [2, 476] [3, 61] [2, 477] [2, 478] [2, 479] [2, 480] [2, 481] [2, 482] [2, 483] [4, 22] [2, 485] [2, 486] [2, 487] [2, 488] [3, 62] [2, 489] [2, 490] [2, 491] [2, 492] [2, 493] [2, 494] [2, 495] [2, 496] [2, 497] [2, 498] [5, 12] [2, 499] [2, 500] [3, 63] [2, 501] [2, 502] [2, 503] [2, 504] [2, 505] [2, 506] [2, 507] [2, 508] [2, 509] [2, 510] [2, 511] [18, 2] [2, 513] [2, 514] [2, 515] [2, 516] [2, 517] [2, 518] [2, 519] [2, 520] [2, 521] [2, 522] [2, 523] [2, 524] [3, 65] [2, 525] [2, 526] [2, 527] [2, 528] [4, 23] [7, 6] [2, 530] [2, 531] [2, 532] [2, 533] [2, 534] [2, 535] [2, 536] [3, 66] [2, 537] [2, 538] [2, 539] [2, 540] [2, 541] [2, 542] [2, 543] [2, 544] [2, 545] [2, 546] [2, 547] [2, 548] [3, 67] [2, 549] [2, 550] [2, 551] [2, 552] [2, 553] [2, 554] [2, 555] [2, 556] [2, 557] [2, 558] [2, 559] [2, 560] [3, 68] [2, 561] [2, 562] [2, 563] [2, 564] [2, 565] [2, 566] [2, 567] [2, 568] [2, 569] [2, 570] [2, 571] [2, 572] [2, 573] [3, 69] [2, 574] [2, 575] [4, 24] [2, 577] [2, 578] [2, 579] [2, 580] [2, 581] [2, 582] [2, 583] [2, 584] [2, 585] [3, 70] [2, 586] [2, 587] [2, 588] [2, 589] [2, 590] [2, 591] [2, 592] [2, 593] [2, 594] [2, 595] [2, 596] [2, 597] [2, 598] [3, 71] [2, 599] [2, 600] [2, 601] [2, 602] [2, 603] [2, 604] [2, 605] [2, 606] [2, 607] [2, 608] [2, 609] [5, 13] [2, 610] [3, 72] [2, 611] [2, 612] [2, 613] [2, 614] [2, 615] [2, 616] [2, 617] [2, 618] [2, 619] [2, 620] [2, 621] [2, 622] [2, 623] [3, 73] [2, 624] [8, 5] [2, 626] [2, 627] [2, 628] [2, 629] [2, 630] [2, 631] [2, 632] [2, 633] [2, 634] [2, 635] [2, 636] [3, 74] [2, 637] [2, 638] [2, 639] [2, 640] [2, 641] [2, 642] [2, 643] [2, 644] [2, 645] [2, 646] [2, 647] [2, 648] [2, 649] [3, 75] [2, 650] [2, 651] [2, 652] [2, 653] [2, 654] [2, 655] [2, 656] [2, 657] [2, 658] [2, 659] [2, 660] [2, 661] [2, 662] [3, 76] [2, 663] [2, 664] [2, 665] [2, 666] [2, 667] [2, 668] [2, 669] [2, 670] [2, 671] [2, 672] [2, 673] [2, 674] [2, 675] [3, 77] [4, 26] [2, 677] [2, 678] [2, 679] [2, 680] [2, 681] [2, 682] [2, 683] [2, 684] [2, 685] [2, 686] [2, 687] [2, 688] [3, 78] [2, 689] [2, 690] [2, 691] [2, 692] [2, 693] [2, 694] [2, 695] [2, 696] [2, 697] [2, 698] [2, 699] [2, 700] [2, 701] [2, 702] [3, 79] [2, 703] [2, 704] [2, 705] [2, 706] [2, 707] [2, 708] [2, 709] [2, 710] [2, 711] [2, 712] [2, 713] [2, 714] [2, 715] [3, 80] [2, 716] [2, 717] [2, 718] [2, 719] [2, 720] [2, 721] [2, 722] [2, 723] [2, 724] [19, 2] [2, 725] [2, 726] [2, 727] [2, 728] [12, 3] [2, 730] [2, 731] [2, 732] [2, 733] [5, 14] [2, 734] [2, 735] [2, 736] [2, 737] [2, 738] [2, 739] [2, 740] [2, 741] [2, 742] [3, 82] [2, 743] [2, 744] [2, 745] [2, 746] [2, 747] [2, 748] [2, 749] [2, 750] [2, 751] [2, 752] [2, 753] [2, 754] [2, 755] [2, 756] [3, 83] [2, 757] [2, 758] [2, 759] [2, 760] [2, 761] [2, 762] [2, 763] [2, 764] [2, 765] [2, 766] [2, 767] [2, 768] [2, 769] [3, 84] [2, 770] [2, 771] [2, 772] [2, 773] [2, 774] [2, 775] [2, 776] [2, 777] [2, 778] [2, 779] [2, 780] [2, 781] [2, 782] [2, 783] [3, 85] [4, 28] [2, 785] [2, 786] [2, 787] [2, 788] [2, 789] [2, 790] [2, 791] [2, 792] [2, 793] [2, 794] [2, 795] [2, 796] [2, 797] [3, 86] [2, 798] [2, 799] [2, 800] [2, 801] [2, 802] [2, 803] [2, 804] [2, 805] [2, 806] [2, 807] [2, 808] [2, 809] [2, 810] [2, 811] [3, 87] [2, 812] [2, 813] [2, 814] [2, 815] [2, 816] [2, 817] [2, 818] [2, 819] [2, 820] [2, 821] [2, 822] [2, 823] [2, 824] [2, 825] [3, 88] [2, 826] [2, 827] [2, 828] [2, 829] [2, 830] [2, 831] [2, 832] [2, 833] [2, 834] [2, 835] [2, 836] [2, 837] [2, 838] [2, 839] [3, 89] [2, 840] [4, 29] [2, 842] [2, 843] [2, 844] [2, 845] [2, 846] [2, 847] [2, 848] [2, 849] [2, 850] [2, 851] [2, 852] [2, 853] [3, 90] [2, 854] [2, 855] [2, 856] [2, 857] [2, 858] [2, 859] [2, 860] [2, 861] [2, 862] [2, 863] [2, 864] [2, 865] [2, 866] [2, 867] [2, 868] [3, 91] [2, 869] [2, 870] [2, 871] [5, 15] [2, 872] [2, 873] [2, 874] [2, 875] [2, 876] [2, 877] [2, 878] [2, 879] [2, 880] [2, 881] [2, 882] [3, 92] [2, 883] [2, 884] [2, 885] [2, 886] [2, 887] [2, 888] [2, 889] [2, 890] [2, 891] [2, 892] [2, 893] [2, 894] [2, 895] [2, 896] [3, 93] [2, 897] [2, 898] [2, 899] [4, 30] [2, 901] [2, 902] [2, 903] [2, 904] [2, 905] [2, 906] [2, 907] [7, 7] [2, 908] [2, 909] [2, 910] [2, 911] [3, 94] [2, 912] [2, 913] [2, 914] [2, 915] [2, 916] [2, 917] [2, 918] [2, 919] [2, 920] [2, 921] [2, 922] [2, 923] [2, 924] [2, 925] [3, 95] [2, 926] [2, 927] [2, 928] [2, 929] [2, 930] [2, 931] [2, 932] [2, 933] [2, 934] [2, 935] [2, 936] [2, 937] [2, 938] [2, 939] [2, 940] [3, 96] [2, 941] [2, 942] [2, 943] [2, 944] [2, 945] [2, 946] [2, 947] [2, 948] [2, 949] [2, 950] [2, 951] [2, 952] [2, 953] [2, 954] [2, 955] [3, 97] [2, 956] [2, 957] [2, 958] [2, 959] [2, 960] [4, 31] [2, 962] [2, 963] [2, 964] [2, 965] [2, 966] [2, 967] [2, 968] [2, 969] [2, 970] [3, 98] [2, 971] [2, 972] [2, 973] [2, 974] [2, 975] [2, 976] [2, 977] [2, 978] [2, 979] [2, 980] [2, 981] [2, 982] [2, 983] [2, 984] [2, 985] [3, 99] [2, 986] [2, 987] [2, 988] [2, 989] [2, 990] [2, 991] [2, 992] [2, 993] [2, 994] [2, 995] [2, 996] [2, 997] [2, 998] [2, 999] [6, 10] [3, -4] [3, -2] [3, -21218] [3, -1/4] 3 1 [1431, 5737585] [1278, 6780590] [983, 36262840] [508, 2044406843184] [274, 3873816255479006870044] [228, 34028236692093846346337460743176821665314] 121 1 [0, 0, 1, 0] [0, 0, 0, 0] [0, 0, Mod(735321672858813933, 1000039000207000297), 0] [0, 0, 0, 0] [Mod(766696600158900228, 1000039000207000297), Mod(9366110197497040718447998 65730, 1000113004462069006305361406593), Mod(6, 1000039000207000297), Mod(30 66786400635600912, 8000312001656002376)] [Mod(761273567620851421, 1000039000207000297), Mod(6350198471236493446056154 0863, 1000113004462069006305361406593), Mod(542283254184885017, 100003900020 7000297), Mod(4933525601020401464, 8000312001656002376)] Mod(583, 875) 1 Mod(0, 2) 0 0 0 1 0 1 1 y 0 1 Mod(1, 2)*x + Mod(1, 2) t*x^2 + (t + 1)*x + 1 Mod(1, 5)*x^2 + Mod(3, 5)*x + Mod(2, 5) 2/x 1 1.2247448713915890490986420373529456960 1 0 1 1 t^2 + t + 1 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 -2/3 1 0 0 0 2 x + 2 0 11 1 1 1/(2*x) 1 + 1/3*x + O(x^2) -2/3 121 121 187 1 5 Total time spent: 2796 pari-2.7.5/src/test/32/time0000644000175000017500000000003012366172547013767 0ustar billbill1 1 Total time spent: 0 pari-2.7.5/src/test/32/polylog0000644000175000017500000000160312405547147014521 0ustar billbill1.0496589501864398696458324932101000704 2.0886953792151632708518141489041442185 - 4.27563394103876217704892645569519 63565*I 4.3226178452644705784020044544722613393 - 2.90951877177225946407469488966471 03179*I [-0.20561675835602830455905189583075314865 - 0.91596559417721901505460351493 238411077*I, -0.20561675835602830455905189583075314865 + 0.91596559417721901 505460351493238411077*I]~ [0.58224052646501250590265632015968010874, 0.7275863077163333895135362968404 8110789] x + 1/4*x^2 + 1/9*x^3 + 1/16*x^4 + O(x^5) 0.58224052646501250590265632015968010874 + 1.3862943611198906188344642429163 531362*x + 0.61370563888010938116553575708364686385*x^2 + 0.5150591481598541 5844595232388847084820*x^3 + 0.56074461109355209566440484750062706103*x^4 + O(x^5) -2.3699397969983658319855374253503230488 0.91596559417721901505460351493238411077 0.34657359027997265470861606072908828404 Total time spent: 4 pari-2.7.5/src/test/32/modular0000644000175000017500000000637412462723331014503 0ustar billbill1: Mod(1, 2)*x^8 + Mod(1, 2)*x^6 + Mod(1, 2)*x^4 + Mod(1, 2)*x^2 + Mod(1, 2) 2: Mod(1, 3)*x^8 + Mod(1, 3)*x^6 + Mod(1, 3)*x^4 + Mod(1, 3)*x^2 + Mod(1, 3) 3: Mod(1, 4294967295)*x^8 + Mod(1, 4294967295)*x^6 + Mod(1, 4294967295)*x^4 + Mod(1, 4294967295)*x^2 + Mod(1, 4294967295) 4: Mod(1, 18446744073709551615)*x^8 + Mod(1, 18446744073709551615)*x^6 + Mod (1, 18446744073709551615)*x^4 + Mod(1, 18446744073709551615)*x^2 + Mod(1, 18 446744073709551615) 5: Mod(1, 100000000000000000000)*x^8 + Mod(1, 100000000000000000000)*x^6 + M od(1, 100000000000000000000)*x^4 + Mod(1, 100000000000000000000)*x^2 + Mod(1 , 100000000000000000000) 1: Mod(1, 2)*x^8 + Mod(1, 2)*x^6 + Mod(1, 2)*x^4 + Mod(1, 2)*x^2 + Mod(1, 2) 2: Mod(1, 3)*x^8 + Mod(1, 3)*x^7 + Mod(2, 3)*x^5 + Mod(2, 3)*x^4 + Mod(2, 3) *x^3 + Mod(1, 3)*x + Mod(1, 3) 3: Mod(1, 4294967295)*x^8 + Mod(4294967293, 4294967295)*x^7 + Mod(3, 4294967 295)*x^6 + Mod(4294967291, 4294967295)*x^5 + Mod(5, 4294967295)*x^4 + Mod(42 94967291, 4294967295)*x^3 + Mod(3, 4294967295)*x^2 + Mod(4294967293, 4294967 295)*x + Mod(1, 4294967295) 4: Mod(1, 18446744073709551615)*x^8 + Mod(18446744073709551613, 184467440737 09551615)*x^7 + Mod(3, 18446744073709551615)*x^6 + Mod(18446744073709551611, 18446744073709551615)*x^5 + Mod(5, 18446744073709551615)*x^4 + Mod(18446744 073709551611, 18446744073709551615)*x^3 + Mod(3, 18446744073709551615)*x^2 + Mod(18446744073709551613, 18446744073709551615)*x + Mod(1, 1844674407370955 1615) 5: Mod(1, 100000000000000000000)*x^8 + Mod(99999999999999999998, 10000000000 0000000000)*x^7 + Mod(3, 100000000000000000000)*x^6 + Mod(999999999999999999 96, 100000000000000000000)*x^5 + Mod(5, 100000000000000000000)*x^4 + Mod(999 99999999999999996, 100000000000000000000)*x^3 + Mod(3, 100000000000000000000 )*x^2 + Mod(99999999999999999998, 100000000000000000000)*x + Mod(1, 10000000 0000000000000) 1: [Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(0, 2)] 2: [Mod(0, 3), Mod(0, 3); Mod(2, 3), Mod(2, 3)] 3: [Mod(4294967286, 4294967295), Mod(6, 4294967295); Mod(4294967276, 4294967 295), Mod(14, 4294967295)] 4: [Mod(18446744073709551606, 18446744073709551615), Mod(6, 1844674407370955 1615); Mod(18446744073709551596, 18446744073709551615), Mod(14, 184467440737 09551615)] 5: [Mod(99999999999999999991, 100000000000000000000), Mod(6, 100000000000000 000000); Mod(99999999999999999981, 100000000000000000000), Mod(14, 100000000 000000000000)] 1: [Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(0, 2)] 2: [Mod(1, 3), Mod(1, 3); Mod(0, 3), Mod(1, 3)] 3: [Mod(7, 4294967295), Mod(10, 4294967295); Mod(15, 4294967295), Mod(22, 42 94967295)] 4: [Mod(7, 18446744073709551615), Mod(10, 18446744073709551615); Mod(15, 184 46744073709551615), Mod(22, 18446744073709551615)] 5: [Mod(7, 100000000000000000000), Mod(10, 100000000000000000000); Mod(15, 1 00000000000000000000), Mod(22, 100000000000000000000)] Mod(Mod(1, y), x) Mod(Mod(1, y), x) error("forbidden division t_INT % t_STR.") error("impossible inverse in %: 0.") error("impossible inverse in %: 0.") error("inconsistent division t_SER % t_POL.") Mod(x, x^2) Mod(x, x^2) Mod(x, x^2) Mod(1, 3) Mod(-x, x^2 + 1) [Mod(1, 2), Mod(0, 2)] Mod(1, 2)*x Mod(1, y)*x Mod(0, 2) Mod(0, 2) *** _^_: Warning: Mod(a,b)^n with n >> b : wasteful. Mod(2, 7) *** _^_: Warning: Mod(a,b)^n with n >> b : wasteful. Mod(4, 7) 1 Total time spent: 0 pari-2.7.5/src/test/32/objets0000644000175000017500000000416212415477723014330 0ustar billbill echo = 1 (on) ? +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 ? binary(65537) [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] ? bittest(10^100,100) 1 ? ceil(-2.5) -2 ? centerlift(Mod(456,555)) -99 ? component(1+O(7^4),3) 1 ? 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]~ ? truncate(1.7,&e) 1 ? e -1 ? denominator(12345/54321) 18107 ? divrem(345,123) [2, 99]~ ? divrem(x^7-1,x^5+1) [x^2, -x^2 - 1]~ ? floor(-1/2) -1 ? floor(-2.5) -3 ? frac(-2.7) 0.30000000000000000000000000000000000000 ? I^2 -1 ? imag(2+3*I) 3 ? lex([1,3],[1,3,5]) -1 ? max(2,3) 3 ? min(2,3) 2 ? Mod(-12,7) Mod(2, 7) ? norm(1+I) 2 ? norm(Mod(x+5,x^3+x+1)) 129 ? numerator((x+1)/(x-1)) x + 1 ? 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) ? numtoperm(7,1035) [2, 4, 6, 1, 5, 7, 3] ? permtonum([4,7,1,6,3,5,2]) 2781 ? 37. 37.000000000000000000000000000000000000 ? real(5-7*I) 5 ? 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] ? sign(-1) -1 ? sign(0) 0 ? sign(0.) 0 ? simplify(((x+I+1)^2-x^2-2*x*(I+1))^2) -4 ? sizedigit([1.3*10^5,2*I*Pi*exp(4*Pi)]) 7 ? truncate(-2.7) -2 ? truncate(sin(x^2)) -1/5040*x^14 + 1/120*x^10 - 1/6*x^6 + x^2 ? type(Mod(x,x^2+1)) "t_POLMOD" ? valuation(6^10000-1,5) 5 ? \p57 realprecision = 57 significant digits ? Pi 3.14159265358979323846264338327950288419716939937510582098 ? \p38 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) ? padicprec(padicno,127) 5 ? length(divisors(1000)) 16 ? Mod(10873,49649)^-1 *** at top-level: Mod(10873,49649)^-1 *** ^--- *** _^_: impossible inverse in Fp_inv: Mod(131, 49649). ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 4 pari-2.7.5/src/test/32/analyz0000644000175000017500000000034212366172547014335 0ustar billbill echo = 1 (on) ? sum(x=0,50000,x); ? sum(x=1,1000,log(x)); ? sum(x=1,25,sum(y=1,100,x/y),0.0); ? sum(x=1,100,sum(y=1,100,x/y,0.0)); ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 24 pari-2.7.5/src/test/32/nfields0000644000175000017500000007566612405547147014504 0ustar billbill 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/147*x^3 + 1/147*x^2 - 8/49*x - 9/49, x^4 + 24*x^2 + 585*x + 179 1)]] ? 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, 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]] ? ideallog(nf2,y,bid) [176, 2, 0]~ ? 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], [[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]] ? 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, -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]] ? 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, -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]] ? 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]]) [[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]] ? 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 - 15*x^4 + 88*x^3 - 273*x^2 + 532*x - 304 ? 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(199, 31533, -7123, 0.E-57)], 2800.6252519070160764863706217370 745514] ? sizebyte(%) 156 ? getheap [217, 100743] ? print("Total time spent: ",gettime); Total time spent: 116 pari-2.7.5/src/test/kerntest.c0000644000175000017500000000365712413013143014662 0ustar billbill#include "pari.h" GEN gen_0, gen_1, gen_m1, gen_2, gen_m2; THREAD pari_sp top, bot, 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; void mt_sigint_block(void) { } void mt_sigint_unblock(void) { } void specinit() { long size = 100000L; bot = (pari_sp)malloc(size); top = avma = bot + size; gen_0 = cgeti(2); affui(0, gen_0); gen_1 = utoipos(1); gen_m1= utoineg(1); gen_2 = utoipos(2); gen_m2= utoineg(2); } void sorstring(ulong x) { #ifdef LONG_IS_64BIT printf("%016lx ", x); #else printf("%08lx ", x); #endif } 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]); 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("\n"); } int main() { GEN x,y,r,z, xr,yr; specinit(); x = utoipos(187654321UL); y = utoineg(12345678UL); printf("INT: %ld\n", itos(x)); printf("conv:"); _voiri(x); printf("+:"); _voiri(addii(x,y)); printf("-:"); _voiri(subii(x,y)); printf("*:"); _voiri(mulii(x,y)); printf("/:"); _voiri(dvmdii(x,y, &z)); printf("rem:"); _voiri(z); printf("pow:\n"); z = mulii(x,x); _voiri(z); z = mulii(z,z); _voiri(z); z = mulii(z,z); _voiri(z); z = mulii(z,z); _voiri(z); z = mulii(z,z); _voiri(z); printf("invmod:"); invmod(y,z,&r); _voiri(r); xr = itor(x, DEFAULTPREC); yr = itor(y, DEFAULTPREC); printf("\nREAL: %f\n", rtodbl(xr)); printf("conv1:"); _voirr(xr); printf("conv2:"); _voirr(dbltor(rtodbl(xr))); printf("+:"); _voirr(addrr(xr,yr)); printf("-:"); _voirr(subrr(xr,yr)); printf("*:"); _voirr(mulrr(xr,yr)); printf("/:"); _voirr(divrr(xr,yr)); printf("gcc bug?:"); _voirr(divru(dbltor(3.),2)); return 0; } pari-2.7.5/src/test/in/0000755000175000017500000000000012613365633013272 5ustar billbillpari-2.7.5/src/test/in/nffactor0000644000175000017500000002633612413013143015011 0ustar billbilldefault(parisize,"16M"); do(T, P) = lift(nffactor(nfinit(T),P)[,1]); do(polcyclo(13,y),x^72-291*x^70+168*x^69+40380*x^68-48588*x^67-3528919*x^66+6672120*x^65+215657160*x^64-575538144*x^63-9642387423*x^62+34735086786*x^61+318475831783*x^60-1543992152304*x^59-7526047084203*x^58+51709921323996*x^57+110268119466273*x^56-1306863903654948*x^55-197687339387338*x^54+24340617020480994*x^53-37674206381844006*x^52-309388136734870296*x^51+1097175021601270233*x^50+1965430743178095924*x^49-17057741307681944498*x^48+12695705864721864408*x^47+149941210123858078557*x^46-449449010694960248724*x^45-360137445013361079753*x^44+4743771886303072354536*x^43-7957480107528139931362*x^42-20006312987061736459890*x^41+103127662005251951018025*x^40-57922725775374790826892*x^39-575374977336477060878406*x^38+1141042155363070337681952*x^37+2107623272811930164219492*x^36-8555883275792119671168984*x^35-6622038332271478648217502*x^34+67788499073804904961005264*x^33-62194621346216574281355513*x^32-298503076979390816950994616*x^31+935868776923024509133161567*x^30-602191893688026944562387144*x^29-2378403718028116295265005703*x^28+7144715267789671188060423636*x^27-8264313767410946129053876314*x^26-2988303993119955116599622124*x^25+36320303706133493815706370331*x^24-93405543373036036850518472592*x^23+137892731303549623166716872621*x^22-73374564495372153466268524626*x^21-180690507689854149951443988039*x^20+506199649638427572646328975856*x^19-511453665473658325356669209047*x^18-183193264910244539106552118338*x^17+1423840911419731272911578335897*x^16-2367314022969857609246689985844*x^15+2236677523353346112926136338695*x^14-1548489683091587051973217338168*x^13+2105049137205776145162583648404*x^12-4754348311294629767834593856064*x^11+7567806891220394207855512254933*x^10-7605431066578089163623568649610*x^9+3882625664788999249342771140339*x^8+1356469287400668040516453202076*x^7-3841355512345259545848813224621*x^6+2330504083587501732658867007532*x^5-169172628407290891217225606775*x^4-398965703199322569698936377044*x^3+198978398979453484569202793808*x^2-60597282938946837445378411698*x+12280639561039083425818958713) do(polcyclo(5,y),x^48+12*x^46+948*x^44+7200*x^42+152361*x^40+815832*x^38+9475380*x^36+44654004*x^34+299137536*x^32+1335241260*x^30+5029216452*x^28+15282825984*x^26+37737671337*x^24+79579803672*x^22+143658877428*x^20+222699104460*x^18+303698198961*x^16+348787956312*x^14+312863646960*x^12+212893847424*x^10+111407984496*x^8+43762394880*x^6+11836253952*x^4+1904684544*x^2+136048896) do(polsubcyclo(17,8,y),x^48-104*x^46+4664*x^44-122476*x^42+2137838*x^40-26567700*x^38+245144964*x^36-1725955872*x^34+9441692003*x^32-40611588644*x^30+138356971048*x^28-374714866240*x^26+807289826646*x^24-1380693858220*x^22+1866021172640*x^20-1978766780068*x^18+1630151673857*x^16-1029505301024*x^14+489498952012*x^12-170832297056*x^10+42133382284*x^8-6904507136*x^6+669868016*x^4-28899680*x^2+16) do(polsubcyclo(19,6,y),x^64-6384*x^62+18261761*x^60-31231019568*x^58+35925400902280*x^56-29635423138225800*x^54+18244443900381139917*x^52-8609789775431197305288*x^50+3173715440318358526295493*x^48-926253189958924421506713024*x^46+216130107574547887816493973792*x^44-40600173780591579547211667354912*x^42+6168621134132051706341715912515370*x^40-760139434277348135867991392951415744*x^38+76052955647065900426700689494084391434*x^36-6175311843554416772593815034596603661344*x^34+406137362468726923132369140307868626461744*x^32-21559959594011538596615817038079394912524336*x^30+919122010228667702998458013093798368177514170*x^28-31251399013676293208252728256910183010646331888*x^26+840017792466500823059432352741453680599704357258*x^24-17651171087877975905738341268934550365403253370816*x^22+285940694256111366646633973109729677687028435758880*x^20-3510138236669349338216717168753743720690200440965920*x^18+31970659328447652254136627725804141367170891626180389*x^16-210577501276259853380917767547980363666145460503950096*x^14+972633665701140285445722173171004563157651576027463941*x^12-3038789368329382179884462851269146550248145196800679728*x^10+6158927928896588396670590928896385649075890120481042824*x^8-7695135079270077790657693634058524039308535641860032904*x^6+5510293734552561962521574495431679567021222445632508873*x^4-1998778331104544904932086470347413669495129560426038280*x^2+273892744995340833777347939263771534786080723599733441) do(y^16-748*y^14+183362*y^12-18209312*y^10+854163776*y^8-19811731456*y^6+217053667328*y^4-963359277056*y^2+1401249857536,x^64-50520*x^62+1184742668*x^60-17134912892184*x^58+171302841202784230*x^56-1257730595773642457272*x^54+7035168717087126283039868*x^52-30701149599207543908253060456*x^50+106209876041363261331175274376961*x^48-294437498300554938723628131780900528*x^46+658747632370852789155278036118795891376*x^44-1194508299658559259423544698671941624911936*x^42+1758886106345358997541429698467814358261692768*x^40-2102877763749659939135348751421310839041552295168*x^38+2037272869739882513058383232251947632400144748327680*x^36-1593244672706602785431833797822694649876503949099971584*x^34+1000137401948528280332750479657406431558467421878362177792*x^32-500163144667908835632768747437877749311388525989506418016256*x^30+197386643425666396587295586758946216300889646426384501395505152*x^28-60764991565332609893728829321665731738637757708625749066895851520*x^26+14391680825163014577680716072706067747656540117078764576362349133824*x^24-2579614931575491289251668514169821364409673054271152939186037020688384*x^22+343089307498773969742537952871359998792597096472804803564329469006053376*x^20-33039893809399713739300133477660888984993965585329459081212907387885715456*x^18+2232207983615195492545494908634867604311043135572503317867045868579149840384*x^16-101424324951708207798235121163034156328923938680623314497489525231592962785280*x^14+2924360883858624736764622501847786486366632522081726107231999581887779150233600*x^12-49361130671745243582144295846906126266126621338339076133495563142930969537806336*x^10+439086453618923969602036267436177792533605154882821831371393950663185250364948480*x^8-1791241595903032942764035441499088453133177154876529243608326027299172423825358848*x^6+3156683219740128500900617761806000080676491013147893106666462267204557337199116288*x^4-2047559682560580731342531379502232338263001052780076721919148124626016913223319552*x^2+364046770867177439711105777657339121207381033680019800170419997640962734592884736) do(y^20+1161*y^16+357096*y^12+15694096*y^8+129931776*y^4+26873856,x^20+1219*x^16+25560*x^14+1352565*x^12+15766260*x^10+468310924*x^8-1266123120*x^6+27117441616*x^4+101145350400*x^2+914700960000) do(y^3+y^2+2,x^24+69) do(y^4+7^2,x^28-14*x^24+20321*x^20+166992*x^16+1171296*x^12+1342208*x^8-5005056*x^4+3211264) setrand(1);do(y^16-24*y^14+196*y^12-696*y^10+1118*y^8-840*y^6+292*y^4-40*y^2+1,x^32-208*x^30+12736*x^28-330032*x^26+4326444*x^24-32221712*x^22+147532904*x^20-437660272*x^18+869634612*x^16-1179150112*x^14+1097619208*x^12-696893680*x^10+295476664*x^8-80251024*x^6+12946192*x^4-1075648*x^2+33614) setrand(29);do(y^16+6*y^8+1,x^64+112*x^60+4672*x^56-61472*x^52+1722640*x^48-19382720*x^44+137146112*x^40+89961600*x^36+762162272*x^32-7723483904*x^28+17460562944*x^24+100233636352*x^20+74611011840*x^16-74722169856*x^12+20300812288*x^8+1358714880*x^4+21381376) setrand(6);do(y^16+2,x^64+192*x^62+17568*x^60+1019520*x^58+42131676*x^56+1319651424*x^54+32559096528*x^52+649228312512*x^50+10651553826426*x^48+145639438552224*x^46+1674922821206832*x^44+16307859539653056*x^42+135023677732167696*x^40+953248899971965824*x^38+5745239175305568960*x^36+29556064271185194240*x^34+129595725382952883843*x^32+483002100692576612640*x^30+1523870714370199019760*x^28+4047489983524093705152*x^26+8985812828648862019536*x^24+16525310345394167002752*x^22+24893927149975603242048*x^20+30294355815129821928192*x^18+29274561574319887883226*x^16+21987801771104340121824*x^14+12494344840480632094992*x^12+5187763623118143696192*x^10+1502211081063677383836*x^8+283567347515314680480*x^6+31146155438884525872*x^4+1543354925530003776*x^2+8057044481403681) do(y^32+28*y^24+70*y^16+28*y^8+1, x^16-72*x^12-280*x^8+288*x^4+16) S=x^5-5*x^3+4*x-1; T=y^15-25*y^13+202*y^11-16*y^10-665*y^9+115*y^8+916*y^7-160*y^6-537*y^5+80*y^4+119*y^3-16*y^2-8*y+1; lift(nfroots(T,S)) S=polsubcyclo(97,12); lift(nfroots(subst(S,x,y),S)) S=x^9+9*x^8+36*x^7+69*x^6+36*x^5-99*x^4-303*x^3-450*x^2-342*x-226; T=y^9-15*y^6-87*y^3-125; lift(nffactor(T,S)) lift(nffactor(nfinit(y^2+1),(x-y)^3*(x^2+y)^4*(x^3-y*x+y)^5)) lift(factor(Mod(y,y^2+1)*x^2 + y)) lift(nffactor(nfinit(y^2+1),Mod(y,y^2+1)*x^2 + y)) factor((2*x+1)^2*(x+1)^3) {P=x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 2/7; K= a^27-63*a^25+1701*a^23-25914*a^21+246960*a^19-700*a^18-1543941*a^17+21168*a^16+6465060*a^15-254016*a^14-18197865*a^13+1560552*a^12+34034175*a^11-5321988*a^10-40965225*a^9+10224144*a^8+29604330*a^7-10606932*a^6-10927980*a^5+5186160*a^4+1256409*a^3-777924*a^2+21952; #nfroots(K,P)} \\ no factor #930 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-172*x^8+192*x^6-112*x^4+32*x^2+4) \\ 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-19578944328750*x^7-23826919393125*x^6+4261743915000*x^5+5216451275625*x^4-517952334375*x^3-635253609375*x^2+26484140625*x+32625390625; #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) \\ Bug #980 P=x^6 - x^5 - 76*x^4 + 60*x^3 + 1140*x^2 + 1155*x - 695 Q=a^36 - 140*a^34 + 8402*a^32 - 288950*a^30 + 6406703*a^28 - 97539585*a^26 + 1059042259*a^24 - 8396309325*a^22 + 49297808195*a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285*a^14 + 3017070472643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 1836758642090*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125 lift(nfroots(Q,P)) \\ Bug #1023 do(a^2+13,polcyclo(13,13*x^2)) \\ Bug #1070 do(y^2-5,x^5-x^4-7*x^3+x^2+7*x-3) \\ Bug #1075 lift(nffactor(polcyclo(21,y), x^2-y^7)) \\ Bug #1132 do(y^4-y^2+1, 3*x^3+(-12*y^3+6*y)*x^2-11*y^2*x+(2*y^3-4*y)) \\ Bug #1141 do(y^2-y+1, (x-(1+y)/3)^2*(x+2*(1+y)/3)) \\ Bug #1142 lift(nffactor(3*y^2+1, 3*x^2+1)) lift(nfroots(3*y^2+1, 3*x^2+1)) \\#1207 lift(nffactor(t^6-6*t^5-3298534883316*t^4+13194139533310*t^3+3626777458830693384585198*t^2-7253554917667983838937052*t-1329227995784915872903826851489644559,x^3-3)) \\#1276 pol=1225*x^6+1750*x^5-21675*x^4-380*x^3+110180*x^2-129720*x+48771;lift(factorback(factornf(pol,subst(pol,x,y)))) \\#1438 factor((x^2-1)*(x^2-2)*(x^2-5)) \\#1446 factor((x^80-1)/(x-1)) \\also exercises Flx_extgcd above half-gcd threshold test(T,p)= { v=polhensellift(T,lift(factormod(T,p)[,1]),p,10); valuation(T-factorback(v),p); } \\also exercises FqX_extgcd above half-gcd threshold test(polcyclo(503),3) test(polcyclo(211),18446744073709551667) nfroots(a^2+1,x^2) do(y^2-22,x^2+926246528884912528275985458927067632*y-4344481316563541186659879867597013188) pari-2.7.5/src/test/in/quad0000644000175000017500000000016112366172547014152 0ustar billbilldefault(realprecision,38); w=quadgen(5); w^0 w+1. w+(I+0.) 1.*w (I+0.)*w norm(w) norml2(w) trace(w) trace(1+0*w) pari-2.7.5/src/test/in/round0000644000175000017500000000055512405547147014352 0ustar billbilldefault(realprecision,38); round((1e-40 + x) / (1e-39 + x)) v=[1,1.6,-4/3,Mod(1,3),quadgen(5),Mod(4/3+x,x^2+1/2),x,4/3+x/3+O(x^2),1/x,[4/3,2],matid(2)/3,""]; test(f)= for(i=1,#v, print(iferr(f(v[i]),E,E))); test(ceil) test(floor) test(frac) test(round) round(0,&E); test(x->[round(x,&e), if(e==E,-'oo,e)]) test(truncate) test(x->[truncate(x,&e), if(e==E,-'oo,e)]) pari-2.7.5/src/test/in/program0000644000175000017500000000207412366172547014674 0ustar billbillHEAP=[50, if(precision(1.)==38,1927,3359)]; STACK=if(precision(1.)==38, 232, 128); STACK == getstack default(realprecision,38); \e alias(ln,log) ln(2) for(x=1,5,print(x!)) fordiv(10,x,print(x)) forprime(p=1,30,print(p)) forstep(x=0,2.9,Pi/12,print(sin(x))) forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" "); if(3<2,print("bof"),print("ok")); kill(y);print(x+y); f(u)=u+1; print(f(5));kill(f); f=12 g(u)=if(u,,return(17));u+2 g(2) g(0) n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1) m=5;while(m<20,print1(m," ");m=m+1);print() \\ default(seriesprecision,12) print((x-12*y)/(y+13*x)); print([1,2;3,4]) print1(x+y);print(x+y); print((x-12*y)/(y+13*x)); print([1,2;3,4]) print1(x+y);print1(" equals ");print(x+y); print1("give a value for s? ");s=input();print(1/(s^2+1)) printtex((x+y)^3/(x-y)^2) for(i=1,100,for(j=1,25,if(i+j==32,break(2)));print(i)) { u=v=p=q=1; for (k=1,400, w=u+v; u=v; v=w; p *= w; q=lcm(q,w); if (k%50==0, print(k" "log(p)/log(q)) ) ); } install(addii,GG) addii(1,2) kill(addii) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/variable0000644000175000017500000000020512366172547015004 0ustar billbillv=[1,O(3),x,O(x),Mod(y,y^2+1),1/y,[y,z],Mat(z),List(),List([y,z])]; { for(i=1,#v, print(iferr(variable(v[i]), E,E)) ) } variable() pari-2.7.5/src/test/in/ff0000644000175000017500000000431512405547147013614 0ustar billbill{ test(p,f) = setrand(1); a = ffgen(p^f, 'a); [ a^2+3*a+1, a/(1+a), 2*(a+1)/3, 1/5+a, if (6*a, 5/6/(a+1)), if (6*a, 5/6*(a+1)), shiftmul(a+1,10), if (2*a, shiftmul(a+1,-10)), a^-1, -a, sqr(a), sqrt(a^(2^10)), sqrtn((a^2+a+1)^3,3), sqrtn((a^2+a+1)^3,3,&z), z, if (ispower(a,3), a^(2/3)), norm(a^2+1), trace(a), charpoly(a), minpoly(a), conjvec(a), factor(x^6-a*x^3+1), ellinit([a,1]), a/x, (x+a)/(x-a), b=ffprimroot(a), fforder(a), b^fflog(a,b), factorff(x^2+x+a), polrootsff(x^2+x+a) ]; } default(echo,1); test(2, 20) 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)) for(i=1,10,print(ffnbirred(11,i))); for(i=1,10,print(ffnbirred(11,i,1))); 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 = 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)); factorff(x^12 + t*x^10 + x^6 + (t+1)*x^2 + 1) \\ #1241 polrootsff(x^2 - x - ffgen((v^2+1) * Mod(1,3))) \\ #1350 polrootsff(2*x+1,2,y) 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); factor((x^24-1)*t^0) factorff(Pol(0),t.p,t.mod) factorff(Pol(1),t.p,t.mod) factorff(x^4-t,t.p,t.mod) 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) 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 pari-2.7.5/src/test/in/lindep0000644000175000017500000000066712366172547014506 0ustar billbilllindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)]) lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)]) lindep([1,2,3;4,5,6;7,8,9]) lindep([x*y, x^2 + y, x^2*y + x*y^2, 1]) z = sqrt(1+5*y+y^2+y^3); seralgdep(z, 2,3) seralgdep(z, 2,2) seralgdep(1/(1-y+O(y^5)), 1,1) seralgdep(1+5*y+O(y^3), 1,10) lindep([]) lindep([0]) lindep([1]) lindep([1,I]) algdep(1,0) algdep(1,-1) z=sqrt(2+O(7^4)); algdep(z,2) lindep(Mod([E*x, E*x + E, E^2*x^2 + E*x + 2*E], E^3)) pari-2.7.5/src/test/in/bnr0000644000175000017500000000225112573550041013770 0ustar billbilldefault(realprecision,38); K=bnfinit(x^3-x-1); subgrouplist(bnrinit(K,10)) K=bnrinit(K,20); default(realprecision,77); nfnewprec(K); default(realprecision,38); subgrouplist(K) subgrouplist(K, 2) subgrouplist(K, 2, 1) bnrL1(bnrinit(bnfinit(x^2+1),10,1),1); setrand(5);bnrL1(bnrinit(bnfinit(y^2+6),1,1),0); bnrL1(bnrinit(bnfinit(x),[5,[1]],1)); \\ #1399 bnf=bnfinit(y^2+1); bnrdisc(bnf,12) setrand(1);bnf=bnfinit(x^2-x-57); test(m)= { print(bnrisconductor(bnf,m), ", ", bnrclassno(bnf,m), ", ", bnrdisc(bnf,m)); } test([[25,13;0,1],[1,1]]) test([[25,13;0,1],[1,0]]) test([[5,3;0,1],[1,0]]) test([5,3;0,1]) m=[idealfactor(bnf,[5,3;0,1]),[1,0]]; H=Mat(2); bnr=bnrinit(bnf, idealstar(bnf,m,2)); f=[bnrclassno,bnrdisc,bnrconductor]; { for (i=1,#f, print(f[i](bnr)); print(f[i](bnr,H)); print(f[i](bnf,m)); print(f[i](bnf,m,H)); ) } bnrdisc(bnf,m,H,1) bnrdisc(bnf,m,H,2) bnrdisc(bnf,m,H,3) bnrdisc(bnf,[5,3;0,1],H,2) bnrdisc(bnf,[5,3;0,1],H,3) bnrclassno(bnf, idealprimedec(bnf,5)[1]) bnr=bnrinit(bnf,[7,[1,1]],1); bnrrootnumber(bnr, [2,1]) bnrrootnumber(bnr, [0,0]) bnr=bnrinit(bnfinit(x^2-97),1,1); bnrrootnumber(bnr,[]) bnfnarrow(bnfinit(x^2-460)) bnrconductor(bnfinit(K),4,Mat(3)) pari-2.7.5/src/test/in/bestappr0000644000175000017500000000073212314242551015026 0ustar billbillbestappr(-1./7, 7) bestappr(-1./7, 6) bestappr(Mod(-1/7,100)) bestappr(Mod(-1/7,100), 6) bestappr(Mod(-1/7,100), 7) bestappr(-1/7 + O(5^10)) bestappr(-1/7 + O(5^10), 6) bestapprPade((x^3+1)/(x^10+2)) bestapprPade((x^3+1)/(x^10+2), 4) bestapprPade(1/(1+x+O(x^10))) bestapprPade(1/(1+x+O(x^10)), 5) bestapprPade(1/(1+x^6+O(x^13)), 5) bestapprPade(1/(1+x^6+O(x^13))) bestapprPade(Mod(x^3+x^2+x+1, x^5-2)) bestapprPade(x^2+x^3+x^4+O(x^5)) bestapprPade(x^-4+x^-3+x^-2+O(x^-1)) pari-2.7.5/src/test/in/interpol0000644000175000017500000000055312366172547015061 0ustar billbilldefault(realprecision, 38); polinterpolate([2,3,4]) polinterpolate([2,3,4] * Mod(1,7)) polinterpolate([2,3,4] * Mod(1,7),, 0) polinterpolate([1,2,4], [2,3,4]) polinterpolate([1,2,4] * Mod(1,7), [2,3,4], 0) polinterpolate([1,2,4], [2,3,4], 1.5) polinterpolate([1,2,4], [2,3,4], 1.5, &e); e polinterpolate([1,2],[0,0]) polinterpolate([],[]) polinterpolate([1],[2]) pari-2.7.5/src/test/in/ellsea0000644000175000017500000000301112414216316014445 0ustar billbill\\package:seadata ellmodulareqn(5) do(i,v)= { E = ellinit([0,0,0,v[2],v[3]]*Mod(1,v[1])); print(i, ": ", ellap(E,v[1])); } { v=[[202600005603433095160409308644759862837,25496852782325453225973142890909600552,129550610797481291887769966647995045232], [173327739907566197112155895875385467119,52716988591102938437323369716512206005,43087597392844950895070462564402654315], [523583591335747530615071369664554118036421993253,25679429559575246581833628827363203226862930934,78220741356817481602535950765825830003112603824], [1319450668936329467137913739322239157303860926441,807652438980115949692649657326438677571309575087,1017125626316888896817395440127041355136940446205], [439581010348913995032270658729785287035964480323270935583,323922016281172901245123590380881598241426088528431020005,54496426275749371996644207660602248980615186517525561222], [2979720374579183569554262247145622188470249961843364603751,428654869348535206084607029945439317783967748844874233571,1182279475380088064870625220629639405548336474256523329003], [6243380271698146227966925307851825694742847655729810693741,4068721281680536125235363885580194460678653324971583338307,2519148351962491328666249705249360758373031631978108875818], [1606938044258990275541962092341162602522202993782792835304761,1,252199199707645577897249048746397012330572101453777389069968], [1267650600228229401496703205953,1,417990942431022911086532367249], [590295810358705651741,1,3], [18446744073709551629,1,42]]; } for(i=1,#v, do(i,v[i])); g=ffgen(nextprime(2^32)^2);E=ellinit([g,3]);ellap(E) pari-2.7.5/src/test/in/sqrtn0000644000175000017500000000170012366172547014367 0ustar billbilldefault(realprecision,38); sqrtn(0.,3) sqrtn(0.*I,3) sqrtn(1/2,3) sqrtn(quadgen(5),3) sqrtn(8+O(17^100), 3) test(b, M)= { my (B = b); for (i=2, M, B *= b; \\ b^i a = sqrtnint(B + 1, i); if (a != b, error([b, B, i])); ); } test(2, 100); test(2^32+1, 10); test(2^64+1, 10); sqrtn(Mod(0,3),-2) sqrtn(O(3),-2) sqrtn(0*ffgen((2^64+13)^2),-2) sqrtn(0*ffgen(3^2),-2) sqrtn(0*ffgen(2^2),-2) sqrtnint(10^1000,1001) sqrtn(2., 10, &z) z sqrtn(10+O(3^8), 10, &z) z sqrtn(1+O(3^3), -3) sqrtn(1,1) sqrtn(1,-1,&z) z sqrtn(Mod(2,4),3) sqrtn(Mod(2,4),3,&z) sqrtn(1, 3) sqrtint(0) iferr(sqrt(3+O(2^2)),E,E) iferr(sqrt(3+O(2^3)),E,E) iferr(sqrt(Mod(2,11)),E,E) iferr(sqrt(Mod(2,33)),E,E) sqrt(0.e-10+1e-10*I) [sqrtn(27+O(3^4),3,&z), z] [sqrtn(16+O(2^5),4,&z), z] [sqrtn(2^6+O(2^9),6,&z), z] sqrtn([8,27],3) iferr(sqrtn(Mod(2,7),3),E,E) [sqrtn(Mod(2,7),3,&z),z] iferr(sqrtn(Mod(2,21),3),E,E) iferr(sqrtn(Mod(6,35),6),E,E) [sqrtn(Mod(64,101),6,&z),z] sqrtn(0,3) pari-2.7.5/src/test/in/minmax0000644000175000017500000000027712314242552014504 0ustar billbillv = [-3,7,-2,11]; obj = [1, v, Vecsmall(v), [-3,7;-2,11]]; { for (i = 1, #obj, my (o = obj[i], u,v); vecmin(o, &u); vecmax(o, &v); print(i, ": ", [vecmax(o), vecmin(o), u, v]); ) } pari-2.7.5/src/test/in/addprimes0000644000175000017500000000113712366172547015174 0ustar billbillp = nextprime(10^6); q = nextprime(p+1); a = 2*3*5*7; sigma2(x) = sigma(x, 2); sigma3(x) = sigma(x, 3); fun = [ispowerful, moebius, core, omega, bigomega, eulerphi, numdiv, sigma, sigma2, sigma3]; vec(n) = vector(#fun, i, fun[i](n)); args = [a, a*p, a*p*q, a*p^2*q, -a*p]; vals = vector(#args, i, vec(args[i])) TEST() = { for (i=1,#args, my(n = args[i]); print("Testing ", n, ", addprimes = ", addprimes()); if (vec(n) != vals[i], error(n)) ); } addprimes(p); TEST(); addprimes([p,q]); TEST(); removeprimes(p); TEST(); removeprimes(addprimes()) addprimes([p,q,1009]); removeprimes([p,q]) pari-2.7.5/src/test/in/sort0000644000175000017500000000104212366172547014206 0ustar billbilldefault(realprecision,38); v = [[1,2], [4,1], [3,4], [1,3/2], [5/2,1.]]; x = [1,2]; y = [5,2]; w = vecsort(v) vecsearch(w, x) vecsearch(w, y) K = [ 1, 2, 3, [2,1], [3,1], (x,y)->sign(x[1] - y[1]) ]; { for (i = 1, #K, iferr (w = vecsort(v, K[i]); print(w); print(vecsearch(w, x, K[i])); print(vecsearch(w, y, K[i])), E, print(E)) ) } vecsort(Vecsmall([4,3,2,1])) vecsort(List([4,3,2,1])) v=[4,3,4,1,4,2,3]; vecsort(v,, 8) vecsort(v,, 8+1) vecsort(v,, 8+4) vecsort(v,, 8+4+1) vecsort(List(),,4) pari-2.7.5/src/test/in/qfbsolve0000644000175000017500000000115112366172547015041 0ustar billbillqfbeval(V,v)= { my(x,y); V=Vec(V);x=v[1];y=v[2]; V[1]*x^2+V[2]*x*y+V[3]*y^2; } bqfb(N=10000)= { my(p,d,r,V,q,q2,Q,Q2); for(i=1,N, until(!issquare(d) && (d%4==0 || d%4==1),d=random(4000)-2000); until(p==1 || kronecker(d,p)>=0, p=random(1000)-100; if(p<3,p=1,p=nextprime(p))); q=qfbprimeform(d,p); V=Vec(q); q2=Qfb(V[3],V[2],V[1]); until(Q!=0||Q2!=0,r=nextprime(random(30000)); Q=qfbsolve(q,r);Q2=qfbsolve(q2,r)); if(Q2==0||qfbeval(q2,Q2)!=r,print("qfbsolve(",q2,",",r,")!=",Q2);break); if(Q==0||qfbeval(q,Q)!=r,print("qfbsolve(",q,",",r,")!=",Q);break)); } bqfb(); pari-2.7.5/src/test/in/gamma0000644000175000017500000000077712532335645014312 0ustar billbilldefault(realprecision,38); default(seriesprecision,6); gamma(2+I+x) gamma(1+x) gamma(-2+x) lngamma(2+I+x) lngamma(1+x) lngamma(-2+x) psi(2+I+x) psi(1+x) psi(-2+x) gamma(-1/2+x) gamma(1+a*x+O(x^2)) psi(x) gamma(x) gamma(1000) psi(2^400) psi(-1.5) binomial(2^64+1,2) binomial(1001.,1000) lngamma(2^301) lngamma(2^301 + 2*I) lngamma(2^64 + 2*I) lngamma(-200.5) gammah(400) gammah(400+I) default(realprecision,115); lngamma(2^301 + 2*I) lngamma(2^301 + 200*I) default(realprecision,154); lngamma(2^301 + 2000*I) pari-2.7.5/src/test/in/bit0000644000175000017500000000123312366172547013777 0ustar billbillhammingweight(15) hammingweight(x^100 + 2*x + 1) hammingweight([Mod(1,2), 2, Mod(0,3)]) hammingweight(Vecsmall([0,1,2,3])) hammingweight(matid(100)) hammingweight(I) N = 2^128+2^64+1; [bittest(N, i) | i<-[60..70]] { args = [0, 3, -3, 2^65-1, N, -N, I]; funs = [bitand, bitnegimply, bitor, bitxor]; for (a=1,#funs, my (f = funs[a]); print("#", f); for (i=1,#args, for (j=i,#args, my(u=args[i], v=args[j]); print([u,v,iferr(f(u,v),E,E)]) ) ) ); print("#bitneg"); for (i=1, #args, my (u=args[i]); print(iferr([u, bitneg(u,65),bitneg(u)],E,E)) ) } bittest(-1,10) bitneg(-2,64) bitneg(1,-2) bitneg(1,128) pari-2.7.5/src/test/in/div0000644000175000017500000000134212366172547014004 0ustar billbilldefault(realprecision,38); v=[3,4,3.1,1/2,x^2+1, Mod(x,x^2+1),ffgen(3^5,'t),quadgen(5),2+O(3^3),Mod(2,3), 2^64 + 1]; { for (i=1,#v, for(j=1,#v, print("* ",[i,j]); print(iferr(v[i]/v[j],E,E)); print(iferr(v[i]\v[j],E,E)); print(iferr(v[i]%v[j],E,E)); print(iferr(v[i]\/v[j],E,E)); print(iferr(divrem(v[i],v[j]),E,E)); ) ) } w=[x + O(x^2),[2,3],Mat(2)]; { for (i=1,#w, for(j=1,#v, print("* ",[i,j]); print(iferr(w[i]/v[j],E,E)); print(iferr(w[i]\v[j],E,E)); print(iferr(w[i]%v[j],E,E)); print(iferr(w[i]\/v[j],E,E)); ) ) } for (i=2,#w, print(w[i]%2)) for (i=2,#w, print(w[i]\2)) divrem(x+y^2,y+x,y) divrem([3,5],2) divrem(1,x) divrem(1,Pol(1)) divrem(1,"a") (5/3) \/ 1 floor((x^2+1)/x) pari-2.7.5/src/test/in/galois0000644000175000017500000002061712366172547014506 0ustar billbill\\package:galdata test(a)= { my(x, y, z); for (i=1, 10000, z = eval(Str("T", a, "_", i)); if (poldegree(z) == 1, break); \\ undefined x = polgalois(z); y = polgalois(poltschirnhaus( poltschirnhaus(z) )); print(x, x==y) ); } { T1_1 = x; T2_1 = x^2+x+1; T3_1 = x^3+x^2-2*x-1; T3_2 = x^3+2; T4_1 = x^4+x^3+x^2+x+1; T4_2 = x^4+1; T4_3 = x^4-2; T4_4 = x^4+8*x+12; T4_5 = x^4+x+1; T5_1 = x^5+x^4-4*x^3-3*x^2+3*x+1; T5_2 = x^5-5*x+12; T5_3 = x^5+2; T5_4 = x^5+20*x+16; T5_5 = x^5-x+1; T6_1 = x^6+x^5+x^4+x^3+x^2+x+1; T6_2 = x^6+108; T6_3 = x^6+2; T6_4 = x^6-3*x^2-1; T6_5 = x^6+3*x^3+3; T6_6 = x^6-3*x^2+1; T6_7 = x^6-4*x^2-1; T6_8 = x^6-3*x^5+6*x^4-7*x^3+2*x^2+x-4; T6_9 = x^6+2*x^3-2; T6_10= x^6+6*x^4+2*x^3+9*x^2+6*x-4; T6_11= x^6+2*x^2+2; T6_12= x^6-2*x^5-5*x^2-2*x-1; T6_13= x^6+2*x^4+2*x^3+x^2+2*x+2; T6_14= x^6-x^5-10*x^4+30*x^3-31*x^2+7*x+9; T6_15= x^6+24*x-20; T6_16= x^6+x+1; T7_1 = x^7+x^6-12*x^5-7*x^4+28*x^3+14*x^2-9*x+1; T7_2 = x^7+7*x^3+7*x^2+7*x-1; T7_3 = x^7-14*x^5+56*x^3-56*x+22; T7_4 = x^7+2; T7_5 = x^7-7*x^3+14*x^2-7*x+1; T7_6 = x^7+7*x^4+14*x+3; T7_7 = x^7+x+1; T8_50 = x^8-x-1; T8_49 = x^8-2*x^6-2*x^5-x^4-x^3+4*x^2+4*x-2; T8_48 = x^8-2*x^6-2*x^5+2*x^4+4*x^2+2; T8_47 = x^8+x^2+2*x+1; T8_46 = x^8-4*x^5-9*x^4-16*x^2-12*x+9; T8_45 = x^8-2*x^6-2*x^5+4*x^3+2*x^2+2; T8_44 = x^8+x^2-1; T8_43 = x^8-x^7+7*x^2-x+1; T8_42 = x^8-2*x^6+2*x^5+3*x^4-2*x^3+x^2+4*x+2; T8_41 = x^8-4*x^5+3*x^4+16*x^2+12*x+9; T8_40 = x^8+8*x^6+18*x^4-1; T8_39 = x^8+x^2+1; T8_38 = x^8-4*x^6+28; T8_37 = x^8-4*x^7+28*x^5-21*x^4-70*x^3+189*x^2-173*x+69; T8_36 = x^8-4*x^7+112*x^4+224*x^3-112*x^2-736*x+536; T8_35 = x^8+4*x^2-1; T8_34 = x^8+4*x^7+5*x^6+x^5+x^4-2*x^3-x^2+3*x+2; T8_33 = x^8-8*x^6+18*x^4-16*x^3-40*x^2+8*x+23; T8_32 = x^8-8*x^6+18*x^4+4; T8_31 = x^8+2*x^6+x^4+14; T8_30 = x^8+4*x^6+4*x^4-2; T8_29 = x^8+x^4+2*x^2+1; T8_28 = x^8+4*x^6+2; T8_27 = x^8+5*x^6+3*x^4-6*x^2-4; T8_26 = x^8+2*x^4-2; T8_25 = x^8-x^7+29*x^2+29; T8_24 = x^8-4*x^2+4; T8_23 = x^8-8*x^6+12*x^4-12; T8_22 = x^8+x^4+4; T8_21 = x^8+2*x^4+4*x^2+2; T8_20 = x^8+x^6-6*x^4-x^2+1; T8_19 = x^8+4*x^4+4*x^2+1; T8_18 = x^8+2*x^6+2*x^2+1; T8_17 = x^8+2*x^4+2; T8_16 = x^8+4*x^4+2; T8_15 = x^8+3; T8_14 = x^8+2*x^7+4*x^6-2*x^5+2*x^4-2*x^3+4*x^2+2*x+1; T8_13 = x^8+4*x^6+8*x^4+4; T8_12 = x^8-22*x^6+135*x^4-150*x^2+1; T8_11 = x^8+9; T8_10 = x^8+2*x^6+4*x^4+3*x^2+1; T8_9 = x^8+4*x^4+1; T8_8 = x^8-2; T8_7 = x^8+x^7-28*x^6-7*x^5+70*x^4+7*x^3-28*x^2-x+1; T8_6 = x^8+2; T8_5 = x^8-12*x^6+36*x^4-36*x^2+9; T8_4 = x^8+3*x^4+1; T8_3 = x^8-x^4+1; T8_2 = x^8+1; T8_1 = x^8+x^7-7*x^6-6*x^5+15*x^4+10*x^3-10*x^2-4*x+1; T9_34 = x^9-x-1; T9_33 = x^9+27*x-24; T9_32 = x^9+x^7+2*x^5+4*x^3-x^2+x+1; T9_31 = x^9-2*x^7-2*x^6-x^5-x^4+4*x^3+5*x^2+4*x+1; T9_30 = x^9+2*x^5+4*x^4+4*x^3+4*x^2+x+1; T9_29 = x^9-6*x^6-18*x^5+36*x^4-36*x^3+108*x^2-144*x+48; T9_28 = x^9-2*x^7-2*x^6-x^5-2*x^4+3*x^2+3*x+1; T9_27 = x^9-36*x^6-54*x^5+432*x^3+324*x^2-243*x-1152; T9_26 = x^9-x^7+5*x^6+x^5-2*x^4+4*x^3+3*x^2-x-1; T9_25 = x^9-9*x^6-9*x^4+24*x^3+9*x^2-9*x+1; T9_24 = x^9-2*x^6-2*x^3-2; T9_23 = x^9+9*x^7-60*x^6+72*x^5+354*x^3-495*x^2+2124*x-845; T9_22 = x^9-12*x^6-27*x^5-18*x^4+9*x^3+36*x-8; T9_21 = x^9+3*x^6+3*x^3-2; T9_20 = x^9-2*x^7-2*x^6-2*x^5+x^4+4*x^3+3*x^2+3*x+1; T9_19 = x^9-3*x^8-24*x^5-24*x^4-48*x+16; T9_18 = x^9-2*x^6-2*x^3-1; T9_17 = x^9-17*x^7-6*x^6+87*x^5+47*x^4-143*x^3-69*x^2+72*x+27; T9_16 = x^9-2*x^7+3*x^6+x^5-x^4-2*x^3+x+1; T9_15 = x^9-9*x^7-21*x^6+72*x^5+99*x^4-99*x^3-585*x^2+549*x+166; T9_14 = x^9-30*x^6+45*x^5+126*x^4-240*x^3-90*x^2+405*x+80; T9_13 = x^9-2*x^6-x^3+1; T9_12 = x^9+x^8+x^7+4*x^6-2*x^5-x^4+3*x^3+x^2-1; T9_11 = x^9-x^6+5*x^3+1; T9_10 = x^9-2; T9_9 = x^9-3*x^8+3*x^7-15*x^6+33*x^5-3*x^4+24*x^3+6*x^2-4; T9_8 = x^9-6*x^6+8*x^3-8; T9_7 = x^9-232*x^7-9*x^6+7485*x^5+8631*x^4-3097*x^3-738*x^2+325*x-27; T9_6 = x^9+x^8-32*x^7-84*x^6-14*x^5+112*x^4+84*x^3+4*x^2-8*x-1; T9_5 = x^9+3*x^6+3*x^3-1; T9_4 = x^9+4*x^6+3*x^3-1; T9_3 = x^9+9*x^7-6*x^6+27*x^5-36*x^4+27*x^3-54*x^2-32; T9_2 = x^9-15*x^7+4*x^6+54*x^5-12*x^4-38*x^3+9*x^2+6*x-1; T9_1 = x^9-9*x^7+27*x^5-30*x^3+9*x-1; T10_45 = x^10-x-1; T10_44 = x^10-2*x^8-2*x^7-2*x^3+2*x^2+x-1; T10_43 = x^10-2*x^8-2*x^7-2*x^6-2*x^5-x^4-2*x^3+3*x^2-2*x+1; T10_42 = x^10-32*x^5-200*x^2+256; T10_41 = x^10+2*x^9+4*x^8-x^6+x^4-2*x-1; T10_40 = x^10+x^9-x^8-x^7-2*x^6+2*x^3+3*x^2+x+1; T10_39 = x^10-2*x^8-2*x^7-2*x^6-2*x^5+2*x^4-2*x^3+2*x^2-1; T10_38 = x^10-2*x^8-x^6-2*x^4+2*x^2-2; T10_37 = x^10-2*x^8-2*x^7-x^6-x^5-x^4-2*x^3-2*x^2+1; T10_36 = x^10-2*x^8-x^6+3*x^4-x^2+2; T10_35 = x^10+300*x^6-18*x^5+10000*x^2-200*x+81; T10_34 = x^10-x^8-2*x^6-x^4+x^2-1; T10_33 = x^10-2*x^9+12*x^8-20*x^7+66*x^6-20*x^5+228*x^4+84*x^3+276*x^2+120*x+100; T10_32 = x^10-9*x^8+27*x^6+2*x^5-27*x^4-9*x^3+8*x+1; T10_31 = x^10-1800*x^8-24000*x^7+1422000*x^6+30960000*x^5-462480000*x^4-14500800000*x^3+12996000000*x^2+2414368000000*x-12197187420489; T10_30 = x^10+90*x^6-648*x^5+1080*x^4-2160*x^3+3645*x^2+5400*x+12960; T10_29 = x^10+2*x^8-2*x^6-x^2+2; T10_28 = x^10-10*x^7+10*x^6+36*x^5+50*x^4-10*x^3-1; T10_27 = x^10+3*x^6-2*x^5+x^2+2*x+1; T10_26 = x^10-15*x^8-75*x^6-6*x^5-165*x^4-30*x^3-180*x^2-50*x-90; T10_25 = x^10-2*x^8-2*x^6-x^2-2; T10_24 = x^10+x^8-x^4+3*x^2-1; T10_23 = x^10-2*x^8-x^7+3*x^6+2*x^5-2*x^4-2*x^3+2*x^2+3*x+1; T10_22 = x^10-2*x^8-2*x^7-x^6+x^4-2*x^3+2*x^2-1; T10_21 = x^10+x^6-2*x^5-x^4+3*x^2-2*x+1; T10_20 = x^10-3*x^9+x^8+36*x^7-39*x^6-105*x^5+99*x^4+180*x^3-45*x^2-135*x-45; T10_19 = x^10-10*x^8+35*x^6-2*x^5-50*x^4+10*x^3+25*x^2-10*x+2; T10_18 = x^10+60*x^6-240*x^5+850*x^2-5440*x-1088; T10_17 = x^10-2*x^5-2; T10_16 = x^10+7*x^8+17*x^6-31*x^4-40*x^2+127; T10_15 = x^10-x^8-2*x^6+x^4+3*x^2-1; T10_14 = x^10+x^8-4*x^6-3*x^4+3*x^2+1; T10_13 = x^10-2*x^8-x^7-2*x^6+x^5+3*x^4-2*x^3-x^2+x+1; T10_12 = x^10+2*x^9+3*x^8-x^6-2*x^5-x^4+3*x^2+2*x+1; T10_11 = x^10+10*x^6+25*x^2-8; T10_10 = x^10-2*x^5-4; T10_9 = x^10-50*x^8-100*x^7+865*x^6+4036*x^5+4100*x^4+16400*x^2+13120*x+2624; T10_8 = x^10-4*x^8+2*x^6+5*x^4-2*x^2-1; T10_7 = x^10-2*x^5-15*x^4-10*x^3-15*x^2-5; T10_6 = x^10+5*x^8-33*x^7-67*x^6+132*x^5-375*x^4+1551*x^3+5505*x^2-8987*x+4291; T10_5 = x^10-2; T10_4 = x^10-x^5-1; T10_3 = x^10-x^8-x^6+3*x^4+2*x^2+1; T10_2 = x^10-35*x^6+130*x^4+160; T10_1 = x^10-x^9+x^8-x^7+x^6-x^5+x^4-x^3+x^2-x+1; T11_8 = x^11-x-1; T11_7 = x^11+x^10+2*x^9+2*x^8+x^6-x^5+2*x^4+2*x^3+x^2-1; T11_6 = x^11-x^10-121*x^9+65*x^8+5345*x^7-481*x^6-96739*x^5-23689*x^4+413690*x^3-493810*x^2+26910*x-856170; T11_5 = x^11-898*x^9-3080*x^8+293480*x^7+4185984*x^6-145552352*x^5+1474999680*x^4-16923164544*x^3+177410331648*x^2-709199732736*x+63589515264; T11_4 = x^11-2; T11_3 = x^11-33*x^9+396*x^7-2079*x^5+4455*x^3-2673*x-243; T11_2 = x^11-x^10+5*x^8+8*x^5+6*x^4-x^3+x^2+3*x+1; T11_1 = x^11+x^10-10*x^9-9*x^8+36*x^7+28*x^6-56*x^5-35*x^4+35*x^3+15*x^2-6*x-1; } default(realprecision, 38); default(new_galois_format, 1) for (i = 1, 11, test(i)) default(new_galois_format, 0) for (i = 1, 7, test(i)) \\ miscellaneous tests setrand(3);polgalois(x^8-24447832222819253258096747170722821932737551721814653244372785289945042560370884249414339208601850*x^4+24447832222819253258096747170722821932737551721825709426404304862673539625219608619381278993545125*x^2+24447832222819253258096747170722821932737551721825709426404304862673539625219608619381278993545125) polgalois(polzagier(11,0)/polzagier(1,0)) polgalois(x^8-1864259299553450972214799899167226732549697977945716*x^6+331143259018657601105207922631212331088735421305543663274125986698777318014979969*x^4-2225286541902342283500014249183311190477390*x^2+5) polgalois(x^8+162644002617632464507038884216211529274267271168000002) polgalois(x^8+2^2^12) setrand(5);polgalois(x^8-3911867303938246274330482940384509030446487325649036998411199166662010711465575565062431210085563041214249877058238647352476889609806751307308111079477582030570450*x^4-3911867303938246274330482940384509030446487325649036998411199166662010711465575569485025077906938222890835591100732814736005780908137290944485033156820540880540405*x^2+3911867303938246274330482940384509030446487325649036998411199166662010711465575569485025077906938222890835591100732814736005780908137290944485033156820540880540405) setrand(15);polgalois(x^8-1642492255488433999638100059165477791152530*x^4-1642492255488433999640965798385546876573045*x^2+1642492255488433999640965798385546876573045) setrand(4);polgalois(x^8-264*x^6+25410*x^4-1054152*x^2+15856203) setrand(15);polgalois(x^8-3512859249280433994187541000*x^6+1542522513156886787688759313741174472421584953335229070*x^4-60930543678769127629182898645000*x^2+300849025) setrand(1); polgalois(x^11+627*x^4-584) pari-2.7.5/src/test/in/pow0000644000175000017500000000075412571635556014037 0ustar billbilldefault(realprecision,38); (Mod(1,3)+I)^0 (Mod(1,9)+I*Mod(1,3))^0 (1/x)^0 [;]^0 Mat(2)^0 Qfb(2,0,-1)^0 Qfb(2,0,-1)^1 Vecsmall([3,2,1])^0 O(2)^1 O(2)^-2 (1/2)^-2 (-2/3)^-2 n=2^64; 1^n (-1)^n (-1)^(n+1) 2^n (1/2)^n Qfb(2,0,-1)^n Mod(x,polcyclo(7))^n O(x)^(1/2) (x^3+O(x^6))^(1/3) [2,3]^3. [2,3]~^3. Mat(2)^3. O(x^0)^(1/3) 0.^(1/2) Mod(2,3)^(1/2) Mod(2,3)^(1/3) Mod(1,4)^(1/2) (2+O(7^5))^(1/2) (3+O(7^5))^(1/2) sqrt(1+O(2)) sqrt(1+O(2^3)) sqrt(Mod(2,4)) [0,1]^[1,2] [0,1]^[1,2]~ [0,1]^[1,1;2,3] pari-2.7.5/src/test/in/diffop0000644000175000017500000000042212366172547014467 0ustar billbilldiffop(E*X,[X,E],[1,X*E],10) diffop(Mod(S/C,S^2+C^2-1),[C],[-S],10) E4(n)=1+240*sum(i=1,n,sigma(i,3)*q^i)+O(q^(n+1)); diffop(E4(15),[q],[q]) diffop(Mod(y,x^2-y),[y],[1]) diffop(Mod(10^100,x^2+y),[y],[1]) diffop(lllx,[x,lx,llx,lllx],[1,1/x,1/(x*lx),1/(x*lx*llx)],6)*Mod(1,3) pari-2.7.5/src/test/in/member0000644000175000017500000000273212405547147014471 0ustar billbill\\package:elldata default(realprecision,38); { members=[ a1, a2, a3, a4, a6, b2, b4, b6, b8, c4, c6, area, bid, bnf, clgp, codiff, cyc, diff, disc, e, eta, f, fu, gen, group, index, j, mod, nf, no, omega, orders, p, pol, polabs, r1, r2, reg, roots, sign, t2, tate, tu, zk, zkst ];} \\ tufu, futu omitted test(s)= { for (i=1, #members, my (m = members[i]); iferr( print(".", m, ": ", eval(Str("s.", m))), E, n = errname(E); if (n != "e_IMPL" && n != "e_TYPE" && n != "e_MISC", error(E)))); } test(x) test(vector(5)) test(vector(20)) test([]~) print("NF"); test( NF = nfinit(y^2-1105) ) print("NF chvar"); test( nfinit(2*y^2+1) ) 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("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)) ) print("ELLQp");test( ellinit([1,2,3,4,5], O(11^2)) ) print("FFELT"); test( ffgen(2^3) ) test( ffgen(3^3) ) test( ffgen((2^64+13)^2) ) print("INTMOD");test( Mod(1,3) ) print("POLMOD");test( Mod(x,x^2+1) ) print("QFB");test( Qfb(1,2,3) ) print("QUAD"); test( quadgen(-4) ) P=idealprimedec(NF,2)[1]; print("PRID"); test(P) print("MODPR"); test(nfmodprinit(NF,P)) A=idealpow(NF,P,2); print("BID"); test(idealstar(NF,A,2)) print("BID (nogen)"); test(idealstar(NF,idealpow(NF,A,1))) pari-2.7.5/src/test/in/valuation0000644000175000017500000000100212405547147015211 0ustar billbilldefault(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() ) } valuation(0,1) valuation(0,-1) valuation(0,0) \\ #1319 s=Mod(1,3)*(1+x); valuation((s+O(x^2)) - s,x) \\ #1336 1./(x+1)+O(x^2) \\ #1345 valuation(0*x,3) == oo 1+O(x)-1 pari-2.7.5/src/test/in/dirmul0000644000175000017500000000026112366172547014515 0ustar billbilldirmul([0,1],[0,1]) dirdiv([0,1,1,1,1],[1]) 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]) pari-2.7.5/src/test/in/deriv0000644000175000017500000000102512366172547014331 0ustar billbilldefault(realprecision,38); sin'(4) derivnum(x=4,sin(x)) derivnum(x=t^2+O(t^4),sin(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, my(u=v[i]); print(deriv(u,'x)); print(u'); print(deriv(u,'y)); iferr(print(intformal(u,'x)),E,print(E)); iferr(print(intformal(u,'y)),E,print(E)); ) } intformal(1-A,Y) a=intformal(Pol(0,x), y) b=intformal(Pol(0,y), x) variable(a) variable(b) a=intformal(O(x), y) b=intformal(O(y), x) variable(a) variable(b) pari-2.7.5/src/test/in/pol0000644000175000017500000000120712516207625014005 0ustar billbillo = [Mod(0,3),y,1/y, (y^2+1)/y, [1,2,3], Vecsmall([1,2,0]), Qfb(1,2,4), Qfb(1,2,-4), y+2*y^2+O(y^4)]; { for (i=1,#o, my (v = o[i]); printsep(" ", Pol(v,y), Pol(v,x), Polrev(v)); printsep(" ", Ser(v,y), Ser(v,x), Ser(v,,5)); ) } o = [2*x+3*y, 2+x+y+O(x^2), 2+x+y+O(y^2)]; { for (i=1,#o, my (v = o[i]); printsep(" ",pollead(v), pollead(v,x), pollead(v,y)) ) } polgraeffe(x^2+x+1) polgraeffe(x^3+x+1) polsym(2*x^4+1,4) norm(I*x+1) trace(I*x+1) matcompanion(2*x^2+1) Pol("") \\#1651 f1=(x-1)/(x*x-x); type(subst(1/f1,x,1)) \\#1690 default(realprecision,38); P(x,y)=(x+1)*y^2+(x^2-x+1)*y+(x^2+x); polroots(P(exp(I*Pi),y)) pari-2.7.5/src/test/in/bnfisintnorm0000644000175000017500000000064512314242551015721 0ustar billbilldo(i)= { my(t = bnfisintnorm(bnf,i)); for (k=1,#t, if (nfeltnorm(bnf,t[k])!=i, error([i,k]))); if (#t, print(i,":",#t)); } default(realprecision,38); \e setrand(1); bnf=bnfinit(x^2+105); for(i=1,1000, do(i)) setrand(1); bnf=bnfinit(x^2-65); for(i=1,1000, do(i-500)) setrand(1); bnf=bnfinit(x^5-37); for(i=1,1000, do(i-500)) /* regression tests: */ bnfisintnorm(bnfinit(x^3+5), 5) bnfisintnorm(bnfinit('y^2+93),54647) pari-2.7.5/src/test/in/multivar-mul0000644000175000017500000000077212366172547015666 0ustar billbill/* Multivariable Laurent polynomial bug finding */ /* 05 Jul 2007 Michael Somos */ x;y;z; pol(N, v)= { my(t = vector(N+1)); t[N+1] = 1; for (i=1,#v, my(n = v[i]); if (n < 1, t[1] = 1 , t[(n-1) \ 2 + 1] = if (n%2,1/y,1/z))); Polrev(t); } /* Attempt to multiply two polynomials in x */ f(N,M,v,w)= iferr(pol(N,v)*pol(M,w); 0, E, 1); {doit(N,M)= forvec(v=[[0,2*N],[0,2*N],[0,2*N]], forvec(w=[[0,2*M],[0,2*M]], if(f(N,M,v,w), print([N,M],v,w)),2),2); } doit(9,9); pari-2.7.5/src/test/in/cyclo0000644000175000017500000000154212366172547014335 0ustar billbillallocatemem(8000000); poliscyclo(1) poliscyclo(x^0) poliscyclo(x) for (i=1,100, if (poliscyclo(polcyclo(i)) != i, error(i))) for (i=1,100, if (!poliscycloprod(x^i-1), error(i))) poliscyclo(polcyclo(10^5)) poliscyclo(polcyclo(12345)) { for (i=1,10, f = polcyclo(i); for(j=i+1,10, g = f*polcyclo(j); if (poliscyclo(g), error("is ", [i,j])); if (!poliscycloprod(g), error("prod ", [i,j])); print (polcyclofactors(g)) ) ); } poliscycloprod((x-1)^2) poliscycloprod((x+1)^2*(x-1)) test(n,t)= if (polcyclo(n,t) != subst(polcyclo(n),x,t), error([n,t])); test(5,1);test(5,-1); test(10,1);test(10,-1); test(40,1);test(40,-1); test(2,-1); test(10,-1); test(11,-1); test(5,Mod(-1,3)) \\ roots of 1 test(20, I) test(10, Mod(3,11)) test(10, 2 + O(11)) test(30, -1.0) z15 = Mod(t,polcyclo(15,t)); test(15, z15) test(30, z15) test(105, z15) pari-2.7.5/src/test/in/contfrac0000644000175000017500000000050612413013143014775 0ustar billbillcontfrac(1,[],-1) contfracpnqn(Vecsmall([])) contfracpnqn([]) contfracpnqn([],0) contfracpnqn([],1) contfracpnqn([2]) contfracpnqn([2],0) contfracpnqn([2],1) v=[1,2,3]; contfracpnqn(v) contfracpnqn(v,0) contfracpnqn(v,1) contfracpnqn(v,2) v=[1,2,3;4,5,6]; contfracpnqn(v) contfracpnqn(v,0) contfracpnqn(v,1) contfracpnqn(v,2) pari-2.7.5/src/test/in/real0000644000175000017500000000007112405547147014137 0ustar billbill\\ #1322 default(realprecision,19) 1. << 2^60 1. >> 2^60 pari-2.7.5/src/test/in/galpol0000644000175000017500000000102312366172547014474 0ustar billbill\\ package: galpol galoisgetpol(8) for(i=1,5,print(galoisgetpol(8,i))) for(i=1,5,print(galoisgetpol(8,i,2))) galoisgetpol(8,6) galoisgetpol(3,1,3) galoisgetpol(3,1,2) test(n,k)= if(galoisidentify(galoisinit(galoisgetpol(n,k)[1])) != [n,k], error([n,k])); test(8,3) test(18,5) test(27,3) test(45,2) test(30,4) test(32,4) test(32,13) test(32,30) test(32,32) test(42,2) test(48,12) test(64,3) test(64,14) test(64,16) test(64,48) test(64,51) test(64,70) test(64,68) test(64,80) test(64,44) galoisidentify(galoisinit(polcyclo(390))) pari-2.7.5/src/test/in/ellanal0000644000175000017500000000065212405547147014631 0ustar billbilldefault(realprecision,38); rk(x)=x=ellinit(x);ellanalyticrank(x); rk([0, -1, 1, -10, -20]) rk([0, 0, 1, -1, 0]) rk([0, 1, 1, -2, 0]) rk([0, 0, 1, -7, 6]) rk([-5187, 176830]) he(x)=x=ellinit(x);ellheegner(x); he([1, 1, 0, -1297, -18530]) he([0, -1, 1, -33, 93]) 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) pari-2.7.5/src/test/in/modfun0000644000175000017500000000023412415474356014507 0ustar billbilldefault(realprecision,38) eta(2+O(2^20)) eta(x+x^2+x^3+x^4+O(x^5)) eta(I) 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) pari-2.7.5/src/test/in/log0000644000175000017500000000012312366172547013777 0ustar billbilldefault(realprecision,38); log(1+10^-30) lngamma(1+10^-30) iferr(log(2+O(33)),E,E) pari-2.7.5/src/test/in/content0000644000175000017500000000037312366172547014677 0ustar billbilldefault(realprecision,38); o=[2,1.0,Mod(1,3),2/3,ffgen(2^3),1/2+I/3,O(2^-3),quadgen(5),Mod(x/2,x^2),2*x,2/x, Qfb(1,2,4),Qfb(-1,2,4),[2,3/4], [1,2;3/2,4]]; test(f)= [ print(iferr(f(p),E,E)) | p<-o ]; test(denominator); test(numerator); test(content); pari-2.7.5/src/test/in/for0000644000175000017500000000021412366172547014005 0ustar billbillN = 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)) pari-2.7.5/src/test/in/iterator0000644000175000017500000000025212314242551015034 0ustar billbillforcomposite(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) pari-2.7.5/src/test/in/help0000644000175000017500000000034312366172547014152 0ustar billbillf()=1; ?x ?sin ?f ?echo ?default(echo) ?default(log) alias(new,sin) ?new addhelp(x,"test1") addhelp(sin,"test2") addhelp(f,"test3") addhelp(echo,"test4") addhelp(new,"test5") ?x ?sin ?f ?echo ?new ?does_not_exist ? ?. ?\ ?1 \t pari-2.7.5/src/test/in/bern0000644000175000017500000000022212366172547014144 0ustar billbillbernfrac(0); bernfrac(1); for(k = 1, 20, print(bernfrac(k))); for(k = 0, 5, print(bernpol(k))); bernfrac(-1) bernreal(-1) bernpol(-1) bernvec(30) pari-2.7.5/src/test/in/factor0000644000175000017500000000133112413013143014451 0ustar billbilldefault(realprecision,38); factor(x^2+I) factor(x^2-1.) factor(x^2+I+1.) factor(x^2+Mod(1,5)) factor(x^2+Mod(1,3)+I) factor(x^2+Mod(1,5)*I) factor(x^2+(1+O(5))*I) factor(x^2+(1+O(3))+I) factor(x^2+(1+O(5))) factor(x^2+quadgen(-3)) factor(x^2+quadgen(-3)*Mod(1,3)) factor(x^2+quadgen(-3)*Mod(1,5)) factor(x^2+quadgen(-3)*(1+O(5))) factor(x^2+quadgen(-3)*(1+O(3))) factor(x^2+Mod(y,y^2+1)) factor(x^2+Mod(y*Mod(1,3),y^2+1)) factor(x^2+Mod(y*Mod(1,5),y^2+1)) factor(x^2+Mod(y*(1+O(3)),y^2+1)) factor(5/2 + I/3) factor(5^4 + 5^4*I) factor(5 + I) factor(15+3*I) factor(4+4*I) factor((3+4*I)/25) q=31271192761826143388782348951/31274945109847936339856761591; factor(q,2) factor(q,500100) factor((x-2.)*(x^2+1)) factor((x+1)^2/(x^2-4)) pari-2.7.5/src/test/in/nfhilbert0000644000175000017500000000301312413013143015147 0ustar billbillnf=nfinit(y^3-1009); P = primes(20); pr = idealprimedec(nf,1009)[1]; a = y^11*(y+1)*101; b = y^5*(y+3)*19; vector(#P, i, nfhilbert(nf, a, P[i]*b, pr)) pr = idealprimedec(nf,19)[1]; a = 19^11*(y+1)*101; b = 19^5*(y+3)*19; vector(#P, i, nfhilbert(nf, a, (1+P[i]*y)*b, pr)) /* old regression cases: */ nf=nfinit(y^2+1); pr=idealprimedec(nf,2)[1]; nfhilbert(nf, [1,1]~, 3, pr) nfhilbert(nf, Mod(0,3), 3, pr) nfhilbert(nf, 3, 0., pr) nfhilbert(nf,[1,-2]~,[1,-2]~, pr) nf=nfinit(y^2+3); nfhilbert(nf,[3,0]~,[3,0]~,idealprimedec(nf,2)[1]) \\ #1147 K = nfinit(x^5-23); p = idealprimedec(K, 2)[1]; nfhilbert(K,x,-x^2-5*x,p) K = nfinit(x^8 + 2*x^7 + 3*x^6 + 3*x^4 + 3*x^2 + 2*x + 3); p = idealprimedec(K, 2)[1]; { for (j = 1,10, setrand(j); a = vectorv(8,i,random(7)); b = vectorv(8,i,random(7)); c = vectorv(8,i,random(7)); d = nfeltmul(K,b,c); if (nfhilbert(K, a,b,p) * nfhilbert(K, a,c,p) != nfhilbert(K, a,d,p), error([a,b,c])) ) } L = [2, 3, 1.0, Mod(1,2), Mod(1,4), Mod(1,8), Mod(1,3), Mod(0,5), 1 + O(2^2), 1 + O(2^3), 1 + O(5)]; for (i=1,#L, for(j=i+1,#L, print([i,j], ": ", iferr(hilbert(L[i],L[j]), E, E)))) print("p = 0:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 0), E, E))) print("p = 2:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 2), E, E))) print("p = 5:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 5), E, E))) \\#1251 hilbert(-1,-1,0) \\#1261 K=nfinit(y^2+5); P=idealprimedec(K,2)[1]; nfhilbert(K,2*y,2,P) \\#1569 K=nfinit(x^3-4*x+2); nfhilbert(K,2,-2, idealprimedec(K,2)[1]) pari-2.7.5/src/test/in/round40000644000175000017500000023553212573107135014436 0ustar billbillallocatemem(10 * 10^6) { v = [ [1,0,-363,0,53550,0,-4091823,0,170172414,0,-3663509067,0,33703350345,0,-63300912912,0,32451860736], [1,-6,18,-30,42,-174,738,-2514,6885,-14348,21720,-29856,48284,-47064,-27768,139824,-135588,56256,78464,-60528,18864,47296,73728,-109056,80656], [1,2,3,-3,122,-1], [1,1,-2,-26,39,-1], [1,0,3888,-12], [1,0,-12,-84,-196,2856,6328,-42336,-64820,352464,298928,-1776096,-262416,5458656,-1875872,-6688416,7866576], [1,0,57,0,1197,0,13681,0,136854,0,1048044,0,4603892,0,11460015,0,16001100,0,11131014,0,2739339,0,-368793,0,-7569], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16], [1,0,-432,0,68688,0,-4717440,0,112637304,0,409406400,0,2774305728,0,4041156096,0,11224978704], [1,0,160,0,11216,0,455360,0,11928052,0,212540000,0,2645190320,0,23223642560,0,143402547926,0,613283590880,0,1764753386480,0,3275906117440,0,3788371498452,0,2940754348320,0,1769278869776,0,73445288000,0,87782430961], [1,0,0,0,-42,0,560,0,-1645,0,2352,0,10290,0,10192,0,3969], [1,0,0,0,576], [1,-43,624,-3816,11173,-15800,9408,-1152,-256], [1,-28,141,0,-887,336,1436], [1,-171,3222,1079,-25200,-9024,34304], [1,-124,1109,-2208,-1504,2048,256], [1,-347283,25076856,-419348507,1408022154,-1607716596,540519736], [1,-130544,2518160,-15612096,27910496,42272512,-146951936,78195712,1806592], [1,-219,2951,-12762,6701,80815,-139748,-128864,354688,42752,-263168], [1,-20819,4970290,-185332015,974972214,1853069313,-4527488547,-3894160116,4476129404], [1,-155,2836,-14379,14428,13117,-9421], [1,-262286,3014265745,-8638841144522,-7230469691722,19997484886500,5356591151857], [1,-599,17808,-98580,-253979,537680,1226232,464832,18896], [1,-29999376,561121360,-119997504,-4488970656,479990016,8977941760,1919960064,256], [1,-25283692,99985153436,-3431807998368,5805487078640,46121794880,-628204481984], [1,-271,14191,-320438,3790080,-25112800,92495160,-167147800,50530009,301971239,-450938136,211398894,-16216756,-8116135,1041461], [1,-16555440,793241872,-6812040640,18249197408,-12596399360,-9598940928,7536655360,2589634816], [1,-3335,1068872,-29372236,170603861,-25778864,-465050888,178972480,-13193008], [1,-511,60996,-2085405,31489262,-239889832,934179225,-1604993848,-72959248,4517839616,-6762846464,4114843648,-916779008], [1,-295,3558,-5031,-24914,17697,28397], [1,-20167,13515214,-589415581,409276760,689575296,-490712576], [1,-1423,112198,-2946382,25666342,-2017279,-128707766,38702420,141457873], [1,-13921853102206569014202396016,13823607745009668573058211237056109158822,-82639509138390410981775119083025418818311274199568,7191389922579887711216370122117810510341770052031768545,-6403782491712680689180662417515214438745217916122612992,-16491332368693741394107994410424645158974225360655824008,12504550730163409756349966122713154452136883600552704256,-700835788721071887889404301240818143183667934525633904], [1,-2265,351933,-10876260,113882619,-320899050,-624685627,2393614800,1152858000,-3523888640,-151501056,1315123200,-232738816], [1,-711,98421,-3240421,25070664,-58439271,31703851,28789266,-19416303], [1,-506,49087,-1669640,17231279,47336349,-144695555,-359331616,176538278,650890177,224030107], [1,-189958896599609331973768440700,687813619771577743504399928302877897734798,-860743693595930793317020644139268141132387039380,2604128524727083170656936316847150343534889684322129,280304933578645057171094798274221018642041201687880,-8574385501054918331765273413936458875072943056877128,-479436876642637253489428928646435311733187408834720,6755064609347154305550891307820436374837227182458896], [1,-4690816,910531264,-11915116288,18021615232,54853406720,-82373120000,-64180142080,54969143296], [1,-6649860,1576752264,-22267257600,-85164579264,-77640519936,-18089594368], [1,-33050180802,1659048077186129481,-272574365342594573834910,11095950373591662695013161508,58710086095790534948543753694,105952057692427053452669684769,70434206621571881660299570170,9218882946199589918384363001], [1,-329544091788,469019476748118,-61449507761159844,363555883847040681,-209190672257869480,-1016729503227038920,1359941005734916512,-457890480465748336], [1,-1150160,1331537926,-601897862304,133574881579623,-15016280356014512,791282768405768068,-14453225350510767424,3154149235832315999,242466621761228454864,224495153622717846854,-670291322259768317344,-916062740958336644647,48963442301119929008,327298375561074497040,32908217054793357184,-23393721242771438528], [1,-2851,158608,-1924400,1243901,34900240,22503032,-108662912,-119975344], [1,-11111186112955398247507018336,243445863707559988779970226428228863828166,-414424563629922001757819169028157495238172960,1123139273032476660541621993600473674277033409,498129315610741879775567628417300033144884288,-2159960274391288199445420339203867726147763080,161278633821087460912298650651190604277783808,333627755901815676223362327425185259040194704], [1,-14504420704,1182354951470244,-23480009042438862560,27882235470885485836070,-9087586203362364155630944,599651930510874648548788156,-3678137244259701713858840096,7016885534906558207253820945,1533248468172570268668346560,-20993688867208520156247602216,24208677107524343574382863104,-8499807937568973364674358384], [1,-2913,1474630,-174340074,5392477240,-26251520300,-34286734387,209569240200,193605730560,-244321588224,-184759603200,14498496512,10333454336], [1,-2181,137643,-694573,1252707,-898221,209611], [1,-973,167753,-3919581,16265742,49310580,-279670537,-250608765,1769132170,725790142,-5312558309,-1392312472,7380239894,1386140637,-3489374699], [1,-1212,22194,-55328,-30951,115500,-2908], [1,-4773835280837163132310630467298960,9870109995525906834183518595974886029184804344444758,-1782775404778879896945364961485617187018000556874876449394160,89883389132977359805126346146881786926610135522042323723472323569,72714593243136238897319878334430413252438964969406750065955662080,-321968360190732413575930663497507427814725029860845628527928503688,-312452766852442968760965441219058671845140150026306340120175130880,41087519521030021203246250696563962180882228355460884053944990096], [1,-49896695,527277779708,-120568048624615,452535974730544,1625411298707505,-1448067181855113,-2752052546805840,2221923470234796], [1,-1046,20228,-68392,-265619,904512,1991640,-2358154,-6146747,-2463528,407228], [1,-549625252,1238278325058,-15329043153964,28925414899409,130312025889136,-32291232291184,-108323448091520,-24340205012416], [1,-2949,16059,10208,-83400,-25584,78256], [1,-3640278,2282599369,-18694808796,-4328145452,125291204160,-18186492672,-205081362432,13073301504], [1,-3152,285561,-9564226,152595945,-1188640275,3575524815,4816808889,-47197026465,33049819979,215848146317,-258582345090,-504831954170,649899122769,650345190624,-691225563843,-408430121580,242381088477,57377645757], [1,-15395,20249992,-239327620,273434573,856975880,-760838848,-750006400,143449856], [1,-2003677328,3012846911824,-25136484060736,32567282104928,90286574332160,-166925807110912,-30270493268992,97725572006144], [1,-61640944,166625534272,-3562612049536,15797138088064,236548072448,-60906347638784,18108824379392,56198906318848], [1,-21383884,35000497050,-11829222158080,237367247198299,-217929167425584,-553512315641022,292541289325812,110433041508969], [1,-23869184,4853367907,-14052765056,-26838500008,56069168640,30654626608], [1,-225138,52033917,-248800311,97200810,921552876,-1066931352], [1,-88696708256,4437008017160880,-23039907832217560704,26485741273275758734176,42379932318953038254592,-58866917909043924655360,-68089115862472243066880,20476771544555918463232], [1,-421636160003888,1902246275640252720,-166497940584948453440,3590656805496104164192,-18533569942452269505792,40219147880321276111616,-39862736608896158137344,14916521497035956080896], [1,-3320,224698,-424748,-1157911,905628,951268], [1,-64961,187497640,-8356326784,-15832630267,65698325576,143412228032,-26731714048,-127433961472], [1,-232394051587274973485503996066296,4038758106150313180814013396186630354012,-18284722485505087322089714887666913243539528,93595182799438815963839033321760695064344070,209067053454541747659819712614587487150583608,-588680842304077969068594235539671561808141348,-538836714977811176095248603569636252559381624,867715345720344138137761716498628626987199041], [1,-53655,319168490,-186349285325,21120443415975,-686099144383750,4735314251803625,2204357656605000,-26162347980297500,12824037220300000,33965267757150000,-36652423750000000,9889099639000000], [1,-125472786714116,674561716001370442,-230527140127968669608,8169775848285148195,1888371575828384127208,1007346199547631496042,-3767048153290292678684,-3343242731361766639199], [1,-34088504,1506866218,-1104149192,-12689882023,4007782176,25448506156], [1,-243443804696372,2923285683273533645014,-103724188690208930700257484,219554589005762032602647336897,-27447284989915966720818474455448,820411316616154701751838916778832,2735010684783093171601973097236320,1536067156806457414066577673199968,-1646791109769306193071759068458624,-1348134788310032629244426609918208,-193806232242166413772905190324736,-7677311000369732927493903060736], [1,-5331,3275258,-663977892,41259312682,9981725432,-375222796900,-231422557815,575556116832,210741891801,-134691222781], [1,-5138,96044,-353472,-420203,3742600,-2116288,-11951190,13094613,11859720,-16211204], [1,-532733417840,4744177349160832,-8413021486831026176,22311336993776500736,-7638962491965308928,-7352121709731774464], [1,-7637967984048,3386340581184784,-42324961034160576,122919529892620128,-58964720593317120,-192640220764305152,245607942083017728,-76666118683840256], [1,-2006,1008774,-17353883,-7844872,51013821,14640013], [1,-12474419222154,2431008594310441359,-6912314557744523417164,33605190900312985781583,-52569003547113031969674,25970935931836648827073], [1,-161443012754157099829832920,10138436074617165816404765780234617807802044,-20060069047647004218617188450114148708733068200,660050897576330492829543886032989254940435324134,-974098875961622456132597564420652229994235789160,-2264260286588310696319122780977992700907740060420,4240004472781140599100651710696566992990808375400,-1414274241286414395747708743194177178965032607775], [1,-1553722352,901513660416,-152989098177664,6553256584676096,-109901782972756992,685652288206471168,-43714124749955072,-9422339586035687424,8817974156500074496,44807770136073207808,-45324909008823779328,-87566115761309089792,86042657488023584768,51374273094909689856,-59775177056420102144,12687790985866903552], [1,-165086,69953110,-9018434345,392237516455,-5982463478261,18025737017474,55747520697647,-168806685673984,-244753603799872,393573790098944,502650387525632,-215239123238912,-336114163122176,-57002141155328], [1,-93823428592,34799861952304,-443389708735808,779896340053856,1393944632569600,-1484337524757760,-2345449331993600,-694036275654400], [1,-61061,2315481,-35028903,275610780,-1232308077,3218060943,-4849095216,3959990439,-1499118593,179027083], [1,-5695,92812,-488095,780736,805481,-2779721,525584,1541164], [1,-8235528536,78777096091648,-14962965975823424,752649877179796160,-12880180969335749632,38155186289451728896,469400924480987815936,702074460321333391360,-715079303427341254656,-2125387453139301433344,-1140826580450709602304,-3849685126809911296], [1,-5406403952479432,6865958511876428164654,-71567316451693131796818392,1752342108645328326901864169,-5653754613528818355093017840,2811073291210554121492866968,7423802461456459480849518400,-6565509149627058490734170224], [1,-151343,1368301504,-21253251016,26539419173,96661676120,-105696181312,-91329016192,40152391424], [1,-807505248612,37556725718396046,-265013994507552057420,318993321672688235401233,978883284203583405618744,4557622950652832660664,-2130952270988696435076960,-1494408400545790896087024], [1,-9448903436,104730633623688,-53760865135709952,4832151934763017856,-84739601628184897024,-42812862492100717568,184460624879942123520,71427552535240871936,-98041653705232138240,-30794067428621123584], [1,-79582678925,8620909385125051,-236507758358268974098,174874878867315968757470,-18058520227439698846912507,645254756102974107764676912,-7870697647323874283979696891,11521347153009947384786791458,34576202721355388442595149476,-70344554343965963219721213592,-10740194212304372050166074384,62770663206984074836346600032,-16345615646987859185051367488,569708459683633657748324224], [1,-456523770,8737152129501,-982742700549550,27196974696122506,-267044865205988930,534419840754543701,3738689503783264990,-4543932463986286454,-15278585690067252590,8496454288061882845,19353624370456339750,-1008847637476820975], [1,-34856,3760018,-13969928,-5409343,51565824,-37781504], [1,-301640751830458520553597141376,328952494035105106001631823186510670131969344412,-133358741515025683238080442729603137995456051732608,1955525927172552794216114449002457559485718278748870,9397121011646773996373023708967458825619733367758208,13257860889783058889903253607299903955098315590042012,6433754692163674744311497881625324357727770698216576,492667067892517490964245788797821843444034967148801], [1,-512577532102040,43768111570354384,-683727333405049120,2702203304894313824,-3908326472950549120,1831103370543136000,-49811703475904000,-49563059750240000], [1,-4442,2971547,-533338420,2818485691,606965289,-20799684871,16060220236,40016291866,-40620996767,-6838744349], [1,-1661445000,648950992194,-9056465203448,-52361475864447,-82213976895840,-37808675256052], [1,-3549,1055643,2390843,-2763021,-10087077,-6219557], [1,-523628898243604618995885416807147298909363801451789372900,367600369666309006452842123621050246321452143630580273014679831593578783458649152654286,-3343275983768744237278154637602147245967274497790433362036635892377724426950499872902658229340,1832082009549845619949867091376004679654159119363411909937509445666660442613413884422767828119857,7972083317253398926405060410933145316118484573008126052905764693835293798003418767254772929076840,11794511604384984730506391635816484705277974441262698427609855343001177151538798564737754260305528,6870707586084866428566813547262155529526409904008120571289108710304360279945306394092746374847840,1364739780535919594206700656372505401403107870453922666372253727638308252150474474123624152944400], [1,-223216,303477256,-17417922005,277522832382,-594271046752,-5464816647875,5815492998512,37144434715472,-2497746038784,-79766894614784,-25810480361472,32744553869312], [1,-7391,100628,-303943,-80708,1274729,-1168709], [1,-11102485161464,638119123854694146704,-1090684976797347138361401856,5790691092346201260104535212544,-2905557524355781158067995198312448,-1740704435184319464552349984251904,8456003228780781810129632899235840,611694445981518923832996667392000,-1827580422204898657895630230781952,296569960368897491493657596919808], [1,-382595410,10131435161569707,-339358625351926857460,1944397043581582983327025,-377576456004292682578424730,18893558349780213971828050325,-114503495274862313003240421015,-941511767079645429966258595415,170925446090929041685072722405,7547994422752820490440513334577,4952842395416051576334911693070,-20605333735289498909471577909366,-17080193694570124063317347368550,22769567946872826808692277299420,13826681275125601697987763384700,-10810372895085097433637727654775], [1,-317966635855342617399169385408829217452748440,13678545113125269147071264087266524532070024308404763646867605208904755730954,-15684278338411526690829309518564793208753920587856759367478501240440935756809346120,612415923065287098473685281157727791918451722108963506485602685360057577081310228969,537814306804262126760386283977264831761888559875268935565912225023248124597985989680,-1990656139061697921305239415958192303820860550542494738202435034180069987344650996640,-2055469177845059349200042772439815497299423127890291811872672651394061790113952185600,-318082857370566991270588466777928875794349614537780585539495916100466479816098809600], [1,-416659279474111237,330377843894082003274229160,-62905768010062743987970346108852670,16821570317735641478410538460455385145365,-1198558791812587254354860392504583675770158336,18870041073230571748664972200517215466193250634297,-3110266503818994429391891213184926395344435891196215,46333969996580915198177746519714350753415778619811755,-71051745585560409536489422446312023987208684949679585,-171670385086621478643416705514305417043725434872977218,353998192629745372651831816938706517212108845354144981,38406503908964266753393497382125776817470966499185790,-335208974242087685397896701245395328967475262796476705,183830028342252095617620250485464751517776308230766835,-28324287359035373403013837385189183497723403582130478,-370669783454900697332687258050823467831694680481879], [1,-2942,425807,-21480253,510509165,-6192552408,36292590688,-53610411500,-425058743459,1751257692002,873280257113,-13398050061528,6817766400536,51340604838743,-41334969659574,-115572213676468,88181505312905,157994239939799,-76512548098590,-116800296271737,13943948986543,27978407467337,1658082397889], [1,-235975492672,591805571783776,-382200656154472448,73171728402630615744,-2825821907089361173504,22281146497688453411328,32388399560710497509376,-589295596207800671283712,-475154989792559233744896,5936410136560770774966272,9110311309239759390113792,-15457901130275180849086464,-36773863935231836576546816,-392960681613067998593024,38539327581294094379384832,21102849638169519181594624], [1,-22,135,-317,90,941,-1851,1519,-580,83], [1,-480,13575,-57397,-15045,155166,-22856,-113661,22119,20089], [1,-5349,69225,30959,-693771,-198237,1904389,513114,-1472148,-541304], [1,-45,339,-792,-186,2907,-2911,-765,2280,-829], [1,-1999,44014,-243753,270704,621536,-1193984,115712,409600,32768], [1,-2154,83832,-98620,-727088,628528,1715120,-1208288,-1009216,688192], [1,-84,180,796,-1713,-2337,5216,1461,-5232,1819], [1,-28714,389720,-442556,-3374000,506160,5449392,774688,-540736,3136], [1,-131061,64254945,-433211377,-295697859,2231628243,196751629,-2475058518,468570444,325387336], [1,-43228917,3217754381,-36758007254,-59567284560,289702061749,332943277127,-581210582241,-584264535430,52410165263], [1,-31323,7353216,-107319715,116275089,383163324,-599105591,-198697686,666629724,-267848648], [1,-170,447,951,-2186,-2265,2785,2117,-798,-433], [1,-97,920,-2507,191,7795,-7979,-2434,5592,-1609], [1,-25601,4735751,-157811795,73527676,713816792,-217322176,-919714240,50378496,268434944], [1,-404,4704,3918,-92546,-153360,222561,511962,102988,-113801], [1,-431,5515,-29560,84442,-134947,110307,-22471,-27036,14251], [1,-129254964843,35178418165170,-223350030592755,251360581683972,960227812394016,-2217902130474495,-80657197605174,3263837746063692,-2051179019383688], [1,-10430037,3613650129,-255462258585,649253166885,405120779307,-2141143390203,901824939450,1197088044012,-731164579192], [1,-50244,30294557,-672636955,-5671628428,-15674959992,-18431496640,-7309777088,1356664064,746926592], [1,-339,4344,10623,-36633,-85575,53843,193416,92484,2087], [1,-31428,5168421,-69645814,-94901634,121411929,57346600,-76184430,18720885,-1242287], [1,-1322,9117,-14806,-25436,87546,-32311,-75542,33116,26104], [1,-189471444,37709676681,-165918005985,34691048736,558925368933,-498161898711,-154612190805,146945330826,-21509240369], [1,-2147,464267,-6245532,12094236,28528805,-87534615,6524347,127671918,-83816513], [1,-2783342,8025984,23658900,-59547440,-78387408,138067248,117240288,-97770944,-60103616], [1,-1255489,64926593,-338839895,426458329,692772093,-1921085372,734227214,1055601045,-717464063], [1,-36319094,630812278698,-1655815071045331,-6028129014962075,246012746225435,22671225935869189,25087340269832470,2776221409366657,-4230997679557999], [1,-873711251373,753411928367685,-13806936287537310,-111661195235268408,-270166294338135339,-191717097502403145,179751315005491911,323631491466547362,124064847445413967], [1,-14849018,494063251800,-710653227516,-3713349421616,4822039295664,4687257735600,-9757306885344,4980576448960,-802641509312], [1,-33175596,143698989,797637285,-324064356,-3785215656,-2493975360,2377896000,1441632000,-683840000], [1,-1929,14472,20253,-156633,-129093,449669,289806,-258072,24407], [1,-614748,2204740,20504164,7285904,-146034016,-334984464,-302768000,-123461056,-18857792], [1,-3029,22091,-40644,-47982,203135,-80355,-209549,146292,22027], [1,-3981,1369677,-17835518,-21602640,14896077,19095023,-1882569,-3453006,-58337], [1,-56691,2221227,-15141714,16322598,55966149,-107613132,13226364,54559296,-19694537], [1,-14521960,647012999,-4984218590,-36502752545,-43863546837,79899788485,212682283274,154229646540,36019185544], [1,-158662082,2623228504,-11293514652,2847667984,61874154160,-78720960080,-54521566560,105714608064,-17136358336], [1,-196587,3209851035,-169981929492,1004435496252,-2429211599883,2941338597321,-1853910108045,570724116606,-66727824497], [1,-911,5074,-2190,-29204,37810,39031,-64347,-13824,25019], [1,-7845,71310,-122285,-330972,945684,133568,-1565232,369216,616384], [1,-145515609,153019764729,-3709746066522,1393445404674,19486365429555,-8829957473691,-23095161469062,11557736900892,833570519624], [1,-1279836,7972421733,-33976650387,-87081745548,139649755464,254306919488,-38030593728,-154168849152,-46733991424], [1,-1983,670992,-4138497,3171843,9255633,-5546089,-7199220,876864,930959], [1,-22338,412581,-1979142,682380,7847946,-7588855,-3039222,2196060,626552], [1,-22113768108,3796190022029887441,-60498021996410510930523,-71963443045623180847600,487699550239607072040156,523305125593515644446032,-1131228403974427035526864,-946796045857905092061056,584092504774559261558848], [1,-16954592,118348117057,-461615145371,-96594517766,2084887420818,-1349388002526,-2335232607204,2081484755957,104568589897], [1,-10489,2707211,-104488860,245611206,380234947,-1177729795,106009611,667160224,62376107], [1,-45837,369335901,-31624086134,-169410056472,-164382128003,465586425823,980522077951,392287249570,-132604621897], [1,-463038,45146493216,-1001353353260,-1082922317616,5505441329328,3829125921584,-6282318595872,-885395763648,497609171008], [1,-841,13536,9553,-157013,-163985,275717,183350,-197524,13031], [1,-15461,715359,-5328764,15402786,-16694517,-5169563,23976863,-13678964,443227], [1,-862775,10856170258,-3134053418062,-1375422646243,19989421509103,3876108599660,-31488084661671,5161577814899,4115642633441], [1,-50213409,41604993225,-1178945921599,1767674719401,4428816426693,-5499446500460,-5981060846562,3930075321357,2711088130897], [1,-14509669203,854596766777094810,-7066981747963431235083291,46268306243972593019173548,-119361738755744810792850960,153452578934040181394048337,-101367063741886754383215702,31015690796531163812304780,-2923893082958254149947912], [1,-734,33756,-127241,-72904,584650,-73590,-605936,-25506,23491], [1,-73853860518,13777317132366702,-115071949708121348242,160844716195874633181,682814078330976048036,-833639776266212564111,-943177567400978615382,831764080222499743356,66392226304335963256], [1,-694758725855,106254756427419398,-3784025583829693170297,-13131948767566391974232,-12527679077150368308464,-1542996140822612863744,1578487928494511479040,-80007592280225568768,597456985245478912], [1,-17515,10964993,-247423288,310805648,1085556229,-1447110681,-631704583,509927518,170424799], [1,-8336,239429,-1115012,1550830,675992,-3307903,2496650,-569892,13592], [1,-5629442086276204273505,386546651233719446359200330993497888059691,-72838371990626194759378155526759022817640816485447,-68944817078273525878833279122529093499192548461768,532698119339953491504511496245901043962109891591692,399760666506683453127871057655514820189115908767536,-1251030146293132816263700188101197788442427262158608,-574105270447410879019496275688738988931548783376384,933502079102512278754584352311502694379008136095296], [1,-89444164815,3805216350344442726,-19525076579766367621887201,10677494665576920234465120,172915220543339268243570816,-75371913447675512226165760,-481724974617695286501519360,133078578075456026880442368,404416685885850617500663808], [1,-5017340872,54242041495381,-5530836376965691,-11636668895078592,11075773964676508,38232904505954064,23198971246434608,2517662503984512,53606420009024], [1,-39793,797843,-4481430,9023194,-3106271,-9102293,6350523,2351580,-1467437], [1,-34677,757365,-2384830,-8575564,7310693,25880563,2552523,-19252762,-8564513], [1,-958954166,5186058440675,-5517238669966482,15054662708038354,6305516444274500,-46821935177109565,37215625652899170,-4390922315873148,-2421624954194536], [1,-6299100,13352120109,-51758626611,-417163766490,-393905254122,823253994102,1291197091500,235580470281,-131269473631], [1,-68277338,5340670808,-96736086908,-116282155376,520304803568,350815905584,-710962872544,-144532807488,203482129472], [1,-1001,222000,-9506853,78349585,-284295243,538163385,-539633442,256936366,-38830541], [1,-38919,34177467,-59964732,-1118422710,-2838483267,-2244178117,692405229,1753197504,630872507], [1,-17126633628,18516619842741,-5017128507606003,8455548998534724,25861081463217288,-49455246822756288,-20953146111899328,72565428488438016,-31456789981646336], [1,-1263537,9873936,-28868559,36398475,-12468609,-10015971,4721094,1594332,-10529], [1,-19146870,1769475136,5281209652,-10032427760,-40835782480,-6739762640,71055695712,63912971840,15410458688], [1,-7447032,4924412571,-359721985189,117617755923,2143792138494,-1486073631188,-2975007994749,3230985686523,-741473702423], [1,-517106,58273606,-1373815122,-4952974364,4913608780,27153942409,6950089002,-34145062392,-20469346393], [1,-3757,1530645,-28029222,2359216,144391005,61784671,-203472129,-207072198,-54303129], [1,-173780,45443268,-1790226588,-8863383152,-4818339936,30375498864,42501629952,-3312569792,-19727103296], [1,-2400825,190198232783,-22943866813291,24838048578516,112066877369032,-119639920213824,-123200993753280,100605510714624,35506136494592], [1,-25753,6751411,-44524192,68742386,111823375,-385704903,257283371,63338444,-67180373], [1,-284655,209650037,-38162364134,-163511305238,-14981588021,711289445675,760350260231,-313829615616,-502101723341], [1,-68325922,137056373910552,-11145282232549212,21173555959782288,42902777425768240,-99554991522541136,10187009777496736,51567358997901760,-19350004011936704], [1,-11733462,65284119,-55303584,-232858944,336527964,205314537,-268417494,-148242276,-18541736], [1,-258893,79530727,-4243301484,-11876635766,16008454795,57961696909,6993684303,-48619490844,-16019695837], [1,-18001,4498247,-188001200,-52454414,551685395,-309521095,-64332897,57315780,-7370757], [1,-1435968130,714533588440,-8231837770332,40163539982096,-106986363839824,167944712628400,-155368804314976,78443060916160,-16677501283264], [1,-405158247,18670761978019422,27304726717430303,-407622516493630984,-1469519465184311920,-1133627454427613440,1794923858940870912,3248244532977154048,1358504654641917952], [1,-404792,2745549,-2331396,-17521082,28819704,34082865,-69811830,-19635428,46786072], [1,-68548140398,1451627133858028890,-5095232432365659132155182,3088999911253813409361703,38873934921503404756228124,-21888154468509856869401849,-79286358464811742369152944,38737113817267168448327653,19271373881512324513129886], [1,-233746,2998825,-13950594,28124252,-19043266,-12805079,21860330,-5429540,-1331272], [1,-10355,21543,160412,-124146,-768627,10747,1106549,390000,-98893], [1,-238089,2428653591,-52281136592,55494790434,272982489999,-244755630607,-464342035173,229499404284,232532331139], [1,-9804802050650,16692730784125432,-2541495071565357628,21109219806111169040,-72218607566697081616,126705850231213211952,-117594235131211600096,52634612644066947776,-8014881018162450368], [1,-1546315729274,288782232725785318,-11969666848599934914420,-27130970349234930466201,47347882539110061930082,124498595190336220679942,-1304964757812833452501,-64114240217284796166421,11258025941338821246113], [1,-84967786647367,333964189732653895352180494,-9366745551868952432186167003262289,-22234121711987296225427381730172744,19539169743580452197619049789466096,51305696359169176802147610083269888,-17680157436544518186836737589196544,-26000314945482248211133277039052800,4518541019882267511313091077443584], [1,-7748673829668,83640796005524661,-937392562807456731,-4611558327627410100,288178943379431256,19088931030202667712,14002224746809121856,-11962021354522502400,-8709955859254358528], [1,-843304,33763525,-106394721,-151759084,340324475,-121861811,-28549267,13500892,493667], [1,-576711,9817828593,-1467968536170,1986116686590,2315529499551,-1792787441257,-759829031733,199468065048,18428192267], [1,-67782267991926,3118994381718067776,-4510225427657444408844,-9065205219388262002800,14548147545483838825008,26311576762212059385392,-13479025960226694184608,-13821453446321155975104,1249714021685870356544], [1,-116597,11204304,-75508472,143658084,90374012,-590670119,595390427,-100047640,-72256661], [1,-3749259036,554393241540,-10928530910172,-39909926964720,20361183490848,153596163158000,62626956568704,-84859519298496,-23307365582656], [1,-2485415052,131251617492,-500838205596,-311199622896,1007849076384,593369475824,-435068972160,-386665742016,-74265379648], [1,-235161,314874197,-3066156650,1109853192,24058441897,-22580421725,-49502851657,52464975134,9173335783], [1,-1315854,125620602,-575073054,-177194175,3317366889,-1778517616,-5030239005,3601178400,766593875], [1,-264278631900,6391720172245021,-1626519277074267211,2468549508074110996,7490117873595926920,-9983338376585959872,-7051946118841625792,5426902073117889792,1165973386759172608], [1,-79480668163070691548277,579797667303611907678285,871006426643549798058665,-5664575884052113261186899,-2721765628562603760591507,18297656442680378045473468,795444294656219988472938,-19650372769147029403078227,4906440383881879319836057], [1,-17361556040,19571584838731,-1912255610523653,-6599847690074333,-1764459194463858,10908227354203500,5823874326739107,-3161768996970613,-458530154815991], [1,-942677402975,306729542653406,-2223101555541649,-3021993537312,7932499451339520,-2016256763813888,-5852785072668672,743954651807744,853725799251968], [1,-388145,847961035,-14279672808,5155032058,75179631715,-45679619663,-98354672793,40080406380,43812242819], [1,-449715623374,5733757254592,-14174764915308,-36178039104112,88431316773488,56172051631024,-118680037031968,-12225526217408,30136055145536], [1,-6233425,50543493135,-277319344376,37556421978,1194329803539,-616149265735,-956720534777,-149559849324,-308254333], [1,-6720205764,466584698229,-850591371171,-5544923326524,-2245384789368,3411810485312,216995495232,-119747460864,6720270848], [1,-68026878750,236661304531200,-24579892325699628,77376432563312400,2783150175184752,-213772569953649232,171920098000293600,41445518831184192,-55371652962821056], [1,-618153,190453312,-13900878563,20306957207,79305438779,-96593023923,-148646368490,107484573608,96104956471], [1,-3837199411252,15987954244320349,-4697757619575778443,2802514151170278956,38842254787450812632,-17674389726474822464,-102961225717149802432,26969461377075245824,86730122212734152192], [1,-312562763163,346886487839985702,-93018430645583163427,-387503893699644070202,-227171488895637052053,1059383162575032981336,1901280189644540086305,1023913564393379937375,106567992233337642217], [1,-361474931790,611242743954816096,1973129339163640404,-4210002821826072816,-21443528944285721232,-15903091278377251408,17306737477063294944,15843200491976309568,-4434448077967904704], [1,-3778306,8394069,18391906,-34113836,-39223526,37637081,36203162,-3782500,-3555784], [1,-191995,18675888,-415738733,-487665149,3237735637,2525439827,-7701107584,-3455492344,5556122951], [1,-3528390465674391,295399734866669842800558,-2387118057773104769342178715473,-7115146127465248916444129922720,11963803174219131542545857515424,51351848128578616328477557919744,7113243674866320054741354132480,-92257589727819000341535933628416,-68487179831190246952800572440576], [1,-45037547,172457645883975,-1790412841228672560,2627143167768991192,9869078575652884449,-12596759728507943955,-11343571983898538301,8920514581505543602,836831771418477463], [1,-14544930060140,137330449552913,-154735085579409,-876479584619080,1181245400641645,1927455097458009,-1718524722383285,-1592842129577062,-167254737213209], [1,-1873500886,25283363424,-29198798220,-138943513968,158616778288,124060717360,-125965364384,-21725034944,16468307008], [1,-3806541,20782949919,-25366811811144,71965988436246,12103674791283,-142770198449983,57267830343243,20593396170576,-4139930393533], [1,-60381,329921913,-102719400354,-307998071508,131405772501,985414316087,568240988175,-134586047862,-1251538057], [1,-19205016,82891756860,-75612791103068,-22071609728016,593620957189344,99885969101168,-1527816117229632,-114091235429184,1291999661947072], [1,-5057480,64075800525,-114778121458632,342619789089451,253607005501671,-1403010587394510,423528819767088,1315290786628078,-789115629856541], [1,-17285705759,3645479098061046,-977455946035418697,574017488559447304,3349789413247368432,-3569470539005100288,-1037838976341249792,2354542035384567808,-697220011518488576], [1,-6736624153863,183177091628494320483286,-6180182788352798530510347577,2716240087955115185667279592,22390195136916081365570958960,-6868581589286990272316103936,-23220089103784231280127389440,2774463146325228316623759360,6830897897415504340570279936], [1,-284114632574,23328357826240,-297773293976816,-1110327740162464,569323040643840,4056968008207104,1629816222242048,-1887449511731968,-365569572674048], [1,-61113734390,16008403307648,-87192050722668,-8774403711472,522877371403184,-217607455565136,-1064677625078688,341515181013568,772225254630464], [1,-575283,495123480,-94146773163,-254138442099,329023946235,1060550521751,-194008114416,-860201958138,231411895019], [1,-8715488748,5970471668822748,-131516946743691692,-362146003783658160,550507485957558816,1689675762706695152,-133240171325456256,-1367117267311120704,41605663243747264], [1,-754302766,204635138688,307739257524,-2886558712752,-9696999595088,-10366769647184,-2966994334496,924587406400,210205089856], [1,-298841222,38173752800,-1269934926572,7899038846608,-16724081597392,-866792844880,54216158908256,-76186873466304,33725611694144], [1,-2022907274,153018343932907460,320981614532593515,-1651825547656661424,-5520681723930583807,-2507330145920455952,7612874974670639605,9523512831628249435,3051738873709998473], [1,-345693,380929328,-8222062311,40755162175,-80293086305,60679695873,375595674,-15404928472,1789630471], [1,-1171530,41629156263,-9975372520038,4403806572024,63987965950752,-13186797282636,-112717060634367,-8838630882576,39713414160403], [1,-15249215987703345643683789,65999669051011969127587880853,-57965945899301298379214742190,-480754726560884120624717949336,46654331036366608056055398309,922676089806829907322011185351,525899145779582992611381401751,803706295997501863197084450,-6533057249290496498299013153], [1,-3,-85,330,1854,-8885,-7333,67837,-61572,-15731], [1,-18999317,14188004237,-654799572422,-142273400912,3076892255165,436752369839,-2186399517169,-425979209310,-20092498369], [1,-55267655,19031864097901,-1323773104630459478,7816233223528156410,-13003751961452721333,-4361156381824269353,29106395680462736587,-19234804081092308268,-410206599790220149], [1,-412277031461850,21678032306781299848248,-2461595077336056893741948,10570781888949923022591312,-10667200780571632434652752,-10137987860380589840189776,21329690948753641253058336,-8768906897999430259248192,500089379074200034412608], [1,-6974625030,7921875723488,-1938747773729292,1214230999079824,4740127316419120,-2454499565586384,-1488131163123616,296470031713856,27233217614912], [1,-792296275135581,7157731383572903793,-14192905336051175984266,-56193023159687986802166,3245304106744257077607,240118027162073934066565,219593747170291395284346,-127601727583918000465764,-153555585114394714772984], [1,-67379282,4783160426852,-37576960879135497,120962277105887128,40492542396123880,-423592117788419911,293306304698596826,64540471360047660,-29466075743752904], [1,-885599,1922958558,-14798379535,23102811288,29078205681,-91476357427,46833416626,23835146496,-18433878713], [1,-37874815979,112053086952040606,-1544680561043401411,-6722143771571041474,-749983562147267093,20680704519842468816,14958350042389121649,-13882577924450532001,-12578727178554392743], [1,-31069515170,993008647032,-6402959118300,-2905149336944,48134362508976,-26066596030032,-84622776300384,86427873915328,-16089254473664], [1,-104969409,2035692788899,-1999021285887904,4277012701797850,6490533958588179,-18781551224385823,6497216849011975,7256037158527100,-3779402883441125], [1,-4555508548662,2674415374271232,-81556857978611852,-155911831259546544,195164499853718640,353033807605799600,-121630137797124768,-160738427156398272,53457532904521792], [1,-292626982,11992564939200,-330201914364588,80624084150032,1942305209216560,-245628921486416,-3461988496574112,-175512680818624,1550860071386176], [1,-173228820876,1791731502684,-1014936656748,-18417922724208,19590235822176,60388707916784,-68861940059520,-61536451698240,71275249001408], [1,-11246620216342,99851364475552,328388289229524,-393490018444528,-2024960633935312,-1892179994121296,-20385701464480,686502512699968,229322168012864], [1,-1237071828105,226330377674255,-1028826653892667,-1243355993777356,7113712215592584,1502735894044352,-14186021241027776,-227811750892288,8154199934755328], [1,-2880325,13051731,61229670,-55416886,-332621863,-257926005,24693879,68374404,11869747], [1,-1216510579279377834,226162806214537461603432492,-91363300579643873512882902453,-190363013774198779059661199340,320772368294364761476370276040,621146801883650894342167055082,-209967955680511453135279973748,-206835781623241247022061648872,46846125166425639252867787039], [1,-16051762116,19087414262829,-126691360247643,-707884372586988,204692259817224,3682390171810368,2263521694089024,-4668341182458624,-4304362700713472], [1,-7418819767071,2646922977548674967694,-83245372936799845908873,498860138779433263629168,-1152057925399851778938048,848492435332317598462976,783476452275007945113600,-1568089294433419059658752,672589256230703474671616], [1,-7250282,838327455,-23386012735,-34079059949,85710931608,65998729223,-89276257757,3941198888,4945836787], [1,-658926378322,18624546237015928,-2062234561069619292,-10800530029643230576,-14347395422084489296,13569364360070177968,50870831766432498080,45071763330662993344,13380496521121534016], [1,-87653,78349445,-12327824838,-54682458328,-36903462411,115909907863,154880615935,24370087762,-3917426209], [1,-438085,117367249,-765249018,-902080036,6285923837,1004191351,-14765116657,2699080210,7161771479], [1,-89381858,-142394209,799646068,1526254980,-1546314144,-4251799647,-1262470950,1268754300,579015000], [1,-1678781529,6313135911903,-888987461357292,461137299708870,4475062911662451,-2137281952110171,-4379994405324045,79551555963984,364326732434611], [1,-5621468032962190117,19721495932848051225969410979081,-494435239021384832364087405797378646465,-3503664529435812829750998396559356043915,-9124243100343144417050357428842011111837,-9526368450086740816186714808892443240283,-486694537840218958297274619641538468550,5828567877426929283173978233126673295980,2905667579994707534468750797365702380296], [1,-814194057585,414056472969393,-19420820935146007,-135767377725635751,-267506949366593571,44028334994232964,753808838498392206,873256330986976101,315197368076799697], [1,-48907,2168113,-15522118,40915117,-21872408,-102803829,224647094,-179223282,51380371], [1,-1019523,5276891832,-512500692083,-2386438662987,-2722713064845,1113611574359,2316252243144,-228547173210,-175243581101], [1,-335795,8955359,-4221018,-218609410,-604886039,-661683308,-298461804,-23856012,12327687], [1,-8493477,119548048545,-1039122579942,1104300080064,4829469460413,-7772017130269,-3487646723661,6666637397586,1090822908167], [1,-24148314,10369842460185,-66358173654029330,-184211899158470751,179153716075265505,863191377824078990,425853472285376526,-508078822351279560,-363722086791200321], [1,-91217336,11790289341,-293572970004,1239757219462,-1181507394248,-2289699741743,4943392317978,-2519232117732,117157404888], [1,-251463513,10440593464,-14265126137,-210419757524,-221483555932,501196160416,1091475057552,697417217984,146211954368], [1,-25940023070,16615613882984966,-829888106638892401149,3107103253174297644999,-337341923594596490527,-10542300455562618582368,12615050591111237515880,-3682983838644978274608,316368182375400330512], [1,-344710145293,506731498334954649,-1305002432564881675,-27770714167595284139,-100974973531681593551,-159136863919579149436,-110396521799745595710,-17097447266803771775,9483928020957047641], [1,-19910899,1108243349,-1950406148,-38850153660,-82634407987,34083615647,288974196125,324929315398,117212127463], [1,-9615,1189381,-10892942,-70419271,-89261804,65855479,155687606,9425986,-52554269], [1,-1147627924054,4374439941008582,-1169722829354124386,-612087790189978155,8807145419930617852,3294095723624945425,-21200736991273111062,-4444970550839273348,16300547401929510392], [1,-7771959873865200,24298758098496889106127,-13467349983140240629450854,-31435123124322071864978217,31200803159740556829335643,120465025183103142530732661,82581065775122714689153866,16184315122000165922082828,-210904929440283813831032], [1,-76777,759763,-2575014,2781966,2455221,-7052269,3554543,904532,-762341], [1,-129121,120356183,-1587001214,7055600862,-14501253063,14635813347,-6580536485,811733712,33502771], [1,-53749,13871545,-212064370,-371996812,1399479345,1662006187,-2712066489,-1696167522,1758914271], [1,-709961863,5807333837354195,-30105496773035385164,118414882271428824296,-124409004468477171111,-6841469921742780647,45908280183240492363,185601242150477146,-3309039887809200593], [1,-449844927,501967196801922,-72847833684086316098,188158281820054449237,-42630456470973039012,-106990492719289674022,32807845530580852935,13035007653546210654,-3390566962302687329], [1,-23035292,118489036601663,-48932375051930605557,8568147074136076147,390559380607279426130,-92321152949709386920,-955466384049168573505,215934908717498580239,651139902668687666017], [1,-1682208809185979027263740087665,38460669002109216521306017047488771434208899615232339,-789215380710611948301225849906279583250175442757096555490324572457729702,1298256148668053925249650971384686586826702470064914229044090274999256215,6030329823121832098863396859553835498131032809403984593479645183753512324,-9490084470419754437453910267860740292415249457134746840897452481872148103,-12394600943847745519754407531435779729178452247379772195631334665755880166,17341080285216312802767349120791681272978457502031451943896949208999010428,3296271969194505878859122633527852637478172298602731294774862093346579128], [1,-1144265495309835730,49923475084524347869216,-15995488733125357472577758,-48796962740367288699108596,55713495918778048738211031,264166134873195160170026981,71070428772729452084221562,-287282783333568985533701572,-168386733883938686911812856], [1,-57220933917748482791055,421432683704137008041973785434926,-19706728990556038367918172669771186953673,-12723424145005161802854383220896287885368,127580657871872145892123207192434478107408,65741687506553976917267947208625253170432,-225142929942783048993990402047872349206272,-69761989665958342964660248694611335247872,78030709323948095525370311539795889876992], [1,-439201344361100057172,298682339369083510723957169,-1993819825297374478439136896,-413303435630088983138297958,14748097505558080719171177748,-9462024177248915246648070223,-26659710763054612986043303206,25359544965613546263800593388,-1888978298649312011654077384], [1,-5802127263,287719052234104404,-28057294707841304943420,35994973074431882507118,93560769205410381354270,-68930980457931982724892,-75581789160975641071308,-2168783935945534218663,1123856354218638808457], [1,0,-1125,-8187,418527,6063246,-29628708,-1114750107,-8016271533,-19159072973], [1,-291018221130686,6177811912283862896672,-24098188560084773665644,-55048694056791696049840,168071111174651808652720,115168131681977741268528,-310410872603033686377248,-2220471709185131354560,40713723811892150741056], [1,-45742676674,13285226508600,-884300379122844,-7924935686070000,-26863342798122320,-44887054617934160,-37686285269143904,-13497695087511104,-823934867294144], [1,-6812707,29260293621,-3863681916534,-33899272787250,-111278748580121,-166973063735213,-96219537975701,14879138337040,25557866840803], [1,-452685,258015456,-32640097359,-100508736369,-549156225,290122084313,369635601162,172652033112,26034334007], [1,-828120321,19196894484243,-2089902600280579,-8925328592739468,-8315112977750355,6139800082126669,8199504364294929,-793429782322065,-1642176313344791], [1,-29399280246084,41736821359896213,-8689441224824011203,25748899993528535340,13652429148325027992,-79459998887124758848,4683397865515364928,63322739270171112192,-2397673249658495488], [1,-25665087553029947767,5002010563050666885419506918,-4640397039631951425031718106690993,13276249105588143916264279701500984,1544827222563604148108556918471440,-40633243602231836771322648275415296,48647018551609709297127556195926272,-20092948136529590566080329583429632,1899626379682900076985335069339648], [1,-4637070372,267390918364691973,-3359070220125120611,-8105967729252032076,14433914809537703496,29396438188961407040,-16037510797635992256,-27512591734201443072,319497287955931648], [1,-740389088691,5004042945081330,-151636472754243634,-523513097234815119,412846622368142655,2424331629274400332,849682242734634177,-1814618342964912189,-649092289960547063], [1,-22667808,21478629458,-159734672882,310522791150,312843358201,-1596160761077,1087057090346,1013551660772,-1068737159384], [1,-118268599457732021762,13399423901526523925888893396,-37425136346633436638727167810220927,91910191137993644964843610826806732,158700085555037722899767217847608640,-466718969360496984942243557276658311,-57994110985325353303034094257966982,489803170996960297784106903074766828,-101196279482189530047794770391958856], [1,-8381463,4529381481,-7123725636,-40365253980,58609388961,112828469567,-139876332639,-95346809970,79811896607], [1,-190623987134302,10493332733817654112,-200976379697735153132,-362113359089685425264,1357637176890689247600,2000562870652299770800,-2241151875769637504288,-3021369928455051919552,-180984330143355512768], [1,-545911781686038,1730369425087127616,-272632842836862857356,888993602871827854480,191956349995970603696,-2594867433851352350928,969701493484050638176,1269690910288337998400,40768664618894583872], [1,-85874508818,1654204738629592,-716784590322130460,5627245910316387344,-17839758794358300240,28737683622515717296,-24297806085710613088,9830990459438087104,-1346093235942890432], [1,-27076783192750,24271758572883968,-243037537579443116,-2310073161266346160,-5326182729140894160,-675777809414818256,13147788338535368160,17552314353524427328,7070510147611960384], [1,-21155105313,1070254921430139,-8712148588351133312,-8310650783259700974,24696514940072822943,6983175715238778641,-12380078215276546173,-800178352897745916,349756210435254643], [1,-12385688757,1916080199393019,-58741618673592542228,26929663025166493266,239986041238361005407,-12316995824222759299,-248523201105492395517,-58399583014201665996,11162188846705939387], [1,-15580412921,10623466568,154966313561,-51279535173,-535328756625,-20329193443,668167599734,246541089532,-85980663233], [1,-1891790001388,574801216007853,-13941273621114531,67799559326838492,-108653948402398568,-13754837500374848,207321333594705472,-191671749190377728,52120943273655808], [1,-762692554055132,188338536604999496013685,-46929736652845070757445419374,-57831423295578968941024692602,204770636072818689433603599849,160466853240255751165397666568,-263630344100570306422895267718,-45159126601739526691377711235,65450970623725405682676537889], [1,-3106123,810597809,-1876412892,-9309480837,20165946328,35098753439,-71648543976,-43488201116,84488560031], [1,-3918735787722242231421117,80084232039976969048861461,-429331637992124079459325854,831075230218880302651032120,-408725236905283779167498811,-420414034582254809217609993,361175537167240879449700119,35761097653507891045200210,-48640722933604597956528257], [1,-112011082963371,5899066359243887720046,-14995174545778923704947,-34251476632829243370858,109639206542080354146123,10175095996245722651752,-196595181254681388459807,130116571613861427796599,-11528618720994558355439], [1,-3246166543941725424,151410873803245034545931959,-110953078534039896467952064542,609107951424251899808848415239,-1121115269275985262145454134649,637639391393057012614116747237,232557885323381458359435104522,-260101647651275389179436402868,16856809039625836040762310344], [1,-120054372,126025066500,-1421354175318,1353917591943,6080973645663,-8845904223982,-1484583717465,5457878297754,-1388894309713], [1,-46957890382377078,570204983223035855740524,-25672873250292003289796170440,33292485242970903574364959872,150518964306624020618101483008,-181040742420192126948708179968,-213632903931162431063281238016,195891936156400167131409285120,69566168302856134094250573824], [1,-32613422196,13293195120138093,-1451198812942745283,-11756808143248997588,-32085693547566336488,-24881695260413271872,37363082983377837632,77251669176633041664,37728923163711151616], [1,-1177876571708,6366485452947343117,-46575653986899163507,118087889720953902204,-102687859188394641768,-32784338554941935424,82031747722754312768,-13088162495314385152,-9550737546785669632], [1,-106193595,4410985912,-41256964077,-99838531933,157099639053,265867078099,-92388561848,5247677968,166889743], [1,-23408585484,71423272387788501,-5957416320204490299,6046568575728367188,17271011510560257480,-12692446337212757440,-7771006242052503744,5134862897421219072,49153182042931712], [1,-694029721,183524338905,-6882896399490,8710775797688,20599308065701,-29781479801389,-10134047490425,24318968190922,-7450233496889], [1,-902673908688158,1392214421567394848,-15624512933141859116,45976911448034913616,-1847088925044495568,-164925717518358482896,157602672401859580640,105528690493768488000,-141810055562534205376], [1,-145135715,1186849347,-1232951040,-9840395474,18746113329,23583433803,-57550208091,-12643422272,45915585619], [1,-1137129,2442823,10556386,-17706290,-32192263,32586259,30777579,-11138776,-8089213], [1,-466028963406063,64934307251398103646,-6795302529775113006487,-20111248346049663289440,10166165643444478722408,51213693101581443134377,-4938111472168085906118,-31715758212696299786004,3018843864850336077112], [1,-9987419931184017,766560303506581526663724687,-73777573791928694859141506558885353,240702694079437759281909426824308596,105453916148765716102467506033386794,-909588225036127831694292097476051563,434609095030391040744938868028123509,574516931945941600135504148887557936,-282567548391085032510183482287898684], [1,-619200324,247155304503,-14227997035842,-2932198663218,80360375375082,12041228088737,-110627350073286,-22984587133092,12136738671032], [1,-194430045483,10930146184233981,-37004080723791054054,169726782696692480550,-121850854246462427577,-419088703965457667649,644180698259593014915,-130415057098479078768,-77994015988756051997], [1,-37014675,150133071037,-89620040871142,-4246798262090,640816272972087,147122927011511,-1170139960911845,-531617720804872,159192200026963], [1,-1085703,3628104285,-197606400462,-400590842046,571459462659,1475071012244,732972054948,15568335054,-9004627981], [1,-4805757,162271526,-1207375811,3240587248,-3189146408,-248324480,2064628672,-711019520,-103058944], [1,-8082773729841,7260177718541589,28691529131451941,-20557898848641255,-213364185531482127,-184371916552970420,329892988876405854,601797085412257449,259979183434469281], [1,-327891526494659045215108397,12415949753135545692786849440153069,-2528824608659201824230894171119626984446,-19867650886035452536415225545819645157008,-59490878386915725860364903888898567091339,-80096469746659429846156883572389294365529,-36334678633058706082811834269602763167737,16048305290574653957540109247696824131978,14598909565142137515897772375275790462111], [1,-1046380114073260670,20461446800168814236788782402,-1395232429054800226055784119164,-11814830543579397346428451421,5187235222648332575642588530166,-236870611278038562893157010142,-4651363385403742416925139405309,150561742385028119335244624551,1038951692548448313014037731009], [1,-14044369,12712692256,-286283415627,368099638175,1245716824619,-1974026678075,-427395032890,1130080662208,-32110434817], [1,-5189841843,23667382972401,-12751055463010026,-70854790453915134,-97420334705757141,102420442025729991,333086507171382423,198625307893879704,-5385976036858301], [1,-100447264,2367460909,-11647735164,-22659089650,114239885504,72479652193,-359640790390,-77397327524,373442503832], [1,-2137478889,106206931677635,-137342518370245600,-548950403860134704,-806850507473777605,-509923887572030632,-99145665684287766,22120067430795354,6701494189754083], [1,-76845191,309627891,1178754408,-2684467622,-5638221435,7036965267,8677867233,-5024074076,-329883557], [1,-73349517645,9184526794530,-275174935414557,624089227488372,736671369199572,-2530554989347968,497043204973776,1702306987221312,-627298115144768], [1,-314188397798636593619823,335970190538190385985388108,-2414209575658577982978368202,-5403727205452820242763021868,12933423122404575469588280664,19593247481667281142338815857,-15129693407601610182001856262,-13604065318256732137470719220,7457050262510409218629063672], [1,-19613331564964,221825287915904845,-928652730777886419,-692577743679720820,4056206153338650200,-326088834466007360,-3929148676265343424,2185149010484329216,-265604387866161664], [1,-3981185570,76011080711988933,-23874049544574829458,-136138771723302192998,-240844682398345291548,-76918201009868870223,155033768170795859610,109760640295897249900,18782705380108675000], [1,-172918841552596,3326082333651752197,-77606226984224548443,-323486630754573011620,43392800154469323992,1311641451694761581248,833149624842987031616,-1354833569202833797376,-1213199124937137459712], [1,-219939,25656614,-148980261,300996296,-192818528,-86227968,120957952,-15949824,-1933312], [1,-325039,3248407325,-61496266078,208103854874,26916787075,-960970439460,946207281740,582283091062,-831729129029], [1,-27077552910,996329801790,-7650375746856,21540998233233,-18800807089122,-20061209044887,49042182145770,-30149768524068,5007823431256], [1,-28751530871839,10574092487997798958822,-1064233181826773349067411689,3086017265431827206232691784,2585812762794672936236166800,-12627806321822040150419161856,2591019949720475543671503104,12609645435265892314981599232,-6595161125977310121290272768], [1,-1167525,31775760,-249446135,758488911,-920336241,222836969,228398058,-23167992,-466673], [1,-25887144925806,3228307717735968,-83460145644098736,-31254690807457824,701552749826173440,32196751623863552,-1808979773357928192,147213095097255168,1319250460887229952], [1,-186067,8007080296,-1865934302217,3966801254303,9764014243985,-22965783804461,-7322978196952,29716362405820,-11181475114489], [1,-9105950887403324,17666285281338173839583953,-570225555961995219052493620,333720143634492832572686024,1257498900967760044752503413,-71646383269843578661102537,-323577514416177359919299151,25676111897036233933151855,5136184155827329813126817], [1,-407428497251464,1169129660369347454339,-12408323314263781106933,-22924663153724183062269,56734592730273345953278,88457730891209789862388,-46732029534409282400013,-57420744657176302056509,17302177255596979365593], [1,-213213855519,5423797965783991833,-1071312540597931185690,-498371991342578083170,5827169960992863316359,3468725904869426685603,-6569781497332253668557,-5369231464981086373632,-798079038447414756797], [1,-39145644316170,43098838479383974936,-1393381401798061080472636,-3902984552673438037505456,3794052851460402331786032,17307395339038214282812080,7735210768810043394014240,-7927441531908453543449664,-4759108912905967023018944], [1,-71587718645955734,417709663167480853549472,-121646909545951504366970700,178902787378484431960104912,289349589287143068373753968,-622054227198478243591683920,331988161251811787761431392,-68106746864077162624351936,4673098904747061778490432], [1,-4705121338830,188778652339574912,-86569198544652853100,134884524756528912976,310097710221151687856,-423514086093021322192,-287314421675886646304,299569972394547221568,-18948072597586879424], [1,-871311988917,41911926136054575,-17588024008736068228,-120949716225573676494,-238622182867805315625,121301920871698218781,1024479863088054971979,1286847499723222294116,524750985381154767083], [1,-660365,155219491,-1477944460,-1948890582,9157180447,10047668573,-12801064069,-17022201300,-4708346837], [1,-162440766,9725435232,-139472754732,-141447952944,651832308528,463200875056,-409455676704,-139580609472,31344580672], [1,-73991769,3779656539275,-1588324550621888,-2850700671540006,6639439780940335,12458178772978345,-3001336183876405,-7186195488461548,1228560936643291], [1,-602280,185127438,-8032330614,4655899242,36336791775,-13888605445,-34794992070,566261220,5905586312], [1,-793305427,10722262867,-37799372520,13250340782,134903221145,-150273057893,-117445140091,161375702896,16536355067], [1,-7241081574,25886115248064,-786523151946252,1487821004382864,4799922480477360,-12254503026731984,-3204019391007648,23648365707528768,-14001538998804416], [1,-68709109711103355268342,794212042694172998959675623203456,-199639739058313536433860442701516,-12256667642945599347878098666683632,-5135370218322307255753488643369808,55826302577396829528549641891338800,42093919672649181457791027580818272,-78094346463401717012162246496433600,-73603759196961759355613981208833984], [1,-3333295274727,34572781123653309,-11642536353513403198,-23346644708711384862,50795498459103908163,109640146196378460331,-23335310666994177381,-69139738612718500884,14647493405052447371], [1,-113,1176,-3819,-386,23467,-28696,-29832,52809,20412,-29249,-13190,-223], [1,-1572,41840,-301023,589524,1129931,-5022917,2678727,7731400,-10207822,3007737,369710,-116575], [1,-46755835,1206514419,-5981923871,-20191272521,74416768475,265724484731,116877948397,-443728589789,-721745657080,-459066275673,-134096733890,-14549748671], [1,-264906556,164181027958,-18724183114540,70479317370001,72968634377264,-492727397394752,41734123101312,1145261155531392,-311954756027392,-1066408976920576,177404063801344,324503752118272], [1,-5714993505410139272296507009782216,49344904230148839293333660593889114227590536,-75912374820652001820427996265214005713100104096,7989457304633369412761744707841570955171670040304,-15974027141958161121922623941579887028811517171968,-74507683121314337453815413692153070376569859762432,171572955584394974398431302183548180568510573755392,196203312057724991575518132602141074697099154452224,-592343421549858666594462955237479564143319009110016,-21950313161471530090788036532799002703196428335104,665588107659149680139605375551402393227427753877504,-327313607586270398972920248639723917317625964130304], [1,-229977242,5072291958437,-111384225021100,762216494900532,-1477672431507456,-1588524670358112,8220409292590464,-6523629466987136,-5815313742183936,11727602200559872,-6334684476656640,1139431063577600], [1,-6882808231898278414037342656,3455143367204290127157342521604388436332,-36661537168170277066262237535877306066556,49588942370382232589832601858597528091646,356029612847288265291799825046259689332740,-524595811862855775985469194571914871611070,-1025519268248587041651819209950715500501700,1453885449064670671053483316089032783488877,747401846174933080367524379803979196331968,-1239203088628559715562735153436589082944258,371531325751546776299376086652334941513708,-25967762675439783998636643093161918358399], [1,-776227,35260611,-410113332,1237367010,2841962582,-15400560964,-1522071034,58779614473,-20028404187,-89273582271,28252161234,49612618017], [1,-136450,5782301,-48188974,-56158306,391808464,181381185,-993288620,-120590148,904251232,-106435088,-198059200,24040000], [1,-185290035842832019128,489482814788592695857251131528,-123165591405668541618484310233779552,1382699398509947087245384403121233136,1451187676274817203561770378629695744,-13349894710179599610890326621200296192,-7161656140212798022704305275356945408,43064097291752964399345748822207213312,16507693434261046711880963152245303296,-50477638084627481625862451247360866304,-13250359536841308975630870347363442688,14228047455441382330877775957566296064], [1,-75175041843787104,61342026170367580199808,-459463266498901473284181276,1317681283458970522968876746,914122129345622228984628000,-4650476380148947381939741522,1679357874014236559395086036,1961391076946617638906024301,-625118212064863116606332772,-340301790330722833417811686,37393240021622932269078624,16301182707955190633537041], [1,-103236086,1999763737347,-18474454131370,23989959263891,154675342323716,-361052854031686,-347070912266276,1292028449255827,25369597086578,-1592955973471413,278906963487694,623764364353873], [1,-32005221058803772,4637628625018039965419958,-3717203173067266200276095100,515928600836885426751576737537,2320049127272374987480220302912,-336813174821028838294852909072,-15025829957190389847037460506240,-18686879576562303590015975665568,15747418480602911176531575123968,45665292986239411427949932910848,29894966333608668824087612589056,5838410116627764613546230919424], [1,-88609157169,692928400278227226000,-18639810502615504141898100307,205777952269910958141151211118,-482100482299731057868364980215,-544825876501103943774907374028,3041454447812245838666224632240,-2257391223497009459404058192895,-2899875613277346059907829946934,4886609292155880670960692388815,-2131600168767190456076052602130,207947193981122938848112605041], [1,-3183024216747548838268,347142389627273461829262758,-441720998655169990664213630864,4524051142705909842996317944557,21516534920861500399431369303444,12595830718870799466701805370122,-52288927013806481740769778432036,-93644009415943389791426854732746,-59025104012256737349525392054516,-14575361103996761413374764908204,-565750002074801746316160856768,165811130561518571726921110129], [1,-81149837561968,58618864154304079578,-10830571585373935637269404,559883747296995376809712124049,-704021501828066365749085402734,-2399148964611094599666442234758,3316182464824620576759571538086,1774891982677587277011080687322,-3555103338212968630407231466105,821712824228692877635550872675,183505222060318667427166134250,6885453722596067903626375625], [1,-1563597153071082805844103218753996,67018408332460754570119044177545638014970296054,-37099623251162852103090511887535812015226342243484,2192103164616289787313759550176665641270606908066305,3243664850340545232184241866506929046611370635737776,-10514814844966903945501503146066088655871990118947664,-14593405378288550597224538554184727096639754156996160,8248342728040074458071264923080698568212480136102752,10243276134747222494276314221993162945870371455561984,-1845163538579634478672993723514426190163328408691456,-1777735033500819774671164457229092452663819911004160,154226446779924775048387201885796557892082364170496], [1,-31223691959794830602,42765558803732842831684673,-2162188858003428992663539272,22770781950430057176647472882,102451102783461555146628667630,-112668144173957992900965272712,-704253264672437025442827529992,-120308852756586442278247401279,1487503938885226109640060456728,941700250082578881601264792984,-685422721638535434474056198048,-502933781105705055904786490864], [1,-115413570,287574254057,-58930369951719,352419522365346,1169402955316028,-2959989895389245,-6672131819310801,7192141635813067,12811780547077466,-4190604601917150,-4269036523999336,678648868147889], [1,-20591096196457859900,1840165796772256356932562727958,-131023868085871742456573444328908,701541835202696113652263210173297,-977060642871327547379950033689264,-894856974044186745852632084570176,2756921144494190878619328965507456,-668446399254552912794190974754176,-1496860430561691770146268333923328,603516994619292536597205769392128,-11814503100330293795716197736448,-1872632051224425073935746363392], [1,0,-1820,0,136936,0,-219035,0,32426,0,-1245,0,1], [1,-1838,110466,-1457530,-594624,21403672,7660335,-108811868,-64537506,201749902,118477401,-163628568,-66610521,54780838,6013838,-2634629], [1,-31231,3740300,-91245378,298050327,934268992,-4401788427,-2431740698,23399074654,-4515560125,-58297569578,31288267422,67359582176,-48602354979,-27725192380,22560578171], [1,-40906,4286270,-77984287,300321740,106381441,-2061594435,1180829506,5534987315,-3707589161,-8142120477,3490266018,6790116438,-312434143,-2360372242,-631502281], [1,-18809,1007298,-19194788,162121198,-636963643,1090404363,-104031362,-2310502773,3004164956,-1048406868,-331692206,203203153,-8625326,-3759294,39563], [1,-280247649,12370143747059,-850996907727117,17385934340695578,-104953177346379097,159438058163777720,405739918822250928,-1435006226138656256,743609052920692224,1986922299122192384,-2872064678639902720,712942514844729344,923102855384727552,-660573116061712384,124295145963126784], [1,-147688084208955,162514697333979754370332,-143071328373556693619330813,814498028407902816901453997,1196611416136583566907442618,-9230269879970666415572781126,-5425788355021335902884454579,39559829432680865697441913757,21760961992967478375384616236,-74241951529995456358177390411,-53798271555346409210041704986,46955989795933394809385282456,49835178466379490784238600176,6845569936271203166407322128,-2455600842687476406035136544], [1,-55984,12125520,-753020810,14698113542,-10692173035,-119906892189,96604699315,352327599777,-246807485043,-429478006526,248789197002,163568577073,-96696233259,13402072876,-354876733], [1,-1558704,11732227927,-17345399656327,7366503686195955,-219574743844310286,1050340456599871611,-735317912369847266,-4907175335868488768,9266149963815066786,3225135837007914497,-18338172819145680515,7818339608856537238,8690381388382833077,-5833601680346328990,-53861918546721361], [1,-47014,1305366,-11961382,38360176,27298817,-406153819,532893405,1091715987,-2802659689,-217964548,4576634412,-1968144183,-2321534605,992713950,510072919], [1,-1468556417308,8300573606061360977,-2705938416133717124406,88913013089260833668088,-724328419046932245976481,1018249670823443732932416,4943137677182200075532416,-13176958801527732381953024,-3702816671601945471262720,34434714043481702461800448,-19941833091022080943325184,-15466571196576506123911168,11141321908580043460706304,2504851002933833130573824,-1206197920399232258277376], [1,-145550294,227269379365,-25771911970426,342428330853015,-1911328449126942,5363840743877974,-6826775727050422,-822314470569433,12964880540399583,-11801460015689989,-2874370303777420,9159227460645875,-2583732509408625,-1835556642885000,850347584171875], [1,-89808081674911266815048,79128424242713365122209007041188013157,-3052605634288681896804299927151469576341541685931943,24591740445889625411404075364678274009623245146424112178428077240,-17295013047448966608202709921007706026591999795959417294752856173802683699,32065934259538323730519329339477925731742492637748351705129217070213658440,180607570389961128875518521066867058106924267586859262925565140714113736839,-310783026814865911699927351862274732318782062129735230464762961875076241643,-702304544416243133992984157877194404768211184446016846306225029609718535980,1058727794193198264458438705495642936140864153797692639517740426916759598389,1221126278789507833801318925491932404091838452610087168109897350161355693478,-1440615126322106993870227378444982950194867821903521311858465280054265740520,-826267695361720929583800717830386241328018992164187448340917881743650769552,584055962731112025260083552274427498515225164253321542720142989848153502736,28668284880261406684208154295930066873387643924604067624639811913733221856], [1,-388076989,1079758962665,-281006949020358,2301148841669910,-3410848405792517,-17769471739473636,56921951799902635,9594228172805605,-213590792333203357,191641376766491029,201891846345306138,-385039239395541241,133476271288119771,48496821572762834,-23740268125285297], [1,-47962447,344298998595169,-1598332423506290719,104781036499703828895,-749710308556203862066,-4349324659762972691351,-632975120607203069430,18754307769062652874915,19566916842088227057339,-11596690452466850281895,-21211124126666080071840,-2795072395379003358055,5387658101225234848338,2195619029190942811826,204373679742809086883], [1,-16518941628,5965603522057334479,-7902534202340150038231033,1563180197295523061482407892335,-46882526739774604073556748947752515,199012743910932707366382724114583796,193796820300599395174342295123702072,-1867627039195345259033198899684724864,1248034401840430437165453602838706816,5205132319166130315425869956472064512,-7581715285764862346487806635495281664,-2219003884964290099007728441527504896,9678066934299569255447806826446049280,-5773320352397120248544510362810892288,1009574104375918576911526017373011968], [1,-214049722596,3515714950664743487,-1352763252743625525233897,134556838299926508927771395895,-694229409087478927613911873976723,-1102057343661796638891548804391356,4122358655749500542829101852368056,6567735440113497250488420670505856,-7532406362362521310529100542616960,-12841282877968992332152198801927680,3381821301827390538283885749808128,8356624089583657435604470882791424,1493225778137995040855190707687424,-199261734637216839574037309931520,-1830221442717099448219317600256], [1,-743770101390697,179419980281548028514163,-47209784662238068446421397693,1248977050905179806682070021106,1138108288107148036661401765271,-16195729635522542904392224321224,-10335199330314339547964315816528,79093290025996932849843874650624,45994798119262657358160806641152,-176564325311670661882126639722496,-104241905119071943248240054968320,168410248253547783422319967862784,106300676916113531032996015702016,-43266322876251150948515193552896,-27685068885118507173495257956352], [1,-1139079482,9939596145423448,-1902335933481257389,117425735899567780910,-2203383527933426907249,-8743264574237991049024,12590871955008258625152,64511776855381108698112,-7620215622544895725568,-160648619168498645729280,-43192155000817402511360,142877658633594204061696,44786017920496170958848,-34610078159668865138688,-5023825047731467976704], [1,-28249891883667623002,209333791113233162830035670621,-206080823889129581613504494878551149,745711151920412521002496959709010921922,-349900362184470467941911122602681421536801,25866755459018097671760805134724063035040394,-218360750504778413337426314748621266761874617,726694460005575886021746251339899033147125897,-948101347386199003904663020605411105820179610,-351473235980877001164810248335701001104968716,2263115345811528628293565339506776266436277322,-1628043327174614390095620802286856399277274247,-1058795307729955319256746357017277202924597536,1647620403823835898580119036145445721584451129,-123241927747452934984757753685795984657593930,-445672242624063036022259389581035096502293254,70659594429098734590418715111126748446091156,39508671506444537160482623431102153222427649], [1,-38916737668,1528799614490356,-2959843739298189104,150572195870418370016,-1887499327892869844416,10111591039381440766592,-24333285436127064356608,9015500577097486903296,83798762809040412580864,-175225989236014069346304,72431666294194247462912,184152647584566164135936,-277161654443569499160576,123482629056011438227456,28344410041864025210880,-47905841572526876590080,17103424167689825288192,-2096255434680407687168], [1,-1275747,575090691,-21949658774,205310705256,49953112230,-4602380202278,-1053036804867,33434535620298,15540401250227,-109588439593713,-70375383550812,174662374195533,138502456852110,-125360405379972,-123681682521918,23360045823231,40926121982052,7767192570581], [1,-191284643876,6341580163006836,-1934761696042349496,164849740308816714448,-4754806011233115697888,31297720637036736916912,40563063715135443568640,-447349624075426149585792,-106666893295835639752960,2465625625557089016418048,238299557470283831347200,-6723424858005364092543232,-1437413580211248751588352,9098140489377774130455552,4194676060685113931065344,-4594013743663310745149440,-3833217510275099671912448,-745788684857196104839168], [1,-11750704,1200072194,-27059115460,275329643437,-1507066331248,4350637026294,-3402695953616,-19674226511210,71635260352328,-81896826447748,-72414392799636,335995637293393,-374570043319420,6375222215324,412780308002080,-455545471094544,219580211621952,-41955549898176], [1,-205266599,3059043580551,-7377470986131672,255750467781184134,-1632953660152413431,1068348929913192629,15919951883702020817,-32949097618499452897,-41812738164568952022,160392472026537870106,-19845888168060926647,-288196883084542066323,200932996304757155217,155961581801981478736,-191793894011410484713,20117729114239674902,27921588898947726276,-6338062216813197688], [1,-45609411820,264233335559214594,-66441505779889023806,1651301768353913905227,-5702509244843790310454,-17718742162923383793609,94554646423607253705100,41437587470866244656495,-576600445583458394851654,185162070050586644716796,1716238691984098960776328,-1138541205600600045107878,-2575616331400632645628288,2165795832813798728006237,1728370435725705408915414,-1598090764684425326864451,-311652308942791826171932,277546280986572881143364], [1,-1504162,19478258228,-1774538541554,33455987402844,43770320753508,-1315720656188287,-2806299428446827,13190626459075508,39866462208944136,-42146184067179328,-226648796078997568,-47571258714568960,562561066722199040,515663033658126336,-448457920894472192,-815336848346726400,-205333486181974016,175547802745831424,85189809140924416,6179324718743552,-953640242118656], [1,-2914968254,729565958618632,-37698933666991280689,557592894223395782959240,-1616283511372600082985105238,97042988438726838461737336436,-232284398484404334687457106105,-6732183788640945316473023556024,-21348108851313726862647539943344,9922779856397149629502473433344,151080206871502990665840133664512,191217808340180216960353992423424,-216777783257003298753858212900864,-657568359287067519413657902383104,-264659148877840769934330259767296,519913318612345880722233221447680,525921319263424904995708534259712,19307792423762224049692793110528,-124791473356889212827540555563008,-16503846133252696483685908611072,10339744705904321576640217874432], [1,-480959,127971287,-6210024988,117387642442,-974058483871,2716073861918,7176144743881,-48663748603594,18221811396627,253842407160806,-280982367878873,-541503028206526,840715026571134,401195003303691,-937048907916075,29239682420856,364610731756647,-90373942881826,-27466833161452,8779464511312,-163262489641], [1,-39941932898,6210764439806586,-5769357270954813832,1526235405765947359933,-105496607496711652450502,450637888725327737131320,9650202211913359888961239,31737300783657595070950160,-10913973852576470640831520,-245106653555832534199738368,-427683566166591584370447360,43660237154569010897502208,877952103594834582382673920,792609270976277877255831552,-195542552331371677253369856,-644898095720832121314476032,-295879994185715924103856128,-3536321127891585200029696,19459832831021097932554240,1829846937231585372536832,7561943891893450440704], [1,-86337736,7598242460043,-167569983434765540,17305983969682532799,-292019419313169397092,2075131431123040068658,-6665424416191304282566,2295068132975694200659,52514343624238390352037,-155524020328280599942642,72098535485922177259119,502162464846325947972732,-1081612566036474720415173,329934201842389030200420,1737975836203010588034872,-2616168718135781832784509,780663560042069680589185,1552368103386097794485265,-1884069429357675284396666,861632370133018734294910,-149417527248961307018797], [1,-75050219,2577820557210,-8708771477008617,10240537455834038070,-4171566442262579317992,166242467088694549400458,-1033863257761812234666121,-8510117703992561276196134,-1712218241553391418046499,59073478059006844802989434,62496120000886690394671741,-133496170027675884289942785,-206919534061107404384206114,87453839145789156887240569,220760986134809816904048267,7507090977497795083539865,-78187519420065641576046009,-14126847417965732398061212,2838691415177922884136661,323334550937520096385754,-26940726295898710940521], [1,-17381757580476,43726977976046475,-38587155046755611490,14404264950505670063217,-1992519320820093070368720,21131148543713011874724917,-40503643542455943304425426,-221092172903838528916304883,686267541176044244116291476,934545360515028736247232153,-3842393422466848354481305014,-2297337276469143012081280444,10852822516123803157100624352,4469779496649171224523959382,-16461707981027715595966487388,-7275510508518637850373793095,11989066274939596734697677612,6820828079009357932513725593,-2377962517799535371613331494,-1864695755179413468652723812,-215224289114498638277938504], [1,0,57,0,1197,0,13681,0,136854,0,1048044,0,4603892,0,11460015,0,16001100,0,11131014,0,2739339,0,-368793,0,-7569], [1,0,0,0,-18,0,0,0,9], [-23708160,-225566208,-1131314688,-3968372736,-7276863744,-1112932224,22694392512,49279399488,50845741200,22483386864], [1,0,-2688,0,3413088,0,-2724744960,0,1535600481660,0,-650301043097664,0,215057090579702112,0,-56979500534544010752,0,12312194148189466704810,0,-2197264040603188502904000,0,326768343229764821604655296,0,-40745795222319658376664019968,0,4276794417515300890531785084048,0,-378647131200860936657636244230400,0,28286761991498448324281307379182240,0,-1780798310985522419497792899399649536,0,94205009985586665787286958769846028883,0,-4168270688350510971203431806915951526848,0,153256282053016072956650306840248729289280,0,-4641329002870144811569747153738728312276480,0,114452317987845573283355038818157554058821648,0,-2263985500383570937855397654604966209249105664,0,35234824323208949432122287222843195049195649184,0,-420671474677100937747713465131110877388775747840,0,3726806815195567658159272381046654302782322548810,0,-23439111687336557701224954796394993807990875876416,0,98647323369477358239247622147334076753681287255648,0,-257022322568849250028056718999196809455429653200128,0,377528109863340174709450199038785141413258084463900,0,-293678194586629498753778041508197163621948960832960,0,112835081178121597247315790519267337889550215700672,0,-17664834640659843760086846517563699616091492848896,0,464167528830919430707812939827867130195290216481], [1,0,-17229669740904638767885350393332951562413714341828385758128479090081583244187998208,0,-71235119005677090243907227200286049434393307742277600967494975973115889925067636736,0,-5259378713381781018295191965451438296538249792128869065118144857985370794902945792,0,-67185232557396629198034682141700718381157435991581841393585439368871735885394083840] ]; } B=8*10^4;for (j = 1, #v, print (j, "\tdisc = ", nfdisc([Pol(v[j]),B]))); \\ regression cases: nfdisc([x^64+2^16, 2]) { setrand(4); nfdisc([x^16+55217847968*x^14+11568829819230010799488*x^12+19573246544559873463135725971456*x^10+115798873240393273382017613115315418501120*x^8+9751010259434557755318401766641355472978476793856*x^6+2904119935452194825826787270394602800779367044985691045888*x^4+6769347776028701650273803177165355131571803342503490887843053568*x^2+63248430005730803250826766342470963758035727918152866840245543135870976,100]) } { \\ #682 setrand(3);nfdisc(x^16-60984*x^12+11303671896*x^8-20089501740000*x^4 +108519183506250000) } { nfdisc([x^24-550424160*x^22+23447555340004224*x^20-254383477518162636864000 *x^18+862812576554550932720517161472*x^16-1110768959838047114430666510009753 600*x^14+541867253550600812790187039808706018508800*x^12-8880986872306708993 8371545135871969866802135040*x^10+502809538666033468057546874414277270924367 6318040064*x^8-104322413758462359374825625780272604972404212502794076160*x^6 +694786520666433058606640970483690360770938934881316184784896*x^4-1330062293 022709810755455132342051017217797022292939901816012800*x^2+16121742882523614 4296369045049933195993063619592571720690380570624,100]) } { nfdisc(x^72-75690*x^66+2229471657*x^60-36061389458264*x^54+392606586400579 074*x^48+539504008591676523876*x^42-426714543074858418197350*x^36-4006505099 33584626955407768*x^30+394042536990878794791484268061*x^24-91837221214280331 370349672199754*x^18+6951526052977952270050730689115037*x^12+785336155384304 5069776294861433728*x^6+4160868820129268027225702088135675904) } f=x^3 - 17298759218009623610183566031041339386720075700346652258609213718601496711017550 61362121841699226629974891813971909562156420018402691827454215309735885355556958 2565670693186076986600637143595083773458690435867304359843677566038921950799648* x^2 + 18711064803260370378157988406301782093292956776803873824168436875360414402394604 63586013733720488993651052248629894449551488639706757608435718517657626971261696 197926369466104020743029503447382758370181747288622353407958575237402147782740*x - 12656647741002885497431100319705272363568484609743163724263941366068388136613989 08689606630749523725171680318089454979912662201922998310310302859164016403007659 6050019301107038128290274152242961922293776060278436798656129125675827400300576; 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=10^100+267; q=10^120+79; T=polcompositum(x^2-p,x^2-q)[1]; nfdisc([T,[2,p,q]]) \\#1710 nfdisc(x^10-29080*x^5-25772600) \\#1735 P=x^10-2*x^9+12*x^8-12*x^7-181*x^6-4*x^5-6899*x^4+9780*x^3+6360*x^2+702*x-45; setrand(3); nfdisc(P) setrand(138); nfdisc(P) pari-2.7.5/src/test/in/select0000644000175000017500000000043612573110466014474 0ustar billbillselect(isprime, vector(50,i,i^2+1)) select(isprime, List([1,2,3,4,5]), 1) 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] v=Vecsmall([1,2,3]); select(x->x,v,1) select(x->x,v) pari-2.7.5/src/test/in/stark0000644000175000017500000000165412366172547014354 0ustar billbillallocatemem(20*10^6) v=[321,520,577,840,904,1009,1129,1229,1297,1509,1901,1937,2305,2584,2920,3281,2^15-199]; for(i=1, #v, print(v[i]": "quadhilbert(v[i]))) { v = [ [y^2-145,1], [y^2-229,1], [y^2-401,1], [y^2-577,1], [y^2-761,1], [y^3-y^2-17*y-16,1], [y^3-14*y-7,1], [y^3-y^2-16*y+22,1], [y^3-36*y-45,1], [y^3-21*y-35,1], /* tougher: */ [y^3-12*y-1,1], [y^3-y^2-17*y-16,1], [y^3-y^2-30*y-27,1], [y^3-14*y-7,1], [y^3-y^2-16*y+22,1], [y^3-y^2-30*y+71,1], [y^3-y^2-16*y-6,1], [y^3-36*y-45,1], [y^3-12*y-1,[5,y+1]], [y^3-y^2-37*y+64,1], [y^3-y^2-9*y+8,1], [y^3-21*y-35,1], [y^3-y^2-16*y+8,1], [y^3-y^2-4*y-1,7], [y^3-y^2-7*y+6,[29,y-13]] ]; } do(w) = { my(mod, bnf); mod = w[2]; bnf = bnfinit(w[1]); if (type(mod) == "t_VEC", mod = idealhnf(bnf, mod[1], mod[2])); bnrstark(bnrinit(bnf, mod, 1), 0); } for(i = 1, #v, print(v[i]": "do(v[i]))); \\ quadray(31897,1) bnrstark(bnrinit(bnfinit(quadpoly(40,y)),120,1),matdiagonal([1,1,2,2])) pari-2.7.5/src/test/in/subst0000644000175000017500000000101712366172547014361 0ustar billbillx; y; p; q; subst(Y/X,X,x) substvec(x+y,[x,y],[1,x]) \\ #1321 v = [p + w*q, w*p + q] * Mod(1, w + 1); substvec(x+y, [x, y], v) \\ #1447 subst(O(x^2),x,0*x) subst(x+O(x^2),x,Mod(1,3)) subst(x+O(x^2),x,Mod(0,3)) subst(1/x+O(x^2),x,Mod(0,3)) subst(2+x+O(x^2),x,Mod(0,3)) substpol(x,1/x,y) substpol(Mod(x*y^2, y^3*x^2+1), y^2,y) substpol(x*y^2/(y^3*x^2+1), y^2,y) substpol(List(), y^2,y) substpol(List(x^2*y^2), y^2,y) substpol(x^2+y^3*x^3+O(x^4),y^2, y) subst(1,x,[;]) subst(1,x,Mat([1,2])) subst(x^2+x^3+O(x^4),x, 2*y+O(y^2)) pari-2.7.5/src/test/in/zn0000644000175000017500000000177712515252551013653 0ustar billbillznprimroot(2) znprimroot(4) znprimroot(8) p=9223372036854775837; znprimroot(p) znprimroot(p^2) znprimroot(2*p^2) znprimroot([2,1;p,2]) znprimroot([2*p^2,[2,1;p,2]]) znstar(0) znstar(1) znstar(10) znstar(14) znstar(247) znstar(-247) znstar(factor(-247)) znstar(factor(0)) Mod(10,148)^(2^64) do(n)= { g = Mod(3,n); phi = eulerphi(n); G = g^(phi-1); o = znorder(g, phi); fo = factor(o); [znlog(G,g), znlog(G,g,o), znlog(G,g,fo), znlog(G,g,[o,fo])]; } do(2^5*5^3*7) 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(6,Mod(2,7),znorder(Mod(2,7))) znlog(3,Mod(3,8),znorder(Mod(3,8))) znlog(5,Mod(2,401)) znlog(7,3+O(2^3)) znlog(7,3+O(2^3), znorder(Mod(3,8))) znlog(7,3+O(7^3)) znlog(2,3+O(7^3)) { for (i = 1,10^4, d = eulerphi(i); if (!istotient(d, &n) || eulerphi(n) != d, error(i))) } Mod(1,2)-Mod(2,4) p=2^80+13; znlog(Mod(3,p),Mod(2,p)) g=Mod(3,11); v=[I,-1,Mat(1),matid(2)/2,Mat([5,1])]; a=Mod(-1,11); for(i=1,#v, print(iferr(znlog(a,g,v[i]),E,E))); pari-2.7.5/src/test/in/characteristic0000644000175000017500000000031712366172547016213 0ustar billbillv=[1,1.,Mod(1,6),1/2,I+Mod(1,3), O(2), quadgen(5)*Mod(1,3), Mod(1,x)]; for (i=1,#v, print(characteristic(v[i]))) characteristic(v) characteristic(matid(2)*Mod(1,2)) characteristic([]) characteristic(List()) pari-2.7.5/src/test/in/history0000644000175000017500000000015512366172547014724 0ustar billbill2 3 4 5 %`````` %```` %3 % %#3 < 5 %#``` < 5 %# < 5 default(histsize,1) 1; %`` default(histsize,10) %`` %13 pari-2.7.5/src/test/in/debugger0000644000175000017500000000103512366172547015005 0ustar billbill\e default(breakloop,1) my(bound=100,step=20,halt=41); check(B)= { my(bi=[B^2]); for(i=1,bound, my(p=i+step,N=p^2); if(i==halt,error("check:",N))) } check(1000); [bound, step, halt, i, p, N, bi, B] break [bound, step, halt, i, p, N, bi, B] my(p=120);for(i=1,100,1/0) [p,i] dbg_err() break fun(N)=check(N^2+1); fun(20); N dbg_up(4) N break f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); f(221,3) z z iferrname("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) i break f()=1/0 f(); allocatemem(10^7) for(i=1,10,if(i==2,1/0)); i break pari-2.7.5/src/test/in/chinese0000644000175000017500000000026712366172547014645 0ustar billbillchinese(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)]) pari-2.7.5/src/test/in/ellweilpairing0000644000175000017500000000371712405547147016235 0ustar billbillweil(E,P,Q,m,p)=lift(ellweilpairing(E,P,Q,m)); tate(E,P,Q,m,p)=if(p%m!=1,return(0));lift(elltatepairing(E,P,Q,m)^((p-1)/m)); check(v,P,Q,m,p)= { my (E=ellinit(v*Mod(1,p))); P*=Mod(1,p); Q*=Mod(1,p); print([weil(E,P,Q,m,p),tate(E,P,Q,m,p),ellgroup(E)]); } check([0,0,1,0,0],[0,0],[57,46],3,103) check([0,0,1,0,0],[64,63],[0,0],3,109) check([0,0,1,0,0],[0,0],[150,32],3,151) check([0,0,1,0,0],[0,156],[13,144],3,157) check([0,0,1,0,0],[0,0],[59,58],3,163) check([0,0,1,0,0],[192,84],[0,192],3,193) check([0,0,1,0,0],[198,92],[0,0],3,199) check([0,0,0,1,0],[1,51],[72,9],4,113) check([0,0,0,1,0],[88,56],[1,31],4,137) check([1,0,0,0,3],[13,6],[147,89],4,149) check([0,0,1,0,0],[5,58],[36,128],4,157) check([0,0,1,0,3],[30,1],[26,1],5,31) check([0,0,1,0,0],[58,107],[22,76],6,109) check([0,0,1,0,0],[90,4],[32,1],6,127) check([0,0,1,0,0],[138,60],[62,155],6,157) check([0,0,0,1,0],[47,53],[160,147],7,197) check([0,0,0,1,0],[50,80],[16,65],8,113) check([1,0,0,0,3],[25,82],[23,49],8,149) check([0,0,1,0,0],[10,67],[88,35],9,127) check([0,0,1,0,0],[102,32],[87,55],9,163) check([0,0,1,0,0],[12,11],[17,5],9,19) check([0,0,1,0,0],[190,47],[194,169],9,199) check([0,0,0,1,0],[28,34],[22,11],10,137) check([0,0,0,1,0],[94,84],[10,142],10,157) check([0,0,0,1,0],[159,29],[115,100],14,197) check([0,0,0,1,0],[154,21],[58,126],15,157) check([0,0,0,1,0],[121,63],[121,64],16,127); check([0,0,0,1,0],[18,104],[177,153],16,191); check([0,0,1,0,0],[16,56],[16,56],2,113); check([0,0,1,0,0],[66,63],[66,63],2,127); check([0,0,1,0,0],[126,78],[89,78],2,157); check([0,0,1,0,0],[150,89],[150,89],2,179); check([0,0,1,0,0],[22,95],[22,95],2,191); check([0,0,0,1,3],[4,1],[4,6],6,7); t=ffgen(Mod(1,2)*(t^6+t^5+t^3+t^2+1)); E=ellinit([0,0,1,0,0],t); P=[t^2+t+1,t+1]; Q=[t^5+t^3+t^2,t^5+t^4+t^3+t^2+t+1]; ellweilpairing(E,P,Q,3) elltatepairing(E,P,Q,3) test(p) = { forvec(v=vector(5,i,[0,p-1]), E=ellinit(v*Mod(1,p)); if (!#E, next); G=ellgroup(E);if(#G>1,print(v,":",G)), ); } test(3); test(5); pari-2.7.5/src/test/in/ideal0000644000175000017500000000340212405547147014273 0ustar billbillQi = nfinit(x^2+1); idealintersect(Qi,0,1) Q = nfinit(y); idealaddtoone(Q,1,[;]) idealaddtoone(Q,2,[;]) idealaddtoone(Q,[;],[;]) idealaddtoone(Q,[;],1) idealaddtoone(Q,[1,[;]]) idealaddtoone(Q,[1,[;],Mat(1/2)]) ideallog(Q,2,idealstar(Q,4,1)) idealstar(Qi,matdiagonal([6,12])) P = idealprimedec(Qi,2)[1]; idealprincipalunits(Qi,P,10) idealintersect(Qi, 1/2,1/2) ideallog(Q,1/2,idealstar(Q,3,1)) K=nfinit(x^2-236*x+13384);\\ Q(sqrt(60)), in disguise idealhnf(K, qfbprimeform(60,2)) K=nfinit(x^3-2); u=nfalgtobasis(K,x);v=nfalgtobasis(K,x^2); idealhnf(K,Mat([u,v])) idealhnf(K,1/4,1/6) idealhnf(K,4,[6,0,0]~) idealhnf(K,2,1/6) idealhnf(K,1/3,u/2) idealhnf(K,u,v/2) P = idealprimedec(K,5); idealval(K,P[1],P[2]) idealval(K,P[2],P[1]) idealval(K,P[2],P[2]) P[1][2] += 5; idealval(K,P[1],P[1]) idealmul(K,P[1],P[1].gen[2]) idealnorm(K,P[1]) idealinv(K,Mod(x,K.pol)) idealpow(K,idealhnf(K,x),-2) v=[1,1/2,x,Mod(x,K.pol),P[1],[;],Mat(1),vector(5),[1,2,3;4,5,6;7,8,9],[1,2,3;0,4,5;0,0,6],I]; for(i=1,#v, if(!nfisideal(K,v[i]),print(i))) idealred(K,2) idealred(K,[2,[;]]) nf=nfinit(x^2+x+1); p = 67452192952521724999; pi = idealprimedec(nf,p)[1]; q = 762234946175168528650011228121; qi = idealprimedec(nf,q)[1]; f=idealfactor(nf, idealdiv(nf,pi,qi)) id=idealfactorback(nf,f) idealnumden(nf,id) idealnumden(nf,pi) idealnumden(nf,1) idealnumden(nf,1/2) idealnumden(nf,x/2) nffactorback(nf, [3, x+1, [1,2]~], [1, 2, 3]) test(nf,F,v)= { my(Y = idealchinese(nf,F,v), P = F[,1], E = F[,2]); for (i=1,#P, if( nfeltval(nf, nfeltadd(nf,v[i],-Y),P[i]) < E[i], error(i))); Y; } v = [x,0,[0,1/7^4]~,Mod(x,nf.pol)]; F = idealfactor(nf, 2*3*7); F[,2] *= 3; test(nf,F,v) F[,2] = [0,1,-2,3]~; 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]) K=nfinit(2*x^2+1); idealprimedec(K,2) pari-2.7.5/src/test/in/extract0000644000175000017500000000213112405547147014665 0ustar billbillA=vector(100,i,i); for(i=35,99, print1(vecextract(A,1<f(x,4)); test(x->f(x,-4))) | f <- fun]; test(x->component(x,2)); test(x->component(x,10)); test(x->polcoeff(x,-1)); test(x->polcoeff(x,2)); test(x->polcoeff(x,10)); polcoeff(O(x),0) s=x*(y+O(x))+y; polcoeff(s,0,y) polcoeff(s,1,y) s=y+O(y^2); polcoeff(s,0,x) polcoeff(s,1,x) vecextract(Vecsmall([3,4,5]),[2,3,1]) pari-2.7.5/src/test/in/matsnf0000644000175000017500000000173512405547147014514 0ustar billbillminpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]) minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]/3) minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]/a) 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]) { for(i=1,15, print(matfrobenius(matrix(i,i,k,j,k>=j),2))); for(i=1,10, print(matfrobenius(matpascal(i),2))); for(i=1,8, print(matfrobenius(mathilbert(i),2))); } matsnf(matdiagonal([x,0,x]), 2) matsnf(matdiagonal([1+x,0,x]), 2) \\Bug #1208 matsnf([0;1;2], 4) matsnf([0;1;2], 5) matsnf(Mat([0,1,2]), 4) matsnf(Mat([0,1,2]), 5) m=[2*x^6+x^5+2*x^4+2*x^3+x^2+2*x+2,2*x^5+x^3+2*x^2+2,x^3+x^2+x;2*x^6+x^3+x+2,2*x^5+2*x^4+x^3+2*x,x^3+2*x^2+2*x;2*x^6+x^4+x^3+2*x^2+2,2*x^5+2*x^4+2*x^3+x^2+2,x^3+2*x^2+x+2];matsnf(m*Mod(1,3), 2) pari-2.7.5/src/test/in/krasner0000644000175000017500000000064412405547147014667 0ustar billbillallocatemem(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); do(p,N,flag)=filter_output(p, padicfields(p,N,flag)); 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(2, [8,12], 1) padicfields(2^64+13, 8, 2) do(2^64+13, 2, 1) do(2, 4, 1) pari-2.7.5/src/test/in/gcdext0000644000175000017500000000411712413013143014456 0ustar billbill{ a=[0,0*x,O(5^3),2,2+O(5^3),x]; for(i=1,#a, for(j=1,#a, print(gcdext(a[i],a[j])))); } gcdext(-1/3*x - 5/9,-x - 5/3) z;T; FF=Mod((O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^7+((2+2^3+O(2^4))*T^3+O(2^4)*T^2+(1+2+O(2^4))*T+(1+2^2+O(2^4)))*z^6+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^5+((1+2+2^3+O(2^4))*T^3+(1+2+2^2+2^3+O(2^4))*T^2+(2+2^3+O(2^4))*T+(1+2^2+2^3+O(2^4)))*z^4+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^3+((2+2^2+2^3+O(2^4))*T^3+(1+2^2+2^3+O(2^4))*T^2+O(2^4)*T+(1+2+2^2+2^3+O(2^4)))*z^2+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z+((1+2^3+O(2^4))+(1+2^2+2^3+O(2^4))*T+(2+2^2+2^3+O(2^4))*T^2+(1+2+2^3+O(2^4))*T^3+O(T^20)),(1+O(2^4))*z^8+(1+O(2^4))); GG=Mod((O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^7+((2+2^3+O(2^4))*T^3+O(2^4)*T^2+(1+2+O(2^4))*T+(1+2^2+O(2^4)))*z^6+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^5+((1+2+2^3+O(2^4))*T^3+(1+2+2^2+2^3+O(2^4))*T^2+(2+2^3+O(2^4))*T+(1+2^2+2^3+O(2^4)))*z^4+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^3+((2+2^2+2^3+O(2^4))*T^3+(1+2^2+2^3+O(2^4))*T^2+O(2^4)*T+(1+2+2^2+2^3+O(2^4)))*z^2+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z+((1+2^3+O(2^4))+(1+2^2+2^3+O(2^4))*T+(2+2^2+2^3+O(2^4))*T^2+(1+2+2^3+O(2^4))*T^3+O(T^20)),(1+O(2^4))*z^8+(1+O(2^4))); AA=truncate(lift(lift(FF))); BB=truncate(lift(lift(GG))); gcdext(AA,BB) gcd(x*Mod(1,7),x*Mod(1,7)) gcd(2*I, 1+I) gcd(I*1., I+1.) gcd(1+O(2),1+O(3)) gcd(2+O(2^2),4+O(2^3)) w=quadgen(5); gcd(w,2*w) gcd(2*w,w) gcd(2,Mod(2,4)) gcd(1/2,Mod(2,4)) gcd(1/3,Mod(2,4)) gcd(Mod(2,4), 2+O(2^3)) gcd(Mod(2,5), I) gcd(Mod(2,5), w) gcd(1/2, 1/(I+1)) gcd(1/2, 2+O(2^3)) gcd(I, 2+O(2^3)) gcd(I, w) gcd(w, 2+O(2^3)) t = Mod(x^2,x^3); gcd(t,y) gcd(t,x) gcd(t,1/y) gcd(t,1/x) gcd(t,1/(x+1)) gcd(Pol(0), y) gcd(x+O(x^5), x^2+O(x^3)) gcd(x+O(x^5), 1/x^2) v=[1,2,1.,Mod(1,2),1/2,1/3,2/3,I,quadgen(5), 1+O(2),2+O(2^2),1/2+O(2)]; { t1=ffgen(2^3); t0=0*t1; t2=ffgen(3^3); for (i=1,#v, print(iferr(gcd(t0,v[i]),E,E)); print(iferr(gcd(t1,v[i]),E,E)); print(iferr(gcd(t2,v[i]),E,E)); ) } gcd(0,1.+I) gcd(0,1+I) gcd(0,Mod(1,3)+I) gcd(1/2, 1.+I) default(realprecision,38); gcd(Pol(0.),x) (k+1.)/k - (2*k+1.)/k gcd(1/(2^64*y),Mod(x^2,2^64*x^3)) pari-2.7.5/src/test/in/ell0000644000175000017500000001471112456454707014003 0ustar billbilldefault(realprecision,38); ellap(ellinit([1,0,1,4,-6]), 2) ellap(ellinit([0,17]), 2) ellap(ellinit([0, 0, 1, -1, 0]),2486246173) testgroup(v,p)= { my(E,F,G,g); E=ellinit(v); if(!E || E.disc%p==0, next); E[13] = 0; /*allow singular curves*/ G=ellgroup(E,p,1); if (G.no == 1, return); g=G.gen; if (!ellisoncurve(E,g), error(E, G)); F=vector(#g,i, ellorder(E,g[i],G.no)); if ((p <= 3 && F!=G.cyc) || (p > 3 && F[1] != G.cyc[1]), print("error:",v,":",F,":",G)); } { for(x=10,63, my(p,E,G,g); p=nextprime(2^x);E=ellinit([0,0,1,2,3]); G = ellgroup(E,p,1); if (!ellisoncurve(E,G.gen), error(E)); if(ellorder(E,G.gen[1])!=G.cyc[1], error(E)); print(p,":",ellgroup(E,p))); for(p=2,3, forvec(v=vector(5,i,[0,p-1]), testgroup(v,p))); forvec(v=vector(2,i,[0,4]), testgroup(v,5)); } setrand(1) a=ffgen(2^8,'a); E=ellinit([a,1,0,0,1]); P=[a^3,ellordinate(E,a^3)[1]]; Q=ellmul(E,P,113); e=elllog(E,P,Q,242) ellmul(E,Q,e) == P ellpow(E,Q,e) == P p=655637; E=ellinit([123,47], p); X=1;until(Y!=[],X++;Y=ellordinate(E,X)); P=[X,Y[1]]; Q=ellmul(E,P,113); o=ellorder(E,P, p+1-ellap(E,p)) e=elllog(E,P,Q,o) ellmul(E,Q,e) == P p=1073741827; E=ellinit([1,3], p); G=[Mod(1050932506,p),Mod(12325986,p)]; P=ellmul(E,G,1023); 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 ellinit(ellfromj(1728)).j ellinit(ellfromj(j)).j ellinit(ellfromj(Mod(0,2))).j ellinit(ellfromj(Mod(0,5))).j ellinit(ellfromj(Mod(3,5))).j ellinit(ellfromj(j*Mod(1,2))).j 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,4,5]); e.eta E = ellchangecurve(e, [2,3,4,5]); E.eta e = ellinit([1,2,3,4,5]); e.eta; e.roots; E = ellchangecurve(e, [2,3,4,5]); E.omega E.eta E.roots ellglobalred(E) ellglobalred(e) E = ellchangecurve(e, [1,0,0,0]); E = ellchangecurve(e, [2,3,4,5]*Mod(1,7)); E.omega E.group ellminimalmodel(ellinit([1/5,1/4,1/3,1/2,1],1),&v) v j=ffgen(2^5,'a);e = ellinit(ellfromj(j)); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[3,7,1,0]); E.group e = ellinit(ellfromj(Mod(1,3))); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[2,7,1,0]); E.group e = ellinit(ellfromj(Mod(1,5))); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[2,7,1,0]); E.group e = ellinit(ellfromj(1/3), O(3^5)); e.tate e.roots E = ellchangecurve(e,[3,1,1,2]); E.tate iferr(ellztopoint(e,3),E,E) e = ellinit(ellfromj(11/8), O(2^5)); e.tate \\#1185 ellwp(ellinit([0,-1,1,-10,-20]),x+O(x^12)) \\#1186 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) u = [e,w,w2]; { for (i = 1, #v, my(f = v[i]); for (j = 1, #u, my (a = u[j]); print([i,j]); print(f(a)); print(f(a, x+O(x^10))); print(f(a, 1/3)); print(f(a, I/3)); print(f(a, (1+I)/3)); ) ) } elleta(e) elleta([1,I]) v = [x->elleisnum(x,2),x->elleisnum(x,4,1),x->elleisnum(x,6,1),x->elleisnum(x,10)]; { for (i = 1, #v, my(f = v[i]); print(f); print(f(e)); print(f(w)); print(f(w2)); ) } \\ #1257 ellrootno(ellinit([0,-1,1,217,-282])) \\ #1296 e=ellinit([0,-1,0,-33,62]); 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]; ellztopoint(e,ellpointtoz(e,[x,y])) e=ellinit([0,-1,1,0,0], O(11^5)); ellpointtoz(e,[0,0]) e=ellinit([1,1,1,-10,-10], O(3^5)); ellpointtoz(e,[3,-2]) e=ellinit(ellfromj(2/9), O(3^10)); x=2; y=ellordinate(e,x)[1]; ellpointtoz(e,[x,y]) e=ellinit(ellfromj(1/4), O(2^10)); x=1/2; y=ellordinate(e,x)[1]; ellpointtoz(e,[x,y]) ellinit([1,1], Mod(1,11)) ellrootno(ellinit([31^4,31^6]), 31) e=ellinit([1,0,0,1,1]); ellordinate(e, I) E=ellchangecurve(e,[1/(2^4*3^4*5^2*7),2,3,4]); forprime(p=2,11, if (ellap(e,p) != ellap(E,p),error(p))); for(k=2,50, if (ellak(e,k) != ellak(E,k),error(k))); if (ellan(e,100) != ellan(E,100),error("ellan")); P=ellchangepoint([0,1],[1,2,3,4]) ellchangepointinv(P,[1,2,3,4]) \\#1416 E=ellinit([155818018413/16,-78179511999813417/32]); ellminimalmodel(E,&v); E2=ellchangecurve(E,v); ellminimalmodel(E2,&w); w \\#1432 E=ellinit([-3,-60,480,0,0]); ellheight(E,[0,0]) e=ellminimalmodel(ellinit([1,1])); e=ellchangecurve(e,1) e=ellchangecurve(e,[2,0,0,0]) ellinit(ellinit([0,1]*Mod(1,5),ffgen(5^2))); J=[0,1728,-3375,8000,54000,-32768,287496,-884736,-12288000,16581375,-884736000,-147197952000,-262537412640768000]; { for (i=1,#J, my(e = ellinit(ellfromj(J[i]))); my(v = ellan(e,200)); print("\n", e.j); forprime(p = 127, 200, print1(v[p]," ")) ); } p=2^32+15; 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]) elladd(E,[0.,125.],[0.,125+1e-38]) iferr(ellmul([0,1,0,2,-15],[2,1],5),E,E) x='x; E=ellinit([x^2,x]) ellminimalmodel(E) ellweilpairing(E,[0],[0],1) ellinit([1]) ellinit([1,1],quadgen(5)) ellinit([Mod(1,2),1],O(2)) ellinit([O(2),1],ffgen(2^3)) ellinit([O(2),1],1.) ellinit([1,2],1.) ellinit([ffgen(5),1],5) ellinit([ffgen(5),1],3) ellinit([1.,1],precision(1.,60)) ellinit([1.,Mod(1,3)]) \\#1527 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) ellzeta(E) ellsigma(E) E=ellinit([0,0,0,Mod(1,1009),0]); ellwp(E) ellzeta(E) ellsigma(E) \\#1558 ellap(ellinit([-1137195,489565862]),2038074751) ellap(ellinit([582304190,64196421]),2147438927) pari-2.7.5/src/test/in/linear0000644000175000017500000000512112366172547014473 0ustar billbillHEAP=[98, if(precision(1.)==38,10174,10354)]; default(realprecision,38); \e algdep(2*cos(2*Pi/13),6) algdep(2*cos(2*Pi/13),6,15) charpoly([1,2;3,4],z) charpoly(Mod(x^2+x+1,x^3+5*x+1),z) charpoly([1,2;3,4],z,1) charpoly(Mod(1,8191)*[1,2;3,4],z,2) lindep(Mod(1,7)*[2,-1;1,3]) lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)]) lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14) matadjoint([1,2;3,4]) matcompanion(x^5-12*x^3+0.0005) matdet([1,2,3;1,5,6;9,8,7]) matdet([1,2,3;1,5,6;9,8,7],1) matdetint([1,2,3;4,5,6]) matdiagonal([2,4,6]) mateigen([1,2,3;4,5,6;7,8,9]) mathess(mathilbert(7)) mathilbert(5) amat=1/mathilbert(7) mathnf(amat) mathnf(amat,1) mathnf(amat,4) mathnf(amat,5) mathnfmod(amat,matdetint(amat)) mathnfmodid(amat,123456789*10^100) matid(5) matimage([1,3,5;2,4,6;3,5,7]) matimage([1,3,5;2,4,6;3,5,7],1) matimage(Pi*[1,3,5;2,4,6;3,5,7]) matimagecompl([1,3,5;2,4,6;3,5,7]) matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) matindexrank([1,1,1;1,1,1;1,1,2]) matintersect([1,2;3,4;5,6],[2,3;7,8;8,9]) matinverseimage([1,1;2,3;5,7],[2,2,6]~) matisdiagonal([1,0,0;0,5,0;0,0,0]) matker(matrix(4,4,x,y,x/y)) matker(matrix(4,4,x,y,sin(x+y))) matker(matrix(4,4,x,y,x+y),1) matkerint(matrix(4,4,x,y,x*y)) matkerint(matrix(4,4,x,y,x*y),1) matkerint(matrix(4,6,x,y,2520/(x+y))) matmuldiagonal(amat,[1,2,3,4,5,6,7]) matmultodiagonal(amat^-1,%) matpascal(8) matrank(matrix(5,5,x,y,x+y)) matrix(5,5,x,y,gcd(x,y)) matrixqz([1,3;3,5;5,7],0) matrixqz([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0],-1) matrixqz([1,3;3,5;5,7],-2) matsize([1,2;3,4;5,6]) matsnf(1/mathilbert(6)) matsnf(x*matid(5)-matrix(5,5,j,k,1),2) matsolve(mathilbert(10),[1,2,3,4,5,6,7,8,9,0]~) matsolvemod([2,3;5,4],[7,11]~,[1,4]~) matsolvemod([2,3;5,4],[7,11]~,[1,4]~,1) matsupplement([1,3;2,4;3,6]) mattranspose(vector(2,x,x)) %*%~ norml2(vector(10,x,x)) qfgaussred(mathilbert(5)) qfjacobi(mathilbert(6)) m=1/mathilbert(7) mp=concat(m,matid(7)) qflll(m) qflllgram(m) qflllgram(m,1) qflllgram(mp~*mp,4) qflll(m,1) qflll(m,2) qflll(mp,4) qfminim([2,1;1,2],4,6) qfperfection([2,0,1;0,2,1;1,1,2]) qfsign(mathilbert(5)-0.11*matid(5)) trace(1+I) trace(Mod(x+5,x^3+x+1)) Vec(sin(x)) vecmax([-3,7,-2,11]) vecmin([-3,7,-2,11]) concat([1,2],[3,4]) concat(Mat(vector(4,x,x)~),vector(4,x,10+x)~) vecextract([1,2,3,4,5,6,7,8,9,10],1000) vecextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y)) round((1.*mathilbert(7))^(-1) << 77) / 2^77 vecsort([8,7,6,5],,1) vecsort([[1,5],[2,4],[1,5,1],[1,4,2]]) vecsort(vector(17,x,5*x%17)) 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]) vector(10,x,1/x) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/logint0000644000175000017500000000015112366172547014513 0ustar billbilllogint(2^99,2) logint(2^100,2,&z) z logint(5^100,2,&z) z logint(5^100,3) logint(5^100,4) logint(5^100,5) pari-2.7.5/src/test/in/graph0000644000175000017500000000154612366172547014331 0ustar billbillHEAP=[31, if(precision(1.)==38,282,296)]; default(realprecision,38); \e plotinit(0,500,500) plotmove(0,0,0);plotbox(0,500,500) plotmove(0,200,150) plotcursor(0) psdraw([0,0,0]) plotinit(1,700,700) plotkill(1) 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=-5,5,sin(x),-1,1) plotpoints(0,225,334) plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) psdraw([0,20,20]) psploth(x=-5,5,sin(x)) psploth(t=0,2*Pi,[sin(5*t),sin(7*t)],1,100) psplothraw(vector(100,k,k),vector(100,k,k*k/100)) plotmove(0,50,50);plotrbox(0,50,50) plotrline(0,200,150) plotcursor(0) plotrmove(0,5,5);plotcursor(0) plotrpoint(0,20,20) plotinit(3,600,600);plotscale(3,-7,7,-2,2);plotcursor(3) plotmove(0,100,100);plotstring(0,Pi) plotmove(0,200,200);plotstring(0,"(0,0)") psdraw([0,10,10]) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/prec0000644000175000017500000000102312366172547014147 0ustar billbillprecision(I,3) precision(1+O(3)+I,3) precision(O(2),3) precision(1+O(2),3) precision(x+1+O(3),3) precision((1+O(3))/((1+O(5))*x),3) precision(Mod(1+O(3),(1+O(3))*x),3) precision([1+O(3),2],3) default(realprecision,38); t=(precision(1.,77)*x+1); precision(t) precision(1./t) precision(Qfb(1,0,-2)); padicprec(1,2) == padicprec(0,2) padicprec(1/2,2)== padicprec(0,2) padicprec(Mod(1,9),3) padicprec(O(2^2),3) padicprec(O(2^2),2) t=1+O(2^3); padicprec(t,2) padicprec((x+2)*t, 2) padicprec((1+2*x+O(x^2))*t, 2) padicprec([2,4]*t, 2) pari-2.7.5/src/test/in/charpoly0000644000175000017500000000275512366172547015054 0ustar billbillcharpoly([x,x+1;1,2],y,0) charpoly([x,x+1;1,2],y,1) charpoly([x,x+1;1,2],y,2) charpoly([x,x+1;1,2],y,3) charpoly([0,0,2,2;0,0,2,2;2,2,0,0;2,2,0,0]) charpoly([0,0,2,2;0,0,2,2;2,2,0,0;2,2,0,0],,4) minpoly(matrix(4,4,i,j,i/j)) default(realprecision,38); A=[5/3,7/45;0,21/10]; mateigen(A) mateigen(A*1.) mateigen(A,1) M=[x,x+y;x+1,1];charpoly(M,w) v=[1,1.,Mod(1,3),1/2,1+O(3),I,quadgen(5),matid(2)*Mod(1,3),matid(2)*Mod(1,2^64+13)]; for(i=1,#v,print(charpoly(v[i]))) charpoly(matid(4),,0) charpoly(matid(4),,3) charpoly(matid(4)*(2^64+13)) m=[1,2,3,4;5,6,7,8;9,10,11,12;1,5,7,11]; charpoly(m*Mod(1,3)) charpoly(m*Mod(1,2^64+13)) matadjoint(matid(2),1) matadjoint([;]) matadjoint(Mat(1)) matadjoint([x,0,0;0,0,0;0,0,0]) matadjoint([Mod(1,2)*x,0,0;0,0,0;0,0,0]) charpoly(x*matid(3)) minpoly(Mod(x+1,x^4+1)) minpoly(Mod(x,x^2)) a=[1,0,0,-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;0,0,1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0;-1,-1,-1,4,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,0,1,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,0,0,-1,-1,-1,4,-1,0,0,0,0,0,0,0,0;0,0,0,-1,0,0,0,-1,4,-1,-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,-1,0,4,-1,-1,-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,0,0,0,-1,0,1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,-1,0,0,3,-1,0,-1;0,0,0,0,0,0,0,0,0,0,0,0,0,-1,3,-2,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,2,0;0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,1]; mateigen(a); mateigen([;]) mateigen([;],1) mateigen(Mat(1)) mateigen(Mat(1),1) pari-2.7.5/src/test/in/sumdedekind0000644000175000017500000000013412366172547015514 0ustar billbillsumdedekind(-2,-3) sumdedekind(2, 4) sumdedekind(123186,28913191) sumdedekind(2^64+1, 2^65) pari-2.7.5/src/test/in/parallel0000644000175000017500000000215212366172547015016 0ustar billbillV=[2^256 + 1, 2^193 - 1]; parapply(factor,V) my(V=[2^256 + 1, 2^193 - 1]); parvector(#V,i,factor(V[i])) fun(V)=pareval(vector(#V,i,()->factor(V[i]))); fun(V) parfirst(fun,V)=parfor(i=1,#V,fun(V[i]),j,if(j,return([i,j]))); parfirst(isprime, [2^600..2^600+1000])[1] parselect(isprime, [2^600..2^600+1000],1) parselect(isprime, [2^600..2^600+1000]) /* Disable tests that depends on ellsea findp(E,n)= { my(check(p) = my(c=ellcard(E,p)); if(isprime(c),c,0)); parforprime(p=2^n,,check(p),card,if(card,return([p,card]))); } my(E=ellinit([1,3])); findp(E,80) */ inline(ell,ell2); ell(a,B,N)=my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellpow(E,[0,1]*Mod(1,N),B); ecm(N,t,B)= iferr(parvector(t,a,ell(a,B,N)),err,gcd(lift(component(err,2)),N),errname(err)=="e_INV"); ecm(2^101-1,500,600!) ell2(a,B,N)=iferr(ell(a,B,N),err,return(gcd(lift(component(err,2)),N)),errname(err)=="e_INV");0; ecm2(N,t,B)=my(z);parfirst(a->ell2(a,B,N),[1..t])[2]; ecm2(2^101-1,500,600!) uninline(); inline(chkell); chkell(n)=a->my(E=ellinit([1,0,0,0,ffgen(2^n)^a]),N=ellcard(E)/4);if(isprime(N),N); ellp(n)=parfirst(chkell(n),[1..10000]); ellp(128) uninline(); pari-2.7.5/src/test/in/bnrL10000644000175000017500000000064012612420416014161 0ustar billbilldefault(realprecision,38); K=bnfinit(x^2+31);bnrL1(bnrinit(K,1,1)) K=bnfinit(x^2-3); bnrL1(bnrinit(K,5,1),,5) bnrL1(bnrinit(K,[5,[1,0]],1),,5) bnrL1(bnrinit(K,[5,[1,1]],1),,5) K=bnfinit(x^2-168);\\#1601 bnrL1(bnrinit(K,[6,[1,1]],1),,5) P=x^5-x^4-5*x^3+4*x^2+3*x-1; S=x^10-26*x^8+233*x^6-832*x^4+1024*x^2-401; bnf=bnfinit(a^2-401*25); cond=rnfconductor(bnf,P); bnr=bnrinit(bnf,cond[1],1); real(bnrL1(bnr,cond[3],1)) pari-2.7.5/src/test/in/sumdiv0000644000175000017500000000223112526672541014524 0ustar billbilln = 10!; fa = factor(n); sumdiv(n, d, eulerphi(d)) sumdiv(n, d, d^2) sumdiv(fa, d, eulerphi(d)) sumdiv(fa, d, d^2) sumdivmult(n, d, eulerphi(d)) sumdivmult(n, d, d^2) sumdivmult(fa, d, eulerphi(d)) sumdivmult(fa, d, d^2) sigma2(x) = sigma(x,2); sigma3(x) = sigma(x,3); core2(x) = core(x,1); fun = [ispowerful, moebius, core, core2, omega, bigomega, eulerphi, numdiv, sigma, sigma2, sigma3]; for(i=1,#fun, print(fun[i](fa))) v = concat([-50..-1], [1..50]); fav = apply(factor, v); { for (i=1,#fun, my(f = fun[i]); for (j=1,#v, if (f(v[j]) != f(fav[j]), error([f,v[j]])))) } \\ allow 0 fun0 = [ispowerful, core, core2, eulerphi]; { for (i=1,#fun0, my(f = fun0[i]); if (f(0) != f(factor(0)), error([f,0]))) } test(fa)= for(i=1,#fun, print(iferr(fun[i](fa),E,E))); test(0) test(factor(0)) test(-2) test(factor(-2)) fa = factor(1); for(i=1,#fun, print(fun[i](fa))) divisors(fa) fa = factor(0); ispowerful(fa) core(fa) core2(fa) divisors(fa) fa = [5!, factor(5!)]; core2(fa) divisors(fa) n = x^2*(x+1)^3*(x+2)^5; fa = factor(n); sumdiv(n, d, d) sumdiv(fa, d, d) sumdivmult(n, d, d) sumdivmult(fa, d, d) \\#1664 divisors([1,2]) \\#1702 moebius(factor(18)) pari-2.7.5/src/test/in/nfrootsof10000644000175000017500000000053011636712103015303 0ustar billbillallocatemem(20*10^6); do(P)=nfrootsof1(nfinit(P))[1]; do(polcyclo(23)) do(polresultant(y^3*x^3-y^2*x^2+1, polcyclo(23))) do(x^54+9*x^51+18*x^48-81*x^45+387*x^42-729*x^39+1953*x^36-7560*x^33+14229*x^30-12393*x^27-270*x^24+6156*x^21+26136*x^18-77679*x^15+88452*x^12-49572*x^9+10287*x^6+972*x^3+27) do(x^2+396735) do(x^2+4372152) do(x^2+x+99184) pari-2.7.5/src/test/in/lift0000644000175000017500000000047312366172547014164 0ustar billbillv=[Mod(y,y^2+1), Mod(1,z), Mod(2,3), 1+O(3)]; T=Pol(v,'x); Z=[1, Mod(5,3), "x", 3+O(3^3), -1/3+O(3), Mod(x,x^2), x*Mod(1,3) + Mod(2,3)]; F=[lift, a->lift(a,'x), a->lift(a,'y), a->lift(a,'z), centerlift,liftall,liftint,liftpol]; { for(i=1,#F, my (f=F[i]); print(f); for (j=1,#Z, print(f(Z[j]))) ) } pari-2.7.5/src/test/in/mathnf0000644000175000017500000000073412366172547014503 0ustar billbill\e mathnf([0,2]) mathnf([0,2], 1) mathnf([0,x]) mathnf([0,x], 1) mathnf([x,x^2+1; x^3+x+1, x+2]*Mod(1,5)) v=[116085838, 181081878, 314252913,10346840]; [H,U]=mathnf(v, 1); [v*U, norml2(U)] [H,U]=mathnf(v, 5); [v*U, norml2(U)] mathnf([]) mathnf([],1) mathnf([;]) mathnf([;],1) mathnfmodid(matrix(0,2), []) mathnfmodid([0,7;-1,0;-1,-1], [6,2,2]) matsolvemod([;],[]~,[]~,1) matsolvemod([;],[],[]~,1) matsolvemod([;],[]~,[],1) matsolvemod([;],1,1,1) matsolvemod([1,2;3,4],1,2,1) pari-2.7.5/src/test/in/env0000644000175000017500000000016012366172547014007 0ustar billbillStrexpand("~root") #Strexpand("~") > 1 Strexpand("$AAA, $BBB, $AAA") getenv("AAA") getenv("__DOES_NOT_EXIST__") pari-2.7.5/src/test/in/thue0000644000175000017500000000150712434213470014155 0ustar billbillallocatemem(20*10^6); thue(x^4 - 13*x^3 - 172*x^2 - 13*x + 1, 9) thue(x^3 - 2, 2) thue(x^6 - 2, 2638) thue(x^3 + x^2 - 43690*x - 3529208, -3572896) thue(x^4-x^3+x^2-x+1,1) thue(x^3-48,320) thue(x^7-401,88) thue(thueinit(x^3-100,1), 25) thue((x+1)^2*(x^2+2), 12) thue((4*x+1)^2*(x^2+2), 75) thueinit(x^0) thue(23*x^4 + 40*x^3 - 600*x^2 + 160*x + 368, -144) thue(x^3+92*x+1,3^3) thue(x^3-18*x^2+81*x+1,3^3) thue((x^4+1)^2,4) thue((x^2+1)^2*(x^2-2),0) thue((x^3-2)^2,0) thue(x^3-2,0) 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) \\ 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) pari-2.7.5/src/test/in/genus2red0000644000175000017500000003733512413013143015106 0ustar billbill\\ Input from Namikawa-Ueno's list of curves of genus 2 \\ with expected reduction types. \\ 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); 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") P0=x^5+a*t^2*x^3+b*t^3*x^2+c*t^4*x+t^5; 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) P0=x^6+a*t*x^3+t^2; do(subst(P0, 'a, 4), "[III], p. 155") P0=t*(x^6+a*t*x^3+t^2); do(subst(P0, 'a, 5), "[IV], p. 155") P0=x^6+t; do(P0, "[V], p. 156") P0=x^6+t^5; do(P0, "[V*], p. 156") P0=x*(x^4+a*t*x^2+t^2); do(subst(P0, 'a, 3), "[VI], p. 156") P0=x*(x^4+t); do(P0, "[VII], p. 156") P0=x*(x^4+t^5); do(P0, "[VII*], p. 156") P0=x^5+t; do(P0, "[VIII-1], p. 156") P0=x^5+t^3; do(P0, "[VIII-2], p. 157") P0=x^5+t^7; do(P0, "[VIII-3], p. 157") P0=x^5+t^9; do(P0, "[VIII-4], p. 157") P0=x^5+t^2; do(P0, "[IX-1], p. 157") P0=x^5+t^4; do(P0, "[IX-2], p. 157") P0=x^5+t^6; do(P0, "[IX-3], p. 157") P0=x^5+t^8; do(P0, "[IX-4], p. 158") \\ Elliptic type, \\ m > 0 FIXME: changed ! 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) \\ 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) \\ 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) \\ 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) \\ m >= 0 m = 10; P0=(x^2-t)^3+a*t^(2*m+3)*(x^2-t)+t^(3*m+4)*x; do(subst(P0, 'a, 3), Strprintf("[2I{0}*-%ld], p. 159",m)) \\ m >= 0 m = 10; P0=(x^2-t)^3+a*t^(2*m+3)*(x^2-t)+t^(3*m+4)*x; do(subst(P0, 'a, 3), Strprintf("[2I{0}*-%ld], p. 159",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}-II-%ld], p. 159",m)) \\ m >= 0 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ m >= 0 m = 10; P0=t*(x^3+t^(6*m+5))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}*-IV-%ld], p. 161",m)) \\ m >= -1 m = 10; P0=t*(x^3+t^(6*m+7))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}*-IV*-%ld], p. 161",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}-III-%ld], p. 161",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+3))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}-III*-%ld], p. 162",m)) \\ m >= 0 m = 10; P0=t*x*(x^2+t^(4*m+3))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}*-III-%ld], p. 162",m)) \\ m >= -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*(x^2+a*x+1); do(subst(P0, 'a, 3), Strprintf("[I{0}*-III*-%ld], p. 162",m)) \\ m >= 0 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) \\ 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) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t); do(P0, Strprintf("[II-II-%ld], p. 163",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^5); do(P0, Strprintf("[II-II*-%ld], p. 163",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+5))*((x-1)^3+t^5); do(P0, Strprintf("[II*-II*-%ld], p. 163",m)) \\ m = -1 P0=t*(x^3+t^2)*((x-1)^3+t^2); do(P0, "[II*-II*-(-1)], p. 163") \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^2); do(P0, Strprintf("[II-IV-%ld], p. 164",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^4); do(P0, Strprintf("[II-IV*-%ld], p. 164",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+5))*((x-1)^3+t^2); do(P0, Strprintf("[II*-IV-%ld], p. 164",m)) \\ m = -1 P0=(x^3+t^2)*(x^3+t); do(P0, "[II*-IV-(-1)], p. 164") \\ m bigger or equal -1 m = 10; P0=t*(x^3+t^(6*m+7))*((x-1)^3+t^2); do(P0, Strprintf("[II*-IV*-%ld], p. 164-165",m)) \\ m >= 0 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) \\ 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) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+2))*((x-1)^3+t^2); do(P0, Strprintf("[IV-IV-%ld], p. 165",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+2))*((x-1)^3+t^4); do(P0, Strprintf("[IV-IV*-%ld], p. 165",m)) \\ m >= -1 m = 10; P0=t*(x^3+t^(6*m+7))*((x-1)^3+t); do(P0, Strprintf("[IV*-IV*-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t); do(P0, Strprintf("[II-III-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+3))*((x-1)^3+t); do(P0, Strprintf("[II-III*-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^5); do(P0, Strprintf("[II*-III-%ld], p. 166",m)) \\ m = -1 P0=(x^2+t)*(x^3+t^2); do(P0, "[II*-III-(-1)], p. 167") \\ m at least -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*((x-1)^3+t^2); do(P0, Strprintf("[II*-III*-%ld], p. 167",m)) \\ m >= 0 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) \\ 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) \\ m = -1 P0=x*(x^2+t)*(x^3+t); do(P0, "[IV-III*-(-1)], p. 167") \\ the top horizontal line has mult. 3. \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^4); do(P0, Strprintf("[IV*-III-%ld], p. 168",m)) \\ m at least -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*((x-1)^3+t); do(P0, Strprintf("[IV*-III*-%ld], p. 168",m)) \\ m >= 0 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) \\ 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) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x-1)*((x-1)^2+t); do(P0, Strprintf("[III-III-%ld], p. 169",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x-1)*((x-1)^2+t^3); do(P0, Strprintf("[III-III*-%ld], p. 169",m)) \\ m >= -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*(x-1)*((x-1)^2+t); do(P0, Strprintf("[III*-III*-{%ld}], p. 169",m)) \\ Parabolic type \\ n > 0 n = 9; P0=(x^3+a*x+1)*(x^2+t^n); do(subst(P0, 'a, 3), Strprintf("[I{%ld-0-0}], p. 170",n)) \\ n, m > 0 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) \\ 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) \\ n, m >= 0 n = 9; m = 10; P0=(x^3+a*t^(4*m+2)*x+t^(6*m+3))*((x-1)^2+t^n); do(subst(P0, 'a, 3), Strprintf("[I{%ld}-I{0}*-%ld], p. 171",n, m)) \\ n > 0 n = 9; P0=t*(x^3+a*x+1)*(x^2+t^n); do(subst(P0, 'a, 3), Strprintf("[I*{%ld-0-0}], p. 171",n)) \\ n, m >= 0 n = 9; m = 10; P0=(x+t)*(x^2+t^(n+2))*((x-1)^3+a*t^(4*m+2)*(x-1)+t^(6*m+3)); do(subst(P0, 'a, 3), Strprintf("[I*{%ld}-I{0}*-%ld], p. 171",n, m)) \\ n > 0 n = 9; P0=(x^4+a*t*x^2+t^2)*((x-1)^2+t^(n-1)); do(subst(P0, 'a, 3), Strprintf("[II{%ld-0}], p. 171",n)) \\ n > 0 n = 9; P0=t*(x^4+a*t*x^2+t^2)*((x-1)^2+t^(n-1)); do(subst(P0, 'a, 3), Strprintf("[II*{%ld-0}], p. 172",n)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+1))*((x-1)^2+t^n); do(P0, Strprintf("[II-I{%ld}-%ld], p. 172",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+5))*((x-1)^2+t^n); do(P0, Strprintf("[II*-I{%ld}-%ld], p. 172",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+2))*((x-1)^2+t^n); do(P0, Strprintf("[IV-I{%ld}-%ld], p. 173",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+4))*((x-1)^2+t^n); do(P0, Strprintf("[IV*-I{%ld}-%ld], p. 173",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+1)); do(P0, Strprintf("[II-I*{%ld}-%ld], p. 173",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+5)); do(P0, Strprintf("[II*-I*{%ld}-%ld], p. 174",n, m)) \\ n >= 0, m = -1 n = 9; P0=t*((x-1)^2+t^n)*(x^3+t^2); do(P0, Strprintf("[II*-I*{%ld}-(-1)], p. 174",n)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+2)); do(P0, Strprintf("[IV-I*{%ld}-%ld], p. 174",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+4)); do(P0, Strprintf("[IV*-I*{%ld}-%ld], p. 174",n, m)) \\ n >= 0, m = -1 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ n >= 0, m = -1 n = 9; P0=t*x*(x^2+t)*((x-1)^2+t^n); do(P0, Strprintf("[III*-I*{%ld}-(-1)], p. 177",n)) \\ attach one more projective line of mult. 1 to the component 2B \\ n >= 0 n = 9; P0=(x^4+t)*((x-1)^2+t^n); do(P0, Strprintf("[III-II{%ld}], p. 177",n)) \\ n > 0 n = 9; P0=(x^4+t^3)*((x-1)^2+t^(n-1)); do(P0, Strprintf("[III*-II{%ld}], p. 178",n)) \\ n = 0 P0=t*(x^2+t)*(x^4+t); do(P0, "[III*-II{0}], p. 178") \\ n >= 0 n = 9; P0=(x^4+t)*(x^2+t^(n+1)); do(P0, Strprintf("[III-II*{%ld}], p. 178",n)) \\ n >= 0 n = 9; P0=(x^4+t^3)*(x^2+t^(n+2)); do(P0, Strprintf("[III*-II*{%ld}], p. 178",n)) \\ Parabolic type continued \\ n, p > 0 n = 9; p = 8; P0=(x^2+t^n)*((x+1)^2+t^p)*(x-1); do(P0, Strprintf("[I{%ld-%ld-0}], p. 179",n,p)) \\ n, p, m > 0 n = 9; p = 8; m = 10; P0=(x+t^(2*m))*(x^2+t^(4*m+n))*((x-1)^2+t^p); do(P0, Strprintf("[I{%ld}-I{%ld}-%ld}], p. 179",n,p,m)) \\ n, p > 0 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) \\ n, p > 0, m >= 0 n = 9; p = 8; m = 10; P0=(x+t^(2*m+1))*(x^2+t^(4*m+n+2))*(x-1+t)*((x-1)^2+t^(p+2)); do(P0, Strprintf("[I*{%ld}-I*{%ld}-%ld], p. 180",n,p,m)) \\ n, p > 0, m >= 0 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) \\ 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) \\ n > 0 odd, m > 0 k = 4; m = 10; n=2*k+1; P0=((x^2-t)+t^(m+1))*((x^2-t)^2+t^(2*m+k+2)*x); do(P0, Strprintf("[2I{%ld}-%ld}], p. 181",n,m)) \\ n > 0 even, m=0 k = 4; n=2*k; P0=((x^2-t)+a*t)*((x^2-t)^2+t^(k+2)); do(subst(P0, 'a, 2), Strprintf("[2I{%ld}-0], p. 181",n)) \\ n > 0 odd, m=0 k = 4; n=2*k+1; P0=((x^2-t)+a*t)*((x^2-t)^2+t^(k+2)*x); do(subst(P0, 'a, 2), Strprintf("[2I{%ld}-0], p. 181",n)) \\ n > 0 even, m >= 0 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) \\ n > 0 odd, m k = 4; m = 10; n=2*k+1; P0=((x^2-t)+t^(m+1)*x)*((x^2-t)^2+t^(2*m+k+3)*x); do(P0, Strprintf("[2I*{%ld}-%ld}], p. 181",n,m)) \\ n, p > 0 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) \\ n > 0 even k = 4; n=2*k; P0=x*((x^2-t^3)^2+t^(k+6)); do(P0, Strprintf("[III{%ld}], p. 182",n)) \\ n > 0 odd k = 4; n=2*k+1; P0=x*((x^2-t^3)^2+t^(k+5)*x); do(P0, Strprintf("[III{%ld}], p. 182",n)) \\ n, p, q > 0 n = 9; p = 8; q = 5; P0=(x^2+t^n)*((x-1)^2+t^p)*((x-2)^2+t^q); do(P0, Strprintf("[I{%ld-%ld-%ld}], pp. 182-183",n,p,q)) \\ n, p, q > 0 n = 9; p = 8; q = 5; P0=t*(x^2+t^n)*((x-1)^2+t^p)*((x-2)^2+t^q); do(P0, Strprintf("[I*{%ld-%ld-%ld}], pp. 183",n,p,q)) \\ n, p > 0, p even 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) \\ 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) \\ n, p > 0 n = 9; k = 4; l = 0; p=2*k+l; P0=t*((x^2-t)^2+t^(k+2)*x^l)*((x-1)^2+t^(n-1)); do(P0, Strprintf("[II*{%ld-%ld}], p. 184",n,p)) \\ n, p > 0 n = 9; k = 4; l = 1; p=2*k+l; P0=t*((x^2-t)^2+t^(k+2)*x^l)*((x-1)^2+t^(n-1)); do(P0, Strprintf("[II*{%ld-%ld}], p. 184",n,p)) \\ n > 0 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ 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) \\ M. Stoll, bug28 genus2red(0,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) \\ J. Mueller, bug28 genus2red(0,(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) P=x^6+4*x^5+24*x^4+32*x^3+56*x^2+48*x+24; genus2red(0,P,3) P=24*x^5+56*x^4+76*x^3+33*x^2-4*x-20; genus2red(0,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) \\ M. Stoll, bug28 P=-5*x^5+5*x^4+10*x^3-7; genus2red(1,P,3) P=-5*x^6-3*x^5-10*x^4-10*x^3-7; genus2red(1,P,3) P=3*x^5+5*x^4+5*x-4; genus2red(1,P,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) \\ M. Stoll, bug27 Q=x^3+1; P=-7*x^6+5*x^3+5*x^2-6*x+1; genus2red(Q,P,3) \\ #1596 genus2red(0,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) \\ #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) \\ #1597 genus2red(0,6*x^6+5*x^4+x^2+1,7) \\ #1597 genus2red(x^3-1,1) pari-2.7.5/src/test/in/op0000644000175000017500000000012512366172547013636 0ustar billbilla = 5; a \= 2 b = 5; b \/= 2 c = 5; c >>= 2 d = 5; d <<= 1 e = 5; e %= 3 [a,b,c,d,e] pari-2.7.5/src/test/in/io0000644000175000017500000000040712366172547013632 0ustar billbillF="io-testfile"; del()=system(Str("rm -f ", F)); del() write(F, 123) write(F, 456) write1(F, "a",7) write1(F, "b") write(F) writetex(F, 1/2) readstr(F) del() \\ write(F, 1) write(F, "1+2") readvec(F) del() \\ writebin(F,1) read(F) del() writebin(F) read(F) del() pari-2.7.5/src/test/in/factorint0000644000175000017500000000011112141040641015160 0ustar billbillfactorint(-33623546348886051018593728804851,1) factorint(691160558642,1) pari-2.7.5/src/test/in/qfisom0000644000175000017500000000440112366172547014517 0ustar billbillin(M,fl)=if(fl,qfisominit(M,fl),qfisominit(M)); checkauto(M,f,fl)= { my(G=if(f,qfauto(in(M,fl)),if(fl,qfauto(M,fl),qfauto(M)))); for(j=1,#G[2],my(Q=G[2][j]); if(M!=Q~*M*Q ,error(v))); print(G[1]); } checkisom(M,N,f,fl)= { my(Q=if(f,qfisom(in(M,fl),N),if(fl,qfisom(M,N,fl),qfisom(M,N)))); if(Q==0 || M!=Q~*N*Q ,error(N),print("OK")); } qfauto(Mat(1)) M=[4,-2,-1,1,1,-2,-2,-2,-1,-1,-1,-1;-2,4,-1,-2,-2,2,2,0,-1,-1,-1,-1;-1,-1,4,-1,-1,1,1,2,0,0,2,2;1,-2,-1,4,1,-1,-1,0,2,2,-1,-1;1,-2,-1,1,4,-1,-1,-1,1,1,0,0;-2,2,1,-1,-1,4,1,0,-1,-1,-1,-1;-2,2,1,-1,-1,1,4,2,1,1,0,0;-2,0,2,0,-1,0,2,4,2,2,2,2;-1,-1,0,2,1,-1,1,2,4,2,1,0;-1,-1,0,2,1,-1,1,2,2,4,0,1;-1,-1,2,-1,0,-1,0,2,1,0,4,2;-1,-1,2,-1,0,-1,0,2,0,1,2,4]; checkauto(M,0) checkauto(M,0,[1,1]) checkauto(M,1) checkauto(M,1,[1,1]) N1=[2,0,-1,-1,-1,1,0,0,0,0,-1,0,-1,1,0,0;0,2,1,1,1,-1,0,0,-1,1,-1,0,0,0,1,1;-1,1,4,2,2,-2,0,1,1,0,-1,1,-1,1,-1,-1;-1,1,2,4,2,-2,0,1,-1,0,1,1,1,1,1,1;-1,1,2,2,4,-2,0,1,-1,0,-1,1,-1,1,1,1;1,-1,-2,-2,-2,4,-1,0,1,0,1,0,1,-1,-1,-1;0,0,0,0,0,-1,2,-1,-1,0,-1,0,-1,0,1,0;0,0,1,1,1,0,-1,2,1,0,0,1,0,1,-1,0;0,-1,1,-1,-1,1,-1,1,4,0,0,0,0,0,-3,-2;0,1,0,0,0,0,0,0,0,2,-1,0,0,-1,0,0;-1,-1,-1,1,-1,1,-1,0,0,-1,4,0,3,-1,0,0;0,0,1,1,1,0,0,1,0,0,0,2,0,1,0,0;-1,0,-1,1,-1,1,-1,0,0,0,3,0,4,-1,0,1;1,0,1,1,1,-1,0,1,0,-1,-1,1,-1,4,0,0;0,1,-1,1,1,-1,1,-1,-3,0,0,0,0,0,4,2;0,1,-1,1,1,-1,0,0,-2,0,0,0,1,0,2,4]; N2=[6,-4,4,-2,2,-1,1,1,-1,2,1,-2,3,-1,1,0;-4,8,-6,2,-1,0,0,-1,2,-4,0,3,-3,0,-2,-1;4,-6,8,-4,1,1,2,2,-2,5,3,-4,2,1,2,2;-2,2,-4,4,-1,0,-2,-2,1,-3,-3,2,-1,-1,-1,-1;2,-1,1,-1,2,0,1,0,0,1,1,-1,1,0,0,0;-1,0,1,0,0,2,1,0,0,1,1,-1,-1,1,0,1;1,0,2,-2,1,1,4,2,0,2,3,-2,0,1,0,1;1,-1,2,-2,0,0,2,4,-1,1,1,-2,1,0,1,0;-1,2,-2,1,0,0,0,-1,2,-1,0,1,-1,0,0,0;2,-4,5,-3,1,1,2,1,-1,6,4,-3,0,2,1,2;1,0,3,-3,1,1,3,1,0,4,6,-2,-2,2,0,2;-2,3,-4,2,-1,-1,-2,-2,1,-3,-2,4,-1,-1,-1,-1;3,-3,2,-1,1,-1,0,1,-1,0,-2,-1,4,-1,1,-1;-1,0,1,-1,0,1,1,0,0,2,2,-1,-1,2,0,1;1,-2,2,-1,0,0,0,1,0,1,0,-1,1,0,2,0;0,-1,2,-1,0,1,1,0,0,2,2,-1,-1,1,0,2]; checkauto(N1,0) checkauto(N1,0,[1,1]); checkauto(N1,1) checkauto(N1,1,[1,1]); checkisom(N1,N2,0) checkisom(N1,N2,0,[1,1]) checkisom(N1,N2,1) checkisom(N1,N2,1,[1,1]) G= [1152,[[-1,0,0,0;0,-1,0,0;0,0,-1,0;0,0,0,-1],[0,0,0,1;0,1,1,0;0,-1,0,0;1,-1,-1,0],[-1,0,0,0;0,0,-1,1;-1,0,1,0;-1,1,1,0]]]; qfautoexport(G) qfautoexport(G,1) pari-2.7.5/src/test/in/trans0000644000175000017500000000162512366172547014355 0ustar billbillHEAP=[183, if(precision(1.)==38, 5763, 8929)]; \\ A tres grande precision \p 2000 \e abs(-0.01) agm(1,2) agm(1+O(7^5),8+O(7^5)) 4*arg(3+3*I) bernreal(12) bernvec(6) eta(q) gammah(10) Pi precision(Pi,38) sqr(1+O(2)) sqrt(13+O(127^12)) teichmuller(7+O(127^12)) \\ A grande precision \p 500 Catalan Euler acos(0.5) acosh(3) 3*asin(sqrt(3)/2) asinh(0.5) 3*atan(sqrt(3)) atanh(0.5) besseljh(1,1) cos(1) cosh(1) exp(1) exp(1.123) incgam(4,1,6) incgamc(2,1) log(2) sin(Pi/6) sinh(1) sqr(tan(Pi/3)) tanh(1) thetanullk(0.5,7) \\ A moyenne precision \p 210 dilog(0.5) eint1(2) lngamma(10^50*I) polylog(5,0.5) polylog(-4,t) polylog(5,0.5,1) polylog(5,0.5,2) polylog(5,0.5,3) psi(1) round(prod(k=1,17,x-exp(2*I*Pi*k/17)), &e) e theta(0.5,3) weber(I) weber(I,1) weber(I,2) zeta(3) \\ A faible precision \p 38 besselk(1+I,1) erfc(2) gamma(10.5) hyperu(1,1,1) incgam(2,1) zeta(0.5+14.1347251*I) \\ if (getheap() != HEAP, getheap()) pari-2.7.5/src/test/in/idealappr0000644000175000017500000000030512366172547015161 0ustar billbillidealaddtoone(nfinit(x),[1,[;]]); K=nfinit(x^2+23); A=idealhnf(K,x/2); idealtwoelt(K, 3, 6) idealtwoelt(K, A) idealtwoelt(K, A, x) idealtwoelt(K, [;]) idealtwoelt(K, [;], 1) idealtwoelt(K, [;], 0) pari-2.7.5/src/test/in/zncoppersmith0000644000175000017500000000064512366172547016134 0ustar billbillp = 10^30+57; q = 10^31+33; N = p*q; p0 = p % 10^20; z = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) gcd(z[1]*10^19 + p0, N) == p setrand(1); P = 4625048078322670354774415943228839104529734663852281547523640; e = 3; X = floor(N^0.3); x0 = 1339991002000615200; C = lift( (Mod(x0,N) + P)^e ); z = zncoppersmith((P+x)^3 - C, N, X) z[1] == x0 zncoppersmith(Pol([192378,19237198,912831923,12938719]), 2*3*5*7, 1000.5, 29.5) pari-2.7.5/src/test/in/rfrac0000644000175000017500000000174012366172547014321 0ustar billbillprd(b)=prod(n=1,#b,a[n]^b[n]); init(N) = { k = 1; v = vector(3^N); w = vector(3^N); forvec(u = vector(N,i,[-1,1]), v[k] = prd(u); w[k] = u; k++); } {doit(N)= for (i=1,#v, A = v[i]; for (j=1,#v, B = v[j]; if ( A+B-A != B, error(A,"+",B)) ) ); } {doit2(i)= for (i=1,#v, A = v[i]; for (j=1,#v, B = v[j]; C = prd(w[i]-w[j]); if(A/B!=C, error(A,"/",B)))); } a=[a1,a2,a3,a4,a5,a6]; N = 4; init(N); doit(N); doit2(N); {doit3(i)= for (i=1,#v, A = v[i]; for (j=1,#v, B = v[j]; D = A*C; for (k=1,#v, C = v[k]; D - C))); } a=[x,1+x,y,1+y]; init(N); doit3(N); \\ regression tests (y/x)/(x^0/y) x1=(8*b^2 + 8*b + 1)/(4*b + 1); x2=32*b^4/(32*b^3 + 40*b^2 + 12*b + 1); x1-x2 \\ simplified ? n=102;(1-x^n)*(1-x^(3*n))/(1+x^(5*n)) n=497;x^n*(1-x^n)/(1+(x^3)^n) M = [ 1, 1, 1; 'a, 'b, 'c; 'a^2, 'b^2, 'c^2 ]; [A, B, C] = M^-1 * [ 'u, 'v, 'w ]~; X = A^2 + B^2 + C^2; Y = A*B + A*C + B*C; Z = 'u^2 - 2*Y; [X == Z,X - Z] trace(I/x) default(realprecision,38); 1./x-1/x pari-2.7.5/src/test/in/cmp0000644000175000017500000000042712405547147014000 0ustar billbilltest(f,g)=[cmp(f,f), cmp(f,g), cmp(g,f)] test(()->1, ()->2) test(1.,2.) test(1,2) test(Vecsmall([1,2]),Vecsmall([1,3])) test(List([1,2]),List([1,3])) test(x,x+1) test(x,y) test(O(x),x+O(x^2)) 1 > "a" 1. > "a" 1/2 > "a" "a" > 0 Mod(1,3) > 0 lex(Vecsmall([1,2]),Vecsmall([1,3])) pari-2.7.5/src/test/in/list0000644000175000017500000000123012405547147014165 0ustar billbillL = List(); for (i=1,10^5,listput(L,i)) L = List([1,2,3]); for (i=1,5000,listinsert(L,i,3)) L = List([1,2,3,3]); concat(L,5) concat(1,L) L = concat(L,L) listsort(L); L listsort(L,1); L listpop(L); L listpop(L,1); L \\ L = List([[1,2,3], 2]) L[1][1] = 3 L L = List([Vecsmall([1,2,3]), 2]) L[1][1] = 3 L = List(); listput(L,1); listpop(L); listpop(L); matdiagonal(List([0])) g(L)=for(i=1,5,listput(L,5-i));L; l=List([10,9,8,7,6,5]); g(l) l listkill(l) listcreate() subst(List([x,x^2+y]),x,1) substvec(List([x,y]), [x,y], [y,x]) substpol(List([x^2,x^3]), x^2, y) getheap()[1] chinese(List()) chinese(List([Mod(1,3)])) chinese(List([Mod(0,2),Mod(1,3),Mod(2,5)])) pari-2.7.5/src/test/in/qf0000644000175000017500000000260212515252602013613 0ustar billbillqfgaussred([0,7,2,3; 7,0,6,8; 2,6,0,9; 3,8,9,0]) Q=[2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,2,1,1,1,1,1,1,1,1,1,1,1;-1,1,2,1,1,1,1,1,1,1,1,1,1;-1,1,1,2,1,1,1,1,1,1,1,1,1;-1,1,1,1,2,1,1,1,1,1,1,1,1;-1,1,1,1,1,2,1,1,1,1,1,1,1;-1,1,1,1,1,1,2,1,1,1,1,1,1;-1,1,1,1,1,1,1,2,1,1,1,1,1;-1,1,1,1,1,1,1,1,2,1,1,1,1;-1,1,1,1,1,1,1,1,1,2,1,1,1;-1,1,1,1,1,1,1,1,1,1,2,1,1;-1,1,1,1,1,1,1,1,1,1,1,2,1;-1,1,1,1,1,1,1,1,1,1,1,1,2]; Q[3,7] += 1.25; Q[7,3] += 1.25; qfsign(Q) Q=[8,4,4,4,4,4,4,4,4,4,4,4;4,8,4,4,4,4,4,4,4,4,4,4;4,4,8,0,0,0,3,0,0,0,0,0;4,4,0 ,8,4,4,1,4,4,4,4,4;4,4,0,4,8,4,4,4,4,4,4,4;4,4,0,4,4,8,4,4,4,4,4,4;4,4,3,1,4,4,8 ,4,1,1,1,1;4,4,0,4,4,4,4,8,4,4,4,4;4,4,0,4,4,4,1,4,8,4,4,4;4,4,0,4,4,4,1,4,4,8,4 ,4;4,4,0,4,4,4,1,4,4,4,8,4;4,4,0,4,4,4,1,4,4,4,4,8]; qfminim(Q,,0,2)[1] qfrep(Q,16) qfrep(Q,8,1) qfminim(Q,,,1) qfminim(Q,8,,1) qfminim(Q,4,,1) qfminim([;],4,,1) qfminim([;],4,,2) qfminim(matid(2),0,1,2) qfminim(matid(2),0,1,1) qfminim(matid(2),0,1,0) L=[360815,2283021;-316840,2566404]; qfminim(L~*L,10^16)[2] qfminim(L~*L,10^16,,2)[2] forqfvec(v, [3,2;2,3], 3, print(v)) forqfvec(v, [3,2;2,3],, print(v)) forqfvec(v,[;],3,) x=[1,2,3]~; y=[-1,0,1]~; qfnorm(x) q=[1,2,3;2,2,-1;3,-1,0]; qfnorm(x, q) qfbil(x,y) qfbil(x,y,q) M=[1,2,3;4,5,6;7,8,9]; qfnorm(M) qfnorm(M,q) qfnorm(1) qfnorm(1,1) qfnorm(x,Mat(1)) qfnorm(x,Mat(x~)) qfbil(1,1) qfbil([1],[1,2]) qfbil([1,2],[1,2],q) qfbil([1,2],[1,2],Mat([1,2])) pari-2.7.5/src/test/in/subgroup0000644000175000017500000000046212366172547015072 0ustar billbillG=[53835600, 29] do(h,G)=print(mathnf(concat(h,matdiagonal(G)))); forsubgroup(h=G,[5], do(h,G)) forsubgroup(h=G,[10], do(h,G)) subgrouplist(G,[12]) forsubgroup(h=[],[1],print(h)) forsubgroup(h=[],[2],print(h)) forsubgroup(h=[],2,print(h)) forsubgroup(h=[2,3],2,print(h)) forsubgroup(h=matid(2),2,print(h)) pari-2.7.5/src/test/in/subfields0000644000175000017500000000642412611153614015173 0ustar billbill/* test(n)= { p = x^n-x-1; c = p; for (i=1,n-3, c = polcompositum(p, c); c = c[#c]); c; } nfsubfields(test(5)); */ /* From Hulpke and Klueners's papers */ {v=[ x^6 + 108, x^8 - 12*x^6 + 23*x^4 - 12*x^2 + 1, x^8 - 10*x^4 + 1, x^8 + 4*x^6 + 10*x^4 + 12*x^2 + 7, x^9 - 18*x^8 + 117*x^7 - 348*x^6 + 396*x^5 + 288*x^4 + 3012*x^3 + 576*x^2 + 576*x - 512, x^10 + 38*x^9 - 99*x^8 + 1334*x^7 - 4272*x^6 + 9244*x^5 - 8297*x^4 + 1222*x^3 + 1023*x^2 - 74*x + 1, x^10 - 20*x^9 + 80*x^8 + 200*x^7 - 3770*x^6 + 872*x^5 + 29080*x^4 + 36280*x^3 - 456615*x^2 + 541260*x - 517448, x^10 - 10*x^8 + 20*x^7 + 235*x^6 + 606*x^5 + 800*x^4 + 600*x^3 + 270*x^2 + 70*x + 16, x^12 + 6*x^9 + 4*x^8 + 8*x^6 - 4*x^5 - 12*x^4 + 8*x^3 - 8*x + 8, x^12 + 9*x^11 + 3*x^10 - 73*x^9 - 177*x^8 - 267*x^7 - 315*x^6 - 267*x^5 - 177*x^4 - 73*x^3 + 3*x^2 + 9*x + 1, x^12 - 34734*x^11 + 401000259*x^10 - 1456627492885*x^9 - 2537142937228035*x^8 + 187620727556 79375516*x^7 - 812368636358864062944*x^6 - 70132863629758257512231931*x^5 + 25834472514 893102332821062085*x^4 + 76623280610352450247247939584745*x^3 - 45080885015422662132 515763499758450*x^2 - 2070499552240812214288316981071818900*x - 5505057590977785454 85364826246753544, x^15 + 20*x^12 + 125*x^11 + 503*x^10 + 1650*x^9 + 3430*x^8 + 4690*x^7 + 4335*x^6 + 2904*x^5 + 1400*x^4 + 485*x^3 + 100*x^2 + 15*x + 1, x^32-2, x^27 - 120*x^25 - 63*x^24 + 5673*x^23 + 5181*x^22 - 138003*x^21 - 167184*x^20 + 1865730*x^19 + 2668613*x^18 - 14070078*x^17 - 21889917*x^16 + 57688596*x^15 + 89482089*x^14 - 132575217*x^13 - 190829625*x^12 + 164200812*x^11 + 215956974*x^10 - 86796519*x^9 - 129504396*x^8 + 1575183*x^7 + 32931993*x^6 + 9928740*x^5 + 49968*x^4 - 372144*x^3 - 50736*x^2 - 1344*x + 64, x^12 - 3*x^10 + 8*x^8 - 14*x^6 + 21*x^4 - 23*x^2 + 26, x^24 +8*x^23 -32*x^22 -298*x^21+624*x^20+4592*x^19-8845*x^18-31488*x^17+76813*x^16+ 65924*x^15 - 265616*x^14 + 48348*x^13 + 385639*x^12 - 394984*x^11 - 20946*x^10 + 369102*x^9 - 362877*x^8+183396*x^7+434501*x^6-194418*x^5+450637*x^4+125800*x^3-16401*x^2-45880*x+ 115151 /* x^60 + 36*x^59 + 579*x^58 + 5379*x^57 + 30720*x^56 + 100695*x^55 + 98167*x^54 - 611235*x^53 - 2499942*x^52 - 1083381*x^51 + 15524106*x^50 + 36302361*x^49 - 22772747*x^48 - 205016994*x^47 - 194408478*x^46 + 417482280*x^45 + 954044226*x^44 + 281620485*x^43 - 366211766*x^42 - 1033459767*x^41 - 8746987110*x^40 - 15534020046*x^39 + 23906439759*x^38 + 104232578583*x^37 + 31342660390*x^36 - 364771340802*x^35 - 547716092637*x^34 + 583582152900*x^33 + 2306558029146*x^32 + 998482693677*x^31 - 3932078004617*x^30 - 5195646620046*x^29 + 2421428069304*x^28 + 10559164336236*x^27 + 3475972372302*x^26 - 22874708335419*x^25 - 33428241525914*x^24 + 21431451023271*x^23 + 90595197659892*x^22 + 50882107959528*x^21 - 67090205528313*x^20 - 117796269461541*x^19 - 74369954660792*x^18 + 25377774560496*x^17 + 126851217660123*x^16 + 104232393296166*x^15 - 29072256729168*x^14 - 83163550972215*x^13 - 24296640395870*x^12 + 14633584964262*x^11 + 8865283658688*x^10 + 5364852154893*x^9 - 1565702171883*x^8 - 7601782249737*x^7 - 2106132289551*x^6 + 3369356619543*x^5 +3717661159674*x^4 +1754791133184*x^3 +573470363592*x^2 +74954438640*x + 3285118944 */ ];} for (i=1,#v, print(i,": ",nfsubfields(v[i]))) nfsubfields(x^12-4*x^11-14*x^10+44*x^9+226*x^8+380*x^7-542*x^6-2620*x^5+4249*x^4-6312*x^3+13056*x^2-67392*x+97344) /* #1758 */ pari-2.7.5/src/test/in/compat0000644000175000017500000003260412405547147014506 0ustar billbill\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< 1e-10, printf("%s(%.1f + I*%.1f):\t%.2g + I*%.2g\n", f, re, im, real(dt), imag(dt)); ), ERR, printf ("%s: %.1f + I*%.1f is a pole ?\n", f, re, im)) ) ); } for(k = 1, #fun, test(fun[k], FUN[k])); default(realprecision,1155); a=sqrt(2)/2; sin(asin(a)) - a cos(acos(a)) - a tan(atan(a)) - a sinh(asinh(a)) - a cosh(acosh(a)) - a tanh(atanh(a)) - a default(realprecision,38); a *= 1.; cotan(a) cotan(I) cotan(a+I) tanh(I) cotan(a+I) pari-2.7.5/src/test/in/whatnow0000644000175000017500000000013212366172547014705 0ustar billbillwhatnow(changevar) whatnow(char) whatnow(allocatemem) whatnow(proveGRH) whatnow(compimag) pari-2.7.5/src/test/in/equal0000644000175000017500000000241112573104115014311 0ustar billbill[O(3)===O(3), 1+O(3)===2+O(3), 1+O(3)==O(3^-1), 1+O(3)==2+O(3)] [O(x)===O(y), 2+O(x)===1+O(x)] [1.===1., 1.===-1.] f(x)=1; g(x)=1; h()=1; [f===g, f===h] [3/2===-3/2, 3/2===3/2] m=Mod(1,2); [Mod(1,3)===m, m===Mod(0,2), m===m] m=Mod(1,x); [m===Mod(Pol(1),x), m===Mod(1,y), m===m] t=ffgen(8); [t===t+1, t===ffgen(4), t===t] q=Qfb(1,2,3); [q===Qfb(1,2,2), q===Qfb(1,3,3), q===Qfb(2,2,3), Qfb(1,0,-2)===Qfb(1,0,-2,1.), q===q] Qfb(1,0,-2)==Qfb(1,0,-2,1.) 1/x===1/y [[1,2,3]===[1,2], [1,2,3]===[1,2,4], [1,2,3]===[1,2,3.], [1,2]===[1,2]] quadgen(5)==quadgen(13) ["ab"==="ac", "ab"==="ab"] 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])) A=Ser(vector(40000,i,i==1)); A==A pari-2.7.5/src/test/in/orthopol0000644000175000017500000000156412366172547015076 0ustar billbillU(n)=polchebyshev(n,2); T(n)=polchebyshev(n,1); L(n)=pollegendre(n); H(n)=polhermite(n); print("U");for (n=-50,50, if (U(n+1)+U(n-1)-2*x*U(n), print(n))) print("T");for (n=-50,50, if (T(n+1)+T(n-1)-2*x*T(n), print(n))) print("L");for (n=-50,50, if ((n+1)*L(n+1)-(2*n+1)*x*L(n)+n*L(n-1), print(n))) print("H");for (n=0,100, Hn=H(n); if (H(n+1)-2*x*Hn+Hn', print(n))) T=polchebyshev(5,1,x); subst(T,x,2) == polchebyshev(5,1,2) U=polchebyshev(5,2,x); subst(U,x,2) == polchebyshev(5,2,2) H=polhermite(5); subst(H,x,2) == polhermite(5,2) L=pollegendre(5); subst(L,x,2) == pollegendre(5,2) polchebyshev(-1,2,2) polchebyshev(-2,2,2) polchebyshev(4,2,2) z=Mod(2,2^64+13); N=1000; T=polchebyshev(N,1);subst(T,x,z) == polchebyshev(N,1,z) T=polchebyshev(N,2);subst(T,x,z) == polchebyshev(N,2,z) T=polhermite(N);subst(T,x,z) == polhermite(N,z) T=pollegendre(N);subst(T,x,z) == pollegendre(N,z) pari-2.7.5/src/test/in/polred0000644000175000017500000000371512366172547014515 0ustar billbillrnfpolredbest(nfinit(quadpoly(5,y)),x^7-14*x^5+56*x^3-56*x+22) \\ rnfpolred(nfinit(quadpoly(1996,y)),quadray(1996,1)) \\ rnfpolred(nfinit(quadpoly(904,y)),quadray(904,1)) K=nfinit(quadpoly(29,y)); T=quadray(29,17) rnfpolredabs(K,T) rnfpolredbest(K,T) rnfpolredabs(K,[T,100],16) rnfpolredbest(K,[T,100]) K=nfinit(y^3-y-1); T=x^3-x-1; rnfpolredabs(K,T) rnfpolredabs(K,T,2) [P,a]=rnfpolredbest(K,T,1); subst(K.pol,y,a) [P,a,b]=rnfpolredbest(K,T,3); subst(K.pol,y,a) substvec(T,[x,y],[a,b]) rnfpolred(nfinit(quadpoly(1129,y)),quadray(1129,1)); nfinit(Pol([256,-2560,5120,6400,-60320,6976,116320,72560,-456615,270630,-129362])); polredabs(quadpoly(14586217464)) { p=x^32 - 1680*x^30 + 1026480*x^28 - 289096080*x^26 + 39933334980*x^24 - 2715474610800*x^22 + 88886222283600*x^20 - 1619990314513200*x^18 + 17928141864081750*x^16 - 125620995771054000*x^14 + 565267786831818000*x^12 - 1629524362237758000*x^10 + 2978275448322310500*x^8 - 3393290168363970000*x^6 + 2319247705779270000*x^4 - 866101453967610000*x^2 + 135345425000900625; #polredabs(p,4) } polredabs(x^12+139968*x^10+24814646784*x^8+1854249948463104*x^6+177954917169813848064*x^4-1827912356210202139164672*x^2+68504919608701082757419237376); polredabs(x^4+10^21*x^2+1) polredabs(x^4+146077*x^2+2629386) \\#1146 polredabs(x^9-4*x^7-3*x^6+9*x^5+8*x^4-6*x^3-9*x^2-4*x-1) \\#1228 polredabs(x^5-13*x^3+3*x^2+5*x-1) \\#1229 polredabs(x^6+21471450*x^2+71643071500) polredbest(x^6+21471450*x^2+71643071500) polredbest(4*x^4+146077*x^2+2629386) polredabs(2*x+1) polredabs(2*x+1,1) polred([x,[1]]) polred(2*x+1) polred(2*x+1,1) polred(4*x^2+1,2) polredbest(2*x+1) polredbest(2*x+1,1) polredbest(4*x^2+1,1) polredord(2*x+1) polredord(4*x^2+1) \\ #1519, test T->unscale != 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) pari-2.7.5/src/test/in/ellglobalred0000644000175000017500000000072212366172547015653 0ustar billbill\\package:elldata { forell(E,1,9999, N = ellconvertname(E[1])[1]; M = ellglobalred( ellinit(E[2], 1) )[1]; if (N != M, print(E," bad for N = ",N)) ); } ellidentify(ellinit([1,1])) ellsearch("11a1") ellsearch("11a") ellsearch("11b") ellsearch("11") ellsearch([11,0,1]) ellsearch([11,0]) ellsearch([11]) ellsearch(11) ellinit("11a1").j iferr(ellsearch([0,0,0,0]),E,E) iferr(ellsearch([0,0,0]),E,E) iferr(ellsearch("curve"),E,E) iferr(ellsearch(I),E,E) pari-2.7.5/src/test/in/bessel0000644000175000017500000000111112366172547014471 0ustar billbilldefault(realprecision,38); default(seriesprecision,6); besseljh(1,2^64) besseljh(10,x) NU = [x,0,1,1/2,sqrt(2),10,1+I]; ARG = [x,1,1/2,1+I]; F=[besselh1,besselh2,besseli,besselj,besseljh,besselk,besseln]; test(f)= { print(f); for (i=1,#NU, for (j=1,#ARG, print([i,j],": ", iferr(f(NU[i],ARG[j]), E,E)); ) ); } for(i=1,#F,test(F[i])); for(i=1,#F,print(F[i](1,Mod(x,x^2+1)))); for(i=1,#F,print(F[i](1,[1]))); for(i=1,#F,print(F[i](1,[1]~))); for(i=1,#F,print(F[i](1,Mat(1)))); besseljh(2,0.) besseljh(2,1e-50) besselk(1,1000) besselk(1e-5,20) besselk(I,1000) besselk(1e-20,1e-5) pari-2.7.5/src/test/in/quadray0000644000175000017500000000144612431620634014661 0ustar billbilldefault(realprecision,38); \\ all quad imaginary whose class group has exponent 2 v=[-15,-35,-51,-91,-115,-123,-187,-195,-235,-267,-403,-427,-435,-483,-555,-595,-627,-715,-795,-1155,-1435,-1995,-3003,-3315,-20,-24,-40,-52,-84,-88,-120,-132,-148,-168,-228,-232,-280,-312,-340,-372,-408,-420,-520,-532,-660,-708,-760,-840,-1012,-1092,-1320,-1380,-1428,-1540,-1848,-5460]; for(i=1, #v, print(v[i]": "quadhilbert(v[i]))) quadhilbert(-4036) quadhilbert(-300003) quadhilbert(-3628843) Q(D,f) = lift(quadray(D,f)); Q(-4,31) Q(-11,2) Q(-15,3) Q(-179,2) Q(-2276,2) 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)) pari-2.7.5/src/test/in/rnf0000644000175000017500000000674212520212701013773 0ustar billbillnf=nfinit(y^2+1); rnfidealmul(rnfinit(nf,x^4-x-1),2,3) rnfidealup(rnfinit(nf,x),[;]) nf=nfinit(quadpoly(1129,y));ord=rnfpseudobasis(nf,quadray(1129,1));rnfsteinitz(nf,ord) rnflllgram(nf,x^3+2,rnfpseudobasis(nf,x^3+2)) rnfpseudobasis(nfinit(quadpoly(17,y)),x^11-11*x^10+31*x^9-26*x^8+36*x^7+7*x^6+15*x^5-27*x^4+26*x^3+20*x^2-33*x+42) rnfconductor(bnfinit(y),x^4+x^3-71*x^2+72*x+5184) K=bnfinit(quadpoly(1596,y),1); rnfbasis(K,rnfsteinitz(K,rnfpseudobasis(K,quadray(K,1)))); nf = nfinit(y^2-3); P = x^3 - 2*y; pr3 = idealprimedec(nf,3)[1]; pr2 = idealprimedec(nf,2)[1]; rnfdedekind(nf, P, pr2) rnfdedekind(nf, P, pr3) rnfdedekind(nf, P, pr2, 1) rnfdedekind(nf, P, pr3, 1) rnfdedekind(nf, P) rnfdedekind(nf, P, [pr2,pr3]) P = (y+1)*x^4 + x^2 + x + 2; rnfdedekind(nf, P, pr2, 1) rnfdedekind(nf, P, pr3, 1) rnfdedekind(nf, P) rnfdedekind(nf, P, [pr2,pr3]) K = nfinit(x^2-x+2); M = [1, 0, x; 0, x, 0; 0,0,2+x]; N = [1, 1, 1]; nfsnf(K, [M, N, N]) rnfisabelian(y,x) rnfisabelian(y^2+23,x^3+x^2-1) T = polcyclo(7, x+Mod(y, nf.pol)); rnfisabelian(nf.pol, T) rnfisabelian(nf, T) rnfisabelian(a^2+1,5*x^3+2) rnfisabelian(4*a^2+1, 9*x^2 + (12*a+3)*x + 2*a) pol = y^3+y^2-2*y-1; bnf = bnfinit(pol); T=rnfisnorminit(bnf, x^3-y); do(T,u,flag=0)=lift(lift(rnfisnorm(T,u,flag))); do(T,y) do(T,2,100) do(T,2,-2*3*5*7) T=rnfisnorminit(y^2+23, x^2-y); do(T,y) do(T,2,100) \\#1157 rnfisnorminit(y,x^2-Mod(2+y,y)); \\#1255 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) nf=nfinit(y); A = [[1,1/2;0,1],[1,1]]; nfhnfmod(nf, A, nfdetint(nf,A)) K=bnfinit(y^2-40); bnfisnorm(K,2, 0) bnfisnorm(K,6, 0) K=bnfinit(y^3-21); bnfisnorm(K,2) bnfisnorm(K,6) L=rnfinit(K,x^2-y); v = [2,1/2,x+y,Mod(1,K.pol),Mod(1/2,K.pol),Mod(y,K.pol),Mod(1,L.polabs),Mod(1/2,L.polabs),Mod(x,L.polabs),Mod(x+y/2,L.pol),y,z,Mod(y+1/2,y^2+1),[1]~,[1,2]~,[1,y]~,[1,I]~, y+I,x^2]; f=[rnfalgtobasis,rnfbasistoalg,rnfeltabstorel,rnfeltreltoabs,rnfeltup,rnfeltdown,rnfelttrace,rnfeltnorm]; test(L,v) = { for (i=1,#v, print(i,":"); for (j=1,#f, print(iferr(f[j](L,v[i]), E,E))) ); my (K = L.nf); for (i=1,#v, print(i,":"); print(iferr(rnfcharpoly(K,x^2-y,v[i]),E,E)) ); } test(L,v); KQ = nfinit(y+1); LQ = rnfinit(KQ, x^2-y); vQ = [2,1/2,x+y, Mod(1/2,KQ.pol), y, Mod(Mod(x/2+1,KQ.pol),LQ.pol), Mod(x,LQ.pol), Mod(x,LQ.polabs), Mod(x+y/2,x^2-y), x, [1]~,[1,2]~,[y]~]; test(LQ, vQ); nf = nfinit(y); rnf = rnfinit(nf,x^2-2); rel = Mod(Mod(1,y)+0*y,x^2-2); a = rnfeltreltoabs(rnf,rel) variable(lift(a)) Labs = nfinit(L.polabs); idL = idealhnf(Labs, x^3+x^2+10); idK = idealhnf(K, y^2+10*y+5); id = rnfidealabstorel(L,Labs.zk*idL) rnfidealnormabs(L,id) == idealnorm(Labs, idL); m = rnfidealreltoabs(L, id) mathnf(matalgtobasis(Labs,m)) == idL m = rnfidealup(L, idK) rnfidealdown(L, m) == idK m = rnfidealdown(L, Labs.zk*idL) rnfidealup(L, m) \\ V=concat(v, [[;], [], 0, [[;],[]], idealprimedec(K,2)[1], idK, idL, Labs.zk*idL, id]); f=[rnfidealhnf,rnfidealreltoabs,rnfidealabstorel,rnfidealdown,rnfidealup,rnfidealnormrel,rnfidealnormabs,rnfidealtwoelt]; { for (i=1,#V, print(i,":"); for (j=1, #f, print(iferr(f[j](L,V[i]),E,E)) ) ) } rnfidealmul(L, 0,1) rnfidealmul(L, 1,0) rnfidealmul(L, x,y) rnfidealmul(L, y,x) rnfidealmul(L, id,x) rnfidealmul(L, x,id) rnfdet(L,[[;],[]]) rnfdet(K,[[;],[]]) rnfdet(K,id) rnfbasis(bnfinit(y^2-1105),x^2-y) \\#1508 K=nfinit(y); L=rnfinit(K,x^3-2); rnfeltdown(L,Mod(Mod(1,K.pol),L.polabs)) \\#1530 L=rnfinit(nfinit(y^2-3),x^2+23); rnfidealtwoelt(L, [[1;0], [1/104]]) pari-2.7.5/src/test/in/ploth0000644000175000017500000000221112502252164014326 0ustar billbill\e \p19 t=plothsizes(); plotinit(0,t[1]-11,t[2]-11) plotscale(0,0,1000,0,1000); plotbox(0,500,500) plotdraw([0,0,0]) psdraw([0,0,0]) 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=-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) 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) plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) psploth(x=-5,5,sin(x)); psplothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500),1); plotmove(0,50,50);plotrbox(0,50,50) plotrline(0,150,100) plotcolor(0,4); plotcursor(0) plotrmove(0,5,5); plotcursor(0) plotrpoint(0,20,20) 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,,1) plotinit(1); plotcopy(0,1, 300,0); plotclip(1); plotdraw([1,10,10]); plotinit(100) pari-2.7.5/src/test/in/trans20000644000175000017500000000216712530662441014427 0ustar billbillOVERFLOW_EXPONENT=if(precision(1.)==38, 2^50, 2^20); default(realprecision,38); default(parisize,20*10^6); exp(quadgen(5)) exp(Mod(x,x^2+1)) iferr(exp(""),E,E) N=2^64; O(2^0)^N iferr(O(2^0)^-N,E,E) 0^N Pol(1)^N (8+O(x^2))^(1/3) (8+O(x^2))^(1/2) sqrt(Mod(1,y)*(1+x+O(x^2))) sqrt(4+x+O(x^2)) iferr(O(x)^0.5,E,E) O(1)^0.5 (1+x+O(x^2))^0.5 iferr(O(x)^((2^65)/3),E,E) iferr(""^0,E,E) iferr(0^Mod(1,3),E,E) N=2^16; y=x^N; y^3 iferr(y^OVERFLOW_EXPONENT,E,E) iferr(0.^(2.^64),E,E) agm(1,1) agm(-1,1) agm(1+x+O(x^10),1) agm(1,[1,2]) log(4+O(3^4)) obj=[Mod(1,3), O(3^5), 3 + O(3^5),I]; test(f,p)=print(iferr(f(p),E,E)); [test(f,p) | f<-[exp,log,cos,sin,tan,cotan];p<-obj]; tan(1+I) cotan(2) asin(1+O(x^3)) asin(-1+O(x^3)) asinh(I+O(x^3)) asinh(-I+O(x^3)) acosh(1+O(x^3)) acosh(1+x^2+O(x^3)) acosh(2+x+O(x^3)) acos(1+O(x^3)) sinh(I) w=Pi/4; test(z)= my(a=expm1(z),b=exp(z)-1); printf("%.1e\n", abs(a-b)/abs(a)); for (i=0,7, z=1e-20+i*w; test(z)) for (i=0,7, z=1e-20+i*w+I; test(z)) erfc(1/2+I) erfc(-1/2+I) expm1(3/4) expm1(1) forstep(x=1, 1+2*Pi, Pi/2, if(abs(expm1(I*x)-exp(I*x)+1) > 1e-38,print(x))) default(realprecision,2003); log(exp(1.5)) - 1.5 pari-2.7.5/src/test/in/aurifeuille0000644000175000017500000000057011636712103015515 0ustar billbillalias(factor_Aurifeuille,"_factor_Aurifeuille") do(d, a) = polcyclo(d, a) / factor_Aurifeuille(a, d); do(35, -7*3^2) do(35, 5*3^2*7^2) do(70, 7*3^2) do(70, -5*3^2) do(44, 2*11*9^2) do(44, 2*11) do(12,6) do(4,8) do(100,2) alias(factor_Aurifeuille_prime,"_factor_Aurifeuille_prime") do(d, a) = polcyclo(d, a) / factor_Aurifeuille_prime(a, d); do(12, 2) do(15, 5) do(30, 3) pari-2.7.5/src/test/in/padic0000644000175000017500000000150612573015517014275 0ustar billbillpadicappr(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) test(p, e = 1)= { my (N = 7*p^2); for (i=0,10,if (!ispower(i+O(p^e), N), print([i,p,e]))); for (i=1,10,if (!ispower((i+O(p^e))^N, N), error([i,p,e]))); } test(2) test(2,2) test(2,3) test(3) test(3,3) test(11,3) test(nextprime(2^64),3) polrootspadic(x^3-x+8, 2, 6) f = subst(x^3-x+8, x, x + Mod(y,y^2+y+1)); padicappr(f, Mod(1+O(2^10)-y, y^2+y+1)) \\#1424 lift(1/2 + O(2)) s=3+3^2+O(3^5) t=2+2^2+O(2^5) f=[cosh,sinh,tanh]; { for (i=1,#f, print(f[i](s)); print(f[i](O(x))); ) } gamma(s) gamma(t) p=2^64+13; gamma(3 + O(p^2)) gamma(-3 + O(p^2)) lngamma(17+O(3^5)) gamma(1/5+O(2^2)) gamma(1/5+O(2^3)) gamma(123+O(2^7)) gamma(123+O(2^8)) gamma(29+O(2^5)) gamma(29+O(2^6)) I + O(5^3) pari-2.7.5/src/test/in/multiif0000644000175000017500000000061312413013143014646 0ustar billbillf(x)= { if(x==1,print(1)); if(x==1,print(1) ,print("default")); if(x==1,print(1) ,x==2,print(2)); if(x==1,print(1) ,x==2,print(2) ,print("default")); if(x==1,print(1) ,x==2,print(2) ,x==3,print(3)); if(x==1,print(1) ,x==2,print(2) ,x==3,print(3) ,print("default")); } for(i=1,4,f(i)); g(x)=if(x,return(1),return(2),return(3)); g(1) g(0) pari-2.7.5/src/test/in/random0000644000175000017500000000116312405547147014477 0ustar billbillff(p,f) = ffgen(p^f, 'a); doell(a)= { my(e, P); e = ellinit([1,1,3,4,5]*a); P = random(e); [P, ellisoncurve(e,P)]; } doff(p,f)=my(a = ff(p,f)); print(random(a)); doell(a); setrand(1); random(Mod(1,3)) doff(2,3) doff(precprime(2^32), 3) doff(nextprime(2^64), 3) random(1.) random(x^5*Mod(1,7)) randomprime(2) randomprime([0,1]) randomprime([2.5,2.4]) randomprime([2.4,2.5]) randomprime() randomprime(10) randomprime([2^100, 2^100 + 2^20]) for (i=1,10, a = random([15,20]); if (a < 15 || a > 20, print(a))) s=getrand(); v=vector(10,i,random()); setrand(s); w=vector(10,i,random()); if(v != w,error("setrand")); random("") pari-2.7.5/src/test/in/intnum0000644000175000017500000000465112405547147014536 0ustar billbilldefault(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]; \p96 check(intcirc(s=1, 0.5, zeta(s)), 1) check(intlaplaceinv(x=2, 1, 1/x), 1) m = intnumstep(); check(intlaplaceinv(x=2, 1, 1/x, m+1), 1) check(intlaplaceinv(x=5, 1, 1/x), 1) check(intlaplaceinv(x=100, 1, 1/x), 1) A = intmellininv(s=2,4, gamma(s)^3); tab = intfuncinit(t=[-oo, 4.5],[oo, 4.5], gamma(2+I*t)^3, 1); check(intmellininvshort(2,4,tab), A) f(x) = 1/(exp(x)-1) - exp(-x)/x; 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) 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, [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) 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) check(intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)), 3/10) check(intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)), 3/10) tab = intnuminit(0,[oo,-I], m+1); check(intnum(x = 0, oo, sin(x)^3*exp(-x), tab), 3/10) check(intnum(x = 0, [oo, -I], x^2*sin(x)), -2) 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) \\ \p 308 a = sumpos(n=1, 1/(n^3+n+1)); 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) 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)) \\ check(suminf(n=1, 2^(-n)), 1) check(sumpos(n=1, 2^(-n)), 1) check(sumnum(n=1,[2,log(2)],2^(-n), intnumstep()+1, 1), 1) \\ tab = sumnuminit(2,,-1); a = sumnumalt(n=1,2,1/(n^3+n+1),tab,1); b = sumalt(n=1,(-1)^n/(n^3+n+1)); check(a, b) \p96 T=intnuminitgen(t,0,[1],exp(2*sinh(t))); check(intnum(x=0,[1],1/(1+x^2),T), Pi/2) T=intnuminitgen(t,0,[[1],1],exp(t-exp(-t))); check(intnum(x=0,[[1],1],exp(-x),T), 1) intfourierexp(t=0,[[1],1], 1/2, exp(-t^2)) intfouriercos(t=0,[[1],1], 1/2, exp(-t^2)) intfouriersin(t=0,[[1],1], 1/2, exp(-t^2)) \p38 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) 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)) pari-2.7.5/src/test/in/idealramgroups0000644000175000017500000000142212611142412016214 0ustar billbill{ K=nfinit(x^30 - 240*x^28 + 24364*x^26 - 1366520*x^24 + 46492470*x^22 - 994986280*x^20 + 13527103660*x^18 - 116596891080*x^16 + 634140564945*x^14 - 2144111162280*x^12 + 4349007947424*x^10 - 4933119511040*x^8 + 2746986107136*x^6 - 564152514560*x^4 + 40138752000*x^2 - 409600000); G=galoisinit(K); forprime(p=2,37, pr = idealprimedec(K,p)[1]; print(pr.p,":", apply(galoisidentify,idealramgroups(K,G,pr)))) } K=nfinit(x^6 + 12*x^5 + 60*x^4 + 376*x^3 + 80268*x^2 + 4569240*x + 66227068); G=galoisinit(K); D=idealprimedec(K,29)[1]; [idealfrobenius(K,G,D),idealramgroups(K,G,D)] K=nfinit(polcyclo(24)); G=galoisinit(K); P=idealprimedec(K,2)[1]; idealramgroups(K,G,P) \\#1755 P=x^8-12*x^6+36*x^4-36*x^2+9;N=nfinit(P);G=galoisinit(N); idealramgroups(N,G,idealprimedec(N,3)[1]) pari-2.7.5/src/test/in/resultant0000644000175000017500000000325712414214040015225 0ustar billbillallocatemem(20*10^6); do(P,Q)=my(v=variable()); substvec(polresultant(P,Q), v, vector(#v,i,i)); P = Pol([k,c,d,e,f,g]); Q = P'; do(P,Q) P = Pol([1,b,c,d,e]); Q = Pol([1,g,h,k,j]); do(P,Q) P = x^7 + x^3 + b*x^2 + c*x + d; Q = x^7 + x^3 + f*x^2 + g*x + h; do(P,Q) P = x^20 + a*x^5 + b; Q = x^20 + c*x^5 + d; do(P,Q) P = (x+a)^8; Q = (x+z)^8; do(P,Q) P = x^50 + 5*a*x^40 + 4*a*x^30 + a*x^20 + 2*a*x^10 + 3*a; Q = x^45 + 2*b*x^35 + b*x^25 + 4*b*x^15 + 5*b*x^5 + 6*b; do(P,Q) P = polcyclo(31); P = subst(P, x, a*x); Q = polcyclo(29); Q = subst(Q, x, a*x); do(P,Q) P = 1 + Polrev( vector(101, j, b^(101-j)) ); Q = 1 + Polrev( vector(101, j, b^(j-1)) ); do(P,Q) P = 1 + Polrev( vector(301,i,1) ); Q = 1 + Polrev( vector(201,i,i-1) ); do(P,Q) P = 1 + Polrev( vector(301,j, (j-1)^5) ); Q = 1 + Polrev( vector(301,j, (j-1)^4) ); do(P,Q) n = 110; polrandom(d, fudge) = x^d + Polrev(vector(d+1, i, round(2^32*sin(i+fudge)))); P = polrandom(n,0); Q = polrandom(n,1/2); do(P,Q) polresultant(-27673*x^2+322883101*x-1876122109136,x^4+4503599627370517) P=-27673*x^2+322883101*x-1876122109136; for(n=2,3,for(l=1,3,print(polresultant(P*x^l+1,n*x^4+4503599627370517)))) polresultant(z^1746-1, polcyclo(1973, z)) for(i=1,15,if(rnfequation(polcyclo(17,'y),x+y^i,1)[2]^17!=1,print("error",i))) \\ #1233 polresultantext(x^2+1, x^2-1) \\ #1234 polresultant(x^4+x^2+1, x^4-y, x, 0) p1=x2*(x3-x4);p2=x2*(x3-2*x4);polresultant(p1,p2,x1) polresultant(x,x,y) A = x*y; B = (x+y)^2; polresultant(A, B) polresultantext(A, B, y) \\ #1509 polresultantext(y^3+y,3*y^2+1,y) poldisc(x^3 + Mod(2,3)*x^2) 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) pari-2.7.5/src/test/in/printf0000644000175000017500000000445512515253503014520 0ustar billbilldefault(realprecision,38); aa=[1.0,2.0] bb=2.5 str="string" ii=10^100+1 /* d conversions */ printf("%%0.12ld for 1 : %0.12ld\n", 1) printf("%%ld for medium : %ld\n", 10^40+10^20+1) printf("%%ld for big : %ld\n", 7^1000) printf("%%ld for very big : %ld\n", 7^10000) /* x conversions */ printf("31 in base 16 == %x\n", 31) printf("%%X for medium : %X\n", 10^40+10^20+1) printf("%%#X for medium : %#X\n", 10^40+10^20+1) printf("%%x for 0: %x\n", 0) printf("%%#X for 0: %#X\n", 0) /* s conversion */ printf("%%10s for \"string\" : %10s\n", str) printf("%%.4s for \"string\" : %.4s\n", str) printf("%%*.*s for \"string\" : %*.*s\n", 10,2, str) printf("%%s for 1 : %s\n", 1) printf("%%s for aa : %s\n", aa) /* same as %Z */ printf("%%s for 4/3 : %s\n", 4/3) printf("%%s inter %%.2s %%4.2f for aa, bb, aa : %4s inter %.2s %4.2f\n", aa, bb, aa) Strprintf("%%s inter %%.2s %%4.2f for aa, bb, aa : %4s inter %.2s %4.2f\n", aa, bb, aa) printf("%%10.5s for 3.5 : %10.5s", 3.5) /* f conversion */ printf("%%10f for Pi : %.10f|\n", Pi) printf("%%20.10f for 2.7 : %20.10f|\n", 2.7) printf("%%+20.10f for 2.7: %+20.10f|\n", 2.7) printf("%%-20.10f for 2.7: %-20.10f|\n", 2.7) printf("%%-*.*f for 2.7: %-*.*f|\n", 20, 10, 2.7) /* e conversion */ printf("%%20.10e for 2.7 : %20.10e|\n", 2.7) printf("%%+20.10E for 2.7: %+20.10E|\n", 2.7) printf("%%-20.10e for 2.7: %-20.10e|\n", 2.7) printf("%%-20.10E for ii : %-20.10E|\n", ii) printf("%%e for 1+0*I : %E\n", 1+0*I) /* g conversion */ printf("%%8.3g for 3.14159: %8.3g\n", 3.14159) printf("%%8.3G for ii : %8.3G\n", ii) printf("%%8.3g for ii : %8.3g\n", ii) printf("%%-20.10g for 4/3 : %-20.10g|\n", 4/3) printf("%%20.13e for 4/3 : %20.13e|\n", 4/3) printf("%%e for 4/3 : %e|\n", 4/3) /* error tests */ printf("%missing argument to format\n") /* ERROR : %m is not a valid format */ printf("%d missing argument to format\n") /* ERROR : missing argument(s) to format */ printf("%%-20.10g for aa : %-20.10g\n", aa) /* ERROR : aa is not a t_REAL */ \\regression tests 10^38 + 1. printf("%.100f",1.) printf("%1.0f",0) printf("%.6f",5e-5) \\ conversions using gtolong() printf("%c",97.5) 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) default(format,"f.5") -0.00000000000000000000000000000000000000293873587705572 pari-2.7.5/src/test/in/str0000644000175000017500000000015512366172547014033 0ustar billbillv=Vecsmall("hello world!") Strchr(v) Strtex(Mat(1/2)) Strtex((x+y)^3/(x-y)^2) Str(x) Str(1/2) Str("a","b",1) pari-2.7.5/src/test/in/err0000644000175000017500000001203412413013143013765 0ustar billbillf(x) = 1/x; g(N) = for(i = -N, N, f(i)); g(10) print(); f=matsolve; f(Mat(0), Col(1)) print(); (matsolve)(Mat(0), Col(1)) print(); a.foo=1/(1+a^2); g(x)=[x.foo]; g(I) print(); (x->1/x)(0) print(); ecm(N,t,B)= { for(a=1,t, iferr( my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellmul(E,[0,1]*Mod(1,N),B), err,if(errname(err)=="e_INV",return(gcd(lift(component(err,2)),N)) ,error(err)))); } ecm(2^64+1,10,200!) ecm2(N,t,B)= { for(a=1,t, iferr( my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellmul(E,[0,1]*Mod(1,N),B), err,return(gcd(lift(component(err,2)),N)) ,errname(err)=="e_INV")); } ecm2(2^64+1,10,200!) rev(A) = my(B=Ser(A)); serreverse(B); iferr(rev([0,0,0,2,2,4,8,4,16,12]),E,0); \\ e_COPRIME T=t^2-2;p=2;A=x^2+1;B=[x+t,x+t];r=polhensellift(A,B,[p,T],6) \\ e_DIM / e_TYPE M = matid(2); M[,1] = 1 M[,3] = 1 M[,1] = [1,2] M[,1] = [1,2,3]~ M[1,] = 1 M[3,] = 1 M[1,] = [1,2]~ M[1,] = [1,2,3] [;][1,] [;][,1] 1[1] issquare(1,&v[1]) 1[1,1] 1[,1] issquare(1,&v[,1]) 1[1,] issquare(1,&v[1,]) v=Vecsmall([1]); v[2] = 1 v[1] = Pi v[1] = 2^64 v[Pi] = 1 \\ RgM_check_ZM M = [1.,0;0,1]; qflll(M,1) \\ RgV_check_ZV addprimes(1.) \\e_MODULUS nfalgtobasis(nfinit(t^3-2),Mod(t,t^2+1)) \\e_DIM vector(-1,i,0) vectorv(-1,i,0) vectorsmall(-1,i,0) matrix(-1,1,i,j,0) matrix(1,-1,i,j,0) next(-1) break(-1) v[-1] v[#v+1] subst(x,1,0) exp(1/x) cos(1/x) sin(1/x) tan(1/x) cotan(1/x) atan(1/x) asin(1/x) acos(1/x) asinh(1/x) acosh(1/x) atanh(1/x) lngamma(x) besselj(2,1/x) besseljh(2,1/x) besselk(2,1/x) besselk(1/3,O(x)) besseln(2,1/x) besseln(1/3,O(x)) polylog(2,1/x) sqrt(x) sqrt(2+O(2^2)) sqrtn(x,3) sqrtn(2+O(2^2),3) log(x) log(0) abs(x+O(x^2)) vecmax([]) vecmax([], &i) vecmin([]) vecmmin([], &i) vecmax(matrix(0,2)) L=List(); listput(L, x, -1) listinsert(L,x,-1) listinsert(L,x,10) listpop(L) ellj(Mod(1,2)) ellj(Qfb(1,1,1)) eta(1+O(2)) eta(1/x) K = nfinit(y^2+1); idealhnf(K, Qfb(1,1,1)) idealfactor(K, [;]) idealval(K, [;], idealprimedec(K,2)[1]); idealdiv(K,2,0, 1); valuation(Pi,2) x^Pi x^x 0^0. agm([],[]) sin(1/2+O(2^1)) cos(1/9+O(3^1)) exp(1/9+O(3^1)) G=[[Vecsmall([6,11,14,16,17,1,21,24,26,27,2,29,30,3,31,4,5,34,36,37,7,39,40,8,41,9,10,42,12,13,15,44,45,18,46,19,20,47,22,23,25,28,48,32,33,35,38,43]),Vecsmall([5,10,13,15,1,17,20,23,25,2,27,28,3,30,4,31,6,33,35,7,37,38,8,40,9,41,11,12,42,14,16,43,18,45,19,46,21,22,47,24,26,29,32,48,34,36,39,44]),Vecsmall([15,25,28,1,4,31,35,38,2,9,41,3,12,42,5,6,16,43,7,19,46,8,22,47,10,11,26,13,14,29,17,18,32,48,20,21,36,23,24,39,27,30,33,34,44,37,40,45]),Vecsmall([30,40,1,42,14,13,45,2,47,24,23,4,5,6,29,28,3,7,48,34,33,9,10,11,39,38,8,15,16,17,12,19,20,21,44,43,18,25,26,27,22,31,35,36,37,32,41,46]),Vecsmall([7,1,44,18,37,20,2,29,3,17,5,35,43,48,45,33,21,39,8,27,10,15,28,42,30,13,6,36,19,32,34,25,38,47,40,23,11,16,4,12,14,46,26,9,22,24,31,41])],Vecsmall([2,2,2,2,3])]; galoissubgroups(G) bnrstark(bnrinit(bnfinit(y^2+1),2,1)) bnrstark(bnrinit(bnfinit(y^2-2),[4,[1,1]],1)) quadray(-16,1) quadray(bnfinit(x^3-2),1) galoissubcyclo(-1) galoissubcyclo(6,Mod(1,3)) galoissubcyclo(6,[;]) galoissubcyclo(6,Mat(1)) galoissubcyclo(znstar(5),matid(2)) galoissubcyclo(bnrinit(bnfinit(y^2+1),1,1), 2) polsubcyclo(-1,2); polsubcyclo(2,-1); random(-1) znprimroot(0) sqrtint(-1) sqrtnint(-1,2) sqrtnint(2,-2) znprimroot(8) polroots(x^2+Mod(1,2)) prime(-2) addprimes(-1) padicappr(x^2+1+O(3^5), 1+O(5)) factorpadic(x^2+1,2,-1) polrootspadic(x^2+1,2,-1) ellinit([1+O(3),1+O(5)]) ellwp([1,I],I) ellsigma([1,I],x,1) ellsigma([1,I],1,1) E=ellinit([1,1]); ellap(E) ellap(E,1) ellap(E,'x) elltaniyama(E,-1) ellheight(E,[2,2]) Qfb(0,0,0) quadpoly(2) qfbprimeform(2,5) qfbcomp(Qfb(1,1,1),Qfb(1,0,2)) \\qfbcompraw(Qfb(21,1,2),Qfb(112,0,2)) galoisinit(x^2) galoisinit(2*x) ellL1(1,-1) ellheegner(ellinit([0,-1,1,-10,-20])) ellheegner(ellinit([0,0,1,-7,6])) substpol(x+O(x^2),x^3,x) intformal(1/(x^2+1)) component(x,-1) component(O(x),2) component(Vecsmall([]),1) polcoeff(O(x),2) polcoeff(x+O(x^2),2) polcoeff([],2) polcoeff([],-1) polcoeff("",2) matcompanion(0*x) matrixqz(Mat([1,2])) matrixqz(Mat(0)) vecextract([1],[-1]); vecextract([1],[2]); idealfrobenius(K,galoisinit(K),idealprimedec(K,2)[1]) nfisincl(x^2,x^2) polcompositum(x^2,x) rnfdedekind(K, x^2+x-1/3) hilbert(Mod(1,2),1) hilbert(Mod(1,3),Mod(1,5)) hilbert(Mod(1,3),2,0) znorder(0) znorder(Mod(2,4)) contfrac(1e100) contfrac(1.,[1],10) contfrac(1,,-1) contfracpnqn(matrix(3,1)); divisors(1/2) idealstar(K,0) idealstar(K,1/2) idealaddtoone(K,[[;]]) idealdiv(K,1,2,1) idealred(K,matid(2),[]) idealtwoelt(K,matid(2),1/2) rnf=rnfinit(K,x^2-y); rnfeltdown(rnf, x) matid(-1) polinterpolate([1,1],[2,3],Pi) modreverse(Mod(-x^3+9*x,x^4-10*x^2+1)) rnfnormgroup(bnrinit(bnfinit(K),9), x^3-2) concat([1,2],[3,4]~) concat([]) concat(List()) mathnfmod([1;2],2) polsturm(x^2) removeprimes(2) forstep(a=1,2,0,) e=ellinit([1,1+O(31^2)]); e.omega e.eta e.area e=ellinit([0,1]); e.tate ellorder(e, [0,0]*Mod(1,2)) thue(x*(x^3-2),0); direuler(p=2, 10, 2/(1-p*X)) solve(x=0,1,x^2+1) warning(1) \\ backward compatibility. Eventually remove inv(x) = trap (e_INV, INFINITY, 1/x) inv(2) inv(0) trap (e_INV, INFINITY, log(0)) pari-2.7.5/src/test/in/sumiter0000644000175000017500000000106212366172547014711 0ustar billbillHEAP=[23, if(precision(1.)==38,200,230)]; \p 19 \e intnum(x=0,Pi,sin(x)) intnum(x=0,4,exp(-x^2)) intnum(x=1,[1],1/(1+x^2)) - Pi/4 intnum(x=-0.5,0.5,1/sqrt(1-x^2)) - Pi/3 intnum(x=0,[[1],-I],sin(x)/x) - Pi/2 \p 38 prod(k=1,10,1+1/k!) prod(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))) prodinf(n=0,-2^-n/(1+2^(-n+1)),1) solve(x=1,4,sin(x)) sum(k=1,10,2^-k) sum(k=1,10,2.^-k) 4*sumalt(n=0,(-1)^n/(2*n+1)) 4*sumalt(n=0,(-1)^n/(2*n+1),1) sumdiv(8!,x,x) suminf(n=1,2.^-n) 6/Pi^2*sumpos(n=1,n^-2) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/disc0000644000175000017500000000002512314242551014123 0ustar billbillpoldisc(Mod(1, 2)*x) pari-2.7.5/src/test/in/ffisom0000644000175000017500000001217512366172547014513 0ustar billbillfpisom2(l,P,Q)= { my(L); x=variable(P); L=factorff(lift(P),l,lift(subst(Q,x,MAXVARN)))[,1]; L=-subst(L,x,0); subst(lift(L),MAXVARN,x)*Mod(1,Q); } fptest(l,P,Q)= { my(C); C=fpisom2(l,P,Q); print(vector(length(C),i,if(subst(P,x,C[i])==0,0,error("fptest("a","l","P","Q")")))); C; } print("-------------e=0--------------"); fptest(13,x^4+2*x^2+2*x+1,x^4+2*x^3+2*x^2+1); fptest(131,x^10+126*x^5+78,x^10+128*x^5+70); fptest(11,x^3+2*x^2+6*x+7,x^3+5*x^2+3*x+6); fptest(1009,x^17+x+25,x^17+42*x^16+61*x^15+952*x^14+113*x^13+398*x^12+694*x^11+238*x^10+465*x^9+308*x^8+545*x^7+145*x^6+79*x^5+896*x^4+515*x^3+63*x^2+808*x+1008); fptest(1009,x^16+x^15+964*x^14+911*x^13+650*x^12+165*x^11+451*x^10+957*x^9+342*x^8+616*x^7+212*x^6+595*x^5+130*x^4+63*x^3+340*x^2+537*x+694,x^16+11); fptest(1009,x^20+595*x^19+863*x^18+194*x^17+127*x^16+364*x^15+31*x^14+869*x^13+422*x^12+663*x^11+669*x^10+28*x^9+9*x^8+937*x^7+35*x^6+292*x^5+302*x^4+441*x^3+863*x^2+118*x+1,x^20+919*x^19+582*x^18+634*x^17+881*x^16+563*x^15+966*x^14+892*x^13+894*x^12+40*x^11+322*x^10+961*x^9+431*x^8+172*x^7+641*x^6+599*x^5+1001*x^4+718*x^3+582*x^2+851*x+1); fptest(23,x^20+x+5,x^20+4*x^19+15*x^18+17*x^17+6*x^16+3*x^15+8*x^14+16*x^13+11*x^12+20*x^11+x^10+20*x^9+11*x^8+16*x^7+8*x^6+3*x^5+6*x^4+17*x^3+15*x^2+4*x+1); fptest(10007,x^30+9557*x^29+7812*x^28+7090*x^27+7645*x^26+4110*x^25+3307*x^24+5763*x^23+7900*x^22+3872*x^21+8123*x^20+4076*x^19+3265*x^18+3777*x^17+3398*x^16+5674*x^15+4018*x^14+6820*x^13+6479*x^12+984*x^11+5652*x^10+1129*x^9+7573*x^8+1822*x^7+837*x^6+4169*x^5+4787*x^4+1616*x^3+5185*x^2+2649*x+1933,x^30+x+2); fptest(67108879,x^30+67107859*x^29+502860*x^28+41752426*x^27+47923483*x^26+56252217*x^25+29702433*x^24+34566275*x^23+43724662*x^22+43031233*x^21+6098024*x^20+7989587*x^19+27885185*x^18+50348895*x^17+46982824*x^16+27081672*x^15+64032686*x^14+24948096*x^13+22483934*x^12+62577008*x^11+33925741*x^10+21192636*x^9+60947997*x^8+24913164*x^7+28577178*x^6+19817925*x^5+12532882*x^4+28467302*x^3+18972253*x^2+4366256*x+32457808,x^30+50150808*x^29+63186895*x^28+49093281*x^27+9998922*x^26+33903391*x^25+64572368*x^24+18465285*x^23+9365844*x^22+146044*x^21+52005244*x^20+51914117*x^19+50853399*x^18+47731827*x^17+63045151*x^16+30915147*x^15+52060592*x^14+54056376*x^13+50213837*x^12+47827172*x^11+33322080*x^10+37183875*x^9+59905379*x^8+12524247*x^7+53983516*x^6+18456131*x^5+47473382*x^4+30607833*x^3+17662487*x^2+66659374*x+2497577); print("-------------e=1--------------"); fptest(11,x^11+x^9+9*x^7+3*x^6+8*x^5+7*x^4+5*x^3+x^2+10*x+3,x^11+10*x+1); fptest(7,x^14+x+4,x^14+5*x^8+5*x^7+x^2+2*x+5); fptest(5,x^30+4*x^26+4*x^25+3*x^20+3*x^16+3*x^12+3*x^8+4*x^6+3*x^4+x^2+x+4,x^30+x^3+x+3); fptest(7,x^35+2*x^2+x+6,x^35+2*x^28+6*x^24+3*x^23+4*x^22+4*x^21+3*x^17+5*x^16+2*x^15+x^14+5*x^13+x^12+4*x^11+4*x^10+5*x^9+4*x^8+3*x^7+2*x^6+6*x^5+3*x^4+x^3+2*x^2+2*x+3); print("-------------e=2--------------"); fptest(2,x^4+x+1,x^4+x^3+1); fptest(5,x^25+2*x^3+3*x+2,x^25+2*x^19+3*x^17+4*x^16+2*x^15+x^14+x^13+3*x^12+2*x^11+4*x^10+2*x^8+4*x^7+4*x^5+2*x^4+3*x^3+2*x+2); fptest(3,x^18+x^3+2*x+1,x^18+x^17+2*x^16+2*x^15+x^14+x^13+x^12+x^11+x^10+2*x^9+x^7+2*x^5+x^4+2*x^3+1); fptest(2,x^20+x^3+1,x^20+x^14+x^13+x^10+x^7+x^5+x^4+x^3+x^2+x+1); print("-------------e=3--------------"); fptest(2,x^8+x^4+x^3+x+1,x^8+x^6+x^5+x^3+1); fptest(3,x^27+x^5+x^3+x^2+2*x+2,x^27+x^25+2*x^24+x^23+x^22+x^20+x^17+2*x^15+2*x^13+x^12+2*x^11+2*x^10+x^9+2*x^8+x^7+2*x^6+2*x^5+2*x^4+2); fptest(2,x^40+x^5+x^4+x^3+1,x^40+x^38+x^37+x^36+x^35+x^34+x^32+x^31+x^30+x^29+x^28+x^25+x^23+x^19+x^16+x^15+x^13+x^11+x^10+x^9+x^7+x^5+x^3+x^2+1); print("-------------e>=4--------------"); fptest(2,x^16+x^15+x^14+x^12+x^7+x^6+x^5+x^2+1,x^16+x^5+x^3+x+1); fptest(2,x^32+x^7+x^3+x^2+1,x^32+x^29+x^28+x^27+x^25+x^24+x^22+x^18+x^17+x^15+x^14+x^13+x^11+x^5+x^4+x^3+1); fptest(2,x^64+x^4+x^3+x+1,x^64+x^59+x^57+x^56+x^53+x^52+x^51+x^48+x^47+x^46+x^45+x^42+x^40+x^39+x^35+x^33+x^32+x^30+x^29+x^26+x^25+x^24+x^22+x^21+x^20+x^18+x^17+x^14+x^13+x^11+x^10+x^7+x^5+x^2+1); fptest(2,x^48+x^5+x^3+x^2+1,x^48+x^46+x^45+x^43+x^42+x^40+x^39+x^38+x^37+x^35+x^34+x^33+x^31+x^29+x^25+x^19+x^18+x^16+x^12+x^9+x^4+x^3+1); print("----------large p---------------"); fptest(300007,x^29+111826*x^28+192245*x^27+118259*x^26+116591*x^25+90193*x^24+179240*x^23+218526*x^22+105853*x^21+39775*x^20+120877*x^19+141649*x^18+95990*x^17+253141*x^16+113157*x^15+174998*x^14+231363*x^13+45405*x^12+279688*x^11+260746*x^10+295341*x^9+186647*x^8+1286*x^7+5846*x^6+226308*x^5+155249*x^4+161003*x^3+892*x^2+124319*x+45791 ,x^29+144375*x^28+258947*x^27+2448*x^26+213576*x^25+275912*x^24+295000*x^23+16021*x^22+62890*x^21+223177*x^20+133874*x^19+291070*x^18+268346*x^17+231097*x^16+27675*x^15+181579*x^14+144969*x^13+37193*x^12+236074*x^11+44381*x^10+87819*x^9+180121*x^8+195512*x^7+82624*x^6+113318*x^5+67595*x^4+26623*x^3+13359*x^2+191742*x+143596); print("----------huge p---------------"); p=nextprime(3^64);P=ffinit(p,19);Q=poltschirnhaus(P);fptest(p,P,Q); p=nextprime(3^66);P=ffinit(p,19);Q=poltschirnhaus(P);fptest(p,P,Q); p=1208925819614629174706189; P=x^3+154950186819311566804335*x^2+793256884583803289109038*x+629557146926040851399629; Q=factormod(polcyclo(13),p)[3,1]; fptest(p,P,Q); pari-2.7.5/src/test/in/zetak0000644000175000017500000000067212571637070014340 0ustar billbilldefault(realprecision,38); do(p) = { my(v = [-3,3,2,0,1/2+I]); my(znf = zetakinit(p)); for(i=1,#v, print(zetak(znf,v[i]))); } allocatemem(20*10^6); do(y^2-3); do(y^2+3); do(y^3-4*y+2); do(y^3-2); do(y^5-3*y^2+y+2); zeta(3+O(5^10)) zeta(1 + I/100) zeta(1000.5) zeta(1000) zeta(100) zeta(31) zeta(100+100*I) zeta(60+I) zeta(-1000+I) zeta(2+O(2^10)) zeta(2^64) zeta(-2^64) iferr(zeta(-1-2^64),E,E) zeta(2+1e-101*I) zeta(1.01) zeta(1e-32) pari-2.7.5/src/test/in/concat0000644000175000017500000000120112366172547014463 0ustar billbillA=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9; matconcat([A, B]) matconcat([A, C]~) matconcat([A, B; C, D]) matconcat([1, [2,3]~, [4,5,6]~]) matconcat([1, [2,3], [4,5,6]]~) matconcat([B, C; A, D]) matconcat([]) concat("x",2) concat([;],1) concat([;],[]) concat([;],[1]) concat(1,[;]) concat([],[;]) concat([1],[;]) concat(1,2) concat(1,[2]) concat(1,Mat(2)) concat(1,A) concat(Mat(2),1) concat(A,1) concat([1,2],[]~) concat([1,2],[1]~) concat([1,2],[1,2]~) concat([2,3], matid(2)) concat([]~,[1,2]) concat([3]~,[1,2]) concat([2,3]~,[]) concat([2,3]~,[1]) concat([2,3]~,[1,2]) concat([;],[]) concat(A,[1,2]) concat(List([[1],[2]])) concat([1]~,Mat(2)) pari-2.7.5/src/test/in/ser0000644000175000017500000000062612601623017014000 0ustar billbilldefault(realprecision,38); s=x+x^2+O(x^5) 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) O(1/x^2) trace(I*x+1+O(x^2)) norm(I*x+1+O(x^2)) a=Ser(vector(200,i,i)); a^2 == a*(a+1) - a \\ test RgX_mullow, RgX_sqrlow 3+O(1) serreverse(x/2+O(x^2)) serreverse(tan(x)/2) Ser(x+y+O(x^2),x) Ser(x+y+O(x^2),y) Ser("") pari-2.7.5/src/test/in/ellff0000644000175000017500000000515412405547147014313 0ustar billbill\\package:seadata test(p,n=0,v='a,w=1)= { my(a=if(n,ffgen(p^n,v),p)); my(E=ellinit([w,1,1-w,0,a+3],a)); my(G=ellgenerators(E)); if (#G==0,return); [d1]=ellgroup(E); my(P=random(E)); G=G[1]; if(ellorder(E,G)!=d1,error([p,n,0])); if(ellmul(E,G,d1)!=[0],error([p,n,1])); if(ellmul(E,P,d1)!=[0],error([p,n,2])); if(d1%ellorder(E,P)!=0,error([p,n,3])); if (d1<10^7, P=ellmul(E,G,1023); if(elllog(E,P,G)!=1023%d1,error([p,n,4])); ); } test(2); test(2,78); test(2,100); test(2,1,,0); test(2,2,,0); test(2,4,,0); test(2,6,,0); test(2,101,,0); test(3,,,0); test(3,50,,0); test(3,51,,1); test(5); test(5,3); test(5,50); test(7,3); test(7,51); test(11,2); test(13,41); test(17,2); test(1009,3); test(1013,7); test(1009,11,'x); test(17); test(41); test(1073741827); test(nextprime(2^65),2); a=ffgen(101^3,'a); E=ellinit([1,3],a); E.j E.disc P=random(E);Q=random(E); R=elladd(E,P,Q); elladd(E,ellsub(E,R,P),ellneg(E,Q)) N=ellcard(E);ellmul(E,P,N) check(a)= { my(E,P,N); E=ellinit(ellfromj(a),a); N=ellcard(E); if ((N==1)!=(#random(E)==1),error(a)); for(i=1,4, P=random(E); if(ellmul(E,P,N)!=[0],error(a))); ellgenerators(E); } { for(a=1,8, g = ffprimroot(ffgen(2^a,'t)); for(i=0,2^a-2, check(g^i))); for(a=1,6, g = ffprimroot(ffgen(3^a,'t)); for(i=0,3^a-2, check(g^i))); for(a=1,4, g = ffprimroot(ffgen(5^a,'t)); for(i=0,5^a-2, check(g^i))); } checkt(p,n,f,B=100)= { my(a=ffgen(p^n,'a)); for(i=1,B, my(E,N,b); 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)); if(#ellmul(E,random(E),N)>1,error([p,n,f],b))); } checkt(3,5,0); checkt(3,6,0); checkt(3,5,1); checkt(3,6,1); checkt(3,5,2); checkt(3,6,2); checkt(7,5,0); checkt(7,6,0); checkt(11,5,0); checkt(11,6,0); checkt(7,5,1); checkt(7,6,1); checkt(13,5,1); checkt(13,6,1); checkt(11,6,2); checkt(13,5,2); checkt(18446744073709551667,2,0,10); checkt(18446744073709551667,3,0,10); checkt(18446744073709551667,2,1,10); checkt(18446744073709551667,3,1,10); checkt(18446744073709551667,2,2,10); checkt(18446744073709551667,3,2,10); checkt(18446744073709551629,2,0,10); checkt(18446744073709551629,3,0,10); checkt(18446744073709551629,2,1,10); checkt(18446744073709551629,3,1,10); checkt(18446744073709551629,2,2,10); checkt(18446744073709551629,3,2,10); E=ellinit([a1,a2,a3,a4,a6]*Mod(1,2)); elldivpol(E,2) check(q)= { my(g,E,x = 1,y); g = ffprimroot(ffgen(q,'t)); E = ellinit(ellfromj(g)); for(i=1,10, x *= g; y = ellordinate(E,x); for(i=1,#y, if (!ellisoncurve(E,[x,y[i]]), error([x,y]))) ); } check(2^4) check(3^4) check((2^64+13)^4) pari-2.7.5/src/test/in/exact00000644000175000017500000000112411636712103014367 0ustar billbilldefault(realprecision,38); Mod(0,2)*x*1. Pol(Mod(0,2)) + 2 Mod(1,2)+Pol(Mod(1,2)) Ser(Mod(1,2)) + 1 (2+0*I)+I*Mod(0,4) a=b=Mod(2, 4) + Mod(2, 4)*I; a*b (Mod(0,2)+I)^2 Mod(0,2)/x a=Mod(1, 2)*x^10 + Mod(1, 2); 2*a a+a valuation(Mod(0,101),101) gcd(Mod(0,5),10) gcd(Mod(0,5),Mod(0,10)) { v = [[0,0,0,0], [0,0,0,Mod(0,2)], [1,0,0,Mod(0,2)], [1,0,0.,Mod(0,2)], [1,0,Mod(0,2),0.]]; for (i = 1, #v, w = v[i]; print1(Pol(w), " "); print1(Polrev(w), " "); print1(Ser(w), " "); w = vecextract(w, "-1..1"); print1(Pol(w), " "); print1(Polrev(w), " "); print1(Ser(w), " "); print(); ) } pari-2.7.5/src/test/in/sumformal0000644000175000017500000000015512314242552015213 0ustar billbillsumformal(1/n) sumformal(0) sumformal(1) sumformal(n) sumformal(n^2) sumformal(x*y + 1) sumformal(x*y + 1,y) pari-2.7.5/src/test/in/ranges0000644000175000017500000000160312413013143014454 0ustar billbill[2^100..2^100+3] [x^2+1|x<-[1..40],isprime(x)] [x|x<-primes(40)] [x|x<-[1..40],isprime(x)] [a^2+b^2|a<-[1..10];b<-[1..10],gcd(a,b)==1] [a^2+b^2|a<-[1..10],isprime(a);b<-[1..10],a!=b && isprime(b)] [[a,b,c]|a<-[1..5];b<-[1..a];c<-[1..b]] primes(100)[4..7] V=[1..5]; V[2..3] V[1..-2] V[-3..-1] V[^3] V=Vecsmall(V); V[2..3] V[1..-2] V[-3..-1] V[^3] M=matrix(5,5,i,j,i+5*j-5); M[2..3,2..3] M[1..2,1] M[1,1..4] M[1..3,] M[,1..3] M[1..5,1..-2] M[1..-2,1..-2] M[-3..-1,-3..-1] M[^3,2..3] M[^2,1] M[1,^4] M[^3,] M[,^3] M[^5,1..-2] M[1..-2,^-2] M[-3..-1,-3..-1] f(v,c=0)=my(a,b=[1,2]);[a,b[c]]=v;[a,b]; f([1,2],1) f([3,4],2) g(v)= { my(a,[b,c]=v,d=v,e=0,f=I); [a,b,c,d,e,f]; } h(v)= { local(a,[b,c]=v,d=v,e=0,f=I); [a,b,c,d,e,f]; } g([3,4]) h([3,4]) \\ #1552 [x|x<-[];y<-[]] [x|x<-[1..5];y<-[1..x-1];z<-[1]] [x|x<-[1..5];y<-[1..x], yx+y, X,Y) setbinop((x,y)->x+y, X) setbinop(x->x, X) pari-2.7.5/src/test/in/polygonal0000644000175000017500000000024212314242552015207 0ustar billbillP(n,s)=((s-2)*n^2-(s-4)*n)>>1; test(s)=for(n=0,10, if (!ispolygonal(P(n,s),s,&N) || N != n, error([n,s]))); for (s=4,10, test(s)) for (s=2^64, 2^64+10, test(s)) pari-2.7.5/src/test/in/det0000644000175000017500000000204512366172547013777 0ustar billbillM=[8, 520037431316, 0, 520037431316, 0, 520035574851, 0, 965887922181; 520037431316, 38628881218179226412880, 4958989308, 38629 323366757228004016, 73478513407, 38628858533840109643628, 4243910044575227, 71751970539224190286968; 0, 4958989308, 0, 4957132843, 0, 5710115047, -5940688, 0; 520037431316, 38629323366757228004016, 4957132843, 38629765515335229595152, 74231495611, 38629300680212375365180, 4243835813079616, 71752791774805257538227; 0, 73478513407, 0, 74231495611, -5940688, 0, 1856465, 0; 520035574851, 38628858533840109643628, 5710115047, 38629300680212375365180, 0, 38628836591317537513845, 4243835813079616, 71751920822489123831004; 0, 4243910044575227, -5940688, 4243835813079616, 1856465, 4243835813079616, -752982204, 7881921412974726; 965887922181, 71751970539224190286968, 0, 71752791774805257538227, 0, 71751920822489123831004, 7881921412974726, 133277068316447073113823]; matdet(M) matdet(M,1) centerlift(chinese(apply(p->matdet(M*Mod(1,p)),primes(200)))) centerlift(chinese(apply(p->matdet(M*Mod(1,p)),vector(5,i,nextprime(2^(128+i)))))) pari-2.7.5/src/test/in/number0000644000175000017500000000404512366172547014515 0ustar billbillHEAP=[92, if(precision(1.)==38,2736,2776)]; default(realprecision,154); Pi; default(realprecision,38); \e addprimes([nextprime(10^9),nextprime(10^10)]) bestappr(Pi,10000) gcdext(123456789,987654321) bigomega(12345678987654321) binomial(1.1,5) chinese(Mod(7,15),Mod(13,21)) content([123,456,789,234]) contfrac(Pi) contfrac(Pi,5) contfrac((exp(1)-1)/(exp(1)+1),[1,3,5,7,9]) contfracpnqn([2,6,10,14,18,22,26]) contfracpnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1]) core(54713282649239) core(54713282649239,1) coredisc(54713282649239) coredisc(54713282649239,1) divisors(8!) eulerphi(257^2) factor(17!+1) factor(100!+1,0) factor(40!+1,100000) factorback(factor(12354545545)) factor(230873846780665851254064061325864374115500032^6) factorcantor(x^11+1,7) centerlift(lift(factorff(x^3+x^2+x-1,3,t^3+t^2+t-1))) 10! factorial(10) factormod(x^11+1,7) factormod(x^11+1,7,1) setrand(1);ffinit(2,11) setrand(1);ffinit(7,4) fibonacci(100) gcd(12345678,87654321) gcd(x^10-1,x^15-1) hilbert(2/3,3/4,5) hilbert(Mod(5,7),Mod(6,7)) isfundamental(12345) isprime(12345678901234567) ispseudoprime(73!+1) issquare(12345678987654321) issquarefree(123456789876543219) kronecker(5,7) kronecker(3,18) lcm(15,-21) lift(chinese(Mod(7,15),Mod(4,21))) modreverse(Mod(x^2+1,x^3-x-1)) moebius(3*5*7*11*13) nextprime(100000000000000000000000) numdiv(2^99*3^49) omega(100!) precprime(100000000000000000000000) prime(100) primes(100) qfbclassno(-12391) qfbclassno(1345) qfbclassno(-12391,1) qfbclassno(1345,1) Qfb(2,1,3)*Qfb(2,1,3) qfbcompraw(Qfb(5,3,-1,0.),Qfb(7,1,-1,0.)) qfbhclassno(2000003) qfbnucomp(Qfb(2,1,9),Qfb(4,3,5),3) form=Qfb(2,1,9);qfbnucomp(form,form,3) qfbnupow(form,111) qfbpowraw(Qfb(5,3,-1,0.),3) qfbprimeform(-44,3) qfbred(Qfb(3,10,12),,-1) qfbred(Qfb(3,10,-20,1.5)) qfbred(Qfb(3,10,-20,1.5),2,,18) qfbred(Qfb(3,10,-20,1.5),1) qfbred(Qfb(3,10,-20,1.5),3,,18) quaddisc(-252) quadgen(-11) quadpoly(-11) quadregulator(17) quadunit(17) sigma(100) sigma(100,2) sigma(100,-3) sqrtint(10!^2+1) znorder(Mod(33,2^16+1)) forprime(p=2,100,print(p," ",lift(znprimroot(p)))) znstar(3120) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/lambert0000644000175000017500000000017412405547147014646 0ustar billbilldo(y)=my(x = lambertw(y)); exp(x)*x / y; do(-1) do(I) default(realprecision,38); do(2) default(realprecision,211); do(1e14) pari-2.7.5/src/test/in/partition0000644000175000017500000000155612366172547015242 0ustar billbilltest(N) = /* pentagonal numbers recurrence */ { my(s,t,p); p = vector(N); p[1] = 1; for (n=1, N-1, s = 0; t = n+1; for (k=1, n, t -= 2*k-1; /* n+1 - k(3k-1)/2 */ if (t<=0,break); s -= (-1)^k*p[t]; t -= k; /* n+1 - k(3k+1)/2 */ if (t<=0,break); s -= (-1)^k*p[t] ); p[n+1] = s; if (s != numbpart(n), error([n, s])) ); } test(10^4); numbpart(0) numbpart(52602) numbpart(147007) numbpart(10^15+2) partitions(0) partitions(1) partitions(9) partitions(9,3) partitions(-1) partitions(5,[3,4],[1,2]) forpart(v=-1,) forpart(v=5,print(Vec(v)),4,3) forpart(v=5,print(Vec(v)),[0,5],[2,4]) my(i=0); forpart(x=55,i++); i forpart(x=9,print(Vec(x))); forpart(x=11,print(Vec(x)),,5); forpart(x=12,print(Vec(x)),,[2,6]); forpart(x=23,print(Vec(x)),[3,6]); forpart(x=5, print(Vec(x)),[0,3]); forpart(x=15, print(Vec(x)),[0,3],7); pari-2.7.5/src/test/in/isprime0000644000175000017500000000065312366172547014676 0ustar billbillisprime(5368962301599408606279497323618896374219) isprime(4309513411435775833571) isprime(26959946667150639794667015087019630673557916260026308143510066298881) p=10^6+3; q=10^6+33; isprime(1+24*p*q, 1) isprime(1+232*p^2*q^3, 1) isprime([2,3,4]) isprime([2,3,4],1) isprime([2,3,4],2) ispseudoprime([1,3,4,5],2) \\isprime(2^3515+159, 2) 10 min \\isprime(2^2000+841, 2) 1 min \\isprime(2^1600+895, 2) 27s isprime(2^1000+297, 2) pari-2.7.5/src/test/in/minim0000644000175000017500000000230311706644717014331 0ustar billbill{d=[4,2,-2,-2,2,1,-2,2,2; 2,4,-2,0,0,0,-1,0,2; -2,-2,4,2,-2,1,1,-1,-2; -2,0,2,4,-3,1,0,-2,0; 2,0,-2,-3,4,-1,0,2,0; 1,0,1,1,-1,4,0,-1,1; -2,-1,1,0,0,0,4,-2,-2; 2,0,-1,-2,2,-1,-2,4,0; 2,2,-2,0,0,1,-2,0,4];} qfperfection(d) {d=[4,2,-2,2,2,-2,-1,0;2,4,-2,0,2,-2,1,-1; -2,-2,4,-2,0,2,1,-1; 2,0,-2,4,1,0,-2,0; 2,2,0,1,4,-1,1,-2;-2,-2,2,0,-1,4,-1,-1; -1,1,1,-2,1,-1,4,0;0,-1,-1,0,-2,-1,0,4];} qfperfection(d) d=[2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,2,1,0,1,1,1,1,1,1,1,1;-1,1,2,1,1,1,1,1, 1,1,1,1;-1,0,1,2,1,1,1,1,1,1,1,1;-1,1,1,1,2,1,1,1,1,1,1,1;-1,1,1,1,1,2,1,1,1,1,1 ,1;-1,1,1,1,1,1,2,1,1,1,1,1;-1,1,1,1,1,1,1,2,1,1,1,1;-1,1,1,1,1,1,1,1,2,1,1,1;-1 ,1,1,1,1,1,1,1,1,2,1,1;-1,1,1,1,1,1,1,1,1,1,2,1;-1,1,1,1,1,1,1,1,1,1,1,2]; qfperfection(d) d=[84,-42,42,-34,49,42,44,-5,42,-42,42,34;-42,84,-42,-8,-44,-42,-47,-20,-22,0,-17,8;42,-42,84,-34,49,42,47,-22,22,-42,22,20;-34,-8,-34,84,3,-34,-31,0,8,34,-5,-42;49,-44,49,3,98,49,49,-27,49,-27,49,-8;42,-42,42,-34,49,84,42,-8,22,-20,24,-8;44,-47,47,-31,49,42,94,20,2,-22,2,25;-5,-20,-22,0,-27,-8,20,84,-42,42,-5,-8;42,-22,22,8,49,22,2,-42,84,-42,42,9;-42,0,-42,34,-27,-20,-22,42,-42,84,-5,-28;42,-17,22,-5,49,24,2,-5,42,-5,84,1;34,8,20,-42,-8,-8,25,-8,9,-28,1,84]; qfperfection(d) pari-2.7.5/src/test/in/elliptic0000644000175000017500000000233612456454707015034 0ustar billbillHEAP=[77, if(precision(1.)==38,5279,5458)]; default(realprecision,154); Pi; default(realprecision,38); \e ellinit([-1,0]) ellinit([-17,0],1) ellsub(%,[-1,4],[-4,2]) ellj(I) \\ acurve=ellinit([0,0,1,-1,0]) apoint=[2,2] 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)) ellan(acurve,100)==deu ellisoncurve(acurve,apoint) acurve=ellchangecurve(acurve,[-1,1,2,3]) 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,%) ellmul(acurve,apoint,10) ellwp(acurve, x+O(x^33)) q*Ser(ellan(acurve,100),q) \\ bcurve=ellinit([-3,0]) elllocalred(bcurve,2) elltaniyama(bcurve) \\ ccurve=ellinit([0,0,-1,-1,0]) l=elllseries(ccurve,2) abs(elllseries(ccurve,2,1.2)-l) < 1.4e-38 \\ tcurve=ellinit([1,0,1,-19,26]); ellorder(tcurve,[1,2]) elltors(tcurve) \\ mcurve=ellinit([-17,0]) mpoints=[[-1,4],[-4,2]]~ mhbi=ellbil(mcurve,mpoints,[9,24]) ma=ellheightmatrix(mcurve,mpoints) matsolve(ma,mhbi) \\ cmcurve=ellinit([0,-3/4,0,-2,-1]) ellmul(cmcurve,[x,y],quadgen(-7)) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/qfb0000644000175000017500000000063312366172547013774 0ustar billbillvec(x) = [component(x,1), component(x,2), component(x,3)]; vec( qfbred(Qfb(6,6,-1),1) ) default(realprecision,38) q=Qfb(7, 30, -14)^2; qfbpowraw(q,-1) q*q^2 q^0 q^1 q^-1 q^-(2^64+1) q=Qfb(2, 1, 3); q2=q*q; q3=qfbcompraw(q,q2) qfbpowraw(q,3) qfbred(q3,1) q=Qfb(1009, 60, 99108027750247771) qfbnupow(q, 8839368315) qfbred(Qfb(22000957029, 25035917443, 7122385192)) p=2^64+13; qfbprimeform(-4,p) qfbprimeform(5,p) pari-2.7.5/src/test/in/rnfkummer0000644000175000017500000000265312405547147015232 0ustar billbilldefault(realprecision,38); allocatemem(20*10^6) count = 0; do(nf,f, H = 0, flag = 0)= setrand(1); print(count++); lift(rnfkummer(bnrinit(bnfinit(nf,1),f,1), H, flag)); 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) 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)) do(quadpoly(5288,y), 9, [1,0;0,3]) do(quadpoly(5288,y), 9, [1,0;0,3], 3) do(y^4+y^3-9*y^2-9*y+11, 10, Mat(5)) do(y^4-y^3-159*y^2-441*y+1701, 10, Mat(5)) do(quadpoly(344,y),11,matdiagonal([5,1])) /* \\ used to be very slow (>20h). Now ~ 7mn do(quadpoly(17,y),311,Mat(13)) do(nf=nfinit(y^4-y^3+2*y+1), idealprimedec(nf,463)[2]); do(y^2+5393946914743),1,,3); */ /* 0 eq. OK at \p200 */ do(y^6-19*y^5-11*y^4-6*y^3-15*y^2-11*y+15, 4, [2,1,1; 0,1,0;0,0,1]) /* more than 1 eq. OK at \p200 */ do(y^6+8*y^5-7*y^4+y^3+4*y^2-9*y+10, 8, [2,1,1,1,1;0,1,0,0,0;0,0,1,0,0;0,0,0,1,0;0,0,0,0,1]) /* 1 eq. Wrong result at \p28. OK at \p200 */ do(y^6-9*y^5-20*y^4-4*y^2-y-17, 17, [2,0,1;0,1,0;0,0,1]) setrand(1); for(i=1,10,rnfkummer(bnrinit(bnfinit(quadpoly(2540,y)),9,1),[3,1;0,1])) do(quadpoly(689,y), 2, Mat(2)) do(y^8-76*y^6+1425*y^4-5776*y^2+5776, 5, matdiagonal([2,1])) do(y^4 - 34*y^2 + 1189, 5, matdiagonal([3,1,1])) do(y, [36,[1]], matdiagonal([3,1]), 3) pari-2.7.5/src/test/in/quadclassunit0000644000175000017500000000116512526651220016071 0ustar billbilldefault(realprecision,38); default(echo,1); test(D) = { for (d = D, D+10^3, if (!isfundamental(d),next); print(d, " ", quadclassunit(d).cyc) ); } setrand(1); test(10^15); test(-10^15) \\ #1195 setrand(11);quadclassunit(-8419588).cyc setrand(2);quadclassunit(-1459008).cyc setrand(7);quadclassunit(-3799812).cyc setrand(1); quadclassunit(-13163208).cyc \\ #1195 with non-fundamental discriminants [oo loop] setrand(38);quadclassunit(-29920).cyc quadclassunit(-13163208,,[0.1]).cyc setrand(1); quadclassunit((2^70+25)).cyc setrand(1); quadclassunit(8*3*5*7).cyc \\ #1700 setrand(1);quadclassunit(-612556842419).cyc pari-2.7.5/src/test/in/polmod0000644000175000017500000000116312366172547014515 0ustar billbilltest() = { print(a*b); print(a/b); print(sqr(a)); print(a^-1); print(a^3); print(a^0); } T=2*x^2 + x + 1; a = Mod(x+1/2, T); b = Mod(x/3+1, T); test(); T=2*x^3 + x + 1; a = Mod(x^2+x+1/2, T); b = Mod(x^2+x/3+1, T); test(); modp(p) = { t = T*Mod(1,p); a = Mod((x^2+x+3) * Mod(1,p), t); b = Mod((3*x^2+2*x+5) * Mod(1,p), t); } modp(17); test(); modp(18446744073709551629); test(); (Mod(1/2, 't)*'x + Mod(1, 't)) ^ 2 Mod(Mod(x,x^2+1),x) Mod(y,x) Mod(1/y,x) Mod(O(y),x) Mod(x,y) Mod(1/x,y) Mod(1+O(y),y) Mod(1+O(y),y+1) modreverse(Mod(0,Pol(1))) modreverse(Mod(1,x+1)) norm(Mod(2^65,3*x+1)) norm(Mod('a,3*x+1)) pari-2.7.5/src/test/in/nf0000644000175000017500000000507212610176414013616 0ustar billbill\p38 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 nfinit(factor(polzagier(9,5))[2,1],2).disc nfinit(Pol([1,0,42,112,728,3248,14224,3392,289478,-804944,2966908,-11015200,17342836,-108601584,381107816,-1679988352,6252186465,-14812800240,28868620970,-27997506768,-33428758132,98285772160,-51592356424,-39975211584,55983352320,-24670808064,5337884160,-733917184,87744512])).disc setrand(3);bnfinit(x^2-(1130481^2+4)).clgp setrand(2);bnfinit(x^4 - x^3 + 63*x^2 - 22*x + 1004).clgp setrand(1);bnfinit(x^8 - 8*x^6 + 38*x^4 - 143*x^2 + 121).clgp bnfcertify(bnfinit(x^2-40!)); bnfcertify(bnfinit(x^8-2)); zetakinit(2*x-1); \\#1736 setrand(1);bnfinit(x^3-87156*x^2-6728799*x-456533).cyc nf=nfinit(y^5-4*y^3+2*y+11); v = [4/3, -1, y^2+y+1, Mod(y,nf.pol),Mod(1/2,nf.pol),[1,2,3,4,5]~]; for (i=1, #v, print( nfelttrace(nf,v[i]) )) for (i=1, #v, print( nfeltnorm(nf,v[i]) )) nfeltnorm(nf,[3,3;y,2]) for (i=1, #v, print( nfbasistoalg(nf,v[i]) )) for (i=1, #v, print( nfalgtobasis(nf,v[i]) )) funs = [nfeltadd, nfeltdiv, nfeltdiveuc, nfeltdivrem, nfeltmod, nfeltmul]; 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))) \\#1253 k=bnfinit(z^2+19*z+6,1); bnfisunit(k,k.fu[1]^2) \\#1158 nf=nfinit(x^2+x+1); nfinit(nf) \\#1180 setrand(1);quadclassunit(572).no bnf=bnfinit(x^3-2); S=bnfsunit(bnf,idealfactor(bnf,2*3*5*7)[,1]); bnfissunit(bnf,S,x) bnfissunit(bnf,S,x+2) bnfissunit(bnf,S,x+100) bnfisunit(bnf, x+100) \\#1247 setrand(1);bnfinit(x^2+1635847).no \\#1381 K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[1][2]; bnfdecodemodule(K, s[1][1]) default(realprecision,19); K=bnfinit(x^5-x^4+x^3+100*x+20,1); A=idealpow(K,idealprimedec(K,5)[2],150); bnfisprincipal(K,A); default(realprecision,173); K=nfnewprec(K); bnfisprincipal(K,A) l=ideallist(K,4,0);ideallistarch(K,l,[1]) l=ideallist(K,4,3);L=ideallistarch(K,l,[1]) bnrdisclist(K,l) bnrdisclist(K,L) bnrdisclist(K,4,[1]) nfinit([y^3+2,[1,x]]) nfinit([y^3+2,[1,x,x^2]]) nfinit([y^3+2,[1,y^5,y]]) K=nfinit([x^5-x^4+x^3+100*x+20,[1,x,x^2-x,1/2*x^4-1/2*x^3+1/2*x^2+40,x^3-x^2+x]]); K.index K=nfinit([x^5+9*x^4+851*x^3+18890*x^2+252376*x+529348, 39820]); nfcertify(K) nfnewprec(x) nfnewprec(quadgen(5)) nfnewprec(vector(5)) 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) pari-2.7.5/src/test/in/factormod0000644000175000017500000000134412366172547015202 0ustar billbillprint(lift(factorcantor(x^1024+1,12289))) setrand(4); lift(factormod(y^3-3*y-1,2238004061)) \\#1451 lift(factormod(x^31+x^30+x^29+x^28+x^26+x^24+x^23+x^21+x^16+x^15+x^14+x^11+x^10+x^9+x^8+x^7+x^3+x^2+x,2)) polrootsmod(x^16-1,41,1) polrootsmod(x^5+x^2-4*x+2,5,1) polrootsmod(Pol(0),2) polrootsmod(Pol(1),2) factorcantor(x^3+x,2) factormod(Pol(0),2) factormod(Pol(1),2) factormod((x^2+x+1)*(x^3+x),2, 1) polrootsmod(x^5+4*x^4+2*x^3+x^2+4*x+2,7) p=2^64+13; polrootsmod(Pol(0),p) polrootsmod(Pol(1),p) polrootsmod(x,p) polrootsmod(2*x+1,p) factormod(x^2+1,p) factormod(x^2+1,p,1) factormod(x^2+3,p,1) factorcantor(x^2+1,p) factorcantor(Pol(0),p) factorcantor(Pol(1),p) polisirreducible((x^2+x+1)*Mod(1,2)) polisirreducible((x^2+1)*Mod(1,p)) pari-2.7.5/src/test/in/subcyclo0000644000175000017500000000004511636712103015027 0ustar billbillpolsubcyclo(8,1) polsubcyclo(1048,2) pari-2.7.5/src/test/in/agm0000644000175000017500000000056012453017374013760 0ustar billbilldefault(realprecision,38); gagm(a,b)= { my(prec=10^(1-precision(a*1.))); while(norm(a-b)>prec^2, aa = (a+b)/2; bb = sqrt(a*b); if (norm(aa-bb)>norm(aa+bb), bb=-bb); a=aa;b=bb); a; } testagm(x)= { my(e = norm(agm(x,1)-gagm(x,1))); if(e > 1.E-75, printf("error %s: %s\n",x,e)); } for(i=-6,6,for(j=-6,6,testagm(1/6+i/3+j*I/3))); agm(1,2+O(5)) pari-2.7.5/src/test/in/lex0000644000175000017500000000062212314242551013774 0ustar billbillv = [0, 2, [1,2], [1,2;3,4], [1,0;1,2], [1,2,3]~, [1,2,3;4,5,6]]; isvec(x) = type(x) == "t_VEC" || type(x) == "t_COL"; { for (i = 1, #v, for (j = i, #v, s = lex(v[i],v[j]); print([i,j,s]); if (s != -lex(v[j], v[i]), error(2)); if (isvec(v[i]) && lex(Vecsmall(v[i]), v[j]) != s, error(3)); if (isvec(v[j]) && lex(v[i], Vecsmall(v[j])) != s, error(4)); ) ); } pari-2.7.5/src/test/in/combinat0000644000175000017500000000037212314242551015002 0ustar billbillvector(10, k, stirling(11,k)) vector(11, k, stirling(12,k)) vector(10, k, stirling(11,k, 2)) vector(11, k, stirling(12,k, 2)) v = vector(5!,i,numtoperm(5, i-1)) if(vecsort(v,lex)!=v,error("numtoperm")); vector(#v, i, permtonum(v[i])) stirling(100,0) pari-2.7.5/src/test/in/digits0000644000175000017500000000055412405547147014505 0ustar billbillbinary(0) digits(0) digits(5^100) check(a,b)=my(v=digits(a,b));if(subst(Pol(v),'x,b)!=a || vecmax(v)>=b,error([a,b])); check(5^100,2) check(5^100,3) check(3^100,2^64-1) check(3^100,2^128+1) sumdigits(0) sumdigits(129) sumdigits(123456789123456789123456789) sumdigits(100000!) default(realprecision,38); binary(0.) binary(0.005) binary(1.1) binary([0,1]) binary(I) pari-2.7.5/src/test/in/primes0000644000175000017500000000033112502252164014500 0ustar billbillprimes(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)]); pari-2.7.5/src/test/in/size0000644000175000017500000000027412366172547014177 0ustar billbilldefault(realprecision,38) #1 #1. == if (#(2^32)==1, 2, 4) length([x]) length(List()) length(List([1,2,3])) length("abc") matsize([1,2,3]) matsize([1,2,3]~) matsize(matrix(2,3)) matsize(1) pari-2.7.5/src/test/in/modpr0000644000175000017500000000210412366172547014340 0ustar billbillnfeltmulmodpr(nfinit(x),x,x,1); v=[0,1/3,y,z,[1,1/3]~, [1,1,1/3]~]; test(P) = { my(f); print(K.pol, ": ", P); f=[nfeltdivmodpr,nfeltmulmodpr]; for (i=1,#v, for (j=i,#v, print("*",[i,j],":"); for (k=1, #f, print(iferr(f[k](K,v[i],v[j],P),E,E)) ) ) ); f=[(K,x,P)->nfeltpowmodpr(K,x,-3,P),nfeltreducemodpr]; for(i=1,#v, print("*",i,":"); for(k=1, #f, print(iferr(f[k](K,v[i],P),E,E))) ) } K=nfinit(y^2+1); P = nfmodprinit(K,idealprimedec(K,2)[1]); test(P); P = nfmodprinit(K,idealprimedec(K,3)[1]); test(P); K=nfinit(y^3-9); P = nfmodprinit(K,idealprimedec(K,3)[1]); test(P); P = nfmodprinit(K,idealprimedec(K,2)[2]); test(P); K=nfinit(y^2-1105); P = nfmodprinit(K,idealprimedec(K,2)[1]); nfeltreducemodpr(K,(-y+1)/2,P) nffactormod(K, x^3+y*x^2+y*x+1, P) m=[1,y;[1/2,1/2]~,1]; v = [1,y]~ nfkermodpr(K, m, P) nfsolvemodpr(K, m, v, P) m=[y,y^2;y^2,y^3] nfkermodpr(K, m, P) nfsolvemodpr(K, m, v, P) nfsolvemodpr(K, m, m, P) K=nfinit(charpoly(Mod(2*x+1,polcyclo(51)))); P=idealprimedec(K,2)[1]; nfeltreducemodpr(K,P.gen[2],nfmodprinit(K,P)) pari-2.7.5/src/test/in/mat0000644000175000017500000000364512456464050014004 0ustar billbilliferr(Mat([1]) + matrix(0,1),E,E) iferr(1/matrix(2,2,i,j,Mod(0, 2)),E,E) test(n)= { until(matrank(M)==n,M=matrix(n,n,i,j,random(Mod(1,2)))); if(M^-1*M!=matid(n),error("F2m")); } test(200) test(2) matsize(matrix(0, 0) * matrix(0, 2)) 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()) Mat(List([1])) Mat([[1,2,3],[2,3,4]]~) Mat(Qfb(1,2,5)) matdiagonal(matid(2)) iferr(matdiagonal([1,2;3,4]),E,E) matpascal(4,1/2) A=[1,2,3;4,5,6];B=[4,6;10,12] matinverseimage(A,B) matinverseimage(A*Mod(1,2),B) matinverseimage(A*Mod(1,7),B) matinverseimage(A*Mod(1,2^64+13),B) matinverseimage(A*Mod(1,3037000507),B) B=[4,10]~; matinverseimage(A*Mod(1,2),B) matinverseimage(A*Mod(1,7),B) matinverseimage(A*Mod(1,2^64+13),B) matinverseimage(A*Mod(1,3037000507),B) test(f)= { print(f,":"); print(f(A*Mod(1,2))); print(f(A*Mod(1,7))); print(f(A*Mod(1,3037000507))); print(f(A*Mod(1,2^64+13))); print(f(A*(1+O(101^3)))); } testall()= { test(matdet); test(matrank); test(matadjoint); test(matimage); test(matimagecompl); test(matindexrank); test(matker); test(lindep); test(x->matsolve(x,vectorv(#x,i,i))); test(x->matsolve(x,matrix(#x,#x,i,j,i+j))); test(x->x^(-1)); test(x->x^2); test(x->A*x); } A = [1,2,4;2,12,7;2,9,11]; testall(); A = [;] testall(); A=[0,1,0;1,0,1;2,0,3]; matdet(A*Mod(1,3037000507)) matdet(A*Mod(1,2^64+13)) matsolve(A*Mod(1,2^64+13),[1,2,3]~) matker([1.,I;I,-1.]) trace(matid(3)) trace([;]) iferr(trace(Mat([1,2])),E,E) matrixqz([1/3,1/4;1/2,1/3]) matrixqz(matrix(2,2),-1) A=[1,2,3;4,5,6;7,8,9]; test(lindep) test(matsupplement) default(parisize,10^6); \\ need to exercise gerepile in matker+matimage p=2^64+13; A=matrix(70,70,i,j, i+j); Ap=Mod(A,p); #matker(Ap) #matimage(Ap) #matker(A) vecsum([]) vecsum([2]) vecsum(primes(4)) pari-2.7.5/src/test/in/print0000644000175000017500000000026712531356742014356 0ustar billbillprintsep(":", 1,2,3,4);print(0); printsep(":");print(0); printsep1(":", 1,2,3,4);print(0); printsep1(":");print(0); printsep(":",matid(2));print(0); printsep1(":",matid(2));print(0); pari-2.7.5/src/test/in/lll0000644000175000017500000000131012366172547014000 0ustar billbillqflllgram(matid(2)*1.) m=[219902325555200,60779507942430,113687426768697,93478400051083;219902325555200 ,60779507942430,61044718855924,60943417301157;214748364800,155393376570,17984250 9148,115833849065;214748364800,155393376570,134851934330,188630128295]; qflll(m, 1) M=[x, x^3 - 852*x^2 - 833561*x; x^3 + 1053355*x^2, x^5 + 1052503*x^4 - 898292021*x^3 - 878035647155*x^2 + 1]; test()= { for(i=1,#v, for (j=1,#f, print(iferr(f[j](v[i]),E,E)); ) ); } v=[[;],Mat(1),Mat(0),Mat([1,2]), [x, x+1; x^2, x^2+x], M]; f=[qflll,x->qflll(x,1),x->qflll(x,2),x->qflll(x,4),x->qflll(x,5),x->qflll(x,8)]; test(); v=vector(#v,i,v[i]~*v[i]); f=[qflllgram,x->qflllgram(x,1),x->qflllgram(x,4),x->qflllgram(x,5)]; test(); pari-2.7.5/src/test/in/norm0000644000175000017500000000066512366172547014204 0ustar billbillnorml2(-1/2) norml2(quadgen(5)) norml2(quadgen(-3)) normlp(-1, 1) normlp(-1/2, 1) normlp(I, 1) default(realprecision,38); F = [x->normlp(x,1), x->normlp(x,2), x->normlp(x,2.5), normlp]; { for(i=1, #F, my(f = F[i]); print(f); print(f([1,-2,3])); print(f([1,-2;-3,4])); print(f([[1,2],[3,4],5,6])); print(f((1+I) + I*x^2)); print(f(-quadgen(5))); print(f(3+4*I)); ) } normlp([95800,217519,414560], 4) pari-2.7.5/src/test/in/arith0000644000175000017500000000006112314242551014310 0ustar billbill\\#1304 issquarefree(0) \\#1412 core(4*10^15+27) pari-2.7.5/src/test/in/galoisinit0000644000175000017500000000732512366172547015373 0ustar billbilldo(p)=galoisidentify(galoisinit(p)); do(algdep(I,3)) do(galoissubcyclo(bnrinit(bnfinit(y),[1232,[1]],1),[4,0,0,0;0,2,0,1;0,0,2,1;0,0,0,1])) do(x^20-40*x^18+605*x^16-4600*x^14+19500*x^12-48250*x^10+70425*x^8-59500*x^6+27625*x^4-6250*x^2+500) do(x^24-12*x^23+6*x^22+440*x^21-1659*x^20-2352*x^19+24274*x^18-34812*x^17-66078*x^16+249212*x^15-192066*x^14-234528*x^13+515149*x^12-234528*x^11-192066*x^10+249212*x^9-66078*x^8-34812*x^7+24274*x^6-2352*x^5-1659*x^4+440*x^3+6*x^2-12*x+1) do(x^4+272*x^3+40256*x^2+1740800*x+25397248) do(x^4+5264*x^3+8034856*x^2+4205424384*x+504485485632) do(x^4+884*x^3-1972*x^2-884*x+1) do(x^4-42*x^2+144) do(x^12-30*x^8-370*x^6+1665*x^4+23166*x^2+81) do(x^24+3*x^22+22*x^20+31*x^18+138*x^16+85*x^14+297*x^12+149*x^10+249*x^8+238*x^6+98*x^4+16*x^2+1) do(x^54+4288*x^45+4739337*x^36+88723254*x^27+799530047*x^18-256778413*x^9+40353607) do(x^54-3762*x^52+6515505*x^50-6911246832*x^48+5039176931676*x^46-2686817670557400*x^44+1087963170065343636*x^42-342933852097598081616*x^40+85549691240003522127726*x^38-17077123231759966515087980*x^36+2746482620444718167893994910*x^34-357137314570021313085512898384*x^32+37572202145621696209178550611604*x^30-3191423993701636005506286262264824*x^28+217847326568033953619436917061987732*x^26-11861321463900503282422713802261870896*x^24+509777643921195165950639871535287639897*x^22-17055767879920589218196924743211626177266*x^20+436388466866294213576027352329957260889977*x^18-8349444825290714596926947944336750514846016*x^16+116184424651196907257566920202449108391711560*x^14-1136293058944245287715303626629567362322332192*x^12+7487695030927212135931358829137467901174408592*x^10-31501276144455609227993784616018089442301260032*x^8+78778033600362485611603755865500353002845187584*x^6-106406869975806738331854667483688298979911757824*x^4+68731119007852853614250618123508690506961555456*x^2-15696850241826982459503429282145309404169764864) do(x^64-3645070*x^56+3769245010705*x^48+120173739648338450*x^40+2124098086173949323364*x^32+16674620185061962554229010*x^24+87774696936415565369888312017*x^16+56323712629998864272734706*x^8+78032457926322172553281) do(x^8-4*x^7-126*x^6+392*x^5+4853*x^4-10364*x^3-58244*x^2+63492*x+197761) do(y^4+1) p=x^14-271*x^13+14191*x^12-320438*x^11+3790080*x^10-25112800*x^9+92495160*x^8-167147800*x^7+50530009*x^6+301971239*x^5-450938136*x^4+211398894*x^3-16216756*x^2-8116135*x+1041461; do(p) do(x^48+688253440*x^36+64889579202*x^24+688253440*x^12+1); \\\\\\\\\\\ nfgaloisconj(x^3-x-1) nfgaloisconj(x^24+2814) nfgaloisconj(x^4+1) nf=nfinit(polcyclo(7)); s = nfgaloisconj(nf)[2]; pr = idealprimedec(nf,11)[1]; nfgaloisapply(nf,s,idealhnf(nf,pr)) nfgaloisapply(nf,s,pr) nfgaloisapply(nf,s,x^2+x) nfgaloisapply(nf,s,1/2) v=[1,1/2,Mod(x,nf.pol),x,vectorv(6),[;],[1,2;x,3]]; for (i=1,#v, print(nfgaloisapply(nf,s,[1,v[i]]))) galoistest(P)= { my(G,F,L); G=galoisinit(P); F=galoissubfields(G,2); for (i=1,#F, my(L=F[i]); if (subst(L[1],x,L[2])!=0, error("galoissubfields1")); if (factorback(L[3]*Mod(1,subst(L[1],x,y)))!=P, error("galoissubfields2"))); } galoistest(x^4 + 431452248691495692750746750*x^3+447244936830156353775324765*x^2+5580140636706480467906000*x - 238676773812533681600); G=galoisinit(x); galoisexport(G); galoisexport(G,1); G=galoisinit(x^12-30*x^8-370*x^6+1665*x^4+23166*x^2+81); galoisexport(G) galoisexport(G, 1) G=galoisinit(x^12-24*x^10-10*x^9+216*x^8+180*x^7-844*x^6-1080*x^5+1056*x^4+2200*x^3+720*x^2-240*x-80); L=galoissubgroups(G) apply(H->galoisisnormal(G,H),L) apply(H->galoisisabelian(H),L) apply(H->galoisisabelian(H,1),L) apply(H->galoisisabelian(H,2),L) vector(#G.group, i, galoisfixedfield(G,G.group[i],1)) galoisfixedfield(G,G.group[2]) galoisfixedfield(G,G.group[2],2,y) galoissubcyclo(17,2) G=galoisinit(polcyclo(20)) galoissubfields(G) pari-2.7.5/src/test/in/apply0000644000175000017500000000051612366172547014351 0ustar billbillapply(x->x^2, [1,2,3,4]) apply(x->x^2, [1,2;3,4]) apply(x->x^2, 4*x^2 + 3*x+ 2) apply(x->x^2, 4*x^2 + 3*x+ 2 + O(x^3)) apply(x->x^2, List([1,2,3,4])) L = List([Mod(1,3), Mod(2,4)]); apply(lift, L) f(x)=L=0;x-1; L=List(); apply(f, L); 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) pari-2.7.5/src/test/in/polyser0000644000175000017500000000245012405547147014714 0ustar billbillHEAP=[62, if(precision(1.)==38,7190,7252)]; default(realprecision,154); Pi; default(realprecision,38); \e apol=y^3+5*y+1 deriv((x+y)^5,y) ((x+y)^5)' dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz) 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) padicappr(apol,1+O(7^8)) padicappr(x^3+5*x+1,Mod(x*(1+O(7^8)),x^2+x-1)) Pol(sin(x)) Pol([1,2,3,4,5]) Polrev([1,2,3,4,5]) polcoeff(sin(x),7) polcyclo(105) pcy=polcyclo(405) pcy * pcy poldegree(x^3/(x-1)) poldisc(x^3+4*x+12) poldiscreduced(x^3+4*x+12) polinterpolate([0,2,3],[0,4,9],5) polisirreducible(x^5+3*x^3+5*x^2+15) pollegendre(10) zpol=0.3+pollegendre(10) polrecip(3*x^7-5*x^3+6*x-9) polresultant(x^3-1,x^3+1) polresultant(x^3-1.,x^3+1.,,1) polroots(x^5-5*x^2-5*x-5) polroots(x^4-1000000000000000000000) polrootsmod(x^16-1,41) polrootspadic(x^4+1,41,6) polsturm(zpol) polsturm(zpol,0.91,1) polsylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0) polsym(x^17-1,17) poltchebi(10) polzagier(6,3) serconvol(sin(x),x*cos(x)) serlaplace(x*exp(x*y)/(exp(x)-1)) serreverse(tan(x)) subst(sin(x),x,y) subst(sin(x),x,x+x^2) taylor(y/(x-y),y) variable(name^4-other) if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/incgam0000644000175000017500000000221712413013143014435 0ustar billbillVs=[0,1/2,10-I,1+128*I]; Vx=[19+236*I,1/10,-1/10,I/10,-I/10,1/10-I/10,100,-100,100+1001*I]; test(fun, p) = { my (P = 1/10.^(p-1)); for (i=1,#Vs, for (j=1,#Vx, my (v,w, s = Vs[i], x = Vx[j]); default(realprecision, p); v = fun(s, x); default(realprecision, p + 38); w = fun(s, x); \\ e = abs((v-w)/w); e = if (abs(w) < 1, abs(v-w), abs((v-w)/w)); if (e > P, printf("%9s, %13s: %.1e\n", s,x,e)); ) ); } test(incgam, 19) test(incgam, 38) test(incgam, 100) mylog(x)=if(x==0, "oo", round(log(abs(x))/log(10))); Vs=[1/10+1/5*I,-1/10,-1/10,-1/10+2/5*I,-1/10+2/5*I,2/5*I,2/5*I,-2/5*I,-2/5*I,-1,-1,-20,-200001/10000]; Vx=[13/10,1/10000,13/10,13/10,1/10000,11/10,1/10000,11/10,1/10000,1/10000,11/10,11/10,11/10]; default(realprecision, 100); VR = vector(#Vs,j,incgam(Vs[j]*1.,Vx[j]*1.)); test(fun, prec)= { default(realprecision,prec); for(j=1,#Vs, res = fun(Vs[j]*1.,Vx[j]*1.) - VR[j]; print(j, ": ", mylog(res)) ); } test(incgam, 38) test(incgam, 76) default(realprecision, 38); incgam(1/2,10^8) eint1(-0.3-95*I) eint1(100) incgam(-10+1e-100,1) eint1(2,5) \p1000 eint1(100) \p481 eint1(150) eint1(0) pari-2.7.5/src/test/in/ispower0000644000175000017500000000466412526672040014713 0ustar billbilldo(n)= my(k,z); if (k=ispower(n,,&z), print([k,z])); {v = [ 3^101*2^20, 3^101*2^101, 3^101*2^101*5, 2^20*3^15*5^5, 2^3*103^6, 2^5*103^10, 2^7*103^10, 2^15*103^10, 2^21*103^42, 2^35*103^70, 2^105*103^210, 103^100003, 541^121 ]; } for (i=1, #v, do(v[i])) for (i=1, 10^6, do(i)) \\#1259 do(-16) do(-64) do(-8) do(-8 * 103^6) do(-1/64) for (i=1, #v, if (!ispowerful(v[i]), print(i))) ispowerful(5^3*(10^1000+1)^2) v = [1, 2^10, 2^15, 2^32, 2^64, 2^128]; /* correct = vector(#v); { for (k = 1, #v, my(u = v[k], s,t); for(i=u, u+10^4, if ((a = ispower(i,,&p)) && isprime(p), s += a; t += p); if (isprime(i), s ++; t += i); ); correct[k] = [s,t]; ) } */ { for (k = 1, #v, my(u = v[k], s,t); s = sum(i=u, u+10^4, isprimepower(i)); t = 0;for (i = u, u+10^4, if (isprimepower(i,&p), t += p)); print([s,t]); \\ if ([s,t] != correct[k], error(k)) ) } isprimepower(541^121) ispowerful(4) p = 10^6+3; q = 10^6+33; r = 10^6+37; v = [Mod(p, p^2*q), Mod(6*p, q*(p*r)^2), Mod(6, p^2*q), Mod(4*p, 8*p^2*q)]; [ispower(a,2) | a<-v] [ispower(a,3) | a<-v] [if(ispower(a,2,&b), b) | a<-v] [if(ispower(a,3,&b), b) | a<-v] [if(issquare(a^2,&b), b) | a<-v] [if(ispower(a^3,3,&b), b) | a<-v] ispower(Mod(2, 7*5^3), 7, &z); z issquare(Mod(1,2)) issquare(Mod(0,2),&s);s issquare(Mod(2,3)) issquare(Mod(13,121)) default(realprecision,38); if(issquare(Pol(0),&z),z) issquare(Pol(4)) issquare(x^2+x) issquare(y^2*x^0) issquare(x^0/4) if(issquare(y^2*x^0,&z),z) issquare(2*x^4+x^3+Mod(1,2)) issquare(x^2+Mod(1,2)) if(issquare(x^2+Mod(1,2),&z),z) t=ffgen(2^3,'t); if(issquare((t*x^2+(1+t)*x+1)^2,&z),z) if(issquare((x^4+x^3+3*x^2+2*x+4)*Mod(1,5),&z),z) if(issquare(4/x^2,&z),z) issquare(1.5) if(issquare(1.5,&z),z) issquare(4/9) issquare(4/3) issquare(I) issquare(ffgen(2^3,'t)) if(issquare(ffgen(2^3,'t),&z),z) 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) if(ispower(-8/27,3,&z),z) ispower(Pol(0),3) ispower(x^2,3) ispower(x^3+x,3) ispower(x^3+4,3) if(ispower(Pol(8),3,&z),z) if(ispower((2+x)^3,3,&z),z) ispower((2+x)^3-1,3) ispower(1009^11) ispower(-1.,3) ispower(I,3) if(ispower(1/(2*x)^3,3,&z), z) if(ispower(1+x+O(x^2),3,&z), z) if(ispower((-2/3)^5,5,&z),z) ispower(3^(11^2)) ispower((2/3)^(11^2)) ispower(30011^(17*11)) issquare(Mod(3,22)) \\#1703 ispower(-167^10) pari-2.7.5/src/test/in/time0000644000175000017500000000024512366172547014161 0ustar billbillgettime(); T=getabstime(); for(i=1,2*10^6,) T2=getabstime(); t2=gettime(); abs(t2 - (T2 - T)) < 5 for(i=1,2*10^6,) t3=gettime(); abs(t2+t3 - (getabstime() - T)) < 5 pari-2.7.5/src/test/in/polylog0000644000175000017500000000031312366172547014704 0ustar billbilldefault(realprecision,38); polylog(3,0.9) polylog(2,3.9) polylog(3,3.9) polylog(2,Mod(x,x^2+1)) polylog(2,[0.5,0.6]) polylog(2,x+O(x^5)) polylog(2,1/2+x+O(x^5)) dilog(-4) polylog(2,1+I,1) polylog(1,2,3) pari-2.7.5/src/test/in/modular0000644000175000017500000000117512462723243014661 0ustar billbillv = [2,3,2^32-1,2^64-1,10^20]; f(a,b,p)=(a*Mod(1,p)) * (b*Mod(1,p)); g(a,p)=sqr(a*Mod(1,p)); test(a,b)= { for (i=1,#v,print(i, ": ", f(a,b,v[i]))); for (i=1,#v,print(i, ": ", g(a,v[i]))); } test(polcyclo(10),polcyclo(5)); test([1,2;3,4], [-1,2;-4,2]); Mod(Mod(1,y),x) Mod(Mod(1,x),y) iferr(Mod(1,"a"),E,E) iferr(Mod(0,0),E,E) iferr(Mod(0,Pol(0)),E,E) iferr(Mod(x+O(x^2), x^3), E,E) Mod(x+O(x^2), x^2) Mod(x+O(x^3), x^2) Mod(Mod(x,x^3), x^2) Mod(Mod(1,12), 9) Mod(1/x,x^2+1) Mod([5,6],2) Mod(3*x,2) Mod(x,y) Mod(Pol(0),2) Pol(0)*Mod(1,2) k=100000000000000000000; Mod(3,7)^-k Mod(3,7)^k \\#1652 p=436^56-35;lift(Mod(271,p)^((p-1)/2)) pari-2.7.5/src/test/in/objets0000644000175000017500000000165512415477723014516 0ustar billbillHEAP=[63, if(precision(1.)==38,822,846)]; default(realprecision,38); \e +3 -5 5+3 5-3 5/3 5\3 5\/3 5%3 5^3 binary(65537) bittest(10^100,100) ceil(-2.5) centerlift(Mod(456,555)) component(1+O(7^4),3) conj(1+I) conjvec(Mod(x^2+x+1,x^3-x-1)) truncate(1.7,&e) e denominator(12345/54321) divrem(345,123) divrem(x^7-1,x^5+1) floor(-1/2) floor(-2.5) frac(-2.7) I^2 imag(2+3*I) lex([1,3],[1,3,5]) max(2,3) min(2,3) Mod(-12,7) norm(1+I) norm(Mod(x+5,x^3+x+1)) numerator((x+1)/(x-1)) 1/(1+x)+O(x^20) numtoperm(7,1035) permtonum([4,7,1,6,3,5,2]) 37. real(5-7*I) shift(1,50) shift([3,4,-11,-12],-2) shiftmul([3,4,-11,-12],-2) sign(-1) sign(0) sign(0.) simplify(((x+I+1)^2-x^2-2*x*(I+1))^2) sizedigit([1.3*10^5,2*I*Pi*exp(4*Pi)]) truncate(-2.7) truncate(sin(x^2)) type(Mod(x,x^2+1)) valuation(6^10000-1,5) \p 57 Pi \p 38 O(x^12) padicno=(5/3)*127+O(127^5) padicprec(padicno,127) length(divisors(1000)) Mod(10873,49649)^-1 if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/analyz0000644000175000017500000000032212366172547014515 0ustar billbillHEAP=[9, if(precision(1.)==38,79,87)]; default(realprecision,38); \e sum(x=0,50000,x); sum(x=1,1000,log(x)); sum(x=1,25,sum(y=1,100,x/y),0.0); sum(x=1,100,sum(y=1,100,x/y,0.0)); if (getheap()!=HEAP, getheap()) pari-2.7.5/src/test/in/nfields0000644000175000017500000000717412405547147014653 0ustar billbilldefault(realprecision,154); Pi; default(realprecision,38); dobnf(T,flag=0,tech=[])= setrand(1); my(K = bnfinit(T,flag,tech)); [K.cyc,K.fu]; \e \\ Initialisations diverses 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) nfinit(nfpol,2) nfinit(nfpol,3)[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]) dobnf(x^2-x-100000,1) \p19 setrand(1);sbnf=bnfcompress(bnfinit(x^3-x^2-14*x-1)) bnfinit(sbnf) \p38 bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1); bnr.cyc bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]],1); bnr2.bid rnfinit(nf2,x^5-x-2) \\ bnfcertify(bnf) dobnf(x^4+24*x^2+585*x+1791,,[0.1,0.1]) bnrconductor(bnf,[[25,13;0,1],[1,1]]) bnrconductorofchar(bnr,[2]) bnfisprincipal(bnf,[5,1;0,1],0) bnfisprincipal(bnf,[5,1;0,1]) bnfisunit(bnf,Mod(3405*x-27466,x^2-x-57)) bnfnarrow(bnf) bnfsignunit(bnf) bnrclassno(bnf,[[5,3;0,1],[1,0]]) lu=ideallist(bnf,55,3); bnrclassnolist(bnf,lu) bnrdisc(bnr,Mat(6)) bnrdisc(bnr) bnrdisc(bnr2,,,2) bnrdisc(bnr,Mat(6),,1) bnrdisc(bnr,,,1) bnrdisc(bnr2,,,3) bnrdisclist(bnf,lu) bnrdisclist(bnf,20) bnrisprincipal(bnr,idealprimedec(bnf,7)[1]) dirzetak(nfinit(x^3-10*x+8), 30) factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1) \\ vp=idealprimedec(nf,3)[1] idx=idealhnf(nf,vp) idy=idealred(nf,idx,[1,5,6]) idx2=idealmul(nf,idx,idx) idt=idealmul(nf,idx,idx,1) idz=idealintersect(nf,idx,idy) aid=[idx,idy,idz,1,idx]; idealadd(nf,idx,idy) idealaddtoone(nf,idx,idy) idealaddtoone(nf,[idy,idx]) idealappr(nf,idy) idealappr(nf,idealfactor(nf,idy),1) idealcoprime(nf,idx,idx) idealdiv(nf,idy,idt) idealdiv(nf,idx2,idx,1) idealfactor(nf,idz) idealhnf(nf,vp[2],3) ideallist(bnf,20) bid=idealstar(nf2,54) ideallog(nf2,y,bid) idealmin(nf,idx,[1,2,3]) idealnorm(nf,idt) idp=idealpow(nf,idx,7) idealpow(nf,idx,7,1) idealprimedec(nf,2) idealprimedec(nf,3) idealprimedec(nf,11) idealtwoelt(nf,idy) idealtwoelt(nf,idy,10) idealstar(nf2,54) idealval(nf,idp,vp) \\ ba=nfalgtobasis(nf,x^3+5) 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) nfeltmod(nf,ba,bb) nfeltmul(nf,ba,bb) nfeltpow(nf,bb,5) nfeltreduce(nf,ba,idx) nfeltval(nf,ba,vp) nffactor(nf2,x^3+x) aut=nfgaloisconj(nf3) nfgaloisapply(nf3,aut[5],Mod(x^5,x^6+108)) nfhilbert(nf,3,5) nfhilbert(nf,3,5,vp) nfhnf(nf,[a,aid]) da=nfdetint(nf,[a,aid]) nfhnfmod(nf,[a,aid],da) nfisideal(bnf[7],[5,1;0,1]) nfisincl(x^2+1,x^4+1) nfisincl(x^2+1,nfinit(x^4+1)) nfisisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1) nfisisom(x^3-2,nfinit(x^3-6*x^2-6*x-30)) nfroots(nf2,x+2) nfrootsof1(nf) nfsnf(nf,[a[,1..3], [1,1,1], [idealinv(nf,idx),idealinv(nf,idy),1]]) nfsubfields(nf) polcompositum(x^4-4*x+2,x^3-x-1) polcompositum(x^4-4*x+2,x^3-x-1,1) polgalois(x^6-3*x^2-1) polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568) polred(x^4-28*x^3-458*x^2+9156*x-25321,3) polred(x^4+576,1) polred(x^4+576,3) polred(p2,0,fa) polred(p2,1,fa) polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568) polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568,1) polredord(x^3-12*x+45*x-1) polsubcyclo(31,5) setrand(1);poltschirnhaus(x^5-x-1) \\ p=x^5-5*x+y; aa=rnfpseudobasis(nf2,p) rnfbasis(bnf2,aa) rnfdisc(nf2,p) rnfequation(nf2,p) rnfequation(nf2,p,1) rnfhnfbasis(bnf2,aa) rnfisfree(bnf2,aa) rnfsteinitz(nf2,aa) \\ nfz=zetakinit(x^2-2); zetak(nfz,-3) 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 pari-2.7.5/src/test/dummy.c0000644000175000017500000000073012314242551014152 0ustar billbillvoid nchar2nlong(){} void newblock(){} void remsBIL(){} void bit_accuracy(){} void is_bigint(){} void divsBIL(){} void copy_bin(){} void pari_free(){} void pari_malloc(){} void shiftaddress(){} void shiftaddress_canon(){} void powuu(){} void gerepilemanysp(){} void ceilr(){} void roundr(){} void pari_err(){} void pari_err_BUG(){} void pari_err_INV(){} void pari_err_OVERFLOW(){} void pari_err_PREC(){} void pari_warn(){} void quadratic_prec_mask(){} void prec2nbits(){} pari-2.7.5/src/test/dotest0000755000175000017500000001030412366172547014117 0ustar billbill#!/bin/sh trap exit 2 bitlen=$1; shift testlist=$@ if (tail -n 1 $0 >/dev/null 2>&1); then tail='tail -n' else tail='tail -' fi if (head -n 1 $0 >/dev/null 2>&1); then head='head -n' else head='head -' fi if (printf %-22s foo >/dev/null 2>&1); then printf=OK else printf= fi wrln () { echo "$1"; echo "$1" >&3; } wr () { echo $n "$1$c"; echo $n "$1$c" >&3; } wrtab () { if test -n "$printf"; then printf %$1s "$2" printf %$1s "$2" >&3 else echo $n "$2 $c" echo $n "$2 $c" >&3 fi; } confdir=../config testdir=../src/test execdir=. if test -f /bin/rm ; then RM=/bin/rm; else RM=rm ; fi if sh -c 'test -x /bin/sh' 2>&-; then x=-x; else x=-r; fi (echo "hi there\c" ; echo " ") > echotmp if grep c echotmp >/dev/null 2>&1 ; then n=-n; c=; else n=; c='\c'; fi $RM -f echotmp . $confdir/version exec 3>> Bench-$VersionMajor.$VersionMinor.$patch dotestSUF=${dotestSUF:-"sta dyn"} for arg in $dotestSUF; do if test $x $execdir/gp-$arg; then SUF="$SUF $arg" datadir=`echo 'print(default(datadir))' | $RUNTEST $execdir/gp-$arg -q -f` fi done file_test=gp.out for suf in $SUF; do eval time$suf=0 files$suf=; done for testdata in $testlist; do O=$IFS;IFS=_;set $testdata;IFS=$O;testname=$1;testmul=$2 pkgs=`${head}1 $testdir/in/$testname | grep package: | cut -f2 -d:` skip="" for pkg in $pkgs; do if test ! $x "$datadir/$pkg"; then wrln "! Skipping $testname: optional package $pkg not installed." skip="true"; fi done if test "$skip" = "true"; then untested="$untested $testname" else file_in=$testdir/in/$testname file_out=$testdir/$bitlen/$testname if test ! -r $file_out; then file_out=$testdir/32/$testname; fi if test ! -r $file_out; then touch $file_out; fi if test ! -r $file_in; then wrln "Error! Missing file, can't test $testname" exit 1 fi testmul=${testmul:-1000} wrtab -27 "* Testing $testname " for suf in $SUF; do file_diff=$testname-$suf.dif gp=$execdir/gp-$suf (echo 'gettime();0;'; cat $file_in; echo 'print("Total time spent: ",gettime);') | $RUNTEST $gp -q --test > $file_test 2>&1 diff -c $file_out $file_test > $file_diff pat=`grep "^[-+!] " $file_diff | grep -v "Total time"` time=`${tail}1 $file_test | sed -n 's,.*Total time spent: \(.*\),\1,p'` if test -n "$time"; then eval t='$'time$suf if test -n "$exprbug"; then t=`expr $time \'\*\' $testmul / 1000 + $t` else t=`expr $time '*' $testmul / 1000 + $t` fi eval time$suf=$t fi pre= if test -z "$pat"; then wr "gp-$suf..TIME=" wrtab 8 "$time "; else eval BUG$suf=BUG eval files$suf=\"'$'files$suf $file_diff\" wrtab -21 "gp-$suf..BUG [${time:-0}]" fi done wrln fi done $RM -f $file_test BUG= for suf in $SUF; do B=`eval echo '$'BUG$suf`; BUG="$BUG$B" t=`eval echo '$'time$suf` if test -n "$B"; then B=' [BUG]'; fi wrln "+++$B Total bench for gp-$suf is $t" done if test -n "$untested"; then wrln "The following tests were skipped:$untested" fi if test -z "$BUG"; then exit 0; fi pwd=`pwd` wrln wrln "PROBLEMS WERE NOTED. The following files list them in diff format: " wrln "Directory: $pwd" bugp=; buge=; for suf in $SUF; do B=`eval echo '$'BUG$suf`; BUG="$BUG$B" if test -n "$B"; then flist=`eval echo '$'files$suf` for f in $flist; do wrln " $f" case "$f" in *program*) bugp="$suf$bugp";; esac done fi done case "x$bugp" in x) file_diff=;; xsta|xdyn) end=" (gp-$bugp only)" file_diff=program-$bugp.dif;; xexe) end=" (gp-$bugp)" file_diff=program.dif;; x*) end="" file_diff=program-sta.dif;; esac if test -n "$file_diff"; then len=`wc -l $file_diff | sed -e 's/ *\([0-9]*\).*/\1/'` pat=`${head}4 $file_diff|${tail}1|grep "\(99\|100\),107"` case "$pat" in *99,107*) elen=29;; *100,107*) elen=24;; *) elen=0;; esac if test $len -eq $elen -a -n "$pat"; then cat << EOT NOTE: the problem noted in 'program' is that install() does not work in your configuration$end, so you will not be able to use this feature. Otherwise you can safely ignore the above warning. EOT fi fi exit 1 pari-2.7.5/src/funclist0000644000175000017500000012174412605246075013467 0ustar billbill1557685643 1558 ../functions/conversions/Col 3234299882 400 ../functions/conversions/Colrev 4195552700 684 ../functions/conversions/List 981428093 924 ../functions/conversions/Mat 2678939693 1487 ../functions/conversions/Mod 3703587249 1772 ../functions/conversions/Pol 812817715 914 ../functions/conversions/Polrev 2844602529 620 ../functions/conversions/Qfb 2571513257 1826 ../functions/conversions/Ser 1244914425 745 ../functions/conversions/Set 2425486384 993 ../functions/conversions/Str 1983631051 398 ../functions/conversions/Strchr 3668703910 592 ../functions/conversions/Strexpand 1117955044 413 ../functions/conversions/Strprintf 2125909664 423 ../functions/conversions/Strtex 1466495582 1560 ../functions/conversions/Vec 2107834942 595 ../functions/conversions/Vecrev 1108364263 729 ../functions/conversions/Vecsmall 1275004057 370 ../functions/conversions/binary 130657493 883 ../functions/conversions/bitand 972947861 613 ../functions/conversions/bitneg 1138344667 706 ../functions/conversions/bitnegimply 2059074700 616 ../functions/conversions/bitor 2769387502 923 ../functions/conversions/bittest 351827735 633 ../functions/conversions/bitxor 1456424929 513 ../functions/conversions/ceil 276292424 1030 ../functions/conversions/centerlift 4171436333 477 ../functions/conversions/characteristic 1580484749 1749 ../functions/conversions/component 2027282389 401 ../functions/conversions/conj 4003200502 838 ../functions/conversions/conjvec 2494482002 1105 ../functions/conversions/denominator 863736833 259 ../functions/conversions/digits 2072628265 514 ../functions/conversions/floor 689569802 220 ../functions/conversions/frac 958959570 550 ../functions/conversions/hammingweight 293423956 246 ../functions/conversions/imag 1061890972 1035 ../functions/conversions/length 1580940764 1934 ../functions/conversions/lift 2551633371 773 ../functions/conversions/liftall 1700859792 785 ../functions/conversions/liftint 2145004205 717 ../functions/conversions/liftpol 4165166886 433 ../functions/conversions/norm 765810884 922 ../functions/conversions/numerator 1895271770 411 ../functions/conversions/numtoperm 622159595 369 ../functions/conversions/padicprec 137224884 360 ../functions/conversions/permtonum 3807185038 2929 ../functions/conversions/precision 2831433609 3398 ../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 1113868494 1709 ../functions/conversions/truncate 3403630479 953 ../functions/conversions/valuation 3384175128 1425 ../functions/conversions/variable 2091712008 516 ../functions/default/TeXstyle 1101063589 291 ../functions/default/breakloop 2501181600 2179 ../functions/default/colors 45066311 2219 ../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 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 3654358528 443 ../functions/default/histsize 220523559 556 ../functions/default/lines 1161338771 240 ../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 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 712378547 1306 ../functions/default/realprecision 312510814 312 ../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 563829741 477 ../functions/default/threadsize 4240558956 932 ../functions/default/timer 4197571579 1431 ../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 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 1336341633 601 ../functions/elliptic_curves/elleta 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 1035396547 705 ../functions/elliptic_curves/ellidentify 1730986466 4261 ../functions/elliptic_curves/ellinit 240812548 602 ../functions/elliptic_curves/ellisoncurve 3064568940 281 ../functions/elliptic_curves/ellj 1723653689 1242 ../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 712202039 307 ../functions/elliptic_curves/ellordinate 722101610 1172 ../functions/elliptic_curves/ellperiods 1794297368 2153 ../functions/elliptic_curves/ellpointtoz 731455575 162 ../functions/elliptic_curves/ellpow 1097874931 763 ../functions/elliptic_curves/ellrootno 1004846089 1809 ../functions/elliptic_curves/ellsearch 2855813971 1140 ../functions/elliptic_curves/ellsigma 3595576828 241 ../functions/elliptic_curves/ellsub 3847829045 1085 ../functions/elliptic_curves/elltaniyama 463127701 362 ../functions/elliptic_curves/elltatepairing 4013058914 1362 ../functions/elliptic_curves/elltors 2219345950 318 ../functions/elliptic_curves/ellweilpairing 2456249932 1334 ../functions/elliptic_curves/ellwp 36981238 1480 ../functions/elliptic_curves/ellzeta 1222568733 758 ../functions/elliptic_curves/ellztopoint 1815276599 5553 ../functions/elliptic_curves/genus2red 1668730040 123 ../functions/gp2c/DEBUGLEVEL 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 2617906549 160 ../functions/gp2c_internal/_cgetg 1229532743 478 ../functions/gp2c_internal/_const 1013746615 244 ../functions/gp2c_internal/_formatcode 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 4035878089 888 ../functions/gp2c_internal/_tovec 918090833 2108 ../functions/gp2c_internal/_typedef 2426792003 312 ../functions/gp2c_internal/_wrap 1104882680 596 ../functions/graphic/plot 165946816 531 ../functions/graphic/plotbox 2126934426 451 ../functions/graphic/plotclip 3520235070 631 ../functions/graphic/plotcolor 610963136 883 ../functions/graphic/plotcopy 663081319 276 ../functions/graphic/plotcursor 2244201152 896 ../functions/graphic/plotdraw 11351953 5248 ../functions/graphic/ploth 755446296 758 ../functions/graphic/plothraw 2127523847 763 ../functions/graphic/plothsizes 917159818 1275 ../functions/graphic/plotinit 1507686506 430 ../functions/graphic/plotkill 2696127875 1249 ../functions/graphic/plotlines 2711875301 574 ../functions/graphic/plotlinetype 2326865526 226 ../functions/graphic/plotmove 3539834349 912 ../functions/graphic/plotpoints 607956083 364 ../functions/graphic/plotpointsize 774343927 553 ../functions/graphic/plotpointtype 1344949581 527 ../functions/graphic/plotrbox 2776236072 577 ../functions/graphic/plotrecth 1464208282 948 ../functions/graphic/plotrecthraw 140592524 479 ../functions/graphic/plotrline 1506919208 398 ../functions/graphic/plotrmove 1566746629 434 ../functions/graphic/plotrpoint 1103920392 743 ../functions/graphic/plotscale 2541689096 920 ../functions/graphic/plotstring 3542751079 547 ../functions/graphic/psdraw 3906960811 340 ../functions/graphic/psploth 1699338007 340 ../functions/graphic/psplothraw 1413077018 2361 ../functions/linear_algebra/algdep 1562845233 2766 ../functions/linear_algebra/charpoly 3926371483 2388 ../functions/linear_algebra/concat 1496930793 912 ../functions/linear_algebra/forqfvec 1135559220 2367 ../functions/linear_algebra/lindep 1885213010 438 ../functions/linear_algebra/listcreate 3413287768 475 ../functions/linear_algebra/listinsert 371937160 368 ../functions/linear_algebra/listkill 2352976546 526 ../functions/linear_algebra/listpop 1191932916 818 ../functions/linear_algebra/listput 884227144 781 ../functions/linear_algebra/listsort 4182706108 1104 ../functions/linear_algebra/matadjoint 2523670318 202 ../functions/linear_algebra/matcompanion 3032582234 2098 ../functions/linear_algebra/matconcat 486768866 1184 ../functions/linear_algebra/matdet 4230110372 1044 ../functions/linear_algebra/matdetint 3118559761 594 ../functions/linear_algebra/matdiagonal 2742450656 1427 ../functions/linear_algebra/mateigen 2715004006 710 ../functions/linear_algebra/matfrobenius 1006778180 243 ../functions/linear_algebra/mathess 1459166046 263 ../functions/linear_algebra/mathilbert 2893696448 4357 ../functions/linear_algebra/mathnf 3195530342 794 ../functions/linear_algebra/mathnfmod 3545461775 636 ../functions/linear_algebra/mathnfmodid 1353085894 335 ../functions/linear_algebra/mathouseholder 229723112 196 ../functions/linear_algebra/matid 3939387398 716 ../functions/linear_algebra/matimage 1659013314 551 ../functions/linear_algebra/matimagecompl 2979739119 519 ../functions/linear_algebra/matindexrank 372964243 648 ../functions/linear_algebra/matintersect 1920196350 820 ../functions/linear_algebra/matinverseimage 543305113 230 ../functions/linear_algebra/matisdiagonal 3529997100 775 ../functions/linear_algebra/matker 3907458254 868 ../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 4135328056 138 ../functions/linear_algebra/matrank 2190495821 621 ../functions/linear_algebra/matrix 4051332933 1509 ../functions/linear_algebra/matrixqz 2001534037 349 ../functions/linear_algebra/matsize 217283128 1574 ../functions/linear_algebra/matsnf 1385960588 493 ../functions/linear_algebra/matsolve 997433783 1442 ../functions/linear_algebra/matsolvemod 3658421602 866 ../functions/linear_algebra/matsupplement 4081660555 207 ../functions/linear_algebra/mattranspose 833948487 310 ../functions/linear_algebra/minpoly 1331290943 858 ../functions/linear_algebra/norml2 1423063517 1198 ../functions/linear_algebra/normlp 306041510 1038 ../functions/linear_algebra/qfauto 2469955322 783 ../functions/linear_algebra/qfautoexport 3205643715 970 ../functions/linear_algebra/qfbil 2663304455 1022 ../functions/linear_algebra/qfgaussred 2089217354 1080 ../functions/linear_algebra/qfisom 1265479323 1173 ../functions/linear_algebra/qfisominit 4164538816 878 ../functions/linear_algebra/qfjacobi 2738765226 3148 ../functions/linear_algebra/qflll 2571047474 1825 ../functions/linear_algebra/qflllgram 1151173386 5570 ../functions/linear_algebra/qfminim 1309940214 1092 ../functions/linear_algebra/qfnorm 884649199 631 ../functions/linear_algebra/qfperfection 3388145892 1110 ../functions/linear_algebra/qfrep 182597421 360 ../functions/linear_algebra/qfsign 3023808062 820 ../functions/linear_algebra/seralgdep 3338722377 634 ../functions/linear_algebra/setbinop 2553744756 320 ../functions/linear_algebra/setintersect 2037144827 574 ../functions/linear_algebra/setisset 2943622176 366 ../functions/linear_algebra/setminus 3876473219 1671 ../functions/linear_algebra/setsearch 1510185044 290 ../functions/linear_algebra/setunion 2343012690 397 ../functions/linear_algebra/trace 1009255636 2824 ../functions/linear_algebra/vecextract 4066532264 1527 ../functions/linear_algebra/vecsearch 2127481713 4246 ../functions/linear_algebra/vecsort 975438261 189 ../functions/linear_algebra/vecsum 3631831174 1145 ../functions/linear_algebra/vector 2820295330 518 ../functions/linear_algebra/vectorsmall 864292486 288 ../functions/linear_algebra/vectorv 2163373123 136 ../functions/member_functions/a1 3140155039 136 ../functions/member_functions/a2 2912778027 136 ../functions/member_functions/a3 3432772391 136 ../functions/member_functions/a4 1592124589 137 ../functions/member_functions/a6 3865780186 90 ../functions/member_functions/area 2455216452 137 ../functions/member_functions/b2 3948972502 136 ../functions/member_functions/b4 1332019359 143 ../functions/member_functions/b6 67273382 136 ../functions/member_functions/b8 3822771829 195 ../functions/member_functions/bid 2143476547 221 ../functions/member_functions/bnf 175549204 136 ../functions/member_functions/c4 655992956 136 ../functions/member_functions/c6 2702710967 266 ../functions/member_functions/clgp 1828862026 96 ../functions/member_functions/codiff 3653427790 286 ../functions/member_functions/cyc 71312838 199 ../functions/member_functions/diff 3827599499 249 ../functions/member_functions/disc 979383943 128 ../functions/member_functions/e 958863332 87 ../functions/member_functions/eta 1589707435 127 ../functions/member_functions/f 3436115540 229 ../functions/member_functions/fu 2707998417 90 ../functions/member_functions/futu 2100492099 327 ../functions/member_functions/gen 778199454 187 ../functions/member_functions/group 1590134045 204 ../functions/member_functions/index 788494505 132 ../functions/member_functions/j 2438121695 87 ../functions/member_functions/mod 2859016160 176 ../functions/member_functions/nf 3500876418 280 ../functions/member_functions/no 22232489 93 ../functions/member_functions/omega 3263892110 151 ../functions/member_functions/orders 3555377828 230 ../functions/member_functions/p 1896741290 242 ../functions/member_functions/pol 1365247405 96 ../functions/member_functions/polabs 2389381105 189 ../functions/member_functions/r1 2681820181 189 ../functions/member_functions/r2 3310137925 236 ../functions/member_functions/reg 4264971167 254 ../functions/member_functions/roots 3731349347 194 ../functions/member_functions/sign 131338638 142 ../functions/member_functions/t2 482533715 90 ../functions/member_functions/tate 2008126926 133 ../functions/member_functions/tu 2066290395 90 ../functions/member_functions/tufu 1665968088 171 ../functions/member_functions/zk 2924685257 142 ../functions/member_functions/zkst 817575908 1451 ../functions/number_fields/bnfcertify 654416520 1799 ../functions/number_fields/bnfcompress 1086935842 498 ../functions/number_fields/bnfdecodemodule 43800451 5200 ../functions/number_fields/bnfinit 476507862 895 ../functions/number_fields/bnfisintnorm 2795798373 1520 ../functions/number_fields/bnfisnorm 2303255407 2749 ../functions/number_fields/bnfisprincipal 1025672292 530 ../functions/number_fields/bnfissunit 3277737232 1587 ../functions/number_fields/bnfisunit 3303533017 819 ../functions/number_fields/bnfnarrow 30185140 954 ../functions/number_fields/bnfsignunit 2219572014 1154 ../functions/number_fields/bnfsunit 228098176 2890 ../functions/number_fields/bnrL1 2672702749 1215 ../functions/number_fields/bnrclassno 826486578 1183 ../functions/number_fields/bnrclassnolist 1390393093 1044 ../functions/number_fields/bnrconductor 2388880686 434 ../functions/number_fields/bnrconductorofchar 4134011564 1456 ../functions/number_fields/bnrdisc 3292276537 2779 ../functions/number_fields/bnrdisclist 299142429 2215 ../functions/number_fields/bnrinit 1297085953 549 ../functions/number_fields/bnrisconductor 4098267331 1306 ../functions/number_fields/bnrisprincipal 1309169618 1461 ../functions/number_fields/bnrrootnumber 1162900897 2256 ../functions/number_fields/bnrstark 653819746 346 ../functions/number_fields/dirzetak 1635227253 1321 ../functions/number_fields/factornf 1651383721 1335 ../functions/number_fields/galoisexport 1065509842 1919 ../functions/number_fields/galoisfixedfield 2282821753 1518 ../functions/number_fields/galoisgetpol 690345336 1105 ../functions/number_fields/galoisidentify 1065659861 3871 ../functions/number_fields/galoisinit 474428460 542 ../functions/number_fields/galoisisabelian 3491431523 559 ../functions/number_fields/galoisisnormal 999481307 869 ../functions/number_fields/galoispermtopol 415883189 2573 ../functions/number_fields/galoissubcyclo 1739582821 432 ../functions/number_fields/galoissubfields 1103908484 810 ../functions/number_fields/galoissubgroups 4041888397 1330 ../functions/number_fields/idealadd 2595771256 868 ../functions/number_fields/idealaddtoone 988771264 1290 ../functions/number_fields/idealappr 819005822 685 ../functions/number_fields/idealchinese 2736419638 376 ../functions/number_fields/idealcoprime 1528977577 990 ../functions/number_fields/idealdiv 133283560 454 ../functions/number_fields/idealfactor 706829025 1831 ../functions/number_fields/idealfactorback 901201287 1024 ../functions/number_fields/idealfrobenius 3001711766 2079 ../functions/number_fields/idealhnf 2234579433 753 ../functions/number_fields/idealintersect 3755090162 414 ../functions/number_fields/idealinv 4061325327 2136 ../functions/number_fields/ideallist 3313133009 1746 ../functions/number_fields/ideallistarch 1430471263 1066 ../functions/number_fields/ideallog 1577350712 385 ../functions/number_fields/idealmin 392441553 1275 ../functions/number_fields/idealmul 2213617432 214 ../functions/number_fields/idealnorm 3621386739 392 ../functions/number_fields/idealnumden 590254486 900 ../functions/number_fields/idealpow 4185462448 1955 ../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 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 794927693 569 ../functions/number_fields/nfbasistoalg 1941191205 887 ../functions/number_fields/nfcertify 1793444342 342 ../functions/number_fields/nfdetint 3831355376 1546 ../functions/number_fields/nfdisc 2893425002 219 ../functions/number_fields/nfeltadd 3704437998 223 ../functions/number_fields/nfeltdiv 64595969 403 ../functions/number_fields/nfeltdiveuc 2739572936 524 ../functions/number_fields/nfeltdivmodpr 2441182165 345 ../functions/number_fields/nfeltdivrem 1301142194 423 ../functions/number_fields/nfeltmod 1895398557 223 ../functions/number_fields/nfeltmul 366144574 521 ../functions/number_fields/nfeltmulmodpr 1405889410 145 ../functions/number_fields/nfeltnorm 3943733724 354 ../functions/number_fields/nfeltpow 3035074752 512 ../functions/number_fields/nfeltpowmodpr 3760170244 359 ../functions/number_fields/nfeltreduce 3125536475 519 ../functions/number_fields/nfeltreducemodpr 2932345806 150 ../functions/number_fields/nfelttrace 3293746003 460 ../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 624126709 736 ../functions/number_fields/nfhilbert 2072610218 507 ../functions/number_fields/nfhnf 868333029 539 ../functions/number_fields/nfhnfmod 1082558102 7702 ../functions/number_fields/nfinit 1575169407 243 ../functions/number_fields/nfisideal 196768795 980 ../functions/number_fields/nfisincl 1085970401 276 ../functions/number_fields/nfisisom 2783715111 448 ../functions/number_fields/nfkermodpr 3646082924 433 ../functions/number_fields/nfmodprinit 987402003 612 ../functions/number_fields/nfnewprec 770708172 1418 ../functions/number_fields/nfroots 967762132 1587 ../functions/number_fields/nfrootsof1 503060488 1181 ../functions/number_fields/nfsnf 1005488227 839 ../functions/number_fields/nfsolvemodpr 2732061843 972 ../functions/number_fields/nfsubfields 1252868226 3254 ../functions/number_fields/polcompositum 1565615061 4266 ../functions/number_fields/polgalois 754868682 1743 ../functions/number_fields/polred 1630097175 4003 ../functions/number_fields/polredabs 2588514985 2291 ../functions/number_fields/polredbest 2107242093 512 ../functions/number_fields/polredord 2575474898 466 ../functions/number_fields/poltschirnhaus 963192925 481 ../functions/number_fields/rnfalgtobasis 2597801200 778 ../functions/number_fields/rnfbasis 2039453614 422 ../functions/number_fields/rnfbasistoalg 1430816044 577 ../functions/number_fields/rnfcharpoly 332875321 1089 ../functions/number_fields/rnfconductor 493784289 3512 ../functions/number_fields/rnfdedekind 2250737713 235 ../functions/number_fields/rnfdet 3226307783 779 ../functions/number_fields/rnfdisc 2002861846 882 ../functions/number_fields/rnfeltabstorel 3119689782 909 ../functions/number_fields/rnfeltdown 2065307501 537 ../functions/number_fields/rnfeltnorm 4001592359 757 ../functions/number_fields/rnfeltreltoabs 1118338923 516 ../functions/number_fields/rnfelttrace 205183268 667 ../functions/number_fields/rnfeltup 4138499114 2180 ../functions/number_fields/rnfequation 3457630168 562 ../functions/number_fields/rnfhnfbasis 3710921157 1501 ../functions/number_fields/rnfidealabstorel 3524519381 482 ../functions/number_fields/rnfidealdown 2124882618 471 ../functions/number_fields/rnfidealhnf 2972910198 410 ../functions/number_fields/rnfidealmul 1270402441 572 ../functions/number_fields/rnfidealnormabs 190446714 445 ../functions/number_fields/rnfidealnormrel 295860721 993 ../functions/number_fields/rnfidealreltoabs 3572608050 463 ../functions/number_fields/rnfidealtwoelt 460503870 915 ../functions/number_fields/rnfidealup 890141568 3847 ../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 1425929762 773 ../functions/number_fields/rnfpolred 2338701732 1880 ../functions/number_fields/rnfpolredabs 2550913263 1973 ../functions/number_fields/rnfpolredbest 2300324313 858 ../functions/number_fields/rnfpseudobasis 4120760786 981 ../functions/number_fields/rnfsteinitz 3857332923 2021 ../functions/number_fields/subgrouplist 3758453012 2039 ../functions/number_fields/zetak 4294924339 1394 ../functions/number_fields/zetakinit 215042210 749 ../functions/number_theoretical/addprimes 143929946 2147 ../functions/number_theoretical/bestappr 3704641807 1922 ../functions/number_theoretical/bestapprPade 371659487 161 ../functions/number_theoretical/bezout 3857964875 371 ../functions/number_theoretical/bigomega 590656338 526 ../functions/number_theoretical/binomial 3062219339 1967 ../functions/number_theoretical/chinese 686535871 1031 ../functions/number_theoretical/content 1721333311 2932 ../functions/number_theoretical/contfrac 2762680277 1347 ../functions/number_theoretical/contfracpnqn 1215033860 661 ../functions/number_theoretical/core 498340475 1129 ../functions/number_theoretical/coredisc 4003493065 334 ../functions/number_theoretical/dirdiv 2123078772 1158 ../functions/number_theoretical/direuler 418145044 689 ../functions/number_theoretical/dirmul 3382938550 627 ../functions/number_theoretical/divisors 3233091324 525 ../functions/number_theoretical/eulerphi 3437351073 6295 ../functions/number_theoretical/factor 3273804125 1262 ../functions/number_theoretical/factorback 1023766457 729 ../functions/number_theoretical/factorcantor 3573143606 1568 ../functions/number_theoretical/factorff 4089779703 347 ../functions/number_theoretical/factorial 3706897439 2084 ../functions/number_theoretical/factorint 4224377394 813 ../functions/number_theoretical/factormod 2120464340 1834 ../functions/number_theoretical/ffgen 4176254427 703 ../functions/number_theoretical/ffinit 3488041316 1370 ../functions/number_theoretical/fflog 3597614832 652 ../functions/number_theoretical/ffnbirred 3573775947 860 ../functions/number_theoretical/fforder 1640799602 1120 ../functions/number_theoretical/ffprimroot 641658465 176 ../functions/number_theoretical/fibonacci 1168948070 2303 ../functions/number_theoretical/gcd 80527233 1123 ../functions/number_theoretical/gcdext 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 1505640347 2566 ../functions/number_theoretical/isprime 1951470040 472 ../functions/number_theoretical/isprimepower 4202316639 1562 ../functions/number_theoretical/ispseudoprime 1582139366 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 2023281030 968 ../functions/number_theoretical/logint 2160606288 190 ../functions/number_theoretical/moebius 4254054828 481 ../functions/number_theoretical/nextprime 2039825979 524 ../functions/number_theoretical/numbpart 1077510865 221 ../functions/number_theoretical/numdiv 3812027075 362 ../functions/number_theoretical/omega 2724935271 2116 ../functions/number_theoretical/partitions 3412010667 1219 ../functions/number_theoretical/polrootsff 805028202 497 ../functions/number_theoretical/precprime 3693765799 270 ../functions/number_theoretical/prime 429279699 442 ../functions/number_theoretical/primepi 530053972 619 ../functions/number_theoretical/primes 2798669539 2553 ../functions/number_theoretical/qfbclassno 3695050800 431 ../functions/number_theoretical/qfbcompraw 1940983238 339 ../functions/number_theoretical/qfbhclassno 973965715 902 ../functions/number_theoretical/qfbnucomp 2697822130 368 ../functions/number_theoretical/qfbnupow 3393949890 338 ../functions/number_theoretical/qfbpowraw 3859788640 639 ../functions/number_theoretical/qfbprimeform 760904670 1434 ../functions/number_theoretical/qfbred 2106514910 916 ../functions/number_theoretical/qfbsolve 3231541093 2938 ../functions/number_theoretical/quadclassunit 411309927 217 ../functions/number_theoretical/quaddisc 4137872200 445 ../functions/number_theoretical/quadgen 1926712746 577 ../functions/number_theoretical/quadhilbert 1522706503 423 ../functions/number_theoretical/quadpoly 376107392 612 ../functions/number_theoretical/quadray 3392391708 376 ../functions/number_theoretical/quadregulator 426124966 575 ../functions/number_theoretical/quadunit 1182031813 521 ../functions/number_theoretical/randomprime 3397278150 476 ../functions/number_theoretical/removeprimes 405726717 467 ../functions/number_theoretical/sigma 2721939469 441 ../functions/number_theoretical/sqrtint 504793252 509 ../functions/number_theoretical/sqrtnint 2352169098 1346 ../functions/number_theoretical/stirling 1102505332 332 ../functions/number_theoretical/sumdedekind 1060747982 357 ../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 3219363957 1133 ../functions/number_theoretical/znstar 280573390 1171 ../functions/operators/cmp 2333676171 1120 ../functions/operators/divrem 1311333090 875 ../functions/operators/lex 3424443404 548 ../functions/operators/max 1305994321 548 ../functions/operators/min 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 542241653 848 ../functions/polynomials/deriv 3783180479 1942 ../functions/polynomials/diffop 2644110396 1484 ../functions/polynomials/eval 997399994 1498 ../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 3865942159 896 ../functions/polynomials/polcyclo 3980671021 912 ../functions/polynomials/polcyclofactors 2540383469 797 ../functions/polynomials/poldegree 288092554 771 ../functions/polynomials/poldisc 1885087402 528 ../functions/polynomials/poldiscreduced 838056086 250 ../functions/polynomials/polgraeffe 2695444232 1133 ../functions/polynomials/polhensellift 2042242352 534 ../functions/polynomials/polhermite 3350225564 749 ../functions/polynomials/polinterpolate 1007436899 437 ../functions/polynomials/poliscyclo 4075425120 497 ../functions/polynomials/poliscycloprod 2559408188 460 ../functions/polynomials/polisirreducible 4266292747 609 ../functions/polynomials/pollead 693228044 460 ../functions/polynomials/pollegendre 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 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 3084901600 333 ../functions/polynomials/serconvol 678736819 330 ../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 3300553752 136 ../functions/programming/_eval_mnemonic 3140964717 1110 ../functions/programming/addhelp 983874885 1936 ../functions/programming/alarm 164541180 1843 ../functions/programming/alias 2897255199 2301 ../functions/programming/allocatemem 3731392400 1596 ../functions/programming/apply 1649867724 490 ../functions/programming/break 3619971697 685 ../functions/programming/breakpoint 1655863837 273 ../functions/programming/dbg_down 2271483609 697 ../functions/programming/dbg_err 4050270931 329 ../functions/programming/dbg_up 902450922 470 ../functions/programming/dbg_x 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 1154955545 285 ../functions/programming/for 1548115268 1490 ../functions/programming/forcomposite 1930174191 1067 ../functions/programming/fordiv 1011325593 915 ../functions/programming/forell 3742891725 2400 ../functions/programming/forpart 523389040 2355 ../functions/programming/forprime 4097689279 583 ../functions/programming/forstep 3286177718 2061 ../functions/programming/forsubgroup 1526035725 1339 ../functions/programming/forvec 1575287630 347 ../functions/programming/getabstime 748638207 252 ../functions/programming/getenv 4278770330 361 ../functions/programming/getheap 3575456435 442 ../functions/programming/getrand 4109487323 285 ../functions/programming/getstack 3623950775 385 ../functions/programming/gettime 551521830 165 ../functions/programming/global 1141761031 2392 ../functions/programming/if 3720775545 10465 ../functions/programming/iferr 2051796286 494 ../functions/programming/inline 1949270646 754 ../functions/programming/input 490792963 3434 ../functions/programming/install 2467288771 1469 ../functions/programming/kill 3065531026 125 ../functions/programming/local 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 325469141 592 ../functions/programming/parselect 2300142208 700 ../functions/programming/parsum 3003736710 744 ../functions/programming/parvector 1811616303 333 ../functions/programming/print 3073867138 437 ../functions/programming/print1 3605500215 7805 ../functions/programming/printf 3800076878 384 ../functions/programming/printsep 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 2278186691 967 ../functions/programming/readvec 1182439920 287 ../functions/programming/return 1550019273 2768 ../functions/programming/select 3452942428 504 ../functions/programming/setrand 3720197410 447 ../functions/programming/system 3717803513 2317 ../functions/programming/trap 722695522 608 ../functions/programming/type 419976951 184 ../functions/programming/uninline 3467212281 421 ../functions/programming/until 2538936335 2381 ../functions/programming/version 3287864719 509 ../functions/programming/warning 1594674442 434 ../functions/programming/whatnow 3282345452 395 ../functions/programming/while 559370645 305 ../functions/programming/write 3083331806 313 ../functions/programming/write1 1788791396 1947 ../functions/programming/writebin 3395311360 248 ../functions/programming/writetex 4162161133 1023 ../functions/sums/derivnum 847633432 836 ../functions/sums/intcirc 675879057 862 ../functions/sums/intfouriercos 3481939193 904 ../functions/sums/intfourierexp 3947097796 857 ../functions/sums/intfouriersin 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 3061973932 975 ../functions/sums/intnuminitgen 2361868629 2774 ../functions/sums/intnumromb 400964355 342 ../functions/sums/intnumstep 3675594259 1432 ../functions/sums/prod 238922829 499 ../functions/sums/prodeuler 4010920763 901 ../functions/sums/prodinf 3627520822 712 ../functions/sums/solve 1209900028 648 ../functions/sums/sum 2063081340 2085 ../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 3764491866 847 ../functions/symbolic_operators/add 3353925834 892 ../functions/symbolic_operators/adde 2224582694 150 ../functions/symbolic_operators/and 807393942 311 ../functions/symbolic_operators/call 2207444170 1092 ../functions/symbolic_operators/coeff 2209173128 720 ../functions/symbolic_operators/compr 1114647704 290 ../functions/symbolic_operators/concat 3074747166 189 ../functions/symbolic_operators/deriv 1369992067 682 ../functions/symbolic_operators/div 2294767635 742 ../functions/symbolic_operators/dive 1770025917 530 ../functions/symbolic_operators/divent 534012629 385 ../functions/symbolic_operators/divente 1255088825 253 ../functions/symbolic_operators/divround 857501574 337 ../functions/symbolic_operators/divrounde 1716660983 1368 ../functions/symbolic_operators/eq 57471919 155 ../functions/symbolic_operators/fact 2828464303 790 ../functions/symbolic_operators/ge 4062103410 781 ../functions/symbolic_operators/gt 928796544 231 ../functions/symbolic_operators/hist 4154293089 124 ../functions/symbolic_operators/id 541828836 846 ../functions/symbolic_operators/le 551395660 778 ../functions/symbolic_operators/lt 4095498863 516 ../functions/symbolic_operators/mm 1103955639 457 ../functions/symbolic_operators/mod 481421093 476 ../functions/symbolic_operators/mode 3747397195 784 ../functions/symbolic_operators/mul 328650357 839 ../functions/symbolic_operators/mule 1979227420 1160 ../functions/symbolic_operators/ne 3811200823 292 ../functions/symbolic_operators/neg 4083690638 171 ../functions/symbolic_operators/not 4250259204 164 ../functions/symbolic_operators/or 331309622 293 ../functions/symbolic_operators/pl 3007025652 276 ../functions/symbolic_operators/pound 3891617857 897 ../functions/symbolic_operators/pow 3484290447 532 ../functions/symbolic_operators/pp 350299153 195 ../functions/symbolic_operators/range 1327651723 238 ../functions/symbolic_operators/shiftl 2222950945 363 ../functions/symbolic_operators/shiftle 540758560 300 ../functions/symbolic_operators/shiftr 3408057925 372 ../functions/symbolic_operators/shiftre 3157788552 440 ../functions/symbolic_operators/slice 1170897255 771 ../functions/symbolic_operators/sub 3687286192 892 ../functions/symbolic_operators/sube 3333748126 198 ../functions/symbolic_operators/trans 278423019 370 ../functions/transcendental/Catalan 3203114013 323 ../functions/transcendental/Euler 4128767667 143 ../functions/transcendental/I 835661978 301 ../functions/transcendental/Pi 3536365179 841 ../functions/transcendental/abs 2484349986 482 ../functions/transcendental/acos 2034584490 370 ../functions/transcendental/acosh 186570540 526 ../functions/transcendental/agm 2673702082 198 ../functions/transcendental/arg 2799632495 484 ../functions/transcendental/asin 3069830700 366 ../functions/transcendental/asinh 1571898858 473 ../functions/transcendental/atan 2789708507 335 ../functions/transcendental/atanh 3784737751 311 ../functions/transcendental/bernfrac 2362022768 283 ../functions/transcendental/bernpol 1190142878 304 ../functions/transcendental/bernreal 1159767886 728 ../functions/transcendental/bernvec 2423860598 208 ../functions/transcendental/besselh1 2824405762 208 ../functions/transcendental/besselh2 391768912 364 ../functions/transcendental/besseli 1918729913 364 ../functions/transcendental/besselj 52495517 446 ../functions/transcendental/besseljh 2577688153 201 ../functions/transcendental/besselk 3275725244 201 ../functions/transcendental/besseln 2865291733 112 ../functions/transcendental/cos 3610629014 137 ../functions/transcendental/cosh 3039924894 124 ../functions/transcendental/cotan 3749138764 232 ../functions/transcendental/dilog 1358921222 1230 ../functions/transcendental/eint1 2742925928 351 ../functions/transcendental/erfc 1932581236 1106 ../functions/transcendental/eta 4186273876 387 ../functions/transcendental/exp 3219425904 1030 ../functions/transcendental/expm1 283840075 815 ../functions/transcendental/gamma 2489052783 171 ../functions/transcendental/gammah 1703809654 306 ../functions/transcendental/hyperu 2351714423 626 ../functions/transcendental/incgam 1394040053 409 ../functions/transcendental/incgamc 2417873690 225 ../functions/transcendental/lambertw 2152402485 1030 ../functions/transcendental/lngamma 3393608858 1090 ../functions/transcendental/log 2637087612 1600 ../functions/transcendental/polylog 1987478852 188 ../functions/transcendental/psi 1520878203 108 ../functions/transcendental/sin 2704877408 133 ../functions/transcendental/sinh 473305427 963 ../functions/transcendental/sqr 685184966 819 ../functions/transcendental/sqrt 213571604 1522 ../functions/transcendental/sqrtn 1255385460 114 ../functions/transcendental/tan 1579606196 139 ../functions/transcendental/tanh 4246144284 278 ../functions/transcendental/teichmuller 2713807692 227 ../functions/transcendental/theta 1059709706 476 ../functions/transcendental/thetanullk 2007207279 1064 ../functions/transcendental/weber 298482603 822 ../functions/transcendental/zeta pari-2.7.5/src/kernel/0000755000175000017500000000000012613365633013165 5ustar billbillpari-2.7.5/src/kernel/ppc64/0000755000175000017500000000000012613365633014121 5ustar billbillpari-2.7.5/src/kernel/ppc64/asm0.h0000644000175000017500000000502512366172547015141 0ustar billbill/* 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. */ /* ASM addll mulll bfffo NOASM divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addc %0,%2,%3\n\txor %1,%2,%2\n\taddze %1,%4\n\t" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong) 0)); \ __value; \ }) #define addllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addc %0,%3,%4\n\tli %1,0\n\taddze %1,%4\n\taddc %0,%2,%5\n\taddze %1,%4\n\t" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" (overflow), "0" ((ulong) 0)); \ __value; \ }) #define bfffo(a) \ __extension__ ({ ulong __a = (a), __value; \ __asm__ ("cntlzd %0, %1" : "=r" (__value) : "r" (__a)); \ __value; \ }) #define subll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subfc %0,%3,%2\n\tli %1,0\n\taddme %1,%4\n\tneg %1,%4" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong)0)); \ __value; \ }) #define subllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subfc %0,%5,%2\n\tli %1,0\n\taddme %1,%5\n\tsubfc %0,%3,%4\n\taddme %1,%5\n\tneg %1,%5" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong)0), "1" (overflow)); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("mulhdu %1,%2,%3\n\tmulld %0,%2,%3\n\t" \ : "=r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mulld %0,%3,%4\n\tmulhdu %2,%3,%4\n\taddc %0,%5,%6\n\taddze %1,%7\n\t" \ : "=&r" (__value), "=r" (hiremainder), "=r" (__temp) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0), "1" (hiremainder), "2" ((ulong) 0)); \ __value; \ }) #endif pari-2.7.5/src/kernel/README0000644000175000017500000000267611636712103014050 0ustar billbillThere is a different directory for each value of "$asmarch". If it contain files MakeLVL[01].SH, these are included in the general Makefile. It contains rules for creating headers and object files in the build directory. The list of object files is given by "$kernel" (default: "mp mpinl") * Level 0 symbols, in object file mpinl.o, are : overflow hiremainder addll addllx subll subllx mulll addmul divll bfffo If no assembler implementation is available the definitions are in none/ (addll.h, mulll.h, bfffo.h, divll.h). Otherwise, in $asmarch/asm0.h If MakeLVL0.SH is not present, the file asm0.h is treated by config/genkernel, creating parilvl0.h. The script expands the following tokens [ to be placed in a C comment ] as follows: ^ASM mod1 mod2 // asm0.h implements modules mod1, mod2 ^NOASM mod1 mod2 // asm0.h does not implement modules mod1, mod2 where mod1, mod2 etc. are modules among addll, mulll, bfffo, divll. In effect, this includes portable code from kernel/none/.h to supplement whatever is provided by asm0.h. CAVEAT: if bfffo and divll are both mentioned, they must appear in this order (divll depends on bfffo). * Inline Level 1 symbols, in mpinl.o: the definitions are in none/level1.h. Inlining may or may not be possible, but a symbol must be defined in mpinl.o in any case. * Non-Inline Level 1 symbols, defined in mp.o: the definitions are in various *.c files in none/ and gmp/ concatenated into $objdir/mp.c. pari-2.7.5/src/kernel/ix86/0000755000175000017500000000000012613365633013763 5ustar billbillpari-2.7.5/src/kernel/ix86/asm0.h0000644000175000017500000001215712366172547015007 0ustar billbill#line 2 "../src/kernel/ix86/asm0.h" /* 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. */ /* This file defines some "level 0" kernel functions for Intel ix86 */ /* It is intended for use with an external "asm" definition */ /* ASM addll mulll bfffo divll */ #ifdef ASMINLINE /* Written by Bruno Haible, 1996-1998. addllx8/subllx8 by Bill Allombert, 2011. */ /* This file can assume the GNU C extensions. (It is included only if __GNUC__ is defined.) */ /* Use local variables whenever possible. */ #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addl %3,%0 ; adcl %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subl %5,%2 ; adcl %4,%0 ; adcl %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subl %5, %0 \n\t" \ "movl (%2), %0 ; adcl (%3),%0; movl %0, (%4) \n\t" \ "movl -4(%2), %0 ; adcl -4(%3),%0; movl %0, -4(%4) \n\t" \ "movl -8(%2), %0 ; adcl -8(%3),%0; movl %0, -8(%4) \n\t" \ "movl -12(%2), %0 ; adcl -12(%3),%0; movl %0, -12(%4) \n\t" \ "movl -16(%2), %0 ; adcl -16(%3),%0; movl %0, -16(%4) \n\t" \ "movl -20(%2), %0 ; adcl -20(%3),%0; movl %0, -20(%4) \n\t" \ "movl -24(%2), %0 ; adcl -24(%3),%0; movl %0, -24(%4) \n\t" \ "movl -28(%2), %0 ; adcl -28(%3),%0; movl %0, -28(%4) \n\t" \ "adcl %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) : "cc"); \ } while(0) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subl %3,%0 ; adcl %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subl %5,%2 ; sbbl %4,%0 ; adcl %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subl %5, %0 \n\t" \ "movl (%2), %0 ; sbbl (%3),%0; movl %0, (%4) \n\t" \ "movl -4(%2), %0 ; sbbl -4(%3),%0; movl %0, -4(%4) \n\t" \ "movl -8(%2), %0 ; sbbl -8(%3),%0; movl %0, -8(%4) \n\t" \ "movl -12(%2), %0 ; sbbl -12(%3),%0; movl %0, -12(%4) \n\t" \ "movl -16(%2), %0 ; sbbl -16(%3),%0; movl %0, -16(%4) \n\t" \ "movl -20(%2), %0 ; sbbl -20(%3),%0; movl %0, -20(%4) \n\t" \ "movl -24(%2), %0 ; sbbl -24(%3),%0; movl %0, -24(%4) \n\t" \ "movl -28(%2), %0 ; sbbl -28(%3),%0; movl %0, -28(%4) \n\t" \ "adcl %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) : "cc"); \ } while(0) #define mulll(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b); \ __asm__ ("mull %3" \ : "=a" /* %eax */ (__valuelo), "=d" /* %edx */ (hiremainder) \ : "0" (__arg1), "rm" (__arg2)); \ __valuelo; \ }) #define addmul(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mull %4 ; addl %5,%0 ; adcl %6,%1" \ : "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (hiremainder), "=r" (__temp) \ : "0" (__arg1), "rm" (__arg2), "g" (hiremainder), "2" ((ulong)0)); \ __valuelo; \ }) #define divll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("divl %4" \ : "=a" /* %eax */ (__value), "=d" /* %edx */ (hiremainder) \ : "0" /* %eax */ (__arg1), "1" /* %edx */ (hiremainder), "mr" (__arg2)); \ __value; \ }) #define bfffo(x) \ __extension__ ({ ulong __arg = (x); \ int leading_one_position; \ __asm__ ("bsrl %1,%0" : "=r" (leading_one_position) : "rm" (__arg)); \ 31 - leading_one_position; \ }) #endif pari-2.7.5/src/kernel/ia64/0000755000175000017500000000000012613365633013730 5ustar billbillpari-2.7.5/src/kernel/ia64/asm1.h0000644000175000017500000000406111636712103014733 0ustar billbill/* Extracted from gmp-4.1.2 * FIXME: This file is unused until somebody implements * invert_word(x) = return floor( 2^(2*BIL)/x ) */ extern ulong invert_word(ulong); #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __extension__ ({ \ ulong __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - (__x > (al)); \ (sl) = __x; \ }) #define divll(x, y) \ __extension__ ({ \ register ulong _di, _x = (x), _y = (y), _q, _ql, _r; \ register ulong _xh, _xl, _k, __hire; \ \ if (_y & 0x8000000000000000UL) \ { _k = 0; __hire = hiremainder; } \ else \ { \ _k = bfffo(_y); \ __hire = (hiremainder << _k) | (_x >> (64 - _k)); \ _x <<= _k; _y <<= _k; \ } \ _di = invert_word(_y); \ _ql = mulll (__hire, _di); \ _q = __hire + hiremainder; \ _xl = mulll(_q, _y); _xh = hiremainder; \ sub_ddmmss (_xh, _r, __hire, _x, _xh, _xl); \ if (_xh != 0) \ { \ sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; \ if (_xh != 0) \ { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; } \ } \ if (_r >= _y) \ { _r -= _y; _q += 1; } \ hiremainder = _r >> _k; \ _q; \ }) pari-2.7.5/src/kernel/ia64/asm0.h0000644000175000017500000000521212366172547014746 0ustar billbill#line 2 "../src/kernel/ia64/asm0.h" /* Copyright (C) 2006 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. */ /* ASM mulll bfffo NOASM addll divll */ #ifdef ASMINLINE /* Written by Guillaume Hanrot */ #define LOCAL_HIREMAINDER register ulong hiremainder #define bfffo(a) \ __extension__ ({ ulong __arg1 = (a), __tmp, _a, _c; \ __asm__ ("mux1 %0 = %1, @rev" : "=r" (__tmp) : "r" (__arg1)); \ __asm__ ("czx1.l %0 = %1" : "=r" (_a) : "r" (-__tmp | __tmp)); \ _c = (_a - 1) << 3; \ __arg1 >>= _c; \ if (__arg1 >= 1 << 4) \ __arg1 >>= 4, _c += 4; \ if (__arg1 >= 1 << 2) \ __arg1 >>= 2, _c += 2; \ _c += __arg1 >> 1; \ 63 - _c; \ }) #define mulll(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value; \ __asm__ ("xma.hu %0 = %2, %3, f0\n\t;;\n\txma.l %1 = %2, %3, f0" \ : "=&f" (hiremainder), "=f" (__value) \ : "f" (__arg1), "f" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value; \ __asm__ ("xma.hu %0 = %2, %3, %4\n\txma.l %1 = %2, %3, %4" \ : "=&f" (hiremainder), "=f" (__value) \ : "f" (__arg1), "f" (__arg2), "f" (hiremainder)); \ __value; \ }) #endif pari-2.7.5/src/kernel/sparcv8_micro/0000755000175000017500000000000012613365633015744 5ustar billbillpari-2.7.5/src/kernel/sparcv8_micro/asm0.h0000644000175000017500000000170512366172547016765 0ustar billbill/* 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. */ /* ASM divll */ #ifdef ASMINLINE #define divll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __tmp; \ __asm__( "mov %1, %%y; nop;nop;nop;\n\t\ udivcc %3,%4,%0;\n\tumul %0,%4,%2;\n\tsub %3,%2,%1"\ : "=&r" (__value), "=&r" (hiremainder), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "1" (hiremainder) \ : "cc"); \ __value;}) #endif pari-2.7.5/src/kernel/sparcv8_micro/MakeLVL0.SH0000644000175000017500000000020411636712103017477 0ustar billbillcat >> $file << EOT parilvl0.h: $kern0/asm0-common.h \$(L0MODS) $cfg/genkernel $kern0/asm0-common.h $kern0/asm0.h > parilvl0.h EOT pari-2.7.5/src/kernel/sparcv8_micro/asm0-common.h0000644000175000017500000000476312366172547020262 0ustar billbill/* 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. */ /* This file is common to SuperSparc and MicroSparc */ /* ASM addll mulll NOASM bfffo */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ( "addcc %2,%3,%0; \ addx %%g0,%%g0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ( "subcc %%g0,%1,%%g0; \ addxcc %2,%3,%0; \ addx %%g0,%%g0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" (overflow) \ : "cc"); \ __value; }) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ( "subcc %2,%3,%0; \ addx %%g0,%%g0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ( "subcc %%g0,%1,%%g0; \ subxcc %2,%3,%0; \ addx %%g0,%%g0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" (overflow) \ : "cc"); \ __value; }) #define mulll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ( "umul %2,%3,%0; \ rd %%y,%1" \ : "=r" (__value), "=r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value;}) #define addmul(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __tmp; \ __asm__ ( "umul %3,%4,%0; \ rd %%y,%2; \ addcc %0,%1,%0; \ addx %%g0,%2,%1" \ : "=&r" (__value), "=&r" (hiremainder), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "1" (hiremainder) \ : "cc"); \ __value;}) #endif pari-2.7.5/src/kernel/hppa64/0000755000175000017500000000000012613365633014267 5ustar billbillpari-2.7.5/src/kernel/hppa64/asm0.h0000644000175000017500000001000212366172547015276 0ustar billbill#line 2 "../src/kernel/hppa64/asm0.h" /* Copyright (C) 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. */ /* This file was made using idea from Bruno Haible ix86 asm inline kernel * and code from Nigel Smart hppa asm kernel. mulll was inspired from * longlong.h from the GNU MP package.*/ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("add %2,%3,%0\n\tadd,dc %%r0,%%r0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %4,%5,%%r0\n\tadd,dc %2,%3,%0\n\tadd,dc %%r0,%%r0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong) 1)\ : "cc"); \ __value; \ }) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %2,%3,%0\n\tadd,dc %%r0,%%r0,%1\n\tsubi 1,%1,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %%r0,%4,%%r0\n\tsub,db %2,%3,%0\n\tadd,dc %%r0,%%r0,%1\n\tsubi 1,%1,%1" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow)\ : "cc"); \ __value; \ }) /* z=a+b; c+= carry; return z */ #define __addllc(a,b,c) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("add %2,%3,%0\n\tadd,dc %4,%%r0,%1" \ : "=&r" (__value), "=r" (c) \ : "r" (__arg1), "r" (__arg2), "r" (c) \ : "cc"); \ __value; \ }) /* 32x32->64 multiply*/ #define __mulhh(a,b) \ __extension__ ({ unsigned int __arg1 = (a), __arg2 = (b); \ ulong __value; \ __asm__ ("xmpyu %1,%2,%0" \ : "=f" (__value) \ : "f" (__arg1), "f" (__arg2) \ : "cc"); \ __value; \ }) #define mulll(arg1,arg2) \ __extension__ ({ \ const ulong __x=(arg1), __y=(arg2); \ const ulong __xlo = LOWWORD(__x), __xhi = HIGHWORD(__x); \ const ulong __ylo = LOWWORD(__y), __yhi = HIGHWORD(__y); \ ulong __xylo,__xymid,__xyhi,__xymidhi,__xymidlo; \ ulong __xylh,__xyhl; \ __xylo = __mulhh(__xlo,__ylo); __xyhi = __mulhh(__xhi,__yhi); \ __xylh = __mulhh(__xlo,__yhi); __xyhl = __mulhh(__xhi,__ylo); \ __xymid = __xylh+__xyhl; \ if (__xymid<__xylh) __xyhi += (1UL << BITS_IN_HALFULONG); \ __xymidhi = HIGHWORD(__xymid); \ __xymidlo = __xymid << BITS_IN_HALFULONG; \ __xylo = __addllc(__xylo,__xymidlo,__xyhi); \ hiremainder = __xyhi + __xymidhi; \ __xylo; \ }) #define addmul(arg1,arg2) \ __extension__ ({ \ const ulong __x=(arg1), __y=(arg2); \ const ulong __xlo = LOWWORD(__x), __xhi = HIGHWORD(__x); \ const ulong __ylo = LOWWORD(__y), __yhi = HIGHWORD(__y); \ ulong __xylo,__xymid,__xyhi,__xymidhi,__xymidlo; \ ulong __xylh,__xyhl; \ __xylo = __mulhh(__xlo,__ylo); __xyhi = __mulhh(__xhi,__yhi); \ __xylh = __mulhh(__xlo,__yhi); __xyhl = __mulhh(__xhi,__ylo); \ __xymid = __xylh+__xyhl; \ if (__xymid<__xylh) __xyhi += (1UL << BITS_IN_HALFULONG); \ __xylo = __addllc(__xylo,hiremainder,__xyhi); \ __xymidhi = HIGHWORD(__xymid); \ __xymidlo = __xymid << BITS_IN_HALFULONG; \ __xylo = __addllc(__xylo,__xymidlo,__xyhi); \ hiremainder = __xyhi + __xymidhi; \ __xylo; \ }) #endif pari-2.7.5/src/kernel/mips/0000755000175000017500000000000012613365633014135 5ustar billbillpari-2.7.5/src/kernel/mips/asm0.h0000644000175000017500000000353612366172547015162 0ustar billbill#line 2 "../src/kernel/mips/asm0.h" /* Copyright (C) 2013 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. */ /* ASM mulll NOASM addll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("multu %2,%3\n\tmfhi %1" \ : "=&l" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : "hi"); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("multu %3,%4\n\tmfhi %0\n\tmflo %2\n\t" \ "addu %1,%2,%5\n\tsltu %2,%1,%5\n\taddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : "hi", "lo"); \ __value; \ }) #endif pari-2.7.5/src/kernel/x86_64/0000755000175000017500000000000012613365633014123 5ustar billbillpari-2.7.5/src/kernel/x86_64/asm0.h0000644000175000017500000001154512366172547015147 0ustar billbill#line 2 "../src/kernel/x86-64/asm0.h" /* Copyright (C) 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. */ /* ASM addll mulll bfffo divll */ /* Written by Bill Allombert from the ix86 version by Bruno Haible. Basically * change insl to insq*/ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addq %3,%0 ; adcq %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subq %5,%2 ; adcq %4,%0 ; adcq %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subq %5, %0 \n\t" \ "movq (%2), %0 ; adcq (%3),%0; movq %0, (%4) \n\t" \ "movq -8(%2), %0 ; adcq -8(%3),%0; movq %0, -8(%4) \n\t" \ "movq -16(%2), %0 ; adcq -16(%3),%0; movq %0, -16(%4) \n\t" \ "movq -24(%2), %0 ; adcq -24(%3),%0; movq %0, -24(%4) \n\t" \ "movq -32(%2), %0 ; adcq -32(%3),%0; movq %0, -32(%4) \n\t" \ "movq -40(%2), %0 ; adcq -40(%3),%0; movq %0, -40(%4) \n\t" \ "movq -48(%2), %0 ; adcq -48(%3),%0; movq %0, -48(%4) \n\t" \ "movq -56(%2), %0 ; adcq -56(%3),%0; movq %0, -56(%4) \n\t" \ "adcq %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subq %3,%0 ; adcq %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subq %5,%2 ; sbbq %4,%0 ; adcq %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subq %5, %0 \n\t" \ "movq (%2), %0 ; sbbq (%3),%0; movq %0, (%4) \n\t" \ "movq -8(%2), %0 ; sbbq -8(%3),%0; movq %0, -8(%4) \n\t" \ "movq -16(%2), %0 ; sbbq -16(%3),%0; movq %0, -16(%4) \n\t" \ "movq -24(%2), %0 ; sbbq -24(%3),%0; movq %0, -24(%4) \n\t" \ "movq -32(%2), %0 ; sbbq -32(%3),%0; movq %0, -32(%4) \n\t" \ "movq -40(%2), %0 ; sbbq -40(%3),%0; movq %0, -40(%4) \n\t" \ "movq -48(%2), %0 ; sbbq -48(%3),%0; movq %0, -48(%4) \n\t" \ "movq -56(%2), %0 ; sbbq -56(%3),%0; movq %0, -56(%4) \n\t" \ "adcq %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define mulll(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b); \ __asm__ ("mulq %3" \ : "=a" /* %eax */ (__valuelo), "=d" /* %edx */ (hiremainder) \ : "0" (__arg1), "rm" (__arg2)); \ __valuelo; \ }) #define addmul(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mulq %4 ; addq %5,%0 ; adcq %6,%1" \ : "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (hiremainder), "=r" (__temp) \ : "0" (__arg1), "rm" (__arg2), "g" (hiremainder), "2" ((ulong)0)); \ __valuelo; \ }) #define divll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("divq %4" \ : "=a" /* %eax */ (__value), "=d" /* %edx */ (hiremainder) \ : "0" /* %eax */ (__arg1), "1" /* %edx */ (hiremainder), "mr" (__arg2)); \ __value; \ }) #define bfffo(x) \ __extension__ ({ ulong __arg = (x); \ long leading_one_position; \ __asm__ ("bsrq %1,%0" : "=r" (leading_one_position) : "rm" (__arg)); \ 63 - leading_one_position; \ }) #endif pari-2.7.5/src/kernel/alpha/0000755000175000017500000000000012613365633014252 5ustar billbillpari-2.7.5/src/kernel/alpha/asm1.h0000644000175000017500000000706012405547147015270 0ustar billbill/* 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. */ /* 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 Copyright (C) 2000 Free Software Foundation, Inc. * FIXME: This file is unused until somebody implements * invert_word(x) = return floor( 2^(2*BIL)/x ) */ extern ulong invert_word(ulong); #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ ulong __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - (__x > (al)); \ (sl) = __x; \ } while (0) #ifdef __GNUC__ #define divll(x, y) \ __extension__ ({ \ register ulong _di, _x = (x), _y = (y), _q, _ql, _r; \ register ulong _xh, _xl, _k, __hire; \ \ if (_y & 0x8000000000000000UL) \ { _k = 0; __hire = hiremainder; } \ else \ { \ _k = bfffo(_y); \ __hire = (hiremainder << _k) | (_x >> (64 - _k)); \ _x <<= _k; _y <<= _k; \ } \ _di = invert_word(_y); \ _ql = mulll (__hire, _di); \ _q = __hire + hiremainder; \ _xl = mulll(_q, _y); _xh = hiremainder; \ sub_ddmmss (_xh, _r, __hire, _x, _xh, _xl); \ if (_xh != 0) \ { \ sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; \ if (_xh != 0) \ { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; } \ } \ if (_r >= _y) \ { _r -= _y; _q += 1; } \ hiremainder = _r >> _k; \ _q; \ }) #else /* __GNUC__ */ static ulong divll(ulong x, ulong y) { register ulong _di, _x = (x), _y = (y), _q, _ql, _r; register ulong _xh, _xl, _k, __hire; if (_y & 0x8000000000000000UL) { _k = 0; __hire = hiremainder; } else { _k = bfffo(_y); __hire = (hiremainder << _k) | (_x >> (64 - _k)); _x <<= _k; _y <<= _k; } _di = invert_word(_y); _ql = mulll (__hire, _di); _q = __hire + hiremainder; _xl = mulll(_q, _y); _xh = hiremainder; sub_ddmmss (_xh, _r, __hire, _x, _xh, _xl); if (_xh != 0) { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; if (_xh != 0) { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; } } if (_r >= _y) { _r -= _y; _q += 1; } hiremainder = _r >> _k; return _q; } #endif /* __GNUC__ */ pari-2.7.5/src/kernel/alpha/asm0.h0000644000175000017500000000477512366172547015305 0ustar billbill/* 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. */ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addq %2,%3,%0\n\tcmpult %4,%2,%1" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0)); \ __value; \ }) #define addllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("addq %3,%4,%0\n\tcmpult %5,%3,%2\n\taddq %5,%6,%0\n\tcmpult %5,%6,%1\n\taddq %6,%7,%1\n\t" \ : "=&r" (__value), "=r" (overflow), "=r" (__temp) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0), "1" (overflow), "2" ((ulong) 0)); \ __value; \ }) #define subll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subq %2,%3,%0\n\tcmpult %2,%4,%1" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong)0)); \ __value; \ }) #define subllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp1, __temp2; \ __asm__ ("subq %4,%5,%2\n\tcmpult %4,%8,%3\n\tsubq %8,%7,%0\n\tcmpult %8,%6,%1\n\taddq %7,%9,%1\n\t" \ : "=r" (__value), "=r" (overflow), "=&r" (__temp1), "=r" (__temp2) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong)0), "1" (overflow), "2" ((ulong)0), "3" ((ulong)0)); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("umulh %2,%3,%1\n\tmulq %2,%3,%0\n\t" \ : "=r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mulq %3,%4,%0\n\tumulh %3,%4,%2\n\taddq %5,%6,%0\n\tcmpult %5,%6,%1\n\taddq %7,%6,%1\n\t" \ : "=&r" (__value), "=r" (hiremainder), "=r" (__temp) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0), "1" (hiremainder), "2" ((ulong) 0)); \ __value; \ }) #endif pari-2.7.5/src/kernel/gmp/0000755000175000017500000000000012613365633013750 5ustar billbillpari-2.7.5/src/kernel/gmp/gcd.c0000644000175000017500000000413112366172547014655 0ustar billbill#line 2 "../src/kernel/gmp/gcd.c" /* Copyright (C) 2000-2003 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. */ /* assume y > x > 0. return y mod x */ static ulong resiu(GEN y, ulong x) { return mpn_mod_1(LIMBS(y), NLIMBS(y), x); } GEN gcdii(GEN a, GEN b) { long v, w; pari_sp av; GEN t; switch (absi_cmp(a,b)) { case 0: return absi(a); case -1: swap(a,b); } if (!signe(b)) return absi(a); /* here |a|>|b|>0. Try single precision first */ if (lgefint(a)==3) return igcduu((ulong)a[2], (ulong)b[2]); if (lgefint(b)==3) { ulong u = resiu(a,(ulong)b[2]); if (!u) return absi(b); return igcduu((ulong)b[2], u); } /* larger than gcd: "avma=av" gerepile (erasing t) is valid */ av = avma; (void)new_chunk(lgefint(b)+1); /* HACK */ t = remii(a,b); if (!signe(t)) { avma=av; return absi(b); } a = b; b = t; v = vali(a); a = shifti(a,-v); setabssign(a); w = vali(b); b = shifti(b,-w); setabssign(b); if (w < v) v = w; switch(absi_cmp(a,b)) { case 0: avma=av; a=shifti(a,v); return a; case -1: swap(a,b); } if (is_pm1(b)) { avma=av; return int2n(v); } { /* general case */ /*This serve two purposes: 1) mpn_gcd destroy its input and need an extra * limb 2) this allows us to use icopy instead of gerepile later. NOTE: we * must put u before d else the final icopy could fail. */ GEN res= cgeti(lgefint(a)+1); GEN ca = icopy_ef(a,lgefint(a)+1); GEN cb = icopy_ef(b,lgefint(b)+1); long l = mpn_gcd(LIMBS(res), LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb)); res[1] = evalsigne(1)|evallgefint(l+2); avma=av; return shifti(res,v); } } pari-2.7.5/src/kernel/gmp/int.h0000644000175000017500000000256512366172547014730 0ustar billbill#line 2 "../src/kernel/gmp/int.h" /* 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. */ #define int_MSW(x) ((x)+lgefint((x))-1) /*x being a t_INT, return a pointer to the most significant word of x.*/ #define int_LSW(x) ((x)+2) /*x being a t_INT, return a pointer to the least significant word of x.*/ #define int_precW(x) ((x)-1) /*x pointing to a mantissa word, return the previous (less significant) * mantissa word.*/ #define int_nextW(x) ((x)+1) /*x pointing to a mantissa word, return the next (more significant) mantissa * word.*/ #define int_W(x,l) ((x)+2+(l)) /*x being a t_INT, return a pointer to the l-th least significant word of x.*/ #define int_W_lg(x,l,lx) ((x)+2+(l)) /*x being a t_INT, return a pointer to the l-th least significant word of x, * assuming lgefint(x) = lx.*/ #define PARI_KERNEL_GMP /*This macro should not be used in libpari itself.*/ pari-2.7.5/src/kernel/gmp/tune.h0000644000175000017500000000634612366172547015112 0ustar billbill#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 __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 __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_MULII2_LIMIT 5 #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 __RgX_MUL_LIMIT 9 #define __RgX_SQR_LIMIT 38 #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 __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 __Flx_MUL_HALFMULII_LIMIT 7 #define __Flx_SQR_HALFSQRI_LIMIT 4 #define __Flx_MUL_MULII_LIMIT 8 #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 __RgX_MUL_LIMIT 7 #define __RgX_SQR_LIMIT 34 #endif pari-2.7.5/src/kernel/gmp/mp.c0000644000175000017500000010341012533333715014524 0ustar billbill#line 2 "../src/kernel/gmp/mp.c" /* Copyright (C) 2002-2003 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. */ /***********************************************************************/ /** **/ /** GMP KERNEL **/ /** BA2002Sep24 **/ /***********************************************************************/ /* GMP t_INT as just like normal t_INT, just the mantissa is the other way * round * * `How would you like to live in Looking-glass House, Kitty? I * wonder if they'd give you milk in there? Perhaps Looking-glass * milk isn't good to drink--But oh, Kitty! now we come to the * passage. You can just see a little PEEP of the passage in * Looking-glass House, if you leave the door of our drawing-room * wide open: and it's very like our passage as far as you can see, * only you know it may be quite different on beyond. Oh, Kitty! * how nice it would be if we could only get through into Looking- * glass House! I'm sure it's got, oh! such beautiful things in it! * * Through the Looking Glass, Lewis Carrol * * (pityful attempt to beat GN code/comments rate) * */ #include #include "pari.h" #include "paripriv.h" #include "../src/kernel/none/tune-gen.h" /*We need PARI invmod renamed to invmod_pari*/ #define INVMOD_PARI static void *pari_gmp_realloc(void *ptr, size_t old_size, size_t new_size) { (void)old_size; return (void *) pari_realloc(ptr,new_size); } static void pari_gmp_free(void *ptr, size_t old_size){ (void)old_size; pari_free(ptr); } static void *(*old_gmp_malloc)(size_t new_size); static void *(*old_gmp_realloc)(void *ptr, size_t old_size, size_t new_size); static void (*old_gmp_free)(void *ptr, size_t old_size); void pari_kernel_init(void) { mp_get_memory_functions (&old_gmp_malloc, &old_gmp_realloc, &old_gmp_free); mp_set_memory_functions((void *(*)(size_t)) pari_malloc, pari_gmp_realloc, pari_gmp_free); } void pari_kernel_close(void) { void *(*new_gmp_malloc)(size_t new_size); void *(*new_gmp_realloc)(void *ptr, size_t old_size, size_t new_size); void (*new_gmp_free)(void *ptr, size_t old_size); mp_get_memory_functions (&new_gmp_malloc, &new_gmp_realloc, &new_gmp_free); if (new_gmp_malloc==pari_malloc) new_gmp_malloc = old_gmp_malloc; if (new_gmp_realloc==pari_gmp_realloc) new_gmp_realloc = old_gmp_realloc; if (new_gmp_free==pari_gmp_free) new_gmp_free = old_gmp_free; mp_set_memory_functions(new_gmp_malloc, new_gmp_realloc, new_gmp_free); } #define LIMBS(x) ((mp_limb_t *)((x)+2)) #define NLIMBS(x) (lgefint(x)-2) /*This one is for t_REALs to emphasize they are not t_INTs*/ #define RLIMBS(x) ((mp_limb_t *)((x)+2)) #define RNLIMBS(x) (lg(x)-2) INLINE void xmpn_copy(mp_limb_t *x, mp_limb_t *y, long n) { while (--n >= 0) x[n]=y[n]; } INLINE void xmpn_mirror(mp_limb_t *x, long n) { long i; for(i=0;i<(n>>1);i++) { ulong m=x[i]; x[i]=x[n-1-i]; x[n-1-i]=m; } } INLINE void xmpn_mirrorcopy(mp_limb_t *z, mp_limb_t *x, long n) { long i; for(i=0;i= 0) x[n]=0; } INLINE GEN icopy_ef(GEN x, long l) { register long lx = lgefint(x); const GEN y = cgeti(l); while (--lx > 0) y[lx]=x[lx]; return y; } /* NOTE: arguments of "spec" routines (muliispec, addiispec, etc.) aren't * GENs but pairs (long *a, long na) representing a list of digits (in basis * BITS_IN_LONG) : a[0], ..., a[na-1]. [ In ordre to facilitate splitting: no * need to reintroduce codewords ] * Use speci(a,na) to visualize the corresponding GEN. */ /***********************************************************************/ /** **/ /** ADDITION / SUBTRACTION **/ /** **/ /***********************************************************************/ GEN setloop(GEN a) { pari_sp av = avma - 2 * sizeof(long); (void)cgetg(lgefint(a) + 3, t_VECSMALL); return icopy_avma(a, av); /* two cells of extra space after a */ } /* we had a = setloop(?), then some incloops. Reset a to b */ GEN resetloop(GEN a, GEN b) { a[0] = evaltyp(t_INT) | evallg(lgefint(b)); affii(b, a); return a; } /* assume a > 0, initialized by setloop. Do a++ */ static GEN incpos(GEN a) { long i, l = lgefint(a); for (i=2; i= y */ INLINE GEN subiuspec(GEN x, ulong s, long nx) { GEN zd; long lz; if (nx == 1) return utoi(x[0] - s); lz = nx + 2; zd = cgeti(lz); mpn_sub_1 (LIMBS(zd), (mp_limb_t *)x, nx, s); if (! zd[lz - 1]) { --lz; } zd[1] = evalsigne(1) | evallgefint(lz); return zd; } /* assume x > y */ INLINE GEN subiispec(GEN x, GEN y, long nx, long ny) { GEN zd; long lz; if (ny==1) return subiuspec(x,*y,nx); lz = nx+2; zd = cgeti(lz); mpn_sub (LIMBS(zd), (mp_limb_t *)x, nx, (mp_limb_t *)y, ny); while (lz >= 3 && zd[lz - 1] == 0) { lz--; } zd[1] = evalsigne(1) | evallgefint(lz); return zd; } static void roundr_up_ip(GEN x, long l) { long i = l; for(;;) { if (++((ulong*)x)[--i]) break; if (i == 2) { x[2] = HIGHBIT; shiftr_inplace(x, 1); break; } } } void affir(GEN x, GEN y) { const long s = signe(x), ly = lg(y); long lx, sh, i; if (!s) { y[1] = evalexpo(-bit_accuracy(ly)); return; } lx = lgefint(x); sh = bfffo(*int_MSW(x)); y[1] = evalsigne(s) | evalexpo(bit_accuracy(lx)-sh-1); if (sh) { if (lx <= ly) { for (i=lx; i>(BITS_IN_LONG-sh); xmpn_mirror(LIMBS(y),ly-2); /* lx > ly: round properly */ if ((x[lx-ly+1]< ly: round properly */ if (x[lx-ly+1] & HIGHBIT) roundr_up_ip(y, ly); } } INLINE GEN shiftispec(GEN x, long nx, long n) { long ny,m; GEN yd, y; if (!n) return icopyspec(x, nx); if (n > 0) { long d = dvmdsBIL(n, &m); long i; ny = nx + d + (m!=0); y = cgeti(ny + 2); yd = y + 2; for (i=0; i 0) { GEN z = (GEN)avma; long d = dvmdsBIL(n, &m); ly = lx+d; y = new_chunk(ly); for ( ; d; d--) *--z = 0; if (!m) for (i=2; i> sh; /* Extend y on the left? */ if (i) { ly++; y = new_chunk(1); y[2] = i; } } } else { ly = lx - dvmdsBIL(-n, &m); if (ly<3) return gen_0; y = new_chunk(ly); if (m) { shift_right(y,x, 2,ly, 0,m); if (y[2] == 0) { if (ly==3) { avma = (pari_sp)(y+3); return gen_0; } ly--; avma = (pari_sp)(++y); } } else { for (i=2; i lg(x)) pari_err_PREC( "truncr (precision loss in truncation)"); y=cgeti(d); y[1] = evalsigne(s) | evallgefint(d); if (++m == BITS_IN_LONG) for (i=2; i= 0) return truncr(x); if ((e=expo(x)) < 0) return gen_m1; d = nbits2prec(e+1); m = remsBIL(e); lx=lg(x); if (d>lx) pari_err_PREC( "floorr (precision loss in truncation)"); y = cgeti(d+1); if (++m == BITS_IN_LONG) { for (i=2; i ly) return 1; return mpn_cmp((mp_limb_t*)x,(mp_limb_t*)y, lx); } INLINE int equaliispec(GEN x, GEN y, long lx, long ly) { if (lx != ly) return 0; return !mpn_cmp((mp_limb_t*)x,(mp_limb_t*)y, lx); } /***********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /***********************************************************************/ /* assume ny > 0 */ INLINE GEN muluispec(ulong x, GEN y, long ny) { if (ny == 1) return muluu(x, *y); else { long lz = ny+3; GEN z = cgeti(lz); ulong hi = mpn_mul_1 (LIMBS(z), (mp_limb_t *)y, ny, x); if (hi) { z[lz - 1] = hi; } else lz--; z[1] = evalsigne(1) | evallgefint(lz); return z; } } /* a + b*|y| */ GEN addumului(ulong a, ulong b, GEN y) { GEN z; long i, lz; ulong hi; if (!signe(y)) return utoi(a); lz = lgefint(y)+1; z = cgeti(lz); z[2]=a; for(i=3;i 0)? hi: x - hi; } /* return |y| \/ x */ GEN diviu_rem(GEN y, ulong x, ulong *rem) { long ly; GEN z; if (!x) pari_err_INV("diviu_rem",gen_0); 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; } z = cgeti(ly); *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x); if (z [ly - 1] == 0) ly--; z[1] = evallgefint(ly) | evalsigne(1); return z; } GEN divis_rem(GEN y, long x, long *rem) { long sy=signe(y),ly,s; GEN z; if (!x) pari_err_INV("divis_rem",gen_0); if (!sy) { *rem = 0; return gen_0; } 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; } z = cgeti(ly); *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x); if (sy<0) *rem = - *rem; if (z[ly - 1] == 0) ly--; z[1] = evallgefint(ly) | evalsigne(s); return z; } GEN divis(GEN y, long x) { long sy=signe(y),ly,s; GEN z; if (!x) pari_err_INV("divis",gen_0); if (!sy) return gen_0; if (x<0) { s = -sy; x = -x; } else s=sy; ly = lgefint(y); if (ly == 3 && (ulong)x > (ulong)y[2]) return gen_0; z = cgeti(ly); (void)mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x); if (z[ly - 1] == 0) ly--; z[1] = evallgefint(ly) | evalsigne(s); return z; } /* We keep llx bits of x and lly bits of y*/ static GEN divrr_with_gmp(GEN x, GEN y) { long lx=RNLIMBS(x),ly=RNLIMBS(y); long lw=minss(lx,ly); long lly=minss(lw+1,ly); GEN w=cgetr(lw+2); long lu=lw+lly; long llx=minss(lu,lx); mp_limb_t *u=(mp_limb_t *)new_chunk(lu); mp_limb_t *z=(mp_limb_t *)new_chunk(lly); mp_limb_t *q,*r; long e=expo(x)-expo(y); long sx=signe(x),sy=signe(y); xmpn_mirrorcopy(z,RLIMBS(y),lly); xmpn_mirrorcopy(u+lu-llx,RLIMBS(x),llx); xmpn_zero(u,lu-llx); q = (mp_limb_t *)new_chunk(lw+1); r = (mp_limb_t *)new_chunk(lly); 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)) mpn_add_1(q,q,lw+1,1); xmpn_mirrorcopy(RLIMBS(w),q,lw); if (q[lw] == 0) e--; else if (q[lw] == 1) { shift_right(w,w, 2,lw+2, 1,1); } else { w[2] = HIGHBIT; e++; } if (sy < 0) sx = -sx; w[1] = evalsigne(sx) | evalexpo(e); avma=(pari_sp) w; return w; } /* We keep llx bits of x and lly bits of y*/ static GEN divri_with_gmp(GEN x, GEN y) { long llx=RNLIMBS(x),ly=NLIMBS(y); long lly=minss(llx+1,ly); GEN w=cgetr(llx+2); long lu=llx+lly, ld=ly-lly; mp_limb_t *u=(mp_limb_t *)new_chunk(lu); mp_limb_t *z=(mp_limb_t *)new_chunk(lly); mp_limb_t *q,*r; long sh=bfffo(y[ly+1]); long e=expo(x)-expi(y); long sx=signe(x),sy=signe(y); if (sh) mpn_lshift(z,LIMBS(y)+ld,lly,sh); else xmpn_copy(z,LIMBS(y)+ld,lly); xmpn_mirrorcopy(u+lu-llx,RLIMBS(x),llx); xmpn_zero(u,lu-llx); q = (mp_limb_t *)new_chunk(llx+1); r = (mp_limb_t *)new_chunk(lly); 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)) mpn_add_1(q,q,llx+1,1); xmpn_mirrorcopy(RLIMBS(w),q,llx); if (q[llx] == 0) e--; else if (q[llx] == 1) { shift_right(w,w, 2,llx+2, 1,1); } else { w[2] = HIGHBIT; e++; } if (sy < 0) sx = -sx; w[1] = evalsigne(sx) | evalexpo(e); avma=(pari_sp) w; return w; } GEN divri(GEN x, GEN y) { long s = signe(y); if (!s) pari_err_INV("divri",gen_0); if (!signe(x)) return real_0_bit(expo(x) - expi(y)); if (!is_bigint(y)) { GEN z = divru(x, y[2]); if (s < 0) togglesign(z); return z; } return divri_with_gmp(x,y); } GEN divrr(GEN x, GEN y) { long sx=signe(x), sy=signe(y), lx,ly,lr,e,i,j; ulong y0,y1; GEN r, r1; if (!sy) pari_err_INV("divrr",y); e = expo(x) - expo(y); if (!sx) return real_0_bit(e); if (sy<0) sx = -sx; lx=lg(x); ly=lg(y); if (ly==3) { ulong k = x[2], l = (lx>3)? x[3]: 0; LOCAL_HIREMAINDER; if (k < (ulong)y[2]) e--; else { l >>= 1; if (k&1) l |= HIGHBIT; k >>= 1; } hiremainder = k; k = divll(l,y[2]); if (hiremainder & HIGHBIT) { k++; if (!k) { k = HIGHBIT; e++; } } r = cgetr(3); r[1] = evalsigne(sx) | evalexpo(e); r[2] = k; return r; } if (ly>=DIVRR_GMP_LIMIT) return divrr_with_gmp(x,y); lr = minss(lx,ly); r = new_chunk(lr); r1 = r-1; r1[1] = 0; for (i=2; ily)? x[lr]: 0; y0 = y[2]; y1 = y[3]; for (i=0; i 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]); } hiremainder = r1[1]; overflow = 0; qp = divll(r1[2],y0); k = hiremainder; } j = lr-i+1; if (!overflow) { long k3, k4; k3 = mulll(qp,y1); if (j == 3) /* i = lr - 2 maximal, r1[3] undefined -> 0 */ k4 = subll(hiremainder,k); else { k3 = subll(k3, r1[3]); k4 = subllx(hiremainder,k); } while (!overflow && k4) { qp--; k3=subll(k3,y1); k4=subllx(k4,y0); } } if (j1; j--) { r1[j] = subll(r1[j], addmul(qp,y[j])); hiremainder += overflow; } if ((ulong)r1[1] != hiremainder) { if ((ulong)r1[1] < hiremainder) { qp--; j = lr-i-(lr-i>=ly); r1[j] = addll(r1[j], y[j]); for (j--; j>1; j--) r1[j] = addllx(r1[j], y[j]); } else { r1[1] -= hiremainder; while (r1[1]) { qp++; if (!qp) { j=i; do ((ulong*)r)[--j]++; while (j && !r[j]); } j = lr-i-(lr-i>=ly); r1[j] = subll(r1[j],y[j]); for (j--; j>1; j--) r1[j] = subllx(r1[j],y[j]); r1[1] -= overflow; } } } *++r1 = qp; } /* i = lr-1 */ /* round correctly */ if ((ulong)r1[1] > (y0>>1)) { j=i; do r[--j]++; while (j && !r[j]); } r1 = r-1; for (j=i; j>=2; j--) r[j]=r1[j]; if (r[0] == 0) e--; else if (r[0] == 1) { shift_right(r,r, 2,lr, 1,1); } else { /* possible only when rounding up to 0x2 0x0 ... */ r[2] = (long)HIGHBIT; e++; } r[0] = evaltyp(t_REAL)|evallg(lr); r[1] = evalsigne(sx) | evalexpo(e); return r; } /* Integer division x / y: such that sign(r) = sign(x) * if z = ONLY_REM return remainder, otherwise return quotient * if z != NULL set *z to remainder * *z is the last object on stack (and thus can be disposed of with cgiv * instead of gerepile) * If *z is zero, we put gen_0 here and no copy. * space needed: lx + ly */ GEN dvmdii(GEN x, GEN y, GEN *z) { long sx=signe(x),sy=signe(y); long lx, ly, lq; pari_sp av; GEN r,q; if (!sy) { if (z == ONLY_REM && !sx) return gen_0; pari_err_INV("dvmdii",y); } if (!sx) { if (!z || z == ONLY_REM) return gen_0; *z=gen_0; return gen_0; } lx=lgefint(x); ly=lgefint(y); lq=lx-ly; if (lq <= 0) { if (lq == 0) { long s=mpn_cmp(LIMBS(x),LIMBS(y),NLIMBS(x)); if (s>0) goto DIVIDE; if (s==0) { if (z == ONLY_REM) return gen_0; if (z) *z = gen_0; if (sx < 0) sy = -sy; return stoi(sy); } } if (z == ONLY_REM) return icopy(x); if (z) *z = icopy(x); return gen_0; } DIVIDE: /* quotient is non-zero */ av=avma; if (sx<0) sy = -sy; if (ly==3) { ulong lq = lx; ulong si; q = cgeti(lq); si = mpn_divrem_1(LIMBS(q), 0, LIMBS(x), NLIMBS(x), y[2]); if (q[lq - 1] == 0) lq--; if (z == ONLY_REM) { avma=av; if (!si) return gen_0; r=cgeti(3); r[1] = evalsigne(sx) | evallgefint(3); r[2] = si; return r; } q[1] = evalsigne(sy) | evallgefint(lq); if (!z) return q; if (!si) { *z=gen_0; return q; } r=cgeti(3); r[1] = evalsigne(sx) | evallgefint(3); r[2] = si; *z=r; return q; } if (z == ONLY_REM) { ulong lr = lgefint(y); ulong lq = lgefint(x)-lgefint(y)+3; GEN r = cgeti(lr); GEN q = cgeti(lq); mpn_tdiv_qr(LIMBS(q), LIMBS(r),0, LIMBS(x), NLIMBS(x), LIMBS(y), NLIMBS(y)); if (!r[lr - 1]) { while(lr>2 && !r[lr - 1]) lr--; if (lr == 2) {avma=av; return gen_0;} /* exact division */ } r[1] = evalsigne(sx) | evallgefint(lr); avma = (pari_sp) r; return r; } else { ulong lq = lgefint(x)-lgefint(y)+3; ulong lr = lgefint(y); GEN q = cgeti(lq); GEN r = cgeti(lr); mpn_tdiv_qr(LIMBS(q), LIMBS(r),0, LIMBS(x), NLIMBS(x), LIMBS(y), NLIMBS(y)); if (q[lq - 1] == 0) lq--; q[1] = evalsigne(sy) | evallgefint(lq); if (!z) { avma = (pari_sp)q; return q; } if (!r[lr - 1]) { while(lr>2 && !r[lr - 1]) lr--; if (lr == 2) {avma=(pari_sp) q; *z=gen_0; return q;} /* exact division */ } r[1] = evalsigne(sx) | evallgefint(lr); avma = (pari_sp) r; *z = r; return q; } } /* Montgomery reduction. * N has k words, assume T >= 0 has less than 2k. * Return res := T / B^k mod N, where B = 2^BIL * such that 0 <= res < T/B^k + N and res has less than k words */ GEN red_montgomery(GEN T, GEN N, ulong inv) { pari_sp av; GEN Te, Td, Ne, Nd, scratch; ulong i, j, m, t, d, k = NLIMBS(N); int carry; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (k == 0) return gen_0; d = NLIMBS(T); /* <= 2*k */ if (d == 0) return gen_0; #ifdef DEBUG if (d > 2*k) pari_err_BUG("red_montgomery"); #endif if (k == 1) { /* as below, special cased for efficiency */ ulong n = (ulong)N[2]; if (d == 1) { hiremainder = (ulong)T[2]; m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ return utoi(hiremainder); } else { /* d = 2 */ hiremainder = (ulong)T[2]; m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ t = addll(hiremainder, (ulong)T[3]); if (overflow) t -= n; /* t > n doesn't fit in 1 word */ return utoi(t); } } /* assume k >= 2 */ av = avma; scratch = new_chunk(k<<1); /* >= k + 2: result fits */ /* copy T to scratch space (pad with zeroes to 2k words) */ Td = scratch; Te = T + 2; for (i=0; i < d ; i++) *Td++ = *Te++; for ( ; i < (k<<1); i++) *Td++ = 0; Te = scratch - 1; /* 1 beyond end of current T mantissa (in scratch) */ Ne = N + 1; /* 1 beyond end of N mantissa */ carry = 0; for (i=0; i N overflows (k+1 words), set Td := Td - N */ Td = Te; Nd = Ne; t = subll(*++Td, *++Nd); *Td = t; while (Td < (GEN)av) { t = subllx(*++Td, *++Nd); *Td = t; } } /* copy result */ Td = (GEN)av - 1; /* *Td = high word of final result */ while (*Td == 0 && Te < Td) Td--; /* strip leading 0s */ k = Td - Te; if (!k) { avma = av; return gen_0; } Td = (GEN)av - k; /* will write mantissa there */ (void)memmove(Td, Te+1, k*sizeof(long)); Td -= 2; Td[0] = evaltyp(t_INT) | evallg(k+2); Td[1] = evalsigne(1) | evallgefint(k+2); #ifdef DEBUG { long l = NLIMBS(N), s = BITS_IN_LONG*l; GEN R = int2n(s); GEN res = remii(mulii(T, Fp_inv(R, N)), N); if (k > lgefint(N) || !equalii(remii(Td,N),res) || cmpii(Td, addii(shifti(T, -s), N)) >= 0) pari_err_BUG("red_montgomery"); } #endif avma = (pari_sp)Td; return Td; } /* EXACT INTEGER DIVISION */ #if 1 && !defined(_WIN64) /* use undocumented GMP interface */ /* mpz_divexact_ui is not LLP64 friendly */ static void GEN2mpz(mpz_t X, GEN x) { long l = lgefint(x)-2; X->_mp_alloc = l; X->_mp_size = signe(x) > 0? l: -l; X->_mp_d = LIMBS(x); } static void mpz2GEN(GEN z, mpz_t Z) { long l = Z->_mp_size; z[1] = evalsigne(l > 0? 1: -1) | evallgefint(labs(l)+2); } /* assume y != 0 and the division is exact */ GEN diviuexact(GEN x, ulong y) { if (!signe(x)) return gen_0; { long l = lgefint(x); mpz_t X, Z; GEN z = cgeti(l); GEN2mpz(X, x); Z->_mp_alloc = l-2; Z->_mp_size = l-2; Z->_mp_d = LIMBS(z); mpz_divexact_ui(Z, X, y); mpz2GEN(z, Z); return z; } } /* Find z such that x=y*z, knowing that y | x (unchecked) */ GEN diviiexact(GEN x, GEN y) { if (!signe(y)) pari_err_INV("diviiexact",y); if (lgefint(y) == 3) { GEN z = diviuexact(x, y[2]); if (signe(y) < 0) togglesign(z); return z; } if (!signe(x)) return gen_0; { long l = lgefint(x); mpz_t X, Y, Z; GEN z = cgeti(l); GEN2mpz(X, x); GEN2mpz(Y, y); Z->_mp_alloc = l-2; Z->_mp_size = l-2; Z->_mp_d = LIMBS(z); mpz_divexact(Z, X, Y); mpz2GEN(z, Z); return z; } } #else /* assume y != 0 and the division is exact */ GEN diviuexact(GEN x, ulong y) { /*TODO: implement true exact division.*/ return divii(x,utoi(y)); } /* Find z such that x=y*z, knowing that y | x (unchecked) * Method: y0 z0 = x0 mod B = 2^BITS_IN_LONG ==> z0 = 1/y0 mod B. * Set x := (x - z0 y) / B, updating only relevant words, and repeat */ GEN diviiexact(GEN x, GEN y) { /*TODO: use mpn_bdivmod instead*/ return divii(x,y); } #endif /* assume yz != and yz | x */ GEN diviuuexact(GEN x, ulong y, ulong z) { long tmp[4]; ulong t; LOCAL_HIREMAINDER; t = mulll(y, z); if (!hiremainder) return diviuexact(x, t); tmp[0] = evaltyp(t_INT)|_evallg(4); tmp[1] = evalsigne(1)|evallgefint(4); tmp[2] = t; tmp[3] = hiremainder; return diviiexact(x, tmp); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION **/ /** **/ /********************************************************************/ /* nx >= ny = num. of digits of x, y (not GEN, see mulii) */ GEN muliispec(GEN x, GEN y, long nx, long ny) { GEN zd; long lz; ulong hi; if (nx < ny) swapspec(x,y, nx,ny); if (!ny) return gen_0; if (ny == 1) return muluispec((ulong)*y, x, nx); lz = nx+ny+2; zd = cgeti(lz); hi = mpn_mul(LIMBS(zd), (mp_limb_t *)x, nx, (mp_limb_t *)y, ny); if (!hi) lz--; /*else zd[lz-1]=hi; GH tell me it is not necessary.*/ zd[1] = evalsigne(1) | evallgefint(lz); return zd; } GEN muluui(ulong x, ulong y, GEN z) { long t, s = signe(z); GEN r; LOCAL_HIREMAINDER; if (!x || !y || !signe(z)) return gen_0; t = mulll(x,y); if (!hiremainder) r = muluispec(t, z+2, lgefint(z)-2); else { long tmp[2]; tmp[1] = hiremainder; tmp[0] = t; r = muliispec(z+2,tmp, lgefint(z)-2, 2); } setsigne(r,s); return r; } GEN sqrispec(GEN x, long nx) { GEN zd; long lz; if (!nx) return gen_0; if (nx==1) return sqru(*x); lz = (nx<<1)+2; zd = cgeti(lz); #ifdef mpn_sqr mpn_sqr(LIMBS(zd), (mp_limb_t *)x, nx); #else mpn_mul_n(LIMBS(zd), (mp_limb_t *)x, (mp_limb_t *)x, nx); #endif if (zd[lz-1]==0) lz--; zd[1] = evalsigne(1) | evallgefint(lz); return zd; } INLINE GEN sqrispec_mirror(GEN x, long nx) { GEN cx=new_chunk(nx); GEN z; xmpn_mirrorcopy((mp_limb_t *)cx,(mp_limb_t *)x,nx); z=sqrispec(cx, nx); xmpn_mirror(LIMBS(z), NLIMBS(z)); return z; } /* leaves garbage on the stack. */ INLINE GEN muliispec_mirror(GEN x, GEN y, long nx, long ny) { GEN cx, cy, z; long s = 0; while (nx && x[nx-1]==0) { nx--; s++; } while (ny && y[ny-1]==0) { ny--; s++; } cx=new_chunk(nx); cy=new_chunk(ny); xmpn_mirrorcopy((mp_limb_t *)cx,(mp_limb_t *)x,nx); xmpn_mirrorcopy((mp_limb_t *)cy,(mp_limb_t *)y,ny); z = nx>=ny ? muliispec(cx, cy, nx, ny): muliispec(cy, cx, ny, nx); if (s) { long i, lz = lgefint(z) + s; (void)new_chunk(s); z -= s; for (i=0; i= 0 */ GEN remi2n(GEN x, long n) { ulong hi; long l, k, lx, ly, sx = signe(x); GEN z, xd, zd; if (!sx || !n) return gen_0; k = dvmdsBIL(n, &l); lx = lgefint(x); if (lx < k+3) return icopy(x); xd = x + (2 + k); /* x = |k|...|1|#|... : copy the last l bits of # and the first k words * ^--- initial xd */ hi = ((ulong)*xd) & ((1UL<> 1; /* 2 + ceil(na/2) */ S = cgetipos(l); if (r) { GEN R = cgeti(2 + na); nr = mpn_sqrtrem(LIMBS(S), LIMBS(R), LIMBS(a), na); if (nr) R[1] = evalsigne(1) | evallgefint(nr+2); else { avma = (pari_sp)S; R = gen_0; } *r = R; } else (void)mpn_sqrtrem(LIMBS(S), NULL, LIMBS(a), na); return S; } /* compute sqrt(|a|), assuming a != 0 */ GEN sqrtr_abs(GEN a) { GEN res; mp_limb_t *b, *c; long l = RNLIMBS(a), e = expo(a), er = e>>1; long n; res = cgetr(2 + l); res[1] = evalsigne(1) | evalexpo(er); if (e&1) { b = (mp_limb_t *) new_chunk(l<<1); xmpn_zero(b,l); xmpn_mirrorcopy(b+l, RLIMBS(a), l); c = (mp_limb_t *) new_chunk(l); n = mpn_sqrtrem(c,b,b,l<<1); /* c <- sqrt; b <- rem */ if (n>l || (n==l && mpn_cmp(b,c,l) > 0)) mpn_add_1(c,c,l,1); } else { ulong u; b = (mp_limb_t *) mantissa2nr(a,-1); b[1] = ((ulong)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); n = mpn_sqrtrem(c,b,b,(l<<1)+2); /* c <- sqrt; b <- rem */ u = (ulong)*c++; if ( u&HIGHBIT || (u == ~HIGHBIT && (n>l || (n==l && mpn_cmp(b,c,l)>0)))) mpn_add_1(c,c,l,1); } xmpn_mirrorcopy(RLIMBS(res),c,l); avma = (pari_sp)res; return res; } /* Normalize a non-negative integer */ GEN int_normalize(GEN x, long known_zero_words) { long i = lgefint(x) - 1 - known_zero_words; for ( ; i > 1; i--) if (x[i]) { setlgefint(x, i+1); return x; } x[1] = evalsigne(0) | evallgefint(2); return x; } /******************************************************************** ** ** ** Base Conversion ** ** ** ********************************************************************/ ulong * convi(GEN x, long *l) { long n = nchar2nlong(2 + (long)(NLIMBS(x) * (BITS_IN_LONG * LOG10_2))); GEN str = cgetg(n+1, t_VECSMALL); unsigned char *res = (unsigned char*) GSTR(str); long llz = mpn_get_str(res, 10, LIMBS(icopy(x)), NLIMBS(x)); long lz; ulong *z; long i, j; unsigned char *t; while (!*res) {res++; llz--;} /*Strip leading zeros*/ lz = (8+llz)/9; z = (ulong*)new_chunk(1+lz); t=res+llz+9; for(i=0;i=S2 */ pari_sp av = avma; GEN ca, cb, u, d; long l, su, sa = signe(a), lb,lna; mp_size_t lu; GEN na; if (!sa) { avma = av; *res = absi(b); return 0; } if (signe(b) < 0) b = negi(b); if (absi_cmp(a, b) < 0) na = sa > 0? addii(a, b): subii(a, b); else na = a; /* Copy serves two purposes: * 1) mpn_gcdext destroys its input and needs an extra limb * 2) allows us to use icopy instead of gerepile later. */ lb = lgefint(b); lna = lgefint(na); ca = icopy_ef(na,lna+1); cb = icopy_ef( b,lb+1); /* must create u first else final icopy could fail. */ u = cgeti(lna+1); d = cgeti(lna+1); /* na >= b */ l = mpn_gcdext(LIMBS(d), LIMBS(u), &lu, LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb)); d[1] = evalsigne(1)|evallgefint(l+2); if (!is_pm1(d)) {avma=av; *res=icopy(d); return 0;} su = lu?((sa ^ lu) < 0)? -1: 1: 0; u[1] = evalsigne(su) | evallgefint(labs(lu)+2); if (su < 0) u = addii(u, b); avma=av; *res=icopy(u); return 1; } } /*================================== * bezout(a,b,pu,pv) *================================== * Return g = gcd(a,b) >= 0, and assign GENs u,v through pointers pu,pv * such that g = u*a + v*b. * Special cases: * a == b == 0 ==> pick u=1, v=0 * a != 0 == b ==> keep v=0 * a == 0 != b ==> keep u=0 * |a| == |b| != 0 ==> keep u=0, set v=+-1 * Assignments through pu,pv will be suppressed when the corresponding * pointer is NULL (but the computations will happen nonetheless). */ GEN bezout(GEN a, GEN b, GEN *pu, GEN *pv) { long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ s = absi_cmp(a,b); if (s < 0) { swap(a,b); pswap(pu,pv); } /* now |a| >= |b| */ sa = signe(a); sb = signe(b); if (!sb) { if (pv) *pv = gen_0; switch(sa) { case 0: if (pu) *pu = gen_0; return gen_0; case 1: if (pu) *pu = gen_1; return icopy(a); case -1: if (pu) *pu = gen_m1; return negi(a); } } if (s == 0) /* |a| == |b| != 0 */ { if (pu) *pu = gen_0; if (sb > 0) { if (pv) *pv = gen_1; return icopy(b); } else { if (pv) *pv = gen_m1; return negi(b); } } /* now |a| > |b| > 0 */ if (lgefint(a) == 3) /* single-word affair */ { g = xxgcduu((ulong)a[2], (ulong)b[2], 0, &xu, &xu1, &xv, &xv1, &s); sa = s > 0 ? sa : -sa; sb = s > 0 ? -sb : sb; if (pu) { if (xu == 0) *pu = gen_0; /* can happen when b divides a */ else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1; else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2; else { *pu = cgeti(3); (*pu)[1] = evalsigne(sa)|evallgefint(3); (*pu)[2] = xu; } } if (pv) { if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1; else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2; else { *pv = cgeti(3); (*pv)[1] = evalsigne(sb)|evallgefint(3); (*pv)[2] = xv; } } if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } else { /* general case */ pari_sp av = avma; /*Copy serves two purposes: * 1) mpn_gcdext destroys its input and needs an extra limb * 2) allows us to use icopy instead of gerepile later. * NOTE: we must put u before d else the final icopy could fail. */ GEN ca = icopy_ef(a,lgefint(a)+1); GEN cb = icopy_ef(b,lgefint(b)+1); GEN u = cgeti(lgefint(a)+1), v = NULL; GEN d = cgeti(lgefint(a)+1); long su,l; mp_size_t lu; l = mpn_gcdext(LIMBS(d), LIMBS(u), &lu, LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb)); if (lu<=0) { if (lu==0) su=0; else {su=-1;lu=-lu;} } else su=1; if (sa<0) su=-su; d[1] = evalsigne(1)|evallgefint(l+2); u[1] = evalsigne(su)|evallgefint(lu+2); if (pv) v=diviiexact(subii(d,mulii(u,a)),b); avma = av; if (pu) *pu=icopy(u); if (pv) *pv=icopy(v); return icopy(d); } } pari-2.7.5/src/kernel/gmp/MakeLVL1.SH0000644000175000017500000000101612314242551015505 0ustar billbillcat >> $file << EOT L1OBJS=$kern1/int.h $knone/level1.h parilvl1.h: \$(L1OBJS) $src/headers/paritune.h if test -r ./tune.h; then d=.; else d=$kern1; fi;\ cat \$\$d/tune.h \$(L1OBJS) > parilvl1.h MP_C=$kern1/mp.c $knone/cmp.c $knone/gcdll.c $knone/ratlift.c\ $knone/invmod.c $kern1/gcd.c $kern1/gcdext.c $knone/mp_indep.c $knone/add.c mpker.c: \$(MP_C) cat \$(MP_C) > mpker.c mpker\$(_O): .headers mpker.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) \$(GMPINCLUDE) -o mpker\$(_O) mpker.c EOT pari-2.7.5/src/kernel/mips64/0000755000175000017500000000000012613365633014307 5ustar billbillpari-2.7.5/src/kernel/mips64/asm0.h0000644000175000017500000000354012366172547015327 0ustar billbill#line 2 "../src/kernel/mips64/asm0.h" /* Copyright (C) 2013 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. */ /* ASM mulll NOASM addll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("dmultu %2,%3\n\tmfhi %1" \ : "=&l" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : "hi"); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("dmultu %3,%4\n\tmfhi %0\n\tmflo %2\n\t" \ "daddu %1,%2,%5\n\tsltu %2,%1,%5\n\tdaddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : "hi", "lo"); \ __value; \ }) #endif pari-2.7.5/src/kernel/hppa/0000755000175000017500000000000012613365633014115 5ustar billbillpari-2.7.5/src/kernel/hppa/asm0.h0000644000175000017500000000541712366172547015142 0ustar billbill#line 2 "../src/kernel/hppa/asm0.h" /* Copyright (C) 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. */ /* This file was made using idea from Bruno Haible ix86 asm inline kernel * and code from Nigel Smart hppa asm kernel. mulll was inspired from * longlong.h from the GNU MP package.*/ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("add %2,%3,%0\n\taddc %%r0,%%r0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %4,%5,%%r0\n\taddc %2,%3,%0\n\taddc %%r0,%%r0,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong) 1)\ : "cc"); \ __value; \ }) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %2,%3,%0\n\taddc %%r0,%%r0,%1\n\tsubi 1,%1,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub %%r0,%4,%%r0\n\tsubb %2,%3,%0\n\taddc %%r0,%%r0,%1\n\tsubi 1,%1,%1" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow)\ : "cc"); \ __value; \ }) #define mulll(a,b) \ __extension__ ({ ulong __arg1 = (a), __arg2 = (b); \ union {double z; ulong x[2];} __vtab; \ __asm__ ("xmpyu %1,%2,%0" \ : "=f" (__vtab.z) \ : "f" (__arg1), "f" (__arg2) \ : "cc"); \ hiremainder=__vtab.x[0]; \ __vtab.x[1]; \ }) #define addmul(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ union {double z; ulong x[2];} __vtab; \ __asm__ ("xmpyu %1,%2,%0" \ : "=f" (__vtab.z) \ : "f" (__arg1), "f" (__arg2) \ : "cc"); \ __asm__ ("add %2,%3,%0\n\taddc %%r0, %4, %1" \ : "=&r" (__value), "=r" (hiremainder) \ : "r" (__vtab.x[1]),"r" (hiremainder), "r" (__vtab.x[0]) \ : "cc"); \ __value; \ }) #endif pari-2.7.5/src/kernel/ppc/0000755000175000017500000000000012613365633013747 5ustar billbillpari-2.7.5/src/kernel/ppc/asm0.h0000644000175000017500000000502512366172547014767 0ustar billbill/* 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. */ /* ASM addll mulll bfffo NOASM divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addc %0,%2,%3\n\txor %1,%2,%2\n\taddze %1,%4\n\t" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong) 0)); \ __value; \ }) #define addllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addc %0,%3,%4\n\tli %1,0\n\taddze %1,%4\n\taddc %0,%2,%5\n\taddze %1,%4\n\t" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" (overflow), "0" ((ulong) 0)); \ __value; \ }) #define bfffo(a) \ __extension__ ({ ulong __a = (a), __value; \ __asm__ ("cntlzw %0, %1" : "=r" (__value) : "r" (__a)); \ __value; \ }) #define subll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subfc %0,%3,%2\n\tli %1,0\n\taddme %1,%4\n\tneg %1,%4" \ : "=&r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong)0)); \ __value; \ }) #define subllx(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subfc %0,%5,%2\n\tli %1,0\n\taddme %1,%5\n\tsubfc %0,%3,%4\n\taddme %1,%5\n\tneg %1,%5" \ : "=r" (__value), "=r" (overflow) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong)0), "1" (overflow)); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("mulhwu %1,%2,%3\n\tmullw %0,%2,%3\n\t" \ : "=r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mullw %0,%3,%4\n\tmulhwu %2,%3,%4\n\taddc %0,%5,%6\n\taddze %1,%7\n\t" \ : "=&r" (__value), "=r" (hiremainder), "=r" (__temp) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0), "1" (hiremainder), "2" ((ulong) 0)); \ __value; \ }) #endif pari-2.7.5/src/kernel/m68k/0000755000175000017500000000000012613365633013752 5ustar billbillpari-2.7.5/src/kernel/m68k/asm0.h0000644000175000017500000001201112366172547014763 0ustar billbill#line 2 "../src/kernel/m68k/asm0.h" /* Copyright (C) 2006 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. */ /* Written by Bill Allombert and dedicated to thoses who wrote the original * m68k kernel mp.s */ /* ASM addll mulll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("add.l %2,%0 ; addx.l %1,%1" \ : "=&d" (__value), "=d" (overflow) \ : "rm" (__arg1), "0" (__arg2), "1" (0UL) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("neg.l %2 ; addx.l %4,%0 ; addx.l %1,%1" \ : "=d" (__value), "=d" (overflow), "=d" (__temp) \ : "0" (__arg1), "d" (__arg2), "2" (overflow), "1" (0UL) \ : "cc"); \ __value; \ }) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("sub.l %3,%0 ; addx.l %1,%1" \ : "=&d" (__value), "=d" (overflow) \ : "0" (__arg1), "rm" (__arg2), "1" (0UL) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("neg.l %2 ; subx.l %4,%0 ; addx.l %1,%1" \ : "=d" (__value), "=d" (overflow), "=d" (__temp) \ : "0" (__arg1), "d" (__arg2), "2" (overflow), "1" (0UL) \ : "cc"); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value; \ __asm__ ("mulu.l %2, %0:%1" \ : "=d" (hiremainder), "=d" (__value) \ : "md" (__arg1) , "1" (__arg2) \ : "cc"); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value; \ __asm__ ("mulu.l %2, %0:%1; add.l %4,%1; addx.l %5,%0" \ : "=&d" (hiremainder), "=&d" (__value) \ : "md" (__arg1), "1" (__arg2), "d" (hiremainder), "d" (0UL) \ : "cc" ); \ __value; \ }) #define bfffo(a) \ __extension__ ({ \ ulong __arg1 = (a), __value; \ __asm__ ("bfffo %1{#0:#0}, %0" \ : "=d" (__value) \ : "md" (__arg1) \ : "cc" ); \ __value; \ }) #define divll(a, b) \ __extension__ ({ \ ulong __arg2 = (b), __value =(a); \ __asm__ ("divu.l %2, %0:%1" \ : "+d" (hiremainder), "+d" (__value) \ : "md" (__arg2) \ : "cc"); \ __value; \ }) #endif pari-2.7.5/src/kernel/sparcv8_super/0000755000175000017500000000000012613365633015771 5ustar billbillpari-2.7.5/src/kernel/sparcv8_super/asm0.h0000644000175000017500000000002211636712103016764 0ustar billbill/* NOASM divll */ pari-2.7.5/src/kernel/sparcv8_super/MakeLVL0.SH0000644000175000017500000000025211636712103017527 0ustar billbillcat >> $file << EOT parilvl0.h: $src/kernel/sparcv8_micro/asm0-common.h \$(L0MODS) $cfg/genkernel $src/kernel/sparcv8_micro/asm0-common.h $kern0/asm0.h > parilvl0.h EOT pari-2.7.5/src/kernel/arm/0000755000175000017500000000000012613365633013744 5ustar billbillpari-2.7.5/src/kernel/arm/asm0.h0000644000175000017500000000475012366172547014770 0ustar billbill/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER register ulong hiremainder #define LOCAL_OVERFLOW register ulong overflow #define addll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("adds %0,%2,%3\n\tadc %1,%4,%4\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" ((ulong)0): "cc"); \ __value; \ }) #define addllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs %1,%4,#1\n\tadcs %0,%2,%3\n\tadc %1,%5,%5\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define subll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs %0,%2,%3\n\tadc %1,%4,%4\n\trsb %1,%1,#1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("rsbs %1,%4,%5\n\tsbcs %0,%2,%3\n\tadc %1,%5,%5\n\trsb %1,%1,#1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("umull %0,%1,%2,%3\n\t" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("umlal %0,%1,%2,%3\n\t" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong) 0), "0" (hiremainder)); \ __value; \ }) #if 0 /* Not supported by all CPU */ #define bfffo(a) \ __extension__ ({ \ ulong __arg1 = (a), __value; \ __asm__ ("clz %0,%1\n\t" \ : "=&r" (__value) \ : "r" (__arg1)); \ __value; \ }) #endif #endif pari-2.7.5/src/kernel/none/0000755000175000017500000000000012613365633014124 5ustar billbillpari-2.7.5/src/kernel/none/addll.h0000644000175000017500000000617612405547147015370 0ustar billbill#line 2 "../src/kernel/none/addll.h" /* Copyright (C) 2003 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. */ /* This file originally adapted from gmp-3.1.1 (from T. Granlund), files * longlong.h and gmp-e_IMPL.h Copyright (C) 2000 Free Software Foundation, Inc. */ #undef LOCAL_OVERFLOW #define LOCAL_OVERFLOW extern ulong overflow; #if !defined(INLINE) extern long addll(ulong x, ulong y); extern long addllx(ulong x, ulong y); extern long subll(ulong x, ulong y); extern long subllx(ulong x, ulong y); #else #if defined(__GNUC__) && !defined(DISABLE_INLINE) #undef LOCAL_OVERFLOW #define LOCAL_OVERFLOW register ulong overflow #define addll(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value = __arg1 + __arg2; \ overflow = (__value < __arg1); \ __value; \ }) #define addllx(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp = __arg1 + overflow;\ overflow = (__tmp < __arg1); \ __value = __tmp + __arg2; \ overflow |= (__value < __tmp); \ __value; \ }) #define subll(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b); \ overflow = (__arg2 > __arg1); \ __arg1 - __arg2; \ }) #define subllx(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp = __arg1 - overflow;\ overflow = (__arg1 < overflow); \ __value = __tmp - __arg2; \ overflow |= (__arg2 > __tmp); \ __value; \ }) #else /* __GNUC__ */ INLINE long addll(ulong x, ulong y) { const ulong z = x+y; overflow=(zx); return (long) z; } INLINE long subllx(ulong x, ulong y) { const ulong z = x-y-overflow; overflow = (z>x || (z==x && overflow)); return (long) z; } #endif /* __GNUC__ */ #endif pari-2.7.5/src/kernel/none/gcd.c0000644000175000017500000000620112405547147015025 0ustar billbill#line 2 "../src/kernel/none/gcd.c" /* Copyright (C) 2003 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. */ /* assume y > x > 0. return y mod x */ static ulong resiu(GEN y, ulong x) { long i, ly = lgefint(y); LOCAL_HIREMAINDER; hiremainder = 0; for (i=2; iy>0, both of them odd. return x-y if x=y mod 4, x+y otherwise */ static void gcd_plus_minus(GEN x, GEN y, GEN res) { pari_sp av = avma; long lx = lgefint(x)-1; long ly = lgefint(y)-1, lt,m,i; GEN t; if ((x[lx]^y[ly]) & 3) /* x != y mod 4*/ t = addiispec(x+2,y+2,lx-1,ly-1); else t = subiispec(x+2,y+2,lx-1,ly-1); lt = lgefint(t)-1; while (!t[lt]) lt--; m = vals(t[lt]); lt++; if (m == 0) /* 2^32 | t */ { for (i = 2; i < lt; i++) res[i] = t[i]; } else if (t[2] >> m) { shift_right(res,t, 2,lt, 0,m); } else { lt--; t++; shift_right(res,t, 2,lt, t[1],m); } res[1] = evalsigne(1)|evallgefint(lt); avma = av; } /* uses modified right-shift binary algorithm now --GN 1998Jul23 */ GEN gcdii(GEN a, GEN b) { long v, w; pari_sp av; GEN t, p1; switch (absi_cmp(a,b)) { case 0: return absi(a); case -1: t=b; b=a; a=t; } if (!signe(b)) return absi(a); /* here |a|>|b|>0. Try single precision first */ if (lgefint(a)==3) return igcduu((ulong)a[2], (ulong)b[2]); if (lgefint(b)==3) { ulong u = resiu(a,(ulong)b[2]); if (!u) return absi(b); return igcduu((ulong)b[2], u); } /* larger than gcd: "avma=av" gerepile (erasing t) is valid */ av = avma; (void)new_chunk(lgefint(b)); /* HACK */ t = remii(a,b); if (!signe(t)) { avma=av; return absi(b); } a = b; b = t; v = vali(a); a = shifti(a,-v); setabssign(a); w = vali(b); b = shifti(b,-w); setabssign(b); if (w < v) v = w; switch(absi_cmp(a,b)) { case 0: avma=av; a=shifti(a,v); return a; case -1: p1=b; b=a; a=p1; } if (is_pm1(b)) { avma=av; return int2n(v); } /* we have three consecutive memory locations: a,b,t. * All computations are done in place */ /* a and b are odd now, and a>b>1 */ while (lgefint(a) > 3) { /* if a=b mod 4 set t=a-b, otherwise t=a+b, then strip powers of 2 */ /* so that t <= (a+b)/4 < a/2 */ gcd_plus_minus(a,b, t); if (is_pm1(t)) { avma=av; return int2n(v); } switch(absi_cmp(t,b)) { case -1: p1 = a; a = b; b = t; t = p1; break; case 1: p1 = a; a = t; t = p1; break; case 0: avma = av; b=shifti(b,v); return b; } } { long r[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; r[2] = (long) gcduodd((ulong)b[2], (ulong)a[2]); avma = av; return shifti(r,v); } } pari-2.7.5/src/kernel/none/asm0.h0000644000175000017500000000114112366172547015137 0ustar billbill/* 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. */ /* NOASM addll mulll bfffo divll */ pari-2.7.5/src/kernel/none/mp_indep.c0000644000175000017500000005642612413013143016060 0ustar billbill#line 2 "../src/kernel/none/mp_indep.c" /* 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. */ /* Find c such that 1=c*b mod 2^BITS_IN_LONG, assuming b odd (unchecked) */ ulong invmod2BIL(ulong b) { static int tab[] = { 0, 0, 0, 8, 0, 8, 0, 0 }; ulong x = b + tab[b & 7]; /* b^(-1) mod 2^4 */ /* Newton applied to 1/x - b = 0 */ #ifdef LONG_IS_64BIT x = x*(2-b*x); /* one more pass necessary */ #endif x = x*(2-b*x); x = x*(2-b*x); return x*(2-b*x); } void affrr(GEN x, GEN y) { long lx,ly,i; y[1] = x[1]; if (!signe(x)) return; lx=lg(x); ly=lg(y); if (lx <= ly) { for (i=2; i ly: round properly */ if (x[ly] & HIGHBIT) roundr_up_ip(y, ly); } GEN trunc2nr(GEN x, long n) { long ex; if (!signe(x)) return gen_0; ex = expo(x) + n; if (ex < 0) return gen_0; return mantissa2nr(x, ex - bit_prec(x) + 1); } /* x a t_REAL, x = i/2^e, i a t_INT */ GEN mantissa_real(GEN x, long *e) { *e = bit_prec(x)-1-expo(x); return mantissa2nr(x, 0); } GEN mului(ulong x, GEN y) { long s = signe(y); GEN z; if (!s || !x) return gen_0; z = muluispec(x, y+2, lgefint(y)-2); setsigne(z,s); return z; } GEN mulsi(long x, GEN y) { long s = signe(y); GEN z; if (!s || !x) return gen_0; if (x<0) { s = -s; x = -x; } z = muluispec((ulong)x, y+2, lgefint(y)-2); setsigne(z,s); return z; } GEN mulss(long x, long y) { long p1; LOCAL_HIREMAINDER; if (!x || !y) return gen_0; if (x<0) { x = -x; if (y<0) { y = -y; p1 = mulll(x,y); return uutoi(hiremainder, p1); } p1 = mulll(x,y); return uutoineg(hiremainder, p1); } else { if (y<0) { y = -y; p1 = mulll(x,y); return uutoineg(hiremainder, p1); } p1 = mulll(x,y); return uutoi(hiremainder, p1); } } GEN sqrs(long x) { long p1; LOCAL_HIREMAINDER; if (!x) return gen_0; if (x<0) x = -x; p1 = mulll(x,x); return uutoi(hiremainder, p1); } GEN muluu(ulong x, ulong y) { long p1; LOCAL_HIREMAINDER; if (!x || !y) return gen_0; p1 = mulll(x,y); return uutoi(hiremainder, p1); } GEN sqru(ulong x) { long p1; LOCAL_HIREMAINDER; if (!x) return gen_0; p1 = mulll(x,x); return uutoi(hiremainder, p1); } /* assume x > 1, y != 0. Return u * y with sign s */ static GEN mulur_2(ulong x, GEN y, long s) { long m, sh, i, lx = lg(y), e = expo(y); GEN z = cgetr(lx); ulong garde; LOCAL_HIREMAINDER; y--; garde = mulll(x,y[lx]); for (i=lx-1; i>=3; i--) z[i]=addmul(x,y[i]); z[2]=hiremainder; /* != 0 since y normalized and |x| > 1 */ sh = bfffo(hiremainder); m = BITS_IN_LONG-sh; if (sh) shift_left(z,z, 2,lx-1, garde,sh); z[1] = evalsigne(s) | evalexpo(m+e); if ((garde << sh) & HIGHBIT) roundr_up_ip(z, lx); return z; } INLINE GEN mul0r(GEN x) { long l = lg(x), e = expo(x); e = (l > 2)? -bit_accuracy(l) + e: (e < 0? (e<<1): 0); return real_0_bit(e); } /* lg(x) > 2 */ INLINE GEN div0r(GEN x) { long l = lg(x), e = expo(x); return real_0_bit(-bit_accuracy(l) - e); } GEN mulsr(long x, GEN y) { long s; if (!x) return mul0r(y); s = signe(y); if (!s) { if (x < 0) x = -x; return real_0_bit( expo(y) + expu(x) ); } if (x==1) return rcopy(y); if (x==-1) return negr(y); if (x < 0) return mulur_2((ulong)-x, y, -s); else return mulur_2((ulong)x, y, s); } GEN mulur(ulong x, GEN y) { long s; if (!x) return mul0r(y); s = signe(y); if (!s) return real_0_bit( expo(y) + expu(x) ); if (x==1) return rcopy(y); return mulur_2(x, y, s); } INLINE void mulrrz_end(GEN z, GEN hi, long lz, long sz, long ez, ulong garde) { long i; if (hi[2] < 0) { if (z != hi) for (i=2; i1 && z[i]==0); if (i == 1) { z[2] = (long)HIGHBIT; ez++; } } z[1] = evalsigne(sz)|evalexpo(ez); } /* mulrrz_end for lz = 3, minor simplifications. z[2]=hiremainder from mulll */ INLINE void mulrrz_3end(GEN z, long sz, long ez, ulong garde) { if (z[2] < 0) { /* z2 < (2^BIL-1)^2 / 2^BIL, hence z2+1 != 0 */ if (garde & HIGHBIT) z[2]++; /* round properly */ ez++; } else { z[2] = (z[2]<<1) | (garde>>(BITS_IN_LONG-1)); if (garde & (1UL<<(BITS_IN_LONG-2))) { z[2]++; /* round properly, z2+1 can overflow */ if (!z[2]) { z[2] = (long)HIGHBIT; ez++; } } } z[1] = evalsigne(sz)|evalexpo(ez); } /* set z <-- x^2 != 0, floating point multiplication. * lz = lg(z) = lg(x) */ INLINE void sqrz_i(GEN z, GEN x, long lz) { long ez = expo(x) << 1; long i, j, lzz, p1; ulong garde; GEN x1; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (lz > MULRR_MULII_LIMIT) { pari_sp av = avma; GEN hi = sqrispec_mirror(x+2, lz-2); mulrrz_end(z, hi, lz, 1, ez, hi[lz]); avma = av; return; } if (lz == 3) { garde = mulll(x[2],x[2]); z[2] = hiremainder; mulrrz_3end(z, 1, ez, garde); return; } lzz = lz-1; p1 = x[lzz]; if (p1) { (void)mulll(p1,x[3]); garde = addmul(p1,x[2]); z[lzz] = hiremainder; } else { garde = 0; z[lzz] = 0; } for (j=lz-2, x1=x-j; j>=3; j--) { p1 = x[j]; x1++; if (p1) { (void)mulll(p1,x1[lz+1]); garde = addll(addmul(p1,x1[lz]), garde); for (i=lzz; i>j; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,x1[i]), z[i]); } z[j] = hiremainder+overflow; } else z[j]=0; } p1 = x[2]; x1++; garde = addll(mulll(p1,x1[lz]), garde); for (i=lzz; i>2; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,x1[i]), z[i]); } z[2] = hiremainder+overflow; mulrrz_end(z, z, lz, 1, ez, garde); } /* lz "large" = lg(y) = lg(z), lg(x) > lz if flag = 1 and >= if flag = 0 */ INLINE void mulrrz_int(GEN z, GEN x, GEN y, long lz, long flag, long sz) { pari_sp av = avma; GEN hi = muliispec_mirror(y+2, x+2, lz+flag-2, lz-2); mulrrz_end(z, hi, lz, sz, expo(x)+expo(y), hi[lz]); avma = av; } /* lz = 3 */ INLINE void mulrrz_3(GEN z, GEN x, GEN y, long flag, long sz) { ulong garde; LOCAL_HIREMAINDER; if (flag) { (void)mulll(x[2],y[3]); garde = addmul(x[2],y[2]); } else garde = mulll(x[2],y[2]); z[2] = hiremainder; mulrrz_3end(z, sz, expo(x)+expo(y), garde); } /* set z <-- x*y, floating point multiplication. Trailing 0s for x are * treated efficiently (important application: mulir). * lz = lg(z) = lg(x) <= ly <= lg(y), sz = signe(z). flag = lg(x) < lg(y) */ INLINE void mulrrz_i(GEN z, GEN x, GEN y, long lz, long flag, long sz) { long ez, i, j, lzz, p1; ulong garde; GEN y1; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (x == y) { sqrz_i(z,x,lz); return; } if (lz > MULRR_MULII_LIMIT) { mulrrz_int(z,x,y,lz,flag,sz); return; } if (lz == 3) { mulrrz_3(z,x,y,flag,sz); return; } ez = expo(x) + expo(y); if (flag) { (void)mulll(x[2],y[lz]); garde = hiremainder; } else garde = 0; lzz=lz-1; p1=x[lzz]; if (p1) { (void)mulll(p1,y[3]); garde = addll(addmul(p1,y[2]), garde); z[lzz] = overflow+hiremainder; } else z[lzz]=0; for (j=lz-2, y1=y-j; j>=3; j--) { p1 = x[j]; y1++; if (p1) { (void)mulll(p1,y1[lz+1]); garde = addll(addmul(p1,y1[lz]), garde); for (i=lzz; i>j; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,y1[i]), z[i]); } z[j] = hiremainder+overflow; } else z[j]=0; } p1 = x[2]; y1++; garde = addll(mulll(p1,y1[lz]), garde); for (i=lzz; i>2; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,y1[i]), z[i]); } z[2] = hiremainder+overflow; mulrrz_end(z, z, lz, sz, ez, garde); } GEN mulrr(GEN x, GEN y) { long flag, ly, lz, sx, sy; GEN z; if (x == y) return sqrr(x); sx = signe(x); if (!sx) return real_0_bit(expo(x) + expo(y)); sy = signe(y); if (!sy) return real_0_bit(expo(x) + expo(y)); if (sy < 0) sx = -sx; lz = lg(x); ly = lg(y); if (lz > ly) { lz = ly; swap(x, y); flag = 1; } else flag = (lz != ly); z = cgetr(lz); mulrrz_i(z, x,y, lz,flag, sx); return z; } GEN sqrr(GEN x) { long lz, sx = signe(x); GEN z; if (!sx) return real_0_bit(2*expo(x)); lz = lg(x); z = cgetr(lz); sqrz_i(z, x, lz); return z; } GEN 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); if (sx < 0) togglesign(z); return z; } sy = signe(y); if (!sy) return real_0_bit(expi(x) + expo(y)); if (sy < 0) sx = -sx; { long lz = lg(y), lx = lgefint(x); GEN hi, z = cgetr(lz); pari_sp av = avma; if (lx < (lz>>1) || (lx < lz && lz > MULRR_MULII_LIMIT)) { /* size mantissa of x < half size of mantissa z, or lx < lz so large * that mulrr will call mulii anyway: mulii */ x = itor(x, lx); hi = muliispec_mirror(y+2, x+2, lz-2, lx-2); mulrrz_end(z, hi, lz, sx, expo(x)+expo(y), hi[lz]); } else /* dubious: complete x with 0s and call mulrr */ mulrrz_i(z, itor(x,lz), y, lz, 0, sx); avma = av; return z; } } /* x + y*z, generic. If lgefint(z) <= 3, caller should use faster variants */ static GEN addmulii_gen(GEN x, GEN y, GEN z, long lz) { long lx = lgefint(x), ly; pari_sp av; GEN t; if (lx == 2) return mulii(z,y); ly = lgefint(y); if (ly == 2) return icopy(x); /* y = 0, wasteful copy */ av = avma; (void)new_chunk(lx+ly+lz); /*HACK*/ t = mulii(z, y); avma = av; return addii(t,x); } /* x + y*z, lgefint(z) == 3 */ static GEN addmulii_lg3(GEN x, GEN y, GEN z) { long s = signe(z), lx, ly; ulong w = z[2]; pari_sp av; GEN t; if (w == 1) return (s > 0)? addii(x,y): subii(x,y); /* z = +- 1 */ lx = lgefint(x); ly = lgefint(y); if (lx == 2) { /* x = 0 */ if (ly == 2) return gen_0; t = muluispec(w, y+2, ly-2); if (signe(y) < 0) s = -s; setsigne(t, s); return t; } if (ly == 2) return icopy(x); /* y = 0, wasteful copy */ av = avma; (void)new_chunk(1+lx+ly);/*HACK*/ t = muluispec(w, y+2, ly-2); if (signe(y) < 0) s = -s; setsigne(t, s); avma = av; return addii(x,t); } /* x + y*z */ GEN addmulii(GEN x, GEN y, GEN z) { long lz = lgefint(z); switch(lz) { case 2: return icopy(x); /* z = 0, wasteful copy */ case 3: return addmulii_lg3(x, y, z); default:return addmulii_gen(x, y, z, lz); } } /* x + y*z, returns x itself and not a copy when y*z = 0 */ GEN addmulii_inplace(GEN x, GEN y, GEN z) { long lz; if (lgefint(y) == 2) return x; lz = lgefint(z); switch(lz) { case 2: return x; case 3: return addmulii_lg3(x, y, z); default:return addmulii_gen(x, y, z, lz); } } /* written by Bruno Haible following an idea of Robert Harley */ long vals(ulong z) { static char tab[64]={-1,0,1,12,2,6,-1,13,3,-1,7,-1,-1,-1,-1,14,10,4,-1,-1,8,-1,-1,25,-1,-1,-1,-1,-1,21,27,15,31,11,5,-1,-1,-1,-1,-1,9,-1,-1,24,-1,-1,20,26,30,-1,-1,-1,-1,23,-1,19,29,-1,22,18,28,17,16,-1}; #ifdef LONG_IS_64BIT long s; #endif if (!z) return -1; #ifdef LONG_IS_64BIT if (! (z&0xffffffff)) { s = 32; z >>=32; } else s = 0; #endif z |= ~z + 1; z += z << 4; z += z << 6; z ^= z << 16; /* or z -= z<<16 */ #ifdef LONG_IS_64BIT return s + tab[(z&0xffffffff)>>26]; #else return tab[z>>26]; #endif } GEN divsi(long x, GEN y) { long p1, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("divsi",gen_0); if (!x || lgefint(y)>3 || ((long)y[2])<0) return gen_0; hiremainder=0; p1=divll(labs(x),y[2]); if (x<0) { hiremainder = -((long)hiremainder); p1 = -p1; } if (s<0) p1 = -p1; return stoi(p1); } GEN divir(GEN x, GEN y) { GEN z; long ly = lg(y), lx = lgefint(x); pari_sp av; if (ly == 2) pari_err_INV("divir",y); if (lx == 2) return div0r(y); if (lx == 3) { z = divur(x[2], y); if (signe(x) < 0) togglesign(z); return z; } z = cgetr(ly); av = avma; affrr(divrr(itor(x, ly+1), y), z); avma = av; return z; } GEN divur(ulong x, GEN y) { pari_sp av; long ly = lg(y); GEN z; if (ly == 2) pari_err_INV("divur",y); if (!x) return div0r(y); if (ly > INVNEWTON_LIMIT) { av = avma; z = invr(y); if (x == 1) return z; return gerepileuptoleaf(av, mulur(x, z)); } z = cgetr(ly); av = avma; affrr(divrr(utor(x,ly+1), y), z); avma = av; return z; } GEN divsr(long x, GEN y) { pari_sp av; long ly = lg(y); GEN z; if (ly == 2) pari_err_INV("divsr",y); if (!x) return div0r(y); if (ly > INVNEWTON_LIMIT) { av = avma; z = invr(y); if (x == 1) return z; if (x ==-1) { togglesign(z); return z; } return gerepileuptoleaf(av, mulsr(x, z)); } z = cgetr(ly); av = avma; affrr(divrr(stor(x,ly+1), y), z); avma = av; return z; } /* returns 1/y, assume y != 0 */ static GEN invr_basecase(GEN y) { long ly = lg(y); GEN z = cgetr(ly); pari_sp av = avma; affrr(divrr(real_1(ly+1), y), z); avma = av; return z; } /* returns 1/b, Newton iteration */ GEN invr(GEN b) { const long s = 6; long i, p, l = lg(b); GEN x, a; ulong mask; if (l <= maxss(INVNEWTON_LIMIT, (1L<>= 1; } x = cgetr(l); a = rcopy(b); a[1] = _evalexpo(0) | evalsigne(1); affrr(invr_basecase(rtor(a, p+2)), x); while (mask > 1) { p <<= 1; if (mask & 1) p--; mask >>= 1; setlg(a, p + 2); setlg(x, p + 2); /* TODO: mulrr(a,x) should be a half product (the higher half is known). * mulrr(x, ) already is */ affrr(addrr(x, mulrr(x, subsr(1, mulrr(a,x)))), x); avma = (pari_sp)a; } x[1] = (b[1] & SIGNBITS) | evalexpo(expo(x)-expo(b)); avma = (pari_sp)x; return x; } GEN modii(GEN x, GEN y) { switch(signe(x)) { case 0: return gen_0; case 1: return remii(x,y); default: { pari_sp av = avma; (void)new_chunk(lgefint(y)); x = remii(x,y); avma=av; if (x==gen_0) return x; return subiispec(y+2,x+2,lgefint(y)-2,lgefint(x)-2); } } } void modiiz(GEN x, GEN y, GEN z) { const pari_sp av = avma; affii(modii(x,y),z); avma=av; } 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 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); return z; } GEN divru(GEN x, ulong y) { long i, lx, garde, sh, e, s = signe(x); GEN z; LOCAL_HIREMAINDER; 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); e = expo(x); lx = lg(x); z = cgetr(lx); if (y <= (ulong)x[2]) { hiremainder = 0; for (i=2; i garde */ garde = divll(0,y); } else { long l = lx-1; hiremainder = x[2]; for (i=2; i= 0) { if (z) *z = utoi(r); return q; } q = gerepileuptoint(av, addis(q, (y < 0)? 1: -1)); if (z) *z = utoi(r + labs(y)); return q; } GEN truedvmdsi(long x, GEN y, GEN *z) { long q, r; if (z == ONLY_REM) return modsi(x, y); q = sdivsi_rem(x,y,&r); if (r >= 0) { if (z) *z = utoi(r); return stoi(q); } q = q - signe(y); if (!z) return stoi(q); *z = subiuspec(y+2,(ulong)-r, lgefint(y)-2); return stoi(q); } /* 2^n = shifti(gen_1, n) */ GEN int2n(long n) { long i, m, l; GEN z; if (n < 0) return gen_0; if (n == 0) return gen_1; l = dvmdsBIL(n, &m) + 3; z = cgetipos(l); for (i = 2; i < l; i++) z[i] = 0; *int_MSW(z) = 1L << m; return z; } /* To avoid problems when 2^(BIL-1) < n. Overflow cleanly, where int2n * returns gen_0 */ GEN int2u(ulong n) { ulong i, m, l; GEN z; if (n == 0) return gen_1; l = dvmduBIL(n, &m) + 3; z = cgetipos(l); for (i = 2; i < l; i++) z[i] = 0; *int_MSW(z) = 1L << m; return z; } GEN shifti(GEN x, long n) { long s = signe(x); GEN y; if(s == 0) return gen_0; y = shiftispec(x + 2, lgefint(x) - 2, n); if (signe(y)) setsigne(y, s); return y; } /* actual operations will take place on a+2 and b+2: we strip the codewords */ GEN mulii(GEN a,GEN b) { long sa,sb; GEN z; sa=signe(a); if (!sa) return gen_0; sb=signe(b); if (!sb) return gen_0; if (sb<0) sa = -sa; z = muliispec(a+2,b+2, lgefint(a)-2,lgefint(b)-2); setsigne(z,sa); return z; } GEN sqri(GEN a) { return sqrispec(a+2, lgefint(a)-2); } /* sqrt()'s result may be off by 1 when a is not representable exactly as a * double [64bit machine] */ ulong usqrt(ulong a) { ulong x = (ulong)sqrt((double)a); #ifdef LONG_IS_64BIT if (x > LOWMASK || x*x > a) x--; #endif return x; } /********************************************************************/ /** **/ /** EXPONENT / CONVERSION t_REAL --> double **/ /** **/ /********************************************************************/ #ifdef LONG_IS_64BIT long dblexpo(double x) { union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ if (x==0.) return -exp_mid; fi.f = x; return ((fi.i & (HIGHBIT-1)) >> mant_len) - exp_mid; } ulong dblmantissa(double x) { union { double f; ulong i; } fi; const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return 0; fi.f = x; return (fi.i << expo_len) | HIGHBIT; } GEN dbltor(double x) { GEN z; long e; union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return real_0_bit(-exp_mid); fi.f = x; z = cgetr(DEFAULTPREC); { const ulong a = fi.i; ulong A; e = ((a & (HIGHBIT-1)) >> mant_len) - exp_mid; if (e == exp_mid+1) pari_err_OVERFLOW("dbltor [NaN or Infinity]"); A = a << expo_len; if (e == -exp_mid) { /* unnormalized values */ int sh = bfffo(A); e -= sh-1; z[2] = A << sh; } else z[2] = HIGHBIT | A; z[1] = _evalexpo(e) | evalsigne(x<0? -1: 1); } return z; } double rtodbl(GEN x) { long ex,s=signe(x); ulong a; union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ if (!s || (ex=expo(x)) < - exp_mid) return 0.0; /* start by rounding to closest */ a = (x[2] & (HIGHBIT-1)) + 0x400; if (a & HIGHBIT) { ex++; a=0; } if (ex >= exp_mid) pari_err_OVERFLOW("t_REAL->double conversion"); fi.i = ((ex + exp_mid) << mant_len) | (a >> expo_len); if (s<0) fi.i |= HIGHBIT; return fi.f; } #else /* LONG_IS_64BIT */ #if PARI_DOUBLE_FORMAT == 1 # define INDEX0 1 # define INDEX1 0 #elif PARI_DOUBLE_FORMAT == 0 # define INDEX0 0 # define INDEX1 1 #endif long dblexpo(double x) { union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int shift = mant_len-32; if (x==0.) return -exp_mid; fi.f = x; { const ulong a = fi.i[INDEX0]; return ((a & (HIGHBIT-1)) >> shift) - exp_mid; } } ulong dblmantissa(double x) { union { double f; ulong i[2]; } fi; const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return 0; fi.f = x; { const ulong a = fi.i[INDEX0]; const ulong b = fi.i[INDEX1]; return HIGHBIT | b >> (BITS_IN_LONG-expo_len) | (a << expo_len); } } GEN dbltor(double x) { GEN z; long e; union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ const int shift = mant_len-32; if (x==0.) return real_0_bit(-exp_mid); fi.f = x; z = cgetr(DEFAULTPREC); { const ulong a = fi.i[INDEX0]; const ulong b = fi.i[INDEX1]; ulong A, B; e = ((a & (HIGHBIT-1)) >> shift) - exp_mid; if (e == exp_mid+1) pari_err_OVERFLOW("dbltor [NaN or Infinity]"); A = b >> (BITS_IN_LONG-expo_len) | (a << expo_len); B = b << expo_len; if (e == -exp_mid) { /* unnormalized values */ int sh; if (A) { sh = bfffo(A); e -= sh-1; z[2] = (A << sh) | (B >> (32-sh)); z[3] = B << sh; } else { sh = bfffo(B); /* B != 0 */ e -= sh-1 + 32; z[2] = B << sh; z[3] = 0; } } else { z[3] = B; z[2] = HIGHBIT | A; } z[1] = _evalexpo(e) | evalsigne(x<0? -1: 1); } return z; } double rtodbl(GEN x) { long ex,s=signe(x),lx=lg(x); ulong a,b,k; union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ const int shift = mant_len-32; if (!s || (ex=expo(x)) < - exp_mid) return 0.0; /* start by rounding to closest */ a = x[2] & (HIGHBIT-1); if (lx > 3) { b = x[3] + 0x400UL; if (b < 0x400UL) a++; if (a & HIGHBIT) { ex++; a=0; } } else b = 0; if (ex >= exp_mid) pari_err_OVERFLOW("t_REAL->double conversion"); ex += exp_mid; k = (a >> expo_len) | (ex << shift); if (s<0) k |= HIGHBIT; fi.i[INDEX0] = k; fi.i[INDEX1] = (a << (BITS_IN_LONG-expo_len)) | (b >> expo_len); return fi.f; } #endif /* LONG_IS_64BIT */ pari-2.7.5/src/kernel/none/bfffo.h0000644000175000017500000000372712366172547015375 0ustar billbill#line 2 "../src/kernel/none/bfffo.h" /* 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. */ #if !defined(INLINE) extern int bfffo(ulong x); #else #if defined(__GNUC__) && !defined(DISABLE_INLINE) #ifdef LONG_IS_64BIT # define bfffo(x) \ __extension__ ({ \ static int __bfffo_tabshi[16]={4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0};\ int __value = BITS_IN_LONG - 4; \ ulong __arg1=(x); \ if (__arg1 & ~0xffffffffUL) {__value -= 32; __arg1 >>= 32;}\ if (__arg1 & ~0xffffUL) {__value -= 16; __arg1 >>= 16;} \ if (__arg1 & ~0x00ffUL) {__value -= 8; __arg1 >>= 8;} \ if (__arg1 & ~0x000fUL) {__value -= 4; __arg1 >>= 4;} \ __value + __bfffo_tabshi[__arg1]; \ }) #else # define bfffo(x) \ __extension__ ({ \ static int __bfffo_tabshi[16]={4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0};\ int __value = BITS_IN_LONG - 4; \ ulong __arg1=(x); \ if (__arg1 & ~0xffffUL) {__value -= 16; __arg1 >>= 16;} \ if (__arg1 & ~0x00ffUL) {__value -= 8; __arg1 >>= 8;} \ if (__arg1 & ~0x000fUL) {__value -= 4; __arg1 >>= 4;} \ __value + __bfffo_tabshi[__arg1]; \ }) #endif #else INLINE int bfffo(ulong x) { static int tabshi[16]={4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0}; int value = BITS_IN_LONG - 4; ulong arg1=x; #ifdef LONG_IS_64BIT if (arg1 & ~0xffffffffUL) {value -= 32; arg1 >>= 32;} #endif if (arg1 & ~0xffffUL) {value -= 16; arg1 >>= 16;} if (arg1 & ~0x00ffUL) {value -= 8; arg1 >>= 8;} if (arg1 & ~0x000fUL) {value -= 4; arg1 >>= 4;} return value + tabshi[arg1]; } #endif #endif pari-2.7.5/src/kernel/none/int.h0000644000175000017500000000260712366172547015101 0ustar billbill#line 2 "../src/kernel/none/int.h" /* 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. */ #define int_MSW(x) ((x)+2) /*x being a t_INT, return a pointer to the most significant word of x.*/ #define int_LSW(x) ((x)+lgefint((x))-1) /*x being a t_INT, return a pointer to the least significant word of x.*/ #define int_precW(x) ((x)+1) /*x pointing to a mantissa word, return the previous (less significant) * mantissa word.*/ #define int_nextW(x) ((x)-1) /*x pointing to a mantissa word, return the next (more significant) mantissa * word.*/ #define int_W(x,l) ((x)+lgefint((x))-1-(l)) /*x being a t_INT, return a pointer to the l-th least significant word of x.*/ #define int_W_lg(x,l,lx) ((x)+lx-1-(l)) /*x being a t_INT, return a pointer to the l-th least significant word of x, * assuming lgefint(x) = lx.*/ #define PARI_KERNEL_NONE /*This macro should not be used in libpari itself.*/ pari-2.7.5/src/kernel/none/cmp.c0000644000175000017500000000652212366172547015061 0ustar billbill#line 2 "../src/kernel/none/cmp.c" /* Copyright (C) 2002-2003 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. */ /********************************************************************/ /** **/ /** Comparison routines **/ /** **/ /********************************************************************/ /*They depend on cmpiispec and equaliispec in mp.c*/ int equalii(GEN x, GEN y) { if ((x[1] & (LGBITS|SIGNBITS)) != (y[1] & (LGBITS|SIGNBITS))) return 0; return equaliispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); } int cmpii(GEN x, GEN y) { const long sx = signe(x), sy = signe(y); if (sxsy) return 1; if (!sx) return 0; if (sx>0) return cmpiispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); else return -cmpiispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); } int 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 */ lx = lg(x); ly = lg(y); if (lx < ly) { i=2; while (isy) return 1; if (!sx) return 0; ex=expo(x); ey=expo(y); if (ex>ey) return sx; if (ex (ulong)y[i]) ? sx : -sx; if (lx>=ly) { while (iey) return 1; if (ex (ulong)y[i])? 1: -1; if (lx>=ly) { while (i 1 */ { if (!x) return y; /* fix up x */ while (!(x&1)) x>>=1; if (x==1) return 1; if (x==y) return y; else if (x>y) goto xislarger;/* will be rare, given how we'll use this */ /* loop invariants: x,y odd and distinct. */ yislarger: if ((x^y)&2) /* ...01, ...11 or vice versa */ y=(x>>2)+(y>>2)+1; /* ==(x+y)>>2 except it can't overflow */ else /* ...01,...01 or ...11,...11 */ y=(y-x)>>2; /* now y!=0 in either case */ while (!(y&1)) y>>=1; /* kill any windfall-gained powers of 2 */ if (y==1) return 1; /* comparand == return value... */ if (x==y) return y; /* this and the next is just one comparison */ else if (x>2)+(y>>2)+1; else x=(x-y)>>2; /* x!=0 */ while (!(x&1)) x>>=1; if (x==1) return 1; if (x==y) return y; else if (x>y) goto xislarger; goto yislarger; } /* Gotos are useful, and Programming is an Art. D.E.Knuth. */ /* PS: Of course written with Dijkstra's lessons firmly in mind... --GN */ /* at least one of a or b is odd, return gcd(a,b) */ INLINE ulong mygcduodd(ulong a, ulong b) { ulong c; if (b&1) { if (a==1 || b==1) c = 1; else c = gcduodd(a, b); } else { if (a==1) c = 1; else c = gcduodd(b, a); } return c; } /* modified right shift binary algorithm with at most one division */ long cgcd(long a,long b) { long v; a=labs(a); if (!b) return a; b=labs(b); if (!a) return b; if (a>b) { a %= b; if (!a) return b; } else { b %= a; if (!b) return a; } v = vals(a|b); return (long)(mygcduodd((ulong)(a>>v), (ulong)(b>>v)) << v); } ulong ugcd(ulong a,ulong b) { long v; if (!b) return a; if (!a) return b; if (a>b) { a %= b; if (!a) return b; } else { b %= a; if (!b) return a; } v = vals(a|b); return mygcduodd(a>>v, b>>v) << v; } /* For gcdii(): assume a>b>0, return gcd(a,b) as a GEN */ static GEN igcduu(ulong a, ulong b) { long v; a %= b; if (!a) return utoipos(b); v = vals(a|b); return utoipos( mygcduodd(a>>v, b>>v) << v ); } /*Warning: overflows silently if lcm does not fit*/ long clcm(long a,long b) { long d = cgcd(a,b); if (!d) return 0; return d == 1? a*b: a*(b/d); } /********************************************************************/ /** **/ /** INTEGER EXTENDED GCD (AND INVMOD) **/ /** **/ /********************************************************************/ /* GN 1998Oct25, originally developed in January 1998 under 2.0.4.alpha, * in the context of trying to improve elliptic curve cryptosystem attacking * algorithms. 2001Jan02 -- added bezout() functionality. * * Two basic ideas - (1) avoid many integer divisions, especially when the * quotient is 1 (which happens more than 40% of the time). (2) Use Lehmer's * trick as modified by Jebelean of extracting a couple of words' worth of * leading bits from both operands, and compute partial quotients from them * as long as we can be sure of their values. The Jebelean modifications * consist in reliable inequalities from which we can decide fast whether * to carry on or to return to the outer loop, and in re-shifting after the * first word's worth of bits has been used up. All of this is described * in R. Lercier's these [pp148-153 & 163f.], except his outer loop isn't * quite right (the catch-up divisions needed when one partial quotient is * larger than a word are missing). * * The API consists of invmod() and bezout() below; the single-word routines * xgcduu and xxgcduu may be called directly if desired; lgcdii() probably * doesn't make much sense out of context. * * The whole lot is a factor 6 .. 8 faster on word-sized operands, and asym- * ptotically about a factor 2.5 .. 3, depending on processor architecture, * than the naive continued-division code. Unfortunately, thanks to the * unrolled loops and all, the code is a bit lengthy. */ /*================================== * xgcduu(d,d1,f,v,v1,s) * xxgcduu(d,d1,f,u,u1,v,v1,s) * rgcduu(d,d1,vmax,u,u1,v,v1,s) *==================================*/ /* * Fast `final' extended gcd algorithm, acting on two ulongs. Ideally this * should be replaced with assembler versions wherever possible. The present * code essentially does `subtract, compare, and possibly divide' at each step, * which is reasonable when hardware division (a) exists, (b) is a bit slowish * and (c) does not depend a lot on the operand values (as on i486). When * wordsize division is in fact an assembler routine based on subtraction, * this strategy may not be the most efficient one. * * xxgcduu() should be called with d > d1 > 0, returns gcd(d,d1), and assigns * the usual signless cont.frac. recurrence matrix to [u, u1; v, v1] (i.e., * the product of all the [0, 1; 1 q_j] where the leftmost factor arises from * the quotient of the first division step), and the information about the * implied signs to s (-1 when an odd number of divisions has been done, * 1 otherwise). xgcduu() is exactly the same except that u,u1 are not com- * puted (and not returned, of course). * * The input flag f should be set to 1 if we know in advance that gcd(d,d1)==1 * (so we can stop the chain division one step early: as soon as the remainder * equals 1). Use this when you intend to use only what would be v, or only * what would be u and v, after that final division step, but not u1 and v1. * With the flag in force and thus without that final step, the interesting * quantity/ies will still sit in [u1 and] v1, of course. * * For computing the inverse of a single-word INTMOD known to exist, pass f=1 * to xgcduu(), and obtain the result from s and v1. (The routine does the * right thing when d1==1 already.) For finishing a multiword modinv known * to exist, pass f=1 to xxgcduu(), and multiply the returned matrix (with * properly adjusted signs) onto the values v' and v1' previously obtained * from the multiword division steps. Actually, just take the scalar product * of [v',v1'] with [u1,-v1], and change the sign if s==-1. (If the final * step had been carried out, it would be [-u,v], and s would also change.) * For reducing a rational number to lowest terms, pass f=0 to xgcduu(). * Finally, f=0 with xxgcduu() is useful for Bezout computations. * [Harrumph. In the above prescription, the sign turns out to be precisely * wrong.] * (It is safe for invmod() to call xgcduu() with f=1, because f&1 doesn't * make a difference when gcd(d,d1)>1. The speedup is negligible.) * * In principle, when gcd(d,d1) is known to be 1, it is straightforward to * recover the final u,u1 given only v,v1 and s. However, it probably isn't * worthwhile, as it trades a few multiplications for a division. * * Note that these routines do not know and do not need to know about the * PARI stack. * * Added 2001Jan15: * rgcduu() is a variant of xxgcduu() which does not have f (the effect is * that of f=0), but instead has a ulong vmax parameter, for use in rational * reconstruction below. It returns when v1 exceeds vmax; v will never * exceed vmax. (vmax=0 is taken as a synonym of ULONG_MAX i.e. unlimited, * in which case rgcduu behaves exactly like xxgcduu with f=0.) The return * value of rgcduu() is typically meaningless; the interesting part is the * matrix. */ ulong xgcduu(ulong d, ulong d1, int f, ulong* v, ulong* v1, long *s) { ulong xv,xv1, xs, q,res; LOCAL_HIREMAINDER; /* The above blurb contained a lie. The main loop always stops when d1 * has become equal to 1. If (d1 == 1 && !(f&1)) after the loop, we do * the final `division' of d by 1 `by hand' as it were. * * The loop has already been unrolled once. Aggressive optimization could * well lead to a totally unrolled assembler version... * * On modern x86 architectures, this loop is a pig anyway. The division * instruction always puts its result into the same pair of registers, and * we always want to use one of them straight away, so pipeline performance * will suck big time. An assembler version should probably do a first loop * computing and storing all the quotients -- their number is bounded in * advance -- and then assembling the matrix in a second pass. On other * architectures where we can cycle through four or so groups of registers * and exploit a fast ALU result-to-operand feedback path, this is much less * of an issue. (Intel sucks. See http://www.x86.org/ ...) */ xs = res = 0; xv = 0UL; xv1 = 1UL; while (d1 > 1UL) { d -= d1; /* no need to use subll */ if (d >= d1) { hiremainder = 0; q = 1 + divll(d,d1); d = hiremainder; xv += q * xv1; } else xv += xv1; /* possible loop exit */ if (d <= 1UL) { xs=1; break; } /* repeat with inverted roles */ d1 -= d; if (d1 >= d) { hiremainder = 0; q = 1 + divll(d1,d); d1 = hiremainder; xv1 += q * xv; } else xv1 += xv; } /* while */ if (!(f&1)) /* division by 1 postprocessing if needed */ { if (xs && d==1) { xv1 += d1 * xv; xs = 0; res = 1UL; } else if (!xs && d1==1) { xv += d * xv1; xs = 1; res = 1UL; } } if (xs) { *s = -1; *v = xv1; *v1 = xv; return (res ? res : (d==1 ? 1UL : d1)); } else { *s = 1; *v = xv; *v1 = xv1; return (res ? res : (d1==1 ? 1UL : d)); } } ulong xxgcduu(ulong d, ulong d1, int f, ulong* u, ulong* u1, ulong* v, ulong* v1, long *s) { ulong xu,xu1, xv,xv1, xs, q,res; LOCAL_HIREMAINDER; xs = res = 0; xu = xv1 = 1UL; xu1 = xv = 0UL; while (d1 > 1UL) { d -= d1; /* no need to use subll */ if (d >= d1) { hiremainder = 0; q = 1 + divll(d,d1); d = hiremainder; xv += q * xv1; xu += q * xu1; } else { xv += xv1; xu += xu1; } /* possible loop exit */ if (d <= 1UL) { xs=1; break; } /* repeat with inverted roles */ d1 -= d; if (d1 >= d) { hiremainder = 0; q = 1 + divll(d1,d); d1 = hiremainder; xv1 += q * xv; xu1 += q * xu; } else { xv1 += xv; xu1 += xu; } } /* while */ if (!(f&1)) /* division by 1 postprocessing if needed */ { if (xs && d==1) { xv1 += d1 * xv; xu1 += d1 * xu; xs = 0; res = 1UL; } else if (!xs && d1==1) { xv += d * xv1; xu += d * xu1; xs = 1; res = 1UL; } } if (xs) { *s = -1; *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return (res ? res : (d==1 ? 1UL : d1)); } else { *s = 1; *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return (res ? res : (d1==1 ? 1UL : d)); } } ulong rgcduu(ulong d, ulong d1, ulong vmax, ulong* u, ulong* u1, ulong* v, ulong* v1, long *s) { ulong xu,xu1, xv,xv1, xs, q, res=0; int f = 0; LOCAL_HIREMAINDER; if (vmax == 0) vmax = ULONG_MAX; xs = res = 0; xu = xv1 = 1UL; xu1 = xv = 0UL; while (d1 > 1UL) { d -= d1; /* no need to use subll */ if (d >= d1) { hiremainder = 0; q = 1 + divll(d,d1); d = hiremainder; xv += q * xv1; xu += q * xu1; } else { xv += xv1; xu += xu1; } /* possible loop exit */ if (xv > vmax) { f=xs=1; break; } if (d <= 1UL) { xs=1; break; } /* repeat with inverted roles */ d1 -= d; if (d1 >= d) { hiremainder = 0; q = 1 + divll(d1,d); d1 = hiremainder; xv1 += q * xv; xu1 += q * xu; } else { xv1 += xv; xu1 += xu; } /* possible loop exit */ if (xv1 > vmax) { f=1; break; } } /* while */ if (!(f&1)) /* division by 1 postprocessing if needed */ { if (xs && d==1) { xv1 += d1 * xv; xu1 += d1 * xu; xs = 0; res = 1UL; } else if (!xs && d1==1) { xv += d * xv1; xu += d * xu1; xs = 1; res = 1UL; } } if (xs) { *s = -1; *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return (res ? res : (d==1 ? 1UL : d1)); } else { *s = 1; *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return (res ? res : (d1==1 ? 1UL : d)); } } /*================================== * cbezout(a,b,uu,vv) *================================== * Same as bezout() but for C longs. * Return g = gcd(a,b) >= 0, and assign longs u,v through pointers uu,vv * such that g = u*a + v*b. * Special cases: * a == b == 0 ==> pick u=1, v=0 (and return 1, surprisingly) * a != 0 == b ==> keep v=0 * a == 0 != b ==> keep u=0 * |a| == |b| != 0 ==> keep u=0, set v=+-1 * Assignments through uu,vv happen unconditionally; non-NULL pointers * _must_ be used. */ long cbezout(long a,long b,long *uu,long *vv) { long s,*t; ulong d = labs(a), d1 = labs(b); ulong r,u,u1,v,v1; #ifdef DEBUG_CBEZOUT err_printf("> cbezout(%ld,%ld,%p,%p)\n", a, b, (void *)uu, (void *)vv); #endif if (!b) { *vv=0L; if (!a) { *uu=1L; #ifdef DEBUG_CBEZOUT err_printf("< %ld (%ld, %ld)\n", 1L, *uu, *vv); #endif return 0L; } *uu = a < 0 ? -1L : 1L; #ifdef DEBUG_CBEZOUT err_printf("< %ld (%ld, %ld)\n", (long)d, *uu, *vv); #endif return (long)d; } else if (!a || (d == d1)) { *uu = 0L; *vv = b < 0 ? -1L : 1L; #ifdef DEBUG_CBEZOUT err_printf("< %ld (%ld, %ld)\n", (long)d1, *uu, *vv); #endif return (long)d1; } else if (d == 1) /* frequently used by nfinit */ { *uu = a; *vv = 0L; #ifdef DEBUG_CBEZOUT err_printf("< %ld (%ld, %ld)\n", 1L, *uu, *vv); #endif return 1L; } else if (d < d1) { /* bug in gcc-2.95.3: * s = a; a = b; b = s; produces wrong result a = b. This is OK: */ { long _x = a; a = b; b = _x; } /* in order to keep the right signs */ r = d; d = d1; d1 = r; t = uu; uu = vv; vv = t; #ifdef DEBUG_CBEZOUT err_printf(" swapping\n"); #endif } /* d > d1 > 0 */ r = xxgcduu(d, d1, 0, &u, &u1, &v, &v1, &s); if (s < 0) { *uu = a < 0 ? (long)u : -(long)u; *vv = b < 0 ? -(long)v : (long)v; } else { *uu = a < 0 ? -(long)u : (long)u; *vv = b < 0 ? (long)v : -(long)v; } #ifdef DEBUG_CBEZOUT err_printf("< %ld (%ld, %ld)\n", (long)r, *uu, *vv); #endif return (long)r; } /*================================== * lgcdii(d,d1,u,u1,v,v1,vmax) *==================================*/ /* Lehmer's partial extended gcd algorithm, acting on two t_INT GENs. * * Tries to determine, using the leading 2*BITS_IN_LONG significant bits of d * and a quantity of bits from d1 obtained by a shift of the same displacement, * as many partial quotients of d/d1 as possible, and assigns to [u,u1;v,v1] * the product of all the [0, 1; 1, q_j] thus obtained, where the leftmost * factor arises from the quotient of the first division step. * * For use in rational reconstruction, input param vmax can be given a * nonzero value. In this case, we will return early as soon as v1 > vmax * (i.e. it is guaranteed that v <= vmax). --2001Jan15 * * MUST be called with d > d1 > 0, and with d occupying more than one * significant word (if it doesn't, the caller has no business with us; * he/she/it should use xgcduu() instead). Returns the number of reduction/ * swap steps carried out, possibly zero, or under certain conditions minus * that number. When the return value is nonzero, the caller should use the * returned recurrence matrix to update its own copies of d,d1. When the * return value is non-positive, and the latest remainder after updating * turns out to be nonzero, the caller should at once attempt a full division, * rather than first trying lgcdii() again -- this typically happens when we * are about to encounter a quotient larger than half a word. (This is not * detected infallibly -- after a positive return value, it is perfectly * possible that the next stage will end up needing a full division. After * a negative return value, however, this is certain, and should be acted * upon.) * * (The sign information, for which xgcduu() has its return argument s, is now * implicit in the LSB of our return value, and the caller may take advantage * of the fact that a return value of +-1 implies u==0,u1==v==1 [only v1 pro- * vides interesting information in this case]. One might also use the fact * that if the return value is +-2, then u==1, but this is rather marginal.) * * If it was not possible to determine even the first quotient, either because * we're too close to an integer quotient or because the quotient would be * larger than one word (if the `leading digit' of d1 after shifting is all * zeros), we return 0 and do not bother to assign anything to the last four * args. * * The division chain might (sometimes) even run to completion. It will be * up to the caller to detect this case. * * This routine does _not_ change d or d1; this will also be up to the caller. * * Note that this routine does not know and does not need to know about the * PARI stack. */ /*#define DEBUG_LEHMER 1 */ int lgcdii(ulong* d, ulong* d1, ulong* u, ulong* u1, ulong* v, ulong* v1, ulong vmax) { /* Strategy: (1) Extract/shift most significant bits. We assume that d * has at least two significant words, but we can cope with a one-word d1. * Let dd,dd1 be the most significant dividend word and matching part of the * divisor. * (2) Check for overflow on the first division. For our purposes, this * happens when the upper half of dd1 is zero. (Actually this is detected * during extraction.) * (3) Get a fix on the first quotient. We compute q = floor(dd/dd1), which * is an upper bound for floor(d/d1), and which gives the true value of the * latter if (and-almost-only-if) the remainder dd' = dd-q*dd1 is >= q. * (If it isn't, we give up. This is annoying because the subsequent full * division will repeat some work already done, but it happens very infre- * quently. Doing the extra-bit-fetch in this case would be awkward.) * (4) Finish initializations. * * The remainder of the action is comparatively boring... The main loop has * been unrolled once (so we don't swap things and we can apply Jebelean's * termination conditions which alternatingly take two different forms during * successive iterations). When we first run out of sufficient bits to form * a quotient, and have an extra word of each operand, we pull out two whole * word's worth of dividend bits, and divisor bits of matching significance; * to these we apply our partial matrix (disregarding overflow because the * result mod 2^(2*BITS_IN_LONG) will in fact give the correct values), and * re-extract one word's worth of the current dividend and a matching amount * of divisor bits. The affair will normally terminate with matrix entries * just short of a whole word. (We terminate the inner loop before these can * possibly overflow.) */ ulong dd,dd1,ddlo,dd1lo, sh,shc; /* `digits', shift count */ ulong xu,xu1, xv,xv1, q,res; /* recurrences, partial quotient, count */ ulong tmp0,tmp1,tmp2,tmpd,tmpu,tmpv; /* temps */ ulong dm1,dm2,d1m1,d1m2; long ld, ld1, lz; /* t_INT effective lengths */ int skip = 0; /* a boolean flag */ LOCAL_OVERFLOW; LOCAL_HIREMAINDER; #ifdef DEBUG_LEHMER voir(d, -1); voir(d1, -1); #endif /* following is just for convenience: vmax==0 means no bound */ if (vmax == 0) vmax = ULONG_MAX; ld = lgefint(d); ld1 = lgefint(d1); lz = ld - ld1; /* >= 0 */ if (lz > 1) return 0; /* rare, quick and desperate exit */ d = int_MSW(d); d1 = int_MSW(d1); /* point at the leading `digits' */ dm1 = *int_precW(d); d1m1 = *int_precW(d1); dm2 = *int_precW(int_precW(d)); d1m2 = *int_precW(int_precW(d1)); dd1lo = 0; /* unless we find something better */ sh = bfffo(*d); /* obtain dividend left shift count */ if (sh) { /* do the shifting */ shc = BITS_IN_LONG - sh; if (lz) { /* dividend longer than divisor */ dd1 = (*d1 >> shc); if (!(HIGHMASK & dd1)) return 0; /* overflow detected */ if (ld1 > 3) dd1lo = (*d1 << sh) + (d1m1 >> shc); else dd1lo = (*d1 << sh); } else { /* dividend and divisor have the same length */ dd1 = (*d1 << sh); if (!(HIGHMASK & dd1)) return 0; if (ld1 > 3) { dd1 += (d1m1 >> shc); if (ld1 > 4) dd1lo = (d1m1 << sh) + (d1m2 >> shc); else dd1lo = (d1m1 << sh); } } /* following lines assume d to have 2 or more significant words */ dd = (*d << sh) + (dm1 >> shc); if (ld > 4) ddlo = (dm1 << sh) + (dm2 >> shc); else ddlo = (dm1 << sh); } else { /* no shift needed */ if (lz) return 0; /* div'd longer than div'r: o'flow automatic */ dd1 = *d1; if (!(HIGHMASK & dd1)) return 0; if(ld1 > 3) dd1lo = d1m1; /* assume again that d has another significant word */ dd = *d; ddlo = dm1; } #ifdef DEBUG_LEHMER err_printf(" %lx:%lx, %lx:%lx\n", dd, ddlo, dd1, dd1lo); #endif /* First subtraction/division stage. (If a subtraction initially suffices, * we don't divide at all.) If a Jebelean condition is violated, and we * can't fix it even by looking at the low-order bits in ddlo,dd1lo, we * give up and ask for a full division. Otherwise we commit the result, * possibly deciding to re-shift immediately afterwards. */ dd -= dd1; if (dd < dd1) { /* first quotient known to be == 1 */ xv1 = 1UL; if (!dd) /* !(Jebelean condition), extraspecial case */ { /* note this can actually happen... Now * q==1 is known, but we underflow already. * OTOH we've just shortened d by a whole word. * Thus we feel pleased with ourselves and * return. (The re-shift code below would * do so anyway.) */ *u = 0; *v = *u1 = *v1 = 1UL; return -1; /* Next step will be a full division. */ } /* if !(Jebelean) then */ } else { /* division indicated */ hiremainder = 0; xv1 = 1 + divll(dd, dd1); /* xv1: alternative spelling of `q', here ;) */ dd = hiremainder; if (dd < xv1) /* !(Jebelean cond'), non-extra special case */ { /* Attempt to complete the division using the * less significant bits, before skipping right * past the 1st loop to the reshift stage. */ ddlo = subll(ddlo, mulll(xv1, dd1lo)); dd = subllx(dd, hiremainder); /* If we now have an overflow, q was _certainly_ too large. Thanks to * our decision not to get here unless the original dd1 had bits set in * the upper half of the word, however, we now do know that the correct * quotient is in fact q-1. Adjust our data accordingly. */ if (overflow) { xv1--; ddlo = addll(ddlo,dd1lo); dd = addllx(dd,dd1); /* overflows again which cancels the borrow */ /* ...and fall through to skip=1 below */ } else /* Test Jebelean condition anew, at this point using _all_ the extracted * bits we have. This is clutching at straws; we have a more or less * even chance of succeeding this time. Note that if we fail, we really * do not know whether the correct quotient would have been q or some * smaller value. */ if (!dd && ddlo < xv1) return 0; /* Otherwise, we now know that q is correct, but we cannot go into the * 1st loop. Raise a flag so we'll remember to skip past the loop. * Get here also after the q-1 adjustment case. */ skip = 1; } /* if !(Jebelean) then */ } res = 1; #ifdef DEBUG_LEHMER err_printf(" q = %ld, %lx, %lx\n", xv1, dd1, dd); #endif if (xv1 > vmax) { /* gone past the bound already */ *u = 0UL; *u1 = 1UL; *v = 1UL; *v1 = xv1; return res; } xu = 0UL; xv = xu1 = 1UL; /* Some invariants from here across the first loop: * * At this point, and again after we are finished with the first loop and * subsequent conditional, a division and the associated update of the * recurrence matrix have just been carried out completely. The matrix * xu,xu1;xv,xv1 has been initialized (or updated, possibly with permuted * columns), and the current remainder == next divisor (dd at the moment) * is nonzero (it might be zero here, but then skip will have been set). * * After the first loop, or when skip is set already, it will also be the * case that there aren't sufficiently many bits to continue without re- * shifting. If the divisor after reshifting is zero, or indeed if it * doesn't have more than half a word's worth of bits, we will have to * return at that point. Otherwise, we proceed into the second loop. * * Furthermore, when we reach the re-shift stage, dd:ddlo and dd1:dd1lo will * already reflect the result of applying the current matrix to the old * ddorig:ddlo and dd1orig:dd1lo. (For the first iteration above, this * was easy to achieve, and we didn't even need to peek into the (now * no longer existent!) saved words. After the loop, we'll stop for a * moment to merge in the ddlo,dd1lo contributions.) * * Note that after the first division, even an a priori quotient of 1 cannot * be trusted until we've checked Jebelean's condition -- it cannot be too * large, of course, but it might be too small. */ if (!skip) { for(;;) { /* First half of loop divides dd into dd1, and leaves the recurrence * matrix xu,...,xv1 groomed the wrong way round (xu,xv will be the newer * entries) when successful. */ tmpd = dd1 - dd; if (tmpd < dd) { /* quotient suspected to be 1 */ #ifdef DEBUG_LEHMER q = 1; #endif tmpu = xu + xu1; /* cannot overflow -- everything bounded by * the original dd during first loop */ tmpv = xv + xv1; } else { /* division indicated */ hiremainder = 0; q = 1 + divll(tmpd, dd); tmpd = hiremainder; tmpu = xu + q*xu1; /* can't overflow, but may need to be undone */ tmpv = xv + q*xv1; } tmp0 = addll(tmpv, xv1); if ((tmpd < tmpu) || overflow || (dd - tmpd < tmp0)) /* !(Jebelean cond.) */ break; /* skip ahead to reshift stage */ else { /* commit dd1, xu, xv */ res++; dd1 = tmpd; xu = tmpu; xv = tmpv; #ifdef DEBUG_LEHMER err_printf(" q = %ld, %lx, %lx [%lu,%lu;%lu,%lu]\n", q, dd, dd1, xu1, xu, xv1, xv); #endif if (xv > vmax) { /* time to return */ *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return res; } } /* Second half of loop divides dd1 into dd, and the matrix returns to its * normal arrangement. */ tmpd = dd - dd1; if (tmpd < dd1) { /* quotient suspected to be 1 */ #ifdef DEBUG_LEHMER q = 1; #endif tmpu = xu1 + xu; /* cannot overflow */ tmpv = xv1 + xv; } else { /* division indicated */ hiremainder = 0; q = 1 + divll(tmpd, dd1); tmpd = hiremainder; tmpu = xu1 + q*xu; tmpv = xv1 + q*xv; } tmp0 = addll(tmpu, xu); if ((tmpd < tmpv) || overflow || (dd1 - tmpd < tmp0)) /* !(Jebelean cond.) */ break; /* skip ahead to reshift stage */ else { /* commit dd, xu1, xv1 */ res++; dd = tmpd; xu1 = tmpu; xv1 = tmpv; #ifdef DEBUG_LEHMER err_printf(" q = %ld, %lx, %lx [%lu,%lu;%lu,%lu]\n", q, dd1, dd, xu, xu1, xv, xv1); #endif if (xv1 > vmax) { /* time to return */ *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return res; } } } /* end of first loop */ /* Intermezzo: update dd:ddlo, dd1:dd1lo. (But not if skip is set.) */ if (res&1) { /* after failed division in 1st half of loop: * [dd1:dd1lo,dd:ddlo] = [ddorig:ddlo,dd1orig:dd1lo] * * [ -xu, xu1 ; xv, -xv1 ] * (Actually, we only multiply [ddlo,dd1lo] onto the matrix and * add the high-order remainders + overflows onto [dd1,dd].) */ tmp1 = mulll(ddlo, xu); tmp0 = hiremainder; tmp1 = subll(mulll(dd1lo,xv), tmp1); dd1 += subllx(hiremainder, tmp0); tmp2 = mulll(ddlo, xu1); tmp0 = hiremainder; ddlo = subll(tmp2, mulll(dd1lo,xv1)); dd += subllx(tmp0, hiremainder); dd1lo = tmp1; } else { /* after failed division in 2nd half of loop: * [dd:ddlo,dd1:dd1lo] = [ddorig:ddlo,dd1orig:dd1lo] * * [ xu1, -xu ; -xv1, xv ] * (Actually, we only multiply [ddlo,dd1lo] onto the matrix and * add the high-order remainders + overflows onto [dd,dd1].) */ tmp1 = mulll(ddlo, xu1); tmp0 = hiremainder; tmp1 = subll(tmp1, mulll(dd1lo,xv1)); dd += subllx(tmp0, hiremainder); tmp2 = mulll(ddlo, xu); tmp0 = hiremainder; dd1lo = subll(mulll(dd1lo,xv), tmp2); dd1 += subllx(hiremainder, tmp0); ddlo = tmp1; } #ifdef DEBUG_LEHMER err_printf(" %lx:%lx, %lx:%lx\n", dd, ddlo, dd1, dd1lo); #endif } /* end of skip-pable section: get here also, with res==1, when there * was a problem immediately after the very first division. */ /* Re-shift. Note: the shift count _can_ be zero, viz. under the following * precise conditions: The original dd1 had its topmost bit set, so the 1st * q was 1, and after subtraction, dd had its topmost bit unset. If now * dd==0, we'd have taken the return exit already, so we couldn't have got * here. If not, then it must have been the second division which has gone * amiss (because dd1 was very close to an exact multiple of the remainder * dd value, so this will be very rare). At this point, we'd have a fairly * slim chance of fixing things by re-examining dd1:dd1lo vs. dd:ddlo, but * this is not guaranteed to work. Instead of trying, we return at once. * The caller will see to it that the initial subtraction is re-done using * _all_ the bits of both operands, which already helps, and the next round * will either be a full division (if dd occupied a halfword or less), or * another llgcdii() first step. In the latter case, since we try a little * harder during our first step, we may actually be able to fix the problem, * and get here again with improved low-order bits and with another step * under our belt. Otherwise we'll have given up above and forced a full- * blown division. * * If res is even, the shift count _cannot_ be zero. (The first step forces * a zero into the remainder's MSB, and all subsequent remainders will have * inherited it.) * * The re-shift stage exits if the next divisor has at most half a word's * worth of bits. * * For didactic reasons, the second loop will be arranged in the same way * as the first -- beginning with the division of dd into dd1, as if res * was odd. To cater for this, if res is actually even, we swap things * around during reshifting. (During the second loop, the parity of res * does not matter; we know in which half of the loop we are when we decide * to return.) */ #ifdef DEBUG_LEHMER err_printf("(sh)"); #endif if (res&1) { /* after odd number of division(s) */ if (dd1 && (sh = bfffo(dd1))) { shc = BITS_IN_LONG - sh; dd = (ddlo >> shc) + (dd << sh); if (!(HIGHMASK & dd)) { *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return -res; /* full division asked for */ } dd1 = (dd1lo >> shc) + (dd1 << sh); } else { /* time to return: <= 1 word left, or sh==0 */ *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return res; } } else { /* after even number of divisions */ if (dd) { sh = bfffo(dd); /* Known to be positive. */ shc = BITS_IN_LONG - sh; /* dd:ddlo will become the new dd1, and v.v. */ tmpd = (ddlo >> shc) + (dd << sh); dd = (dd1lo >> shc) + (dd1 << sh); dd1 = tmpd; /* This has completed the swap; now dd is again the current divisor. * The following test originally inspected dd1 -- a most subtle and * most annoying bug. The Management. */ if (HIGHMASK & dd) { /* recurrence matrix is the wrong way round; swap it. */ tmp0 = xu; xu = xu1; xu1 = tmp0; tmp0 = xv; xv = xv1; xv1 = tmp0; } else { /* recurrence matrix is the wrong way round; fix this. */ *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return -res; /* full division asked for */ } } else { /* time to return: <= 1 word left */ *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return res; } } /* end reshift */ #ifdef DEBUG_LEHMER err_printf(" %lx:%lx, %lx:%lx\n", dd, ddlo, dd1, dd1lo); #endif /* The Second Loop. Rip-off of the first, but we now check for overflow * in the recurrences. Returns instead of breaking when we cannot fix the * quotient any longer. */ for(;;) { /* First half of loop divides dd into dd1, and leaves the recurrence * matrix xu,...,xv1 groomed the wrong way round (xu,xv will be the newer * entries) when successful. */ tmpd = dd1 - dd; if (tmpd < dd) { /* quotient suspected to be 1 */ #ifdef DEBUG_LEHMER q = 1; #endif tmpu = xu + xu1; tmpv = addll(xv, xv1); /* xv,xv1 will overflow first */ tmp1 = overflow; } else { /* division indicated */ hiremainder = 0; q = 1 + divll(tmpd, dd); tmpd = hiremainder; tmpu = xu + q*xu1; tmpv = addll(xv, mulll(q,xv1)); tmp1 = overflow | hiremainder; } tmp0 = addll(tmpv, xv1); if ((tmpd < tmpu) || overflow || tmp1 || (dd - tmpd < tmp0)) /* !(Jebelean cond.) */ { /* The recurrence matrix has not yet been warped... */ *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; break; } /* commit dd1, xu, xv */ res++; dd1 = tmpd; xu = tmpu; xv = tmpv; #ifdef DEBUG_LEHMER err_printf(" q = %ld, %lx, %lx\n", q, dd, dd1); #endif if (xv > vmax) { /* time to return */ *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; return res; } /* Second half of loop divides dd1 into dd, and the matrix returns to its * normal arrangement. */ tmpd = dd - dd1; if (tmpd < dd1) { /* quotient suspected to be 1 */ #ifdef DEBUG_LEHMER q = 1; #endif tmpu = xu1 + xu; tmpv = addll(xv1, xv); tmp1 = overflow; } else { /* division indicated */ hiremainder = 0; q = 1 + divll(tmpd, dd1); tmpd = hiremainder; tmpu = xu1 + q*xu; tmpv = addll(xv1, mulll(q, xv)); tmp1 = overflow | hiremainder; } tmp0 = addll(tmpu, xu); if ((tmpd < tmpv) || overflow || tmp1 || (dd1 - tmpd < tmp0)) /* !(Jebelean cond.) */ { /* The recurrence matrix has not yet been unwarped, so it is * the wrong way round; fix this. */ *u = xu1; *u1 = xu; *v = xv1; *v1 = xv; break; } res++; /* commit dd, xu1, xv1 */ dd = tmpd; xu1 = tmpu; xv1 = tmpv; #ifdef DEBUG_LEHMER err_printf(" q = %ld, %lx, %lx\n", q, dd1, dd); #endif if (xv1 > vmax) { /* time to return */ *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return res; } } /* end of second loop */ return res; } /* 1 / Mod(x,p). Assume x < p */ ulong Fl_invsafe(ulong x, ulong p) { long s; ulong xv, xv1, g = xgcduu(p, x, 1, &xv, &xv1, &s); if (g != 1UL) return 0UL; xv = xv1 % p; if (s < 0) xv = p - xv; return xv; } /* 1 / Mod(x,p). Assume x < p */ ulong Fl_inv(ulong x, ulong p) { ulong xv = Fl_invsafe(x, p); if (!xv && p!=1UL) pari_err_INV("Fl_inv", mkintmod(utoi(x), utoi(p))); return xv; } pari-2.7.5/src/kernel/none/divll.h0000644000175000017500000001543512405547147015420 0ustar billbill#line 2 "../src/kernel/none/divll.h" /* Copyright (C) 2003 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. */ /* This file originally adapted from gmp-3.1.1 (from T. Granlund), files * longlong.h and gmp-e_IMPL.h Copyright (C) 2000 Free Software Foundation, Inc. */ #undef LOCAL_HIREMAINDER #define LOCAL_HIREMAINDER extern ulong hiremainder; #if !defined(INLINE) extern long divll(ulong x, ulong y); #else #define __GLUE(hi, lo) (((hi) << BITS_IN_HALFULONG) | (lo)) #define __SPLIT(a, b, c) b = HIGHWORD(a); c = LOWWORD(a) #define __LDIV(a, b, q, r) q = a / b; r = a - q*b extern ulong hiremainder; /* divide (hiremainder * 2^BITS_IN_LONG + n0) by d; assume hiremainder < d. * Return quotient, set hiremainder to remainder */ #if defined(__GNUC__) && !defined(DISABLE_INLINE) #undef LOCAL_HIREMAINDER #define LOCAL_HIREMAINDER register ulong hiremainder #define divll(n0, d) \ __extension__ ({ \ ulong __d1, __d0, __q1, __q0, __r1, __r0, __m, __n1, __n0; \ ulong __k, __d; \ \ __n1 = hiremainder; __n0 = n0; __d = d; \ if (__n1 == 0) \ { /* Only one division needed */ \ __LDIV(__n0, __d, __q1, hiremainder); \ } \ else if (__d < LOWMASK) \ { /* Two half-word divisions */ \ __n1 = __GLUE(__n1, HIGHWORD(__n0)); \ __LDIV(__n1, __d, __q1, __r1); \ __n1 = __GLUE(__r1, LOWWORD(__n0)); \ __LDIV(__n1, __d, __q0, hiremainder); \ __q1 = __GLUE(__q1, __q0); \ } \ else \ { /* General case */ \ if (__d & HIGHBIT) \ { \ __k = 0; __SPLIT(__d, __d1, __d0); \ } \ else \ { \ __k = bfffo(__d); \ __n1 = (__n1 << __k) | (__n0 >> (BITS_IN_LONG - __k)); \ __n0 <<= __k; \ __d = __d << __k; __SPLIT(__d, __d1, __d0); \ } \ __LDIV(__n1, __d1, __q1, __r1); \ __m = __q1 * __d0; \ __r1 = __GLUE(__r1, HIGHWORD(__n0)); \ if (__r1 < __m) \ { \ __q1--, __r1 += __d; \ if (__r1 >= __d) /* we didn't get carry when adding to __r1 */ \ if (__r1 < __m) __q1--, __r1 += __d; \ } \ __r1 -= __m; \ __LDIV(__r1, __d1, __q0, __r0); \ __m = __q0 * __d0; \ __r0 = __GLUE(__r0, LOWWORD(__n0)); \ if (__r0 < __m) \ { \ __q0--, __r0 += __d; \ if (__r0 >= __d) \ if (__r0 < __m) __q0--, __r0 += __d; \ } \ hiremainder = (__r0 - __m) >> __k; \ __q1 = __GLUE(__q1, __q0); \ } \ __q1; \ }) #else /* __GNUC__ */ INLINE long divll(ulong n0, ulong d) { ulong __d1, __d0, __q1, __q0, __r1, __r0, __m, __n1, __n0; ulong __k, __d; __n1 = hiremainder; __n0 = n0; __d = d; if (__n1 == 0) { /* Only one division needed */ __LDIV(__n0, __d, __q1, hiremainder); } else if (__d < LOWMASK) { /* Two half-word divisions */ __n1 = __GLUE(__n1, HIGHWORD(__n0)); __LDIV(__n1, __d, __q1, __r1); __n1 = __GLUE(__r1, LOWWORD(__n0)); __LDIV(__n1, __d, __q0, hiremainder); __q1 = __GLUE(__q1, __q0); } else { /* General case */ if (__d & HIGHBIT) { __k = 0; __SPLIT(__d, __d1, __d0); } else { __k = bfffo(__d); __n1 = (__n1 << __k) | (__n0 >> (BITS_IN_LONG - __k)); __n0 = __n0 << __k; __d = __d << __k; __SPLIT(__d, __d1, __d0); } __LDIV(__n1, __d1, __q1, __r1); __m = __q1 * __d0; __r1 = __GLUE(__r1, HIGHWORD(__n0)); if (__r1 < __m) { __q1--, __r1 += __d; if (__r1 >= __d) /* we didn't get carry when adding to __r1 */ if (__r1 < __m) __q1--, __r1 += __d; } __r1 -= __m; __LDIV(__r1, __d1, __q0, __r0); __m = __q0 * __d0; __r0 = __GLUE(__r0, LOWWORD(__n0)); if (__r0 < __m) { __q0--, __r0 += __d; if (__r0 >= __d) if (__r0 < __m) __q0--, __r0 += __d; } hiremainder = (__r0 - __m) >> __k; __q1 = __GLUE(__q1, __q0); } return __q1; } #endif /* __GNUC__ */ #endif pari-2.7.5/src/kernel/none/level1.h0000644000175000017500000010222512405547147015470 0ustar billbill#line 2 "../src/kernel/none/level1.h" /* 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. */ /* This file defines "level 1" kernel functions. * These functions can be inline; they are also defined externally in * mpinl.c, which includes this file and never needs to be changed */ INLINE long evallg(long x) { if (x & ~LGBITS) pari_err_OVERFLOW("lg()"); return _evallg(x); } INLINE long evalvalp(long x) { long v = _evalvalp(x); if (v & ~VALPBITS) pari_err_OVERFLOW("valp()"); return v; } INLINE long evalexpo(long x) { long v = _evalexpo(x); if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()"); return v; } INLINE long evalprecp(long x) { long v = _evalprecp(x); if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()"); return v; } /* 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: * z = cgetg(t,a); av = avma; garbage(); ltop = avma; * for (i=1; i 0) { GEN z = (GEN)ltop; z[0] = evaltyp(t_VECSMALL) | evallg(l); #ifdef DEBUG { long i; for (i = 1; i < l; i++) z[i] = 0; } #endif } } INLINE void fixlg(GEN x, long ly) { long lx = lg(x), l = lx - ly; if (l > 0) { /* stackdummy(x+lx, x+ly) */ GEN z = x + ly; z[0] = evaltyp(t_VECSMALL) | evallg(l); setlg(x, ly); #ifdef DEBUG { long i; for (i = 1; i < l; i++) z[i] = 0; } #endif } } /* update lg(z) before affrr(y, z) [ to cater for precision loss ]*/ INLINE void affrr_fixlg(GEN y, GEN z) { fixlg(z, lg(y)); affrr(y, z); } /*******************************************************************/ /* */ /* ALLOCATE ON STACK */ /* */ /*******************************************************************/ 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 avma = (pari_sp)z; #ifdef MEMSTEP if (DEBUGMEM && memused != DISABLE_MEMUSED) { long d = (long)memused - (long)z; if (d > 4*MEMSTEP || d < -4*MEMSTEP) { memused = (pari_sp)z; err_printf("...%4.0lf Mbytes used\n",(top-memused)/1048576.); } } #endif return z; } INLINE char * stack_malloc(size_t N) { long n = nchar2nlong(N); return (char*)new_chunk(n); } INLINE char * stack_calloc(size_t N) { char *p = stack_malloc(N); memset(p, 0, N); return p; } /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */ INLINE GEN cgetg_copy(GEN x, long *plx) { GEN y; *plx = lg(x); y = new_chunk((size_t)*plx); y[0] = x[0] & (TYPBITS|LGBITS); return y; } INLINE GEN cgetg_block(long x, long y) { GEN z = newblock((size_t)x); z[0] = evaltyp(y) | evallg(x); return z; } INLINE GEN cgetg(long x, long y) { GEN z = new_chunk((size_t)x); z[0] = evaltyp(y) | evallg(x); return z; } INLINE GEN cgeti(long x) { GEN z = new_chunk((size_t)x); z[0] = evaltyp(t_INT) | evallg(x); return z; } INLINE GEN cgetipos(long x) { GEN z = cgeti(x); z[1] = evalsigne(1) | evallgefint(x); return z; } INLINE GEN cgetineg(long x) { GEN z = cgeti(x); z[1] = evalsigne(-1) | evallgefint(x); return z; } INLINE GEN cgetr_block(long x) { GEN z = newblock((size_t)x); z[0] = evaltyp(t_REAL) | evallg(x); return z; } INLINE GEN cgetr(long x) { GEN z = new_chunk((size_t)x); z[0] = evaltyp(t_REAL) | evallg(x); return z; } /*******************************************************************/ /* */ /* COPY, NEGATION, ABSOLUTE VALUE */ /* */ /*******************************************************************/ /* cannot do memcpy because sometimes x and y overlap */ INLINE GEN leafcopy(GEN x) { register long lx = lg(x); GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */ while (--lx > 0) y[lx] = x[lx]; y[0] = x[0] & (TYPBITS|LGBITS); return y; } INLINE GEN icopy(GEN x) { long i = lgefint(x), lx = i; GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */ while (--i > 0) y[i] = x[i]; y[0] = evaltyp(t_INT) | evallg(lx); return y; } INLINE GEN icopyspec(GEN x, long nx) { long i = nx+2, lx = i; GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */ x -= 2; while (--i >= 2) y[i] = x[i]; y[1] = evalsigne(1) | evallgefint(lx); y[0] = evaltyp(t_INT) | evallg(lx); return y; } INLINE GEN rcopy(GEN x) { return leafcopy(x); } INLINE GEN mpcopy(GEN x) { return leafcopy(x); } INLINE GEN mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; } INLINE GEN mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; } INLINE GEN absi(GEN x) { return mpabs(x); } INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; } INLINE GEN absr(GEN x) { return mpabs(x); } INLINE GEN mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; } INLINE GEN negi(GEN x) { return mpneg(x); } INLINE GEN negr(GEN x) { return mpneg(x); } /* negate in place */ INLINE void togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } } INLINE void setabssign(GEN x) { x[1] &= ~HIGHBIT; } /* negate in place, except universal constants */ INLINE void togglesign_safe(GEN *px) { switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */ { case 0: *px = gen_m1; break; case 3: *px = gen_m2; break; case 6: *px = gen_1; break; case 9: *px = gen_2; break; default: togglesign(*px); } } /* setsigne(y, signe(x)) */ INLINE void affectsign(GEN x, GEN y) { y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS); } /* copies sign in place, except for universal constants */ INLINE void affectsign_safe(GEN x, GEN *py) { if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py); } /*******************************************************************/ /* */ /* GEN -> LONG, LONG -> GEN */ /* */ /*******************************************************************/ /* assume x != 0, return -x as a t_INT */ INLINE GEN utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; } /* assume x != 0, return utoi(x) */ INLINE GEN utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; } INLINE GEN utoi(ulong x) { return x? utoipos(x): gen_0; } INLINE GEN stoi(long x) { if (!x) return gen_0; return x > 0? utoipos((ulong)x): utoineg((ulong)-x); } /* x 2^BIL + y */ INLINE GEN uutoi(ulong x, ulong y) { GEN z; if (!x) return utoi(y); z = cgetipos(4); *int_W_lg(z, 1, 4) = x; *int_W_lg(z, 0, 4) = y; return z; } /* - (x 2^BIL + y) */ INLINE GEN uutoineg(ulong x, ulong y) { GEN z; if (!x) return y? utoineg(y): gen_0; z = cgetineg(4); *int_W_lg(z, 1, 4) = x; *int_W_lg(z, 0, 4) = y; return z; } INLINE long itos(GEN x) { long s = signe(x); long u; if (!s) return 0; u = x[2]; if (lgefint(x) > 3 || u < 0) pari_err_OVERFLOW("t_INT-->long assignment"); return (s>0) ? u : -u; } /* as itos, but return 0 if too large. Cf is_bigint */ INLINE long itos_or_0(GEN x) { long n; if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0; return signe(x) > 0? n: -n; } INLINE ulong itou(GEN x) { switch(lgefint(x)) { case 2: return 0; case 3: return x[2]; default: pari_err_OVERFLOW("t_INT-->ulong assignment"); return 0; /* not reached */ } } /* as itou, but return 0 if too large. Cf is_bigint */ INLINE ulong itou_or_0(GEN x) { if (lgefint(x) != 3) return 0; return (ulong)x[2]; } INLINE GEN real_0_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; } INLINE GEN real_0(long prec) { return real_0_bit(-prec2nbits(prec)); } INLINE GEN real_1(long prec) { GEN x = cgetr(prec); long i; x[1] = evalsigne(1) | _evalexpo(0); x[2] = (long)HIGHBIT; for (i=3; i> r) & 1UL:0; } /*******************************************************************/ /* */ /* COMPARISON */ /* */ /*******************************************************************/ INLINE int cmpir(GEN x, GEN y) { pari_sp av; GEN z; if (!signe(x)) return -signe(y); if (!signe(y)) return signe(x); av=avma; z = itor(x, realprec(y)); avma=av; return cmprr(z,y); /* cmprr does no memory adjustment */ } INLINE int cmpri(GEN x, GEN y) { return -cmpir(y,x); } INLINE int cmpsr(long x, GEN y) { pari_sp av; GEN z; if (!x) return -signe(y); av=avma; z = stor(x, LOWDEFAULTPREC); avma=av; return cmprr(z,y); } INLINE int cmprs(GEN x, long y) { return -cmpsr(y,x); } /* compare x and |y| */ INLINE int cmpui(ulong x, GEN y) { long l = lgefint(y); ulong p; if (!x) return (l > 2)? -1: 0; if (l == 2) return 1; if (l > 3) return -1; p = y[2]; if (p == x) return 0; return p < x ? 1 : -1; } INLINE int cmpiu(GEN x, ulong y) { return -cmpui(y,x); } INLINE int cmpsi(long x, GEN y) { ulong p; if (!x) return -signe(y); if (x > 0) { if (signe(y)<=0) return 1; if (lgefint(y)>3) return -1; p = y[2]; if (p == (ulong)x) return 0; return p < (ulong)x ? 1 : -1; } if (signe(y)>=0) return -1; if (lgefint(y)>3) return 1; p = y[2]; if (p == (ulong)-x) return 0; return p < (ulong)(-x) ? -1 : 1; } INLINE int cmpis(GEN x, long y) { return -cmpsi(y,x); } INLINE int mpcmp(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? cmpii(x,y) : cmpir(x,y); return (typ(y)==t_INT) ? -cmpir(y,x) : cmprr(x,y); } /* x == y ? */ INLINE int equalsi(long x, GEN y) { if (!x) return !signe(y); if (x > 0) { if (signe(y) <= 0 || lgefint(y) != 3) return 0; return ((ulong)y[2] == (ulong)x); } if (signe(y) >= 0 || lgefint(y) != 3) return 0; return ((ulong)y[2] == (ulong)-x); } /* x == |y| ? */ INLINE int equalui(ulong x, GEN y) { if (!x) return !signe(y); return (lgefint(y) == 3 && (ulong)y[2] == x); } INLINE int equaliu(GEN x, ulong y) { return equalui(y,x); } INLINE int equalis(GEN x, long y) { return equalsi(y,x); } /* assume x != 0, is |x| == 2^n ? */ INLINE int absrnz_equal2n(GEN x) { if ((ulong)x[2]==HIGHBIT) { long i, lx = lg(x); for (i = 3; i < lx; i++) if (x[i]) return 0; return 1; } return 0; } /* assume x != 0, is |x| == 1 ? */ INLINE int absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); } INLINE long maxss(long x, long y) { return x>y?x:y; } INLINE long minss(long x, long y) { return xy?x:y; } INLINE double maxdd(double x, double y) { return x>y?x:y; } INLINE double mindd(double x, double y) { return x 0) return y > 0? adduu(x,y): subuu(x, -y); if (y > 0) return subuu(y, -x); else { /* - adduu(-x, -y) */ ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t); } } INLINE GEN subss(long x, long y) { return addss(-y,x); } INLINE GEN subii(GEN x, GEN y) { if (x==y) return gen_0; /* frequent with x = y = gen_0 */ return addii_sign(x, signe(x), y, -signe(y)); } INLINE GEN addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); } INLINE GEN addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); } INLINE GEN subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); } INLINE GEN addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); } INLINE GEN subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); } INLINE GEN subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); } INLINE GEN addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); } INLINE GEN addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); } INLINE GEN subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); } INLINE GEN subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); } /*******************************************************************/ /* */ /* MOD, REM, DIV */ /* */ /*******************************************************************/ INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); } INLINE long mod64(GEN x) { return mod2BIL(x) & 63; } INLINE long mod32(GEN x) { return mod2BIL(x) & 31; } INLINE long mod16(GEN x) { return mod2BIL(x) & 15; } INLINE long mod8(GEN x) { return mod2BIL(x) & 7; } INLINE long mod4(GEN x) { return mod2BIL(x) & 3; } INLINE long mod2(GEN x) { return mod2BIL(x) & 1; } INLINE int mpodd(GEN x) { return signe(x) && mod2(x); } INLINE GEN truedivii(GEN a,GEN b) { return truedvmdii(a,b,NULL); } INLINE GEN truedivis(GEN a, long b) { return truedvmdis(a,b,NULL); } INLINE GEN truedivsi(long a, GEN b) { return truedvmdsi(a,b,NULL); } INLINE GEN divii(GEN a, GEN b) { return dvmdii(a,b,NULL); } INLINE GEN remii(GEN a, GEN b) { return dvmdii(a,b,ONLY_REM); } INLINE GEN divss(long x, long y) { return stoi(x / y); } INLINE GEN modss(long x, long y) { return stoi(smodss(x, y)); } INLINE GEN remss(long x, long y) { return stoi(x % y); } INLINE long smodss(long x, long y) { long r = x%y; return (r >= 0)? r: labs(y) + r; } INLINE long sdivss_rem(long x, long y, long *r) { long q; LOCAL_HIREMAINDER; if (!y) pari_err_INV("sdivss_rem",gen_0); hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y)); if (x < 0) { hiremainder = -((long)hiremainder); q = -q; } if (y < 0) q = -q; *r = hiremainder; return q; } INLINE GEN divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); } INLINE ulong udivuu_rem(ulong x, ulong y, ulong *r) { if (!y) pari_err_INV("udivuu_rem",gen_0); *r = x % y; return x / y; } INLINE ulong udivui_rem(ulong x, GEN y, ulong *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("udivui_rem",gen_0); if (!x || lgefint(y)>3) { *r = x; return 0; } hiremainder=0; q = (long)divll(x, (ulong)y[2]); if (s < 0) q = -q; *r = hiremainder; return q; } /* assume d != 0 and |n| / d can be represented as an ulong. * Return |n|/d, set *r = |n| % d */ INLINE ulong udiviu_rem(GEN n, ulong d, ulong *r) { switch(lgefint(n)) { case 2: *r = 0; return 0; case 3: { ulong nn = n[2]; *r = nn % d; return nn / d; } default: /* 4 */ { ulong n1, n0, q; LOCAL_HIREMAINDER; n0 = *int_W(n,0); n1 = *int_W(n,1); hiremainder = n1; q = divll(n0, d); *r = hiremainder; return q; } } } INLINE long sdivsi_rem(long x, GEN y, long *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("sdivsi_rem",gen_0); if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; } hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]); if (x < 0) { hiremainder = -((long)hiremainder); q = -q; } if (s < 0) q = -q; *r = hiremainder; return q; } INLINE GEN divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); } INLINE long sdivsi(long x, GEN y) { long q, s = signe(y); if (!s) pari_err_INV("sdivsi",gen_0); if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0; q = labs(x) / y[2]; if (x < 0) q = -q; if (s < 0) q = -q; return q; } INLINE GEN dvmdss(long x, long y, GEN *z) { long r; GEN q = divss_rem(x,y, &r); *z = stoi(r); return q; } INLINE long dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); } INLINE ulong dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); } INLINE GEN dvmdsi(long x, GEN y, GEN *z) { long r; GEN q = divsi_rem(x,y, &r); *z = stoi(r); return q; } INLINE GEN dvmdis(GEN x, long y, GEN *z) { long r; GEN q = divis_rem(x,y, &r); *z = stoi(r); return q; } INLINE long smodis(GEN x, long y) { pari_sp av = avma; long r; (void)divis_rem(x,y, &r); avma = av; return (r >= 0) ? r: labs(y) + r; } INLINE GEN modis(GEN x, long y) { return stoi(smodis(x,y)); } INLINE GEN modsi(long x, GEN y) { long r; (void)sdivsi_rem(x, y, &r); return (r >= 0)? stoi(r): addsi_sign(r, y, 1); } INLINE ulong umodui(ulong x, GEN y) { if (!signe(y)) pari_err_INV("umodui",gen_0); if (!x || lgefint(y) > 3) return x; return x % (ulong)y[2]; } INLINE GEN remsi(long x, GEN y) { long r; (void)sdivsi_rem(x,y, &r); return stoi(r); } INLINE GEN remis(GEN x, long y) { pari_sp av = avma; long r; (void)divis_rem(x,y, &r); avma = av; return stoi(r); } INLINE GEN rdivis(GEN x, long y, long prec) { GEN z = cgetr(prec); pari_sp av = avma; affrr(divrs(itor(x,prec), y),z); avma = av; return z; } INLINE GEN rdivsi(long x, GEN y, long prec) { GEN z = cgetr(prec); pari_sp av = avma; affrr(divsr(x, itor(y,prec)), z); avma = av; return z; } INLINE GEN rdivss(long x, long y, long prec) { GEN z = cgetr(prec); pari_sp av = avma; affrr(divrs(stor(x, prec), y), z); avma = av; return z; } INLINE void rdiviiz(GEN x, GEN y, GEN z) { pari_sp av = avma; long prec = realprec(z); affir(x, z); if (!is_bigint(y)) { affrr(divrs(z, y[2]), z); if (signe(y) < 0) togglesign(z); } else affrr(divrr(z, itor(y,prec)), z); avma = av; } INLINE GEN rdivii(GEN x, GEN y, long prec) { GEN z = cgetr(prec); pari_sp av = avma; affir(x, z); if (lg(y) == 3) { affrr(divru(z, y[2]), z); if (signe(y) < 0) togglesign(z); } else affrr(divrr(z, itor(y,prec)), z); avma = av; return z; } INLINE GEN fractor(GEN x, long prec) { return rdivii(gel(x,1), gel(x,2), prec); } INLINE int dvdii(GEN x, GEN y) { pari_sp av=avma; GEN r = remii(x,y); avma = av; return r == gen_0; } INLINE int dvdsi(long x, GEN y) { if (!signe(y)) return x == 0; if (lgefint(y) != 3) return 0; return x % y[2] == 0; } INLINE int dvdui(ulong x, GEN y) { if (!signe(y)) return x == 0; if (lgefint(y) != 3) return 0; return x % y[2] == 0; } INLINE int dvdis(GEN x, long y) { return y? smodis(x, y) == 0: signe(x) == 0; } INLINE int dvdiu(GEN x, ulong y) { return y? umodiu(x, y) == 0: signe(x) == 0; } INLINE int dvdisz(GEN x, long y, GEN z) { const pari_sp av = avma; long r; GEN p1 = divis_rem(x,y, &r); avma = av; if (r) return 0; affii(p1,z); return 1; } INLINE int dvdiuz(GEN x, ulong y, GEN z) { const pari_sp av = avma; ulong r; GEN p1 = diviu_rem(x,y, &r); avma = av; if (r) return 0; affii(p1,z); return 1; } INLINE int dvdiiz(GEN x, GEN y, GEN z) { const pari_sp av=avma; GEN p2; const GEN p1=dvmdii(x,y,&p2); if (signe(p2)) { avma=av; return 0; } affii(p1,z); avma=av; return 1; } /*******************************************************************/ /* */ /* MP (INT OR REAL) */ /* */ /*******************************************************************/ INLINE GEN mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); } INLINE GEN mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); } INLINE GEN mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); } INLINE GEN mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); } INLINE long mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); } INLINE GEN mpadd(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? addii(x,y) : addir(x,y); return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y); } INLINE GEN mpsub(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? subii(x,y) : subir(x,y); return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y); } INLINE GEN mpmul(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y); return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y); } INLINE GEN mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); } INLINE GEN mpdiv(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? divii(x,y) : divir(x,y); return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y); } /*******************************************************************/ /* */ /* Z/nZ, n ULONG */ /* */ /*******************************************************************/ INLINE ulong Fl_double(ulong a, ulong p) { ulong res = a << 1; return (res >= p || res < a) ? res - p : res; } INLINE ulong Fl_triple(ulong a, ulong p) { ulong res = a << 1; if (res >= p || res < a) res -= p; res += a; return (res >= p || res < a)? res - p: res; } INLINE ulong Fl_add(ulong a, ulong b, ulong p) { ulong res = a + b; return (res >= p || res < a) ? res - p : res; } INLINE ulong Fl_neg(ulong x, ulong p) { return x ? p - x: 0; } INLINE ulong Fl_sub(ulong a, ulong b, ulong p) { ulong res = a - b; return (res > a) ? res + p: res; } /* centerlift(u mod p) */ INLINE long Fl_center(ulong u, ulong p, ulong ps2) { return (long) (u > ps2)? u - p: u; } INLINE ulong Fl_mul(ulong a, ulong b, ulong p) { register ulong x; LOCAL_HIREMAINDER; x = mulll(a,b); if (!hiremainder) return x % p; (void)divll(x,p); return hiremainder; } INLINE ulong Fl_sqr(ulong a, ulong p) { register ulong x; LOCAL_HIREMAINDER; x = mulll(a,a); if (!hiremainder) return x % p; (void)divll(x,p); return hiremainder; } INLINE ulong Fl_div(ulong a, ulong b, ulong p) { return Fl_mul(a, Fl_inv(b, p), p); } /*******************************************************************/ /* */ /* DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY */ /* */ /*******************************************************************/ INLINE GEN addri(GEN x, GEN y) { return addir(y,x); } INLINE GEN addis(GEN x, long s) { return addsi(s,x); } INLINE GEN addiu(GEN x, ulong s) { return addui(s,x); } INLINE GEN addrs(GEN x, long s) { return addsr(s,x); } INLINE GEN subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; } INLINE GEN subis(GEN x, long y) { return addsi(-y,x); } INLINE GEN subrs(GEN x, long y) { return addsr(-y,x); } INLINE GEN mulis(GEN x, long s) { return mulsi(s,x); } INLINE GEN muliu(GEN x, ulong s) { return mului(s,x); } INLINE GEN mulru(GEN x, ulong s) { return mulur(s,x); } INLINE GEN mulri(GEN x, GEN s) { return mulir(s,x); } INLINE GEN mulrs(GEN x, long s) { return mulsr(s,x); } /*******************************************************************/ /* */ /* VALUATION, EXPONENT, SHIFTS */ /* */ /*******************************************************************/ INLINE long vali(GEN x) { long i; GEN xp; if (!signe(x)) return -1; xp=int_LSW(x); for (i=0; !*xp; i++) xp=int_nextW(xp); return vals(*xp) + i * BITS_IN_LONG; } /* assume x > 0 */ INLINE long expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); } INLINE long expi(GEN x) { const long lx=lgefint(x); return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1; } INLINE GEN shiftr(GEN x, long n) { const long e = evalexpo(expo(x)+n); const GEN y = rcopy(x); if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()"); y[1] = (y[1]&~EXPOBITS) | e; return y; } INLINE GEN mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); } /* FIXME: adapt/use mpn_[lr]shift instead */ /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits * (feeding f from the right). Assume sh > 0 */ INLINE void shift_left(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh) { GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax; ulong l, m = BITS_IN_LONG - sh, k = f >> m; while (se > sb) { l = *se--; *te-- = (l << sh) | k; k = l >> m; } *te = (*se << sh) | k; } /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits * (feeding f from the left). Assume sh > 0 */ INLINE void shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh) { GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin; ulong k, l = *sb++, m = BITS_IN_LONG - sh; *tb++ = (l >> sh) | (f << m); while (sb < se) { k = l << m; l = *sb++; *tb++ = (l >> sh) | k; } } /* Backward compatibility. Inefficient && unused */ extern ulong hiremainder; INLINE ulong shiftl(ulong x, ulong y) { hiremainder = x>>(BITS_IN_LONG-y); return (x<>y); } INLINE void shiftr_inplace(GEN z, long d) { setexpo(z, expo(z)+d); } /*******************************************************************/ /* */ /* ASSIGNMENT */ /* */ /*******************************************************************/ INLINE void affii(GEN x, GEN y) { long lx = lgefint(x); if (lg(y)t_INT assignment"); while (--lx) y[lx] = x[lx]; } INLINE void affsi(long s, GEN x) { if (!s) x[1] = evalsigne(0) | evallgefint(2); else { if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] = s; } else { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; } } } INLINE void affui(ulong u, GEN x) { if (!u) x[1] = evalsigne(0) | evallgefint(2); else { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; } } INLINE void affsr(long x, GEN y) { long sh, i, ly = lg(y); if (!x) { y[1] = evalexpo(-prec2nbits(ly)); return; } if (x < 0) { x = -x; sh = bfffo(x); y[1] = evalsigne(-1) | _evalexpo((BITS_IN_LONG-1)-sh); } else { sh = bfffo(x); y[1] = evalsigne(1) | _evalexpo((BITS_IN_LONG-1)-sh); } y[2] = x<=0, bmax>0 such that * 0 <= x < m; 2*amax*bmax < m * attempts to find t_INT a, b such that * (1) a = b*x (mod m) * (2) |a| <= amax, 0 < b <= bmax * (3) gcd(m, b) = gcd(a, b) * If unsuccessful, it will return 0 and leave a,b unchanged (and * caller may deduce no such a,b exist). If successful, sets a,b * and returns 1. If there exist a,b satisfying (1), (2), and * (3') gcd(m, b) = 1 * then they are uniquely determined subject to (1),(2) and * (3'') gcd(a, b) = 1, * and will be returned by the routine. (The caller may wish to * check gcd(a,b)==1, either directly or based on known prime * divisors of m, depending on the application.) * Reference: @article {MR97c:11116, AUTHOR = {Collins, George E. and Encarnaci{\'o}n, Mark J.}, TITLE = {Efficient rational number reconstruction}, JOURNAL = {J. Symbolic Comput.}, VOLUME = {20}, YEAR = {1995}, NUMBER = {3}, PAGES = {287--297}, } * Preprint available from: * ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1994/94-64.ps.gz */ /* #define DEBUG_RATLIFT */ static ulong get_vmax(GEN r, long lb, long lbb) { long lr = lb - lgefint(r); ulong vmax; if (lr > 1) /* still more than a word's worth to go */ vmax = ULONG_MAX; /* (cannot in fact happen) */ else { /* take difference of bit lengths */ long lbr = bfffo(*int_MSW(r)); lr = lr*BITS_IN_LONG - lbb + lbr; if ((ulong)lr > BITS_IN_LONG) vmax = ULONG_MAX; else if (lr == 0) vmax = 1UL; else vmax = 1UL << (lr-1); /* pessimistic but faster than a division */ } #ifdef DEBUG_RATLIFT err_printf("rl-fs: vmax=%lu\n", vmax); #endif return vmax; } /* Assume x,m,amax >= 0,bmax > 0 are t_INTs, 0 <= x < m, 2 amax * bmax < m */ 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; long lb, lbb, s, s0; ulong vmax; ulong xu, xu1, xv, xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ /* special cases x=0 and/or amax=0 */ if (!signe(x)) { *a = gen_0; *b = gen_1; return 1; } if (!signe(amax)) return 0; /* assert: m > x > 0, amax > 0 */ /* check whether a=x, b=1 is a solution */ if (cmpii(x,amax) <= 0) { *a = icopy(x); *b = gen_1; return 1; } /* There is no special case for single-word numbers since this is * mainly meant to be used with large moduli. */ (void)new_chunk(lgefint(bmax) + lgefint(amax)); /* room for a,b */ d = m; d1 = x; v = gen_0; v1 = gen_1; /* assert d1 > amax, v1 <= bmax here */ lb = lgefint(bmax); lbb = bfffo(*int_MSW(bmax)); s = 1; av1 = avma; lim = stack_lim(av, 1); /* General case: Euclidean division chain starting with m div x, and * with bounds on the sequence of convergents' denoms v_j. * Just to be different from what invmod and bezout are doing, we work * here with the all-nonnegative matrices [u,u1;v,v1]=prod_j([0,1;1,q_j]). * Loop invariants: * (a) (sign)*[-v,v1]*x = [d,d1] (mod m) (componentwise) * (sign initially +1, changes with each Euclidean step) * so [a,b] will be obtained in the form [-+d,v] or [+-d1,v1]; * this congruence is a consequence of * * (b) [x,m]~ = [u,u1;v,v1]*[d1,d]~, * where u,u1 is the usual numerator sequence starting with 1,0 * instead of 0,1 (just multiply the eqn on the left by the inverse * matrix, which is det*[v1,-u1;-v,u], where "det" is the same as the * "(sign)" in (a)). From m = v*d1 + v1*d and * * (c) d > d1 >= 0, 0 <= v < v1, * we have d >= m/(2*v1), so while v1 remains smaller than m/(2*amax), * the pair [-(sign)*d,v] satisfies (1) but violates (2) (d > amax). * Conversely, v1 > bmax indicates that no further solutions will be * forthcoming; [-(sign)*d,v] will be the last, and first, candidate. * Thus there's at most one point in the chain division where a solution * can live: v < bmax, v1 >= m/(2*amax) > bmax, and this is acceptable * iff in fact d <= amax (e.g. m=221, x=34 or 35, amax=bmax=10 fail on * this count while x=32,33,36,37 succeed). However, a division may leave * a zero residue before we ever reach this point (consider m=210, x=35, * amax=bmax=10), and our caller may find that gcd(d,v) > 1 (Examples: * keep m=210 and consider any of x=29,31,32,33,34,36,37,38,39,40,41). * Furthermore, at the start of the loop body we have in fact * * (c') 0 <= v < v1 <= bmax, d > d1 > amax >= 0, * (and are never done already). * * Main loop is similar to those of invmod() and bezout(), except for * having to determine appropriate vmax bounds, and checking termination * conditions. The signe(d1) condition is only for paranoia */ while (lgefint(d) > 3 && signe(d1)) { /* determine vmax for lgcdii so as to ensure v won't overshoot. * If v+v1 > bmax, the next step would take v1 beyond the limit, so * since [+-d1,v1] is not a solution, we give up. Otherwise if v+v1 * is way shorter than bmax, use vmax=MAXULUNG. Otherwise, set vmax * to a crude lower approximation of bmax/(v+v1), or to 1, which will * allow the inner loop to do one step */ r = addii(v,v1); if (cmpii(r,bmax) > 0) { avma = av; return 0; } /* done, not found */ vmax = get_vmax(r, lb, lbb); /* do a Lehmer-Jebelean round */ lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, vmax); if (lhmres) /* check progress */ { /* apply matrix */ if (lhmres == 1 || lhmres == -1) { s = -s; if (xv1 == 1) { /* re-use v+v1 computed above */ v = v1; v1 = r; r = subii(d,d1); d = d1; d1 = r; } else { r = subii(d, mului(xv1,d1)); d = d1; d1 = r; r = addii(v, mului(xv1,v1)); v = v1; v1 = r; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; r = addii(muliu(v,xu), muliu(v1,xv)); v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r; if (lhmres&1) { togglesign(d); s = -s; } else togglesign(d1); } /* check whether we're done. Assert v <= bmax here. Examine v1: * if v1 > bmax, check d and return 0 or 1 depending on the outcome; * if v1 <= bmax, check d1 and return 1 if d1 <= amax, otherwise proceed*/ if (cmpii(v1,bmax) > 0) { avma = av; if (cmpii(d,amax) > 0) return 0; /* done, not found */ /* done, found */ *a = icopy(d); setsigne(*a,-s); *b = icopy(v); return 1; } if (cmpii(d1,amax) <= 0) { /* done, found */ avma = av; if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0; *b = icopy(v1); return 1; } } /* lhmres != 0 */ if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); #ifdef DEBUG_LEHMER err_printf("Full division:\n q = %Ps\n", q); #endif d = d1; d1 = r; r = addii(v, mulii(q,v1)); v = v1; v1 = r; s = -s; /* check whether we are done now. Since we weren't before the div, it * suffices to examine v1 and d1 -- the new d (former d1) cannot cut it */ if (cmpii(v1,bmax) > 0) { avma = av; return 0; } /* done, not found */ if (cmpii(d1,amax) <= 0) /* done, found */ { avma = av; if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0; *b = icopy(v1); return 1; } } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ratlift"); gerepileall(av1, 4, &d, &d1, &v, &v1); } } /* end while */ /* Postprocessing - final sprint. Since we usually underestimate vmax, * this function needs a loop here instead of a simple conditional. * Note we can only get here when amax fits into one word (which will * typically not be the case!). The condition is bogus -- d1 is never * zero at the start of the loop. There will be at most a few iterations, * so we don't bother collecting garbage */ while (signe(d1)) { /* Assertions: lgefint(d)==lgefint(d1)==3. * Moreover, we aren't done already, or we would have returned by now. * Recompute vmax */ #ifdef DEBUG_RATLIFT err_printf("rl-fs: d,d1=%Ps,%Ps\n", d, d1); err_printf("rl-fs: v,v1=%Ps,%Ps\n", v, v1); #endif r = addii(v,v1); if (cmpii(r,bmax) > 0) { avma = av; return 0; } /* done, not found */ vmax = get_vmax(r, lb, lbb); /* single-word "Lehmer", discarding the gcd or whatever it returns */ (void)rgcduu((ulong)*int_MSW(d), (ulong)*int_MSW(d1), vmax, &xu, &xu1, &xv, &xv1, &s0); #ifdef DEBUG_RATLIFT err_printf("rl-fs: [%lu,%lu; %lu,%lu] %s\n", xu, xu1, xv, xv1, s0 < 0 ? "-" : "+"); #endif if (xv1 == 1) /* avoid multiplications */ { /* re-use r = v+v1 computed above */ v = v1; v1 = r; r = subii(d,d1); d = d1; d1 = r; s = -s; } else if (xu == 0) /* and xv==1, xu1==1, xv1 > 1 */ { r = subii(d, mului(xv1,d1)); d = d1; d1 = r; r = addii(v, mului(xv1,v1)); v = v1; v1 = r; s = -s; } else { r = subii(muliu(d,xu), muliu(d1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; r = addii(muliu(v,xu), muliu(v1,xv)); v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r; if (s0 < 0) { togglesign(d); s = -s; } else togglesign(d1); } /* check whether we're done, as above. Assert v <= bmax. * if v1 > bmax, check d and return 0 or 1 depending on the outcome; * if v1 <= bmax, check d1 and return 1 if d1 <= amax, otherwise proceed. */ if (cmpii(v1,bmax) > 0) { avma = av; if (cmpii(d,amax) > 0) return 0; /* done, not found */ /* done, found */ *a = icopy(d); setsigne(*a,-s); *b = icopy(v); return 1; } if (cmpii(d1,amax) <= 0) { /* done, found */ avma = av; if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0; *b = icopy(v1); return 1; } } /* while */ /* We have run into d1 == 0 before returning. This cannot happen */ pari_err_BUG("ratlift failed to catch d1 == 0"); return 0; /* NOTREACHED */ } pari-2.7.5/src/kernel/none/mp.c0000644000175000017500000015011112413013143014663 0ustar billbill#line 2 "../src/kernel/none/mp.c" /* Copyright (C) 2000-2003 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. */ /***********************************************************************/ /** **/ /** MULTIPRECISION KERNEL **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #include "../src/kernel/none/tune-gen.h" void pari_kernel_init(void) { } void pari_kernel_close(void) { } /* NOTE: arguments of "spec" routines (muliispec, addiispec, etc.) aren't * GENs but pairs (long *a, long na) representing a list of digits (in basis * BITS_IN_LONG) : a[0], ..., a[na-1]. [ In ordre to facilitate splitting: no * need to reintroduce codewords ] */ #define LIMBS(x) ((x)+2) #define NLIMBS(x) (lgefint(x)-2) /* Normalize a non-negative integer */ GEN int_normalize(GEN x, long known_zero_words) { long i, lx = lgefint(x); GEN x0; if (lx == 2) { x[1] = evalsigne(0) | evallgefint(2); return x; } if (!known_zero_words && x[2]) return x; for (i = 2+known_zero_words; i < lx; i++) if (x[i]) break; x0 = x; i -= 2; x += i; if (x0 == (GEN)avma) avma = (pari_sp)x; else stackdummy((pari_sp)(x0+i), (pari_sp)x0); lx -= i; x[0] = evaltyp(t_INT) | evallg(lx); if (lx == 2) x[1] = evalsigne(0) | evallgefint(lx); else x[1] = evalsigne(1) | evallgefint(lx); return x; } /***********************************************************************/ /** **/ /** ADDITION / SUBTRACTION **/ /** **/ /***********************************************************************/ GEN setloop(GEN a) { pari_sp av = avma; (void)cgetg(lgefint(a) + 3, t_VECSMALL); return icopy_avma(a, av); /* two cells of extra space before a */ } /* we had a = setloop(?), then some incloops. Reset a to b */ GEN resetloop(GEN a, GEN b) { long lb = lgefint(b); a += lgefint(a) - lb; a[0] = evaltyp(t_INT) | evallg(lb); affii(b, a); return a; } /* assume a > 0, initialized by setloop. Do a++ */ static GEN incpos(GEN a) { long i, l = lgefint(a); for (i=l-1; i>1; i--) if (++a[i]) return a; l++; a--; /* use extra cell */ a[0]=evaltyp(t_INT) | _evallg(l); a[1]=evalsigne(1) | evallgefint(l); a[2]=1; return a; } /* assume a < 0, initialized by setloop. Do a++ */ static GEN incneg(GEN a) { long i, l = lgefint(a)-1; if (a[l]--) { if (l == 2 && !a[2]) { a++; /* save one cell */ a[0] = evaltyp(t_INT) | _evallg(2); a[1] = evalsigne(0) | evallgefint(2); } return a; } for (i = l-1;; i--) /* finishes since a[2] != 0 */ if (a[i]--) break; if (!a[2]) { a++; /* save one cell */ a[0] = evaltyp(t_INT) | _evallg(l); a[1] = evalsigne(-1) | evallgefint(l); } return a; } /* assume a initialized by setloop. Do a++ */ GEN incloop(GEN a) { switch(signe(a)) { case 0: a--; /* use extra cell */ a[0]=evaltyp(t_INT) | _evallg(3); a[1]=evalsigne(1) | evallgefint(3); a[2]=1; return a; case -1: return incneg(a); default: return incpos(a); } } INLINE GEN adduispec(ulong s, GEN x, long nx) { GEN xd, zd = (GEN)avma; long lz; if (nx == 1) return adduu(s, (ulong)x[0]); lz = nx+3; (void)new_chunk(lz); xd = x + nx; *--zd = (ulong)*--xd + s; if ((ulong)*zd < s) for(;;) { if (xd == x) { *--zd = 1; break; } /* enlarge z */ *--zd = ((ulong)*--xd) + 1; if (*zd) { lz--; break; } } else lz--; while (xd > x) *--zd = *--xd; *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } GEN adduispec_offset(ulong s, GEN x, long offset, long nx) { GEN xd = x+lgefint(x)-nx-offset; while (nx && *xd==0) {xd++; nx--;} if (!nx) return utoi(s); return adduispec(s,xd,nx); } static GEN addiispec(GEN x, GEN y, long nx, long ny) { GEN xd, yd, zd; long lz, i = -2; LOCAL_OVERFLOW; if (nx < ny) swapspec(x,y, nx,ny); if (ny == 1) return adduispec(*y,x,nx); zd = (GEN)avma; lz = nx+3; (void)new_chunk(lz); xd = x + nx; yd = y + ny; zd[-1] = addll(xd[-1], yd[-1]); #ifdef addllx8 for ( ; i-8 > -ny; i-=8) addllx8(xd+i, yd+i, zd+i, overflow); #endif for ( ; i >= -ny; i--) zd[i] = addllx(xd[i], yd[i]); if (overflow) for(;;) { if (i < -nx) { zd[i] = 1; i--; break; } /* enlarge z */ zd[i] = (ulong)xd[i] + 1; if (zd[i]) { i--; lz--; break; } i--; } else lz--; for (; i >= -nx; i--) zd[i] = xd[i]; zd += i+1; *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } /* assume x >= s */ INLINE GEN subiuspec(GEN x, ulong s, long nx) { GEN xd, zd = (GEN)avma; long lz; LOCAL_OVERFLOW; if (nx == 1) return utoi(x[0] - s); lz = nx+2; (void)new_chunk(lz); xd = x + nx; *--zd = subll(*--xd, s); if (overflow) for(;;) { *--zd = ((ulong)*--xd) - 1; if (*xd) break; } if (xd == x) while (*zd == 0) { zd++; lz--; } /* shorten z */ else do *--zd = *--xd; while (xd > x); *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } /* assume x > y */ static GEN subiispec(GEN x, GEN y, long nx, long ny) { GEN xd,yd,zd; long lz, i = -2; LOCAL_OVERFLOW; if (ny==1) return subiuspec(x,*y,nx); zd = (GEN)avma; lz = nx+2; (void)new_chunk(lz); xd = x + nx; yd = y + ny; zd[-1] = subll(xd[-1], yd[-1]); #ifdef subllx8 for ( ; i-8 > -ny; i-=8) subllx8(xd+i, yd+i, zd+i, overflow); #endif for ( ; i >= -ny; i--) zd[i] = subllx(xd[i], yd[i]); if (overflow) for(;;) { zd[i] = ((ulong)xd[i]) - 1; if (xd[i--]) break; } if (i>=-nx) for (; i >= -nx; i--) zd[i] = xd[i]; else while (zd[i+1] == 0) { i++; lz--; } /* shorten z */ zd += i+1; *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } static void roundr_up_ip(GEN x, long l) { long i = l; for(;;) { if (++((ulong*)x)[--i]) break; if (i == 2) { x[2] = (long)HIGHBIT; shiftr_inplace(x, 1); break; } } } void affir(GEN x, GEN y) { const long s = signe(x), ly = lg(y); long lx, sh, i; if (!s) { y[1] = evalexpo(-bit_accuracy(ly)); return; } lx = lgefint(x); sh = bfffo(x[2]); y[1] = evalsigne(s) | evalexpo(bit_accuracy(lx)-sh-1); if (sh) { if (lx <= ly) { for (i=lx; i ly: round properly */ if ((x[ly]< ly: round properly */ if (x[ly] & HIGHBIT) roundr_up_ip(y, ly); } } INLINE GEN shiftispec(GEN x, long nx, long n) { long ny, i, m; GEN y, yd; if (!n) return icopyspec(x, nx); if (n > 0) { GEN z = (GEN)avma; long d = dvmdsBIL(n, &m); ny = nx+d; y = new_chunk(ny + 2); yd = y + 2; for ( ; d; d--) *--z = 0; if (!m) for (i=0; i> sh; /* Extend y on the left? */ if (i) { ny++; y = new_chunk(1); y[2] = i; } } } else { ny = nx - dvmdsBIL(-n, &m); if (ny<1) return gen_0; y = new_chunk(ny + 2); yd = y + 2; if (m) { shift_right(yd,x, 0,ny, 0,m); if (yd[0] == 0) { if (ny==1) { avma = (pari_sp)(y+3); return gen_0; } ny--; avma = (pari_sp)(++y); } } else { for (i=0; i lg(x)) pari_err_PREC( "truncr (precision loss in truncation)"); y=cgeti(d); y[1] = evalsigne(s) | evallgefint(d); if (++m == BITS_IN_LONG) for (i=2; i= 0) return truncr(x); if ((e=expo(x)) < 0) return gen_m1; d = nbits2prec(e+1); m = remsBIL(e); lx=lg(x); if (d>lx) pari_err_PREC( "floorr (precision loss in truncation)"); y = new_chunk(d); if (++m == BITS_IN_LONG) { for (i=2; i=2; i--) { y[i]++; if (y[i]) goto END; } y=new_chunk(1); y[2]=1; d++; END: y[1] = evalsigne(-1) | evallgefint(d); y[0] = evaltyp(t_INT) | evallg(d); return y; } INLINE int cmpiispec(GEN x, GEN y, long lx, long ly) { long i; if (lx < ly) return -1; if (lx > ly) return 1; i = 0; while (i (ulong)y[i])? 1: -1; } INLINE int equaliispec(GEN x, GEN y, long lx, long ly) { long i; if (lx != ly) return 0; i = ly-1; while (i>=0 && x[i]==y[i]) i--; return i < 0; } /***********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /***********************************************************************/ /* assume ny > 0 */ INLINE GEN muluispec(ulong x, GEN y, long ny) { GEN yd, z = (GEN)avma; long lz = ny+3; LOCAL_HIREMAINDER; (void)new_chunk(lz); yd = y + ny; *--z = mulll(x, *--yd); while (yd > y) *--z = addmul(x,*--yd); if (hiremainder) *--z = hiremainder; else lz--; *--z = evalsigne(1) | evallgefint(lz); *--z = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)z; return z; } /* a + b*|Y| */ GEN addumului(ulong a, ulong b, GEN Y) { GEN yd,y,z; long ny,lz; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (!signe(Y)) return utoi(a); y = LIMBS(Y); z = (GEN)avma; ny = NLIMBS(Y); lz = ny+3; (void)new_chunk(lz); yd = y + ny; *--z = addll(a, mulll(b, *--yd)); if (overflow) hiremainder++; /* can't overflow */ while (yd > y) *--z = addmul(b,*--yd); if (hiremainder) *--z = hiremainder; else lz--; *--z = evalsigne(1) | evallgefint(lz); *--z = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)z; return z; } /***********************************************************************/ /** **/ /** DIVISION **/ /** **/ /***********************************************************************/ ulong umodiu(GEN y, ulong x) { long sy=signe(y),ly,i; LOCAL_HIREMAINDER; if (!x) pari_err_INV("umodiu",gen_0); if (!sy) return 0; ly = lgefint(y); if (x <= (ulong)y[2]) hiremainder=0; else { if (ly==3) return (sy > 0)? (ulong)y[2]: x - (ulong)y[2]; hiremainder=y[2]; ly--; y++; } for (i=2; i 0)? hiremainder: x - hiremainder; } /* return |y| \/ x */ GEN diviu_rem(GEN y, ulong x, ulong *rem) { long ly,i; GEN z; 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; else { if (ly==3) { *rem = (ulong)y[2]; return gen_0; } hiremainder=y[2]; ly--; y++; } z = cgetipos(ly); for (i=2; i3)? x[3]: 0; LOCAL_HIREMAINDER; if (k < (ulong)y[2]) e--; else { l >>= 1; if (k&1) l |= HIGHBIT; k >>= 1; } hiremainder = k; k = divll(l,y[2]); if (hiremainder & HIGHBIT) { k++; if (!k) { k = HIGHBIT; e++; } } r = cgetr(3); r[1] = evalsigne(sx) | evalexpo(e); r[2] = k; return r; } lr = minss(lx,ly); r = new_chunk(lr); r1 = r-1; r1[1] = 0; for (i=2; ily)? x[lr]: 0; y0 = y[2]; y1 = y[3]; for (i=0; i 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]); } hiremainder = r1[1]; overflow = 0; qp = divll(r1[2],y0); k = hiremainder; } j = lr-i+1; if (!overflow) { long k3, k4; k3 = mulll(qp,y1); if (j == 3) /* i = lr - 2 maximal, r1[3] undefined -> 0 */ k4 = subll(hiremainder,k); else { k3 = subll(k3, r1[3]); k4 = subllx(hiremainder,k); } while (!overflow && k4) { qp--; k3 = subll(k3,y1); k4 = subllx(k4,y0); } } if (j1; j--) { r1[j] = subll(r1[j], addmul(qp,y[j])); hiremainder += overflow; } if ((ulong)r1[1] != hiremainder) { if ((ulong)r1[1] < hiremainder) { qp--; j = lr-i-(lr-i>=ly); r1[j] = addll(r1[j], y[j]); for (j--; j>1; j--) r1[j] = addllx(r1[j], y[j]); } else { r1[1] -= hiremainder; while (r1[1]) { qp++; if (!qp) { j=i; do ((ulong*)r)[--j]++; while (j && !r[j]); } j = lr-i-(lr-i>=ly); r1[j] = subll(r1[j],y[j]); for (j--; j>1; j--) r1[j] = subllx(r1[j],y[j]); r1[1] -= overflow; } } } *++r1 = qp; } /* i = lr-1 */ /* round correctly */ if ((ulong)r1[1] > (y0>>1)) { j=i; do ((ulong*)r)[--j]++; while (j && !r[j]); } r1 = r-1; for (j=i; j>=2; j--) r[j]=r1[j]; if (r[0] == 0) e--; else if (r[0] == 1) { shift_right(r,r, 2,lr, 1,1); } else { /* possible only when rounding up to 0x2 0x0 ... */ r[2] = (long)HIGHBIT; e++; } r[0] = evaltyp(t_REAL)|evallg(lr); r[1] = evalsigne(sx) | evalexpo(e); return r; } GEN divri(GEN x, GEN y) { long lx, s = signe(y); pari_sp av; GEN z; if (!s) pari_err_INV("divri",y); if (!signe(x)) return real_0_bit(expo(x) - expi(y)); if (!is_bigint(y)) { GEN z = divru(x, y[2]); if (s < 0) togglesign(z); return z; } lx = lg(x); z = cgetr(lx); av = avma; affrr(divrr(x, itor(y, lx+1)), z); avma = av; return z; } /* Integer division x / y: such that sign(r) = sign(x) * if z = ONLY_REM return remainder, otherwise return quotient * if z != NULL set *z to remainder * *z is the last object on stack (and thus can be disposed of with cgiv * instead of gerepile) * If *z is zero, we put gen_0 here and no copy. * space needed: lx + ly */ GEN dvmdii(GEN x, GEN y, GEN *z) { long sx=signe(x),sy=signe(y); long lx, ly, lz, i, j, sh, lq, lr; pari_sp av; ulong y0,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 (!z || z == ONLY_REM) return gen_0; *z=gen_0; return gen_0; } lx=lgefint(x); ly=lgefint(y); lz=lx-ly; if (lz <= 0) { if (lz == 0) { for (i=2; i (ulong)y[i]) goto DIVIDE; goto TRIVIAL; } if (z == ONLY_REM) return gen_0; if (z) *z = gen_0; if (sx < 0) sy = -sy; return stoi(sy); } TRIVIAL: if (z == ONLY_REM) return icopy(x); if (z) *z = icopy(x); return gen_0; } 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> m; } else { r1[1] = 0; for (j=2; j1; j--) { r1[j] = subll(r1[j], addmul(qp,y[j])); hiremainder += overflow; } if ((ulong)r1[1] < hiremainder) { qp--; j = ly-1; r1[j] = addll(r1[j],y[j]); for (j--; j>1; j--) r1[j] = addllx(r1[j],y[j]); } *++r1 = qp; } lq = lz+2; if (!z) { qd = (ulong*)av; xd = (ulong*)(x + lq); if (x[1]) { lz++; lq++; } while (lz--) *--qd = *--xd; *--qd = evalsigne(sy) | evallgefint(lq); *--qd = evaltyp(t_INT) | evallg(lq); avma = (pari_sp)qd; return (GEN)qd; } j=lq; while (j> sh; *--rd = l | (*--xd << shl); } l = *xd >> sh; if (l) *--rd = l; else lr--; } *--rd = evalsigne(sx) | evallgefint(lr); *--rd = evaltyp(t_INT) | evallg(lr); avma = (pari_sp)rd; return (GEN)rd; } lr = lz+2; rd = NULL; /* gcc -Wall */ if (lz) { /* non zero remainder: initialize rd */ xd = (ulong*)(x + lx); if (!sh) { rd = (ulong*)avma; (void)new_chunk(lr); while (lz--) *--rd = *--xd; } else { /* shift remainder right by sh bits */ const ulong shl = BITS_IN_LONG - sh; ulong l; rd = (ulong*)x; /* overwrite shifted y */ xd--; while (--lz) { l = *xd >> sh; *--rd = l | (*--xd << shl); } l = *xd >> sh; if (l) *--rd = l; else lr--; } *--rd = evalsigne(sx) | evallgefint(lr); *--rd = evaltyp(t_INT) | evallg(lr); rd += lr; } qd = (ulong*)av; xd = (ulong*)(x + lq); if (x[1]) lq++; j = lq-2; while (j--) *--qd = *--xd; *--qd = evalsigne(sy) | evallgefint(lq); *--qd = evaltyp(t_INT) | evallg(lq); q = (GEN)qd; if (lr==2) *z = gen_0; else { /* rd has been properly initialized: we had lz > 0 */ while (lr--) *--qd = *--rd; *z = (GEN)qd; } avma = (pari_sp)qd; return q; } /* Montgomery reduction. * N has k words, assume T >= 0 has less than 2k. * Return res := T / B^k mod N, where B = 2^BIL * such that 0 <= res < T/B^k + N and res has less than k words */ GEN red_montgomery(GEN T, GEN N, ulong inv) { pari_sp av; GEN Te, Td, Ne, Nd, scratch; ulong i, j, m, t, d, k = NLIMBS(N); int carry; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (k == 0) return gen_0; d = NLIMBS(T); /* <= 2*k */ if (d == 0) return gen_0; #ifdef DEBUG if (d > 2*k) pari_err_BUG("red_montgomery"); #endif if (k == 1) { /* as below, special cased for efficiency */ ulong n = (ulong)N[2]; if (d == 1) { hiremainder = (ulong)T[2]; m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ return utoi(hiremainder); } else { /* d = 2 */ hiremainder = (ulong)T[3]; m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ t = addll(hiremainder, (ulong)T[2]); if (overflow) t -= n; /* t > n doesn't fit in 1 word */ return utoi(t); } } /* assume k >= 2 */ av = avma; scratch = new_chunk(k<<1); /* >= k + 2: result fits */ /* copy T to scratch space (pad with zeroes to 2k words) */ Td = (GEN)av; Te = T + (d+2); for (i=0; i < d ; i++) *--Td = *--Te; for ( ; i < (k<<1); i++) *--Td = 0; Te = (GEN)av; /* 1 beyond end of current T mantissa (in scratch) */ Ne = N + k+2; /* 1 beyond end of N mantissa */ carry = 0; for (i=0; i N overflows (k+1 words), set Td := Td - N */ Td = Te; Nd = Ne; t = subll(*--Td, *--Nd); *Td = t; while (Td > scratch) { t = subllx(*--Td, *--Nd); *Td = t; } } /* copy result */ Td = (GEN)av; while (*scratch == 0 && Te > scratch) scratch++; /* strip leading 0s */ while (Te > scratch) *--Td = *--Te; k = (GEN)av - Td; if (!k) { avma = av; return gen_0; } k += 2; *--Td = evalsigne(1) | evallgefint(k); *--Td = evaltyp(t_INT) | evallg(k); #ifdef DEBUG { long l = NLIMBS(N), s = BITS_IN_LONG*l; GEN R = int2n(s); GEN res = remii(mulii(T, Fp_inv(R, N)), N); if (k > lgefint(N) || !equalii(remii(Td,N),res) || cmpii(Td, addii(shifti(T, -s), N)) >= 0) pari_err_BUG("red_montgomery"); } #endif avma = (pari_sp)Td; return Td; } /* EXACT INTEGER DIVISION */ /* assume xy>0, the division is exact and y is odd. Destroy x */ static GEN diviuexact_i(GEN x, ulong y) { long i, lz, lx; ulong q, yinv; GEN z, z0, x0, x0min; if (y == 1) return icopy(x); lx = lgefint(x); if (lx == 3) return utoipos((ulong)x[2] / y); yinv = invmod2BIL(y); lz = (y <= (ulong)x[2]) ? lx : lx-1; z = new_chunk(lz); z0 = z + lz; x0 = x + lx; x0min = x + lx-lz+2; while (x0 > x0min) { *--z0 = q = yinv*((ulong)*--x0); /* i-th quotient */ if (!q) continue; /* x := x - q * y */ { /* update neither lowest word (could set it to 0) nor highest ones */ register GEN x1 = x0 - 1; LOCAL_HIREMAINDER; (void)mulll(q,y); if (hiremainder) { if ((ulong)*x1 < hiremainder) { *x1 -= hiremainder; do (*--x1)--; while ((ulong)*x1 == ULONG_MAX); } else *x1 -= hiremainder; } } } i=2; while(!z[i]) i++; z += i-2; lz -= i-2; z[0] = evaltyp(t_INT)|evallg(lz); z[1] = evalsigne(1)|evallg(lz); avma = (pari_sp)z; return z; } /* assume y != 0 and the division is exact */ GEN diviuexact(GEN x, ulong y) { pari_sp av; long lx, vy, s = signe(x); GEN z; if (!s) return gen_0; if (y == 1) return icopy(x); lx = lgefint(x); if (lx == 3) { ulong q = (ulong)x[2] / y; return (s > 0)? utoipos(q): utoineg(q); } av = avma; (void)new_chunk(lx); vy = vals(y); if (vy) { y >>= vy; if (y == 1) { avma = av; return shifti(x, -vy); } x = shifti(x, -vy); if (lx == 3) { ulong q = (ulong)x[2] / y; avma = av; return (s > 0)? utoipos(q): utoineg(q); } } else x = icopy(x); avma = av; z = diviuexact_i(x, y); setsigne(z, s); return z; } /* Find z such that x=y*z, knowing that y | x (unchecked) * Method: y0 z0 = x0 mod B = 2^BITS_IN_LONG ==> z0 = 1/y0 mod B. * Set x := (x - z0 y) / B, updating only relevant words, and repeat */ GEN diviiexact(GEN x, GEN y) { long lx, ly, lz, vy, i, ii, sx = signe(x), sy = signe(y); pari_sp av; ulong y0inv,q; GEN z; if (!sy) pari_err_INV("diviiexact",gen_0); if (!sx) return gen_0; lx = lgefint(x); if (lx == 3) { q = (ulong)x[2] / (ulong)y[2]; return (sx+sy) ? utoipos(q): utoineg(q); } vy = vali(y); av = avma; (void)new_chunk(lx); /* enough room for z */ if (vy) { /* make y odd */ y = shifti(y,-vy); x = shifti(x,-vy); lx = lgefint(x); } else x = icopy(x); /* necessary because we destroy x */ avma = av; /* will erase our x,y when exiting */ /* now y is odd */ ly = lgefint(y); if (ly == 3) { x = diviuexact_i(x,(ulong)y[2]); /* x != 0 */ setsigne(x, (sx+sy)? 1: -1); return x; } y0inv = invmod2BIL(y[ly-1]); i=2; while (i=2; i--,ii--) { long limj; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; z[i] = q = y0inv*((ulong)x[ii]); /* i-th quotient */ if (!q) continue; /* x := x - q * y */ (void)mulll(q,y[0]); limj = maxss(lx - lz, ii+3-ly); { /* update neither lowest word (could set it to 0) nor highest ones */ register GEN x0 = x + (ii - 1), y0 = y - 1, xlim = x + limj; for (; x0 >= xlim; x0--, y0--) { *x0 = subll(*x0, addmul(q,*y0)); hiremainder += overflow; } if (hiremainder && limj != lx - lz) { if ((ulong)*x0 < hiremainder) { *x0 -= hiremainder; do (*--x0)--; while ((ulong)*x0 == ULONG_MAX); } else *x0 -= hiremainder; } } } i=2; while(!z[i]) i++; z += i-2; lz -= (i-2); z[0] = evaltyp(t_INT)|evallg(lz); z[1] = evalsigne((sx+sy)? 1: -1) | evallg(lz); avma = (pari_sp)z; return z; } /* assume yz != and yz | x */ GEN diviuuexact(GEN x, ulong y, ulong z) { long tmp[4]; ulong t; LOCAL_HIREMAINDER; t = mulll(y, z); if (!hiremainder) return diviuexact(x, t); tmp[0] = evaltyp(t_INT)|_evallg(4); tmp[1] = evalsigne(1)|evallgefint(4); tmp[2] = hiremainder; tmp[3] = t; return diviiexact(x, tmp); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION (BASECASE) **/ /** **/ /********************************************************************/ /* nx >= ny = num. of digits of x, y (not GEN, see mulii) */ INLINE GEN muliispec_basecase(GEN x, GEN y, long nx, long ny) { GEN z2e,z2d,yd,xd,ye,zd; long p1,lz; LOCAL_HIREMAINDER; if (ny == 1) return muluispec((ulong)*y, x, nx); if (ny == 0) return gen_0; zd = (GEN)avma; lz = nx+ny+2; (void)new_chunk(lz); xd = x + nx; yd = y + ny; ye = yd; p1 = *--xd; *--zd = mulll(p1, *--yd); z2e = zd; while (yd > y) *--zd = addmul(p1, *--yd); *--zd = hiremainder; while (xd > x) { LOCAL_OVERFLOW; yd = ye; p1 = *--xd; z2d = --z2e; *z2d = addll(mulll(p1, *--yd), *z2d); z2d--; while (yd > y) { hiremainder += overflow; *z2d = addll(addmul(p1, *--yd), *z2d); z2d--; } *--zd = hiremainder + overflow; } if (*zd == 0) { zd++; lz--; } /* normalize */ *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } INLINE GEN sqrispec_basecase(GEN x, long nx) { GEN z2e,z2d,yd,xd,zd,x0,z0; long p1,lz; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (nx == 1) return sqru((ulong)*x); if (nx == 0) return gen_0; zd = (GEN)avma; lz = (nx+1) << 1; z0 = new_chunk(lz); if (nx == 1) { *--zd = mulll(*x, *x); *--zd = hiremainder; goto END; } xd = x + nx; /* compute double products --> zd */ p1 = *--xd; yd = xd; --zd; *--zd = mulll(p1, *--yd); z2e = zd; while (yd > x) *--zd = addmul(p1, *--yd); *--zd = hiremainder; x0 = x+1; while (xd > x0) { LOCAL_OVERFLOW; p1 = *--xd; yd = xd; z2e -= 2; z2d = z2e; *z2d = addll(mulll(p1, *--yd), *z2d); z2d--; while (yd > x) { hiremainder += overflow; *z2d = addll(addmul(p1, *--yd), *z2d); z2d--; } *--zd = hiremainder + overflow; } /* multiply zd by 2 (put result in zd - 1) */ zd[-1] = ((*zd & HIGHBIT) != 0); shift_left(zd, zd, 0, (nx<<1)-3, 0, 1); /* add the squares */ xd = x + nx; zd = z0 + lz; p1 = *--xd; zd--; *zd = mulll(p1,p1); zd--; *zd = addll(hiremainder, *zd); while (xd > x) { p1 = *--xd; zd--; *zd = addll(mulll(p1,p1)+ overflow, *zd); zd--; *zd = addll(hiremainder + overflow, *zd); } END: if (*zd == 0) { zd++; lz--; } /* normalize */ *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); avma=(pari_sp)zd; return zd; } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION (FFT) **/ /** **/ /********************************************************************/ /* Compute parameters for FFT: len: result length k: FFT depth. n: number of blocks (2^k) bs: block size mod: Modulus is M=2^(BIL*mod)+1 ord: order of 2 in Z/MZ. We must have: bs*n >= l 2^(BIL*mod) > nb*2^(2*BIL*bs) 2^k | 2*BIL*mod */ static void mulliifft_params(long len, long *k, long *mod, long *bs, long *n, ulong *ord) { long r; *k = expu((3*len)>>2)-3; do { (*k)--; r = *k-(TWOPOTBITS_IN_LONG+2); *n = 1L<<*k; *bs = (len+*n-1)>>*k; *mod= 2**bs+1; if (r>0) *mod=((*mod+(1L<>r)<=3**bs); *ord= 4**mod*BITS_IN_LONG; } /* Zf_: arithmetic in ring Z/MZ where M= 2^(BITS_IN_LONG*mod)+1 * for some mod. * Do not garbage collect. */ static GEN Zf_add(GEN a, GEN b, GEN M) { GEN y, z = addii(a,b); long mod = lgefint(M)-3; long l = NLIMBS(z); if (l<=mod) return z; y = subis(z, 1); if (NLIMBS(y)<=mod) return z; return int_normalize(y,1); } static GEN Zf_sub(GEN a, GEN b, GEN M) { GEN z = subii(a,b); return signe(z)>=0? z: addii(M,z); } /* destroy z */ static GEN Zf_red_destroy(GEN z, GEN M) { long mod = lgefint(M)-3; long l = NLIMBS(z); GEN y; if (l<=mod) return z; y = shifti(z, -mod*BITS_IN_LONG); z = int_normalize(z, NLIMBS(y)); y = Zf_red_destroy(y, M); z = subii(z, y); if (signe(z)<0) z = addii(z, M); return z; } INLINE GEN Zf_shift(GEN a, ulong s, GEN M) { return Zf_red_destroy(shifti(a, s), M); } /* Multiply by sqrt(2)^s We use the formula sqrt(2)=z_8*(1-z_4)) && z_8=2^(ord/16) [2^(ord/4)+1] */ static GEN Zf_mulsqrt2(GEN a, ulong s, ulong ord, GEN M) { ulong hord = ord>>1; if (!signe(a)) return gen_0; if (odd(s)) /* Multiply by 2^(s/2) */ { GEN az8 = Zf_shift(a, ord>>4, M); GEN az83 = Zf_shift(az8, ord>>3, M); a = Zf_sub(az8, az83, M); s--; } if (s < hord) return Zf_shift(a, s>>1, M); else return subii(M,Zf_shift(a, (s-hord)>>1, M)); } INLINE GEN Zf_sqr(GEN a, GEN M) { return Zf_red_destroy(sqri(a), M); } INLINE GEN Zf_mul(GEN a, GEN b, GEN M) { return Zf_red_destroy(mulii(a,b), M); } /* In place, bit reversing FFT */ static void muliifft_dit(ulong o, ulong ord, GEN M, GEN FFT, long d, long step) { pari_sp av = avma; long i; ulong j, no = (o<<1)%ord; long hstep=step>>1; for (i = d+1, j = 0; i <= d+hstep; ++i, j =(j+o)%ord) { GEN a = Zf_add(gel(FFT,i), gel(FFT,i+hstep), M); GEN b = Zf_mulsqrt2(Zf_sub(gel(FFT,i), gel(FFT,i+hstep), M), j, ord, M); affii(a,gel(FFT,i)); affii(b,gel(FFT,i+hstep)); avma = av; } if (hstep>1) { muliifft_dit(no, ord, M, FFT, d, hstep); muliifft_dit(no, ord, M, FFT, d+hstep, hstep); } } /* In place, bit reversed FFT, inverse of muliifft_dit */ static void muliifft_dis(ulong o, ulong ord, GEN M, GEN FFT, long d, long step) { pari_sp av = avma; long i; ulong j, no = (o<<1)%ord; long hstep=step>>1; if (hstep>1) { muliifft_dis(no, ord, M, FFT, d, hstep); muliifft_dis(no, ord, M, FFT, d+hstep, hstep); } for (i = d+1, j = 0; i <= d+hstep; ++i, j =(j+o)%ord) { GEN z = Zf_mulsqrt2(gel(FFT,i+hstep), j, ord, M); GEN a = Zf_add(gel(FFT,i), z, M); GEN b = Zf_sub(gel(FFT,i), z, M); affii(a,gel(FFT,i)); affii(b,gel(FFT,i+hstep)); avma = av; } } static GEN muliifft_spliti(GEN a, long na, long bs, long n, long mod) { GEN ap = a+na-1; GEN c = cgetg(n+1, t_VEC); long i,j; for(i=1;i<=n;i++) { GEN z = cgeti(mod+3); if (na) { long m = minss(bs, na), v=0; GEN zp, aa=ap-m+1; while (!*aa && v>k; M = int2n(mod*BITS_IN_LONG); M[2+mod] = 1; FFT = muliifft_spliti(a, na, bs, n, mod); muliifft_dit(o, ord, M, FFT, 0, n); av = avma; for(i=1; i<=n; i++) { affii(Zf_sqr(gel(FFT,i), M), gel(FFT,i)); avma=av; } muliifft_dis(ord-o, ord, M, FFT, 0, n); for(i=1; i<=n; i++) { affii(Zf_shift(gel(FFT,i), (ord>>1)-k, M), gel(FFT,i)); avma=av; } return gerepileuptoint(ltop, muliifft_unspliti(FFT,bs,2+len)); } static GEN muliispec_fft(GEN a, GEN b, long na, long nb) { pari_sp av, av2, ltop = avma; long len = na+nb; long k, mod, bs, n; GEN FFT, FFTb, M; long i; ulong o, ord; mulliifft_params(len,&k,&mod,&bs,&n,&ord); o = ord>>k; M = int2n(mod*BITS_IN_LONG); M[2+mod] = 1; FFT = muliifft_spliti(a, na, bs, n, mod); av=avma; muliifft_dit(o, ord, M, FFT, 0, n); FFTb = muliifft_spliti(b, nb, bs, n, mod); av2 = avma; muliifft_dit(o, ord, M, FFTb, 0, n); for(i=1; i<=n; i++) { affii(Zf_mul(gel(FFT,i), gel(FFTb,i), M), gel(FFT,i)); avma=av2; } avma=av; muliifft_dis(ord-o, ord, M, FFT, 0, n); for(i=1; i<=n; i++) { affii(Zf_shift(gel(FFT,i),(ord>>1)-k,M), gel(FFT,i)); avma=av; } return gerepileuptoint(ltop, muliifft_unspliti(FFT,bs,2+len)); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION (KARATSUBA) **/ /** **/ /********************************************************************/ /* return (x shifted left d words) + y. Assume d > 0, x > 0 and y >= 0 */ static GEN addshiftw(GEN x, GEN y, long d) { GEN z,z0,y0,yd, zd = (GEN)avma; long a,lz,ly = lgefint(y); z0 = new_chunk(d); a = ly-2; yd = y+ly; if (a >= d) { y0 = yd-d; while (yd > y0) *--zd = *--yd; /* copy last d words of y */ a -= d; if (a) z = addiispec(LIMBS(x), LIMBS(y), NLIMBS(x), a); else z = icopy(x); } else { y0 = yd-a; while (yd > y0) *--zd = *--yd; /* copy last a words of y */ while (zd > z0) *--zd = 0; /* complete with 0s */ z = icopy(x); } lz = lgefint(z)+d; z[1] = evalsigne(1) | evallgefint(lz); z[0] = evaltyp(t_INT) | evallg(lz); return z; } /* Fast product (Karatsuba) of integers. a and b are "special" GENs * c,c0,c1,c2 are genuine GENs. */ GEN muliispec(GEN a, GEN b, long na, long nb) { GEN a0,c,c0; long n0, n0a, i; pari_sp av; if (na < nb) swapspec(a,b, na,nb); if (nb < MULII_KARATSUBA_LIMIT) return muliispec_basecase(a,b,na,nb); if (nb >= MULII_FFT_LIMIT) return muliispec_fft(a,b,na,nb); i=(na>>1); n0=na-i; na=i; av=avma; a0=a+na; n0a=n0; while (n0a && !*a0) { a0++; n0a--; } if (n0a && nb > n0) { /* nb <= na <= n0 */ GEN b0,c1,c2; long n0b; nb -= n0; c = muliispec(a,b,na,nb); b0 = b+nb; n0b = n0; while (n0b && !*b0) { b0++; n0b--; } if (n0b) { c0 = muliispec(a0,b0, n0a,n0b); c2 = addiispec(a0,a, n0a,na); c1 = addiispec(b0,b, n0b,nb); c1 = muliispec(LIMBS(c1),LIMBS(c2), NLIMBS(c1),NLIMBS(c2)); c2 = addiispec(LIMBS(c0),LIMBS(c), NLIMBS(c0),NLIMBS(c)); c1 = subiispec(LIMBS(c1),LIMBS(c2), NLIMBS(c1),NLIMBS(c2)); } else { c0 = gen_0; c1 = muliispec(a0,b, n0a,nb); } c = addshiftw(c,c1, n0); } else { c = muliispec(a,b,na,nb); c0 = muliispec(a0,b,n0a,nb); } return gerepileuptoint(av, addshiftw(c,c0, n0)); } GEN muluui(ulong x, ulong y, GEN z) { long t, s = signe(z); GEN r; LOCAL_HIREMAINDER; if (!x || !y || !signe(z)) return gen_0; t = mulll(x,y); if (!hiremainder) r = muluispec(t, z+2, lgefint(z)-2); else { long tmp[2]; tmp[0] = hiremainder; tmp[1] = t; r = muliispec(z+2,tmp,lgefint(z)-2,2); } setsigne(r,s); return r; } #define sqrispec_mirror sqrispec #define muliispec_mirror muliispec /* x % (2^n), assuming n >= 0 */ GEN remi2n(GEN x, long n) { long hi,l,k,lx,ly, sx = signe(x); GEN z, xd, zd; if (!sx || !n) return gen_0; k = dvmdsBIL(n, &l); lx = lgefint(x); if (lx < k+3) return icopy(x); xd = x + (lx-k-1); /* x = |_|...|#|1|...|k| : copy the last l bits of # and the last k words * ^--- initial xd */ hi = ((ulong)*xd) & ((1UL<= SQRI_FFT_LIMIT) return sqrispec_fft(a,na); i=(na>>1); n0=na-i; na=i; av=avma; a0=a+na; n0a=n0; while (n0a && !*a0) { a0++; n0a--; } c = sqrispec(a,na); if (n0a) { GEN t, c1, c0 = sqrispec(a0,n0a); #if 0 c1 = shifti(muliispec(a0,a, n0a,na),1); #else /* faster */ t = addiispec(a0,a,n0a,na); t = sqrispec(LIMBS(t),NLIMBS(t)); c1= addiispec(LIMBS(c0),LIMBS(c), NLIMBS(c0), NLIMBS(c)); c1= subiispec(LIMBS(t),LIMBS(c1), NLIMBS(t), NLIMBS(c1)); #endif c = addshiftw(c,c1, n0); c = addshiftw(c,c0, n0); } else c = addshiftw(c,gen_0,n0<<1); return gerepileuptoint(av, c); } /********************************************************************/ /** **/ /** KARATSUBA SQUARE ROOT **/ /** adapted from Paul Zimmermann's implementation of **/ /** his algorithm in GMP (mpn_sqrtrem) **/ /** **/ /********************************************************************/ /* Square roots table */ static const unsigned char approx_tab[192] = { 128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142, 143,144,144,145,146,147,148,149,150,150,151,152,153,154,155,155, 156,157,158,159,160,160,161,162,163,163,164,165,166,167,167,168, 169,170,170,171,172,173,173,174,175,176,176,177,178,178,179,180, 181,181,182,183,183,184,185,185,186,187,187,188,189,189,190,191, 192,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201, 202,203,203,204,204,205,206,206,207,208,208,209,209,210,211,211, 212,212,213,214,214,215,215,216,217,217,218,218,219,219,220,221, 221,222,222,223,224,224,225,225,226,226,227,227,228,229,229,230, 230,231,231,232,232,233,234,234,235,235,236,236,237,237,238,238, 239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247, 247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255 }; /* N[0], assume N[0] >= 2^(BIL-2). * Return r,s such that s^2 + r = N, 0 <= r <= 2s */ static void p_sqrtu1(ulong *N, ulong *ps, ulong *pr) { ulong prec, r, s, q, u, n0 = N[0]; q = n0 >> (BITS_IN_LONG - 8); /* 2^6 = 64 <= q < 256 = 2^8 */ s = approx_tab[q - 64]; /* 128 <= s < 255 */ r = (n0 >> (BITS_IN_LONG - 16)) - s * s; /* r <= 2*s */ if (r > (s << 1)) { r -= (s << 1) | 1; s++; } /* 8-bit approximation from the high 8-bits of N[0] */ prec = 8; n0 <<= 2 * prec; while (2 * prec < BITS_IN_LONG) { /* invariant: s has prec bits, and r <= 2*s */ r = (r << prec) + (n0 >> (BITS_IN_LONG - prec)); n0 <<= prec; u = 2 * s; q = r / u; u = r - q * u; s = (s << prec) + q; u = (u << prec) + (n0 >> (BITS_IN_LONG - prec)); q = q * q; r = u - q; if (u < q) { s--; r += (s << 1) | 1; } n0 <<= prec; prec = 2 * prec; } *ps = s; *pr = r; } /* N[0..1], assume N[0] >= 2^(BIL-2). * Return 1 if remainder overflows, 0 otherwise */ static int p_sqrtu2(ulong *N, ulong *ps, ulong *pr) { ulong cc, qhl, r, s, q, u, n1 = N[1]; LOCAL_OVERFLOW; p_sqrtu1(N, &s, &r); /* r <= 2s */ qhl = 0; while (r >= s) { qhl++; r -= s; } /* now r < s < 2^(BIL/2) */ r = (r << BITS_IN_HALFULONG) | (n1 >> BITS_IN_HALFULONG); u = s << 1; q = r / u; u = r - q * u; q += (qhl & 1) << (BITS_IN_HALFULONG - 1); qhl >>= 1; /* (initial r)<<(BIL/2) + n1>>(BIL/2) = (qhl<<(BIL/2) + q) * 2s + u */ s = ((s + qhl) << BITS_IN_HALFULONG) + q; cc = u >> BITS_IN_HALFULONG; r = (u << BITS_IN_HALFULONG) | (n1 & LOWMASK); r = subll(r, q * q); cc -= overflow + qhl; /* now subtract 2*q*2^(BIL/2) + 2^BIL if qhl is set */ if ((long)cc < 0) { if (s) { r = addll(r, s); cc += overflow; s--; } else { cc++; s = ~0UL; } r = addll(r, s); cc += overflow; } *ps = s; *pr = r; return cc; } static void xmpn_zero(GEN x, long n) { while (--n >= 0) x[n]=0; } static void xmpn_copy(GEN z, GEN x, long n) { long k = n; while (--k >= 0) z[k] = x[k]; } /* a[0..la-1] * 2^(lb BIL) | b[0..lb-1] */ static GEN catii(GEN a, long la, GEN b, long lb) { long l = la + lb + 2; GEN z = cgetipos(l); xmpn_copy(LIMBS(z), a, la); xmpn_copy(LIMBS(z) + la, b, lb); return int_normalize(z, 0); } /* sqrt n[0..1], assume n normalized */ static GEN sqrtispec2(GEN n, GEN *pr) { ulong s, r; int hi = p_sqrtu2((ulong*)n, &s, &r); GEN S = utoi(s); *pr = hi? uutoi(1,r): utoi(r); return S; } /* sqrt n[0], _dont_ assume n normalized */ static GEN sqrtispec1_sh(GEN n, GEN *pr) { GEN S; ulong r, s, u0 = (ulong)n[0]; int sh = bfffo(u0) & ~1UL; if (sh) u0 <<= sh; p_sqrtu1(&u0, &s, &r); /* s^2 + r = u0, s < 2^(BIL/2). Rescale back: * 2^(2k) n = S^2 + R * so 2^(2k) n = (S - s0)^2 + (2*S*s0 - s0^2 + R), s0 = S mod 2^k. */ if (sh) { int k = sh >> 1; ulong s0 = s & ((1L<>= k; r >>= sh; } S = utoi(s); if (pr) *pr = utoi(r); return S; } /* sqrt n[0..1], _dont_ assume n normalized */ static GEN sqrtispec2_sh(GEN n, GEN *pr) { GEN S; ulong U[2], r, s, u0 = (ulong)n[0], u1 = (ulong)n[1]; int hi, sh = bfffo(u0) & ~1UL; if (sh) { u0 = (u0 << sh) | (u1 >> (BITS_IN_LONG-sh)); u1 <<= sh; } U[0] = u0; U[1] = u1; hi = p_sqrtu2(U, &s, &r); /* s^2 + R = u0|u1. Rescale back: * 2^(2k) n = S^2 + R * so 2^(2k) n = (S - s0)^2 + (2*S*s0 - s0^2 + R), s0 = S mod 2^k. */ if (sh) { int k = sh >> 1; ulong s0 = s & ((1L<>= k; r = (r>>sh) | (hiremainder << (BITS_IN_LONG-sh)); hi = (hiremainder & (1L<> 1; h = n - l; /* N = a3(h) | a2(h) | a1(l) | a0(l words) */ S = sqrtispec(N, h, &R); /* S^2 + R = a3|a2 */ z = catii(LIMBS(R), NLIMBS(R), N + 2*h, l); /* = R | a1(l) */ q = dvmdii(z, shifti(S,1), &u); z = catii(LIMBS(u), NLIMBS(u), N + n + h, l); /* = u | a0(l) */ S = addshiftw(S, q, l); R = subii(z, sqri(q)); if (signe(R) < 0) { GEN S2 = shifti(S,1); R = addis(subiispec(LIMBS(S2),LIMBS(R), NLIMBS(S2),NLIMBS(R)), -1); S = addis(S, -1); } *r = R; return S; } /* Return S (and set R) s.t S^2 + R = N, 0 <= R <= 2S. * As for dvmdii, R is last on stack and guaranteed to be gen_0 in case the * remainder is 0. R = NULL is allowed. */ GEN sqrtremi(GEN N, GEN *r) { pari_sp av; GEN S, R, n = N+2; long k, l2, ln = NLIMBS(N); int sh; if (ln <= 2) { if (ln == 2) return sqrtispec2_sh(n, r); if (ln == 1) return sqrtispec1_sh(n, r); if (r) *r = gen_0; return gen_0; } av = avma; sh = bfffo(n[0]) >> 1; l2 = (ln + 1) >> 1; if (sh || (ln & 1)) { /* normalize n, so that n[0] >= 2^BIL / 4 */ GEN s0, t = new_chunk(ln + 1); t[ln] = 0; if (sh) shift_left(t, n, 0,ln-1, 0, sh << 1); else xmpn_copy(t, n, ln); S = sqrtispec(t, l2, &R); /* t normalized, 2 * l2 words */ /* Rescale back: * 2^(2k) n = S^2 + R, k = sh + (ln & 1)*BIL/2 * so 2^(2k) n = (S - s0)^2 + (2*S*s0 - s0^2 + R), s0 = S mod 2^k. */ k = sh + (ln & 1) * (BITS_IN_LONG/2); s0 = remi2n(S, k); R = addii(shifti(R,-1), mulii(s0, S)); R = shifti(R, 1 - (k<<1)); S = shifti(S, -k); } else S = sqrtispec(n, l2, &R); if (!r) { avma = (pari_sp)S; return gerepileuptoint(av, S); } gerepileall(av, 2, &S, &R); *r = R; return S; } /* compute sqrt(|a|), assuming a != 0 */ #if 1 GEN sqrtr_abs(GEN x) { long l = lg(x) - 2, e = expo(x), er = e>>1; GEN b, c, res = cgetr(2 + l); res[1] = evalsigne(1) | evalexpo(er); if (e&1) { b = new_chunk(l << 1); xmpn_copy(b, x+2, l); xmpn_zero(b + l,l); b = sqrtispec(b, l, &c); xmpn_copy(res+2, b+2, l); if (cmpii(c, b) > 0) roundr_up_ip(res, l+2); } else { 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; 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]; if ( u&HIGHBIT || (u == ~HIGHBIT && cmpii(c,b) > 0)) roundr_up_ip(res, l+2); } avma = (pari_sp)res; return res; } #else /* use t_REAL: currently much slower (quadratic division) */ #ifdef LONG_IS_64BIT /* 64 bits of b = sqrt(a[0] * 2^64 + a[1]) [ up to 1ulp ] */ static ulong sqrtu2(ulong *a) { ulong c, b = dblmantissa( sqrt((double)a[0]) ); LOCAL_HIREMAINDER; LOCAL_OVERFLOW; /* > 32 correct bits, 1 Newton iteration to reach 64 */ if (b <= a[0]) return HIGHBIT | (a[0] >> 1); hiremainder = a[0]; c = divll(a[1], b); return (addll(c, b) >> 1) | HIGHBIT; } /* 64 bits of sqrt(a[0] * 2^63) */ static ulong sqrtu2_1(ulong *a) { ulong t[2]; t[0] = (a[0] >> 1); t[1] = (a[0] << (BITS_IN_LONG-1)) | (a[1] >> 1); return sqrtu2(t); } #else /* 32 bits of sqrt(a[0] * 2^32) */ static ulong sqrtu2(ulong *a) { return dblmantissa( sqrt((double)a[0]) ); } /* 32 bits of sqrt(a[0] * 2^31) */ static ulong sqrtu2_1(ulong *a) { return dblmantissa( sqrt(2. * a[0]) ); } #endif GEN sqrtr_abs(GEN x) { long l1, i, l = lg(x), ex = expo(x); GEN a, t, y = cgetr(l); pari_sp av, av0 = avma; a = rtor(x, l+1); t = cgetr(l+1); if (ex & 1) { /* odd exponent */ a[1] = evalsigne(1) | _evalexpo(1); t[2] = (long)sqrtu2((ulong*)a + 2); } else { /* even exponent */ a[1] = evalsigne(1) | _evalexpo(0); t[2] = (long)sqrtu2_1((ulong*)a + 2); } t[1] = evalsigne(1) | _evalexpo(0); for (i = 3; i <= l; i++) t[i] = 0; /* |x| = 2^(ex/2) a, t ~ sqrt(a) */ l--; l1 = 1; av = avma; while (l1 < l) { /* let t := (t + a/t)/2 */ l1 <<= 1; if (l1 > l) l1 = l; setlg(a, l1 + 2); setlg(t, l1 + 2); affrr(addrr(t, divrr(a,t)), t); shiftr_inplace(t, -1); avma = av; } affrr(t,y); shiftr_inplace(y, (ex>>1)); avma = av0; return y; } #endif /******************************************************************* * * * Base Conversion * * * *******************************************************************/ static void convi_dac(GEN x, ulong l, ulong *res) { pari_sp ltop=avma; ulong m; GEN x1,x2; if (l==1) { *res=itou(x); return; } m=l>>1; x1=dvmdii(x,powuu(1000000000UL,m),&x2); convi_dac(x1,l-m,res+m); convi_dac(x2,m,res); avma=ltop; } /* convert integer --> base 10^9 [not memory clean] */ ulong * convi(GEN x, long *l) { long lz, lx = lgefint(x); ulong *z; if (lx == 3 && (ulong)x[2] < 1000000000UL) { z = (ulong*)new_chunk(1); *z = x[2]; *l = 1; return z+1; } lz = 1 + (long)bit_accuracy_mul(lx, LOG10_2/9); z = (ulong*)new_chunk(lz); convi_dac(x,(ulong)lz,z); while (z[lz-1]==0) lz--; *l=lz; return z+lz; } pari-2.7.5/src/kernel/none/gcdext.c0000644000175000017500000001376012405547147015556 0ustar billbill#line 2 "../src/kernel/none/gcdext.c" /* Copyright (C) 2003 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. */ /*================================== * bezout(a,b,pu,pv) *================================== * Return g = gcd(a,b) >= 0, and assign GENs u,v through pointers pu,pv * such that g = u*a + v*b. * Special cases: * a == b == 0 ==> pick u=1, v=0 * a != 0 == b ==> keep v=0 * a == 0 != b ==> keep u=0 * |a| == |b| != 0 ==> keep u=0, set v=+-1 * Assignments through pu,pv will be suppressed when the corresponding * pointer is NULL (but the computations will happen nonetheless). */ GEN 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; long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ s = absi_cmp(a,b); if (s < 0) { t=b; b=a; a=t; pt=pu; pu=pv; pv=pt; } /* now |a| >= |b| */ sa = signe(a); sb = signe(b); if (!sb) { if (pv) *pv = gen_0; switch(sa) { case 0: if (pu) *pu = gen_0; return gen_0; case 1: if (pu) *pu = gen_1; return icopy(a); case -1: if (pu) *pu = gen_m1; return(negi(a)); } } if (s == 0) /* |a| == |b| != 0 */ { if (pu) *pu = gen_0; if (sb > 0) { if (pv) *pv = gen_1; return icopy(b); } else { if (pv) *pv = gen_m1; return(negi(b)); } } /* now |a| > |b| > 0 */ if (lgefint(a) == 3) /* single-word affair */ { g = xxgcduu((ulong)a[2], (ulong)b[2], 0, &xu, &xu1, &xv, &xv1, &s); sa = s > 0 ? sa : -sa; sb = s > 0 ? -sb : sb; if (pu) { if (xu == 0) *pu = gen_0; /* can happen when b divides a */ else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1; else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2; else { *pu = cgeti(3); (*pu)[1] = evalsigne(sa)|evallgefint(3); (*pu)[2] = xu; } } if (pv) { if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1; else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2; else { *pv = cgeti(3); (*pv)[1] = evalsigne(sb)|evallgefint(3); (*pv)[2] = xv; } } if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* general case */ av = avma; (void)new_chunk(lgefint(b) + (lgefint(a)<<1)); /* room for u,v,gcd */ /* if a is significantly larger than b, calling lgcdii() is not the best * way to start -- reduce a mod b first */ if (lgefint(a) > lgefint(b)) { d = absi(b), q = dvmdii(absi(a), d, &d1); if (!signe(d1)) /* a == qb */ { avma = av; if (pu) *pu = gen_0; if (pv) *pv = sb < 0 ? gen_m1 : gen_1; return (icopy(d)); } else { u = gen_0; u1 = v = gen_1; v1 = negi(q); } /* if this results in lgefint(d) == 3, will fall past main loop */ } else { d = absi(a); d1 = absi(b); u = v1 = gen_1; u1 = v = gen_0; } av1 = avma; lim = stack_lim(av, 1); /* main loop is almost identical to that of invmod() */ while (lgefint(d) > 3 && signe(d1)) { lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX); if (lhmres != 0) /* check progress */ { /* apply matrix */ if ((lhmres == 1) || (lhmres == -1)) { if (xv1 == 1) { r = subii(d,d1); d=d1; d1=r; a = subii(u,u1); u=u1; u1=a; a = subii(v,v1); v=v1; v1=a; } else { r = subii(d, mului(xv1,d1)); d=d1; d1=r; a = subii(u, mului(xv1,u1)); u=u1; u1=a; a = subii(v, mului(xv1,v1)); v=v1; v1=a; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; a = subii(muliu(u,xu), muliu(u1,xv)); u1 = subii(muliu(u,xu1), muliu(u1,xv1)); u = a; a = subii(muliu(v,xu), muliu(v1,xv)); v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a; if (lhmres&1) { togglesign(d); togglesign(u); togglesign(v); } else { togglesign(d1); togglesign(u1); togglesign(v1); } } } if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); #ifdef DEBUG_LEHMER err_printf("Full division:\n"); printf(" q = "); output(q); sleep (1); #endif a = subii(u,mulii(q,u1)); u=u1; u1=a; a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"bezout"); gerepileall(av1,6, &d,&d1,&u,&u1,&v,&v1); } } /* end while */ /* Postprocessing - final sprint */ if (signe(d1)) { /* 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); u = subii(muliu(u,xu), muliu(u1, xv)); v = subii(muliu(v,xu), muliu(v1, xv)); if (s < 0) { sa = -sa; sb = -sb; } avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* get here when the final sprint was skipped (d1 was zero already). * Now the matrix is final, and d contains the gcd. */ avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); return icopy(d); } pari-2.7.5/src/kernel/none/tune-gen.h0000644000175000017500000000402212314242551016004 0ustar billbill#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; #endif pari-2.7.5/src/kernel/none/add.c0000644000175000017500000002143012405547147015021 0ustar billbill#line 2 "../src/kernel/none/add.c" /* Copyright (C) 2002-2003 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. */ INLINE GEN icopy_sign(GEN x, long sx) { GEN y=icopy(x); setsigne(y,sx); return y; } GEN addsi_sign(long x, GEN y, long sy) { long sx,ly; GEN z; if (!x) return icopy_sign(y, sy); if (!sy) return stoi(x); if (x<0) { sx=-1; x=-x; } else sx=1; if (sx==sy) { z = adduispec(x,y+2, lgefint(y)-2); setsigne(z,sy); return z; } ly=lgefint(y); if (ly==3) { const long d = y[2] - x; if (!d) return gen_0; z=cgeti(3); if (y[2] < 0 || d > 0) { z[1] = evalsigne(sy) | evallgefint(3); z[2] = d; } else { z[1] = evalsigne(-sy) | evallgefint(3); z[2] =-d; } return z; } z = subiuspec(y+2,x, ly-2); setsigne(z,sy); return z; } GEN addui_sign(ulong x, GEN y, long sy) { long ly; GEN z; if (!x) return icopy_sign(y, sy); if (!sy) return utoipos(x); if (sy == 1) return adduispec(x,y+2, lgefint(y)-2); ly=lgefint(y); if (ly==3) { const ulong t = y[2]; if (x == t) return gen_0; z=cgeti(3); if (x < t) { z[1] = evalsigne(-1) | evallgefint(3); z[2] = t - x; } else { z[1] = evalsigne(1) | evallgefint(3); z[2] = x - t; } return z; } z = subiuspec(y+2,x, ly-2); setsigne(z,-1); return z; } /* return gen_0 when the sign is 0 */ GEN addii_sign(GEN x, long sx, GEN y, long sy) { long lx,ly; GEN z; if (!sx) return sy? icopy_sign(y, sy): gen_0; if (!sy) return icopy_sign(x, sx); lx = lgefint(x); ly = lgefint(y); if (sx==sy) z = addiispec(x+2,y+2,lx-2,ly-2); else { /* sx != sy */ long i = cmpiispec(x+2,y+2,lx-2,ly-2); if (!i) return gen_0; /* we must ensure |x| > |y| for subiispec */ if (i < 0) { sx = sy; z = subiispec(y+2,x+2,ly-2,lx-2); } else z = subiispec(x+2,y+2,lx-2,ly-2); } setsigne(z,sx); return z; } INLINE GEN rcopy_sign(GEN x, long sx) { GEN y = rcopy(x); setsigne(y,sx); return y; } GEN addir_sign(GEN x, long sx, GEN y, long sy) { long e, l, ly; GEN z; if (!sx) return rcopy_sign(y, sy); e = expo(y) - expi(x); if (!sy) { if (e >= 0) return rcopy_sign(y, sy); z = itor(x, nbits2prec(-e)); setsigne(z, sx); return z; } ly = lg(y); if (e > 0) { l = ly - divsBIL(e); if (l < 3) return rcopy_sign(y, sy); } else l = ly + nbits2extraprec(-e); z = (GEN)avma; y = addrr_sign(itor(x,l), sx, y, sy); ly = lg(y); while (ly--) *--z = y[ly]; avma = (pari_sp)z; return z; } static GEN addsr_sign(long x, GEN y, long sy) { long e, l, ly, sx; GEN z; if (!x) return rcopy_sign(y, sy); if (x < 0) { sx = -1; x = -x; } else sx = 1; e = expo(y) - expu(x); if (!sy) { if (e >= 0) return rcopy_sign(y, sy); if (sx == -1) x = -x; return stor(x, nbits2prec(-e)); } ly = lg(y); if (e > 0) { l = ly - divsBIL(e); if (l < 3) return rcopy_sign(y, sy); } else l = ly + nbits2extraprec(-e); z = (GEN)avma; y = addrr_sign(stor(x,l), sx, y, sy); ly = lg(y); while (ly--) *--z = y[ly]; avma = (pari_sp)z; return z; } GEN addsr(long x, GEN y) { return addsr_sign(x, y, signe(y)); } GEN subsr(long x, GEN y) { return addsr_sign(x, y, -signe(y)); } /* return x + 1, assuming x > 0 is a normalized t_REAL of exponent 0 */ GEN 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); shift_right(y, x, 3,l, x[2], 1); return y; } /* return subrs(x,1) to the min of (prec(x), prec(x-1) + 1), * assuming x > 1 is a normalized t_REAL of exponent 0 * [ goal: avoid the loss of significant bits form subrs ]*/ GEN subrex01(GEN x) { long i, sh, k, ly, lx = lg(x); ulong u; GEN y; k = 2; u = (ulong)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); sh = bfffo(u); if (sh) shift_left(y+2, x+k, 0, lx-k-1, 0, sh); else { for (i = 2; i < lx-k+2; i++) y[i] = x[k-2 + i]; } for (i = lx-k+2; i < ly; i++) y[i] = 0; y[1] = evalsigne(1) | evalexpo(- (bit_accuracy(k) + sh)); return y; } GEN addrr_sign(GEN x, long sx, GEN y, long sy) { long lx, ex = expo(x); long ly, ey = expo(y), e = ey - ex; long i, j, lz, ez, m; int extend, f2; GEN z; LOCAL_OVERFLOW; if (!sy) { if (!sx) { if (e > 0) ex = ey; return real_0_bit(ex); } if (e >= 0) return real_0_bit(ey); lz = nbits2prec(-e); lx = lg(x); if (lz > lx) lz = lx; z = cgetr(lz); while(--lz) z[lz] = x[lz]; setsigne(z,sx); return z; } if (!sx) { if (e <= 0) return real_0_bit(ex); lz = nbits2prec(e); ly = lg(y); if (lz > ly) lz = ly; z = cgetr(lz); while (--lz) z[lz] = y[lz]; setsigne(z,sy); return z; } if (e < 0) { swap(x,y); lswap(sx,sy); ey=ex; e=-e; } /* now ey >= ex */ lx = lg(x); ly = lg(y); /* If exponents differ, need to shift one argument, here x. If * extend = 1: extension of x,z by m < BIL bits (round to 1 word) */ /* in this case, lz = lx + d + 1, otherwise lx + d */ extend = 0; if (e) { long d = dvmdsBIL(e, &m), l = ly-d; if (l <= 2) return rcopy_sign(y, sy); if (l > lx) { lz = lx + d + 1; extend = 1; } else { lz = ly; lx = l; } if (m) { /* shift x right m bits */ const pari_sp av = avma; const ulong sh = BITS_IN_LONG-m; GEN p1 = x; x = new_chunk(lx + lz + 1); shift_right(x,p1,2,lx, 0,m); if (extend) x[lx] = p1[lx-1] << sh; avma = av; /* HACK: cgetr(lz) will not overwrite x */ } } else { /* d = 0 */ m = 0; if (lx > ly) lx = ly; lz = lx; } if (sx == sy) { /* addition */ i = lz-1; j = lx-1; if (extend) { ulong garde = addll(x[lx], y[i]); if (m < 4) /* don't extend for few correct bits */ z = cgetr(--lz); else { z = cgetr(lz); z[i] = garde; } } else { z = cgetr(lz); z[i] = addll(x[j], y[i]); j--; } i--; for (; j>=2; i--,j--) z[i] = addllx(x[j],y[i]); if (overflow) { z[1] = 1; /* stops since z[1] != 0 */ for (;;) { z[i] = (ulong) y[i]+1; if (z[i--]) break; } if (i <= 0) { shift_right(z,z, 2,lz, 1,1); z[1] = evalsigne(sx) | evalexpo(ey+1); return z; } } for (; i>=2; i--) z[i] = y[i]; z[1] = evalsigne(sx) | evalexpo(ey); return z; } /* subtraction */ if (e) f2 = 1; else { 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]); } /* result is non-zero. f2 = (y > x) */ i = lz-1; z = cgetr(lz); if (f2) { j = lx-1; if (extend) z[i] = subll(y[i], x[lx]); 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 (; i>=2; i--) z[i] = y[i]; sx = sy; } else { if (extend) z[i] = subll(x[lx], y[i]); else z[i] = subll(x[i], y[i]); for (i--; i>=2; i--) z[i] = subllx(x[i], y[i]); } x = z+2; i = 0; while (!x[i]) i++; lz -= i; z += i; j = bfffo(z[2]); /* need to shift left by j bits to normalize mantissa */ ez = ey - (j | (i * BITS_IN_LONG)); if (extend) { /* z was extended by d+1 words [should be e bits = d words + m bits] */ /* not worth keeping extra word if less than 5 significant bits in there */ if (m - j < 5 && lz > 3) { /* shorten z */ ulong last = (ulong)z[--lz]; /* cancelled word */ /* if we need to shift anyway, shorten from left * If not, shorten from right, neutralizing last word of z */ if (j == 0) /* stackdummy((pari_sp)(z + lz+1), (pari_sp)(z + lz)); */ z[lz] = evaltyp(t_VECSMALL) | _evallg(1); else { GEN t = z; z++; shift_left(z,t,2,lz-1, last,j); } if ((last< 1) i--; if (i == 1) { ez++; z[2] = (long)HIGHBIT; } } } else if (j) shift_left(z,z,2,lz-1, 0,j); } else if (j) shift_left(z,z,2,lz-1, 0,j); z[1] = evalsigne(sx) | evalexpo(ez); z[0] = evaltyp(t_REAL) | evallg(lz); avma = (pari_sp)z; return z; } pari-2.7.5/src/kernel/none/MakeLVL1.SH0000644000175000017500000000077712314242551015676 0ustar billbillcat >> $file << EOT L1OBJS=$kern1/int.h $knone/level1.h parilvl1.h: \$(L1OBJS) $src/headers/paritune.h if test -r ./tune.h; then d=.; else d=$kern1; fi;\ cat \$\$d/tune.h \$(L1OBJS) > parilvl1.h MP_C=$kern1/mp.c $knone/cmp.c $knone/gcdll.c $knone/ratlift.c\ $knone/invmod.c $kern1/gcd.c $kern1/gcdext.c $knone/mp_indep.c $knone/add.c mpker.c: \$(MP_C) cat \$(MP_C) > mpker.c mpker\$(_O): .headers mpker.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) -o mpker\$(_O) mpker.c EOT pari-2.7.5/src/kernel/none/invmod.c0000644000175000017500000001220512405547147015565 0ustar billbill#line 2 "../src/kernel/none/invmod.c" /* Copyright (C) 2003 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. */ /*================================== * invmod(a,b,res) *================================== * If a is invertible, return 1, and set res = a^{ -1 } * Otherwise, return 0, and set res = gcd(a,b) * * This is sufficiently different from bezout() to be implemented separately * instead of having a bunch of extra conditionals in a single function body * to meet both purposes. */ #ifdef INVMOD_PARI INLINE int invmod_pari(GEN a, GEN b, GEN *res) #else int invmod(GEN a, GEN b, GEN *res) #endif { GEN v,v1,d,d1,q,r; pari_sp av, av1, lim; long s; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ if (!signe(b)) { *res=absi(a); return 0; } av = avma; if (lgefint(b) == 3) /* single-word affair */ { ulong d1 = umodiu(a, (ulong)(b[2])); if (d1 == 0) { if (b[2] == 1L) { *res = gen_0; return 1; } else { *res = absi(b); return 0; } } g = xgcduu((ulong)(b[2]), d1, 1, &xv, &xv1, &s); #ifdef DEBUG_LEHMER err_printf(" <- %lu,%lu\n", (ulong)(b[2]), (ulong)(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; *res = utoipos(xv); return 1; } (void)new_chunk(lgefint(b)); d = absi(b); d1 = modii(a,d); v=gen_0; v1=gen_1; /* general case */ #ifdef DEBUG_LEHMER err_printf("INVERT: -------------------------\n"); output(d1); #endif av1 = avma; lim = stack_lim(av,1); while (lgefint(d) > 3 && signe(d1)) { #ifdef DEBUG_LEHMER err_printf("Calling Lehmer:\n"); #endif lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX); if (lhmres != 0) /* check progress */ { /* apply matrix */ #ifdef DEBUG_LEHMER err_printf("Lehmer returned %d [%lu,%lu;%lu,%lu].\n", lhmres, xu, xu1, xv, xv1); #endif if ((lhmres == 1) || (lhmres == -1)) { if (xv1 == 1) { r = subii(d,d1); d=d1; d1=r; a = subii(v,v1); v=v1; v1=a; } else { r = subii(d, mului(xv1,d1)); d=d1; d1=r; a = subii(v, mului(xv1,v1)); v=v1; v1=a; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); a = subii(muliu(v,xu), muliu(v1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a; if (lhmres&1) { togglesign(d); togglesign(v); } else { togglesign(d1); togglesign(v1); } } } #ifdef DEBUG_LEHMER else err_printf("Lehmer returned 0.\n"); output(d); output(d1); output(v); output(v1); sleep(1); #endif if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); #ifdef DEBUG_LEHMER err_printf("Full division:\n"); printf(" q = "); output(q); sleep (1); #endif a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"invmod"); gerepileall(av1, 4, &d,&d1,&v,&v1); } } /* end while */ /* Postprocessing - final sprint */ if (signe(d1)) { /* 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); #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,%ld,%lu; %lx\n", g,s,xv1,avma); #endif if (g != 1UL) { avma = av; *res = utoipos(g); return 0; } /* (From the xgcduu() blurb:) * For finishing the multiword modinv, we now have to multiply the * returned matrix (with properly adjusted signs) onto the values * v' and v1' previously obtained from the multiword division steps. * Actually, it is sufficient to take the scalar product of [v',v1'] * with [u1,-v1], and change the sign if s==1. */ v = subii(muliu(v,xu1),muliu(v1,xv1)); if (s > 0) setsigne(v,-signe(v)); avma = av; *res = modii(v,b); #ifdef DEBUG_LEHMER output(*res); fprintfderr("============================Done.\n"); sleep(1); #endif return 1; } /* get here when the final sprint was skipped (d1 was zero already) */ avma = av; if (!equalii(d,gen_1)) { *res = icopy(d); return 0; } *res = modii(v,b); #ifdef DEBUG_LEHMER output(*res); err_printf("============================Done.\n"); sleep(1); #endif return 1; } pari-2.7.5/src/kernel/none/mulll.h0000644000175000017500000000773012366172547015436 0ustar billbill#line 2 "../src/kernel/none/mulll.h" /* 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. */ #undef LOCAL_HIREMAINDER #define LOCAL_HIREMAINDER extern ulong hiremainder; /* Version Peter Montgomery */ /* * Assume (for presentation) that BITS_IN_LONG = 32. * Then 0 <= xhi, xlo, yhi, ylo <= 2^16 - 1. Hence * * -2^31 + 2^16 <= (xhi-2^15)*(ylo-2^15) + (xlo-2^15)*(yhi-2^15) <= 2^31. * * If xhi*ylo + xlo*yhi = 2^32*overflow + xymid, then * * -2^32 + 2^16 <= 2^32*overflow + xymid - 2^15*(xhi + ylo + xlo + yhi) <= 0. * * 2^16*overflow <= (xhi+xlo+yhi+ylo)/2 - xymid/2^16 <= 2^16*overflow + 2^16-1 * * This inequality was derived using exact (rational) arithmetic; * it remains valid when we truncate the two middle terms. */ #if !defined(INLINE) extern long mulll(ulong x, ulong y); extern long addmul(ulong x, ulong y); #else #if defined(__GNUC__) && !defined(DISABLE_INLINE) #undef LOCAL_HIREMAINDER #define LOCAL_HIREMAINDER register ulong hiremainder #define mulll(x, y) \ __extension__ ({ \ const ulong __x = (x), __y = (y);\ const ulong __xlo = LOWWORD(__x), __xhi = HIGHWORD(__x); \ const ulong __ylo = LOWWORD(__y), __yhi = HIGHWORD(__y); \ ulong __xylo,__xymid,__xyhi,__xymidhi,__xymidlo; \ ulong __xhl,__yhl; \ \ __xylo = __xlo*__ylo; __xyhi = __xhi*__yhi; \ __xhl = __xhi+__xlo; __yhl = __yhi+__ylo; \ __xymid = __xhl*__yhl - (__xyhi+__xylo); \ \ __xymidhi = HIGHWORD(__xymid); \ __xymidlo = __xymid << BITS_IN_HALFULONG; \ \ __xylo += __xymidlo; \ hiremainder = __xyhi + __xymidhi + (__xylo < __xymidlo) \ + ((((__xhl + __yhl) >> 1) - __xymidhi) & HIGHMASK); \ \ __xylo; \ }) #define addmul(x, y) \ __extension__ ({ \ const ulong __x = (x), __y = (y);\ const ulong __xlo = LOWWORD(__x), __xhi = HIGHWORD(__x); \ const ulong __ylo = LOWWORD(__y), __yhi = HIGHWORD(__y); \ ulong __xylo,__xymid,__xyhi,__xymidhi,__xymidlo; \ ulong __xhl,__yhl; \ \ __xylo = __xlo*__ylo; __xyhi = __xhi*__yhi; \ __xhl = __xhi+__xlo; __yhl = __yhi+__ylo; \ __xymid = __xhl*__yhl - (__xyhi+__xylo); \ \ __xylo += hiremainder; __xyhi += (__xylo < hiremainder); \ \ __xymidhi = HIGHWORD(__xymid); \ __xymidlo = __xymid << BITS_IN_HALFULONG; \ \ __xylo += __xymidlo; \ hiremainder = __xyhi + __xymidhi + (__xylo < __xymidlo) \ + ((((__xhl + __yhl) >> 1) - __xymidhi) & HIGHMASK); \ \ __xylo; \ }) #else INLINE long mulll(ulong x, ulong y) { const ulong xlo = LOWWORD(x), xhi = HIGHWORD(x); const ulong ylo = LOWWORD(y), yhi = HIGHWORD(y); ulong xylo,xymid,xyhi,xymidhi,xymidlo; ulong xhl,yhl; xylo = xlo*ylo; xyhi = xhi*yhi; xhl = xhi+xlo; yhl = yhi+ylo; xymid = xhl*yhl - (xyhi+xylo); xymidhi = HIGHWORD(xymid); xymidlo = xymid << BITS_IN_HALFULONG; xylo += xymidlo; hiremainder = xyhi + xymidhi + (xylo < xymidlo) + ((((xhl + yhl) >> 1) - xymidhi) & HIGHMASK); return xylo; } INLINE long addmul(ulong x, ulong y) { const ulong xlo = LOWWORD(x), xhi = HIGHWORD(x); const ulong ylo = LOWWORD(y), yhi = HIGHWORD(y); ulong xylo,xymid,xyhi,xymidhi,xymidlo; ulong xhl,yhl; xylo = xlo*ylo; xyhi = xhi*yhi; xhl = xhi+xlo; yhl = yhi+ylo; xymid = xhl*yhl - (xyhi+xylo); xylo += hiremainder; xyhi += (xylo < hiremainder); xymidhi = HIGHWORD(xymid); xymidlo = xymid << BITS_IN_HALFULONG; xylo += xymidlo; hiremainder = xyhi + xymidhi + (xylo < xymidlo) + ((((xhl + yhl) >> 1) - xymidhi) & HIGHMASK); return xylo; } #endif #endif pari-2.7.5/src/kernel/none/mpinl.c0000644000175000017500000000131312366172547015412 0ustar billbill/* 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. */ #define PARI_NO_PARIINL_H #define INLINE #ifndef DISABLE_INLINE # define DISABLE_INLINE #endif #include "pari.h" ulong hiremainder, overflow; pari-2.7.5/src/graph/0000755000175000017500000000000012613365633013006 5ustar billbillpari-2.7.5/src/graph/plotQt.c0000644000175000017500000003755712366172547014463 0ustar billbill/* 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. */ ///////////////////////////////////////////////////////////////////////////// // // High resolution plot using Trolltech's Qt library // // You may possibly want to use this file with a "Qt Free Edition" // which is distributed under the terms of the Q PUBLIC LICENSE (QPL), // or with a "Qt/Embedded Free Edition" which is // distributed under the terms of the GNU General Public License (GPL). // Please check http://www.trolltech.com for details. // // ---Nils-Peter Skoruppa (www.countnumber.de) ///////////////////////////////////////////////////////////////////////////// extern "C" { #include "pari.h" #include "paripriv.h" #undef grem #undef swap #include "rect.h" } #ifdef __QPE__ #include #else #include #endif #include #include #include #include #include #include #include #include class Plotter: public QWidget { #ifdef __FANCY_WIN__ Q_OBJECT signals: void clicked(); protected: void mouseReleaseEvent( QMouseEvent*); #endif public: Plotter( long *w, long *x, long *y, long lw, QWidget* parent = 0, const char* name = 0, WFlags fl = 0); void save( const QString& s = *plotFile + ".xpm",//QString("pariplot.xpm"), const QString& f = QString( "XPM")); protected: void paintEvent( QPaintEvent *); void resizeEvent ( QResizeEvent *); #ifndef __FANCY_WIN__ void keyPressEvent( QKeyEvent *); #endif private: long *w; // map into rectgraph indexes long *x; // x, y: array of x,y-coorinates of the long *y; // top left corners of the rectwindows long lw; // lw: number of rectwindows long numcolors; QColor *color; QFont font; static QString *plotFile; void draw(QPainter *p); // public: // static void setPlotFile( const char *); }; QString *Plotter::plotFile = new QString( "pariplot"); Plotter::Plotter( long *w, long *x, long *y, long lw, QWidget* parent, const char* name, WFlags fl) : QWidget( parent, name, fl), font( "lucida", 9) { long i; this->w=w; this->x=x; this->y=y; this->lw=lw; #ifndef __FANCY_WIN__ this->resize( pari_plot.width, pari_plot.height); this->setCaption( "Pari QtPlot"); #endif this->setFont( font); numcolors = lg(pari_colormap)-1; color = (QColor*)pari_malloc(numcolors*sizeof(QColor)); for (i = 1; i < lg(pari_colormap); i++) { int r, g, b; color_to_rgb(gel(pari_colormap,i), &r, &g, &b); color[i-1] = QColor(r, g, b); } this->setBackgroundColor( color[0]); } // void Plotter::setPlotFile( const char *s) { // delete Plotter::plotFile; // Plotter::plotFile = new QString( s); // } struct data_qt { QPainter *p; long numcolors; QColor *color; }; static void SetForeground(void *data, long col) { struct data_qt *d = (struct data_qt *) data; d->p->setPen(d->color[col]); } static void DrawPoint(void *data, long x, long y) { struct data_qt *d = (struct data_qt *) data; d->p->drawPoint(x, y); } static void DrawLine(void *data, long x1, long y1, long x2, long y2) { struct data_qt *d = (struct data_qt *) data; d->p->drawLine(x1, y1, x2, y2); } static void DrawRectangle(void *data, long x, long y, long w, long h) { struct data_qt *d = (struct data_qt *) data; d->p->drawRect(x, y, w, h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { struct data_qt *d = (struct data_qt *) data; QPointArray xp=QPointArray(nb); long i; for (i=0;ip->drawPoints(xp); } static void DrawLines(void *data, long nb, struct plot_points *p) { struct data_qt *d = (struct data_qt *) data; QPointArray xp=QPointArray(nb); long i; for (i=0;ip->drawPolyline(xp); } static void DrawString(void *data, long x, long y, char *text, long numtext) { struct data_qt *d = (struct data_qt *) data; d->p->drawText(x, y, QString(text), numtext); } void Plotter::draw(QPainter *p){ struct plot_eng plotQt; struct data_qt d; d.p= p; d.numcolors = numcolors; d.color=color; plotQt.sc=&SetForeground; plotQt.pt=&DrawPoint; plotQt.ln=&DrawLine; plotQt.bx=&DrawRectangle; plotQt.mp=&DrawPoints; plotQt.ml=&DrawLines; plotQt.st=&DrawString; plotQt.pl=&pari_plot; plotQt.data = (void *)&d; double xs = double(this->width()) / pari_plot.width, ys = double(this->height()) / pari_plot.height; gen_rectdraw0(&plotQt, this->w, this->x, this->y,this->lw,xs,ys); } void Plotter::save( const QString& s, const QString& f){ QPixmap pm( this->width(), this->height()); QPainter p; p.begin( &pm, this); p.fillRect( 0, 0, pm.width(), pm.height(), color[0]); this->draw(&p); p.end(); // supported formats in qt2: BMP, JPEG, PNG, PNM, XBM, XPM ; PNG is broken pm.save( s, f); } void Plotter::paintEvent( QPaintEvent *) { QPainter p; p.begin( this); this->draw(&p); p.end(); } void Plotter::resizeEvent( QResizeEvent *) { } #ifndef __FANCY_WIN__ void Plotter::keyPressEvent( QKeyEvent *e) { switch ( tolower( e->ascii())) { case 's': save(); this->setCaption( "Pari QtPlot: " + *plotFile); break; } } #endif #ifdef __FANCY_WIN__ void Plotter::mouseReleaseEvent( QMouseEvent*) { emit clicked(); } #endif #ifdef __FANCY_WIN__ // // The envelope for an instance of plotter // #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* XPM */ static const char * const fullscreen_xpm[] = { "14 14 2 1", " c None", ". c #000000", "..............", ". .. .", ". .. .", ". .... .", ". .. .", ". . .. . .", "..............", "..............", ". . .. . .", ". .. .", ". .... .", ". .. .", ". .. .", ".............."}; class SaveAsDialog: public #ifdef __QPE__ //QDialog #else QFileDialog #endif { Q_OBJECT public: SaveAsDialog( const QString & c = QString::null, const QString & s = QString::null, int w = 0, int h = 0, QWidget *parent = 0, const char *name = 0, WFlags f = 0); ~SaveAsDialog(); #ifdef __QPE__ QString selectedFile() { return nameW->text();} #endif int picWidth() { return widthW->value();} int picHeight() { return heightW->value();} private: QLineEdit *nameW; QSpinBox *widthW, *heightW; }; SaveAsDialog::SaveAsDialog( const QString & c, const QString & s, int w, int h, QWidget *parent, const char *name, WFlags f) #ifdef __QPE__ // simplistic dialog in case of QPE ( fancy alternative: class FileSelector) : QDialog( parent, name, TRUE, f) { if( c) this->setCaption( c); nameW = new QLineEdit( this); if( s) nameW->setText( s); widthW = new QSpinBox( 1, 65536, 1, this); if( w > 0) widthW->setValue( w); heightW = new QSpinBox( 1, 65536, 1, this); if( h > 0) heightW->setValue( h); QVBoxLayout *top = new QVBoxLayout( this, 10); QGridLayout *contents = new QGridLayout( 3, 2); top->addLayout( contents); QLabel *l; l = new QLabel( nameW, "Name : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 0, 0); contents->addWidget( nameW, 0, 1); l = new QLabel( widthW, "Width : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 1, 0); contents->addWidget( widthW, 1, 1); l = new QLabel( heightW, "Height : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 2, 0); contents->addWidget( heightW, 2, 1); top->activate(); this->resize( 160, this->height()); // hack!!! #else : QFileDialog( parent, name, TRUE) { if( c) this->setFilters( c); if( s) this->setSelection( s); QLabel *l; QWidget *wt = new QWidget( this); QHBoxLayout *spinBoxes = new QHBoxLayout( wt, 5); widthW = new QSpinBox( 1, 65536, 1, wt); l = new QLabel( widthW, "&width ", wt); spinBoxes->addWidget( l); spinBoxes->addWidget( widthW); if( w > 0) widthW->setValue( w); heightW = new QSpinBox( 1, 65536, 1, wt); spinBoxes->addSpacing(10); l = new QLabel( heightW, "&height ", wt); l->setAlignment( AlignRight | AlignVCenter); spinBoxes->addWidget( l); spinBoxes->addWidget( heightW); if( h > 0) heightW->setValue( h); l = new QLabel( "Resolution:", this); QFileDialog::addWidgets( l, wt, 0); #endif } SaveAsDialog::~SaveAsDialog() { } class PlotWindow: public QMainWindow { Q_OBJECT public: PlotWindow( long *w, long *x, long *y, long lw, QWidget* parent = 0, const char* name = 0, WFlags fl = 0); ~PlotWindow(); #ifndef __QPE__ protected: void resizeEvent( QResizeEvent *); #endif private slots: void fullScreen(); void normalView(); void save(); void save( int); private: static const QStrList file_formats; Plotter *plr; QString saveFileName; int saveFileFormat; #ifndef __QPE__ QLabel *res; #endif }; const QStrList PlotWindow::file_formats = QImage::outputFormats(); PlotWindow::PlotWindow( long *w, long *x, long *y, long lw, QWidget* parent, const char* name, WFlags fl) : QMainWindow( parent, name, fl), saveFileName( "pariplot"), saveFileFormat( 0) { this->setCaption( "Pari QtPlot"); #ifdef __QPE__ QToolBar *toolBar = new QToolBar( this); QMenuBar *menuBar = new QMenuBar( toolBar); toolBar->setHorizontalStretchable( TRUE); this->setToolBarsMovable( FALSE); #else QMenuBar *menuBar = this->menuBar(); menuBar->setFrameStyle( QFrame::Panel | QFrame::Raised); #endif // Setting up the File and View menu QPopupMenu *format = new QPopupMenu( this); for( uint i = 0; i < file_formats.count(); i++) { format->insertItem( QString( QStrList(file_formats).at(i)) + " ...", this, SLOT( save( int)), 0, i); if( 0 == QString( QStrList(file_formats).at(i)).compare( "PNG")) format->setItemEnabled( i, FALSE); // PNG seems to be broken } QPopupMenu *file = new QPopupMenu( this); CHECK_PTR( file ); file->insertItem( "&Save", this, SLOT( save()), CTRL+Key_S); file->insertItem( "Save &as", format); file->insertSeparator(); file->insertItem( "&Close", this, SLOT(close()), CTRL+Key_C); menuBar->insertItem( "&File", file ); #ifndef __QPE__ QPopupMenu *view = new QPopupMenu( this); menuBar->insertItem( "&View", view); #endif // Setting up the Fullscreen action QAction *a = new QAction( "use full screen", QPixmap( (const char ** )fullscreen_xpm), "&Fullscreen", CTRL+Key_F, this); connect( a, SIGNAL( activated()), this, SLOT( fullScreen())); #ifdef __QPE__ a->addTo( toolBar); #else a->addTo( view); #endif // Setting up an instance of plotter plr = new Plotter( w, x, y, lw, this); connect( plr, SIGNAL(clicked()), this, SLOT( normalView())); this->setCentralWidget( plr); #ifndef __QPE__ this->resize( pari_plot.width, pari_plot.height + 25); res = new QLabel( statusBar()); statusBar()->addWidget( res); #endif } PlotWindow::~PlotWindow() { } #ifndef __QPE__ void PlotWindow::resizeEvent( QResizeEvent *e) { QMainWindow::resizeEvent( e); res->setText( QString( "Resolution: ") + QString::number( plr->width()) + "x" + QString::number( plr->height())); res->setFixedSize( res->sizeHint()); } #endif void PlotWindow::fullScreen() { if ( plr->parentWidget()) { plr->reparent( 0, WStyle_Tool | WStyle_Customize | WStyle_StaysOnTop, QPoint( 0, 0), FALSE); plr->resize( qApp->desktop()->width(), qApp->desktop()->height()); plr->show(); } } void PlotWindow::normalView() { if ( !plr->parentWidget()) { plr->reparent( this, 0, QPoint(0,0), FALSE); this->setCentralWidget( plr); plr->show(); } } void PlotWindow::save() { QString ff = QString( QStrList(file_formats).at( saveFileFormat)); QString fn = saveFileName + "." + ff.lower(); plr->save( fn, ff); this->setCaption( QString( "Pari QtPlot:") + fn); #ifndef __QPE__ statusBar()->message( QString( "File %1 saved" ).arg( fn), 2000 ); #endif } void PlotWindow::save( int id) { QString ff( QStrList(file_formats).at( id)); #ifdef __QPE__ QString s( "Save as"); #else QString s( ff + " (*." + ff.lower() +");;All (*)"); #endif SaveAsDialog d( s, saveFileName + "." + ff.lower(), plr->width(), plr->height()); if( QDialog::Rejected == d.exec()) return; QString fn = d.selectedFile(); if ( !fn.isEmpty()) { if( QFile( fn).exists() && QMessageBox::warning( this, this->caption(), QString( "A file named\n\"") + fn + QString( "\"\nalready exists\n" "Should this file be overwritten ?\n\n"), "&Overwrite", "&Cancel")) return; saveFileName = fn; int p; if( (p = saveFileName.findRev( "." + ff, -1, FALSE)) >=0) saveFileName.truncate( p); saveFileFormat = id; int old_w = plr->width(), old_h = plr->height(); int w = d.picWidth(), h = d.picHeight(); if( w != old_w || h != old_h) { plr->resize( w, h); save(); plr->resize( old_w, old_h); } else save(); } } #include "plotQt.moc.cpp" #endif // __FANCY_WIN__ // // Implementation of the two architecture-dependent functions // (from rect.h) requested by pari's plotting routines // void rectdraw0(long *w, long *x, long *y, long lw) { if (pari_daemon()) return; // parent process returns pari_close(); PARI_get_plot(); // launch Qt window int argc = 1; char *argv[] = { "gp", "-qws"}; // set argc = 2 for cross // development using qvfb #ifdef __QPE__ QPEApplication #else QApplication #endif a( argc, argv); #ifdef __FANCY_WIN__ PlotWindow *win = new PlotWindow(w, x, y, lw); #else Plotter *win = new Plotter( w, x, y, lw); #endif #ifdef __QPE__ a.showMainWidget( win); #else a.setMainWidget( win); win->show(); #endif a.exec(); exit( 0); } void PARI_get_plot() /* This function initialises the structure rect.h: pari_plot */ { if (pari_plot.init) return; // pari_plot is already set #ifdef __QPE__ pari_plot.width = 240; // width and pari_plot.height = 320; // height of plot window #else pari_plot.width = 400; // width and pari_plot.height = 300; // height of plot window #endif pari_plot.hunit = 3; // pari_plot.vunit = 3; // pari_plot.fwidth = 6; // font width pari_plot.fheight = 9; // and height pari_plot.init = 1; // flag: pari_plot is set now! } pari-2.7.5/src/graph/plotps.c0000644000175000017500000000346412366172547014507 0ustar billbill/* 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. */ /*******************************************************************/ /* HIGH RESOLUTION PLOT VIA POSTSCRIPT FILE */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "rect.h" BEGINEXTERN void system0(const char *s); ENDEXTERN void rectdraw0(long *w, long *x, long *y, long lw) { struct plot_eng plot; FILE *file; char *s, *cmd; const char *v; if (pari_daemon()) return; /* parent process returns */ s = pari_unique_filename("plotps"); pari_unlink(s); s = stack_strcat(s, ".ps"); file = fopen(s, "w"); if (!file) pari_err_FILE("postscript file", s); psplot_init(&plot, file, 1.0, 1.0, 9); fprintf(file,"0 %ld translate -90 rotate\n", plot.pl->height - 50); gen_rectdraw0(&plot, w, x, y, lw, 1, 1); fprintf(file,"stroke showpage\n"); (void)fclose(file); v = os_getenv("GP_POSTSCRIPT_VIEWER"); if (!v) v = "open -W"; cmd = pari_sprintf("%s \"%s\" 2>/dev/null", v, s); system0(cmd); pari_unlink(s); exit(0); } void PARI_get_plot() { if (pari_plot.init) return; pari_plot.width = 400; pari_plot.height = 300; pari_plot.fheight = 9; pari_plot.fwidth = 6; pari_plot.hunit = 3; pari_plot.vunit = 3; pari_plot.init = 1; } pari-2.7.5/src/graph/plotWin32.c0000644000175000017500000000630612533333715014755 0ustar billbill/* Copyright (C) 2009 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. */ /* Written by Vasili Burdo */ #include #include #include "pari.h" #include "paripriv.h" #include "rect.h" static void SetForeground(void *data, long col) { int r,g,b; color_to_rgb(gel(pari_colormap,col), &r, &g, &b); HPEN hOldPen = SelectObject((HDC)data, CreatePen(PS_SOLID, 2, RGB(r,g,b))); if( hOldPen ) DeleteObject(hOldPen); } static void DrawPoint(void *data, long x, long y) { Ellipse((HDC)data,x-1,y-1,x+1,y+1); } static void DrawLine(void *data, long x1, long y1, long x2, long y2) { MoveToEx((HDC)data, x1, y1, NULL); LineTo((HDC)data,x2,y2); } static void DrawRectangle(void *data, long x, long y, long w, long h) { RECT rc; rc.left = x; rc.right = x+w; rc.top = y; rc.bottom = y+h; FrameRect((HDC)data, &rc, GetStockObject(HOLLOW_BRUSH)); } static void DrawPoints(void *data, long nb, struct plot_points *p) { long i; for (i=0; i= 0) { sprintf(buf, "%9.*g", i, d); if (strlen(buf) <= 9) return buf; } return buf; /* Should not happen? */ } typedef unsigned char screen[ISCR+1][JSCR+1]; static void fill_gap(screen scr, long i, int jnew, int jpre) { int mid, i_up, i_lo, up, lo; if (jpre < jnew - 2) { up = jnew - 1; i_up = i; lo = jpre + 1; i_lo = i - 1; } else if (jnew < jpre - 2) { up = jpre - 1; i_up = i - 1; lo = jnew + 1; i_lo = i; } else return; /* if gap < 2, leave it as it is. */ mid = (jpre+jnew)/2; if (mid>JSCR) mid=JSCR; else if (mid<0) mid=0; if (lo<0) lo=0; if (lo<=JSCR) while (lo <= mid) scr[i_lo][lo++] = ':'; if (up>JSCR) up=JSCR; if (up>=0) while (up > mid) scr[i_up][up--] = ':'; } static double todbl(GEN x) { return rtodbl(gtofp(x, LOWDEFAULTPREC)); } /* code is either a t_CLOSURE (from GP: ploth, etc.) or a t_POL/t_VEC of * two t_POLs from rectsplines */ static GEN READ_EXPR(GEN code, GEN x) { if (typ(code)!=t_CLOSURE) return gsubst(code,0,x); set_lex(-1, x); return closure_evalgen(code); } void 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; int jnew, jpre = 0; /* for lint */ GEN x, dx; double diff, dyj, ysml, ybig, y[ISCR+1]; screen scr; char buf[80], z; sig=gcmp(b,a); if (!sig) return; if (sig<0) { x=a; a=b; b=x; } x = gtofp(a, prec); push_lex(x, code); dx = divru(gtofp(gsub(b,a),prec), ISCR-1); for (j=1; j<=JSCR; j++) scr[1][j]=scr[ISCR][j]=YY; for (i=2; 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); if (ybigu) ybig = gtodouble(ybigu); diff = ybig - ysml; if (!diff) { ybig += 1; diff= 1.; } dyj = ((JSCR-1)*3+2) / diff; /* 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) { if (0<=jz && jz<=JSCR) scr[i][jz]=z; j = 3 + DTOL((y[i]-ysml)*dyj); jnew = j/3; if (i > 1) fill_gap(scr, i, jnew, jpre); if (0<=jnew && jnew<=JSCR) scr[i][jnew] = PICT(j); jpre = jnew; } pari_putc('\n'); pari_printf("%s ", dsprintf9(ybig, buf)); for (i=1; i<=ISCR; i++) pari_putc(scr[i][JSCR]); pari_putc('\n'); for (j=(JSCR-1); j>=2; j--) { pari_puts(" "); for (i=1; i<=ISCR; i++) pari_putc(scr[i][j]); pari_putc('\n'); } pari_printf("%s ", dsprintf9(ysml, buf)); for (i=1; i<=ISCR; i++) pari_putc(scr[i][1]); pari_putc('\n'); { char line[10 + 32 + 32 + ISCR - 9]; sprintf(line, "%10s%-9.7g%*.7g\n"," ",todbl(a),ISCR-9,todbl(b)); pari_printf(line); } pop_lex(1); } /********************************************************************/ /** **/ /** RECTPLOT FUNCTIONS **/ /** **/ /********************************************************************/ void init_graph(void) { long n; for (n=0; nhead = e->tail = NULL; e->sizex = e->sizey = 0; current_color[n] = DEFAULT_COLOR; rectgraph[n] = e; } } void free_graph(void) { int i; for (i=0; itable); pari_free((void*)rgb_colors); } if (pari_colormap) pari_free(pari_colormap); if (pari_graphcolors) pari_free(pari_graphcolors); } static PariRect * check_rect(long ne) { const long m = NUMRECT-1; if (ne < 0) pari_err_DOMAIN("graphic function", "rectwindow", "<", gen_0, stoi(ne)); if (ne > m) pari_err_DOMAIN("graphic function", "rectwindow", ">", stoi(m), stoi(ne)); return rectgraph[ne]; } static PariRect * check_rect_init(long ne) { PariRect *e = check_rect(ne); if (!RHead(e)) pari_err_TYPE("graphic function [use plotinit() first]", stoi(ne)); return e; } static long initrect_get_arg(GEN x, long flag, long *dft) { /* FIXME: gequal0(x) undocumented backward compatibility hack */ if (!x || gequal0(x) || flag) { PARI_get_plot(); return *dft - 1; } if (typ(x) != t_INT) pari_err_TYPE("initrect",x); return itos(x); } void initrect_gen(long ne, GEN x, GEN y, long flag) { const long m = NUMRECT-3; long xi, yi; xi = initrect_get_arg(x, flag, &pari_plot.width); yi = initrect_get_arg(y, flag, &pari_plot.height); if (flag) { if (x) xi = DTOL(xi * gtodouble(x)); if (y) yi = DTOL(yi * gtodouble(y)); } if (ne > m) pari_err_DOMAIN("graphic function", "rectwindow", ">", stoi(m), stoi(ne)); initrect(ne, xi, yi); } static void Rchain(PariRect *e, RectObj *z) { if (!RHead(e)) RHead(e) = z; else RoNext(RTail(e)) = z; RTail(e) = z; RoNext(z) = NULL; } void initrect(long ne, long x, long y) { PariRect *e; RectObj *z; if (x <= 1) pari_err_DOMAIN("initrect", "x", "<=", gen_1, stoi(x)); if (y <= 1) pari_err_DOMAIN("initrect", "y", "<=", gen_1, stoi(y)); e = check_rect(ne); if (RHead(e)) killrect(ne); z = (RectObj*) pari_malloc(sizeof(RectObj)); RoType(z) = ROt_NULL; Rchain(e, z); RXsize(e) = x; RXcursor(e) = 0; RYsize(e) = y; RYcursor(e) = 0; RXscale(e) = 1; RXshift(e) = 0; RYscale(e) = 1; RYshift(e) = 0; RHasGraph(e) = 0; } GEN rectcursor(long ne) { PariRect *e = check_rect_init(ne); return mkvec2s((long)RXcursor(e), (long)RYcursor(e)); } static void rectscale0(long ne, double x1, double x2, double y1, double y2) { PariRect *e = check_rect_init(ne); double x, y; x = RXshift(e) + RXscale(e) * RXcursor(e); y = RYshift(e) + RYscale(e) * RYcursor(e); RXscale(e) = RXsize(e)/(x2-x1); RXshift(e) = -x1*RXscale(e); RYscale(e) = RYsize(e)/(y1-y2); RYshift(e) = -y2*RYscale(e); RXcursor(e) = (x - RXshift(e)) / RXscale(e); RYcursor(e) = (y - RYshift(e)) / RYscale(e); } void rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2) { rectscale0(ne, gtodouble(x1), gtodouble(x2), gtodouble(y1), gtodouble(y2)); } static void rectmove0(long ne, double x, double y, long relative) { PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj1P)); if (relative) { RXcursor(e) += x; RYcursor(e) += y; } else { RXcursor(e) = x; RYcursor(e) = y; } RoType(z) = ROt_MV; RoMVx(z) = RXcursor(e) * RXscale(e) + RXshift(e); RoMVy(z) = RYcursor(e) * RYscale(e) + RYshift(e); Rchain(e, z); } void rectmove(long ne, GEN x, GEN y) { rectmove0(ne,gtodouble(x),gtodouble(y),0); } void rectrmove(long ne, GEN x, GEN y) { rectmove0(ne,gtodouble(x),gtodouble(y),1); } void rectpoint0(long ne, double x, double y,long relative) /* code = ROt_MV/ROt_PT */ { PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj1P)); if (relative) { RXcursor(e) += x; RYcursor(e) += y; } else { RXcursor(e) = x; RYcursor(e) = y; } RoPTx(z) = RXcursor(e)*RXscale(e) + RXshift(e); RoPTy(z) = RYcursor(e)*RYscale(e) + RYshift(e); RoType(z) = ( DTOL(RoPTx(z)) < 0 || DTOL(RoPTy(z)) < 0 || DTOL(RoPTx(z)) > RXsize(e) || DTOL(RoPTy(z)) > RYsize(e) ) ? ROt_MV : ROt_PT; Rchain(e, z); RoCol(z) = current_color[ne]; } void rectpoint(long ne, GEN x, GEN y) { rectpoint0(ne,gtodouble(x),gtodouble(y),0); } void rectrpoint(long ne, GEN x, GEN y) { rectpoint0(ne,gtodouble(x),gtodouble(y),1); } void rectcolor(long ne, long c) { long n = lg(pari_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)); current_color[ne] = c; } void rectline0(long ne, double gx2, double gy2, long relative) /* code = ROt_MV/ROt_LN */ { double dx,dy,dxy,xmin,xmax,ymin,ymax,x1,y1,x2,y2; PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P)); const double c = 1 + 1e-10; x1 = RXcursor(e)*RXscale(e) + RXshift(e); y1 = RYcursor(e)*RYscale(e) + RYshift(e); if (relative) { RXcursor(e)+=gx2; RYcursor(e)+=gy2; } else { RXcursor(e)=gx2; RYcursor(e)=gy2; } x2 = RXcursor(e)*RXscale(e) + RXshift(e); y2 = RYcursor(e)*RYscale(e) + RYshift(e); xmin = maxdd(mindd(x1,x2),0); xmax = mindd(maxdd(x1,x2),RXsize(e)); ymin = maxdd(mindd(y1,y2),0); ymax = mindd(maxdd(y1,y2),RYsize(e)); dxy = x1*y2 - y1*x2; dx = x2-x1; dy = y2-y1; if (dy) { if (dx*dy<0) { xmin = maxdd(xmin,(dxy+RYsize(e)*dx)/dy); xmax=mindd(xmax,dxy/dy); } else { xmin=maxdd(xmin,dxy/dy); xmax=mindd(xmax,(dxy+RYsize(e)*dx)/dy); } } if (dx) { if (dx*dy<0) { ymin=maxdd(ymin,(RXsize(e)*dy-dxy)/dx); ymax=mindd(ymax,-dxy/dx); } else { ymin=maxdd(ymin,-dxy/dx); ymax=mindd(ymax,(RXsize(e)*dy-dxy)/dx); } } RoLNx1(z) = xmin; RoLNx2(z) = xmax; if (dx*dy<0) { RoLNy1(z) = ymax; RoLNy2(z) = ymin; } else { RoLNy1(z) = ymin; RoLNy2(z) = ymax; } RoType(z) = (xmin>xmax*c || ymin>ymax*c) ? ROt_MV : ROt_LN; Rchain(e, z); RoCol(z) = current_color[ne]; } /* Given coordinates of ends of a line, and labels l1 l2 attached to the ends, plot ticks where the label coordinate takes "round" values */ static void rectticks(PARI_plot *WW, long ne, double dx1, double dy1, double dx2, double dy2, double l1, double l2, long flags) { long dx,dy,dxy,dxy1,x1,y1,x2,y2,nticks,n,n1,dn; double minstep, maxstep, step, l_min, l_max, minl, maxl, dl, dtx, dty, x, y; double ddx, ddy; const double mult[3] = { 2./1., 5./2., 10./5. }; PariRect *e = check_rect_init(ne); int do_double = !(flags & TICKS_NODOUBLE); x1 = DTOL(dx1*RXscale(e) + RXshift(e)); y1 = DTOL(dy1*RYscale(e) + RYshift(e)); x2 = DTOL(dx2*RXscale(e) + RXshift(e)); y2 = DTOL(dy2*RYscale(e) + RYshift(e)); dx = x2 - x1; dy = y2 - y1; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; dxy1 = maxss(dx, dy); dx /= WW->hunit; dy /= WW->vunit; if (dx > 1000 || dy > 1000) dxy = 1000; /* avoid overflow */ else dxy = (long)sqrt(dx*dx + dy*dy); nticks = (long) ((dxy + 2.5)/4); if (!nticks) return; /* Now we want to find nticks (or less) "round" numbers between l1 and l2. For our purpose round numbers have "last significant" digit either *) any; *) even; *) divisible by 5. We need to choose which alternative is better. */ if (l1 < l2) l_min = l1, l_max = l2; else l_min = l2, l_max = l1; minstep = (l_max - l_min)/(nticks + 1); maxstep = 2.5*(l_max - l_min); step = exp(log(10) * floor(log10(minstep))); if (!(flags & TICKS_ENDSTOO)) { double d = 2*(l_max - l_min)/dxy1; /* Two pixels off */ l_min += d; l_max -= d; } for (n = 0; ; n++) { if (step >= maxstep) return; if (step >= minstep) { minl = ceil(l_min/step); maxl = floor(l_max/step); if (minl <= maxl && maxl - minl + 1 <= nticks) { nticks = (long) (maxl - minl + 1); l_min = minl * step; l_max = maxl * step; break; } } step *= mult[ n % 3 ]; } /* Where to position doubleticks, variants: small: each 5, double: each 10 (n===2 mod 3) small: each 2, double: each 10 (n===1 mod 3) small: each 1, double: each 5 */ dn = (n % 3 == 2)? 2: 5; n1 = ((long)minl) % dn; /* unused if do_double = FALSE */ /* now l_min and l_max keep min/max values of l with ticks, and nticks is the number of ticks to draw. */ if (nticks == 1) ddx = ddy = 0; /* unused: for lint */ else { dl = (l_max - l_min)/(nticks - 1); ddx = (dx2 - dx1) * dl / (l2 - l1); ddy = (dy2 - dy1) * dl / (l2 - l1); } x = dx1 + (dx2 - dx1) * (l_min - l1) / (l2 - l1); y = dy1 + (dy2 - dy1) * (l_min - l1) / (l2 - l1); /* assume hunit and vunit form a square. For clockwise ticks: */ dtx = WW->hunit * dy/dxy * (y2 > y1 ? 1 : -1); /* y-coord runs down */ dty = WW->vunit * dx/dxy * (x2 > x1 ? 1 : -1); for (n = 0; n < nticks; n++) { RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P)); double lunit = WW->hunit > 1 ? 1.5 : 2; double l = (do_double && (n + n1) % dn == 0) ? lunit: 1; RoLNx1(z) = RoLNx2(z) = x*RXscale(e) + RXshift(e); RoLNy1(z) = RoLNy2(z) = y*RYscale(e) + RYshift(e); if (flags & TICKS_CLOCKW) { RoLNx1(z) += dtx*l; RoLNy1(z) -= dty*l; /* y-coord runs down */ } if (flags & TICKS_ACLOCKW) { RoLNx2(z) -= dtx*l; RoLNy2(z) += dty*l; /* y-coord runs down */ } RoType(z) = ROt_LN; Rchain(e, z); RoCol(z) = current_color[ne]; x += ddx; y += ddy; } } void rectline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),0); } void rectrline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),1); } void rectbox0(long ne, double gx2, double gy2, long relative) { double x1,y1,x2,y2,xmin,ymin,xmax,ymax; double xx,yy; PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObj2P)); x1 = RXcursor(e)*RXscale(e) + RXshift(e); y1 = RYcursor(e)*RYscale(e) + RYshift(e); if (relative) { xx = RXcursor(e)+gx2; yy = RYcursor(e)+gy2; } else { xx = gx2; yy = gy2; } x2 = xx*RXscale(e) + RXshift(e); y2 = yy*RYscale(e) + RYshift(e); xmin = maxdd(mindd(x1,x2),0); xmax = mindd(maxdd(x1,x2),RXsize(e)); ymin = maxdd(mindd(y1,y2),0); ymax = mindd(maxdd(y1,y2),RYsize(e)); RoType(z) = ROt_BX; RoBXx1(z) = xmin; RoBXy1(z) = ymin; RoBXx2(z) = xmax; RoBXy2(z) = ymax; Rchain(e, z); RoCol(z) = current_color[ne]; } void rectbox(long ne, GEN gx2, GEN gy2) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0); } void rectrbox(long ne, GEN gx2, GEN gy2) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1); } static void freeobj(RectObj *z) { switch(RoType(z)) { case ROt_MP: case ROt_ML: pari_free(RoMPxs(z)); pari_free(RoMPys(z)); break; case ROt_ST: pari_free(RoSTs(z)); break; } pari_free(z); } void killrect(long ne) { RectObj *z, *t; PariRect *e = check_rect_init(ne); current_color[ne]=DEFAULT_COLOR; z=RHead(e); RHead(e) = RTail(e) = NULL; RXsize(e) = RYsize(e) = 0; RXcursor(e) = RYcursor(e) = 0; RXscale(e) = RYscale(e) = 1; RXshift(e) = RYshift(e) = 0; while (z) { t = RoNext(z); freeobj(z); z = t; } } void rectpoints0(long ne, double *listx, double *listy, long lx) /* code = ROt_MP */ { double *ptx, *pty, x, y; long i, cp=0; PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjMP)); RoMPxs(z) = ptx = (double*) pari_malloc(lx*sizeof(double)); RoMPys(z) = pty = (double*) pari_malloc(lx*sizeof(double)); for (i=0; i=0 && y>=0 && x<=RXsize(e) && y<=RYsize(e)) { ptx[cp]=x; pty[cp]=y; cp++; } } RoType(z) = ROt_MP; RoMPcnt(z) = cp; Rchain(e, z); RoCol(z) = current_color[ne]; } void rectpoints(long ne, GEN listx, GEN listy) { long i,lx, tx=typ(listx), ty=typ(listy); double *px,*py; if (!is_matvec_t(tx) || !is_matvec_t(ty)) { rectpoint(ne, listx, listy); return; } lx = lg(listx); if (tx == t_MAT) pari_err_TYPE("rectpoints",listx); if (ty == t_MAT) pari_err_TYPE("rectpoints",listy); if (lg(listy) != lx) pari_err_DIM("rectpoints"); lx--; if (!lx) return; px = (double*) pari_malloc(lx*sizeof(double)); listx++; py = (double*) pari_malloc(lx*sizeof(double)); listy++; for (i=0; i xmax && x2 > xmax)) return 0; if (fabs(x1 - x2) < fabs(y1 - y2)) { /* Exchange x and y */ xy_exch = 1; dswap(xmin, ymin); dswap(x1, y1); dswap(xmax, ymax); dswap(x2, y2); } /* Build y as a function of x */ xi = x1; yi = y1; sl = x1==x2? 0: (y2 - yi)/(x2 - xi); if (x1 > x2) { x1_is_xmn = 0; xmn = x2; xmx = x1; } else { x1_is_xmn = 1; xmn = x1; xmx = x2; } if (xmn < xmin) { xmn = xmin; rc |= x1_is_xmn? CLIPLINE_CLIP_1: CLIPLINE_CLIP_2; } if (xmx > xmax) { xmx = xmax; rc |= x1_is_xmn? CLIPLINE_CLIP_2: CLIPLINE_CLIP_1; } if (xmn > xmx) return 0; ymn = yi + (xmn - xi)*sl; ymx = yi + (xmx - xi)*sl; if (sl < 0) t = ymn, ymn = ymx, ymx = t; if (ymn > ymax || ymx < ymin) return 0; if (rc & CLIPLINE_CLIP_1) x1 = x1_is_xmn? xmn: xmx; if (rc & CLIPLINE_CLIP_2) x2 = x1_is_xmn? xmx: xmn; /* Now we know there is an intersection, need to move x1 and x2 */ x1_is_ymn = ((sl >= 0) == (x1 < x2)); if (ymn < ymin) { double x = (ymin - yi)/sl + xi; /* slope != 0 ! */ if (x1_is_ymn) x1 = x, rc |= CLIPLINE_CLIP_1; else x2 = x, rc |= CLIPLINE_CLIP_2; } if (ymx > ymax) { double x = (ymax - yi)/sl + xi; /* slope != 0 ! */ if (x1_is_ymn) x2 = x, rc |= CLIPLINE_CLIP_2; else x1 = x, rc |= CLIPLINE_CLIP_1; } if (rc & CLIPLINE_CLIP_1) y1 = yi + (x1 - xi)*sl; if (rc & CLIPLINE_CLIP_2) y2 = yi + (x2 - xi)*sl; if (xy_exch) /* Exchange x and y */ *x1p = y1, *x2p = y2, *y1p = x1, *y2p = x2; else *x1p = x1, *x2p = x2, *y1p = y1, *y2p = y2; return rc; } void rectclip(long rect) { PariRect *s = check_rect_init(rect); RectObj *next, *R = RHead(s), **prevp = &RHead(s); double xmin = 0, xmax = RXsize(s); double ymin = 0, ymax = RYsize(s); for (; R; R = next) { int did_clip = 0; #define REMOVE() { *prevp = next; freeobj(R); break; } #define NEXT() { prevp = &RoNext(R); break; } next = RoNext(R); switch(RoType(R)) { case ROt_PT: if ( DTOL(RoPTx(R)) < xmin || DTOL(RoPTx(R)) > xmax || DTOL(RoPTy(R)) < ymin || DTOL(RoPTy(R)) > ymax) REMOVE(); NEXT(); case ROt_BX: if (RoLNx1(R) < xmin) RoLNx1(R) = xmin, did_clip = 1; if (RoLNx2(R) < xmin) RoLNx2(R) = xmin, did_clip = 1; if (RoLNy1(R) < ymin) RoLNy1(R) = ymin, did_clip = 1; if (RoLNy2(R) < ymin) RoLNy2(R) = ymin, did_clip = 1; if (RoLNx1(R) > xmax) RoLNx1(R) = xmax, did_clip = 1; if (RoLNx2(R) > xmax) RoLNx2(R) = xmax, did_clip = 1; if (RoLNy1(R) > ymax) RoLNy1(R) = ymax, did_clip = 1; if (RoLNy2(R) > ymax) RoLNy2(R) = ymax, did_clip = 1; /* Remove zero-size clipped boxes */ if (did_clip && RoLNx1(R) == RoLNx2(R) && RoLNy1(R) == RoLNy2(R)) REMOVE(); NEXT(); case ROt_LN: if (!clipline(xmin, xmax, ymin, ymax, &RoLNx1(R), &RoLNy1(R), &RoLNx2(R), &RoLNy2(R))) REMOVE(); NEXT(); case ROt_MP: { int c = RoMPcnt(R), f = 0, t = 0; while (f < c) { if ( DTOL(RoMPxs(R)[f]) >= xmin && DTOL(RoMPxs(R)[f]) <= xmax && DTOL(RoMPys(R)[f]) >= ymin && DTOL(RoMPys(R)[f]) <= ymax) { if (t != f) { RoMPxs(R)[t] = RoMPxs(R)[f]; RoMPys(R)[t] = RoMPys(R)[f]; } t++; } f++; } if (t == 0) REMOVE(); RoMPcnt(R) = t; NEXT(); } case ROt_ML: { /* Hard case. Break a multiline into several pieces * if some part is clipped. */ int c = RoMPcnt(R) - 1; int f = 0, t = 0, had_lines = 0, had_hole = 0, rc; double ox = RoMLxs(R)[0], oy = RoMLys(R)[0], oxn, oyn; while (f < c) { /* Endpoint of this segment is startpoint of next one: need to * preserve it if it is clipped. */ oxn = RoMLxs(R)[f+1]; oyn = RoMLys(R)[f+1]; rc = clipline(xmin, xmax, ymin, ymax, &ox, &oy, /* &RoMLxs(R)[f], &RoMLys(R)[f], */ &RoMLxs(R)[f+1], &RoMLys(R)[f+1]); RoMLxs(R)[f] = ox; ox = oxn; RoMLys(R)[f] = oy; oy = oyn; if (!rc) { if (had_lines) had_hole = 1; f++; continue; } if (!had_lines || (!(rc & CLIPLINE_CLIP_1) && !had_hole) ) { /* Continuous */ had_lines = 1; if (t != f) { if (t == 0) { RoMPxs(R)[t] = RoMPxs(R)[f]; RoMPys(R)[t] = RoMPys(R)[f]; } RoMPxs(R)[t+1] = RoMPxs(R)[f+1]; RoMPys(R)[t+1] = RoMPys(R)[f+1]; } t++; f++; if (rc & CLIPLINE_CLIP_2) had_hole = 1, RoMLcnt(R) = t+1; continue; } /* Is not continuous, automatically R is not pari_free()ed. */ t++; RoMLcnt(R) = t; if (rc & CLIPLINE_CLIP_2) { /* Needs separate entry */ RectObj *n = (RectObj*) pari_malloc(sizeof(RectObj2P)); RoType(n) = ROt_LN; RoCol(n) = RoCol(R); RoLNx1(n) = RoMLxs(R)[f]; RoLNy1(n) = RoMLys(R)[f]; RoLNx2(n) = RoMLxs(R)[f+1]; RoLNy2(n) = RoMLys(R)[f+1]; RoNext(n) = next; RoNext(R) = n; /* Restore the unclipped value: */ RoMLxs(R)[f+1] = oxn; RoMLys(R)[f+1] = oyn; f++; prevp = &RoNext(n); } if (f + 1 < c) { /* Are other lines */ RectObj *n = (RectObj*) pari_malloc(sizeof(RectObjMP)); RoType(n) = ROt_ML; RoCol(n) = RoCol(R); RoMLcnt(n) = c - f; RoMLxs(n) = (double*) pari_malloc(sizeof(double)*(c - f)); RoMLys(n) = (double*) pari_malloc(sizeof(double)*(c - f)); memcpy(RoMPxs(n),RoMPxs(R) + f, sizeof(double)*(c - f)); memcpy(RoMPys(n),RoMPys(R) + f, sizeof(double)*(c - f)); RoMPxs(n)[0] = oxn; RoMPys(n)[0] = oyn; RoNext(n) = next; RoNext(R) = n; next = n; } break; } if (t == 0) REMOVE(); NEXT(); } } #undef REMOVE #undef NEXT } } /********************************************************************/ /** **/ /** HI-RES PLOT **/ /** **/ /********************************************************************/ void Printx(dblPointList *f) { long i; printf("x: [%0.5g,%0.5g], y: [%0.5g,%0.5g]\n", f->xsml, f->xbig, f->ysml, f->ybig); for (i = 0; i < f->nb; i++) printf("%0.5g ", f->d[i]); printf("\n"); } static void Appendx(dblPointList *f, dblPointList *l,double x) { (l->d)[l->nb++]=x; if (x < f->xsml) f->xsml = x; if (x > f->xbig) f->xbig = x; } static void Appendy(dblPointList *f, dblPointList *l,double y) { (l->d)[l->nb++]=y; if (y < f->ysml) f->ysml = y; if (y > f->ybig) f->ybig = y; } static void get_xy(long cplx, GEN t, double *x, double *y) { if (cplx) { if (typ(t) == t_VEC) { if (lg(t) != 2) pari_err_DIM("get_xy"); t = gel(t,1); } *x = gtodouble( real_i(t) ); *y = gtodouble( imag_i(t) ); } else { if (typ(t) != t_VEC || lg(t) != 3) pari_err_DIM("get_xy"); *x = gtodouble( gel(t,1) ); *y = gtodouble( gel(t,2) ); } } /* t a t_VEC (possibly a scalar if cplx), get next (x,y) coordinate starting * at index *i [update i] */ static void get_xy_from_vec(long cplx, GEN t, long *i, double *x, double *y) { if (cplx) { GEN z; if (typ(t) == t_VEC) z = gel(t,(*i)++); else { z = t; (*i)++; } *x = gtodouble( real_i(z) ); *y = gtodouble( imag_i(z) ); } else { *x = gtodouble( gel(t, (*i)++) ); *y = gtodouble( gel(t, (*i)++) ); } } /* X,Y t_VEC, get next (x,y) coordinate starting at index i * Y ignored if (cplx) */ static void get_xy_from_vec2(long cplx, GEN X, GEN Y, long i, double *x, double *y) { if (cplx) { GEN z = gel(X,i); *x = gtodouble( real_i(z) ); *y = gtodouble( imag_i(z) ); } else { *x = gtodouble( gel(X, i) ); *y = gtodouble( gel(Y, i) ); } } /* Convert data from GEN to double before we call rectplothrawin. */ static dblPointList* gtodblList(GEN data, long flags) { dblPointList *l; double xsml, xbig, ysml, ybig; long nl=lg(data)-1, lx1, i, j; const long param = (flags & (PLOT_PARAMETRIC|PLOT_COMPLEX)); const long cplx = (flags & PLOT_COMPLEX); if (! is_vec_t(typ(data))) pari_err_TYPE("gtodblList",data); if (!nl) return NULL; lx1 = lg(gel(data,1)); if (!param && lx1 == 1) return NULL; if (nl == 1 && !cplx) pari_err_DIM("gtodblList"); /* Allocate memory, then convert coord. to double */ l = (dblPointList*)pari_malloc((cplx? 2*nl: nl)*sizeof(dblPointList)); for (i=0; id = (double*)pari_malloc(lx*sizeof(double)); LY->d = (double*)pari_malloc(lx*sizeof(double)); for (j=1; j<=lx; j++) { double xx, yy; get_xy_from_vec2(cplx, x,y, j, &xx,&yy); LX->d[j-1] = xx; LY->d[j-1] = yy; } LX->nb = LY->nb = lx; } /* Now compute extremas */ if (param) { l[0].nb = cplx? nl: nl/2; for (i=0; i < l[0].nb; i+=2) if (l[i+1].nb) break; if (i >= l[0].nb) { pari_free(l); return NULL; } xsml = xbig = l[i ].d[0]; ysml = ybig = l[i+1].d[0]; for (; i < l[0].nb; i+=2) { dblPointList *LX = l + i, *LY = l + (i+1); for (j=0; j < LY->nb; j++) { double x = LX->d[j], y = LY->d[j]; if (x < xsml) xsml = x; else if (x > xbig) xbig = x; if (y < ysml) ysml = y; else if (y > ybig) ybig = y; } } } else { l[0].nb = nl-1; xsml = xbig = l[0].d[0]; ysml = ybig = l[1].d[0]; for (j=0; j < l[1].nb; j++) { double x = l[0].d[j]; if (x < xsml) xsml = x; else if (x > xbig) xbig = x; } for (i=1; i <= l[0].nb; i++) for (j=0; j < l[i].nb; j++) { double y = l[i].d[j]; if (y < ysml) ysml = y; else if (y > ybig) ybig = y; } } l[0].xsml = xsml; l[0].xbig = xbig; l[0].ysml = ysml; l[0].ybig = ybig; return l; } /* (x+y)/2 */ static GEN rmiddle(GEN x, GEN y) { GEN z = addrr(x,y); shiftr_inplace(z,-1); return z; } static void single_recursion(dblPointList *pl,GEN code,GEN xleft,double yleft, GEN xright,double yright,long depth) { GEN xx; pari_sp av = avma; double yy, dy=pl[0].ybig - pl[0].ysml; if (depth==RECUR_MAXDEPTH) return; xx = rmiddle(xleft,xright); yy = gtodouble(READ_EXPR(code,xx)); if (dy && fabs(yleft+yright-2*yy)< dy*RECUR_PREC) return; single_recursion(pl,code, xleft,yleft, xx,yy, depth+1); Appendx(&pl[0],&pl[0],rtodbl(xx)); Appendy(&pl[0],&pl[1],yy); single_recursion(pl,code, xx,yy, xright,yright, depth+1); avma = av; } static void param_recursion(long cplx, dblPointList *pl,GEN code,GEN tleft,double xleft, double yleft, GEN tright,double xright,double yright, long depth) { GEN tt, p1; pari_sp av=avma; double xx, dy=pl[0].ybig - pl[0].ysml; double yy, dx=pl[0].xbig - pl[0].xsml; if (depth==RECUR_MAXDEPTH) return; tt = rmiddle(tleft,tright); p1 = READ_EXPR(code,tt); get_xy(cplx, p1, &xx,&yy); if (dx && dy && fabs(xleft+xright-2*xx) < dx*RECUR_PREC && fabs(yleft+yright-2*yy) < dy*RECUR_PREC) return; param_recursion(cplx, pl,code, tleft,xleft,yleft, tt,xx,yy, depth+1); Appendx(&pl[0],&pl[0],xx); Appendy(&pl[0],&pl[1],yy); param_recursion(cplx, pl,code, tt,xx,yy, tright,xright,yright, depth+1); avma = av; } /* Graph 'code' for parameter values in [a,b], using 'testpoints' sample * points (0 = use a default value); code is either a t_CLOSURE (from GP: * ploth, etc.) or a t_POL/t_VEC of two t_POLs from rectsplines. Returns a * dblPointList of (absolute) coordinates. */ static dblPointList * rectplothin(GEN a, GEN b, GEN code, long prec, ulong flags, long testpoints) { const double INF = 1./0.; const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); const long recur = flags & PLOT_RECURSIVE; const long cplx = flags & PLOT_COMPLEX; GEN t,dx,x; dblPointList *pl; long tx, i, j, sig, nc, nl, ncoords, nbpoints, non_vec = 0; pari_sp av = avma; sig = gcmp(b,a); if (!sig) return NULL; if (sig < 0) swap(a, b); if (testpoints) { if (testpoints < 2) pari_err_DOMAIN("ploth", "#points", "<", gen_2, stoi(testpoints)); } else { if (recur) testpoints = 8; else testpoints = param? 1500: 1000; } /* compute F(a) to determine nc = #curves; nl = #coord. lists */ x = gtofp(a, prec); if (typ(code) == t_CLOSURE) push_lex(x, code); t = READ_EXPR(code,x); tx = typ(t); if (param) { if (cplx) nc = nl = (tx == t_VEC)? lg(t)-1: 1; else { if (tx != t_VEC) pari_err_TYPE("ploth [not a t_VEC with PLOT_PARAMETRIC]", t); nl = lg(t)-1; nc = nl/2; if (odd(nl)) pari_err_TYPE("ploth [parametric ploc with odd # of components]",t); } } else { if (!is_matvec_t(tx)) { nl = 2; non_vec = 1; } else { if (tx != t_VEC) pari_err_TYPE("ploth [not a t_VEC]",t); nl = lg(t); } nc = nl-1; } if (!nc) { avma = av; return NULL; } if (recur && nc > 1) pari_err_TYPE("ploth [multi-curves cannot be plot recursively]",t); ncoords = cplx? 2*nl: nl; nbpoints = recur? testpoints << RECUR_MAXDEPTH: testpoints; pl=(dblPointList*) pari_malloc(ncoords*sizeof(dblPointList)); /* set [xy]sml,[xy]big to default values */ if (param) { pl[0].xsml = INF; pl[0].xbig =-INF; } else { pl[0].xsml = gtodouble(a); pl[0].xbig = gtodouble(b); } pl[0].ysml = INF; pl[0].ybig =-INF; for (i = 0; i < ncoords; i++) { pl[i].d = (double*)pari_malloc((nbpoints+1)*sizeof(double)); pl[i].nb=0; } dx = divru(gtofp(gsub(b,a),prec), testpoints-1); if (recur) /* recursive plot */ { double yleft, yright = 0; if (param) { GEN tleft = cgetr(prec), tright = cgetr(prec); double xleft, xright = 0; pari_sp av2 = avma; affgr(a,tleft); t = READ_EXPR(code,tleft); get_xy(cplx,t, &xleft,&yleft); for (i=0; i0) contains the number of points in the list * data[i].d (hopefully, data[2i].nb=data[2i+1].nb when i>0...) * * + If flags contain PLOT_PARAMETRIC, the array length should be * even, and successive pairs (data[2i].d, data[2i+1].d) represent * curves to plot. * * + If there is no such flag, the first element is an array with * x-coordinates and the following ones contain y-coordinates. * If grect >= 0, output to this rectwindow. Otherwise draw immediately to * screen (grect=-1) or to screen (grect=-2), using two drawing rectangles: * one for labels, another for graphs.*/ static GEN rectplothrawin(long grect, dblPointList *data, long flags) { const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); const pari_sp av = avma; PARI_plot *W; dblPointList y,x; double xsml, xbig, ysml, ybig; long ltype, max_graphcolors; long i,nc,nbpoints, w[2], wx[2], wy[2]; if (!data) return cgetg(1,t_VEC); x = data[0]; nc = x.nb; set_range(x.xsml, x.xbig, &xsml, &xbig); set_range(x.ysml, x.ybig, &ysml, &ybig); if (grect >= 0) /* output to rectwindow, no labels */ W = NULL; else { const long srect = NUMRECT-2; long lm, rm, tm, bm; if (grect == -1) /* output to screen */ { W = &pari_plot; PARI_get_plot(); } else /* output to file */ { W = &pari_psplot; PARI_get_psplot(); } grect = NUMRECT-1; /* left/right/top/bottom margin */ lm = W->fwidth*10; rm = W->hunit-1; tm = W->vunit-1; bm = W->vunit+W->fheight-1; w[0] = srect; wx[0] = 0; wy[0] = 0; w[1] = grect; wx[1] = lm; wy[1] = tm; /* Window (width x height) is given in pixels, correct pixels are 0..n-1, * whereas rect functions work with windows whose pixel range is [0,n] */ initrect(srect, W->width - 1, W->height - 1); rectlinetype(srect,-2); /* Frame */ current_color[srect] = DEFAULT_COLOR; initrect(grect, W->width - (lm+rm) - 1, W->height - (tm+bm) - 1); /* draw labels on srect */ put_label(srect, lm, 0, ybig, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirTOP); put_label(srect, lm, W->height-bm, ysml, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirVGAP); put_label(srect, lm, W->height - bm, xsml, RoSTdirLEFT|RoSTdirTOP); put_label(srect, W->width-rm-1, W->height-bm, xbig, RoSTdirRIGHT|RoSTdirTOP); } RHasGraph(check_rect(grect)) = 1; if (!(flags & PLOT_NO_RESCALE)) rectscale0(grect, xsml, xbig, ysml, ybig); if (!(flags & PLOT_NO_FRAME)) { int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0; PARI_plot *pl = W; if (!pl) { PARI_get_plot(); pl = &pari_plot; } rectlinetype(grect, -2); /* Frame. */ current_color[grect] = DEFAULT_COLOR; rectmove0(grect,xsml,ysml,0); rectbox0(grect,xbig,ybig,0); if (!(flags & PLOT_NO_TICK_X)) { rectticks(pl, grect, xsml, ysml, xbig, ysml, xsml, xbig, TICKS_CLOCKW | do_double); rectticks(pl, grect, xbig, ybig, xsml, ybig, xbig, xsml, TICKS_CLOCKW | do_double); } if (!(flags & PLOT_NO_TICK_Y)) { rectticks(pl, grect, xbig, ysml, xbig, ybig, ysml, ybig, TICKS_CLOCKW | do_double); rectticks(pl, grect, xsml, ybig, xsml, ysml, ybig, ysml, TICKS_CLOCKW | do_double); } } if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0)) { rectlinetype(grect, -1); /* Axes. */ current_color[grect] = AXIS_COLOR; rectmove0(grect,0.0,ysml,0); rectline0(grect,0.0,ybig,0); } if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0)) { rectlinetype(grect, -1); /* Axes. */ current_color[grect] = AXIS_COLOR; rectmove0(grect,xsml,0.0,0); rectline0(grect,xbig,0.0,0); } if (param) { i = 0; flags |= PLOT_PARAMETRIC; flags &= (~PLOT_COMPLEX); /* turn COMPLEX to PARAMETRIC*/ } else i = 1; max_graphcolors = lg(pari_graphcolors)-1; for (ltype = 0; ltype < nc; ltype++) { current_color[grect] = pari_graphcolors[1+(ltype%max_graphcolors)]; if (param) x = data[i++]; y = data[i++]; nbpoints = y.nb; if (flags & (PLOT_POINTS_LINES|PLOT_POINTS)) { rectlinetype(grect, rectpoint_itype + ltype); /* Graphs */ rectpointtype(grect,rectpoint_itype + ltype); /* Graphs */ rectpoints0(grect,x.d,y.d,nbpoints); if (!(flags & PLOT_POINTS_LINES)) continue; } if (flags & PLOT_SPLINES) { /* rectsplines will call us back with ltype == 0 */ int old = rectline_itype; rectline_itype = rectline_itype + ltype; rectsplines(grect,x.d,y.d,nbpoints,flags); rectline_itype = old; } else { rectlinetype(grect, rectline_itype + ltype); /* Graphs */ rectlines0(grect,x.d,y.d,nbpoints,0); } } for (i--; i>=0; i--) pari_free(data[i].d); pari_free(data); if (W) { if (W == &pari_plot) rectdraw0(w,wx,wy,2); else postdraw0(w,wx,wy,2, 0); killrect(w[1]); killrect(w[0]); } avma = av; retmkvec4(dbltor(xsml), dbltor(xbig), dbltor(ysml), dbltor(ybig)); } /*************************************************************************/ /* */ /* HI-RES FUNCTIONS */ /* */ /*************************************************************************/ GEN rectploth(long ne, GEN a,GEN b,GEN code, long prec,ulong flags,long tpts) { dblPointList *pl = rectplothin(a,b, code, prec, flags, tpts); return rectplothrawin(ne, pl, flags); } GEN rectplothraw(long ne, GEN data, long flags) { dblPointList *pl = gtodblList(data,flags); return rectplothrawin(ne, pl, flags); } static long plothraw_flags(long fl) { switch(fl) { case 0: return PLOT_PARAMETRIC|PLOT_POINTS; case 1: return PLOT_PARAMETRIC; default:return PLOT_PARAMETRIC|fl; } } static GEN plothraw0(long ne, GEN listx, GEN listy, long flags) { pari_sp av = avma; GEN z = rectplothraw(ne, mkvec2(listx,listy), plothraw_flags(flags)); return gerepileupto(av, z); } GEN plothraw(GEN listx, GEN listy, long flags) { return plothraw0(-1, listx, listy, flags); } GEN ploth(GEN a, GEN b, GEN code, long prec,long flags,long numpoints) { return rectploth(-1, a,b,code,prec,flags,numpoints); } GEN ploth2(GEN a, GEN b, GEN code, long prec) { return rectploth(-1, a,b,code,prec,PLOT_PARAMETRIC,0); } GEN plothmult(GEN a, GEN b, GEN code, long prec) { return rectploth(-1, a,b,code,prec,0,0); } GEN postplothraw(GEN listx, GEN listy, long flags) { return plothraw0(-2, listx, listy, flags); } GEN postploth(GEN a, GEN b, GEN code, long prec,long flags, long numpoints) { return rectploth(-2, a,b,code,prec, flags,numpoints); } GEN postploth2(GEN a, GEN b, GEN code, long prec, long numpoints) { return rectploth(-2, a,b,code,prec, PLOT_PARAMETRIC,numpoints); } GEN plothsizes(void) { return plothsizes_flag(0); } GEN plothsizes_flag(long flag) { GEN vect = cgetg(1+6,t_VEC); PARI_get_plot(); gel(vect,1) = stoi(pari_plot.width); gel(vect,2) = stoi(pari_plot.height); if (flag) { gel(vect,3) = dbltor(pari_plot.hunit*1.0/pari_plot.width); gel(vect,4) = dbltor(pari_plot.vunit*1.0/pari_plot.height); gel(vect,5) = dbltor(pari_plot.fwidth*1.0/pari_plot.width); gel(vect,6) = dbltor(pari_plot.fheight*1.0/pari_plot.height); } else { gel(vect,3) = stoi(pari_plot.hunit); gel(vect,4) = stoi(pari_plot.vunit); gel(vect,5) = stoi(pari_plot.fwidth); gel(vect,6) = stoi(pari_plot.fheight); } return vect; } void plot_count(long *w, long lw, col_counter rcolcnt) { RectObj *O; long col, i; for (col = 1; col < lg(pari_colormap)-1; col++) for (i = 0; i < ROt_MAX; i++) rcolcnt[col][i] = 0; for (i = 0; i < lw; i++) { PariRect *e = rectgraph[w[i]]; for (O = RHead(e); O; O=RoNext(O)) switch(RoType(O)) { case ROt_MP : rcolcnt[RoCol(O)][ROt_PT] += RoMPcnt(O); break; /* Multiple Point */ case ROt_PT : /* Point */ case ROt_LN : /* Line */ case ROt_BX : /* Box */ case ROt_ML : /* Multiple lines */ case ROt_ST : rcolcnt[RoCol(O)][RoType(O)]++; break; /* String */ } } } /*************************************************************************/ /* */ /* POSTSCRIPT OUTPUT */ /* */ /*************************************************************************/ static void PARI_get_psplot(void) { if (pari_psplot.init) return; pari_psplot.init = 1; pari_psplot.width = 1120 - 60; /* 1400 - 60 for hi-res */ pari_psplot.height= 800 - 40; /* 1120 - 60 for hi-res */ pari_psplot.fheight= 15; pari_psplot.fwidth = 6; pari_psplot.hunit = 5; pari_psplot.vunit = 5; } static void gendraw(GEN list, long ps, long flag) { long i,n,ne,*w,*x,*y; if (typ(list) != t_VEC) pari_err_TYPE("rectdraw",list); n = lg(list)-1; if (!n) return; if (n%3) pari_err_DIM("rectdraw"); n = n/3; w = (long*)pari_malloc(n*sizeof(long)); x = (long*)pari_malloc(n*sizeof(long)); y = (long*)pari_malloc(n*sizeof(long)); if (flag) PARI_get_plot(); for (i=0; i= l) { pari_warn(warner,"non-existent color: %ld", col); col = l-1; } color_to_rgb(gel(pari_colormap,col+1), &r, &g, &b); fprintf((FILE*)data,"%f %f %f setrgbcolor\n", r/255., g/255., b/255.); } static void ps_point(void *data, long x, long y) { fprintf((FILE*)data,"%ld %ld p\n",y,x); } static void ps_line(void *data, long x1, long y1, long x2, long y2) { fprintf((FILE*)data,"%ld %ld m %ld %ld l\n",y1,x1,y2,x2); fprintf((FILE*)data,"stroke\n"); } static void ps_rect(void *data, long x, long y, long w, long h) { fprintf((FILE*)data,"%ld %ld m %ld %ld l %ld %ld l %ld %ld l closepath\n",y,x, y,x+w, y+h,x+w, y+h,x); } static void ps_points(void *data, long nb, struct plot_points *p) { long i; for (i=0; isc = &ps_sc; S->pt = &ps_point; S->ln = &ps_line; S->bx = &ps_rect; S->mp = &ps_points; S->ml = &ps_lines; S->st = &ps_string; S->pl = &pari_psplot; S->data = (void*)f; } void postdraw0(long *w, long *x, long *y, long lw, long scale) { struct plot_eng plot; FILE *psfile; double xscale = 0.65, yscale = 0.65; long fontsize = 16; psfile = fopen(current_psfile, "a"); if (!psfile) pari_err_FILE("postscript file",current_psfile); if (scale) { double psxscale, psyscale; PARI_get_psplot(); PARI_get_plot(); psxscale = pari_psplot.width * 1.0/pari_plot.width ; psyscale = pari_psplot.height* 1.0/pari_plot.height; fontsize = (long) (fontsize/psxscale); xscale *= psxscale; yscale *= psyscale; } psplot_init(&plot, psfile, xscale, yscale, fontsize); gen_rectdraw0(&plot, w, x, y, lw, 1, 1); fprintf(psfile,"stroke showpage\n"); fclose(psfile); } #define RoColT(R) minss(numcolors,RoCol(R)) void gen_rectdraw0(struct plot_eng *eng, long *w, long *x, long *y, long lw, double xs, double ys) { void *data = eng->data; 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; for(i=0; isc(data,RoColT(R)); eng->pt(data, DTOL((RoPTx(R)+x0)*xs), DTOL((RoPTy(R)+y0)*ys)); break; case ROt_LN: eng->sc(data,RoColT(R)); eng->ln(data, DTOL((RoLNx1(R)+x0)*xs), DTOL((RoLNy1(R)+y0)*ys), DTOL((RoLNx2(R)+x0)*xs), DTOL((RoLNy2(R)+y0)*ys)); break; case ROt_BX: eng->sc(data,RoColT(R)); eng->bx(data, DTOL((RoBXx1(R)+x0)*xs), DTOL((RoBXy1(R)+y0)*ys), DTOL((RoBXx2(R)-RoBXx1(R))*xs), DTOL((RoBXy2(R)-RoBXy1(R))*ys)); break; case ROt_MP: { double *ptx = RoMPxs(R); double *pty = RoMPys(R); long nb = RoMPcnt(R); struct plot_points *points = (struct plot_points *) pari_malloc(sizeof(*points)*nb); for(j=0;jsc(data,RoColT(R)); eng->mp(data, nb, points); pari_free(points); break; } case ROt_ML: { double *ptx = RoMLxs(R); double *pty = RoMLys(R); long nb = RoMLcnt(R); struct plot_points *points = (struct plot_points *) pari_malloc(sizeof(*points)*nb); for(j=0;jsc(data,RoColT(R)); eng->ml(data, nb, points); pari_free(points); break; } case ROt_ST: { long dir = RoSTdir(R); long hjust = dir & RoSTdirHPOS_mask, hgap = dir & RoSTdirHGAP; long vjust = dir & RoSTdirVPOS_mask, vgap = dir & RoSTdirVGAP; char *text = RoSTs(R); long l = RoSTl(R); long x, y; long shift = (hjust == RoSTdirLEFT ? 0 : (hjust == RoSTdirRIGHT ? 2 : 1)); if (hgap) hgap = (hjust == RoSTdirLEFT) ? hgapsize : -hgapsize; if (vgap) vgap = (vjust == RoSTdirBOTTOM) ? 2*vgapsize : -2*vgapsize; if (vjust != RoSTdirBOTTOM) vgap -= ((vjust == RoSTdirTOP) ? 2 : 1)*(fheight - 1); x = DTOL((RoSTx(R) + x0 + hgap - (l * fwidth * shift)/2)*xs); y = DTOL((RoSTy(R) + y0 - vgap/2)*ys); eng->sc(data,RoColT(R)); eng->st(data, x, y, text, l); break; } default: break; } } } } /*************************************************************************/ /* */ /* RGB COLORS */ /* */ /*************************************************************************/ /* 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 = sprintf("0x%02x%02x%02x", split(/\s+/, $hex)); $name = lc($name); next if ($done{$name}); $done{$name} = 1; print "COL(\"$name\", $hex),\n"; } */ #define COL(x,y) {(void*)x,(void*)y,0,NULL} static hashentry col_list[] = { COL("", 0x000000), COL("snow", 0xfffafa), COL("ghostwhite", 0xf8f8ff), COL("whitesmoke", 0xf5f5f5), COL("gainsboro", 0xdcdcdc), COL("floralwhite", 0xfffaf0), COL("oldlace", 0xfdf5e6), COL("linen", 0xfaf0e6), COL("antiquewhite", 0xfaebd7), COL("papayawhip", 0xffefd5), COL("blanchedalmond", 0xffebcd), COL("bisque", 0xffe4c4), COL("peachpuff", 0xffdab9), COL("navajowhite", 0xffdead), COL("moccasin", 0xffe4b5), COL("cornsilk", 0xfff8dc), COL("ivory", 0xfffff0), COL("lemonchiffon", 0xfffacd), COL("seashell", 0xfff5ee), COL("honeydew", 0xf0fff0), COL("mintcream", 0xf5fffa), COL("azure", 0xf0ffff), COL("aliceblue", 0xf0f8ff), COL("lavender", 0xe6e6fa), COL("lavenderblush", 0xfff0f5), COL("mistyrose", 0xffe4e1), COL("white", 0xffffff), COL("black", 0x000000), COL("darkslategray", 0x2f4f4f), COL("darkslategrey", 0x2f4f4f), COL("dimgray", 0x696969), COL("dimgrey", 0x696969), COL("slategray", 0x708090), COL("slategrey", 0x708090), COL("lightslategray", 0x778899), COL("lightslategrey", 0x778899), COL("gray", 0xbebebe), COL("grey", 0xbebebe), COL("lightgrey", 0xd3d3d3), COL("lightgray", 0xd3d3d3), COL("midnightblue", 0x191970), COL("navy", 0x000080), COL("navyblue", 0x000080), COL("cornflowerblue", 0x6495ed), COL("darkslateblue", 0x483d8b), COL("slateblue", 0x6a5acd), COL("mediumslateblue", 0x7b68ee), COL("lightslateblue", 0x8470ff), COL("mediumblue", 0x0000cd), COL("royalblue", 0x4169e1), COL("blue", 0x0000ff), COL("dodgerblue", 0x1e90ff), COL("deepskyblue", 0x00bfff), COL("skyblue", 0x87ceeb), COL("lightskyblue", 0x87cefa), COL("steelblue", 0x4682b4), COL("lightsteelblue", 0xb0c4de), COL("lightblue", 0xadd8e6), COL("powderblue", 0xb0e0e6), COL("paleturquoise", 0xafeeee), COL("darkturquoise", 0x00ced1), COL("mediumturquoise", 0x48d1cc), COL("turquoise", 0x40e0d0), COL("cyan", 0x00ffff), COL("lightcyan", 0xe0ffff), COL("cadetblue", 0x5f9ea0), COL("mediumaquamarine", 0x66cdaa), COL("aquamarine", 0x7fffd4), COL("darkgreen", 0x006400), COL("darkolivegreen", 0x556b2f), COL("darkseagreen", 0x8fbc8f), COL("seagreen", 0x2e8b57), COL("mediumseagreen", 0x3cb371), COL("lightseagreen", 0x20b2aa), COL("palegreen", 0x98fb98), COL("springgreen", 0x00ff7f), COL("lawngreen", 0x7cfc00), COL("green", 0x00ff00), COL("chartreuse", 0x7fff00), COL("mediumspringgreen", 0x00fa9a), COL("greenyellow", 0xadff2f), COL("limegreen", 0x32cd32), COL("yellowgreen", 0x9acd32), COL("forestgreen", 0x228b22), COL("olivedrab", 0x6b8e23), COL("darkkhaki", 0xbdb76b), COL("khaki", 0xf0e68c), COL("palegoldenrod", 0xeee8aa), COL("lightgoldenrodyellow", 0xfafad2), COL("lightyellow", 0xffffe0), COL("yellow", 0xffff00), COL("gold", 0xffd700), COL("lightgoldenrod", 0xeedd82), COL("goldenrod", 0xdaa520), COL("darkgoldenrod", 0xb8860b), COL("rosybrown", 0xbc8f8f), COL("indianred", 0xcd5c5c), COL("saddlebrown", 0x8b4513), COL("sienna", 0xa0522d), COL("peru", 0xcd853f), COL("burlywood", 0xdeb887), COL("beige", 0xf5f5dc), COL("wheat", 0xf5deb3), COL("sandybrown", 0xf4a460), COL("tan", 0xd2b48c), COL("chocolate", 0xd2691e), COL("firebrick", 0xb22222), COL("brown", 0xa52a2a), COL("darksalmon", 0xe9967a), COL("salmon", 0xfa8072), COL("lightsalmon", 0xffa07a), COL("orange", 0xffa500), COL("darkorange", 0xff8c00), COL("coral", 0xff7f50), COL("lightcoral", 0xf08080), COL("tomato", 0xff6347), COL("orangered", 0xff4500), COL("red", 0xff0000), COL("hotpink", 0xff69b4), COL("deeppink", 0xff1493), COL("pink", 0xffc0cb), COL("lightpink", 0xffb6c1), COL("palevioletred", 0xdb7093), COL("maroon", 0xb03060), COL("mediumvioletred", 0xc71585), COL("violetred", 0xd02090), COL("magenta", 0xff00ff), COL("violet", 0xee82ee), COL("plum", 0xdda0dd), COL("orchid", 0xda70d6), COL("mediumorchid", 0xba55d3), COL("darkorchid", 0x9932cc), COL("darkviolet", 0x9400d3), COL("blueviolet", 0x8a2be2), COL("purple", 0xa020f0), COL("mediumpurple", 0x9370db), COL("thistle", 0xd8bfd8), COL("snow1", 0xfffafa), COL("snow2", 0xeee9e9), COL("snow3", 0xcdc9c9), COL("snow4", 0x8b8989), COL("seashell1", 0xfff5ee), COL("seashell2", 0xeee5de), COL("seashell3", 0xcdc5bf), COL("seashell4", 0x8b8682), COL("antiquewhite1", 0xffefdb), COL("antiquewhite2", 0xeedfcc), COL("antiquewhite3", 0xcdc0b0), COL("antiquewhite4", 0x8b8378), COL("bisque1", 0xffe4c4), COL("bisque2", 0xeed5b7), COL("bisque3", 0xcdb79e), COL("bisque4", 0x8b7d6b), COL("peachpuff1", 0xffdab9), COL("peachpuff2", 0xeecbad), COL("peachpuff3", 0xcdaf95), COL("peachpuff4", 0x8b7765), COL("navajowhite1", 0xffdead), COL("navajowhite2", 0xeecfa1), COL("navajowhite3", 0xcdb38b), COL("navajowhite4", 0x8b795e), COL("lemonchiffon1", 0xfffacd), COL("lemonchiffon2", 0xeee9bf), COL("lemonchiffon3", 0xcdc9a5), COL("lemonchiffon4", 0x8b8970), COL("cornsilk1", 0xfff8dc), COL("cornsilk2", 0xeee8cd), COL("cornsilk3", 0xcdc8b1), COL("cornsilk4", 0x8b8878), COL("ivory1", 0xfffff0), COL("ivory2", 0xeeeee0), COL("ivory3", 0xcdcdc1), COL("ivory4", 0x8b8b83), COL("honeydew1", 0xf0fff0), COL("honeydew2", 0xe0eee0), COL("honeydew3", 0xc1cdc1), COL("honeydew4", 0x838b83), COL("lavenderblush1", 0xfff0f5), COL("lavenderblush2", 0xeee0e5), COL("lavenderblush3", 0xcdc1c5), COL("lavenderblush4", 0x8b8386), COL("mistyrose1", 0xffe4e1), COL("mistyrose2", 0xeed5d2), COL("mistyrose3", 0xcdb7b5), COL("mistyrose4", 0x8b7d7b), COL("azure1", 0xf0ffff), COL("azure2", 0xe0eeee), COL("azure3", 0xc1cdcd), COL("azure4", 0x838b8b), COL("slateblue1", 0x836fff), COL("slateblue2", 0x7a67ee), COL("slateblue3", 0x6959cd), COL("slateblue4", 0x473c8b), COL("royalblue1", 0x4876ff), COL("royalblue2", 0x436eee), COL("royalblue3", 0x3a5fcd), COL("royalblue4", 0x27408b), COL("blue1", 0x0000ff), COL("blue2", 0x0000ee), COL("blue3", 0x0000cd), COL("blue4", 0x00008b), COL("dodgerblue1", 0x1e90ff), COL("dodgerblue2", 0x1c86ee), COL("dodgerblue3", 0x1874cd), COL("dodgerblue4", 0x104e8b), COL("steelblue1", 0x63b8ff), COL("steelblue2", 0x5cacee), COL("steelblue3", 0x4f94cd), COL("steelblue4", 0x36648b), COL("deepskyblue1", 0x00bfff), COL("deepskyblue2", 0x00b2ee), COL("deepskyblue3", 0x009acd), COL("deepskyblue4", 0x00688b), COL("skyblue1", 0x87ceff), COL("skyblue2", 0x7ec0ee), COL("skyblue3", 0x6ca6cd), COL("skyblue4", 0x4a708b), COL("lightskyblue1", 0xb0e2ff), COL("lightskyblue2", 0xa4d3ee), COL("lightskyblue3", 0x8db6cd), COL("lightskyblue4", 0x607b8b), COL("slategray1", 0xc6e2ff), COL("slategray2", 0xb9d3ee), COL("slategray3", 0x9fb6cd), COL("slategray4", 0x6c7b8b), COL("lightsteelblue1", 0xcae1ff), COL("lightsteelblue2", 0xbcd2ee), COL("lightsteelblue3", 0xa2b5cd), COL("lightsteelblue4", 0x6e7b8b), COL("lightblue1", 0xbfefff), COL("lightblue2", 0xb2dfee), COL("lightblue3", 0x9ac0cd), COL("lightblue4", 0x68838b), COL("lightcyan1", 0xe0ffff), COL("lightcyan2", 0xd1eeee), COL("lightcyan3", 0xb4cdcd), COL("lightcyan4", 0x7a8b8b), COL("paleturquoise1", 0xbbffff), COL("paleturquoise2", 0xaeeeee), COL("paleturquoise3", 0x96cdcd), COL("paleturquoise4", 0x668b8b), COL("cadetblue1", 0x98f5ff), COL("cadetblue2", 0x8ee5ee), COL("cadetblue3", 0x7ac5cd), COL("cadetblue4", 0x53868b), COL("turquoise1", 0x00f5ff), COL("turquoise2", 0x00e5ee), COL("turquoise3", 0x00c5cd), COL("turquoise4", 0x00868b), COL("cyan1", 0x00ffff), COL("cyan2", 0x00eeee), COL("cyan3", 0x00cdcd), COL("cyan4", 0x008b8b), COL("darkslategray1", 0x97ffff), COL("darkslategray2", 0x8deeee), COL("darkslategray3", 0x79cdcd), COL("darkslategray4", 0x528b8b), COL("aquamarine1", 0x7fffd4), COL("aquamarine2", 0x76eec6), COL("aquamarine3", 0x66cdaa), COL("aquamarine4", 0x458b74), COL("darkseagreen1", 0xc1ffc1), COL("darkseagreen2", 0xb4eeb4), COL("darkseagreen3", 0x9bcd9b), COL("darkseagreen4", 0x698b69), COL("seagreen1", 0x54ff9f), COL("seagreen2", 0x4eee94), COL("seagreen3", 0x43cd80), COL("seagreen4", 0x2e8b57), COL("palegreen1", 0x9aff9a), COL("palegreen2", 0x90ee90), COL("palegreen3", 0x7ccd7c), COL("palegreen4", 0x548b54), COL("springgreen1", 0x00ff7f), COL("springgreen2", 0x00ee76), COL("springgreen3", 0x00cd66), COL("springgreen4", 0x008b45), COL("green1", 0x00ff00), COL("green2", 0x00ee00), COL("green3", 0x00cd00), COL("green4", 0x008b00), COL("chartreuse1", 0x7fff00), COL("chartreuse2", 0x76ee00), COL("chartreuse3", 0x66cd00), COL("chartreuse4", 0x458b00), COL("olivedrab1", 0xc0ff3e), COL("olivedrab2", 0xb3ee3a), COL("olivedrab3", 0x9acd32), COL("olivedrab4", 0x698b22), COL("darkolivegreen1", 0xcaff70), COL("darkolivegreen2", 0xbcee68), COL("darkolivegreen3", 0xa2cd5a), COL("darkolivegreen4", 0x6e8b3d), COL("khaki1", 0xfff68f), COL("khaki2", 0xeee685), COL("khaki3", 0xcdc673), COL("khaki4", 0x8b864e), COL("lightgoldenrod1", 0xffec8b), COL("lightgoldenrod2", 0xeedc82), COL("lightgoldenrod3", 0xcdbe70), COL("lightgoldenrod4", 0x8b814c), COL("lightyellow1", 0xffffe0), COL("lightyellow2", 0xeeeed1), COL("lightyellow3", 0xcdcdb4), COL("lightyellow4", 0x8b8b7a), COL("yellow1", 0xffff00), COL("yellow2", 0xeeee00), COL("yellow3", 0xcdcd00), COL("yellow4", 0x8b8b00), COL("gold1", 0xffd700), COL("gold2", 0xeec900), COL("gold3", 0xcdad00), COL("gold4", 0x8b7500), COL("goldenrod1", 0xffc125), COL("goldenrod2", 0xeeb422), COL("goldenrod3", 0xcd9b1d), COL("goldenrod4", 0x8b6914), COL("darkgoldenrod1", 0xffb90f), COL("darkgoldenrod2", 0xeead0e), COL("darkgoldenrod3", 0xcd950c), COL("darkgoldenrod4", 0x8b6508), COL("rosybrown1", 0xffc1c1), COL("rosybrown2", 0xeeb4b4), COL("rosybrown3", 0xcd9b9b), COL("rosybrown4", 0x8b6969), COL("indianred1", 0xff6a6a), COL("indianred2", 0xee6363), COL("indianred3", 0xcd5555), COL("indianred4", 0x8b3a3a), COL("sienna1", 0xff8247), COL("sienna2", 0xee7942), COL("sienna3", 0xcd6839), COL("sienna4", 0x8b4726), COL("burlywood1", 0xffd39b), COL("burlywood2", 0xeec591), COL("burlywood3", 0xcdaa7d), COL("burlywood4", 0x8b7355), COL("wheat1", 0xffe7ba), COL("wheat2", 0xeed8ae), COL("wheat3", 0xcdba96), COL("wheat4", 0x8b7e66), COL("tan1", 0xffa54f), COL("tan2", 0xee9a49), COL("tan3", 0xcd853f), COL("tan4", 0x8b5a2b), COL("chocolate1", 0xff7f24), COL("chocolate2", 0xee7621), COL("chocolate3", 0xcd661d), COL("chocolate4", 0x8b4513), COL("firebrick1", 0xff3030), COL("firebrick2", 0xee2c2c), COL("firebrick3", 0xcd2626), COL("firebrick4", 0x8b1a1a), COL("brown1", 0xff4040), COL("brown2", 0xee3b3b), COL("brown3", 0xcd3333), COL("brown4", 0x8b2323), COL("salmon1", 0xff8c69), COL("salmon2", 0xee8262), COL("salmon3", 0xcd7054), COL("salmon4", 0x8b4c39), COL("lightsalmon1", 0xffa07a), COL("lightsalmon2", 0xee9572), COL("lightsalmon3", 0xcd8162), COL("lightsalmon4", 0x8b5742), COL("orange1", 0xffa500), COL("orange2", 0xee9a00), COL("orange3", 0xcd8500), COL("orange4", 0x8b5a00), COL("darkorange1", 0xff7f00), COL("darkorange2", 0xee7600), COL("darkorange3", 0xcd6600), COL("darkorange4", 0x8b4500), COL("coral1", 0xff7256), COL("coral2", 0xee6a50), COL("coral3", 0xcd5b45), COL("coral4", 0x8b3e2f), COL("tomato1", 0xff6347), COL("tomato2", 0xee5c42), COL("tomato3", 0xcd4f39), COL("tomato4", 0x8b3626), COL("orangered1", 0xff4500), COL("orangered2", 0xee4000), COL("orangered3", 0xcd3700), COL("orangered4", 0x8b2500), COL("red1", 0xff0000), COL("red2", 0xee0000), COL("red3", 0xcd0000), COL("red4", 0x8b0000), COL("debianred", 0xd70751), COL("deeppink1", 0xff1493), COL("deeppink2", 0xee1289), COL("deeppink3", 0xcd1076), COL("deeppink4", 0x8b0a50), COL("hotpink1", 0xff6eb4), COL("hotpink2", 0xee6aa7), COL("hotpink3", 0xcd6090), COL("hotpink4", 0x8b3a62), COL("pink1", 0xffb5c5), COL("pink2", 0xeea9b8), COL("pink3", 0xcd919e), COL("pink4", 0x8b636c), COL("lightpink1", 0xffaeb9), COL("lightpink2", 0xeea2ad), COL("lightpink3", 0xcd8c95), COL("lightpink4", 0x8b5f65), COL("palevioletred1", 0xff82ab), COL("palevioletred2", 0xee799f), COL("palevioletred3", 0xcd6889), COL("palevioletred4", 0x8b475d), COL("maroon1", 0xff34b3), COL("maroon2", 0xee30a7), COL("maroon3", 0xcd2990), COL("maroon4", 0x8b1c62), COL("violetred1", 0xff3e96), COL("violetred2", 0xee3a8c), COL("violetred3", 0xcd3278), COL("violetred4", 0x8b2252), COL("magenta1", 0xff00ff), COL("magenta2", 0xee00ee), COL("magenta3", 0xcd00cd), COL("magenta4", 0x8b008b), COL("orchid1", 0xff83fa), COL("orchid2", 0xee7ae9), COL("orchid3", 0xcd69c9), COL("orchid4", 0x8b4789), COL("plum1", 0xffbbff), COL("plum2", 0xeeaeee), COL("plum3", 0xcd96cd), COL("plum4", 0x8b668b), COL("mediumorchid1", 0xe066ff), COL("mediumorchid2", 0xd15fee), COL("mediumorchid3", 0xb452cd), COL("mediumorchid4", 0x7a378b), COL("darkorchid1", 0xbf3eff), COL("darkorchid2", 0xb23aee), COL("darkorchid3", 0x9a32cd), COL("darkorchid4", 0x68228b), COL("purple1", 0x9b30ff), COL("purple2", 0x912cee), COL("purple3", 0x7d26cd), COL("purple4", 0x551a8b), COL("mediumpurple1", 0xab82ff), COL("mediumpurple2", 0x9f79ee), COL("mediumpurple3", 0x8968cd), COL("mediumpurple4", 0x5d478b), COL("thistle1", 0xffe1ff), COL("thistle2", 0xeed2ee), COL("thistle3", 0xcdb5cd), COL("thistle4", 0x8b7b8b), COL("gray0", 0x000000), COL("grey0", 0x000000), COL("gray1", 0x030303), COL("grey1", 0x030303), COL("gray2", 0x050505), COL("grey2", 0x050505), COL("gray3", 0x080808), COL("grey3", 0x080808), COL("gray4", 0x0a0a0a), COL("grey4", 0x0a0a0a), COL("gray5", 0x0d0d0d), COL("grey5", 0x0d0d0d), COL("gray6", 0x0f0f0f), COL("grey6", 0x0f0f0f), COL("gray7", 0x121212), COL("grey7", 0x121212), COL("gray8", 0x141414), COL("grey8", 0x141414), COL("gray9", 0x171717), COL("grey9", 0x171717), COL("gray10", 0x1a1a1a), COL("grey10", 0x1a1a1a), COL("gray11", 0x1c1c1c), COL("grey11", 0x1c1c1c), COL("gray12", 0x1f1f1f), COL("grey12", 0x1f1f1f), COL("gray13", 0x212121), COL("grey13", 0x212121), COL("gray14", 0x242424), COL("grey14", 0x242424), COL("gray15", 0x262626), COL("grey15", 0x262626), COL("gray16", 0x292929), COL("grey16", 0x292929), COL("gray17", 0x2b2b2b), COL("grey17", 0x2b2b2b), COL("gray18", 0x2e2e2e), COL("grey18", 0x2e2e2e), COL("gray19", 0x303030), COL("grey19", 0x303030), COL("gray20", 0x333333), COL("grey20", 0x333333), COL("gray21", 0x363636), COL("grey21", 0x363636), COL("gray22", 0x383838), COL("grey22", 0x383838), COL("gray23", 0x3b3b3b), COL("grey23", 0x3b3b3b), COL("gray24", 0x3d3d3d), COL("grey24", 0x3d3d3d), COL("gray25", 0x404040), COL("grey25", 0x404040), COL("gray26", 0x424242), COL("grey26", 0x424242), COL("gray27", 0x454545), COL("grey27", 0x454545), COL("gray28", 0x474747), COL("grey28", 0x474747), COL("gray29", 0x4a4a4a), COL("grey29", 0x4a4a4a), COL("gray30", 0x4d4d4d), COL("grey30", 0x4d4d4d), COL("gray31", 0x4f4f4f), COL("grey31", 0x4f4f4f), COL("gray32", 0x525252), COL("grey32", 0x525252), COL("gray33", 0x545454), COL("grey33", 0x545454), COL("gray34", 0x575757), COL("grey34", 0x575757), COL("gray35", 0x595959), COL("grey35", 0x595959), COL("gray36", 0x5c5c5c), COL("grey36", 0x5c5c5c), COL("gray37", 0x5e5e5e), COL("grey37", 0x5e5e5e), COL("gray38", 0x616161), COL("grey38", 0x616161), COL("gray39", 0x636363), COL("grey39", 0x636363), COL("gray40", 0x666666), COL("grey40", 0x666666), COL("gray41", 0x696969), COL("grey41", 0x696969), COL("gray42", 0x6b6b6b), COL("grey42", 0x6b6b6b), COL("gray43", 0x6e6e6e), COL("grey43", 0x6e6e6e), COL("gray44", 0x707070), COL("grey44", 0x707070), COL("gray45", 0x737373), COL("grey45", 0x737373), COL("gray46", 0x757575), COL("grey46", 0x757575), COL("gray47", 0x787878), COL("grey47", 0x787878), COL("gray48", 0x7a7a7a), COL("grey48", 0x7a7a7a), COL("gray49", 0x7d7d7d), COL("grey49", 0x7d7d7d), COL("gray50", 0x7f7f7f), COL("grey50", 0x7f7f7f), COL("gray51", 0x828282), COL("grey51", 0x828282), COL("gray52", 0x858585), COL("grey52", 0x858585), COL("gray53", 0x878787), COL("grey53", 0x878787), COL("gray54", 0x8a8a8a), COL("grey54", 0x8a8a8a), COL("gray55", 0x8c8c8c), COL("grey55", 0x8c8c8c), COL("gray56", 0x8f8f8f), COL("grey56", 0x8f8f8f), COL("gray57", 0x919191), COL("grey57", 0x919191), COL("gray58", 0x949494), COL("grey58", 0x949494), COL("gray59", 0x969696), COL("grey59", 0x969696), COL("gray60", 0x999999), COL("grey60", 0x999999), COL("gray61", 0x9c9c9c), COL("grey61", 0x9c9c9c), COL("gray62", 0x9e9e9e), COL("grey62", 0x9e9e9e), COL("gray63", 0xa1a1a1), COL("grey63", 0xa1a1a1), COL("gray64", 0xa3a3a3), COL("grey64", 0xa3a3a3), COL("gray65", 0xa6a6a6), COL("grey65", 0xa6a6a6), COL("gray66", 0xa8a8a8), COL("grey66", 0xa8a8a8), COL("gray67", 0xababab), COL("grey67", 0xababab), COL("gray68", 0xadadad), COL("grey68", 0xadadad), COL("gray69", 0xb0b0b0), COL("grey69", 0xb0b0b0), COL("gray70", 0xb3b3b3), COL("grey70", 0xb3b3b3), COL("gray71", 0xb5b5b5), COL("grey71", 0xb5b5b5), COL("gray72", 0xb8b8b8), COL("grey72", 0xb8b8b8), COL("gray73", 0xbababa), COL("grey73", 0xbababa), COL("gray74", 0xbdbdbd), COL("grey74", 0xbdbdbd), COL("gray75", 0xbfbfbf), COL("grey75", 0xbfbfbf), COL("gray76", 0xc2c2c2), COL("grey76", 0xc2c2c2), COL("gray77", 0xc4c4c4), COL("grey77", 0xc4c4c4), COL("gray78", 0xc7c7c7), COL("grey78", 0xc7c7c7), COL("gray79", 0xc9c9c9), COL("grey79", 0xc9c9c9), COL("gray80", 0xcccccc), COL("grey80", 0xcccccc), COL("gray81", 0xcfcfcf), COL("grey81", 0xcfcfcf), COL("gray82", 0xd1d1d1), COL("grey82", 0xd1d1d1), COL("gray83", 0xd4d4d4), COL("grey83", 0xd4d4d4), COL("gray84", 0xd6d6d6), COL("grey84", 0xd6d6d6), COL("gray85", 0xd9d9d9), COL("grey85", 0xd9d9d9), COL("gray86", 0xdbdbdb), COL("grey86", 0xdbdbdb), COL("gray87", 0xdedede), COL("grey87", 0xdedede), COL("gray88", 0xe0e0e0), COL("grey88", 0xe0e0e0), COL("gray89", 0xe3e3e3), COL("grey89", 0xe3e3e3), COL("gray90", 0xe5e5e5), COL("grey90", 0xe5e5e5), COL("gray91", 0xe8e8e8), COL("grey91", 0xe8e8e8), COL("gray92", 0xebebeb), COL("grey92", 0xebebeb), COL("gray93", 0xededed), COL("grey93", 0xededed), COL("gray94", 0xf0f0f0), COL("grey94", 0xf0f0f0), COL("gray95", 0xf2f2f2), COL("grey95", 0xf2f2f2), COL("gray96", 0xf5f5f5), COL("grey96", 0xf5f5f5), COL("gray97", 0xf7f7f7), COL("grey97", 0xf7f7f7), COL("gray98", 0xfafafa), COL("grey98", 0xfafafa), COL("gray99", 0xfcfcfc), COL("grey99", 0xfcfcfc), COL("gray100", 0xffffff), COL("grey100", 0xffffff), COL("darkgrey", 0xa9a9a9), COL("darkgray", 0xa9a9a9), COL("darkblue", 0x00008b), COL("darkcyan", 0x008b8b), COL("darkmagenta", 0x8b008b), COL("darkred", 0x8b0000), COL("lightgreen", 0x90ee90), COL(NULL,0) /* sentinel */ }; #undef COL static void colorname_to_rgb(const char *s, int *r, int *g, int *b) { hashentry *ep; long rgb; if (!rgb_colors) rgb_colors = hashstr_import_static(col_list, 1000); ep = hash_search(rgb_colors, (void*)s); if (!ep) pari_err(e_MISC, "unknown color %s", s); rgb = (long)ep->val; *b = rgb & 0xff; rgb >>= 8; *g = rgb & 0xff; rgb >>= 8; *r = rgb; } void color_to_rgb(GEN c, int *r, int *g, int *b) { switch(typ(c)) { case t_STR: colorname_to_rgb(GSTR(c), r,g,b); break; default: /* t_VECSMALL: */ *r = c[1]; *g = c[2]; *b = c[3]; break; } } pari-2.7.5/src/graph/rect.h0000644000175000017500000002165712366172547014134 0ustar billbill/* 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. */ BEGINEXTERN #define PLOT_NAME_LEN 20 typedef struct PARI_plot { long width; long height; long hunit; long vunit; long fwidth; long fheight; long init; char name[PLOT_NAME_LEN+1]; } PARI_plot; extern PARI_plot pari_plot, pari_psplot; extern PARI_plot *pari_plot_engine; typedef struct dblPointList{ double *d; /* data */ long nb; /* number of elements */ double xsml,xbig,ysml,ybig; /* extrema */ } dblPointList; typedef struct RectObj { struct RectObj *next; long code,color; } RectObj; typedef struct PariRect { RectObj *head,*tail; long sizex,sizey; double cursorx,cursory; double xscale,yscale; double xshift,yshift; long has_graph; /* xy-ranges of this rectangle should be used for interactive operations. */ } PariRect; /* The structures below are "subclasses" of RectObj. */ typedef struct RectObj1P { struct RectObj *next; long code,color; double x,y; } RectObj1P; typedef struct RectObj2P { struct RectObj *next; long code,color; double x1,y1; double x2,y2; } RectObj2P; typedef struct RectObjMP { struct RectObj *next; long code,color; long count; double *xs,*ys; } RectObjMP; typedef struct RectObjST { struct RectObj *next; long code,color; long length; char *s; double x,y; long dir; } RectObjST; typedef struct RectObjPN { struct RectObj *next; long code,color; long pen; } RectObjPN; typedef struct RectObjPS { struct RectObj *next; long code,color; double size; } RectObjPS; struct plot_points { long x, y; }; struct plot_eng { PARI_plot *pl; void *data; void (*sc)(void *data, long col); void (*pt)(void *data, long x, long y); void (*ln)(void *data, long x1, long y1, long x2, long y2); void (*bx)(void *data, long x, long y, long w, long h); void (*mp)(void *data, long n, struct plot_points *points); void (*ml)(void *data, long n, struct plot_points *points); void (*st)(void *data, long x, long y, char *s, long l); }; #define ROt_MV 0 /* Move */ #define ROt_PT 1 /* Point */ #define ROt_LN 2 /* Line */ #define ROt_BX 3 /* Box */ #define ROt_MP 4 /* Multiple point */ #define ROt_ML 5 /* Multiple lines */ #define ROt_ST 6 /* String */ #define ROt_PTT 7 /* Point type change */ #define ROt_LNT 8 /* Line type change */ #define ROt_PTS 9 /* Point size change */ #define ROt_NULL 10 /* To be the start of the chain */ #define ROt_MAX 10 /* Maximal type */ /* Pointer conversion. */ #define RoMV(rop) ((RectObj1P*)rop) #define RoPT(rop) ((RectObj1P*)rop) #define RoLN(rop) ((RectObj2P*)rop) #define RoBX(rop) ((RectObj2P*)rop) #define RoMP(rop) ((RectObjMP*)rop) #define RoML(rop) ((RectObjMP*)rop) #define RoST(rop) ((RectObjST*)rop) #define RoPTT(rop) ((RectObjPN*)rop) #define RoPTS(rop) ((RectObjPS*)rop) #define RoLNT(rop) ((RectObjPN*)rop) #define RoNULL(rop) ((RectObj*)rop) /* All the access to the rectangle data _should_ go via these macros! */ #define RHead(rp) ((rp)->head) #define RTail(rp) ((rp)->tail) #define RXsize(rp) ((rp)->sizex) #define RYsize(rp) ((rp)->sizey) #define RXcursor(rp) ((rp)->cursorx) #define RYcursor(rp) ((rp)->cursory) #define RXshift(rp) ((rp)->xshift) #define RYshift(rp) ((rp)->yshift) #define RXscale(rp) ((rp)->xscale) #define RYscale(rp) ((rp)->yscale) #define RHasGraph(rp) ((rp)->has_graph) #define RoNext(rop) ((rop)->next) #define RoType(rop) ((rop)->code) #define RoCol(rop) ((rop)->color) #define RoMVx(rop) (RoMV(rop)->x) #define RoMVy(rop) (RoMV(rop)->y) #define RoPTx(rop) (RoPT(rop)->x) #define RoPTy(rop) (RoPT(rop)->y) #define RoLNx1(rop) (RoLN(rop)->x1) #define RoLNy1(rop) (RoLN(rop)->y1) #define RoLNx2(rop) (RoLN(rop)->x2) #define RoLNy2(rop) (RoLN(rop)->y2) #define RoBXx1(rop) (RoBX(rop)->x1) #define RoBXy1(rop) (RoBX(rop)->y1) #define RoBXx2(rop) (RoBX(rop)->x2) #define RoBXy2(rop) (RoBX(rop)->y2) #define RoMPcnt(rop) (RoMP(rop)->count) #define RoMPxs(rop) (RoMP(rop)->xs) #define RoMPys(rop) (RoMP(rop)->ys) #define RoMLcnt(rop) (RoML(rop)->count) #define RoMLxs(rop) (RoML(rop)->xs) #define RoMLys(rop) (RoML(rop)->ys) #define RoSTs(rop) (RoST(rop)->s) #define RoSTl(rop) (RoST(rop)->length) #define RoSTx(rop) (RoST(rop)->x) #define RoSTy(rop) (RoST(rop)->y) #define RoSTdir(rop) (RoST(rop)->dir) #define RoSTdirLEFT 0x00 #define RoSTdirCENTER 0x01 #define RoSTdirRIGHT 0x02 #define RoSTdirHPOS_mask 0x03 #define RoSTdirBOTTOM 0x00 #define RoSTdirVCENTER 0x04 #define RoSTdirTOP 0x08 #define RoSTdirVPOS_mask 0x0c #define RoSTdirHGAP 0x10 #define RoSTdirVGAP 0x20 #define RoPTTpen(rop) (RoPTT(rop)->pen) #define RoLNTpen(rop) (RoLNT(rop)->pen) #define RoPTSsize(rop) (RoPTS(rop)->size) #define PL_POINTS 1 #define PLOT_PARAMETRIC 0x00001 #define PLOT_RECURSIVE 0x00002 #define PLOT_NO_RESCALE 0x00004 #define PLOT_NO_AXE_X 0x00008 #define PLOT_NO_AXE_Y 0x00010 #define PLOT_NO_FRAME 0x00020 #define PLOT_POINTS 0x00040 #define PLOT_POINTS_LINES 0x00080 #define PLOT_SPLINES 0x00100 #define PLOT_NO_TICK_X 0x00200 #define PLOT_NO_TICK_Y 0x00400 #define PLOT_NODOUBLETICK 0x00800 #define PLOT_COMPLEX 0x01000 #define RECT_CP_RELATIVE 0x1 #define RECT_CP_NW 0x0 #define RECT_CP_SW 0x2 #define RECT_CP_SE 0x4 #define RECT_CP_NE 0x6 #define TICKS_CLOCKW 1 /* Draw in clockwise direction */ #define TICKS_ACLOCKW 2 /* Draw in anticlockwise direction */ #define TICKS_ENDSTOO 4 /* Draw at endspoints if needed */ #define TICKS_NODOUBLE 8 /* Do not draw double-length ticks */ /* Not implemented yet */ #define TICKS_COORD 16 /* Output [x,y,l,isdbl] for each tick */ #define TICKS_RELATIVE 32 /* x,y-coordinates are relative */ extern long rectpoint_itype; extern long rectline_itype; /* plotport.c */ typedef long (*col_counter)[ROt_MAX]; void color_to_rgb(GEN c, int *r, int *g, int *b); void initrect(long ne, long x, long y); void initrect_gen(long ne, GEN x, GEN y, long flag); void killrect(long ne); void plot_count(long *w, long lw, col_counter rcolcnt); void plot(GEN a, GEN b, GEN code, GEN ysmlu, GEN ybigu, long prec); GEN ploth(GEN a, GEN b, GEN code, long prec, long flag, long numpoints); GEN ploth2(GEN a, GEN b, GEN code, long prec); GEN plothmult(GEN a, GEN b, GEN code, long prec); GEN plothraw(GEN listx, GEN listy, long flag); GEN plothsizes(void); GEN plothsizes_flag(long flag); void postdraw(GEN list); void postdraw_flag(GEN list, long flag); GEN postploth(GEN a,GEN b,GEN code,long prec,long flag,long numpoints); GEN postploth2(GEN a,GEN b,GEN code,long prec,long numpoints); GEN postplothraw(GEN listx, GEN listy, long flag); void psplot_init(struct plot_eng *S, FILE *f, double xscale, double yscale, long fontsize); void Printx(dblPointList *f); void rectbox(long ne, GEN gx2, GEN gy2); void rectcolor(long ne, long color); void rectcopy(long source, long dest, long xoff, long yoff); void rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag); GEN rectcursor(long ne); void rectdraw(GEN list); void rectdraw_flag(GEN list, long flag); void rectline(long ne, GEN gx2, GEN gy2); void rectlines(long ne, GEN listx, GEN listy, long flag); void rectlinetype(long ne, long t); void rectmove(long ne, GEN x, GEN y); GEN rectploth(long drawrect,GEN a, GEN b, GEN code, long prec, ulong flags, long testpoints); GEN rectplothraw(long drawrect, GEN data, long flags); void rectpoint(long ne, GEN x, GEN y); void rectpoints(long ne, GEN listx, GEN listy); void rectpointtype(long ne, long t); void rectpointsize(long ne, GEN size); void rectrbox(long ne, GEN gx2, GEN gy2); void rectrline(long ne, GEN gx2, GEN gy2); void rectrmove(long ne, GEN x, GEN y); void rectrpoint(long ne, GEN x, GEN y); void rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2); void rectstring(long ne, char *x); void rectstring3(long ne, char *x, long dir); void rectclip(long rect); void gen_rectdraw0(struct plot_eng *eng, long *w, long *x, long *y, long lw, double xs, double ys); /* architecture-dependent plot file (plotX.c ...) */ void PARI_get_plot(); void rectdraw0(long *w, long *x, long *y, long lw); ENDEXTERN pari-2.7.5/src/graph/plotQt4.c0000644000175000017500000003634012366172547014534 0ustar billbill/* 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. */ ///////////////////////////////////////////////////////////////////////////// // // High resolution plot using Trolltech's Qt library // // You may possibly want to use this file with a "Qt Free Edition" // which is distributed under the terms of the Q PUBLIC LICENSE (QPL), // or with a "Qt/Embedded Free Edition" which is // distributed under the terms of the GNU General Public License (GPL). // Please check http://www.trolltech.com for details. // // ---Nils-Peter Skoruppa (www.countnumber.de) ///////////////////////////////////////////////////////////////////////////// #ifdef __QPE__ #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include "pari.h" #include "paripriv.h" #undef grem #include "rect.h" } using namespace Qt; class Plotter: public QWidget { #ifdef __FANCY_WIN__ Q_OBJECT signals: void clicked(); protected: void mouseReleaseEvent( QMouseEvent*); #endif public: Plotter( long *w, long *x, long *y, long lw, QWidget* parent = 0); void save( const QString& s = *plotFile + ".xpm",//QString("pariplot.xpm"), const QString& f = QString( "XPM")); protected: void paintEvent( QPaintEvent *); //void resizeEvent ( QResizeEvent *); #ifndef __FANCY_WIN__ void keyPressEvent( QKeyEvent *); #endif private: long *w; // map into rectgraph indexes long *x; // x, y: array of x,y-coorinates of the long *y; // top left corners of the rectwindows long lw; // lw: number of rectwindows long numcolors; QColor *color; QFont font; static QString *plotFile; void draw(QPainter *p); // public: // static void setPlotFile( const char *); }; QString *Plotter::plotFile = new QString( "pariplot"); Plotter::Plotter( long *w, long *x, long *y, long lw, QWidget* parent) : QWidget( parent), font( "lucida", 9) { long i; this->w=w; this->x=x; this->y=y; this->lw=lw; #ifndef __FANCY_WIN__ this->resize( pari_plot.width, pari_plot.height); this->setCaption( "Pari QtPlot"); #endif this->setFont( font); numcolors = lg(pari_colormap)-1; color = (QColor*)gpmalloc(numcolors*sizeof(QColor)); for (i = 1; i < lg(pari_colormap); i++) { int r, g, b; color_to_rgb(gel(pari_colormap,i), &r, &g, &b); color[i-1] = QColor(r, g, b); } QPalette palette; palette.setColor(backgroundRole(), color[0]); setPalette(palette); } // void Plotter::setPlotFile( const char *s) { // delete Plotter::plotFile; // Plotter::plotFile = new QString( s); // } struct data_qt { QPainter *p; long numcolors; QColor *color; }; static void SetForeground(void *data, long col) { struct data_qt *d = (struct data_qt *) data; d->p->setPen(d->color[col]); } static void DrawPoint(void *data, long x, long y) { struct data_qt *d = (struct data_qt *) data; d->p->drawPoint(x, y); } static void DrawLine(void *data, long x1, long y1, long x2, long y2) { struct data_qt *d = (struct data_qt *) data; d->p->drawLine(x1, y1, x2, y2); } static void DrawRectangle(void *data, long x, long y, long w, long h) { struct data_qt *d = (struct data_qt *) data; d->p->drawRect(x, y, w, h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { struct data_qt *d = (struct data_qt *) data; QPolygon xp=QPolygon(nb); long i; for (i=0;ip->drawPoints(xp); } static void DrawLines(void *data, long nb, struct plot_points *p) { struct data_qt *d = (struct data_qt *) data; QPolygon xp=QPolygon(nb); long i; for (i=0;ip->drawPolyline(xp); } static void DrawString(void *data, long x, long y, char *text, long numtext) { struct data_qt *d = (struct data_qt *) data; d->p->drawText(x, y, QString(text).left(numtext)); } void Plotter::draw(QPainter *p){ struct plot_eng plotQt; struct data_qt d; d.p= p; d.numcolors = numcolors; d.color=color; plotQt.sc=&SetForeground; plotQt.pt=&DrawPoint; plotQt.ln=&DrawLine; plotQt.bx=&DrawRectangle; plotQt.mp=&DrawPoints; plotQt.ml=&DrawLines; plotQt.st=&DrawString; plotQt.pl=&pari_plot; plotQt.data=(void *)&d; double xs = double(this->width()) / pari_plot.width, ys = double(this->height()) / pari_plot.height; gen_rectdraw0(&plotQt, this->w, this->x, this->y,this->lw,xs,ys); } void Plotter::save( const QString& s, const QString& f) { QPixmap pm( this->width(), this->height()); QPainter p; p.begin(&pm); p.initFrom(this); p.fillRect( 0, 0, pm.width(), pm.height(), color[0]); draw(&p); p.end(); pm.save( s, f.toAscii().data()); } void Plotter::paintEvent( QPaintEvent *) { QPainter p; p.begin( this); this->draw(&p); p.end(); } //void Plotter::resizeEvent( QResizeEvent *) { } #ifndef __FANCY_WIN__ void Plotter::keyPressEvent( QKeyEvent *e) { switch ( tolower( e->ascii())) { case 's': save(); this->setCaption( "Pari QtPlot: " + *plotFile); break; } } #endif #ifdef __FANCY_WIN__ void Plotter::mouseReleaseEvent( QMouseEvent*) { emit clicked(); } #endif #ifdef __FANCY_WIN__ // // The envelope for an instance of plotter // /* XPM */ static const char * const fullscreen_xpm[] = { "14 14 2 1", " c None", ". c #000000", "..............", ". .. .", ". .. .", ". .... .", ". .. .", ". . .. . .", "..............", "..............", ". . .. . .", ". .. .", ". .... .", ". .. .", ". .. .", ".............."}; /* class SaveAsDialog: public #ifdef __QPE__ //QDialog #else QFileDialog #endif { Q_OBJECT public: SaveAsDialog( const QString & c = QString::null, const QString & s = QString::null, int w = 0, int h = 0, QWidget *parent = 0, const char *name = 0, WFlags f = 0); ~SaveAsDialog(); #ifdef __QPE__ QString selectedFile() { return nameW->text();} #endif int picWidth() { return widthW->value();} int picHeight() { return heightW->value();} private: QLineEdit *nameW; QSpinBox *widthW, *heightW; }; SaveAsDialog::SaveAsDialog( const QString & c, const QString & s, int w, int h, QWidget *parent, const char *name, WFlags f) #ifdef __QPE__ // simplistic dialog in case of QPE ( fancy alternative: class FileSelector) : QDialog( parent, name, TRUE, f) { if( c) this->setCaption( c); nameW = new QLineEdit( this); if( s) nameW->setText( s); widthW = new QSpinBox( 1, 65536, 1, this); if( w > 0) widthW->setValue( w); heightW = new QSpinBox( 1, 65536, 1, this); if( h > 0) heightW->setValue( h); QVBoxLayout *top = new QVBoxLayout( this, 10); QGridLayout *contents = new QGridLayout( 3, 2); top->addLayout( contents); QLabel *l; l = new QLabel( nameW, "Name : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 0, 0); contents->addWidget( nameW, 0, 1); l = new QLabel( widthW, "Width : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 1, 0); contents->addWidget( widthW, 1, 1); l = new QLabel( heightW, "Height : ", this); l->setAlignment( AlignRight | AlignVCenter); contents->addWidget( l, 2, 0); contents->addWidget( heightW, 2, 1); top->activate(); this->resize( 160, this->height()); // hack!!! #else : QFileDialog( parent, name, TRUE) { if( c) this->setFilters( c); if( s) this->setSelection( s); QLabel *l; QWidget *wt = new QWidget( this); QHBoxLayout *spinBoxes = new QHBoxLayout( wt, 5); widthW = new QSpinBox( 1, 65536, 1, wt); l = new QLabel( widthW, "&width ", wt); spinBoxes->addWidget( l); spinBoxes->addWidget( widthW); if( w > 0) widthW->setValue( w); heightW = new QSpinBox( 1, 65536, 1, wt); spinBoxes->addSpacing(10); l = new QLabel( heightW, "&height ", wt); l->setAlignment( AlignRight | AlignVCenter); spinBoxes->addWidget( l); spinBoxes->addWidget( heightW); if( h > 0) heightW->setValue( h); l = new QLabel( "Resolution:", this); QFileDialog::addWidgets( l, wt, 0); #endif } SaveAsDialog::~SaveAsDialog() { } */ class PlotWindow: public QMainWindow { Q_OBJECT public: PlotWindow( long *w, long *x, long *y, long lw, QWidget* parent = 0, const char* name = 0); ~PlotWindow(); #ifndef __QPE__ protected: void resizeEvent( QResizeEvent *); #endif private slots: void fullScreen(); void normalView(); void save(); void save( int); private: static const QList file_formats; Plotter *plr; QString saveFileName; int saveFileFormat; #ifndef __QPE__ QLabel *res; QMenu* menuFile; QMenu* menuView; QMenu* menuFormat; QAction* quitAction; QAction* saveAction; QAction* fullScreenAction; QSignalMapper* signalMapper; QIcon* icon; #endif }; const QList PlotWindow::file_formats = QImageWriter::supportedImageFormats(); PlotWindow::PlotWindow( long *w, long *x, long *y, long lw, QWidget* parent, const char* name) : QMainWindow( parent), saveFileName( "pariplot"), saveFileFormat( 0) { setWindowTitle( "Pari QtPlot"); QPalette palette; palette.setColor(this->backgroundRole(), white); this->setPalette(palette); menuFile = menuBar()->addMenu("&File"); saveAction = new QAction("&Save",this); saveAction->setShortcut(QKeySequence(CTRL+Key_S)); connect (saveAction, SIGNAL(triggered()), this, SLOT(save())); menuFile->addAction(saveAction); menuFormat = menuFile->addMenu("Save &as"); signalMapper = new QSignalMapper(this); for( int i = 0; i < file_formats.count(); i++) { QAction* tmpAction; tmpAction = new QAction(QString(file_formats.at(i)),this); connect (tmpAction, SIGNAL(triggered()), signalMapper, SLOT(map())); signalMapper->setMapping(tmpAction,i); menuFormat->addAction(tmpAction); } connect (signalMapper, SIGNAL(mapped(int)), this,SLOT(save(int))); quitAction = new QAction("&Quit",this); quitAction->setShortcut(QKeySequence(CTRL+Key_Q)); connect (quitAction, SIGNAL(triggered()), this, SLOT(close())); menuFile->addAction(quitAction); menuView = menuBar()->addMenu("&View"); fullScreenAction = new QAction("Use &full screen", this); fullScreenAction->setShortcut(QKeySequence(CTRL+Key_F)); icon = new QIcon(); icon->addPixmap(QPixmap( (const char ** )fullscreen_xpm)); fullScreenAction->setIcon(*icon); connect(fullScreenAction, SIGNAL( triggered()), this, SLOT( fullScreen())); menuView->addAction(fullScreenAction); // Setting up an instance of plotter plr = new Plotter( w, x, y, lw, this); connect( plr, SIGNAL(clicked()), this, SLOT( normalView())); this->setCentralWidget( plr); #ifndef __QPE__ this->resize( pari_plot.width, pari_plot.height + 24); res = new QLabel( ); statusBar()->addWidget( res); #endif } PlotWindow::~PlotWindow() { } #ifndef __QPE__ void PlotWindow::resizeEvent( QResizeEvent *e) { QMainWindow::resizeEvent( e); res->setText( QString( "Resolution: ") + QString::number( plr->width()) + "x" + QString::number( plr->height())); res->setFixedSize( res->sizeHint()); } #endif void PlotWindow::fullScreen() { plr->setParent( 0); plr->showMaximized(); plr->show(); } void PlotWindow::normalView() { if ( !plr->parentWidget()) { plr->setParent( this); this->setCentralWidget( plr); plr->show(); } } void PlotWindow::save() { QString ff = QString( file_formats.at( saveFileFormat)); QString fn = saveFileName + "." + ff.toLower(); plr->save( fn, ff); setWindowTitle( QString( "Pari QtPlot:") + fn); #ifndef __QPE__ //statusBar()->message( QString( "File %1 saved" ).arg( fn), 2000 ); #endif } void PlotWindow::save( int id) { QString ff( file_formats.at( id)); QString s( ff + " (*." + ff.toLower() +");;All (*)"); QString fn = QFileDialog::getSaveFileName(this, saveFileName + "." + ff, saveFileName + "." + ff, s); if ( !fn.isEmpty() ) { saveFileName = fn; int p; if( (p = saveFileName.lastIndexOf( "." + ff, -1)) >=0) saveFileName.truncate( p); saveFileFormat = id; save(); } } #include "plotQt4.moc.cpp" #endif // __FANCY_WIN__ // // Implementation of the two architecture-dependent functions // (from rect.h) requested by pari's plotting routines // void rectdraw0(long *w, long *x, long *y, long lw) { if (pari_daemon()) return; // parent process returns pari_close(); PARI_get_plot(); // launch Qt window int argc = 1; // set argc = 2 for cross char * argv[] = { "gp", "-qws"}; // development using qvfb #ifdef __QPE__ QPEApplication #else QApplication #endif a( argc, argv); #ifdef __FANCY_WIN__ PlotWindow *win = new PlotWindow(w, x, y, lw); #else Plotter *win = new Plotter( w, x, y, lw); #endif #ifdef __QPE__ a.showMainWidget( win); #else //a.setMainWidget( win); win->show(); #endif a.exec(); exit( 0); } void PARI_get_plot() /* This function initialises the structure rect.h: pari_plot */ { if (pari_plot.init) return; // pari_plot is already set #ifdef __QPE__ pari_plot.width = 240; // width and pari_plot.height = 320; // height of plot window #else pari_plot.width = 400; // width and pari_plot.height = 300; // height of plot window #endif pari_plot.hunit = 3; // pari_plot.vunit = 3; // pari_plot.fwidth = 6; // font width pari_plot.fheight = 9; // and height pari_plot.init = 1; // flag: pari_plot is set now! } pari-2.7.5/src/graph/plotnull.c0000644000175000017500000000142612366172547015033 0ustar billbill/* 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 "rect.h" void rectdraw0(long *w, long *x, long *y, long lw) { (void)w; (void)x; (void)y; (void)lw; } void PARI_get_plot() { pari_err(e_MISC,"high resolution graphics disabled"); } pari-2.7.5/src/graph/plotX.c0000644000175000017500000001733112366172547014272 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* HIGH RESOLUTION PLOT */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "rect.h" #ifdef HPPA # ifndef __GNUC__ typedef char *caddr_t; # endif #endif BEGINEXTERN #include #include #include #ifndef XK_c # include #endif ENDEXTERN static Colormap PARI_Colormap; static XColor *PARI_Colors; struct data_x { Display *display; Window win; int numcolors; GC gc; }; /* after fork(), we don't want the child to recover but to exit */ static void exiterr(const char *str) { term_color(c_ERR); err_printf("\n *** X fatal error: %s\n",str); term_color(c_NONE); exit(1); } static void SetForeground(void *data, long col) { struct data_x *dx = (struct data_x *) data; XSetForeground(dx->display,dx->gc, PARI_Colors[col].pixel); } static void DrawPoint(void *data, long x, long y) { struct data_x *dx = (struct data_x *) data; XDrawPoint(dx->display,dx->win,dx->gc, x,y); } static void DrawLine(void *data, long x1, long y1, long x2, long y2) { struct data_x *dx = (struct data_x *) data; XDrawLine(dx->display,dx->win,dx->gc, x1,y1, x2,y2); } static void DrawRectangle(void *data, long x, long y, long w, long h) { struct data_x *dx = (struct data_x *) data; XDrawRectangle(dx->display,dx->win,dx->gc, x,y, w,h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { struct data_x *dx = (struct data_x *) data; XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb); long i; for (i=0;idisplay,dx->win,dx->gc, xp, nb, 0); pari_free(xp); } static void DrawLines(void *data, long nb, struct plot_points *p) { struct data_x *dx = (struct data_x *) data; XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb); long i; for (i=0;idisplay,dx->win,dx->gc, xp, nb, 0); pari_free(xp); } static void DrawString(void *data, long x, long y, char *text, long numtext) { struct data_x *dx = (struct data_x *) data; XDrawString(dx->display,dx->win,dx->gc, x,y, text, numtext); } #define MAX_BUF 256 static int Xerror(Display *d, XErrorEvent *pari_err) { char buf[MAX_BUF]; XGetErrorText(d,pari_err->error_code,buf,MAX_BUF); exiterr(buf); return 0; } static int IOerror(Display *d) { char buf[MAX_BUF]; sprintf(buf, "lost display on %s", DisplayString(d)); exiterr(buf); return 0; } static void PARI_ColorSetUp(Display *display, GEN colors) { static int init_done = 0; long i, n = lg(colors)-1; if (init_done) return; init_done=1; PARI_Colormap = DefaultColormap(display, 0); PARI_Colors = (XColor *) pari_malloc((n+1) * sizeof(XColor)); for (i=0; ifid); XClearWindow(display, win); XMapWindow(display, win); oldwidth = pari_plot.width; oldheight = pari_plot.height; dx.display= display; dx.win = win; dx.numcolors = lg(pari_colormap)-1; dx.gc = gc; plotX.sc = &SetForeground; plotX.pt = &DrawPoint; plotX.ln = &DrawLine; plotX.bx = &DrawRectangle; plotX.mp = &DrawPoints; plotX.ml = &DrawLines; plotX.st = &DrawString; plotX.pl = &pari_plot; plotX.data = (void*)&dx; for(;;) { XNextEvent(display, &event); switch(event.type) { case ClientMessage: if (event.xclient.message_type != wm_protocols || (Atom)event.xclient.data.l[0] != wm_delete_window) break; case ButtonPress: case DestroyNotify: EXIT: XUnloadFont(display,font_info->fid); XFreeGC(display,gc); XCloseDisplay(display); exit(0); case KeyRelease: /* Mod4 == Super on "std" Linux */ keystate = event.xkey.state & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask); switch (XkbKeycodeToKeysym(display, event.xkey.keycode, 0,0)) { case XK_q: if (!keystate || keystate == ControlMask) goto EXIT; break; case XK_c: if (keystate == ControlMask) goto EXIT; break; } break; case ConfigureNotify: { int width = event.xconfigure.width; int height = event.xconfigure.height; if (width == oldwidth && height == oldheight) break; oldwidth = width; oldheight = height; /* recompute scale */ xs = ((double)width)/pari_plot.width; ys = ((double)height)/pari_plot.height; } case Expose: gen_rectdraw0(&plotX, w, x, y,lw,xs,ys); } } } void PARI_get_plot() { Display *display; int screen; if (pari_plot.init) return; if (!(display = XOpenDisplay(NULL))) pari_err(e_MISC, "no X server"); screen = DefaultScreen(display); pari_plot.width = DisplayWidth(display, screen) - 40; pari_plot.height = DisplayHeight(display, screen) - 60; pari_plot.fheight = 15; pari_plot.fwidth = 9; pari_plot.hunit = 5; pari_plot.vunit = 5; pari_plot.init = 1; XCloseDisplay(display); } pari-2.7.5/src/graph/plotfltk.c0000644000175000017500000001257012366172547015023 0ustar billbill/* 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. */ ///////////////////////////////////////////////////////////////////////////// // // High resolution plot using FLTK library // Bill Allombert 2003 // // Based on plotQt by Nils-Peter Skoruppa (www.countnumber.de) ///////////////////////////////////////////////////////////////////////////// extern "C" { #include "pari.h" #include "paripriv.h" #include "rect.h" } #include #include #include static long numcolors; class Plotter: public Fl_Window { public: Plotter( long *w, long *x, long *y, long lw, const char* name = 0); private: void draw(); int handle(int event); private: long *my_w; // map into rectgraph indexes long *my_x; // x, y: array of x,y-coordinates of the long *my_y; // top left corners of the rectwindows long my_lw; // lw: number of rectwindows Fl_Color *color; }; static Fl_Color rgb_color(int R, int G, int B) { return fl_color_cube(R*FL_NUM_RED/256, G*FL_NUM_GREEN/256, B*FL_NUM_BLUE/256); } Plotter::Plotter( long *w, long *x, long *y, long lw, const char* name) : Fl_Window(pari_plot.width, pari_plot.height, "PARI/GP") { long i; this->my_w=w; this->my_x=x; this->my_y=y; this->my_lw=lw; numcolors = lg(pari_colormap)-1; color = (Fl_Color*)pari_malloc(numcolors*sizeof(Fl_Color)); for (i = 1; i < lg(pari_colormap); i++) { int r, g, b; color_to_rgb(gel(pari_colormap,i), &r, &g, &b); color[i-1] = rgb_color(r, g, b); } } static void DrawPoint(void *data, long x, long y) { (void)data; fl_point(x,y); } static void DrawLine(void *data, long x1, long y1, long x2, long y2) { (void)data; fl_line(x1,y1, x2,y2); } static void DrawRectangle(void *data, long x, long y, long w, long h) { (void)data; fl_rect(x,y,w,h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { long i; (void)data; for (i=0; iw())/pari_plot.width; double ys = double(this->h())/pari_plot.height; fl_font(FL_COURIER, int(pari_plot.fheight * xs)); fl_color(color[0]); // transparent window on Windows otherwise fl_rectf(0, 0, this->w(), this->h()); pl.sc = &SetForeground; pl.pt = &DrawPoint; pl.ln = &DrawLine; pl.bx = &DrawRectangle; pl.mp = &DrawPoints; pl.ml = &DrawLines; pl.st = &DrawString; pl.pl = &pari_plot; pl.data = (void*)color; gen_rectdraw0(&pl, my_w, my_x, my_y, my_lw, xs, ys); } int Plotter::handle(int event) { switch(event) { case FL_PUSH: switch(Fl::event_button()) { case 1: exit(0); case 2: { static int flag=0; static int my_x; static int my_y; static int my_w; static int my_h; flag=1-flag; if (flag) { my_x=this->x(); my_y=this->y(); my_w=this->w(); my_h=this->h(); this->fullscreen(); } else { this->fullscreen_off(my_x,my_y,my_w,my_h); this->size_range(1,1); } return 1; } } case FL_KEYUP: switch(Fl::event_key()) { case 'q': switch(Fl::event_shift()) { case 0: case FL_CTRL: exit(0); } break; case 'c': if (Fl::event_state() == FL_CTRL) exit(0); break; } default: return 0; } } // // Implementation of the two architecture-dependent functions // (from rect.h) requested by pari's plotting routines // void rectdraw0(long *w, long *x, long *y, long lw) { Plotter *win; if (pari_daemon()) return; // parent process returns pari_close(); PARI_get_plot(); Fl::visual(FL_DOUBLE|FL_INDEX); win = new Plotter( w, x, y, lw); win->size_range(1,1); win->box(FL_FLAT_BOX); win->end(); win->show(); Fl::run(); exit(0); } void PARI_get_plot() /* This function initialises the structure rect.h: pari_plot */ { if (pari_plot.init) return; // pari_plot is already set pari_plot.width = 400; // width and pari_plot.height = 300; // height of plot window pari_plot.hunit = 3; // pari_plot.vunit = 3; // pari_plot.fwidth = 6; // font width pari_plot.fheight = 9; // and height pari_plot.init = 1; // flag: pari_plot is set now! } pari-2.7.5/src/whatnow0000644000175000017500000003215712314242552013317 0ustar billbill!_ #_ % +_ -_ 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 pari-2.7.5/src/systems/0000755000175000017500000000000012613365633013414 5ustar billbillpari-2.7.5/src/systems/winCE/0000755000175000017500000000000012613365633014421 5ustar billbillpari-2.7.5/src/systems/winCE/pariCE.h0000644000175000017500000000051312314242551015723 0ustar billbill/* only needed for Windows CE */ #ifndef PARICE_H #define PARICE_H extern int isspace(int); extern int isdigit(int); extern int isalpha(int); extern int isalnum(int); extern long strtol(const char *, char **, int ); extern int rename(const char *, const *); extern int unlink(char *); extern void *calloc(size_t, size_t); #endif pari-2.7.5/src/systems/winCE/pariCE.c0000644000175000017500000000725112314242551015724 0ustar billbill#include #include int isspace(int c) { if ((c >= 0x09) && (c <= 0x0D)) return 1; else if (c == 0x20) return 1; return 0; } int isdigit(int c) { if ((c >= '0') && (c <= '9')) return 1; else return 0; } int isxdigit(int c) { if ((c >= '0') && (c <= '9')) return 1; else if ((c >= 'a') && (c <= 'f')) return 1; else if ((c >= 'A') && (c <= 'F')) return 1; else return 0; } int isalpha(int c) { if ((c >= 'a') && (c <= 'z')) return 1; else if ((c >= 'A') && (c <= 'Z')) return 1; else return 0; } int isalnum(int c) { if ((c >= '0') && (c <= '9')) return 1; else if ((c >= 'a') && (c <= 'z')) return 1; else if ((c >= 'A') && (c <= 'Z')) return 1; else return 0; } static int checkDigit(char ch, int base) { int n; if (ch >= '0' && ch <= '9') n = ch - '0'; else if (ch >= 'a' && ch <= 'z') n = ch + 10 - 'a'; else if (ch >= 'A' && ch <= 'Z') n = ch + 10 - 'A'; else return -1; return n >= base ? -1 : n; } long strtol(const char *s, char **endptr, int base) { const char *sc; char sign; int actualbase; double result; /* if the base is illegal, then return 0; */ if (! (base >= 2 && base <= 36) ){ if (endptr) *endptr = (char *)s; return 0; } /* skip leading spaces */ for (sc = s; *sc == ' '; ++sc); /* parse the sign */ if (*sc == '-' || *sc == '+') { sign = *sc; sc++; } else { sign = '+'; } /* the default base = 10 */ actualbase = base == 0 ? 10 : base; /* if base is undefined, and number starts '0x', then we have base 16 */ if (base == 0 && sc[0] == '0' && (sc[1] == 'x' || sc[1] == 'X')) { actualbase = 16; sc += 2; } /* else if base is undefined, and number starts '0', then we have base 8 */ else if (base == 0 && sc[0] == '0') actualbase = 8; /* else if base == 16, then skip any leading '0x' */ else if (base == 16 && sc[0] == '0' && (sc[1] == 'x' || sc[1] == 'X')) sc += 2; /* skip leading zeroes */ for (; *sc == '0'; ++sc); /* the result so far is 0. We are going to work with doubles because these give 52 bits of accuracy */ result = 0.0; /* sc now points to the first unprocessed digit. Keep processing until first non digit or overflow */ for (;;) { int d = checkDigit(*sc, actualbase); /* if the digit was illegal, then we have terminated */ if (d < 0) { if (endptr) *endptr = (char *)sc; return sign == '-' ? -(long)result : (long)result; } /* roll in the new digit */ result = result * actualbase + d; /* check for overflow */ if (sign == '+' && result > (double)LONG_MAX) { if (endptr) *endptr = (char *)(sc+1); return LONG_MAX; } if (sign == '-' && result > -(double)LONG_MIN) { if (endptr) *endptr = (char *)(sc+1); return LONG_MIN; } /* go on to the next character */ sc++; } } /* * Implement rename and unlink in win32 procedures. This is complicated * by the fact that these procedures take wide chars. */ #define MAX_FILENAME_LEN 128 int rename(const char *oldname, const char *newname) { int succ; short soldname[MAX_FILENAME_LEN]; short snewname[MAX_FILENAME_LEN]; MultiByteToWideChar(CP_ACP, 0, oldname, strlen(oldname)+1, soldname, MAX_FILENAME_LEN); MultiByteToWideChar(CP_ACP, 0, newname, strlen(newname)+1, snewname, MAX_FILENAME_LEN); succ = MoveFile(soldname, snewname); return !succ; } int unlink(char *name) { int succ; short wname[MAX_FILENAME_LEN]; MultiByteToWideChar(CP_ACP, 0, name, strlen(name)+1, wname, MAX_FILENAME_LEN); succ = DeleteFile(wname); return !succ; } void *calloc(size_t nelem, size_t size) { const size_t n = nelem*size; char *p = malloc(n); if (p) memset(p, '\0', n); return p; } pari-2.7.5/src/systems/os2/0000755000175000017500000000000012613365633014117 5ustar billbillpari-2.7.5/src/systems/os2/pari.def.base0000644000175000017500000000040111636712103016426 0ustar billbillLIBRARY '' INITINSTANCE TERMINSTANCE ; Can't put http://.../ in VENDOR, since it is split on : ; One should be be glad that .../ is good enough DESCRIPTION '@#:#@' CODE LOADONCALL DATA LOADONCALL NONSHARED MULTIPLE EXPORTS pari-2.7.5/src/systems/os2/README0000644000175000017500000000416312314242551014772 0ustar billbillOn OS/2 the build goes the same way as on Unix, e.g., sh Configure make gp make bench With the current implementation of install(), one can load the functions from the PARI library only if the GP executable is build for dynamic linking. By default, the build will go to an AOUT-type executables (to simplify the logic of Configure, and enable restricted binary compatibility with DOS/Windows). Unfortunately, AOUT-type DLLs are very restricted; thus the build of dynamically linked target fails. To build with OMF-type target cd Oos2-ix86 make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll -Zstack 8192" RLLIBS=-lreadline_import DLLD_IGNORE= AR=emxomfar bench This build constructs a working DLL. Both -Zomf and -Zcrtdll are crucial to have a functioning DLL (see EMX documentation for details). -Zstack 8192 forces the same C stack size as for AOUT build (and the same - 8M - as on many Unices, so you get fewer surprises when things work on Unix, but core on OS/2 due only to shorter C stack). (The standard Configure adds -Zsysv-signals option; in fact, this option is not needed - as checked with v2.3.5.) Use of the the readline-DLL (via the readline_import.lib library) is not only a convenience, but also statically linked readline library are often broken; sigh... To use the gnuplot-engine DLL gnpltdrw.DLL, one can give Configure the option --graphic=gnuplot-dynamic,gnpltdrw (requires linking with -Zcrtdll for graphics to work). Add -DOLD_SET_FEEDBACK_RECTANGLE gcc option if gnpltdrw.DLL supports mousing, but is an old build, so it won't report this capability. Thus the build process may look like this: sh Configure --graphic=gnuplot-dynamic,gnpltdrw make gp cd Oos2-ix86 make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll -Zstack 8192 -DUSE_SET_FEEDBACK_RECTANGLE" RLLIBS=-lreadline_import DLLD_IGNORE= AR=emxomfar bench cd .. The statically build PARI library is in a file named similar to libpari-2_2.a, the library for linking with the PARI DLL is named as pari-2_2.a (or pari-2_2.lib). As a debugging tool, the constructed DLL reports its build options via the standard OS/2 way: bldlevel FULL_NAME_OF_THE_DLL pari-2.7.5/src/systems/os2/os2.c0000644000175000017500000001333711636712103014765 0ustar billbill#include "dlfcn.h" #define INCL_BASE #include #include #include #include #include static ULONG retcode; static char fail[300]; static ULONG dllHandle; static char dllname[80]; static int handle_found; static int handle_loaded; #ifdef DLOPEN_INITTERM unsigned long _DLL_InitTerm(unsigned long modHandle, unsigned long flag) { switch (flag) { case 0: /* INIT */ /* Save handle */ dllHandle = modHandle; handle_found = 1; return TRUE; case 1: /* TERM */ handle_found = 0; dllHandle = (unsigned long)NULLHANDLE; return TRUE; } return FALSE; } #endif HMODULE find_myself(void) { static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf, ULONG * Offset, ULONG Address); HMODULE doscalls_h, mod; static int failed; ULONG obj, offset, rc; char buf[260]; if (failed) return 0; failed = 1; doscalls_h = (HMODULE)dlopen("DOSCALLS",0); if (!doscalls_h) return 0; /* {&doscalls_handle, NULL, 360}, */ /* DosQueryModFromEIP */ rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP); if (rc) return 0; rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen); if (rc) return 0; failed = 0; handle_found = 1; dllHandle = mod; return mod; } void * dlopen(char *path, int mode) { HMODULE handle; char tmp[260], *beg, *dot; ULONG rc; unsigned fpflag = _control87(0,0); fail[0] = 0; if (!path) { /* Our own handle. */ if (handle_found || find_myself()) { if (handle_loaded) return (void*)dllHandle; rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname); if (rc) { strcpy(fail, "can't find my DLL name by the handle"); retcode = rc; return 0; } rc = DosLoadModule((PSZ)fail, sizeof fail, (PSZ)dllname, &handle); if (rc) { strcpy(fail, "can't load my own DLL"); retcode = rc; return 0; } handle_loaded = 1; goto ret; } retcode = ERROR_MOD_NOT_FOUND; strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM"); return 0; } if ((rc = DosLoadModule((PSZ)fail, sizeof fail, (PSZ)path, &handle)) == 0) goto ret; retcode = rc; /* Not found. Check for non-FAT name and try truncated name. */ /* Don't know if this helps though... */ for (beg = dot = path + strlen(path); beg > path && !strchr(":/\\", *(beg-1)); beg--) if (*beg == '.') dot = beg; if (dot - beg > 8) { int n = beg+8-path; memmove(tmp, path, n); memmove(tmp+n, dot, strlen(dot)+1); rc = DosLoadModule((PSZ)fail, sizeof fail, (PSZ)tmp, &handle); if (rc == 0) goto ret; retcode = rc; } handle = 0; ret: _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */ return (void *)handle; } #define ERROR_WRONG_PROCTYPE 0xffffffff void * dlsym(void *handle, char *symbol) { ULONG rc, type; PFN addr; fail[0] = 0; rc = DosQueryProcAddr((HMODULE)handle, 0, (PSZ)symbol, &addr); if (rc == 0) { rc = DosQueryProcType((HMODULE)handle, 0, (PSZ)symbol, &type); if (rc == 0 && type == PT_32BIT) return (void *)addr; rc = ERROR_WRONG_PROCTYPE; } retcode = rc; return NULL; } char * dlerror(void) { static char buf[700]; ULONG len; if (retcode == 0) return NULL; if (retcode == ERROR_WRONG_PROCTYPE) { strcpy(buf, "Wrong procedure type"); len = strlen(buf); } if ((retcode != ERROR_WRONG_PROCTYPE) && DosGetMessage(NULL, 0, buf, sizeof buf - 1, retcode, (PSZ)"OSO001.MSG", &len)) { if (fail[0]) sprintf(buf, "OS/2 system error code %d, possible problematic module: '%s'", (int)retcode, fail); else sprintf(buf, "OS/2 system error code %d", (int)retcode); } else { buf[len] = '\0'; if (len && buf[len - 1] == '\n') buf[--len] = 0; if (len && buf[len - 1] == '\r') buf[--len] = 0; if (len && buf[len - 1] == '.') buf[--len] = 0; if (fail[0] && len < 300) sprintf(buf + len, ", possible problematic module: '%s'", fail); } retcode = 0; return buf; } int dlclose(void *handle) { ULONG rc; if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0; retcode = rc; return 2; } void* get_stack(double fraction, long min) { int rc; TIB *tib; PIB *pib; char *s, *e; unsigned long d; if (!(_emx_env & 0x200)) return 0; /* not OS/2. */ rc = DosGetInfoBlocks(&tib, &pib); if (rc) return 0; /* ignore error */ s = (char*)tib->tib_pstack; e = (char*)tib->tib_pstacklimit; d = fraction * (e-s); if (min >= 3*(e-s)/4) min = 3*(e-s)/4; if (d < min) d = min; return (void*)(s + d); } pari-2.7.5/src/systems/os2/dlfcn.h0000644000175000017500000000021411636712103015343 0ustar billbill#define RTLD_LAZY 1 #define RTLD_GLOBAL 1 void *dlopen(char *path, int mode); void *dlsym(void *handle, char *symbol); char *dlerror(void); pari-2.7.5/src/systems/win32/0000755000175000017500000000000012613365633014356 5ustar billbillpari-2.7.5/src/systems/win32/README.MSVC0000644000175000017500000000614112314242551015776 0ustar billbillPosted on pari-dev by Bill Daly : [edited to fit current filenames] ================================= Here is a description of the steps necessary to compile PARI with the MSVC compiler under WIN32. 1. Unzip the archive, preserving folder names so that the directory structure is correct. I use WinZip to do this, and I put the files on my D: drive, so that the files for pari-2.1.0 for example will be stored under D:\pari-2.1.0. Note that the archive as downloaded, pari.tgz, is an archive of an archive. Winzip doesn't know how to unzip pari.tgz, so I use Aladdin Expander to do this, which will create for example the file pari-2.1.0.tar in the same directory as pari.tgz. Unfortunately, Aladdin Expander doesn't know how to unzip this file, so I use Winzip to do it. Isn't Windows wonderful? 2. MSVC doesn't like names of the form "pari-2.1.0", so rename the base directory to something like "pari210". Now the files are stored under D:\pari210. 3. Start MSVC (I use version 6, but earlier versions will probably work the same way). 4. Select "File\New..." and pick the "Project" tab to create a new project. Select "Win32 Console Application" as the project type, and specify the project name as "pari210". Make sure that the "Location" of the files is D:\pari210. Click "OK", then select "An empty project" (should be the default anyway) and click "Finish". 5. Select "Project\Add to project\Files..." to add files to the project. Select all the *.c and *.h files in src\basemath, src\headers, src\kernel\ix86, src\language, src\modules and Odos, EXCEPT pariCE.[ch]; all of the files in src\gp except gp_rl.c; the files plotnull.c, plotport.c and rect.h in src\graph.c; and the file src\kernel\none\mp.c. 6. Select "Project\Settings" and pick the "C/C++" tab. Select "Preprocessor" from the "Category" menu, and enter "D:\pari210\src\headers,D:\pari210\Odos" into the "Additional include directories" box. (I also select the "Code Generation" category and change the "Struct member alignment" to "1 byte", but this may not be necessary.) It is usually convenient for debugging to select the "Debug" tab and specify a "Working directory", e.g. "D:\gp" if you have .gp files there that you can use for testing. You should now be able to build and test the program. When you want to build a release version, you will have to repeat step 6 above, since MSVC doesn't apply the project settings globally. A couple of points: ------------------- You may get some inconsequential warning messages. You can suppress these by adding a line of the form: #pragma warning(disable: ...) to paricfg.h, where ... is a space-delimited list of warning numbers, e.g. "4018 4244" corresponding to the warnings C4018 and C4244. When you compile a release version, global optimization is enabled by default. MSVC is fairly buggy with global optimization, so you may find that some modules won't compile with it, e.g. sumiter.c. You can either disable global optimization (in "Project\Settings" under the tab "C/C++" in the category "Optimization"), or you can surround the offending code with: #pragma optimization("g", off) ... #pragma optimization("g", on) pari-2.7.5/src/systems/win32/pariinl.h0000644000175000017500000000036412366172547016175 0ustar billbill/* This file contains declarations/definitions of functions that * _can_ be inlined. */ #ifndef WINCE # include "../src/kernel/ix86/level0.h" #else # include "../src/kernel/none/level0.h" #endif #include "../src/kernel/none/level1.h" pari-2.7.5/src/systems/mingw/0000755000175000017500000000000012613365633014535 5ustar billbillpari-2.7.5/src/systems/mingw/mingw.c0000644000175000017500000000745112405547147016032 0ustar billbill/* Copyright (C) 2009 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. */ /* Originally written by Vasili Burdo */ #include #include #include "mingw.h" static const char * pariwin32_basedir = NULL; const char* win32_basedir(void) { if (pariwin32_basedir) return pariwin32_basedir; else { char basedir[1024]; char* slash; GetModuleFileNameA(0, basedir, sizeof(basedir) ); slash = strrchr(basedir, '\\'); if (slash) slash[1] = 0; pariwin32_basedir = strdup(basedir); return pariwin32_basedir; } } char* win32_datadir(void) { char datadir[1029]; const char * basedir = win32_basedir(); sprintf(datadir, "%sdata",basedir); return strdup(datadir); } static WORD win32_console_color(unsigned long c) { int shift, intense = 0; if( c >= 30 && c <= 37 ) { shift = 0; c -= 30; } else if( c >= 40 && c <= 47 ) { shift = 4; c -= 40; } else if( c >= 90 && c <= 97 ) { shift = 0; intense = 8; c -= 90; } else if(c >= 100 && c <= 107) { shift = 4; intense = 8; c -= 100; } else return 0; WORD w = 0; switch(c) { case 0: w = 0; break; /* black */ case 1: w = 4; break; /* red */ case 2: w = 2; break; /* green */ case 3: w = 6; break; /* yellow RG */ case 4: w = 1; break; /* blue */ case 5: w = 5; break; /* magenta RB */ case 6: w = 3; break; /* cyan GB */ case 7: w = 7; break; /* white RGB */ } return (w|intense) << shift; } void win32_ansi_fputs(const char* s, void* f) { WORD color; unsigned long c[3]; long nbarg; if( !(f == stdout || f == stderr) ) { fputs(s,f); return; } while(1) { char *p; p = strstr(s, "\x1b["); if( p > s ) fwrite(s,p-s,1,f); if( p ) p += 2; else { fputs(s,f); return; } nbarg = 0; c[nbarg++] = strtoul(p,&p,10); if( *p == ';' ) c[nbarg++] = strtoul(p+1,&p,10); if( *p == ';' ) c[nbarg++] = strtoul(p+1,&p,10); if( *p++ == 'm' ) { switch(nbarg) { case 1: color = 7; break; case 2: color = win32_console_color(c[1]); if (c[0]&4) color |= 0x8000; break; case 3: color = win32_console_color(c[1]) | win32_console_color(c[2]); if (c[0]&4) color |= 0x8000; } fflush(f); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color); } s = p; } } int win32_terminal_width(void) { CONSOLE_SCREEN_BUFFER_INFO sbi; if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi)) return 0; return sbi.srWindow.Right - sbi.srWindow.Left + 1; } int win32_terminal_height(void) { CONSOLE_SCREEN_BUFFER_INFO sbi; if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi)) return 0; return sbi.srWindow.Bottom - sbi.srWindow.Top + 1; } void win32_set_pdf_viewer(void) { char *s = getenv("GP_PDF_VIEWER"); if (!s) { HKEY handle; const char *key = "AcroExch.Document\\shell\\open\\command"; const long SZ = 512; char str[SZ], *buf; int status; DWORD L = SZ; (void)RegOpenKeyEx(HKEY_CLASSES_ROOT, key, 0, KEY_READ, &handle); status = RegQueryValueEx(handle, NULL, 0, NULL, (LPBYTE)str, &L); RegCloseKey(handle); if (status) return; buf = malloc(strlen(str)+16); /*must not be freed*/ sprintf(buf,"GP_PDF_VIEWER=%s",str); putenv(buf); } } pari-2.7.5/src/systems/mingw/mingw.h0000644000175000017500000000141212405547147016026 0ustar billbill/* Copyright (C) 2009 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. */ const char* win32_basedir(void); char* win32_datadir(void); 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); pari-2.7.5/src/systems/darwin/0000755000175000017500000000000012613365633014700 5ustar billbillpari-2.7.5/src/systems/darwin/darwin.c0000644000175000017500000001417712366172547016347 0ustar billbill/* Copyright (c) 2002 Peter O'Gorman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Modified for PARI/GP by the PARI group */ #include "pari.h" #ifndef HAS_DLOPEN #include #include #include #include #include #include #include #include #include "dlfcn.h" #define ERR_STR_LEN 256 static void *dlsymIntern(void *handle, const char *symbol); static const char *error(int setget, const char *str, ...); /* Set and get the error string for use by dlerror */ static const char *error(int setget, const char *str, ...) { static char errstr[ERR_STR_LEN]; static int err_filled = 0; const char *retval; va_list arg; if (setget == 0) { va_start(arg, str); strncpy(errstr, "dlsimple: ", ERR_STR_LEN); vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg); va_end(arg); err_filled = 1; retval = NULL; } else { retval = err_filled? errstr: NULL; err_filled = 0; } return retval; } /* dlopen */ void *dlopen(const char *path, int mode) { void *module = 0; NSObjectFileImage ofi = 0; NSObjectFileImageReturnCode ofirc; static int (*make_private_module_public) (NSModule module) = 0; unsigned int flags = NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE; /* If we got no path, the app wants the global namespace, use -1 as the marker in this case */ if (!path) return (void *)-1; /* Create the object file image, works for things linked with the -bundle arg to ld */ ofirc = NSCreateObjectFileImageFromFile(path, &ofi); switch (ofirc) { case NSObjectFileImageSuccess: /* It was okay, so use NSLinkModule to link in the image */ if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW; module = NSLinkModule(ofi, path,flags); /* Don't forget to destroy the object file image, unless you like leaks */ NSDestroyObjectFileImage(ofi); /* If the mode was global, then change the module, this avoids multiply defined symbol errors to first load private then make global. Silly, isn't it. */ if ((mode & RTLD_GLOBAL)) { if (!make_private_module_public) { _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void**)&make_private_module_public); } make_private_module_public((NSModule)module); } break; case NSObjectFileImageInappropriateFile: /* It may have been a dynamic library rather than a bundle, try to load it */ module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); break; case NSObjectFileImageFailure: error(0,"Object file setup failure : \"%s\"", path); return 0; case NSObjectFileImageArch: error(0,"No object for this architecture : \"%s\"", path); return 0; case NSObjectFileImageFormat: error(0,"Bad object file format : \"%s\"", path); return 0; case NSObjectFileImageAccess: error(0,"Can't read object file : \"%s\"", path); return 0; } if (!module) error(0, "Can not open \"%s\"", path); return module; } static int is_mach_header(void *handle) { /* Check for both possible magic numbers depending on x86/ppc byte order */ return ((((struct mach_header *)handle)->magic == MH_MAGIC) || (((struct mach_header *)handle)->magic == MH_CIGAM)); } /* used by dlsym to find the symbol */ void *dlsymIntern(void *handle, const char *symbol) { NSSymbol nssym = NULL; if (handle == (void *)-1) { /* Global context */ if (NSIsSymbolNameDefined(symbol)) nssym = NSLookupAndBindSymbol(symbol); } else { if (is_mach_header(handle)) { /* library */ if (NSIsSymbolNameDefinedInImage((struct mach_header *)handle, symbol)) nssym = NSLookupSymbolInImage((struct mach_header *)handle, symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); } else /* bundle */ nssym = NSLookupSymbolInModule((NSModule)handle, symbol); } if (!nssym) { error(0, "Symbol \"%s\" Not found", symbol); return NULL; } return NSAddressOfSymbol(nssym); } const char *dlerror(void) { return error(1, (char *)NULL); } int dlclose(void *handle) { if (is_mach_header(handle)) { error(0, "Can't remove dynamic libraries on darwin"); return 0; } if (!NSUnLinkModule((NSModule)handle, 0)) { error(0, "unable to unlink module %s", NSNameOfModule((NSModule)handle)); return 1; } return 0; } /* dlsym, prepend the underscore and call dlsymIntern */ void *dlsym(void *handle, const char *symbol) { static char undersym[257]; /* Saves calls to malloc(3) */ int sym_len = strlen(symbol); void *value = NULL; char *malloc_sym = NULL; if (sym_len < 256) { snprintf(undersym, 256, "_%s", symbol); value = dlsymIntern(handle, undersym); } else { malloc_sym = (char*)malloc(sym_len + 2); if (malloc_sym) { sprintf(malloc_sym, "_%s", symbol); value = dlsymIntern(handle, malloc_sym); pari_free(malloc_sym); } else error(0, "Unable to allocate memory"); } return value; } #endif pari-2.7.5/src/systems/darwin/dlfcn.h0000644000175000017500000000437112366172547016151 0ustar billbill/* Copyright (c) 2002 Jorge Acereda & Peter O'Gorman Portions may be copyright others, see the AUTHORS file included with this distribution. Maintained by Peter O'Gorman Bug Reports and other queries should go to Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _DLFCN_H_ #define _DLFCN_H_ #ifdef __cplusplus extern "C" { #endif /* * Structure filled in by dladdr(). */ typedef struct dl_info { const char *dli_fname; /* Pathname of shared object */ void *dli_fbase; /* Base address of shared object */ const char *dli_sname; /* Name of nearest symbol */ void *dli_saddr; /* Address of nearest symbol */ } Dl_info; extern void * dlopen(const char *path, int mode); extern void * dlsym(void * handle, const char *symbol); extern const char * dlerror(void); extern int dlclose(void * handle); extern int dladdr(void *, Dl_info *); #define RTLD_LAZY 0x1 #define RTLD_NOW 0x2 #define RTLD_LOCAL 0x4 #define RTLD_GLOBAL 0x8 #define RTLD_NOLOAD 0x10 #define RTLD_NODELETE 0x80 #ifdef __cplusplus } #endif #endif /* _DLFCN_H_ */ pari-2.7.5/src/systems/cygwin/0000755000175000017500000000000012613365633014714 5ustar billbillpari-2.7.5/src/systems/cygwin/cygwin.c0000644000175000017500000000156112366172547016370 0ustar billbill/* Copyright (C) 2009 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. */ /* Written by Vasili Burdo */ #include #include char* win32_datadir(void) { char datadir[1024]; char* slash; GetModuleFileNameA(0, datadir, sizeof(datadir) ); slash = strrchr(datadir, '\\'); if( slash ) *(slash+1) = 0; strcat(datadir, "data"); return strdup(datadir); } pari-2.7.5/src/gp/0000755000175000017500000000000012613365633012313 5ustar billbillpari-2.7.5/src/gp/gp_init.c0000644000175000017500000001727412405547147014124 0ustar billbill/* 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 (y20, 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 */ ,}; pari-2.7.5/src/gp/gp.c0000644000175000017500000021113612533333715013066 0ustar billbill/* 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. */ /*******************************************************************/ /** **/ /** PARI CALCULATOR **/ /** **/ /*******************************************************************/ #ifdef _WIN32 # include # include "../systems/mingw/mingw.h" # ifndef WINCE # include # endif #endif #include "pari.h" #include "paripriv.h" #include "gp.h" /********************************************************************/ /** **/ /** 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 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 **/ /** **/ /*******************************************************************/ 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) { 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); for (i=0; i-request@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@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) { 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"); } #define QUOTE "_QUOTE" #define DOUBQUOTE "_DOUBQUOTE" #define BACKQUOTE "_BACKQUOTE" static char * _cat(char *s, const char *t) { *s = 0; strcat(s,t); return s + strlen(t); } 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) { 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; } static void cut_trailing_garbage(char *s) { 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; } } } 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) community(); else if (flag & h_LONG) external_help(s,3); else commands(n); return; } 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) { if (flag & h_LONG) external_help(stack_strcat("se:def,",s),3); else simple_help(s,"default"); } static void aide0(const char *s0, int flag) { 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 ) */ 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; 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 aide(const char *s, long flag) { pari_sp av = avma; if ((flag & h_RL) == 0) { 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; } /********************************************************************/ /** **/ /** 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; 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-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 ?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; isimplify)? "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*)""; 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); } } } 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; #ifdef READLINE if (GP_DATA->use_readline) readline_prompt_color(s, c); else #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; } 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); } return buf; } /********************************************************************/ /* */ /* GP MAIN LOOP */ /* */ /********************************************************************/ static int is_interactive(void) { ulong f = GP_DATA->flags&(gpd_TEXMACS|gpd_TEST); return pari_infile == stdin && !f && gp_is_interactive; } 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) { 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; } void echo_and_log(const char *prompt, const char *s) { 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(); } /* 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) { 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.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) { BLOCK_EH_START #ifdef READLINE if (GP_DATA->use_readline) res = get_line_from_readline(p, Prompt_cont, F); else #endif { 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); 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; } 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 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) { 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: 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); } /* 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++) { 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 */ /* 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) { long l = atol(s); if (l < 0) l = 0; if (l > 255) l = 255; return l; } GEN sd_graphcolormap(const char *v, long flag) { 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; } 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; } GEN sd_help(const char *v, long flag) { 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; } static GEN 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 (flag == d_ACKNOWLEDGE) 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); } 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", ¤t_psfile); } 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; } pari-2.7.5/src/gp/gp_default.h0000644000175000017500000000141012605246304014564 0ustar billbill/* 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 */ }; pari-2.7.5/src/gp/highlvl.h0000644000175000017500000001705312605246305014122 0ustar billbill/* This file is autogenerated from the database. */ /* 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 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."}, {"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 %s%s\n\n", s, wp.oldarg, wp.name, wp.newarg); if (ep) msg(out, ep->help); out_term_color(out, c_NONE); return 1; } pari-2.7.5/src/gp/whatnow.h0000644000175000017500000003271612314556643014165 0ustar billbill/* 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, _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 }; pari-2.7.5/src/gp/highlvl.c0000644000175000017500000000200312366172547014114 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* SOME GP FUNCTION THAT MAY BE USEFUL OUTSIDE OF IT */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "gp.h" #include "../graph/rect.h" #include "highlvl.h" pari-2.7.5/src/gp/gp_init.h0000644000175000017500000000416212605246304014112 0ustar billbill/* This file is autogenerated from the database. */ /* 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."}, {NULL,0,NULL,0,NULL,NULL} /* sentinel */ }; pari-2.7.5/src/gp/gp_rl.c0000644000175000017500000006213212366172547013573 0ustar billbill/* 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. */ /*******************************************************************/ /* */ /* INTERFACE TO READLINE COMPLETION */ /* */ /*******************************************************************/ #include "pari.h" #ifdef READLINE #include "paripriv.h" #include "gp.h" typedef int (*RLCI)(int, int); /* rl_complete and rl_insert functions */ typedef char* (*GF)(const char*, int); /* generator function */ BEGINEXTERN /* otherwise C++ compilers will choke on rl_message() prototype */ #define USE_VARARGS #define PREFER_STDARG #include #include 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; static int change_state(const char *msg, ulong flag, int count) { int c = (readline_state & flag) != 0; ulong o_readline_state = readline_state; switch(count) { default: c = 0; break; /* off */ case -1: c = 1; break; /* on */ case -2: c = 1 - c; /* toggle */ } if (c) readline_state |= flag; else { readline_state &= ~flag; if (!readline_state && o_readline_state) readline_state = 1; } rl_save_prompt(); rl_message("[%s: %s] ", msg, c? "on": "off"); c = rl_read_key(); rl_restore_prompt(); rl_clear_message(); rl_stuff_char(c); return 1; } /* Wrapper around rl_complete to allow toggling insertion of arguments */ static int pari_rl_complete(int count, int key) { int ret; pari_rl_back = 0; if (count <= 0) return change_state("complete args", DO_ARGS_COMPLETE, count); rl_begin_undo_group(); if (rl_last_func == pari_rl_complete) rl_last_func = (RLCI) rl_complete; /* Make repeated TABs different */ ret = ((RLCI)rl_complete)(count,key); if (pari_rl_back && (pari_rl_back <= rl_point)) rl_point -= pari_rl_back; rl_end_undo_group(); return ret; } static int did_matched_insert; static int pari_rl_matched_insert_suspend(int count, int key) { ulong o_readline_state = 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; return 1; } static int pari_rl_matched_insert_restore(int count, int key) { (void)count; (void)key; if (did_matched_insert) readline_state |= DO_MATCHED_INSERT; return 1; } static const char paropen[] = "([{"; static const char parclose[] = ")]}"; /* To allow insertion of () with a point in between. */ static int pari_rl_matched_insert(int count, int key) { int i = 0, ret; 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) return ((RLCI)rl_insert)(count,key); rl_begin_undo_group(); ((RLCI)rl_insert)(count,key); ret = ((RLCI)rl_insert)(count,parclose[i]); rl_point -= count; rl_end_undo_group(); return ret; } static int pari_rl_default_matched_insert(int count, int key) { if (!did_init_matched) { did_init_matched = 1; readline_state |= DO_MATCHED_INSERT; } return pari_rl_matched_insert(count, key); } static int pari_rl_forward_sexp(int count, int key) { int deep = 0, dir = 1, move_point = 0, lfail; (void)key; if (count < 0) { count = -count; dir = -1; if (!rl_point) goto fail; rl_point--; } while (count || deep) { move_point = 1; /* Need to move point if moving left. */ lfail = 0; /* Do not need to fail left movement yet. */ while ( !is_keyword_char(rl_line_buffer[rl_point]) && !strchr("\"([{}])",rl_line_buffer[rl_point]) && !( (dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0 && (lfail = 1)))) rl_point += dir; if (lfail || !rl_line_buffer[rl_point]) goto fail; if (is_keyword_char(rl_line_buffer[rl_point])) { while ( is_keyword_char(rl_line_buffer[rl_point]) && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0 && (lfail = 1))) || (move_point = 0))) rl_point += dir; if (deep && lfail) goto fail; if (!deep) count--; } else if (strchr(paropen,rl_line_buffer[rl_point])) { if (deep == 0 && dir == -1) goto fail; /* We are already out of pars. */ rl_point += dir; deep++; if (!deep) count--; } else if (strchr(parclose,rl_line_buffer[rl_point])) { if (deep == 0 && dir == 1) { rl_point++; goto fail; /* Get out of pars. */ } rl_point += dir; deep--; if (!deep) count--; } else if (rl_line_buffer[rl_point] == '\"') { int bad = 1; rl_point += dir; while ( ((rl_line_buffer[rl_point] != '\"') || (bad = 0)) && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0)) || (move_point = 0)) ) rl_point += dir; if (bad) goto fail; rl_point += dir; /* Skip the other delimiter */ if (!deep) count--; } else { fail: rl_ding(); return 1; } } if (dir != 1 && move_point) rl_point++; return 1; } static int pari_rl_backward_sexp(int count, int key) { return pari_rl_forward_sexp(-count, key); } /* do we add () at the end of completed word? (is it a function?) */ static int add_paren(int end) { entree *ep; const char *s; if (end < 0 || rl_line_buffer[end] == '(') return 0; /* not from command_generator or already there */ ep = do_alias(current_ep); /* current_ep set in command_generator */ if (EpVALENCE(ep) < EpNEW) { /* is it a constant masked as a function (e.g Pi)? */ s = ep->help; if (!s) return 1; while (is_keyword_char(*s)) s++; return (*s != '='); } switch(EpVALENCE(ep)) { case EpVAR: return typ((GEN)ep->value) == t_CLOSURE; case EpINSTALL: return 1; } return 0; } static void match_concat(char **matches, const char *s) { matches[0] = (char*)pari_realloc((void*)matches[0], strlen(matches[0])+strlen(s)+1); strcat(matches[0],s); } #define add_comma(x) (x==-2) /* from default_generator */ /* a single match, possibly modify matches[0] in place */ static void treat_single(int code, char **matches) { if (add_paren(code)) { match_concat(matches,"()"); pari_rl_back = 1; if (rl_point == rl_end) rl_completion_append_character = '\0'; /* Do not append space. */ } else if (add_comma(code)) match_concat(matches,","); } #undef add_comma static char ** matches_for_emacs(const char *text, char **matches) { if (!matches) printf("@"); else { int i; printf("%s@", matches[0] + strlen(text)); if (matches[1]) print_fun_list(matches+1,0); /* we don't want readline to do anything, but insert some junk * which will be erased by emacs. */ for (i=0; matches[i]; i++) pari_free(matches[i]); pari_free(matches); } matches = (char **) pari_malloc(2*sizeof(char *)); matches[0] = (char*)pari_malloc(2); sprintf(matches[0],"_"); matches[1] = NULL; printf("@E_N_D"); pari_flush(); return matches; } /* Attempt to complete on the contents of TEXT. 'code' is used to * differentiate between callers when a single match is found. * Return the array of matches, NULL if there are none. */ static char ** get_matches(int code, const char *text, GF f) { char **matches = rl_completion_matches(text, f); if (matches && !matches[1]) treat_single(code, matches); if (GP_DATA->flags & gpd_EMACS) matches = matches_for_emacs(text,matches); return matches; } 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); strcpy(s+junk,name); return s; } static void init_prefix(const char *text, int *len, int *junk, char **TEXT) { long l = strlen(text), j = l-1; while (j >= 0 && is_keyword_char(text[j])) j--; j++; *TEXT = (char*)text + j; *junk = j; *len = l - j; } static int is_internal(entree *ep) { return ep->menu >= 13 && ep->menu <= 15; } /* Generator function for command completion. STATE lets us know whether * to start from scratch; without any state (i.e. STATE == 0), then we * start at the top of the list. */ static char * hashtable_generator(const char *text, int state, entree **hash) { static int hashpos, len, junk; static entree* ep; static char *TEXT; /* If this is a new word to complete, initialize now: * + indexes hashpos (GP hash list) and n (keywords specific to long help). * + file completion and keyword completion use different word boundaries, * have TEXT point to the keyword start. * + save the length of TEXT for efficiency. */ if (!state) { hashpos = 0; ep = hash[hashpos]; init_prefix(text, &len, &junk, &TEXT); } /* Return the next name which partially matches from the command list. */ for(;;) if (!ep) { if (++hashpos >= functions_tblsz) return NULL; /* no names matched */ ep = hash[hashpos]; } else if (is_internal(ep) || strncmp(ep->name,TEXT,len)) ep = ep->next; else break; current_ep = ep; ep = ep->next; return add_prefix(current_ep->name,text,junk); } /* Generator function for member completion. STATE lets us know whether * to start from scratch; without any state (i.e. STATE == 0), then we * start at the top of the list. */ static char * member_generator(const char *text, int state) { static int hashpos, len, junk; static entree* ep; static char *TEXT; entree **hash=functions_hash; /* If this is a new word to complete, initialize now: * + indexes hashpos (GP hash list) and n (keywords specific to long help). * + file completion and keyword completion use different word boundaries, * have TEXT point to the keyword start. * + save the length of TEXT for efficiency. */ if (!state) { hashpos = 0; ep = hash[hashpos]; init_prefix(text, &len, &junk, &TEXT); } /* Return the next name which partially matches from the command list. */ for(;;) if (!ep) { if (++hashpos >= functions_tblsz) return NULL; /* no names matched */ ep = hash[hashpos]; } else if (ep->name[0]=='_' && ep->name[1]=='.' && !strncmp(ep->name+2,TEXT,len)) break; else ep = ep->next; current_ep = ep; ep = ep->next; return add_prefix(current_ep->name+2,text,junk); } static char * command_generator(const char *text, int state) { return hashtable_generator(text,state, functions_hash); } static char * default_generator(const char *text,int state) { return hashtable_generator(text,state, defaults_hash); } static char * ext_help_generator(const char *text, int state) { static int len, junk, n, def, key; static char *TEXT; if (!state) { n = 0; def = key = 1; init_prefix(text, &len, &junk, &TEXT); } if (def) { char *s = default_generator(TEXT, state); if (s) return add_prefix(s, text, junk); def = 0; } if (key) { for ( ; keyword_list[n]; n++) if (!strncmp(keyword_list[n],TEXT,len)) return add_prefix(keyword_list[n++], text, junk); key = 0; state = 0; } return command_generator(text, state); } static void rl_print_aide(char *s, int flag) { int p = rl_point, e = rl_end; FILE *save = pari_outfile; 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); rl_restore_prompt(); rl_point = p; rl_end = e; pari_outfile = save; rl_clear_message(); rl_refresh_line(0,0); } /* add a space between \ and following text. Attempting completion now * would delete char. Hitting again will complete properly */ static char ** add_space(int start) { char **m; int p = rl_point + 1; rl_point = start + 2; rl_insert(1, ' '); rl_point = p; /*better: fake an empty completion, but don't append ' ' after it! */ rl_completion_append_character = '\0'; m = (char**)pari_malloc(2 * sizeof(char*)); m[0] = (char*)pari_malloc(1); *(m[0]) = 0; m[1] = NULL; return m; } static char ** pari_completion(char *text, int START, int END) { int i, first=0, start=START; rl_completion_append_character = ' '; current_ep = NULL; /* If the line does not begin by a backslash, then it is: * . an old command ( if preceded by "whatnow(" ). * . a default ( if preceded by "default(" ). * . a member function ( if preceded by "." + keyword_chars ) * . a file name (in current directory) ( if preceded by 'read' or 'writexx' ) * . a command */ if (start >=1 && rl_line_buffer[start] != '~') start--; while (start && is_keyword_char(rl_line_buffer[start])) start--; if (rl_line_buffer[start] == '~') { GF f = (GF)rl_username_completion_function; for(i=start+1;i<=END;i++) if (rl_line_buffer[i] == '/') { f = (GF)rl_filename_completion_function; break; } return get_matches(-1, text, f); } while (rl_line_buffer[first] && isspace((int)rl_line_buffer[first])) first++; switch (rl_line_buffer[first]) { case '\\': if (first == start) return add_space(start); return get_matches(-1, text, rl_filename_completion_function); case '?': if (rl_line_buffer[first+1] == '?') return get_matches(-1, text, ext_help_generator); return get_matches(-1, text, command_generator); } while (start && rl_line_buffer[start] != '(' && rl_line_buffer[start] != ',') start--; if (rl_line_buffer[start] == '(' && start) { int iend, j,k; entree *ep; char buf[200]; i = start; while (i && isspace((int)rl_line_buffer[i-1])) i--; iend = i; while (i && is_keyword_char(rl_line_buffer[i-1])) i--; 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); j = start + 1; while (j <= END && isspace((int)rl_line_buffer[j])) j++; 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 && (rl_line_buffer[j] == ')' || !rl_line_buffer[j]) && (iend - i < (long)sizeof(buf)) && ( strncpy(buf, rl_line_buffer + i, iend - i), buf[iend - i] = 0, 1) && (ep = is_entry(buf)) && ep->help) { const char *s = ep->help; while (is_keyword_char(*s)) s++; if (*s++ == '(') { /* function call: insert arguments */ const char *e = s; while (*e && *e != ')' && *e != '(') e++; if (*e == ')') { /* we just skipped over the arguments in short help text */ char *str = strncpy((char*)pari_malloc(e-s + 1), s, e-s); char **ret = (char**)pari_malloc(sizeof(char*)*2); str[e-s] = 0; ret[0] = str; ret[1] = NULL; if (GP_DATA->flags & gpd_EMACS) ret = matches_for_emacs("",ret); return ret; } } } } for(i = END-1; i >= start; i--) if (!is_keyword_char(rl_line_buffer[i])) { if (rl_line_buffer[i] == '.') return get_matches(-1, text, member_generator); break; } return get_matches(END, text, command_generator); } /* long help if count < 0 */ static int rl_short_help(int count, int key) { int flag = h_RL; char *s = rl_line_buffer + rl_point; (void)key; /* func() with cursor on ')', e.g. following completion */ if (s > rl_line_buffer && *s == ')' && s[-1] == '(') s--; while (s > rl_line_buffer && is_keyword_char(s[-1])) s--; /* check for '\c' */ if (s > rl_line_buffer && s[-1] == '\\') s--; if (count < 0 || rl_last_func == rl_short_help) flag |= h_LONG; rl_print_aide(s, flag); return 0; } static int 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", ¤t_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); } static int history_is_new(char *s) { HIST_ENTRY *e; if (!*s) return 0; if (!history_length) return 1; e = history_get(history_length); /* paranoia: e != NULL, unless readline is in a weird state */ return e? strcmp(s, e->line): 0; } static void gp_add_history(char *s) { if (history_is_new(s)) { add_history(s); append_history(1,current_histfile); } } /* Read line; returns a malloc()ed string of the user input or NULL on EOF. Increments the buffer size appropriately if needed; fix *endp if so. */ static char * gprl_input(char **endp, int first, input_method *IM, filtre_t *F) { char buf[MAX_PROMPT_LEN + 24]; 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); char *s, *t; if (! (s = readline(prompt)) ) return NULL; /* EOF */ gp_add_history(s); /* Makes a copy */ l = strlen(s) + 1; /* put back \n that readline stripped. This is needed for * { print("a * b"); } * and conforms with the other input methods anyway. */ t = (char*)pari_malloc(l + 1); strncpy(t, s, l-1); t[l-1] = '\n'; t[l] = 0; /* equivalent to sprintf(t,"%s\n", s) */ if (left < l) { ulong incr = b->len; if (incr < l) incr = l; fix_buffer(b, b->len + incr); *endp = b->buf + used; } return t; } /* request one line interactively. * Return 0: EOF * 1: got one line from readline or pari_infile */ int get_line_from_readline(const char *prompt, const char *prompt_cont, filtre_t *F) { const int index = history_length; char *s; input_method IM; IM.prompt = prompt; IM.prompt_cont = prompt_cont; IM.getline = &gprl_input; IM.free = 1; if (! input_loop(F,&IM)) { pari_puts("\n"); return 0; } s = F->buf->buf; if (*s) { if (history_length > index+1) { /* Multi-line input. Remove incomplete lines */ int i = history_length; while (i > index) { HIST_ENTRY *e = remove_history(--i); pari_free(e->line); pari_free(e); } gp_add_history(s); } echo_and_log(prompt, s); } return 1; } #endif pari-2.7.5/MACHINES0000644000175000017500000005554211636712103012233 0ustar billbillNOTE : Due to the widespread availability of free and reliable operating systems (e.g. GNU/Linux) and C compilers (e.g. gcc), and the gradual extinction of "exotic" systems, this file is no longer actively maintained. See http://pari.math.u-bordeaux1.fr/buildlog.html for an overview of the development platforms we have access to and actively maintain. ============================================================================== This file gives information about architectures/operating systems GP has been compiled on. If your configuration is not listed, it means that nobody sent us information about it. If indeed GP builds successfuly, we'd be grateful if you could notify us at the address pari@math.u-bordeaux.fr Please include a line analogous to the ones below, so that we can accordingly expand the list. ============================================================================== General notes: binaries should be compiled with native kernel (--without-gmp) - Arch a star (*) in the first column means GP was built using portable kernel. - Bench, as output by `make bench' 1) can vary with load, available memory, compiler version ... 2) is not the actual time spent: bench "nfields" is weighted by 1/5. 3) An ! present next to the timing means that install() did not work with that configuration ([BUG] in 'program' bench) NOTE: bench timings in version 2.0.11 and 2.0.12 were not correct (given between parentheses). Add about 25% to running times for comparison with other versions. Clock frequency in MHz when known, in BM (BogoMIPS) otherwise. Bench Arch / proc: OS: Compiler: sta: dyn: GP version: ============================================================================== DEC/Alpha alpha21264c 1000MHz OSF1-V5.1 cc 990 1165 2.2.3 IS alpha21264b 833MHz OSF1-V5.1 cc 1867 2099 2.1.1 JC alpha21264 667Mhz FreeBSD-4.0 gcc 2626! 2656 2.0.20 IS alpha21264 500MHz OSF1-V4.0 gcc-2.8.1 3178 3436 2.1.0 JC alpha21264 500MHz OSF1-V4.0 gcc-2.95.3 1885 1980 2.2.1 GH alpha21164a 600MHz Linux-2.4.9 gcc.2.96 3746 3771 2.2.6 alpha21164a 600MHz Linux-2.2.13 egcs 4270 4350 2.0.19(26)IS alpha21164 600MHz OSF1-V4.0D cc 3996 4384 2.0.10 LG alpha21164 533Mhz Linux 2.0.34 gcc (4294) (4385) 2.0.12 JC alpha21164 500Mhz Linux-2.2.13 egcs-2.91.66 5167 5217 2.1.1 alpha21164 500Mhz Linux-2.2.13 gcc-2.95.3 4319 4253 2.2.2 (27) alpha21064 172Mhz OSF1-3.0 cc 34104 35564 2.1.1 ------------------------------------------------------------------------------ Sun/SPARC Sun-Fire V440 1593MHz*4 Solaris-10 gcc-4.0.3 655 658 2.3.0 SHo UltraSPARCIII+ 900MHz Solaris-9 gcc-3.4.1 1434 1442 2.2.8 IS UltraSPARCIII 750MHz Solaris-8 gcc-3.4.1 1685 1708 2.2.8 IS UltraSPARC-IIe 502MHz Solaris-8 gcc 3608 3646 2.1.4 HR UltraSPARCII 450MHz Solaris-7 gcc-3.4.1 3007 3007 2.2.8 IS UltraSPARC60 450MHz Solaris-7 gcc 3970 4010 2.0.19 IS UltraSPARC60 450MHz Solaris-7 cc 5070 5210 2.0.19 IS UltraSPARC2i 440MHz Solaris-8 gcc-2.95.2 2802 3028 2.3.0 Ultra250 400MHz Solaris-7 gcc 4510 4560 2.0.19 IS Ultra250 400MHz Solaris-7 cc 5950 6090 2.0.19 IS UltraSPARC60 360MHz Solaris-2.6 gcc 5034 5209 2.0.16 IS UltraSPARC60 360MHz Solaris-2.6 cc 6329 6453 2.0.16 IS UltraSPARC2i 360MHz Solaris-7 egcs 5816 6286 2.0.16(17)HS UltraSPARC2i 333MHz Solaris-7 gcc 5666 6818 2.0.20(18) UltraSparcII 300MHz Linux-2.4.18 gcc-3.2.3 6102 6184 2.1.5 BA UltraSPARC10 300MHz Solaris-2.6 gcc (5932) (6102) 2.0.12 GN UltraSPARC 300MHz Solaris-2.5 gcc 7643 7566 2.0.9 IS UltraSPARC2 296MHz Solaris-2.5.1 gcc 6098 6277 2.0.16 IS UltraSPARC2 296MHz Solaris-2.5.1 cc 7676 7869 2.0.16 IS UltraSPARC2i 270MHz Solaris-7 gcc 9008 7860 2.0.16 IZ UltraSPARC2i 270MHz Solaris-2.6 cc 9200 9970 2.0.10 LG UltraSPARC2 248MHz Solaris-7 cc-5.0 9420 9692 2.0.18(13)GN UltraSPARC2 248MHz Solaris-7 egcs 7218 7262 2.0.16 HS UltraSPARC 200MHz Solaris-2.5.1 gcc 9226 9268 2.0.16 IS UltraSPARC 200MHz Solaris-2.5.1 cc 11226 11755 2.0.16 IS UltraSPARC 167MHz Solaris-2.6 gcc 10767 11218 2.0.16 IS UltraSPARC 167MHz Solaris-2.6 cc 13677 13967 2.0.16 IS UltraSPARC 167MHz Solaris-7 gcc-2.8.1 9106 9144 2.2.4 UltraSPARC 167MHz Solaris-2.5 g++ 13474 13418 2.0.9 (7) LG UltraSPARC 167MHz Solaris-2.5 CC 15778! 16400! 2.0.9 LG UltraSPARC 167MHz Solaris-2.5 cc 16241 17048 2.0.9 LG UltraSPARC 143MHz Solaris-2.5 gcc-2.95.3 11905 11723 2.2.1 SuperSPARC2 75MHz Solaris-2.5 gcc 16969 17013 2.0.10 LG SuperSPARC 50Mhz Linux-2.2.14 gcc 41126 40854 2.0.18(20)BA SuperSPARC 40MHz SunOS-4.1.3 gcc 31178 30456 2.0.19 SuperSPARC 40Mhz Solaris-2.5 gcc 31528 31576 2.0.16 TurboSPARC 170MHz Solaris-2.5 gcc 15907 16529 2.0.9 LG MicroSPARC2 110MHz NextStep-v3 cc 37794! - 2.0.9 LG MicroSPARC2 110MHz SunOS-4.1.4 gcc 31476 32123 2.0.9 LG MicroSPARC2 110MHz Solaris-2.5 gcc-2.7.2 24197 24107 2.2.2 SPARCv7(SS2) 40MHz SunOS-4.1.3 gcc 115212! 115364 2.0.9 LG SPARCv7(ELC) 33MHz SunOS-4.1.1 gcc 139406! - 2.0.8 GN SPARCv7(SS400) ??? SunOS-4.1.4 gcc 107074 106494 2.0.16(19)DE SPARCv7(HWS210) ??? Linux-2.2.5 gcc 98488! - 2.0.16(14)DE ------------------------------------------------------------------------------ Intel/x86_64 in 64bit mode Core2Duo 3400MHz Linux-2.6.20-16 gcc-4.1.2 134 136 2.3.2 RN AMD Opteron 2400MHz Linux-2.6.12-1 gcc-4.0.1 198 204 2.2.11 PZ AMD Opteron 2200MHz Linux-2.6.11-6 gcc-3.4.3 206 221 2.3.0 AMD Opteron 2000MHz Linux-2.4.22 gcc-3.3.2 290 290 2.2.8 AMD Athlon 64 3000+ Linux-2.6.15 gcc-4.1.0 300 287 2.3.0 JB AMD Opteron 1333MHz Linux-2.6.5 gcc-3.3 413 419 2.2.8 BA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Intel/x86 AMD Opteron 1333MHz Linux-2.6.5 gcc-3.3 536 539 2.2.8 BA AMD Athlon XP2400+ Linux-2.4.21 gcc-3.2 428 398 2.2.5 (41)MH AMD Athlon XP1800+ Linux-2.4.17 gcc-3.0.4 616 616 2.2.3 (30)PE AMD Athlon MP1800+ Linux-2.4.9 gcc-2.96 696 688 2.2.3 (29)HC AMD Athlon 1250MHz Linux-2.4.2 gcc-2.96 597 591 2.2.10a HV AMD Athlon 1200MHz Linux-2.4.7 gcc-2.96 1002 992 2.1.2 CL AMD Athlon 1100MHz Linux-2.4.2-2 gcc 1078 1076 2.1.1 DP AMD Duron 1200MHz Linux-2.4.19 gcc-3.2 789 800 2.2.4 QL AMD Duron 1200MHz Linux-2.4.19 gcc-2.95.3 834 851 2.2.4 QL AMD Duron 1000MHz Linux-2.4.0 egcs 1364 1428 2.0.20 QL AMD Athlon 850MHz Linux-2.2.17 gcc 1364 1342 2.1.0 JC AMD Duron 700MHz Linux-2.4.0 egcs 2066 2138 2.0.20 QL AMD Athlon 500MHz Linux-2.2.13 gcc 2736 2724 2.0.18 MS AMD K6-2 350Mhz Linux-2.0.34 egcs (4856) (4756) 2.0.11 SH AMD K6-2 350Mhz Linux-2.0.36 gcc 5154 4850 2.0.17 AMD K6 266MHz Linux-2.2.5 pgcc 5861 6001 2.0.16(16)IS AMD K6 233Mhz Linux-2.2.14 gcc 6968 7158 2.0.18 QL IBM/Cyrix 200MHz Linux-2.0.35 gcc 13190 13729 2.0.15 AP CoreDuo 2160MHz MacOS X 10.4 gcc-4.0.1 376 - 2.3.0 LG PentiumIV 3000MHz Linux-2.6.22-1 gcc-4.1.2 376 370 2.3.3 RM PentiumIV 3000MHz Linux-2.6.11-1 gcc-3.4.3 291 296 2.2.11 PZ PentiumM 1600MHz Linux-2.6.8 gcc-3.3.4 461 460 2.2.8 JD PentiumIV 2800MHz Linux-2.6.11 gcc-3.4.1 402 398 2.3.0 PentiumIV 2000MHz Linux-2.4.20 gcc-3.3 794 962 2.2.6 (42)ID PentiumIV 2000MHz Linux-2.4.18 gcc-3.2 849 835 2.1.5 (25)FU PentiumIV 1800MHz WinXP + Cygwin gcc-3.2 1384! - 2.2.5 (38)DC PentiumIV 1695MHz FreeBSD 4.6.2 gcc-2.95.3 904 918 2.2.5 MW PentiumIV 1600MHz Linux-2.4.18-3 gcc-2.96 930 926 2.2.5 PentiumIV 1400MHz Linux-2.4.4-4 gcc-2.95.3 1318 1354 2.1.3 HG PentiumIII 1400MHz FreeBSD-4.6.2 gcc-2.95.3 752 757 2.2.4(35) IS PentiumIII 1133MHz Linux-2.4.18 gcc-2.96 1028 1055 2.2.4(36) IS PentiumIII 1000MHz Linux-2.4.7-10 gcc-2.96 1128 1180 2.2.4 PentiumIII 933MHz Linux-2.2.15 egcs 1450 1485 2.0.20 IS PentiumIII 800MHz Linux-2.2.14 egcs 1900 1882 2.0.20 CL PentiumIII 800MHz Linux-2.2.19 gcc-2.96 1638 1624 2.1.2 OT PentiumIII 733MHz Linux-2.2.14 egcs 2080 2090 2.0.19 IS PentiumIII 550MHz Linux-2.5.56 gcc.3.2.1 1918 1984 2.2.5 MH PentiumIII 533MHz Linux-2.2.14 gcc 2710 2730 2.0.19 IS PentiumIII 500MHz Linux-2.2.12 egcs 3154 3176 2.0.18 HC PentiumII 450MHz Linux-2.4.18 gcc-3.0.4 2348 2426 2.2.3 (31)PE PentiumII 450MHz Linux-2.0.35 gcc 3220 3230 2.1.1 TT PentiumII 400MHz Linux-2.3.99 gcc 3392 3410 2.0.20(25)GH PentiumII 400MHz Linux-2.2.14 gcc 3886 3902 2.0.20 GH PentiumII 366MHz Linux-2.2.16 gcc-2.95.2 4018 4118 2.1.3 HG PentiumII 350MHz Linux-2.2.16 gcc-2.95.2 3760 3784 2.2.1 PentiumII 350MHz Win98 mingw-2.95.2 4412! - 2.1.0 (22) PentiumII 350MHz Win98 + Cygwin1 gcc-2.95.2-5 4026! - 2.2.1 PentiumII 350MHz Win98 + RSX gcc 9436! - 2.0.20(24) PentiumII 350Mhz Linux 2.0.36 pgcc-2.92.21 (3310) (3340) 2.0.12(11)PE PentiumII 350Mhz Linux 2.0.36 egcs-2.92.21 (3352) (3402) 2.0.12(11)PE PentiumII 350Mhz Linux 2.0.36 gcc (3600) (3610) 2.0.12 PE PentiumII 333Mhz Linux-2.2.19 gcc-2.7 4446 4464 2.1.1 BA PentiumII 333Mhz Linux-2.2.19 gcc-3.0.2 4104 4218 2.1.1 BA PentiumII 300MHz NextStep-3.3 cc 5325! - 2.0.10 PentiumII 233MHz FreeBSD-2.2.5 gcc (6251) (6114) 2.0.11 PentiumII 233MHz Linux-2.0.35 gcc (7460) (7586) 2.0.12 HG PentiumPro 200MHz Linux-2.2.12 egcs 2.91.66 6036 6044 2.2.6 Pentium 266Mhz Linux-2.0.29 gcc (7256) (7044) 2.0.11 Pentium 200MHz Linux-2.2.10 gcc 12062 12340 2.0.18 MS Pentium 200Mhz NextStep-3.3 cc 16035! - 2.0.06 MS Pentium 166MHz FreeBSD-2.2.5 gcc (15159) (14481) 2.0.11 Pentium 166MHz Solaris-2.6 gcc (13550) (13746) 2.0.12 GN Pentium 133MHz Linux-1.2.8 gcc-2.7.2p (15448!) - 2.0.12 GN Pentium 133MHz FreeBSD-2.2.5 gcc 15231 17259 2.0.10 KK 486DX (Cyrix) 66MHz Linux 2.2.18 gcc 59078 60600 2.1.1 CC 486DX2 50MHz Linux-2.0.33 gcc 213710 216224 2.0.9 LG 486DX 50MHz DOS-5 + EMX gcc 77126! - 2.0.20 *i860 40MHz Concentrix cc 147989! - 2.0.9 LG - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Intel/ARM *StrongARM 110MHz Linux-2.4.5 gcc-2.95.2 17162! - 2.1.1 BA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Intel/ia64 *Itanium II 1000MHz Linux-2.4.19 gcc-3.0.4 1318 1478 2.1.5 BA *Itanium 800MHz Linux-2.4.9 gcc-3.0.1 2557 2474 2.1.2 (28)BA Itanium 733MHz Linux-2.4.21 gcc-4.1.0 1405 1494 2.2.13 BA ------------------------------------------------------------------------------ Motorola MC68060 50MHz Linux-2.4.31 gcc-4.0.3 30010 30584 2.2.13(40)BA *MC68060 50MHz Linux-2.4.26 gcc-3.3.3 49586 50296 2.2.8 (40)BA *MC68060 50MHz Linux-2.2.20 gcc-2.95.4 74998 2.1.3 (37)BA *MC68040 25MHz NextStep-v2 cc 250542! - 2.0.9 LG MC68030 25MHz SunOS-4.0.3 gcc 683736! 685248 2.0.9 (4) *MC68030 25MHz SunOS-4.0.3 gcc 1034136!1038368 2.0.9 ------------------------------------------------------------------------------ IBM/Cell Sony PS3 3192MHZ Linux 2.6.18 gcc-4.3.2 620 643 2.4.3 BA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IBM/POWER,PowerPC PPC G5 2000MHz MacOS X 10.4 gcc-4.0.1 461 - 2.3.0 LG PPC G4 1667MHz MacOS X 10.4 gcc-3.3 543 - 2.3.0 LG PPC G4 1000MHz MacOS X 10.3 gcc-3.3 940 - 2.3.2 BM *PPC G4 400MHz MacOS X 10.2 gcc-3.1 5174! - 2.1.4 MB *PowerMac3,3 500MHz Linux-2.4.2 gcc 3742 3732 2.1.1 BA *PPC800(G3) 400MHz Linux-2.4.3 gcc 4640 4624 2.2.0 GH *PPC750(G3) 400MHZ Linux-2.4.24 gcc-2.95.4 3840 3872 2.1.5 SC *PPC???(G3) 350MHz MacOS X 10.1 gcc-2.95.2 5722! - 2.1.2 NI *PPC750(G3) 266MHz Linux-2.2.6 gcc 6944 6924 2.0.18 DE *PPC604e 233MHz AIX-4.2 cc (8616!) - 2.0.12(3) GN *PPC604 133MHz AIX-4.2 cc 21528! - 2.0.4 (3) GN *PPC601 100MHz AIX-4.1 cc 21692! - 2.0.4 (3) GN *PPC601 75MHz Linux-2.1.24 gcc 51810 52702 2.0.9 EK *PPC601 66MHz AIX-3.2.5 cc 66280! - 2.0.4 (3) GN *POWER2 66MHz AIX-4.2 cc 37592! - 2.0.4 (3) GN ------------------------------------------------------------------------------ IBM/S390 *S390 773BM Linux-2.4.19 gcc-3.2.3 5272 5646 2.1.5 (39)BA *S390 630BM Linux-2.4.17 gcc-2.95.4 6764 6574 2.1.3 (33)BA ------------------------------------------------------------------------------ SGI/MIPS *R5000 250MHz Linux-2.4.20 gcc-3.2.3 10778 10664 2.2.6CVS BA *R10000 196MHz IRIX-6.4 cc 8461 9856 2.0.10(8) TP *R10000 196Mhz IRIX-6.2 cc 15719 15581 2.0.13(12)BN *R4000 75MHz Linux-2.4.19 gcc-2.95.4 37324 36098 2.1.5 BA *R4000 50/70MHz IRIX-5.2 gcc 70764 70114 2.0.9 (1) TP *R4000 50/70MHz IRIX-5.2 cc 81467 80176 2.0.9 (2) TP ------------------------------------------------------------------------------ HP/PA-RISC HPPA9000/785 552MHz HPUX-11.00 gcc-2.9 8284 8460 2.2.4(34) IS *HPPA8500 440MHz Linux-2.4.16 gcc-3.0.3 7558 7814 2.1.2 BA HPPA9000/778 134MHz HPUX-10.20 cc 18898! 29138! 2.0.19(9) *HPPA9000/778 134MHz HPUX-10.20 cc (23666!) - 2.0.12(10) HPPA9000/735 100MHz HPUX-10.20 cc (25106!)(38898!)2.0.12(9) HPPA9000/735 100MHz HPUX-09-07 cc 25714! - 2.0.16(15)IS HPPA9000/720 ??? HPUX-10.20 cc 66138! - 2.0.9 *HPPA9000/720 ??? HPUX-10.20 cc 101114! 119626 2.0.9 HPPA9000/712 90MHz HPUX-10.20 cc (26756!)(45196!) 2.0.12(9) *HPPA9000/712 ??? HPUX-10.10 gcc 66328! 71250! 2.0.5 (6) *HPPA7100LC 60MHz NextStep-v3 cc 62866! - 2.0.10 LG *HPPA7000 50MHz HPUX-09.05 cc 113406! 152778! 2.0.9 LG ------------------------------------------------------------------------------ Notes: ====== (1) uncomment the last PLOTLIBS= in Makefile (2) same as above, compiled with cc -O2 (3) AIX/POWER versions built with cc options including -qarch=com -qtune=601 (any other tuning makes them slower GN) Addendum (IK): gcc 2.8.1 -O2 -DGCC_INLINE -mtune=604e produces a faster binary (4) Slightly different results in make bench (last decimal different in 3 tests, due to a different mulsr()) (6) gcc -fPIC (otherwise /usr/bin/ld will not link the shared library) (7) the `program' bench fails on "install(addii)". But if the symbol addii is declared within extern "C" {} in paridecl.h, it works. (8) use CC = cc -64 -DLONG_IS_64BIT CFLAGS = -O -OPT:Olimit=2170 LD = cc -64 LDFLAGS = -O -L/usr/lib64 DLLD = cc -64 DLLDFLAGS = -shared -elf -no_unresolved -all -L/usr/lib64 CPP = cc -64 -E -I. (9) * for gp-dyn: couldn't find a way to produce PIC code with either -- HP as, version HP92453-03 UX.10.20.05 (DAVIS) PA-RISC 2.0 Assembler (+z, +Z ignored) -- gcc-2.8.1 + gas-2.6 (hppa1.1-hp-hpux9.01), using BFD version 2.6 (-fPIC -shared ignored) (bad) FIX: in o-hpux.hppa/Makefile, move kernel.o from OBJS to OBJSGP. Hence kernel.o has to be linked explicitly with all programs compiled with libpari.sl * for gp-sta: remove +z from CFLAGS and LDFLAGS, final link only worked with the following command line (there has to be a better way...): cc dummy.c -c cc -o gp-sta -Wl,-a,archive -O dummy.o [... rest as produced by Configure] where dummy.c defines three dummy symbols (referenced in static libc): shl_findsym(){} shl_unload(){} shl_load(){} Whatever else I tried, linking failed: /usr/ccs/bin/ld: Data address is out of range for short load or store Reference from: kernel.o(0x8) [for all symbols defined in level0.s] (10) compiled without +z flags (11) CFLAGS (for egcs)= -O9 -malign-double -fschedule-insns2 -mpentium\ -march=pentium -fomit-frame-pointer -fno-strength-reduce\ -fno-inline-functions -fexpensive-optimizations CFLAGS (for pgcc)= -O9 -malign-double -mk6 -fomit-frame-pointer\ -fno-strength-reduce -fno-inline-functions Libc: 5.4.46. egcs/pgcc compiled with Haifa scheduler Binutils: 2.9.1.0.4 or 2.9.1.0.15 (12) used LD = cc -Wl,-rpath,my_exotic_DLL_path (13) use /opt/SUNWspro/bin/fpversion to get explicit recommended CFLAGS. use -fsimple=1; the Sun FD6U2 cc 5.3 defaults to -fsimple=2 at higher optimization levels, which is deadly to PARI. (these options must be given _after_ the -fast macro if -fast is used, or the -fast expansion will override them.) (14) use asmarch=sparcv7 (15) Configure defaults to hpux-none. Use Configure -a and specify the hppa kernel. Remove +z from compiler flags (16) CFLAGS = -mk6 -march=i586 -O6 (17) 256kb L2 Cache - Ultra U5 (18) 2 MB L2 Cache - Ultra U10 (19) replace err by pari_err in src/kernel/sparcv7/level0.S [in 2.0.16 or 17] (20) asmarch incorrectly defaulted to MicroSPARC (bypassed using Configure -a) (22) same machine as above, native binary compiled with mingw32-gcc-2.95.2 had to modify Odos/Makefile (to link with readline-4.0). PROBLEMS: * when started from the shell, on ^C GP quits! OK when started from GUI * stdin redirection from the shell (gp < file) doesn't work (SEGV in gp). * ANSI escape sequences are printed "as is" (so don't enable colors) (24) same machine as above, using the RSX compatibility package (25) Xeon (26) RedHat-7.0 + alpha has a broken glibc-2.1.x [issquare(8388609^2) = 0 !] Updating to glibc-2.2 fixes the problem. (27) gcc-2.95.3 -O + new inline assembler [gcc-2.95.2 and gcc-2.95.3 -O3 both produce a broken binary] (28) gp-dyn: add -fPIC to CFLAGS [or linking fails]. gcc-2.96 fails (29) added -mcpu=athlon -march=athlon to CFLAGS (very minor speedup). clock frequency for Athlon 1800+ = 1530MHz (30) cpu=Athlon XP1800+ Mandrake 8.1, Linux-2.4.17 CFLAGS= -fbranch-probabilities -fstrict-aliasing -falign-jumps -foptimize-sibling-calls -fssa -maccumulate-outgoing-args -minline-all-stringops -march=athlon -O3 -DGCC_INLINE -Wall -Wno-implicit -fomit-frame-pointer (31) cpu=Pentium II 450@463 (FSB a 103mhz), Bi-Pro Linux-2.4.18-rc2 + patches CFLAGS= -fbranch-probabilities -O3 -DGCC_INLINE -Wall -Wno-implicit -fstrict-aliasing -fssa -foptimize-sibling-calls -falign-jumps -march=pentiumpro -maccumulate-outgoing-args -minline-all-stringops -fomit-frame-pointer (32) gp-dyn: add -fPIC to CFLAGS [or linking fails]. Most gcc 2.95 ARM support lib have buggy (unsigned)%(unsigned) (33) LCDS System: 9672 G6 Model ZX7 (10 way processor, 32GB RAM) DASD: Shark 2105-F20 (2.1 terabytes) (34) 64-bit executable (35) SMP, 512KB L2 cache (36) UP, 256KB L2 cache (37) http://db.debian.org/machines.cgi?host=crest Build with gcc -fPIC. (38) Cygwin 1.3.20-1 (39) http://db.debian.org/machines.cgi?host=raptor (40) same machine as (37) but without -fPIC. (41) 1 GB RAM, NForce2 chipset, 2.4.21pre7 kernel (Red Hat 8.0) CFLAGS = -O2 -s -DGCC_INLINE -Wall -fbranch-probabilities -mmmx -msse -m3dnow -ffast-math -fno-unsafe-math-optimizations -D__USE_ISOC99 -D__USE_EXTERN_INLINES -fomit-frame-pointer -DBOTH_GNUPLOT_AND_X11 -fno-unsafe-math-optimizations is mandatory with -ffast-math, in order to avoid bugs in nfields test. Used -fprofile-arcs for the first compilation parse, then -fbranch-probabilities to generate optimized executables. For this machine, many benchmarks are too short to provide accurate results (TIME=0 or 10). (42) gcc 3.3 version 20030226 -O3 failed to compile buch2.c with "internal compiler error". Works fine after compiling manually this file at -O2. (43) marie.medicis.polytechnique.fr ============================================================================= Contributors: AW = Aleksander Wittlin AP = Andreas Piotrowski BA = Bill Allombert BM = Brian Mach Inneirghthe BN = Balasubramanian Narasimhan CC = Christian Cornelssen CL = Christian Labesse DC = David Cleaver DE = Denis Excoffier DP = David Purdy EK = Emmanuel Kowalski FU = Frederic Udina GH = Guillaume Hanrot GN = Gerhard Niklasch HC = Henri Cohen HG = Herbert Gangl HR = Herman te Riele HS = Hans Schaechl HV = Hugo van der Sanden ID = Ingo Dittmer IS = Igor Schein JB = Jonathan Baker JC = John Cremona JD = Jeroen Demeyer KK = Kimitoshi Kono LG = Louis Granboulan MB = Marco Bucci MH = Mohammad Bahathir Hashim MS = Michael Stoll MW = Mariusz Wodzicki NI = Nathaniel Irons PE = Philippe Elbaz-Vincent OT = Olivier Thibault PZ = Paul Zimmermann QL = Qing Liu RM = Richard J. Mathar RN = Reed Nessler SC = Scott Chadde SH = Steve Harding SHo= Steve Holmes TP = Thomas Papanikolaou TT = Tibor I. Toth XR = Xavier Roblot